This is an automated email from the ASF dual-hosted git repository. dahn pushed a commit to branch 4.19 in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.19 by this push: new 47a268202bc [VMware] Sync the disk path or datastore changes for IDE disks, and before any volume resize during start vm (for the volumes on datastore cluster) (#10748) 47a268202bc is described below commit 47a268202bca0c10ef5de729df99815bd3e64bd1 Author: Suresh Kumar Anaparti <sureshkumar.anapa...@gmail.com> AuthorDate: Mon May 12 16:51:04 2025 +0530 [VMware] Sync the disk path or datastore changes for IDE disks, and before any volume resize during start vm (for the volumes on datastore cluster) (#10748) --- .../hypervisor/vmware/resource/VmwareResource.java | 111 ++++++++++++--------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 20495530909..9e105749da9 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2350,13 +2350,16 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes continue; } + VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context); + Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = getVolumeDatastoreDetails(vol, dataStoresDetails); + syncVolumeDatastoreAndPathForDatastoreCluster(vol, diskInfoBuilder, matchingExistingDisk, volumeDsDetails, diskDatastores, hyperHost, context); + if (deployAsIs && vol.getType() == Volume.Type.ROOT) { rootDiskTO = vol; resizeRootDiskOnVMStart(vmMo, rootDiskTO, hyperHost, context); continue; } - VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context); String diskController = getDiskController(vmMo, matchingExistingDisk, vol, chosenDiskControllers, deployAsIs); if (DiskControllerType.getType(diskController) == DiskControllerType.ide) { controllerKey = vmMo.getIDEControllerKey(ideUnitNumber); @@ -2365,7 +2368,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes // Ensure maximum of 2 data volumes over IDE controller, 3 includeing root volume if (vmMo.getNumberOfVirtualDisks() > 3) { throw new CloudRuntimeException("Found more than 3 virtual disks attached to this VM [" + vmMo.getVmName() + "]. Unable to implement the disks over " - + diskController + " controller, as maximum number of devices supported over IDE controller is 4 includeing CDROM device."); + + diskController + " controller, as maximum number of devices supported over IDE controller is 4 including CDROM device."); } } } else { @@ -2385,51 +2388,6 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes if (!hasSnapshot) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); - DataStoreTO primaryStore = volumeTO.getDataStore(); - Map<String, String> details = vol.getDetails(); - boolean managed = false; - String iScsiName = null; - - if (details != null) { - managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED)); - iScsiName = details.get(DiskTO.IQN); - } - - String primaryStoreUuid = primaryStore.getUuid(); - // if the storage is managed, iScsiName should not be null - String datastoreName = managed ? VmwareResource.getDatastoreName(iScsiName) : primaryStoreUuid; - Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(datastoreName); - - assert (volumeDsDetails != null); - if (volumeDsDetails == null) { - throw new Exception("Primary datastore " + primaryStore.getUuid() + " is not mounted on host."); - } - - if (vol.getDetails().get(DiskTO.PROTOCOL_TYPE) != null && vol.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) { - if (diskInfoBuilder != null && matchingExistingDisk != null) { - String[] diskChain = matchingExistingDisk.getDiskChain(); - if (diskChain != null && diskChain.length > 0) { - DatastoreFile file = new DatastoreFile(diskChain[0]); - if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) { - if (s_logger.isInfoEnabled()) - s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName()); - volumeTO.setPath(file.getFileBaseName()); - } - } - DatastoreMO diskDatastoreMofromVM = getDataStoreWhereDiskExists(hyperHost, context, diskInfoBuilder, vol, diskDatastores); - if (diskDatastoreMofromVM != null) { - String actualPoolUuid = diskDatastoreMofromVM.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID); - if (actualPoolUuid != null && !actualPoolUuid.equalsIgnoreCase(primaryStore.getUuid())) { - volumeDsDetails = new Pair<>(diskDatastoreMofromVM.getMor(), diskDatastoreMofromVM); - if (s_logger.isInfoEnabled()) - s_logger.info("Detected datastore uuid change on volume: " + volumeTO.getId() + " " + primaryStore.getUuid() + " -> " + actualPoolUuid); - ((PrimaryDataStoreTO)primaryStore).setUuid(actualPoolUuid); - } - } - } - } - String[] diskChain = syncDiskChain(dcMo, vmMo, vol, matchingExistingDisk, volumeDsDetails.second()); int deviceNumber = -1; @@ -2441,6 +2399,7 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes scsiUnitNumber++; } + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); Long maxIops = volumeTO.getIopsWriteRate() + volumeTO.getIopsReadRate(); VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), deviceNumber, i + 1, maxIops); s_logger.debug(LogUtils.logGsonWithoutException("The following definitions will be used to start the VM: virtual device [%s], volume [%s].", device, volumeTO)); @@ -2709,6 +2668,64 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes } } + private Pair<ManagedObjectReference, DatastoreMO> getVolumeDatastoreDetails(DiskTO vol, HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails) throws Exception { + boolean managed = false; + String iScsiName = null; + Map<String, String> details = vol.getDetails(); + if (MapUtils.isNotEmpty(details)) { + managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED)); + iScsiName = details.get(DiskTO.IQN); + } + + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); + DataStoreTO primaryStore = volumeTO.getDataStore(); + String primaryStoreUuid = primaryStore.getUuid(); + // if the storage is managed, iScsiName should not be null + String datastoreName = managed ? VmwareResource.getDatastoreName(iScsiName) : primaryStoreUuid; + Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(datastoreName); + if (volumeDsDetails == null) { + throw new Exception("Primary datastore " + primaryStore.getUuid() + " is not mounted on host."); + } + + return volumeDsDetails; + } + + private void syncVolumeDatastoreAndPathForDatastoreCluster(DiskTO vol, VirtualMachineDiskInfoBuilder diskInfoBuilder, VirtualMachineDiskInfo matchingExistingDisk, + Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails, List<Pair<Integer, ManagedObjectReference>> diskDatastores, + VmwareHypervisorHost hyperHost, VmwareContext context) throws Exception { + if (vol.getDetails() == null || vol.getDetails().get(DiskTO.PROTOCOL_TYPE) == null || !vol.getDetails().get(DiskTO.PROTOCOL_TYPE).equalsIgnoreCase("DatastoreCluster")) { + return; + } + + if (diskInfoBuilder != null && matchingExistingDisk != null) { + String[] diskChain = matchingExistingDisk.getDiskChain(); + if (diskChain != null && diskChain.length > 0) { + DatastoreFile file = new DatastoreFile(diskChain[0]); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); + if (!file.getFileBaseName().equalsIgnoreCase(volumeTO.getPath())) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + file.getFileBaseName()); + } + volumeTO.setPath(file.getFileBaseName()); + vol.setPath(file.getFileBaseName()); + } + } + DatastoreMO diskDatastoreMofromVM = getDataStoreWhereDiskExists(hyperHost, context, diskInfoBuilder, vol, diskDatastores); + if (diskDatastoreMofromVM != null) { + String actualPoolUuid = diskDatastoreMofromVM.getCustomFieldValue(CustomFieldConstants.CLOUD_UUID); + VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData(); + DataStoreTO primaryStore = volumeTO.getDataStore(); + if (actualPoolUuid != null && !actualPoolUuid.equalsIgnoreCase(primaryStore.getUuid())) { + volumeDsDetails = new Pair<>(diskDatastoreMofromVM.getMor(), diskDatastoreMofromVM); + if (s_logger.isInfoEnabled()) { + s_logger.info("Detected datastore uuid change on volume: " + volumeTO.getId() + " " + primaryStore.getUuid() + " -> " + actualPoolUuid); + } + ((PrimaryDataStoreTO)primaryStore).setUuid(actualPoolUuid); + } + } + } + } + private boolean powerOnVM(final VirtualMachineMO vmMo, final String vmInternalCSName, final String vmNameOnVcenter) throws Exception { int retry = 20; while (retry-- > 0) {