Updated Branches:
  refs/heads/4.2 f27ca638c -> bfe30cd2e

CLOUDSTACK-3681: fix bunch of bugs related to vmware, regarding to snapshot


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

Branch: refs/heads/4.2
Commit: bfe30cd2e31906365a306d87fe331ccdcec5c33c
Parents: f27ca63
Author: Edison Su <[email protected]>
Authored: Wed Jul 24 15:36:39 2013 -0700
Committer: Edison Su <[email protected]>
Committed: Wed Jul 24 15:54:36 2013 -0700

----------------------------------------------------------------------
 api/src/com/cloud/agent/api/to/DataTO.java      |   3 +
 .../com/cloud/hypervisor/HypervisorGuru.java    |   4 +-
 .../storage/resource/StorageProcessor.java      |   1 +
 .../StorageSubsystemCommandHandlerBase.java     |   2 +
 .../cloudstack/storage/to/SnapshotObjectTO.java |   1 +
 .../cloudstack/storage/to/TemplateObjectTO.java |   9 +
 .../cloudstack/storage/to/VolumeObjectTO.java   |   8 +
 .../kvm/storage/KVMStorageProcessor.java        |   5 +
 .../com/cloud/hypervisor/guru/VMwareGuru.java   | 128 ++++++------
 .../resource/VmwareStorageProcessor.java        | 199 ++++++++++++++++++-
 .../xen/resource/XenServerStorageProcessor.java |   7 +-
 .../cloud/hypervisor/HypervisorGuruBase.java    |   5 +-
 .../hypervisor/HypervisorGuruManagerImpl.java   |  14 +-
 13 files changed, 297 insertions(+), 89 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/api/src/com/cloud/agent/api/to/DataTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/DataTO.java 
b/api/src/com/cloud/agent/api/to/DataTO.java
index 21e802f..8d24a05 100644
--- a/api/src/com/cloud/agent/api/to/DataTO.java
+++ b/api/src/com/cloud/agent/api/to/DataTO.java
@@ -18,9 +18,12 @@
  */
 package com.cloud.agent.api.to;
 
+import com.cloud.hypervisor.Hypervisor;
+
 public interface DataTO {
     public DataObjectType getObjectType();
     public DataStoreTO getDataStore();
+    public Hypervisor.HypervisorType getHypervisorType();
     /**
      * @return
      */

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/api/src/com/cloud/hypervisor/HypervisorGuru.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/hypervisor/HypervisorGuru.java 
b/api/src/com/cloud/hypervisor/HypervisorGuru.java
index 47ca17a..0d0fed8 100644
--- a/api/src/com/cloud/hypervisor/HypervisorGuru.java
+++ b/api/src/com/cloud/hypervisor/HypervisorGuru.java
@@ -22,6 +22,7 @@ import com.cloud.agent.api.Command;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.utils.Pair;
 import com.cloud.utils.component.Adapter;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.VirtualMachine;
@@ -40,12 +41,13 @@ public interface HypervisorGuru extends Adapter {
 
     /**
      * Give hypervisor guru opportunity to decide if certain command needs to 
be delegated to other host, mainly to secondary storage VM host
+     *
      * @param hostId original hypervisor host
      * @param cmd command that is going to be sent, hypervisor guru usually 
needs to register various context objects into the command object
      *
      * @return delegated host id if the command will be delegated
      */
-    long getCommandHostDelegation(long hostId, Command cmd);
+    Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd);
 
     /**
      *  @return true if VM can be migrated independently with CloudStack, and 
therefore CloudStack needs to track and reflect host change

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/core/src/com/cloud/storage/resource/StorageProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StorageProcessor.java 
b/core/src/com/cloud/storage/resource/StorageProcessor.java
index f503fa3..5fa9f8a 100644
--- a/core/src/com/cloud/storage/resource/StorageProcessor.java
+++ b/core/src/com/cloud/storage/resource/StorageProcessor.java
@@ -32,6 +32,7 @@ public interface StorageProcessor {
     public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd);
     public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd);
     public Answer createTemplateFromVolume(CopyCommand cmd);
+    public Answer createTemplateFromSnapshot(CopyCommand cmd);
     public Answer backupSnapshot(CopyCommand cmd);
     public Answer attachIso(AttachCommand cmd);
     public Answer attachVolume(AttachCommand cmd);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
----------------------------------------------------------------------
diff --git 
a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java 
b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
index c0bbfbe..385a277 100644
--- 
a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
+++ 
b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
@@ -84,6 +84,8 @@ public class StorageSubsystemCommandHandlerBase implements 
StorageSubsystemComma
             return processor.backupSnapshot(cmd);
         } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && 
destData.getObjectType() == DataObjectType.VOLUME) {
                return processor.createVolumeFromSnapshot(cmd);
+        } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && 
destData.getObjectType() == DataObjectType.TEMPLATE) {
+            return processor.createTemplateFromSnapshot(cmd);
         }
 
         return new Answer(cmd, false, "not implemented yet");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
----------------------------------------------------------------------
diff --git 
a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java 
b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
index 4754dcf..d2cb72a 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
@@ -111,6 +111,7 @@ public class SnapshotObjectTO implements DataTO {
         this.name = name;
     }
 
+    @Override
     public HypervisorType getHypervisorType() {
         return hypervisorType;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
----------------------------------------------------------------------
diff --git 
a/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java 
b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
index abe59eb..2347de3 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
@@ -16,6 +16,7 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import com.cloud.hypervisor.Hypervisor;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
 
 import com.cloud.agent.api.to.DataObjectType;
@@ -38,6 +39,7 @@ public class TemplateObjectTO implements DataTO {
     private String name;
     private String guestOsType;
     private Long size;
+    private Hypervisor.HypervisorType hypervisorType;
 
     public TemplateObjectTO() {
 
@@ -53,6 +55,7 @@ public class TemplateObjectTO implements DataTO {
         this.accountId = template.getAccountId();
         this.name = template.getUniqueName();
         this.format = template.getFormat();
+        this.hypervisorType = template.getHypervisorType();
     }
 
     public TemplateObjectTO(TemplateInfo template) {
@@ -69,6 +72,7 @@ public class TemplateObjectTO implements DataTO {
         if (template.getDataStore() != null) {
             this.imageDataStore = template.getDataStore().getTO();
         }
+        this.hypervisorType = template.getHypervisorType();
     }
 
     @Override
@@ -128,6 +132,11 @@ public class TemplateObjectTO implements DataTO {
         return this.imageDataStore;
     }
 
+    @Override
+    public Hypervisor.HypervisorType getHypervisorType() {
+        return this.hypervisorType;
+    }
+
     public void setDataStore(DataStoreTO store){
         this.imageDataStore = store;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
----------------------------------------------------------------------
diff --git 
a/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java 
b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
index ab3d5ea..9f466ae 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
@@ -16,6 +16,7 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import com.cloud.hypervisor.Hypervisor;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 
 import com.cloud.agent.api.to.DataObjectType;
@@ -41,6 +42,7 @@ public class VolumeObjectTO implements DataTO {
     private Long bytesWriteRate;
     private Long iopsReadRate;
     private Long iopsWriteRate;
+    private Hypervisor.HypervisorType hypervisorType;
 
     public VolumeObjectTO() {
 
@@ -67,6 +69,7 @@ public class VolumeObjectTO implements DataTO {
         this.bytesWriteRate = volume.getBytesWriteRate();
         this.iopsReadRate = volume.getIopsReadRate();
         this.iopsWriteRate = volume.getIopsWriteRate();
+        this.hypervisorType = volume.getHypervisorType();
     }
 
     public String getUuid() {
@@ -87,6 +90,11 @@ public class VolumeObjectTO implements DataTO {
         return this.dataStore;
     }
 
+    @Override
+    public Hypervisor.HypervisorType getHypervisorType() {
+        return this.hypervisorType;
+    }
+
 
     public void setDataStore(DataStoreTO store){
         this.dataStore = store;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
 
b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
index 25c94f7..ea6460a 100644
--- 
a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
+++ 
b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -404,6 +404,11 @@ public class KVMStorageProcessor implements 
StorageProcessor {
     }
 
     @Override
+    public Answer createTemplateFromSnapshot(CopyCommand cmd) {
+        return null;  //To change body of implemented methods use File | 
Settings | File Templates.
+    }
+
+    @Override
     public Answer backupSnapshot(CopyCommand cmd) {
         DataTO srcData = cmd.getSrcTO();
         DataTO destData = cmd.getDestTO();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/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 b86b6d9..fa6831e 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java
@@ -28,6 +28,7 @@ import java.util.UUID;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import com.cloud.host.Host;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.storage.command.CopyCommand;
@@ -42,7 +43,6 @@ import com.cloud.agent.api.UnregisterVMCommand;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
 import com.cloud.agent.api.storage.CreateVolumeOVACommand;
 import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
-import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 import com.cloud.agent.api.to.DataObjectType;
 import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.DataTO;
@@ -294,92 +294,82 @@ public class VMwareGuru extends HypervisorGuruBase 
implements HypervisorGuru {
     }
 
     @Override @DB
-    public long getCommandHostDelegation(long hostId, Command cmd) {
+    public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command 
cmd) {
         boolean needDelegation = false;
 
-        if(cmd instanceof PrimaryStorageDownloadCommand ||
-                cmd instanceof BackupSnapshotCommand ||
-                cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
-                cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
-                cmd instanceof CopyVolumeCommand ||
-                cmd instanceof CreateVolumeOVACommand ||
-                cmd instanceof PrepareOVAPackingCommand ||
-                cmd instanceof CreateVolumeFromSnapshotCommand ||
-                cmd instanceof CopyCommand) {
-            if (cmd instanceof CopyCommand) {
-                CopyCommand cpyCommand = (CopyCommand)cmd;
-                DataTO srcData = cpyCommand.getSrcTO();
-                DataStoreTO srcStoreTO = srcData.getDataStore();
-                DataTO destData = cpyCommand.getDestTO();
-                DataStoreTO destStoreTO = destData.getDataStore();
-
-                if (destData.getObjectType() == DataObjectType.VOLUME && 
destStoreTO.getRole() == DataStoreRole.Primary &&
-                        srcData.getObjectType() == DataObjectType.TEMPLATE && 
srcStoreTO.getRole() == DataStoreRole.Primary) {
-                    needDelegation = false;
-                } else {
-                    needDelegation = true;
-                }
+        if (cmd instanceof CopyCommand) {
+            CopyCommand cpyCommand = (CopyCommand)cmd;
+            DataTO srcData = cpyCommand.getSrcTO();
+            DataStoreTO srcStoreTO = srcData.getDataStore();
+            DataTO destData = cpyCommand.getDestTO();
+            DataStoreTO destStoreTO = destData.getDataStore();
+
+            if (!(HypervisorType.VMware == srcData.getHypervisorType() ||
+                    HypervisorType.VMware == destData.getHypervisorType()
+            )) {
+                return new Pair<Boolean, Long>(Boolean.FALSE, new 
Long(hostId));
+            }
+
+            if (destData.getObjectType() == DataObjectType.VOLUME && 
destStoreTO.getRole() == DataStoreRole.Primary &&
+                    srcData.getObjectType() == DataObjectType.TEMPLATE && 
srcStoreTO.getRole() == DataStoreRole.Primary) {
+                needDelegation = false;
             } else {
                 needDelegation = true;
             }
+        }
 
+        if(!needDelegation) {
+            return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
         }
-        /* Fang: remove this before checking in */
-        // needDelegation = false;
 
-        if (cmd instanceof PrepareOVAPackingCommand ||
-                cmd instanceof CreateVolumeOVACommand  ) {
+        HostVO host = _hostDao.findById(hostId);
+        long dcId = host.getDataCenterId();
+
+        Pair<HostVO, SecondaryStorageVmVO> cmdTarget = 
_secStorageMgr.assignSecStorageVm(dcId, cmd);
+        if(cmdTarget != null) {
+            // TODO, we need to make sure agent is actually connected too
+
             cmd.setContextParam("hypervisor", 
HypervisorType.VMware.toString());
-        }
-        if(needDelegation) {
-            HostVO host = _hostDao.findById(hostId);
-            assert(host != null);
-            assert(host.getHypervisorType() == HypervisorType.VMware);
-            long dcId = host.getDataCenterId();
-
-            Pair<HostVO, SecondaryStorageVmVO> cmdTarget = 
_secStorageMgr.assignSecStorageVm(dcId, cmd);
-            if(cmdTarget != null) {
-                // TODO, we need to make sure agent is actually connected too
-                cmd.setContextParam("hypervisor", 
HypervisorType.VMware.toString());
+            if (host.getType() == Host.Type.Routing) {
                 Map<String, String> hostDetails = 
_hostDetailsDao.findDetails(hostId);
                 cmd.setContextParam("guid", 
resolveNameInGuid(hostDetails.get("guid")));
                 cmd.setContextParam("username", hostDetails.get("username"));
                 cmd.setContextParam("password", hostDetails.get("password"));
                 cmd.setContextParam("serviceconsole", 
_vmwareMgr.getServiceConsolePortGroupName());
                 cmd.setContextParam("manageportgroup", 
_vmwareMgr.getManagementPortGroupName());
+            }
 
-                CommandExecLogVO execLog = new 
CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), 
cmd.getClass().getSimpleName(), 1);
-                _cmdExecLogDao.persist(execLog);
-                cmd.setContextParam("execid", String.valueOf(execLog.getId()));
-
-                if(cmd instanceof BackupSnapshotCommand ||
-                        cmd instanceof CreatePrivateTemplateFromVolumeCommand 
||
-                        cmd instanceof 
CreatePrivateTemplateFromSnapshotCommand ||
-                        cmd instanceof CopyVolumeCommand ||
-                        cmd instanceof CopyCommand ||
-                        cmd instanceof CreateVolumeOVACommand ||
-                        cmd instanceof PrepareOVAPackingCommand ||
-                        cmd instanceof CreateVolumeFromSnapshotCommand) {
-
-                    String workerName = _vmwareMgr.composeWorkerName();
-                    long checkPointId = 1;
-                    // FIXME: Fix                    long checkPointId = 
_checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), 
workerName));
-                    cmd.setContextParam("worker", workerName);
-                    cmd.setContextParam("checkpoint", 
String.valueOf(checkPointId));
-
-                    // some commands use 2 workers
-                    String workerName2 = _vmwareMgr.composeWorkerName();
-                    long checkPointId2 = 1;
-                    // FIXME: Fix                    long checkPointId2 = 
_checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), 
workerName2));
-                    cmd.setContextParam("worker2", workerName2);
-                    cmd.setContextParam("checkpoint2", 
String.valueOf(checkPointId2));
-                }
-
-                return cmdTarget.first().getId();
+            CommandExecLogVO execLog = new 
CommandExecLogVO(cmdTarget.first().getId(), cmdTarget.second().getId(), 
cmd.getClass().getSimpleName(), 1);
+            _cmdExecLogDao.persist(execLog);
+            cmd.setContextParam("execid", String.valueOf(execLog.getId()));
+
+            if(cmd instanceof BackupSnapshotCommand ||
+                    cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
+                    cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
+                    cmd instanceof CopyVolumeCommand ||
+                    cmd instanceof CopyCommand ||
+                    cmd instanceof CreateVolumeOVACommand ||
+                    cmd instanceof PrepareOVAPackingCommand ||
+                    cmd instanceof CreateVolumeFromSnapshotCommand) {
+
+                String workerName = _vmwareMgr.composeWorkerName();
+                long checkPointId = 1;
+                // FIXME: Fix                    long checkPointId = 
_checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), 
workerName));
+                cmd.setContextParam("worker", workerName);
+                cmd.setContextParam("checkpoint", 
String.valueOf(checkPointId));
+
+                // some commands use 2 workers
+                String workerName2 = _vmwareMgr.composeWorkerName();
+                long checkPointId2 = 1;
+                // FIXME: Fix                    long checkPointId2 = 
_checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), 
workerName2));
+                cmd.setContextParam("worker2", workerName2);
+                cmd.setContextParam("checkpoint2", 
String.valueOf(checkPointId2));
             }
-        }
 
-        return hostId;
+            return new Pair<Boolean, 
Long>(Boolean.TRUE,cmdTarget.first().getId());
+
+        }
+        return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/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 4760ac2..ccf4e43 100644
--- 
a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
+++ 
b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -39,6 +39,7 @@ 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;
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 
 import com.cloud.agent.api.Answer;
@@ -77,7 +78,6 @@ import com.cloud.storage.Volume;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.template.VmdkProcessor;
 import com.cloud.utils.Pair;
-import com.cloud.utils.StringUtils;
 import com.cloud.utils.Ternary;
 import com.cloud.utils.script.Script;
 import com.cloud.vm.VirtualMachine.State;
@@ -543,7 +543,6 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
        @Override
        public Answer createTemplateFromVolume(CopyCommand cmd) {
                VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
-               PrimaryDataStoreTO primaryStore = 
(PrimaryDataStoreTO)volume.getDataStore();
                TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
                DataStoreTO imageStore = template.getDataStore();
                
@@ -579,7 +578,7 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
                                        hostService.getWorkerName(context, cmd, 
0));
 
                        TemplateObjectTO newTemplate = new TemplateObjectTO();
-                       newTemplate.setPath(template.getName());
+                       newTemplate.setPath(result.first());
                        newTemplate.setFormat(ImageFormat.OVA);
                        newTemplate.setSize(result.third());
                        return new CopyCmdAnswer(newTemplate);
@@ -591,12 +590,196 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
 
                        s_logger.error("Unexpecpted exception ", e);
 
-                       details = "CreatePrivateTemplateFromVolumeCommand 
exception: " + StringUtils.getExceptionStackInfo(e);
+                       details = "CreatePrivateTemplateFromVolumeCommand 
exception: " + e.toString();
                        return new CopyCmdAnswer(details);
                }
        }
-       
-       private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, 
String volumePath,
+
+    private void writeMetaOvaForTemplate(String installFullPath, String 
ovfFilename, String vmdkFilename,
+                                         String templateName, long diskSize) 
throws Exception {
+
+        // TODO a bit ugly here
+        BufferedWriter out = null;
+        try {
+            out = new BufferedWriter(new OutputStreamWriter(new 
FileOutputStream(installFullPath + "/" + templateName +".ova.meta")));
+            out.write("ova.filename=" + templateName + ".ova");
+            out.newLine();
+            out.write("version=1.0");
+            out.newLine();
+            out.write("ovf=" + ovfFilename);
+            out.newLine();
+            out.write("numDisks=1");
+            out.newLine();
+            out.write("disk1.name=" + vmdkFilename);
+            out.newLine();
+            out.write("disk1.size=" + diskSize);
+            out.newLine();
+        } finally {
+            if(out != null)
+                out.close();
+        }
+    }
+
+    private Ternary<String, Long, Long> createTemplateFromSnapshot(String 
installPath, String templateUniqueName,
+                                                                   String 
secStorageUrl, String snapshotPath, Long templateId) throws Exception {
+        //Snapshot path is decoded in this form: 
/snapshots/account/volumeId/uuid/uuid
+        String[] tokens = snapshotPath.split(File.separator);
+        String backupSSUuid = tokens[tokens.length - 1];
+        String snapshotFolder = StringUtils.join(tokens, File.separator, 0, 
tokens.length -1);
+
+        String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+        String installFullPath = secondaryMountPoint + "/" + installPath;
+        String installFullOVAName = installFullPath + "/" + templateUniqueName 
+ ".ova";  //Note: volss for tmpl
+        String snapshotRoot = secondaryMountPoint + "/" + snapshotFolder;
+        String snapshotFullOVAName = snapshotRoot + "/" + backupSSUuid + 
".ova";
+        String snapshotFullOvfName = snapshotRoot + "/" + backupSSUuid + 
".ovf";
+        String result;
+        Script command;
+        String templateVMDKName = "";
+        String snapshotFullVMDKName = snapshotRoot + "/" + backupSSUuid + "/";
+
+        synchronized(installPath.intern()) {
+            command = new Script(false, "mkdir", _timeout, s_logger);
+            command.add("-p");
+            command.add(installFullPath);
+
+            result = command.execute();
+            if(result != null) {
+                String msg = "unable to prepare template directory: "
+                        + installPath + ", storage: " + secStorageUrl + ", 
error msg: " + result;
+                s_logger.error(msg);
+                throw new Exception(msg);
+            }
+        }
+
+        try {
+            if(new File(snapshotFullOVAName).exists()) {
+                command = new Script(false, "cp", _timeout, s_logger);
+                command.add(snapshotFullOVAName);
+                command.add(installFullOVAName);
+                result = command.execute();
+                if(result != null) {
+                    String msg = "unable to copy snapshot " + 
snapshotFullOVAName + " to " + installFullPath;
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                }
+
+                // untar OVA file at template directory
+                command = new Script("tar", 0, s_logger);
+                command.add("--no-same-owner");
+                command.add("-xf", installFullOVAName);
+                command.setWorkDir(installFullPath);
+                s_logger.info("Executing command: " + command.toString());
+                result = command.execute();
+                if(result != null) {
+                    String msg = "unable to untar snapshot " + 
snapshotFullOVAName + " to "
+                            + installFullPath;
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                }
+
+            } else {  // there is no ova file, only ovf originally;
+                if(new File(snapshotFullOvfName).exists()) {
+                    command = new Script(false, "cp", _timeout, s_logger);
+                    command.add(snapshotFullOvfName);
+                    //command.add(installFullOvfName);
+                    command.add(installFullPath);
+                    result = command.execute();
+                    if(result != null) {
+                        String msg = "unable to copy snapshot " + 
snapshotFullOvfName + " to " + installFullPath;
+                        s_logger.error(msg);
+                        throw new Exception(msg);
+                    }
+
+                    s_logger.info("vmdkfile parent dir: " + 
snapshotFullVMDKName);
+                    File snapshotdir = new File(snapshotFullVMDKName);
+                    // File snapshotdir = new File(snapshotRoot);
+                    File[] ssfiles = snapshotdir.listFiles();
+                    // List<String> filenames = new ArrayList<String>();
+                    for (int i = 0; i < ssfiles.length; i++) {
+                        String vmdkfile = ssfiles[i].getName();
+                        s_logger.info("vmdk file name: " + vmdkfile);
+                        if(vmdkfile.toLowerCase().startsWith(backupSSUuid) && 
vmdkfile.toLowerCase().endsWith(".vmdk")) {
+                            snapshotFullVMDKName += vmdkfile;
+                            templateVMDKName += vmdkfile;
+                            break;
+                        }
+                    }
+                    if (snapshotFullVMDKName != null) {
+                        command = new Script(false, "cp", _timeout, s_logger);
+                        command.add(snapshotFullVMDKName);
+                        command.add(installFullPath);
+                        result = command.execute();
+                        s_logger.info("Copy VMDK file: " + 
snapshotFullVMDKName);
+                        if(result != null) {
+                            String msg = "unable to copy snapshot vmdk file " 
+ snapshotFullVMDKName + " to " + installFullPath;
+                            s_logger.error(msg);
+                            throw new Exception(msg);
+                        }
+                    }
+                } else {
+                    String msg = "unable to find any snapshot ova/ovf files" + 
snapshotFullOVAName + " to " + installFullPath;
+                    s_logger.error(msg);
+                    throw new Exception(msg);
+                }
+            }
+
+            long physicalSize = new File(installFullPath + "/" + 
templateVMDKName).length();
+            VmdkProcessor processor = new VmdkProcessor();
+            // long physicalSize = new File(installFullPath + "/" + 
templateUniqueName + ".ova").length();
+            Map<String, Object> params = new HashMap<String, Object>();
+            params.put(StorageLayer.InstanceConfigKey, _storage);
+            processor.configure("VMDK Processor", params);
+            long virtualSize = 
processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
+
+            postCreatePrivateTemplate(installFullPath, templateId, 
templateUniqueName, physicalSize, virtualSize);
+            writeMetaOvaForTemplate(installFullPath, backupSSUuid + 
File.separator + backupSSUuid + ".ovf", templateVMDKName, templateUniqueName, 
physicalSize);
+            return new Ternary<String, Long, Long>(installPath + "/" + 
templateUniqueName + ".ova", physicalSize, virtualSize);
+        } catch(Exception e) {
+            // TODO, clean up left over files
+            throw e;
+        }
+    }
+
+    @Override
+    public Answer createTemplateFromSnapshot(CopyCommand cmd) {
+        SnapshotObjectTO snapshot = (SnapshotObjectTO)cmd.getSrcTO();
+        TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+        DataStoreTO imageStore = template.getDataStore();
+        String details;
+        String uniqeName = UUID.randomUUID().toString();
+
+        VmwareContext context = hostService.getServiceContext(cmd);
+        try {
+            if (!(imageStore instanceof  NfsTO)) {
+                return new CopyCmdAnswer("Only support create template from 
snapshot, when the dest store is nfs");
+            }
+
+            NfsTO nfsSvr = (NfsTO)imageStore;
+            Ternary<String, Long, Long> result = 
createTemplateFromSnapshot(template.getPath(),
+                    uniqeName,
+                    nfsSvr.getUrl(), snapshot.getPath(),
+                    template.getId()
+                    );
+
+            TemplateObjectTO newTemplate = new TemplateObjectTO();
+            newTemplate.setPath(result.first());
+            newTemplate.setSize(result.second());
+            newTemplate.setFormat(ImageFormat.OVA);
+            return new CopyCmdAnswer(newTemplate);
+        } catch (Throwable e) {
+            if (e instanceof RemoteException) {
+                hostService.invalidateServiceContext(context);
+            }
+
+            s_logger.error("Unexpecpted exception ", e);
+
+            details = "CreatePrivateTemplateFromSnapshotCommand exception: " + 
e.toString();
+            return new CopyCmdAnswer(details);
+        }
+    }
+
+    private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String 
volumePath,
                String secStorageUrl, String secStorageDir, String exportName,
                String workerVmName) throws Exception {
 
@@ -760,7 +943,7 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
 
                        s_logger.error("Unexpecpted exception ", e);
 
-                       details = "BackupSnapshotCommand exception: " + 
StringUtils.getExceptionStackInfo(e);
+                       details = "BackupSnapshotCommand exception: " + 
e.toString();
                        return new CopyCmdAnswer(details);
                }
        }
@@ -1298,7 +1481,7 @@ public class VmwareStorageProcessor implements 
StorageProcessor {
                        }
 
                        s_logger.error("Unexpecpted exception ", e);
-                       details = "CreateVolumeFromSnapshotCommand exception: " 
+ StringUtils.getExceptionStackInfo(e);
+                       details = "CreateVolumeFromSnapshotCommand exception: " 
+ e.toString();
                }
                return new CopyCmdAnswer(details);
        }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
 
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
index e88d6a5..b7fdcca 100644
--- 
a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
+++ 
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
@@ -1438,7 +1438,12 @@ public class XenServerStorageProcessor implements 
StorageProcessor {
         return new CopyCmdAnswer(details);
     }
 
-       @Override
+    @Override
+    public Answer createTemplateFromSnapshot(CopyCommand cmd) {
+        return null;  //To change body of implemented methods use File | 
Settings | File Templates.
+    }
+
+    @Override
        public Answer createVolumeFromSnapshot(CopyCommand cmd) {
                Connection conn = this.hypervisorResource.getConnection();
                DataTO srcData = cmd.getSrcTO();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java 
b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 2ffd682..ec68529 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -29,6 +29,7 @@ import com.cloud.configuration.Config;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.server.ConfigurationServer;
 import com.cloud.storage.dao.VMTemplateDetailsDao;
+import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.NicProfile;
 import com.cloud.vm.NicVO;
@@ -135,8 +136,8 @@ public abstract class HypervisorGuruBase extends 
AdapterBase implements Hypervis
     }
 
     @Override
-    public long getCommandHostDelegation(long hostId, Command cmd) {
-        return hostId;
+    public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command 
cmd) {
+        return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bfe30cd2/server/src/com/cloud/hypervisor/HypervisorGuruManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruManagerImpl.java 
b/server/src/com/cloud/hypervisor/HypervisorGuruManagerImpl.java
index a8aad57..4d1e1b5 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruManagerImpl.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruManagerImpl.java
@@ -25,6 +25,7 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import com.cloud.utils.Pair;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -59,15 +60,12 @@ public class HypervisorGuruManagerImpl extends ManagerBase 
implements Hypervisor
 
     @Override
     public long getGuruProcessedCommandTargetHost(long hostId, Command cmd) {
-        HostVO hostVo = _hostDao.findById(hostId);
-        HypervisorGuru hvGuru = null;
-        if(hostVo.getType() == Host.Type.Routing) {
-            hvGuru = _hvGurus.get(hostVo.getHypervisorType());
+        for(HypervisorGuru guru : _hvGuruList) {
+            Pair<Boolean, Long> result = guru.getCommandHostDelegation(hostId, 
cmd);
+            if (result.first()) {
+                return result.second();
+            }
         }
-
-        if(hvGuru != null)
-            return hvGuru.getCommandHostDelegation(hostId, cmd);
-
         return hostId;
     }
 }

Reply via email to