cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sate...@apache.org
Subject git commit: updated refs/heads/vmware-storage-motion to 73f6edd
Date Fri, 17 May 2013 19:09:58 GMT
Updated Branches:
  refs/heads/vmware-storage-motion 20541641f -> 73f6edd47


CLOUDSTACK-659
Support for storage migration in Cloudstack deployment over VMware
Added VmwareStorageMotionStrategy to deal with storage motion tasks.
Added target host parameter to MigrateWithStorageCommand.

Signed-off-by: Sateesh Chodapuneedi <sateesh@apache.org>


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

Branch: refs/heads/vmware-storage-motion
Commit: 73f6edd47b341ec6b1ec38fb816b9585cc97d7f1
Parents: 2054164
Author: Sateesh Chodapuneedi <sateesh@apache.org>
Authored: Sat May 18 00:32:07 2013 +0530
Committer: Sateesh Chodapuneedi <sateesh@apache.org>
Committed: Sat May 18 00:38:20 2013 +0530

----------------------------------------------------------------------
 .../cloud/agent/api/MigrateWithStorageCommand.java |   12 +
 .../motion/VmwareStorageMotionStrategy.java        |  212 +++++++++++++++
 2 files changed, 224 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73f6edd4/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
index 058aa15..a108a2a 100644
--- a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
+++ b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
@@ -24,10 +24,18 @@ import com.cloud.agent.api.to.StorageFilerTO;
 public class MigrateWithStorageCommand extends Command {
     VirtualMachineTO vm;
     Map<VolumeTO, StorageFilerTO> volumeToFiler;
+    String tgtHost;
 
     public MigrateWithStorageCommand(VirtualMachineTO vm, Map<VolumeTO, StorageFilerTO>
volumeToFiler) {
         this.vm = vm;
         this.volumeToFiler = volumeToFiler;
+        this.tgtHost = null;
+    }
+
+    public MigrateWithStorageCommand(VirtualMachineTO vm, Map<VolumeTO, StorageFilerTO>
volumeToFiler, String tgtHost) {
+        this.vm = vm;
+        this.volumeToFiler = volumeToFiler;
+        this.tgtHost = tgtHost;
     }
 
     public VirtualMachineTO getVirtualMachine() {
@@ -38,6 +46,10 @@ public class MigrateWithStorageCommand extends Command {
         return volumeToFiler;
     }
 
+    public String getTargetHost() {
+        return tgtHost;
+    }
+
     @Override
     public boolean executeInSequence() {
         return true;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/73f6edd4/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
new file mode 100644
index 0000000..1678a04
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cloudstack.storage.motion;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.MigrateWithStorageAnswer;
+import com.cloud.agent.api.MigrateWithStorageCommand;
+import com.cloud.agent.api.MigrateWithStorageCompleteAnswer;
+import com.cloud.agent.api.MigrateWithStorageCompleteCommand;
+import com.cloud.agent.api.MigrateWithStorageReceiveAnswer;
+import com.cloud.agent.api.MigrateWithStorageReceiveCommand;
+import com.cloud.agent.api.MigrateWithStorageSendAnswer;
+import com.cloud.agent.api.MigrateWithStorageSendCommand;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.Host;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@Component
+public class VmwareStorageMotionStrategy implements DataMotionStrategy {
+    private static final Logger s_logger = Logger.getLogger(VmwareStorageMotionStrategy.class);
+    @Inject AgentManager agentMgr;
+    @Inject VolumeDao volDao;
+    @Inject VolumeDataFactory volFactory;
+    @Inject PrimaryDataStoreDao storagePoolDao;
+    @Inject VMInstanceDao instanceDao;
+
+    @Override
+    public boolean canHandle(DataObject srcData, DataObject destData) {
+        return false;
+    }
+
+    @Override
+    public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host
destHost) {
+        if (srcHost.getHypervisorType() == HypervisorType.VMware && destHost.getHypervisorType()
== HypervisorType.VMware) {
+            s_logger.debug(this.getClass() + " can handle the request because the hosts have
VMware hypervisor");
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Void copyAsync(DataObject srcData, DataObject destData,
+            AsyncCompletionCallback<CopyCommandResult> callback) {
+        CopyCommandResult result = new CopyCommandResult(null, null);
+        result.setResult("Unsupported operation requested for copying data.");
+        callback.complete(result);
+
+        return null;
+    }
+
+    @Override
+    public Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo,
Host srcHost, Host destHost,
+            AsyncCompletionCallback<CopyCommandResult> callback) {
+        Answer answer = null;
+        String errMsg = null;
+        try {
+            VMInstanceVO instance = instanceDao.findById(vmTo.getId());
+            if (instance != null) {
+                if (srcHost.getClusterId() == destHost.getClusterId()) {
+                    answer = migrateVmWithVolumesWithinCluster(instance, vmTo, srcHost, destHost,
volumeMap);
+                } else {
+                    answer = migrateVmWithVolumesAcrossCluster(instance, vmTo, srcHost, destHost,
volumeMap);
+                }
+            } else {
+                throw new CloudRuntimeException("Unsupported operation requested for moving
data.");
+            }
+        } catch (Exception e) {
+            s_logger.error("copy failed", e);
+            errMsg = e.toString();
+        }
+
+        CopyCommandResult result = new CopyCommandResult(null, answer);
+        result.setResult(errMsg);
+        callback.complete(result);
+        return null;
+    }
+
+    private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to,
Host srcHost,
+            Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException
{
+
+        // Initiate migration of a virtual machine with it's volumes.
+        try {
+            Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO,
StorageFilerTO>();
+            for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet())
{
+                VolumeInfo volume = entry.getKey();
+                VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId()));
+                StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue());
+                volumeToFilerto.put(volumeTo, filerTo);
+            }
+
+            // Migration across cluster needs to be done in three phases.
+            // 1. Send a migrate command to source resource to initiate migration 
+            //	  Run validations against target!! 
+            // 2. Complete the process. Update the volume details.
+            MigrateWithStorageCommand migrateWithStorageCmd = new MigrateWithStorageCommand(to,
volumeToFilerto, destHost.getGuid());
+            MigrateWithStorageAnswer migrateWithStorageAnswer = (MigrateWithStorageAnswer)
agentMgr.send(
+                    srcHost.getId(), migrateWithStorageCmd);
+            if (migrateWithStorageAnswer == null) {
+                s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost
+ " failed.");
+                throw new CloudRuntimeException("Error while migrating the vm " + vm + "
to host " + destHost);
+            } else if (!migrateWithStorageAnswer.getResult()) {
+                s_logger.error("Migration with storage of vm " + vm+ " failed. Details: "
+ migrateWithStorageAnswer.getDetails());
+                throw new CloudRuntimeException("Error while migrating the vm " + vm + "
to host " + destHost +
+                        ". " + migrateWithStorageAnswer.getDetails());
+            } else {
+                // Update the volume details after migration.
+                updateVolumesAfterMigration(volumeToPool);
+            }
+            s_logger.debug("Storage migration of VM " + vm.getInstanceName() + " completed
successfully. Migrated to host " + destHost.getName());
+
+            return migrateWithStorageAnswer;
+        } catch (OperationTimedoutException e) {
+            s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
+            throw new AgentUnavailableException("Operation timed out on storage motion for
" + vm, destHost.getId());
+        }
+    }
+
+    private Answer migrateVmWithVolumesWithinCluster(VMInstanceVO vm, VirtualMachineTO to,
Host srcHost,
+            Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException
{
+
+        // Initiate migration of a virtual machine with it's volumes.
+        try {
+            Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO,
StorageFilerTO>();
+            for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet())
{
+                VolumeInfo volume = entry.getKey();
+                VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId()));
+                StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue());
+                volumeToFilerto.put(volumeTo, filerTo);
+            }
+
+            MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto);
+            MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer) agentMgr.send(destHost.getId(),
command);
+            if (answer == null) {
+                s_logger.error("Migration with storage of vm " + vm + " failed.");
+                throw new CloudRuntimeException("Error while migrating the vm " + vm + "
to host " + destHost);
+            } else if (!answer.getResult()) {
+                s_logger.error("Migration with storage of vm " + vm+ " failed. Details: "
+ answer.getDetails());
+                throw new CloudRuntimeException("Error while migrating the vm " + vm + "
to host " + destHost +
+                        ". " + answer.getDetails());
+            } else {
+                // Update the volume details after migration.
+                updateVolumesAfterMigration(volumeToPool);
+            }
+
+            return answer;
+        } catch (OperationTimedoutException e) {
+            s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
+            throw new AgentUnavailableException("Operation timed out on storage motion for
" + vm, destHost.getId());
+        }
+    }
+
+    private void updateVolumesAfterMigration(Map<VolumeInfo, DataStore> volumeToPool)
{
+        for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+            VolumeInfo volume = entry.getKey();
+            StoragePool pool = (StoragePool)entry.getValue();
+
+            VolumeVO volumeVO = volDao.findById(volume.getId());
+            Long oldPoolId = volumeVO.getPoolId();
+            volumeVO.setLastPoolId(oldPoolId);
+            volumeVO.setFolder(pool.getPath());
+            volumeVO.setPodId(pool.getPodId());
+            volumeVO.setPoolId(pool.getId());
+
+            volDao.update(volume.getId(), volumeVO);
+            s_logger.debug("Volume path was successfully updated for volume " + volume.getName()
+ " after it was migrated.");
+        }
+    }
+}


Mime
View raw message