Support for volume live migration across datastores
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/20106139 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/20106139 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/20106139 Branch: refs/heads/vmware-storage-motion Commit: 20106139cf3ae3db11150f084c4155026d8e7584 Parents: cabbba7 Author: Sateesh Chodapuneedi <sate...@apache.org> Authored: Mon May 20 07:35:46 2013 +0530 Committer: Sateesh Chodapuneedi <sate...@apache.org> Committed: Tue May 28 16:51:35 2013 +0530 ---------------------------------------------------------------------- .../hypervisor/vmware/manager/VmwareManager.java | 5 + .../vmware/manager/VmwareManagerImpl.java | 31 ++++++++ .../hypervisor/vmware/resource/VmwareResource.java | 61 ++++++++++++++- 3 files changed, 93 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/20106139/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java index fb6d3d6..9273143 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.List; import java.util.Map; +import com.cloud.agent.api.to.VolumeTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.vmware.manager.VmwareStorageManager; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -66,4 +67,8 @@ public interface VmwareManager { String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType); public String getRootDiskController(); + + String getVmName(long l); + + String getStoragePoolOfVolume(long volumeId); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/20106139/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index 9f260f1..0d50a2c 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -35,6 +35,8 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -45,6 +47,8 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.to.VolumeTO; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; @@ -79,6 +83,9 @@ import com.cloud.serializer.GsonHelper; import com.cloud.server.ConfigurationServer; import com.cloud.storage.JavaStorageLayer; import com.cloud.storage.StorageLayer; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; @@ -92,6 +99,8 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SshHelper; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.HostConnectSpec; @@ -124,6 +133,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Inject ConfigurationDao _configDao; @Inject ConfigurationServer _configServer; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; + @Inject VMInstanceDao _vmDao; + @Inject VolumeDao _volDao; + @Inject DataStoreManager dataStoreMgr; String _mountParent; StorageLayer _storage; @@ -865,4 +877,23 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw public String getRootDiskController() { return _rootDiskController; } + + @Override + public String getVmName(long volumeId) { + Long instanceId; + VolumeVO vol = _volDao.findById(volumeId); + instanceId = vol.getInstanceId(); + VMInstanceVO vmInstance = null; + if (instanceId != null) { + vmInstance = _vmDao.findById(instanceId); + } + return vmInstance.getInstanceName(); + } + + @Override + public String getStoragePoolOfVolume(long volumeId) { + VolumeVO vol = _volDao.findById(volumeId); + long poolId = vol.getPoolId(); + return dataStoreMgr.getPrimaryDataStore(poolId).getUuid(); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/20106139/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 91579ae..3c9319e 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 @@ -167,6 +167,7 @@ import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateVolumeOVACommand; import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.storage.PrepareOVAPackingAnswer; import com.cloud.agent.api.storage.PrepareOVAPackingCommand; @@ -297,9 +298,6 @@ import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator; import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.VirtualSCSISharing; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; -import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; import org.apache.log4j.Logger; import org.apache.log4j.NDC; @@ -3588,8 +3586,63 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } private Answer execute(MigrateVolumeCommand cmd) { + String volumePath = cmd.getVolumePath(); + StorageFilerTO poolTo = cmd.getPool(); - return null; + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd)); + } + + VmwareContext context = getServiceContext(); + VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + final String vmName = mgr.getVmName(cmd.getVolumeId()); + + VirtualMachineMO vmMo = null; + VmwareHypervisorHost srcHyperHost = null; + + ManagedObjectReference morDs = null; + ManagedObjectReference morDc = null; + VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec(); + List<VirtualMachineRelocateSpecDiskLocator> diskLocators = new ArrayList<VirtualMachineRelocateSpecDiskLocator>(); + VirtualMachineRelocateSpecDiskLocator diskLocator = null; + + String srcDiskName = ""; + String srcDsName = ""; + + try { + srcHyperHost = getHyperHost(getServiceContext()); + morDc = srcHyperHost.getHyperHostDatacenter(); + srcDsName = mgr.getStoragePoolOfVolume(cmd.getVolumeId()); + + // find VM through datacenter (VM is not at the target host yet) + vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName); + if (vmMo == null) { + String msg = "VM " + vmName + " does not exist in VMware datacenter " + morDc.getValue(); + s_logger.error(msg); + throw new Exception(msg); + } + + srcDiskName = String.format("[%s] %s.vmdk", srcDsName, volumePath); + diskLocator = new VirtualMachineRelocateSpecDiskLocator(); + diskLocator.setDatastore(morDs); + diskLocator.setDiskId(getVirtualDiskInfo(vmMo, srcDiskName)); + + diskLocators.add(diskLocator); + relocateSpec.getDisk().add(diskLocator); + + // Change datastore + if (!vmMo.changeDatastore(relocateSpec)) { + throw new Exception("Change datastore operation failed during volume migration"); + } else { + s_logger.debug("Successfully migrated volume " + vmName + " to target datastore"); + } + + return new MigrateVolumeAnswer(cmd, true, null, volumePath); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.error(msg, e); + return new MigrateVolumeAnswer(cmd, false, msg, null); + } } private int getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception {