From 2e57e4c63add987495753daa4a6534254acb2287 Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Fri, 11 May 2012 17:05:13 -0700 Subject: [PATCH] Add support routines for incremental snapshot support --- .../hypervisor/vmware/mo/TestVmwareMO.java | 36 +--------- .../vmware/mo/SnapshotDescriptor.java | 27 ++++++++ .../vmware/mo/VirtualMachineMO.java | 35 +++++++++- .../hypervisor/vmware/util/VmwareHelper.java | 68 +++++++++++++++++-- 4 files changed, 126 insertions(+), 40 deletions(-) diff --git a/core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java b/core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java index 9647ca39e1f..5738164b725 100755 --- a/core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java +++ b/core/test/com/cloud/hypervisor/vmware/mo/TestVmwareMO.java @@ -16,8 +16,10 @@ import java.util.GregorianCalendar; import org.apache.log4j.Logger; +import com.cloud.hypervisor.vmware.mo.SnapshotDescriptor.SnapshotInfo; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.serializer.GsonHelper; +import com.cloud.utils.Pair; import com.cloud.utils.testcase.Log4jEnabledTestCase; import com.google.gson.Gson; import com.vmware.vim25.DynamicProperty; @@ -29,40 +31,6 @@ public class TestVmwareMO extends Log4jEnabledTestCase { private static final Logger s_logger = Logger.getLogger(TestVmwareMO.class); public void test() { - try { - VmwareContext context = TestVmwareContextFactory.create( - "10.223.80.29", "Administrator", "Suite219"); - - HostMO hostMo = new HostMO(context, "HostSystem", "host-10"); - ObjectContent[] ocs = hostMo.getVmPropertiesOnHyperHost(new String[] {"name", "config.template", "runtime.bootTime"}); - if(ocs != null) { - for(ObjectContent oc : ocs) { - DynamicProperty[] props = oc.getPropSet(); - if(props != null) { - String name = null; - boolean template = false; - GregorianCalendar bootTime = null; - - for(DynamicProperty prop : props) { - if(prop.getName().equals("name")) - name = prop.getVal().toString(); - else if(prop.getName().equals("config.template")) - template = (Boolean)prop.getVal(); - else if(prop.getName().equals("runtime.bootTime")) - bootTime = (GregorianCalendar)prop.getVal(); - } - - System.out.println("name: " + name + ", template: " + template + ", bootTime: " + bootTime); - - } - System.out.println(""); - } - } - - context.close(); - } catch(Exception e) { - s_logger.error("Unexpected exception : ", e); - } } } diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java index bfebc4a2dce..4d4b459e4b1 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/SnapshotDescriptor.java @@ -247,6 +247,28 @@ public class SnapshotDescriptor { public DiskInfo[] getDisks() { return _disks; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("SnapshotInfo : { id: "); + sb.append(_id); + sb.append(", displayName: ").append(_displayName); + sb.append(", numOfDisks: ").append(_numOfDisks); + sb.append(", disks: ["); + if(_disks != null) { + int i = 0; + for(DiskInfo diskInfo : _disks) { + if(i > 0) + sb.append(", "); + sb.append(diskInfo.toString()); + i++; + } + } + sb.append("]}"); + + return sb.toString(); } } @@ -265,6 +287,11 @@ public class SnapshotDescriptor { public String getDeviceName() { return _deviceName; + } + + @Override + public String toString() { + return "DiskInfo: { device: " + _deviceName + ", file: " + _diskFileName + " }"; } } } diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index c9f15270d2f..ba7f003bc68 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -942,7 +942,40 @@ public class VirtualMachineMO extends BaseMO { if(s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - attachDisk() done(successfully)"); - } + } + + public void attachDisk(Pair[] vmdkDatastorePathChain, int controllerKey) throws Exception { + + if(s_logger.isTraceEnabled()) + s_logger.trace("vCenter API trace - attachDisk(). target MOR: " + _mor.get_value() + ", vmdkDatastorePath: " + + new Gson().toJson(vmdkDatastorePathChain)); + + VirtualDevice newDisk = VmwareHelper.prepareDiskDevice(this, controllerKey, + vmdkDatastorePathChain, -1, 1); + VirtualMachineConfigSpec reConfigSpec = new VirtualMachineConfigSpec(); + VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1]; + VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec(); + + deviceConfigSpec.setDevice(newDisk); + deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.add); + + deviceConfigSpecArray[0] = deviceConfigSpec; + reConfigSpec.setDeviceChange(deviceConfigSpecArray); + + ManagedObjectReference morTask = _context.getService().reconfigVM_Task(_mor, reConfigSpec); + String result = _context.getServiceUtil().waitForTask(morTask); + + if(!result.equals("sucess")) { + if(s_logger.isTraceEnabled()) + s_logger.trace("vCenter API trace - attachDisk() done(failed)"); + throw new Exception("Failed to attach disk due to " + TaskMO.getTaskFailureInfo(_context, morTask)); + } + + _context.waitForTaskProgressDone(morTask); + + if(s_logger.isTraceEnabled()) + s_logger.trace("vCenter API trace - attachDisk() done(successfully)"); + } // vmdkDatastorePath: [datastore name] vmdkFilePath public List> detachDisk(String vmdkDatastorePath, boolean deleteBackingFile) throws Exception { diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 428b77c6673..46dfc6a1829 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -137,8 +137,8 @@ public class VmwareHelper { disk.setConnectable(connectInfo); return disk; - } - + } + // vmdkDatastorePath: [datastore name] vmdkFilePath, create delta disk based on disk from template public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, String vmdkDatastorePath, int sizeInMb, ManagedObjectReference morDs, VirtualDisk templateDisk, int deviceNumber, int contextNumber) throws Exception { @@ -244,8 +244,48 @@ public class VmwareHelper { disk.setConnectable(connectInfo); return disk; - } - + } + + public static VirtualDevice prepareDiskDevice(VirtualMachineMO vmMo, int controllerKey, + Pair[] vmdkDatastorePathChain, + int deviceNumber, int contextNumber) throws Exception { + + assert(vmdkDatastorePathChain != null); + assert(vmdkDatastorePathChain.length >= 1); + + VirtualDisk disk = new VirtualDisk(); + + VirtualDiskFlatVer2BackingInfo backingInfo = new VirtualDiskFlatVer2BackingInfo(); + backingInfo.setDatastore(vmdkDatastorePathChain[0].second()); + backingInfo.setFileName(vmdkDatastorePathChain[0].first()); + backingInfo.setDiskMode(VirtualDiskMode.persistent.toString()); + if(vmdkDatastorePathChain.length > 1) { + Pair[] parentDisks = new Pair[vmdkDatastorePathChain.length - 1]; + for(int i = 0; i < vmdkDatastorePathChain.length - 1; i++) + parentDisks[i] = vmdkDatastorePathChain[i + 1]; + + setParentBackingInfo(backingInfo, parentDisks); + } + + disk.setBacking(backingInfo); + + if(controllerKey < 0) + controllerKey = vmMo.getIDEDeviceControllerKey(); + if(deviceNumber < 0) + deviceNumber = vmMo.getNextDeviceNumber(controllerKey); + + disk.setControllerKey(controllerKey); + disk.setKey(-contextNumber); + disk.setUnitNumber(deviceNumber); + + VirtualDeviceConnectInfo connectInfo = new VirtualDeviceConnectInfo(); + connectInfo.setConnected(true); + connectInfo.setStartConnected(true); + disk.setConnectable(connectInfo); + + return disk; + } + private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo, ManagedObjectReference morDs, String[] parentDatastorePathList) { @@ -262,7 +302,25 @@ public class VmwareHelper { parentBacking.setFileName(parentDatastorePathList[0]); backingInfo.setParent(parentBacking); - } + } + + private static void setParentBackingInfo(VirtualDiskFlatVer2BackingInfo backingInfo, + Pair[] parentDatastorePathList) { + + VirtualDiskFlatVer2BackingInfo parentBacking = new VirtualDiskFlatVer2BackingInfo(); + parentBacking.setDatastore(parentDatastorePathList[0].second()); + parentBacking.setDiskMode(VirtualDiskMode.persistent.toString()); + + if(parentDatastorePathList.length > 1) { + Pair[] nextDatastorePathList = new Pair[parentDatastorePathList.length -1]; + for(int i = 0; i < parentDatastorePathList.length -1; i++) + nextDatastorePathList[i] = parentDatastorePathList[i + 1]; + setParentBackingInfo(parentBacking, nextDatastorePathList); + } + parentBacking.setFileName(parentDatastorePathList[0].first()); + + backingInfo.setParent(parentBacking); + } public static Pair prepareIsoDevice(VirtualMachineMO vmMo, String isoDatastorePath, ManagedObjectReference morDs, boolean connect, boolean connectAtBoot, int deviceNumber, int contextNumber) throws Exception {