Updated Branches: refs/heads/master 6689e83d7 -> 98dd501a8
Changes related to Review Board comments Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/98dd501a Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/98dd501a Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/98dd501a Branch: refs/heads/master Commit: 98dd501a818beef03b5f593822b525348874f007 Parents: 6689e83 Author: Mike Tutkowski <[email protected]> Authored: Sat Jul 20 17:44:23 2013 -0600 Committer: Mike Tutkowski <[email protected]> Committed: Sat Jul 20 17:44:23 2013 -0600 ---------------------------------------------------------------------- .../vmware/resource/VmwareResource.java | 233 ++++++++++--------- 1 file changed, 128 insertions(+), 105 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/98dd501a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index bbac725..c7f487e 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.concurrent.*; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; @@ -4073,33 +4074,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return str.replace('/', '-'); } - // This methd can be used to determine if the datastore is active yet. - // When an iSCSI target is created on a host and that target already contains - // the metadata that represents a datastore, the datastore shows up within - // vCenter as existent, but not necessarily active. - // Call this method and pass in the datastore's name to wait, if necessary, - // for the datastore to become active. - private boolean datastoreFileExists(DatastoreMO dsMo, String volumeDatastorePath) { - for (int i = 0; i < 10; i++) { - try { - return dsMo.fileExists(volumeDatastorePath); - } - catch (Exception e) { - if (!e.getMessage().contains("is not accessible")) { - break; - } - } - - try { - Thread.sleep(5000); - } - catch (Exception e) { - } - } - - return false; - } - @Override public ManagedObjectReference handleDatastoreAndVmdkAttach(Command cmd, String iqn, String storageHost, int storagePort, String initiatorUsername, String initiatorPassword, String targetUsername, String targetPassword) throws Exception { @@ -4115,7 +4089,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), dsMo.getName()); - if (!datastoreFileExists(dsMo, volumeDatastorePath)) { + if (!dsMo.fileExists(volumeDatastorePath)) { String dummyVmName = getWorkerName(context, cmd, 0); VirtualMachineMO vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName); @@ -4209,49 +4183,80 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - private ManagedObjectReference createVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, - int storagePortNumber, String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception { + private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets, + final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception { VmwareContext context = getServiceContext(); - ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); - ClusterMO cluster = new ClusterMO(context, morCluster); - List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts(); - HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget(); + ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size()); - target.setAddress(storageIpAddress); - target.setPort(storagePortNumber); - target.setIScsiName(iqn); + final List<Exception> exceptions = new ArrayList<Exception>(); - HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties(); + for (Pair<ManagedObjectReference, String> hostPair : lstHosts) { + HostMO host = new HostMO(context, hostPair.first()); + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); - String strAuthType = "chapRequired"; + boolean iScsiHbaConfigured = false; - auth.setChapAuthEnabled(true); - auth.setChapInherited(false); - auth.setChapAuthenticationType(strAuthType); - auth.setChapName(chapName); - auth.setChapSecret(chapSecret); - auth.setMutualChapInherited(false); - auth.setMutualChapAuthenticationType(strAuthType); - auth.setMutualChapName(mutualChapName); - auth.setMutualChapSecret(mutualChapSecret); + for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { + if (hba instanceof HostInternetScsiHba) { + // just finding an instance of HostInternetScsiHba means that we have found at least one configured iSCSI HBA + // at least one iSCSI HBA must be configured before a CloudStack user can use this host for iSCSI storage + iScsiHbaConfigured = true; - target.setAuthenticationProperties(auth); + final String iScsiHbaDevice = hba.getDevice(); - final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>(); + final HostStorageSystemMO hss = hostStorageSystem; - lstTargets.add(target); + executorService.submit(new Thread() { + @Override + public void run() { + try { + if (add) { + hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); + } + else { + hss.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); + } + + hss.rescanHba(iScsiHbaDevice); + hss.rescanVmfs(); + } + catch (Exception ex) { + synchronized (exceptions) { + exceptions.add(ex); + } + } + } + }); + } + } + + if (!iScsiHbaConfigured) { + throw new Exception("An iSCSI HBA must be configured before a host can use iSCSI storage."); + } + } + + executorService.shutdown(); + + if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) { + throw new Exception("The system timed out before completing the task 'rescanAllHosts'."); + } + + if (exceptions.size() > 0) { + throw new Exception(exceptions.get(0).getMessage()); + } + } - HostDatastoreSystemMO hostDatastoreSystem = null; - HostStorageSystemMO hostStorageSystem = null; + private void rescanAllHosts(final List<Pair<ManagedObjectReference, String>> lstHosts) throws Exception { + VmwareContext context = getServiceContext(); + + ExecutorService executorService = Executors.newFixedThreadPool(lstHosts.size()); - final List<Thread> threads = new ArrayList<Thread>(); final List<Exception> exceptions = new ArrayList<Exception>(); for (Pair<ManagedObjectReference, String> hostPair : lstHosts) { HostMO host = new HostMO(context, hostPair.first()); - hostDatastoreSystem = host.getHostDatastoreSystemMO(); - hostStorageSystem = host.getHostStorageSystemMO(); + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); boolean iScsiHbaConfigured = false; @@ -4265,12 +4270,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa final HostStorageSystemMO hss = hostStorageSystem; - threads.add(new Thread() { + executorService.submit(new Thread() { @Override public void run() { try { - hss.addInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); - hss.rescanHba(iScsiHbaDevice); hss.rescanVmfs(); } @@ -4289,33 +4292,90 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } - for (Thread thread : threads) { - thread.start(); - } + executorService.shutdown(); - for (Thread thread : threads) { - thread.join(); + if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES)) { + throw new Exception("The system timed out before completing the task 'rescanAllHosts'."); } if (exceptions.size() > 0) { throw new Exception(exceptions.get(0).getMessage()); } + } + + private ManagedObjectReference createVmfsDatastore(VmwareHypervisorHost hyperHost, String datastoreName, String storageIpAddress, + int storagePortNumber, String iqn, String chapName, String chapSecret, String mutualChapName, String mutualChapSecret) throws Exception { + VmwareContext context = getServiceContext(); + ManagedObjectReference morCluster = hyperHost.getHyperHostCluster(); + ClusterMO cluster = new ClusterMO(context, morCluster); + List<Pair<ManagedObjectReference, String>> lstHosts = cluster.getClusterHosts(); + + HostInternetScsiHbaStaticTarget target = new HostInternetScsiHbaStaticTarget(); + + target.setAddress(storageIpAddress); + target.setPort(storagePortNumber); + target.setIScsiName(iqn); + + HostInternetScsiHbaAuthenticationProperties auth = new HostInternetScsiHbaAuthenticationProperties(); + + String strAuthType = "chapRequired"; + + auth.setChapAuthEnabled(true); + auth.setChapInherited(false); + auth.setChapAuthenticationType(strAuthType); + auth.setChapName(chapName); + auth.setChapSecret(chapSecret); + auth.setMutualChapInherited(false); + auth.setMutualChapAuthenticationType(strAuthType); + auth.setMutualChapName(mutualChapName); + auth.setMutualChapSecret(mutualChapSecret); + + target.setAuthenticationProperties(auth); + + final List<HostInternetScsiHbaStaticTarget> lstTargets = new ArrayList<HostInternetScsiHbaStaticTarget>(); + + lstTargets.add(target); + + addRemoveInternetScsiTargetsToAllHosts(true, lstTargets, lstHosts); - ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(iqn); + rescanAllHosts(lstHosts); + + HostMO host = new HostMO(context, lstHosts.get(0).first()); + HostDatastoreSystemMO hostDatastoreSystem = host.getHostDatastoreSystemMO(); + + ManagedObjectReference morDs = hostDatastoreSystem.findDatastoreByName(datastoreName); if (morDs != null) { return morDs; } + rescanAllHosts(lstHosts); + + HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); List<HostScsiDisk> lstHostScsiDisks = hostDatastoreSystem.queryAvailableDisksForVmfs(); HostScsiDisk hostScsiDisk = getHostScsiDisk(hostStorageSystem.getStorageDeviceInfo().getScsiTopology(), lstHostScsiDisks, iqn); if (hostScsiDisk == null) { + // check to see if the datastore actually does exist already + morDs = hostDatastoreSystem.findDatastoreByName(datastoreName); + + if (morDs != null) { + return morDs; + } + throw new Exception("A relevant SCSI disk could not be located to use to create a datastore."); } - return hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk); + morDs = hostDatastoreSystem.createVmfsDatastore(datastoreName, hostScsiDisk); + + if (morDs != null) { + rescanAllHosts(lstHosts); + + return morDs; + } + + throw new Exception("Unable to create a datastore"); } // the purpose of this method is to find the HostScsiDisk in the passed-in array that exists (if any) because @@ -4363,46 +4423,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa lstTargets.add(target); - final List<Thread> threads = new ArrayList<Thread>(); - final List<Exception> exceptions = new ArrayList<Exception>(); - - for (Pair<ManagedObjectReference, String> hostPair : lstHosts) { - final HostMO host = new HostMO(context, hostPair.first()); - final HostStorageSystemMO hostStorageSystem = host.getHostStorageSystemMO(); - - for (HostHostBusAdapter hba : hostStorageSystem.getStorageDeviceInfo().getHostBusAdapter()) { - if (hba instanceof HostInternetScsiHba) { - final String iScsiHbaDevice = hba.getDevice(); + addRemoveInternetScsiTargetsToAllHosts(false, lstTargets, lstHosts); - Thread thread = new Thread() { - @Override - public void run() { - try { - hostStorageSystem.removeInternetScsiStaticTargets(iScsiHbaDevice, lstTargets); - - hostStorageSystem.rescanHba(iScsiHbaDevice); - hostStorageSystem.rescanVmfs(); - } - catch (Exception ex) { - exceptions.add(ex); - } - } - }; - - threads.add(thread); - - thread.start(); - } - } - } - - for (Thread thread : threads) { - thread.join(); - } - - if (exceptions.size() > 0) { - throw new Exception(exceptions.get(0).getMessage()); - } + rescanAllHosts(lstHosts); } protected Answer execute(AttachIsoCommand cmd) {
