cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kelv...@apache.org
Subject git commit: updated refs/heads/4.2-forward to 834fdc8
Date Sat, 24 Aug 2013 00:51:14 GMT
Updated Branches:
  refs/heads/4.2-forward d90166357 -> 834fdc885


CLOUDSTACK-3237: acknowledge the behind-back VMDK disk consolidation happend in vCenter after
storage live migration


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/834fdc88
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/834fdc88
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/834fdc88

Branch: refs/heads/4.2-forward
Commit: 834fdc8859a92989a818fac2f24af97c87d5ed55
Parents: d9016635
Author: Kelven Yang <kelveny@gmail.com>
Authored: Fri Aug 23 17:38:17 2013 -0700
Committer: Kelven Yang <kelveny@gmail.com>
Committed: Fri Aug 23 17:38:34 2013 -0700

----------------------------------------------------------------------
 .../storage/snapshot/SnapshotObject.java        | 14 ++++
 .../manager/VmwareStorageManagerImpl.java       |  3 +-
 .../resource/VmwareStorageProcessor.java        | 84 +++++++++++++++++---
 .../hypervisor/vmware/mo/VirtualMachineMO.java  | 29 ++++++-
 4 files changed, 115 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/834fdc88/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index 3d67d38..e69881c 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -38,6 +38,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.utils.component.ComponentContext;
@@ -262,6 +263,19 @@ public class SnapshotObject implements SnapshotInfo {
                     snapshotStore.setParentSnapshotId(0L);
                 }
                 this.snapshotStoreDao.update(snapshotStore.getId(), snapshotStore);
+                
+                // update side-effect of snapshot operation
+                if(snapshotTO.getVolume().getPath() != null) {
+                	VolumeVO vol = this.volumeDao.findByUuid(snapshotTO.getVolume().getUuid());
+                	if(vol != null) {
+	                	s_logger.info("Update volume path change due to snapshot operation, volume
" + vol.getId() + " path: "
+	                		+ vol.getPath() + "->" + snapshotTO.getVolume().getPath());
+	                	vol.setPath(snapshotTO.getVolume().getPath());
+	                	this.volumeDao.update(vol.getId(), vol);
+                	} else {
+                		s_logger.error("Cound't find the original volume with uuid: " + snapshotTO.getVolume().getUuid());
+                	}
+                }
             } else {
                 throw new CloudRuntimeException("Unknown answer: " + answer.getClass());
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/834fdc88/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
index e7fbb04..955b111 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java
@@ -292,6 +292,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager
{
     }
 
     @Override
+    @Deprecated
     public Answer execute(VmwareHostService hostService, BackupSnapshotCommand cmd) {
         Long accountId = cmd.getAccountId();
         Long volumeId = cmd.getVolumeId();
@@ -362,7 +363,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager
{
             } finally {
                 if(vmMo != null){
                     ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
-                    if (snapshotMor != null){
+                    if (snapshotMor != null) {
                         vmMo.removeSnapshot(snapshotUuid, false);
                     }
                 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/834fdc88/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
index 138f725..c2e55fb 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -58,6 +58,7 @@ import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
 import com.cloud.hypervisor.vmware.mo.ClusterMO;
 import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
 import com.cloud.hypervisor.vmware.mo.DatacenterMO;
+import com.cloud.hypervisor.vmware.mo.DatastoreFile;
 import com.cloud.hypervisor.vmware.mo.DatastoreMO;
 import com.cloud.hypervisor.vmware.mo.HostMO;
 import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
@@ -949,7 +950,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
         }
     }
 
-    private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
+    // return Pair<String(divice bus name), String[](disk chain)>
+    private Pair<String, String[]> exportVolumeToSecondaryStroage(VirtualMachineMO
vmMo, String volumePath,
             String secStorageUrl, String secStorageDir, String exportName,
             String workerVmName) throws Exception {
 
@@ -978,7 +980,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
             }
 
             // 4 MB is the minimum requirement for VM memory in VMware
-            vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+            String disks[] = vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
                     VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
             clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
             if(clonedVm == null) {
@@ -988,6 +990,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
             }
 
             clonedVm.exportVm(exportPath, exportName, false, false);
+            
+            return new Pair<String, String[]>(volumeDeviceInfo.second(), disks);
         } finally {
             if(clonedVm != null) {
                 clonedVm.detachAllDisks();
@@ -996,15 +1000,15 @@ public class VmwareStorageProcessor implements StorageProcessor {
         }
     }
 
-
-    private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath,
+    // Ternary<String(backup uuid in secondary storage), String(device bus name), String[](original
disk chain in the snapshot)>
+    private Ternary<String, String, String[]> backupSnapshotToSecondaryStorage(VirtualMachineMO
vmMo, String installPath,
             String volumePath, String snapshotUuid, String secStorageUrl,
             String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception
{
 
         String backupUuid = UUID.randomUUID().toString();
-        exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
+        Pair<String, String[]> snapshotInfo = exportVolumeToSecondaryStroage(vmMo,
volumePath, secStorageUrl,
                 installPath, backupUuid, workerVmName);
-        return backupUuid + "/" + backupUuid;
+        return new Ternary<String, String, String[]>(backupUuid + "/" + backupUuid,
snapshotInfo.first(), snapshotInfo.second());
     }
 
     @Override
@@ -1033,6 +1037,9 @@ public class VmwareStorageProcessor implements StorageProcessor {
         String details = null;
         boolean success = false;
         String snapshotBackupUuid = null;
+        
+        boolean hasOwnerVm = false;
+        Ternary<String, String, String[]> backupResult = null;
 
         VmwareContext context = hostService.getServiceContext(cmd);
         VirtualMachineMO vmMo = null;
@@ -1041,6 +1048,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
             VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
             morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
primaryStore.getUuid());
 
+            CopyCmdAnswer answer = null;
+            
             try {
                 if (vmName != null) {
                     vmMo = hyperHost.findVmOnHyperHost(vmName);
@@ -1067,31 +1076,84 @@ public class VmwareStorageProcessor implements StorageProcessor {
                         // attach volume to worker VM
                         String datastoreVolumePath = dsMo.getDatastorePath(volumePath + ".vmdk");
                         vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+                    } else {
+                    	s_logger.info("Using owner VM " + vmName + " for snapshot operation");
+                    	hasOwnerVm = true;
                     }
+                } else {
+                	s_logger.info("Using owner VM " + vmName + " for snapshot operation");
+                	hasOwnerVm = true;
                 }
 
                 if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(),
false, false)) {
                     throw new Exception("Failed to take snapshot " + srcSnapshot.getName()
+ " on vm: " + vmName);
                 }
 
-                snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(),
srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
+                backupResult = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(),
srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
                         hostService.getWorkerName(context, cmd, 1));
+                snapshotBackupUuid = backupResult.first();
 
                 success = (snapshotBackupUuid != null);
                 if (!success) {
                     details = "Failed to backUp the snapshot with uuid: " + snapshotUuid
+ " to secondary storage.";
-                    return new CopyCmdAnswer(details);
+                    answer = new CopyCmdAnswer(details);
                 } else {
                     details = "Successfully backedUp the snapshot with Uuid: " + snapshotUuid
+ " to secondary storage.";
                     SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
                     newSnapshot.setPath(destSnapshot.getPath() + "/" + snapshotBackupUuid);
-                    return new CopyCmdAnswer(newSnapshot);
+                    answer = new CopyCmdAnswer(newSnapshot);
                 }
             } finally {
                 if(vmMo != null){
                     ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
-                    if (snapshotMor != null){
+                    if (snapshotMor != null) {
                         vmMo.removeSnapshot(snapshotUuid, false);
+                        
+                        // Snapshot operation may cause disk consolidation in VMware, when
this happens
+                        // we need to update CloudStack DB
+                        //
+                        // TODO: this post operation fixup is not atomic and not safe when
management server stops
+                        // in the middle
+                        if(backupResult != null && hasOwnerVm) {
+                        	s_logger.info("Check if we have disk consolidation after snapshot
operation");
+                        	
+                        	boolean chainConsolidated = false;
+                        	for(String vmdkDsFilePath : backupResult.third()) {
+                        		s_logger.info("Validate disk chain file:" + vmdkDsFilePath);
+                        		
+                        		if(vmMo.getDiskDevice(vmdkDsFilePath, false) == null) {
+                        			s_logger.info("" + vmdkDsFilePath + " no longer exists, consolidation
detected");
+                        			chainConsolidated = true;
+                        			break;
+                        		} else {
+                        			s_logger.info("" + vmdkDsFilePath + " is found still in chain");
+                        		}
+                        	}
+                        	
+                        	if(chainConsolidated) {
+                        		String topVmdkFilePath = null;
+                        		try {
+                        			topVmdkFilePath = vmMo.getDiskCurrentTopBackingFileInChain(backupResult.second());
+                        		} catch(Exception e) {
+                        			s_logger.error("Unexpected exception", e);
+                        		}
+                        		
+                        		s_logger.info("Disk has been consolidated, top VMDK is now: " +
topVmdkFilePath);
+                        		if(topVmdkFilePath != null) {
+	                        		DatastoreFile file = new DatastoreFile(topVmdkFilePath);
+	                        		
+	                        		SnapshotObjectTO snapshotInfo = (SnapshotObjectTO)answer.getNewData();
+	                        		VolumeObjectTO vol = new VolumeObjectTO();
+	                        		vol.setUuid(srcSnapshot.getVolume().getUuid());
+	                        		vol.setPath(file.getFileBaseName());
+	                        		snapshotInfo.setVolume(vol);
+                        		} else {
+                        			s_logger.error("Disk has been consolidated, but top VMDK is not
found ?!");
+                        		}
+                        	}
+                        }
+                    } else {
+                    	s_logger.error("Can not find the snapshot we just used ?!");
                     }
                 }
 
@@ -1105,6 +1167,8 @@ public class VmwareStorageProcessor implements StorageProcessor {
                     s_logger.warn("Failed to destroy worker VM: " + workerVMName);
                 }
             }
+            
+            return answer;
         } catch (Throwable e) {
             if (e instanceof RemoteException) {
                 hostService.invalidateServiceContext(context);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/834fdc88/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
----------------------------------------------------------------------
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 8e3df50..6a16ffa 100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java
@@ -1551,11 +1551,13 @@ public class VirtualMachineMO extends BaseMO {
 		return diskDsFullPaths.toArray(new String[0]);
 	}
 
-	public void cloneFromCurrentSnapshot(String clonedVmName, int cpuSpeedMHz, int memoryMb,
String diskDevice,
+	// return the disk chain (VMDK datastore paths) for cloned snapshot
+	public String[] cloneFromCurrentSnapshot(String clonedVmName, int cpuSpeedMHz, int memoryMb,
String diskDevice,
 		ManagedObjectReference morDs) throws Exception {
 		assert(morDs != null);
 		String[] disks = getCurrentSnapshotDiskChainDatastorePaths(diskDevice);
 		cloneFromDiskChain(clonedVmName, cpuSpeedMHz, memoryMb, disks, morDs);
+		return disks;
 	}
 
 	public void cloneFromDiskChain(String clonedVmName, int cpuSpeedMHz, int memoryMb,
@@ -1576,7 +1578,6 @@ public class VirtualMachineMO extends BaseMO {
 		boolean bSuccess = false;
 		try {
     		VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
-    	    //VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
     		VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
 
     	    VirtualDevice device = VmwareHelper.prepareDiskDevice(clonedVmMo, -1, disks, morDs,
-1, 1);
@@ -1611,7 +1612,6 @@ public class VirtualMachineMO extends BaseMO {
 
 	public void plugDevice(VirtualDevice device) throws Exception {
         VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
-        //VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
         VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
         deviceConfigSpec.setDevice(device);
         deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
@@ -1624,7 +1624,6 @@ public class VirtualMachineMO extends BaseMO {
 
 	public void tearDownDevice(VirtualDevice device) throws Exception {
         VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
-        //VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[1];
         VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
         deviceConfigSpec.setDevice(device);
         deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
@@ -1826,6 +1825,28 @@ public class VirtualMachineMO extends BaseMO {
 
 		return null;
 	}
+	
+	public String getDiskCurrentTopBackingFileInChain(String deviceBusName) throws Exception
{
+		List<VirtualDevice> devices = (List<VirtualDevice>)_context.getVimClient().getDynamicProperty(_mor,
"config.hardware.device");
+		if(devices != null && devices.size() > 0) {
+			for(VirtualDevice device : devices) {
+				if(device instanceof VirtualDisk) {
+					s_logger.info("Test against disk device, controller key: " + device.getControllerKey()
+ ", unit number: " + device.getUnitNumber());
+
+					VirtualDeviceBackingInfo backingInfo = ((VirtualDisk)device).getBacking();
+					if(backingInfo instanceof VirtualDiskFlatVer2BackingInfo) {
+						VirtualDiskFlatVer2BackingInfo diskBackingInfo = (VirtualDiskFlatVer2BackingInfo)backingInfo;
+						
+						String deviceNumbering = getDeviceBusName(devices, device);
+						if(deviceNumbering.equals(deviceBusName))
+							return diskBackingInfo.getFileName();
+					}
+				}
+			}
+		}
+
+		return null;
+	}
 
 	@Deprecated
 	public List<Pair<String, ManagedObjectReference>> getDiskDatastorePathChain(VirtualDisk
disk, boolean followChain) throws Exception {


Mime
View raw message