From 4b581bfa5f2d62de0452fee0a47ed20336667056 Mon Sep 17 00:00:00 2001 From: Likitha Shetty Date: Tue, 13 Aug 2013 12:44:44 -0700 Subject: [PATCH] BUG-ID: CLOUDSTACK-7662. Resize of detached volume fails. Support offline volume resize on ESX by creating a worker VM to attach the unattached volume to and then resize it. (cherry picked from commit 65ed25b7a63586e25a568d845527d547f0045889) --- .../vmware/resource/VmwareResource.java | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) 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 226a884bc45..085b6bbed49 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 @@ -545,11 +545,43 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String path = cmd.getPath(); String vmName = cmd.getInstanceName(); long newSize = cmd.getNewSize() / 1024; + long oldSize = cmd.getCurrentSize()/1024; + boolean useWorkerVm = false; + + VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); + String poolId = cmd.getPoolUuid(); + VirtualMachineMO vmMo = null; + DatastoreMO dsMo = null; + ManagedObjectReference morDS = null; + String vmdkDataStorePath = null; try { - VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext()); + if (newSize < oldSize) { + throw new Exception("VMware doesn't support shrinking volume from larger size: " + oldSize/(1024*1024) + " GB to a smaller size: " + newSize/(1024*1024) + " GB"); + } else if (newSize == oldSize) { + return new ResizeVolumeAnswer(cmd, true, "success", newSize*1024); + } + if (vmName.equalsIgnoreCase("none")) { + // we need to spawn a worker VM to attach the volume to and + // resize the volume. + useWorkerVm = true; + vmName = this.getWorkerName(getServiceContext(), cmd, 0); + + morDS = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolId); + dsMo = new DatastoreMO(hyperHost.getContext(), morDS); + s_logger.info("Create worker VM " + vmName); + vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, vmName); + if (vmMo == null) { + throw new Exception("Unable to create a worker VM for volume resize"); + } + + synchronized (this) { + vmdkDataStorePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, path + ".vmdk"); + vmMo.attachDisk(new String[] { vmdkDataStorePath }, morDS); + } + } // find VM through datacenter (VM is not at the target host yet) - VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName); + vmMo = hyperHost.findVmOnPeerHyperHost(vmName); if (vmMo == null) { String msg = "VM " + vmName + " does not exist in VMware datacenter"; s_logger.error(msg); @@ -563,13 +595,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa throw new Exception("No such disk device: " + path); } VirtualDisk disk = vdisk.first(); - long oldSize = disk.getCapacityInKB(); - if (newSize < oldSize) { - throw new Exception("VMware doesn't support shrinking volume from larger size: " + oldSize/(1024*1024) + " GB to a smaller size: " - + newSize/(1024*1024) + " GB"); - } else if (newSize == oldSize) { - return new ResizeVolumeAnswer(cmd, true, "success", newSize * 1024); - } disk.setCapacityInKB(newSize); VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec(); @@ -586,6 +611,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.error("Unable to resize volume", e); String error = "Failed to resize volume: " + e.getMessage(); return new ResizeVolumeAnswer(cmd, false, error); + } finally { + try { + if (useWorkerVm == true) { + s_logger.info("Destroy worker VM after volume resize"); + vmMo.detachDisk(vmdkDataStorePath, false); + vmMo.destroy(); + } + } catch (Throwable e) { + s_logger.info("Failed to destroy worker VM: " + vmName); + } } }