You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mt...@apache.org on 2014/03/28 20:28:41 UTC

git commit: updated refs/heads/master to 0879ab8

Repository: cloudstack
Updated Branches:
  refs/heads/master d68e13fcb -> 0879ab812


CLOUDSTACK-6170 (VMware root-disk support for managed storage)


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

Branch: refs/heads/master
Commit: 0879ab812e8b533bee836ce774c843b0a15baa4a
Parents: d68e13f
Author: Mike Tutkowski <mi...@solidfire.com>
Authored: Wed Mar 26 10:48:46 2014 -0600
Committer: Mike Tutkowski <mi...@solidfire.com>
Committed: Fri Mar 28 13:15:04 2014 -0600

----------------------------------------------------------------------
 .../com/cloud/hypervisor/guru/VMwareGuru.java   | 55 +++++++++++++
 .../vmware/resource/VmwareResource.java         | 87 ++++++++++++++++----
 .../resource/VmwareStorageProcessor.java        | 27 +++++-
 3 files changed, 149 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0879ab81/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
index 9cb37f5..77c45b2 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -29,10 +29,16 @@ import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 import com.cloud.agent.api.BackupSnapshotCommand;
@@ -48,6 +54,7 @@ import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
 import com.cloud.agent.api.to.DataObjectType;
 import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.cluster.ClusterManager;
@@ -76,7 +83,10 @@ import com.cloud.secstorage.CommandExecLogVO;
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.GuestOSVO;
 import com.cloud.storage.Storage;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.secondary.SecondaryStorageVmManager;
 import com.cloud.template.VirtualMachineTemplate.BootloaderType;
 import com.cloud.utils.Pair;
@@ -123,6 +133,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
     private VMInstanceDao _vmDao;
     @Inject
     private ClusterManager _clusterMgr;
+    @Inject
+    VolumeDao _volumeDao;
+    @Inject
+    PrimaryDataStoreDao _storagePoolDao;
+    @Inject
+    VolumeDataFactory _volFactory;
 
     protected VMwareGuru() {
         super();
@@ -476,4 +492,43 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co
     public ConfigKey<?>[] getConfigKeys() {
         return new ConfigKey<?>[] {VmwareReserveCpu, VmwareReserveMemory};
     }
+
+    @Override
+    public List<Command> finalizeExpungeVolumes(VirtualMachine vm) {
+        List<Command> commands = new ArrayList<Command>();
+
+        List<VolumeVO> volumes = _volumeDao.findByInstance(vm.getId());
+
+        if (volumes != null) {
+            for (VolumeVO volume : volumes) {
+                StoragePoolVO storagePool = _storagePoolDao.findById(volume.getPoolId());
+
+                // storagePool should be null if we are expunging a volume that was never
+                // attached to a VM that was started (the "trick" for storagePool to be null
+                // is that none of the VMs this volume may have been attached to were ever started,
+                // so the volume was never assigned to a storage pool)
+                if (storagePool != null && storagePool.isManaged() && volume.getVolumeType() == Volume.Type.ROOT) {
+                    VolumeInfo volumeInfo = _volFactory.getVolume(volume.getId());
+                    PrimaryDataStore primaryDataStore = (PrimaryDataStore)volumeInfo.getDataStore();
+                    Map<String, String> details = primaryDataStore.getDetails();
+
+                    if (details == null) {
+                        details = new HashMap<String, String>();
+
+                        primaryDataStore.setDetails(details);
+                    }
+
+                    details.put(DiskTO.MANAGED, Boolean.TRUE.toString());
+
+                    DeleteCommand cmd = new DeleteCommand(volumeInfo.getTO());
+
+                    commands.add(cmd);
+
+                    break;
+                }
+            }
+        }
+
+        return commands;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0879ab81/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 f84d682..85fe91b 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
@@ -1412,9 +1412,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             DiskTO[] disks = validateDisks(vmSpec.getDisks());
             assert (disks.length > 0);
             NicTO[] nics = vmSpec.getNics();
-            Map<String, String> iqnToPath = new HashMap<String, String>();
 
-            HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, iqnToPath, cmd);
+            HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, cmd);
             if ((dataStoresDetails == null) || (dataStoresDetails.isEmpty())) {
                 String msg = "Unable to locate datastore details of the volumes to be attached";
                 s_logger.error(msg);
@@ -1471,9 +1470,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
                     for (DiskTO vol : disks) {
                         if (vol.getType() == Volume.Type.ROOT) {
-                            DataStoreTO primaryStore = vol.getData().getDataStore();
-                            /** @todo Mike T. update this in 4.4 to support root disks on managed storage */
-                            rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
+                            Map<String, String> details = vol.getDetails();
+                            boolean managed = false;
+
+                            if (details != null) {
+                                managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
+                            }
+
+                            if (managed) {
+                                String datastoreName = VmwareResource.getDatastoreName(details.get(DiskTO.IQN));
+
+                                rootDiskDataStoreDetails = dataStoresDetails.get(datastoreName);
+                            }
+                            else {
+                                DataStoreTO primaryStore = vol.getData().getDataStore();
+
+                                rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
+                            }
                         }
                     }
 
@@ -1759,7 +1772,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
             vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
             postNvpConfigBeforeStart(vmMo, vmSpec);
-            postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey);
+
+            Map<String, String> iqnToPath = new HashMap<String, String>();
+
+            postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey, iqnToPath);
 
             //
             // Power-on VM
@@ -1891,7 +1907,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         final String datastoreDiskPath;
 
         if (isManaged) {
-            datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
+            if (volumeTO.getVolumeType() == Volume.Type.ROOT) {
+                datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, dsMo.getName());
+            }
+            else {
+                datastoreDiskPath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
+            }
         } else {
             datastoreDiskPath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dcMo, vmMo.getName(), dsMo, volumeTO.getPath());
         }
@@ -2177,9 +2198,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         return controllerKey;
     }
 
-    private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey, int scsiControllerKey)
-            throws Exception {
-
+    private void postDiskConfigBeforeStart(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, DiskTO[] sortedDisks, int ideControllerKey,
+            int scsiControllerKey, Map<String, String> iqnToPath) throws Exception {
         VirtualMachineDiskInfoBuilder diskInfoBuilder = vmMo.getDiskInfoBuilder();
 
         for (DiskTO vol : sortedDisks) {
@@ -2194,14 +2214,45 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
             String[] diskChain = diskInfo.getDiskChain();
             assert (diskChain.length > 0);
 
+            Map<String, String> details = vol.getDetails();
+            boolean managed = false;
+
+            if (details != null) {
+                managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
+            }
+
             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());
+
+            if (managed) {
+                DatastoreFile originalFile = new DatastoreFile(volumeTO.getPath());
+
+                if (!file.getFileBaseName().equalsIgnoreCase(originalFile.getFileBaseName())) {
+                    if (s_logger.isInfoEnabled())
+                        s_logger.info("Detected disk-chain top file change on volume: " + volumeTO.getId() + " " + volumeTO.getPath() + " -> " + diskChain[0]);
+                }
+            }
+            else {
+                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());
+                }
             }
 
             VolumeObjectTO volInSpec = getVolumeInSpec(vmSpec, volumeTO);
-            volInSpec.setPath(file.getFileBaseName());
+
+            if (managed) {
+                String datastoreVolumePath = diskChain[0];
+
+                iqnToPath.put(details.get(DiskTO.IQN), datastoreVolumePath);
+
+                vol.setPath(datastoreVolumePath);
+                volumeTO.setPath(datastoreVolumePath);
+                volInSpec.setPath(datastoreVolumePath);
+            }
+            else {
+                volInSpec.setPath(file.getFileBaseName());
+            }
+
             volInSpec.setChainInfo(_gson.toJson(diskInfo));
         }
     }
@@ -2263,7 +2314,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
     }
 
     private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context,
-            DiskTO[] disks, Map<String, String> iqnToPath, Command cmd) throws Exception {
+            DiskTO[] disks, Command cmd) throws Exception {
         HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> mapIdToMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
 
         assert (hyperHost != null) && (context != null);
@@ -2299,8 +2350,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                             DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDatastore);
                             String datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
 
-                            iqnToPath.put(iScsiName, datastoreVolumePath);
-
                             volumeTO.setPath(datastoreVolumePath);
                             vol.setPath(datastoreVolumePath);
                         }
@@ -3462,6 +3511,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
         }
 
         addRemoveInternetScsiTargetsToAllHosts(false, lstManagedTargets, lstHosts);
+
+        rescanAllHosts(lstHosts);
     }
 
     private void addRemoveInternetScsiTargetsToAllHosts(final boolean add, final List<HostInternetScsiHbaStaticTarget> lstTargets,
@@ -4281,7 +4332,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
     public Answer execute(DeleteCommand cmd) {
         if (s_logger.isInfoEnabled()) {
-            s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
+            s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
         }
 
         /*

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0879ab81/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 9d86b16..86e6554 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -46,6 +46,7 @@ import org.apache.cloudstack.storage.command.DeleteCommand;
 import org.apache.cloudstack.storage.command.DettachCommand;
 import org.apache.cloudstack.storage.command.ForgetObjectCmd;
 import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
 import org.apache.cloudstack.storage.to.VolumeObjectTO;
@@ -1420,10 +1421,17 @@ public class VmwareStorageProcessor implements StorageProcessor {
         return new CreateObjectAnswer(newSnapshot);
     }
 
+    // format: [datastore_name] file_name.vmdk (the '[' and ']' chars should only be used to denote the datastore)
+    private String getManagedDatastoreNameFromPath(String path) {
+        int lastIndexOf = path.lastIndexOf("]");
+
+        return path.substring(1, lastIndexOf);
+    }
+
     @Override
     public Answer deleteVolume(DeleteCommand cmd) {
         if (s_logger.isInfoEnabled()) {
-            s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
+            s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
         }
 
         try {
@@ -1431,8 +1439,23 @@ public class VmwareStorageProcessor implements StorageProcessor {
             VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
             VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
             DataStoreTO store = vol.getDataStore();
+            PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO)store;
+
+            Map<String, String> details = primaryDataStoreTO.getDetails();
+            boolean isManaged = false;
+            String managedDatastoreName = null;
+
+            if (details != null) {
+                isManaged = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
+
+                if (isManaged) {
+                    managedDatastoreName = getManagedDatastoreNameFromPath(vol.getPath());
+                }
+            }
+
+            ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost,
+                isManaged ? managedDatastoreName : store.getUuid());
 
-            ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
             if (morDs == null) {
                 String msg = "Unable to find datastore based on volume mount point " + store.getUuid();
                 s_logger.error(msg);