You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/12/20 00:06:51 UTC

[08/10] git commit: updated refs/heads/master to 62bb5d8

add xenserver 6.2.0 hotfix support, to optimize vdi copy

add xenserver hot fix

Conflicts:

	api/src/com/cloud/vm/VirtualMachineName.java
	core/src/com/cloud/host/HostInfo.java
	core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
	deps/XenServerJava/src/com/xensource/xenapi/VDI.java
	engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
	engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
	engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
	plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
	plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
	plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
	plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
	server/src/com/cloud/configuration/Config.java


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

Branch: refs/heads/master
Commit: 8caf52c6bc1ea6ff6be17d4ce4da60460fa2663a
Parents: c40d03b
Author: Edison Su <su...@gmail.com>
Authored: Thu Dec 19 14:15:41 2013 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Thu Dec 19 14:15:41 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/vm/VirtualMachineName.java    |  13 +
 core/src/com/cloud/host/HostInfo.java           |   3 +-
 .../cloudstack/storage/command/CopyCommand.java |  12 +
 .../cloudstack/storage/to/SnapshotObjectTO.java |  17 +
 .../src/com/xensource/xenapi/Event.java         |  15 +
 .../src/com/xensource/xenapi/Types.java         |  50 ++
 .../src/com/xensource/xenapi/VDI.java           |  23 +
 .../subsystem/api/storage/EndPointSelector.java |   2 +
 .../orchestration/VolumeOrchestrator.java       |   8 +-
 .../datastore/db/SnapshotDataStoreDao.java      |   2 +
 .../motion/AncientDataMotionStrategy.java       |  16 +-
 .../snapshot/XenserverSnapshotStrategy.java     |  24 +-
 .../endpoint/DefaultEndPointSelector.java       |  49 ++
 .../image/db/SnapshotDataStoreDaoImpl.java      |  32 +
 .../src/com/cloud/hypervisor/XenServerGuru.java |  40 +-
 .../xen/discoverer/XcpServerDiscoverer.java     |  48 +-
 .../xen/resource/CitrixResourceBase.java        | 650 ++-------------
 .../xen/resource/XenServerPoolVms.java          |   5 +
 .../xen/resource/XenServerStorageProcessor.java |   2 +-
 .../xen/resource/Xenserver625Resource.java      | 112 +++
 .../resource/Xenserver625StorageProcessor.java  | 822 +++++++++++++++++++
 .../xenserver/XenServerResourceNewBase.java     | 340 ++++++++
 .../xenserver/xenserver62/cloud-plugin-storage  | 301 +++++++
 .../vm/hypervisor/xenserver/xenserver62/patch   |  74 ++
 server/src/com/cloud/configuration/Config.java  |   7 +
 25 files changed, 2036 insertions(+), 631 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/api/src/com/cloud/vm/VirtualMachineName.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/VirtualMachineName.java b/api/src/com/cloud/vm/VirtualMachineName.java
index c5fc3de..d3b14c7 100755
--- a/api/src/com/cloud/vm/VirtualMachineName.java
+++ b/api/src/com/cloud/vm/VirtualMachineName.java
@@ -26,6 +26,19 @@ import com.cloud.dc.Vlan;
 public class VirtualMachineName {
     public static final String SEPARATOR = "-";
 
+    public static boolean isValidCloudStackVmName(String name, String instance) {
+        String[] parts = name.split(SEPARATOR);
+        if (parts.length <= 1) {
+            return false;
+        }
+
+        if (!parts[parts.length - 1].equals(instance)) {
+            return false;
+        }
+
+        return true;
+    }
+    
     public static String getVnetName(long vnetId) {
         StringBuilder vnet = new StringBuilder();
         Formatter formatter = new Formatter(vnet);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/core/src/com/cloud/host/HostInfo.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/host/HostInfo.java b/core/src/com/cloud/host/HostInfo.java
index 89fb806..4a95aa8 100644
--- a/core/src/com/cloud/host/HostInfo.java
+++ b/core/src/com/cloud/host/HostInfo.java
@@ -21,5 +21,6 @@ public final class HostInfo {
     public static final String HOST_OS = "Host.OS"; //Fedora, XenServer, Ubuntu, etc
     public static final String HOST_OS_VERSION = "Host.OS.Version"; //12, 5.5, 9.10, etc
     public static final String HOST_OS_KERNEL_VERSION = "Host.OS.Kernel.Version"; //linux-2.6.31 etc
-
+    public static final String XS620_SNAPSHOT_HOTFIX = "xs620_snapshot_hotfix";
 }
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/core/src/org/apache/cloudstack/storage/command/CopyCommand.java
----------------------------------------------------------------------
diff --git a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java
index 7fcde1e..446c61f 100644
--- a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java
+++ b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java
@@ -16,6 +16,9 @@
 // under the License.
 package org.apache.cloudstack.storage.command;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.to.DataTO;
 
@@ -24,6 +27,7 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
     private DataTO destTO;
     private DataTO cacheTO;
     boolean executeInSequence = false;
+    Map<String, String> options = new HashMap<String, String>();
 
     public CopyCommand(DataTO srcData, DataTO destData, int timeout, boolean executeInSequence) {
         super();
@@ -66,4 +70,12 @@ public final class CopyCommand extends Command implements StorageSubSystemComman
         return this.getWait() * 1000;
     }
 
+    public void setOptions(Map<String, String> options) {
+        this.options = options;
+    }
+
+    public Map<String, String> getOptions() {
+        return options;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
----------------------------------------------------------------------
diff --git a/core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
index 03b4609..51ecc5b 100644
--- a/core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
+++ b/core/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
@@ -16,8 +16,11 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import java.util.ArrayList;
+
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.commons.lang.ArrayUtils;
 
 import com.cloud.agent.api.to.DataObjectType;
 import com.cloud.agent.api.to.DataStoreTO;
@@ -34,6 +37,8 @@ public class SnapshotObjectTO implements DataTO {
     private HypervisorType hypervisorType;
     private long id;
     private boolean quiescevm;
+    private String[] parents;
+
 
     public SnapshotObjectTO() {
 
@@ -49,9 +54,17 @@ public class SnapshotObjectTO implements DataTO {
         }
 
         SnapshotInfo parentSnapshot = snapshot.getParent();
+        ArrayList<String> parentsArry = new ArrayList<String>();
         if (parentSnapshot != null) {
             this.parentSnapshotPath = parentSnapshot.getPath();
+            while(parentSnapshot != null) {
+                parentsArry.add(parentSnapshot.getPath());
+                parentSnapshot = parentSnapshot.getParent();
+            }
+            parents =  parentsArry.toArray(new String[parentsArry.size()]);
+            ArrayUtils.reverse(parents);
         }
+
         this.dataStore = snapshot.getDataStore().getTO();
         this.setName(snapshot.getName());
         this.hypervisorType = snapshot.getHypervisorType();
@@ -139,6 +152,10 @@ public class SnapshotObjectTO implements DataTO {
         this.quiescevm = quiescevm;
     }
 
+    public String[] getParents() {
+        return parents;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder("SnapshotTO[datastore=").append(dataStore).append("|volume=").append(volume).append("|path").append(path).append("]").toString();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/deps/XenServerJava/src/com/xensource/xenapi/Event.java
----------------------------------------------------------------------
diff --git a/deps/XenServerJava/src/com/xensource/xenapi/Event.java b/deps/XenServerJava/src/com/xensource/xenapi/Event.java
index 68594fb..ec43814 100644
--- a/deps/XenServerJava/src/com/xensource/xenapi/Event.java
+++ b/deps/XenServerJava/src/com/xensource/xenapi/Event.java
@@ -300,4 +300,19 @@ public class Event extends XenAPIObject {
         return Types.toString(result);
     }
 
+    public static Map properFrom(Connection c, Set<String> classes, String token, Double timeout) throws BadServerResponse, XenAPIException, XmlRpcException,
+            Types.SessionNotRegistered,
+            Types.EventsLost {
+        String method_call = "event.from";
+        String session = c.getSessionReference();
+        Object[] method_params = {Marshalling.toXMLRPC(session), Marshalling.toXMLRPC(classes), Marshalling.toXMLRPC(token), Marshalling.toXMLRPC(timeout)};
+        Map response = c.dispatch(method_call, method_params);
+        Object result = response.get("Value");
+        Map value = (Map)result;
+        Map<String, Object> from = new HashMap<String, Object>();
+        from.put("token", value.get("token"));
+        from.put("events", Types.toSetOfEventRecord(value.get("events")));
+        return from;
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/deps/XenServerJava/src/com/xensource/xenapi/Types.java
----------------------------------------------------------------------
diff --git a/deps/XenServerJava/src/com/xensource/xenapi/Types.java b/deps/XenServerJava/src/com/xensource/xenapi/Types.java
index c6451ff..777d580 100644
--- a/deps/XenServerJava/src/com/xensource/xenapi/Types.java
+++ b/deps/XenServerJava/src/com/xensource/xenapi/Types.java
@@ -1279,6 +1279,17 @@ public class Types
                 String p1 = ErrorDescription.length > 1 ? ErrorDescription[1] : "";
                 throw new Types.CrlNameInvalid(p1);
             }
+            if (ErrorDescription[0].equals("VDI_NOT_SPARSE"))
+            {
+                String p1 = ErrorDescription.length > 1 ? ErrorDescription[1] : "";
+                throw new Types.VdiNotSparse(p1);
+            }
+            if (ErrorDescription[0].equals("VDI_TOO_SMALL"))
+            {
+                String p1 = ErrorDescription.length > 1 ? ErrorDescription[1] : "";
+                String p2 = ErrorDescription.length > 2 ? ErrorDescription[2] : "";
+                throw new Types.VdiTooSmall(p1, p2);
+            }
             if (ErrorDescription[0].equals("HOST_POWER_ON_MODE_DISABLED"))
             {
                 throw new Types.HostPowerOnModeDisabled();
@@ -7823,6 +7834,45 @@ public class Types
     }
 
     /**
+     * The VDI is too small. Please resize it to at least the minimum size.
+     */
+    public static class VdiTooSmall extends XenAPIException {
+        public final String vdi;
+        public final String minimumSize;
+
+        /**
+         * Create a new VdiTooSmall
+         *
+         * @param vdi
+         * @param minimumSize
+         */
+        public VdiTooSmall(String vdi, String minimumSize) {
+            super("The VDI is too small. Please resize it to at least the minimum size.");
+            this.vdi = vdi;
+            this.minimumSize = minimumSize;
+        }
+
+    }
+
+    /**
+     * The VDI is not stored using a sparse format. It is not possible to query and manipulate only the changed blocks (or 'block differences' or 'disk deltas') between two VDIs. Please select a VDI which uses a sparse-aware technology such as VHD.
+     */
+    public static class VdiNotSparse extends XenAPIException {
+        public final String vdi;
+
+        /**
+         * Create a new VdiNotSparse
+         *
+         * @param vdi
+         */
+        public VdiNotSparse(String vdi) {
+            super("The VDI is not stored using a sparse format. It is not possible to query and manipulate only the changed blocks (or 'block differences' or 'disk deltas') between two VDIs. Please select a VDI which uses a sparse-aware technology such as VHD.");
+            this.vdi = vdi;
+        }
+
+    }
+
+    /**
      * The hosts in this pool are not homogeneous.
      */
     public static class HostsNotHomogeneous extends XenAPIException {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/deps/XenServerJava/src/com/xensource/xenapi/VDI.java
----------------------------------------------------------------------
diff --git a/deps/XenServerJava/src/com/xensource/xenapi/VDI.java b/deps/XenServerJava/src/com/xensource/xenapi/VDI.java
index 2c32c84..992a6a6 100644
--- a/deps/XenServerJava/src/com/xensource/xenapi/VDI.java
+++ b/deps/XenServerJava/src/com/xensource/xenapi/VDI.java
@@ -1609,6 +1609,29 @@ public class VDI extends XenAPIObject {
     }
 
     /**
+     * Copy either a full VDI or the block differences between two VDIs into either a fresh VDI or an existing VDI.
+     *
+     * @param sr The destination SR (only required if the destination VDI is not specified
+     * @param baseVdi The base VDI (only required if copying only changed blocks, by default all blocks will be copied)
+     * @param intoVdi The destination VDI to copy blocks into (if omitted then a destination SR must be provided and a fresh VDI will be created)
+     * @return Task
+     */
+    public Task copyAsync2(Connection c, SR sr, VDI baseVdi, VDI intoVdi) throws
+        BadServerResponse,
+        XenAPIException,
+        XmlRpcException,
+        Types.VdiReadonly,
+        Types.VdiTooSmall,
+        Types.VdiNotSparse {
+        String method_call = "Async.VDI.copy";
+        String session = c.getSessionReference();
+        Object[] method_params = {Marshalling.toXMLRPC(session), Marshalling.toXMLRPC(this.ref), Marshalling.toXMLRPC(sr), Marshalling.toXMLRPC(baseVdi), Marshalling.toXMLRPC(intoVdi)};
+        Map response = c.dispatch(method_call, method_params);
+        Object result = response.get("Value");
+        return Types.toTask(result);
+    }
+
+    /**
      * Make a fresh VDI in the specified SR and copy the supplied VDI's data to the new disk
      *
      * @param sr The destination SR

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
index b812f6e..8f5921d 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
@@ -30,4 +30,6 @@ public interface EndPointSelector {
     List<EndPoint> selectAll(DataStore store);
 
     EndPoint select(Scope scope, Long storeId);
+
+    EndPoint selectHypervisorHost(Scope scope);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
index 4243646..578a785 100644
--- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java
@@ -397,10 +397,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
         ServiceOffering offering, DiskOffering diskOffering, List<StoragePool> avoids, long size, HypervisorType hyperType) {
         StoragePool pool = null;
 
-        if (diskOffering != null && diskOffering.isCustomized()) {
-            diskOffering.setDiskSize(size);
-        }
-
         DiskProfile dskCh = null;
         if (volume.getVolumeType() == Type.ROOT && Storage.ImageFormat.ISO != template.getFormat()) {
             dskCh = createDiskCharacteristics(volume, template, dc, offering);
@@ -408,6 +404,10 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
             dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
         }
 
+        if (diskOffering != null && diskOffering.isCustomized()) {
+            dskCh.setSize(size);
+        }
+
         dskCh.setHyperType(hyperType);
 
         final HashSet<StoragePool> avoidPools = new HashSet<StoragePool>(avoids);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
index 67ce558..83c337d 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java
@@ -52,4 +52,6 @@ public interface SnapshotDataStoreDao extends GenericDao<SnapshotDataStoreVO, Lo
     List<SnapshotDataStoreVO> listOnCache(long snapshotId);
 
     void updateStoreRoleToCache(long storeId);
+
+    SnapshotDataStoreVO findLatestSnapshotForVolume(Long volumeId, DataStoreRole role);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 48c39cd..3809722 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -18,13 +18,11 @@
  */
 package org.apache.cloudstack.storage.motion;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.inject.Inject;
 
-import org.apache.log4j.Logger;
-import org.springframework.stereotype.Component;
-
 import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
@@ -46,6 +44,8 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.cloudstack.storage.command.CopyCommand;
 import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.storage.MigrateVolumeAnswer;
@@ -470,6 +470,14 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
         int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue()));
 
         DataObject cacheData = null;
+        SnapshotInfo snapshotInfo = (SnapshotInfo)srcData;
+        Object payload = snapshotInfo.getPayload();
+        Boolean fullSnapshot = true;
+        if (payload != null) {
+            fullSnapshot = (Boolean)payload;
+        }
+        Map<String, String> options = new HashMap<String, String>();
+        options.put("fullSnapshot", fullSnapshot.toString());
         Answer answer = null;
         try {
             if (needCacheStorage(srcData, destData)) {
@@ -478,6 +486,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
 
                 CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait, VirtualMachineManager.ExecuteInSequence.value());
                 cmd.setCacheTO(cacheData.getTO());
+                cmd.setOptions(options);
                 EndPoint ep = selector.select(srcData, destData);
                 if (ep == null) {
                     String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
@@ -488,6 +497,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
                 }
             } else {
                 CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _backupsnapshotwait, VirtualMachineManager.ExecuteInSequence.value());
+                cmd.setOptions(options);
                 EndPoint ep = selector.select(srcData, destData);
                 if (ep == null) {
                     String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
index 14fb618..bcae7b5 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/XenserverSnapshotStrategy.java
@@ -22,7 +22,6 @@ import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
-
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
@@ -104,29 +103,30 @@ public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
 
         // determine full snapshot backup or not
 
-        boolean fullBackup = false;
 
-        if (parentSnapshot != null) {
-            int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
+        boolean fullBackup = true;
+        SnapshotDataStoreVO parentSnapshotOnBackupStore = snapshotStoreDao.findLatestSnapshotForVolume(snapshot.getVolumeId(), DataStoreRole.Image);
+        if (parentSnapshotOnBackupStore != null) {
+            int _deltaSnapshotMax = NumbersUtil.parseInt(configDao.getValue("snapshot.delta.max"),
+                    SnapshotManager.DELTAMAX);
             int deltaSnap = _deltaSnapshotMax;
-
             int i;
-            SnapshotDataStoreVO parentSnapshotOnBackupStore = null;
+
             for (i = 1; i < deltaSnap; i++) {
-                parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(parentSnapshot.getId(), DataStoreRole.Image);
-                if (parentSnapshotOnBackupStore == null) {
-                    break;
-                }
                 Long prevBackupId = parentSnapshotOnBackupStore.getParentSnapshotId();
-
                 if (prevBackupId == 0) {
                     break;
                 }
-
                 parentSnapshotOnBackupStore = snapshotStoreDao.findBySnapshot(prevBackupId, DataStoreRole.Image);
+                if (parentSnapshotOnBackupStore == null) {
+                    break;
+                }
             }
+
             if (i >= deltaSnap) {
                 fullBackup = true;
+            } else {
+                fullBackup = false;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
index 6560d2f..9f23940 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
@@ -27,6 +27,7 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import com.cloud.utils.db.Transaction;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
@@ -60,6 +61,7 @@ public class DefaultEndPointSelector implements EndPointSelector {
     private final String findOneHostOnPrimaryStorage =
         "select h.id from host h, storage_pool_host_ref s  where h.status = 'Up' and h.type = 'Routing' and h.resource_state = 'Enabled' and"
             + " h.id = s.host_id and s.pool_id = ? ";
+    private String findOneHypervisorHostInScope = "select h.id from host h where h.status = 'Up' and h.hypervisor_type is not null ";
 
     protected boolean moveBetweenPrimaryImage(DataStore srcStore, DataStore destStore) {
         DataStoreRole srcRole = srcStore.getRole();
@@ -292,4 +294,51 @@ public class DefaultEndPointSelector implements EndPointSelector {
         }
         return endPoints;
     }
+
+    @Override
+    public EndPoint selectHypervisorHost(Scope scope) {
+        StringBuilder sbuilder = new StringBuilder();
+        sbuilder.append(findOneHypervisorHostInScope);
+        if (scope.getScopeType() == ScopeType.ZONE) {
+            sbuilder.append(" and h.data_center_id = ");
+            sbuilder.append(scope.getScopeId());
+        } else if (scope.getScopeType() == ScopeType.CLUSTER) {
+            sbuilder.append(" and h.cluster_id = ");
+            sbuilder.append(scope.getScopeId());
+        }
+        sbuilder.append(" ORDER by rand() limit 1");
+
+        String sql = sbuilder.toString();
+        PreparedStatement pstmt = null;
+        ResultSet rs = null;
+        HostVO host = null;
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+
+        try {
+            pstmt = txn.prepareStatement(sql);
+            rs = pstmt.executeQuery();
+            while (rs.next()) {
+                long id = rs.getLong(1);
+                host = hostDao.findById(id);
+            }
+        } catch (SQLException e) {
+            s_logger.warn("can't find endpoint", e);
+        } finally {
+            try {
+                if (rs != null) {
+                    rs.close();
+                }
+                if (pstmt != null) {
+                    pstmt.close();
+                }
+            } catch (SQLException e) {
+            }
+        }
+
+        if (host == null) {
+            return null;
+        }
+
+        return RemoteHostEndPoint.getHypervisorHostEndPoint(host);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
index e40cfd0..519d3db 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java
@@ -54,8 +54,13 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
     private SearchBuilder<SnapshotDataStoreVO> snapshotSearch;
     private SearchBuilder<SnapshotDataStoreVO> storeSnapshotSearch;
     private SearchBuilder<SnapshotDataStoreVO> snapshotIdSearch;
+
     private final String parentSearch = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where store_id = ? "
         + " and store_role = ? and volume_id = ? and state = 'Ready'" + " order by created DESC " + " limit 1";
+    private final String findLatestSnapshot = "select store_id, store_role, snapshot_id from cloud.snapshot_store_ref where " +
+            " store_role = ? and volume_id = ? and state = 'Ready'" +
+            " order by created DESC " +
+            " limit 1";
 
     @Override
     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
@@ -204,6 +209,33 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
     }
 
     @Override
+    public SnapshotDataStoreVO findLatestSnapshotForVolume(Long volumeId, DataStoreRole role) {
+        TransactionLegacy txn = TransactionLegacy.currentTxn();
+        PreparedStatement pstmt = null;
+        ResultSet rs = null;
+        try {
+            pstmt = txn.prepareStatement(findLatestSnapshot);
+            pstmt.setString(1, role.toString());
+            pstmt.setLong(2, volumeId);
+            rs = pstmt.executeQuery();
+            while (rs.next()) {
+                long sid = rs.getLong(1);
+                long snid = rs.getLong(3);
+                return findByStoreSnapshot(role, sid, snid);
+            }
+        } catch (SQLException e) {
+            s_logger.debug("Failed to find parent snapshot: " + e.toString());
+        } finally {
+            try {
+                if (pstmt != null)
+                    pstmt.close();
+            } catch (SQLException e) {
+            }
+        }
+        return null;
+    }
+
+    @Override
     @DB
     public SnapshotDataStoreVO findParent(DataStoreRole role, Long storeId, Long volumeId) {
         TransactionLegacy txn = TransactionLegacy.currentTxn();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
index bd10cb0..89a727b 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/XenServerGuru.java
@@ -19,17 +19,30 @@ package com.cloud.hypervisor;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
-import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.*;
+import com.cloud.host.HostInfo;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.GuestOSVO;
 import com.cloud.storage.dao.GuestOSDao;
 import com.cloud.template.VirtualMachineTemplate.BootloaderType;
+import com.cloud.utils.Pair;
 import com.cloud.vm.VirtualMachineProfile;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.storage.command.CopyCommand;
 
 @Local(value = HypervisorGuru.class)
 public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru {
     @Inject
     GuestOSDao _guestOsDao;
+    @Inject
+    EndPointSelector endPointSelector;
+    @Inject
+    HostDao hostDao;
 
     protected XenServerGuru() {
         super();
@@ -60,4 +73,29 @@ public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru
     public boolean trackVmHostChange() {
         return true;
     }
+
+    @Override
+    public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
+        if (cmd instanceof CopyCommand) {
+            CopyCommand cpyCommand = (CopyCommand)cmd;
+            DataTO srcData = cpyCommand.getSrcTO();
+            DataTO destData = cpyCommand.getDestTO();
+
+            if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) {
+                DataStoreTO srcStore = srcData.getDataStore();
+                DataStoreTO destStore = destData.getDataStore();
+                if (srcStore instanceof NfsTO && destStore instanceof NfsTO) {
+                    HostVO host = hostDao.findById(hostId);
+                    EndPoint ep = endPointSelector.selectHypervisorHost(new ZoneScope(host.getDataCenterId()));
+                    host = hostDao.findById(ep.getId());
+                    hostDao.loadDetails(host);
+                    boolean snapshotHotFix = Boolean.parseBoolean(host.getDetail(HostInfo.XS620_SNAPSHOT_HOTFIX));
+                    if (snapshotHotFix) {
+                        return new Pair<Boolean, Long>(Boolean.TRUE, new Long(ep.getId()));
+                    }
+                }
+            }
+        }
+        return new Pair<Boolean, Long>(Boolean.FALSE, new Long(hostId));
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
index ecdb821..cd1b30b 100755
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
@@ -34,13 +34,6 @@ import javax.persistence.EntityExistsException;
 import org.apache.log4j.Logger;
 import org.apache.xmlrpc.XmlRpcException;
 
-import com.xensource.xenapi.Connection;
-import com.xensource.xenapi.Host;
-import com.xensource.xenapi.Pool;
-import com.xensource.xenapi.Session;
-import com.xensource.xenapi.Types.SessionAuthenticationFailed;
-import com.xensource.xenapi.Types.XenAPIException;
-
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.Listener;
 import com.cloud.agent.api.AgentControlAnswer;
@@ -82,6 +75,7 @@ import com.cloud.hypervisor.xen.resource.XenServer602Resource;
 import com.cloud.hypervisor.xen.resource.XenServer610Resource;
 import com.cloud.hypervisor.xen.resource.XenServer620Resource;
 import com.cloud.hypervisor.xen.resource.XenServerConnectionPool;
+import com.cloud.hypervisor.xen.resource.Xenserver625Resource;
 import com.cloud.resource.Discoverer;
 import com.cloud.resource.DiscovererBase;
 import com.cloud.resource.ResourceManager;
@@ -98,6 +92,12 @@ import com.cloud.utils.db.QueryBuilder;
 import com.cloud.utils.db.SearchCriteria.Op;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.exception.HypervisorVersionChangedException;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.Host;
+import com.xensource.xenapi.Pool;
+import com.xensource.xenapi.Session;
+import com.xensource.xenapi.Types.SessionAuthenticationFailed;
+import com.xensource.xenapi.Types.XenAPIException;
 
 @Local(value = Discoverer.class)
 public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, Listener, ResourceStateAdapter {
@@ -112,6 +112,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
     protected String _guestNic;
     protected boolean _setupMultipath;
     protected String _instance;
+    private String xs620snapshothotfix = "Xenserver-Vdi-Copy-HotFix";
 
     @Inject
     protected AlertManager _alertMgr;
@@ -149,6 +150,11 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
         }
     }
 
+    protected boolean xenserverHotFixEnabled() {
+        //temporary fix, we should call xenserver api to get the hot fix is enabled or not.
+        return Boolean.parseBoolean(_configDao.getValue(Config.XenServerHotFix.name()));
+    }
+
     @Override
     public Map<? extends ServerResource, Map<String, String>>
         find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags) throws DiscoveryException {
@@ -274,6 +280,8 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
                     hostOS = record.softwareVersion.get("platform_name");
                 }
 
+                //Boolean xs620hotfix = record.tags.contains(xs620snapshothotfix);
+                Boolean xs620hotfix = xenserverHotFixEnabled();
                 String hostOSVer = prodVersion;
                 String hostKernelVer = record.softwareVersion.get("linux");
 
@@ -303,6 +311,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
                 details.put(HostInfo.HOST_OS_VERSION, hostOSVer);
                 details.put(HostInfo.HOST_OS_KERNEL_VERSION, hostKernelVer);
                 details.put(HostInfo.HYPERVISOR_VERSION, xenVersion);
+                details.put(HostInfo.XS620_SNAPSHOT_HOTFIX, xs620hotfix.toString());
 
                 String privateNetworkLabel = _networkMgr.getDefaultManagementTrafficLabel(dcId, HypervisorType.XenServer);
                 String storageNetworkLabel = _networkMgr.getDefaultStorageTrafficLabel(dcId, HypervisorType.XenServer);
@@ -452,9 +461,21 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
             return new XenServer602Resource();
         else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0"))
             return new XenServer610Resource();
-        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0"))
-            return new XenServer620Resource();
-        else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) {
+        else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) {
+            /*
+            Set<String> tags =record.tags;
+            if (tags.contains(xs620snapshothotfix)) {
+                return new Xenserver625Resource();
+            } else {
+                return new XenServer620Resource();
+            }*/
+            boolean hotfix = xenserverHotFixEnabled();
+            if (hotfix) {
+                return new Xenserver625Resource();
+            } else {
+                return new XenServer620Resource();
+            }
+        } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) {
             String prodVersionTextShort = record.softwareVersion.get("product_version_text_short").trim();
             if ("5.6 SP2".equals(prodVersionTextShort)) {
                 return new XenServer56SP2Resource();
@@ -607,7 +628,12 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L
         } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.1.0")) {
             resource = XenServer610Resource.class.getName();
         } else if (prodBrand.equals("XenServer") && prodVersion.equals("6.2.0")) {
-            resource = XenServer620Resource.class.getName();
+            String hotfix = details.get("Xenserer620HotFix");
+            if (hotfix != null && hotfix.equalsIgnoreCase("Xenserver-Vdi-Copy-HotFix")) {
+                resource = Xenserver625Resource.class.getName();
+            } else {
+                resource = XenServer620Resource.class.getName();
+            }
         } else if (prodBrand.equals("XenServer") && prodVersion.equals("5.6.100")) {
             String prodVersionTextShort = details.get("product_version_text_short").trim();
             if ("5.6 SP2".equals(prodVersionTextShort)) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index f38bb3c..fdbeefd 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -49,6 +49,9 @@ import javax.ejb.Local;
 import javax.naming.ConfigurationException;
 import javax.xml.parsers.DocumentBuilderFactory;
 
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.log4j.Logger;
 import org.apache.xmlrpc.XmlRpcException;
@@ -102,8 +105,6 @@ import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.AttachIsoCommand;
 import com.cloud.agent.api.AttachVolumeAnswer;
 import com.cloud.agent.api.AttachVolumeCommand;
-import com.cloud.agent.api.BackupSnapshotAnswer;
-import com.cloud.agent.api.BackupSnapshotCommand;
 import com.cloud.agent.api.BumpUpPriorityCommand;
 import com.cloud.agent.api.CheckHealthAnswer;
 import com.cloud.agent.api.CheckHealthCommand;
@@ -121,13 +122,9 @@ import com.cloud.agent.api.CleanupNetworkRulesCmd;
 import com.cloud.agent.api.ClusterSyncAnswer;
 import com.cloud.agent.api.ClusterSyncCommand;
 import com.cloud.agent.api.Command;
-import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
-import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
 import com.cloud.agent.api.CreateStoragePoolCommand;
 import com.cloud.agent.api.CreateVMSnapshotAnswer;
 import com.cloud.agent.api.CreateVMSnapshotCommand;
-import com.cloud.agent.api.CreateVolumeFromSnapshotAnswer;
-import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
 import com.cloud.agent.api.DeleteStoragePoolCommand;
 import com.cloud.agent.api.DeleteVMSnapshotAnswer;
 import com.cloud.agent.api.DeleteVMSnapshotCommand;
@@ -147,8 +144,6 @@ import com.cloud.agent.api.HostStatsEntry;
 import com.cloud.agent.api.HostVmStateReportEntry;
 import com.cloud.agent.api.MaintainAnswer;
 import com.cloud.agent.api.MaintainCommand;
-import com.cloud.agent.api.ManageSnapshotAnswer;
-import com.cloud.agent.api.ManageSnapshotCommand;
 import com.cloud.agent.api.MigrateAnswer;
 import com.cloud.agent.api.MigrateCommand;
 import com.cloud.agent.api.ModifySshKeysCommand;
@@ -247,7 +242,6 @@ import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CopyVolumeCommand;
 import com.cloud.agent.api.storage.CreateAnswer;
 import com.cloud.agent.api.storage.CreateCommand;
-import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
 import com.cloud.agent.api.storage.DestroyCommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@@ -262,10 +256,8 @@ import com.cloud.agent.api.to.IpAddressTO;
 import com.cloud.agent.api.to.NfsTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.PortForwardingRuleTO;
-import com.cloud.agent.api.to.S3TO;
 import com.cloud.agent.api.to.StaticNatRuleTO;
 import com.cloud.agent.api.to.StorageFilerTO;
-import com.cloud.agent.api.to.SwiftTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.exception.InternalErrorException;
@@ -282,7 +274,6 @@ import com.cloud.network.rules.FirewallRule;
 import com.cloud.resource.ServerResource;
 import com.cloud.resource.hypervisor.HypervisorResource;
 import com.cloud.storage.Storage;
-import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.StoragePoolType;
 import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
@@ -303,6 +294,41 @@ import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.PowerState;
 import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.snapshot.VMSnapshot;
+import com.google.gson.Gson;
+import com.trilead.ssh2.SCPClient;
+import com.xensource.xenapi.Bond;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.Console;
+import com.xensource.xenapi.Host;
+import com.xensource.xenapi.HostCpu;
+import com.xensource.xenapi.HostMetrics;
+import com.xensource.xenapi.Network;
+import com.xensource.xenapi.PBD;
+import com.xensource.xenapi.PIF;
+import com.xensource.xenapi.PIF.Record;
+import com.xensource.xenapi.Pool;
+import com.xensource.xenapi.SR;
+import com.xensource.xenapi.Session;
+import com.xensource.xenapi.Task;
+import com.xensource.xenapi.Types;
+import com.xensource.xenapi.Types.BadAsyncResult;
+import com.xensource.xenapi.Types.BadServerResponse;
+import com.xensource.xenapi.Types.ConsoleProtocol;
+import com.xensource.xenapi.Types.IpConfigurationMode;
+import com.xensource.xenapi.Types.OperationNotAllowed;
+import com.xensource.xenapi.Types.SrFull;
+import com.xensource.xenapi.Types.VbdType;
+import com.xensource.xenapi.Types.VmBadPowerState;
+import com.xensource.xenapi.Types.VmPowerState;
+import com.xensource.xenapi.Types.XenAPIException;
+import com.xensource.xenapi.VBD;
+import com.xensource.xenapi.VBDMetrics;
+import com.xensource.xenapi.VDI;
+import com.xensource.xenapi.VIF;
+import com.xensource.xenapi.VLAN;
+import com.xensource.xenapi.VM;
+import com.xensource.xenapi.VMGuestMetrics;
+import com.xensource.xenapi.XenAPIObject;
 
 /**
  * CitrixResourceBase encapsulates the calls to the XenServer Xapi process
@@ -537,25 +563,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         } else if (clazz == ModifyStoragePoolCommand.class) {
             return execute((ModifyStoragePoolCommand)cmd);
         } else if (clazz == DeleteStoragePoolCommand.class) {
-            return execute((DeleteStoragePoolCommand)cmd);
-        } else if (clazz == CopyVolumeCommand.class) {
-            return execute((CopyVolumeCommand)cmd);
-        } else if (clazz == ResizeVolumeCommand.class) {
-            return execute((ResizeVolumeCommand)cmd);
+            return execute((DeleteStoragePoolCommand) cmd);
+        }else if (clazz == ResizeVolumeCommand.class) {
+            return execute((ResizeVolumeCommand) cmd);
         } else if (clazz == AttachVolumeCommand.class) {
             return execute((AttachVolumeCommand)cmd);
         } else if (clazz == AttachIsoCommand.class) {
-            return execute((AttachIsoCommand)cmd);
-        } else if (clazz == ManageSnapshotCommand.class) {
-            return execute((ManageSnapshotCommand)cmd);
-        } else if (clazz == BackupSnapshotCommand.class) {
-            return execute((BackupSnapshotCommand)cmd);
-        } else if (clazz == CreateVolumeFromSnapshotCommand.class) {
-            return execute((CreateVolumeFromSnapshotCommand)cmd);
-        } else if (clazz == CreatePrivateTemplateFromVolumeCommand.class) {
-            return execute((CreatePrivateTemplateFromVolumeCommand)cmd);
-        } else if (clazz == CreatePrivateTemplateFromSnapshotCommand.class) {
-            return execute((CreatePrivateTemplateFromSnapshotCommand)cmd);
+            return execute((AttachIsoCommand) cmd);
         } else if (clazz == UpgradeSnapshotCommand.class) {
             return execute((UpgradeSnapshotCommand)cmd);
         } else if (clazz == GetStorageStatsCommand.class) {
@@ -1482,6 +1496,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return vm;
     }
 
+
     protected void finalizeVmMetaData(VM vm, Connection conn, VirtualMachineTO vmSpec) throws Exception {
 
         Map<String, String> details = vmSpec.getDetails();
@@ -3607,13 +3622,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         throw new CloudRuntimeException("Com'on no control domain?  What the crap?!#@!##$@");
     }
 
+    protected void umountSnapshotDir(Connection conn, Long dcId) {
+        try {
+            callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString());
+        } catch (Exception e) {
+            s_logger.debug("Failed to umount snapshot dir",e);
+        }
+    }
+
     protected ReadyAnswer execute(ReadyCommand cmd) {
         Connection conn = getConnection();
         Long dcId = cmd.getDataCenterId();
         // Ignore the result of the callHostPlugin. Even if unmounting the
         // snapshots dir fails, let Ready command
         // succeed.
-        callHostPlugin(conn, "vmopsSnapshot", "unmountSnapshotsDir", "dcId", dcId.toString());
+        umountSnapshotDir(conn, dcId);
 
         setupLinkLocalNetwork(conn);
         // try to destroy CD-ROM device for all system VMs on this host
@@ -4019,109 +4042,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    boolean swiftDownload(Connection conn, SwiftTO swift, String container, String rfilename, String dir, String lfilename, Boolean remote) {
-        String result = null;
-        try {
-            result =
-                callHostPluginAsync(conn, "swiftxen", "swift", 60 * 60, "op", "download", "url", swift.getUrl(), "account", swift.getAccount(), "username",
-                    swift.getUserName(), "key", swift.getKey(), "rfilename", rfilename, "dir", dir, "lfilename", lfilename, "remote", remote.toString());
-            if (result != null && result.equals("true")) {
-                return true;
-            }
-        } catch (Exception e) {
-            s_logger.warn("swift download failed due to ", e);
-        }
-        return false;
-    }
-
-    boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) {
-        String result = null;
-        try {
-            result =
-                callHostPluginAsync(conn, "swiftxen", "swift", wait, "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(), "username",
-                    swift.getUserName(), "key", swift.getKey(), "container", container, "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString());
-            if (result != null && result.equals("true")) {
-                return true;
-            }
-        } catch (Exception e) {
-            s_logger.warn("swift upload failed due to " + e.toString(), e);
-        }
-        return false;
-    }
-
-    boolean swiftDelete(Connection conn, SwiftTO swift, String rfilename) {
-        String result = null;
-        try {
-            result =
-                callHostPlugin(conn, "swiftxen", "swift", "op", "delete", "url", swift.getUrl(), "account", swift.getAccount(), "username", swift.getUserName(), "key",
-                    swift.getKey(), "rfilename", rfilename);
-            if (result != null && result.equals("true")) {
-                return true;
-            }
-        } catch (Exception e) {
-            s_logger.warn("swift download failed due to ", e);
-        }
-        return false;
-    }
-
-    public String swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) {
-        String lfilename;
-        String ldir;
-        if (isISCSI) {
-            ldir = "/dev/VG_XenStorage-" + srUuid;
-            lfilename = "VHD-" + snapshotUuid;
-        } else {
-            ldir = "/var/run/sr-mount/" + srUuid;
-            lfilename = snapshotUuid + ".vhd";
-        }
-        swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait);
-        return lfilename;
-    }
-
-    protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath,
-        String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait, Long secHostId) {
-        String backupSnapshotUuid = null;
-
-        if (prevBackupUuid == null) {
-            prevBackupUuid = "";
-        }
-
-        // Each argument is put in a separate line for readability.
-        // Using more lines does not harm the environment.
-        String backupUuid = UUID.randomUUID().toString();
-        String results =
-            callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait, "primaryStorageSRUuid", primaryStorageSRUuid, "dcId", dcId.toString(), "accountId",
-                accountId.toString(), "volumeId", volumeId.toString(), "secondaryStorageMountPath", secondaryStorageMountPath, "snapshotUuid", snapshotUuid,
-                "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString(), "secHostId", secHostId.toString());
-        String errMsg = null;
-        if (results == null || results.isEmpty()) {
-            errMsg =
-                "Could not copy backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId + " from primary storage " + primaryStorageSRUuid +
-                    " to secondary storage " + secondaryStorageMountPath + " due to null";
-        } else {
-
-            String[] tmp = results.split("#");
-            String status = tmp[0];
-            backupSnapshotUuid = tmp[1];
-            // status == "1" if and only if backupSnapshotUuid != null
-            // So we don't rely on status value but return backupSnapshotUuid as an
-            // indicator of success.
-            if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) {
-                s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId + " to secondary storage");
-                return backupSnapshotUuid;
-            } else {
-                errMsg =
-                    "Could not copy backupUuid: " + backupSnapshotUuid + " of volumeId: " + volumeId + " from primary storage " + primaryStorageSRUuid +
-                        " to secondary storage " + secondaryStorageMountPath + " due to " + tmp[1];
-            }
-        }
-        String source = backupUuid + ".vhd";
-        killCopyProcess(conn, source);
-        s_logger.warn(errMsg);
-        return null;
-
-    }
-
     protected String callHostPluginAsync(Connection conn, String plugin, String cmd, int wait, String... params) {
         int timeout = wait * 1000;
         Map<String, String> args = new HashMap<String, String>();
@@ -6273,14 +6193,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    void destroyVDI(Connection conn, VDI vdi) {
-        try {
-            vdi.destroy(conn);
-        } catch (Exception e) {
-            String msg = "destroy VDI failed due to " + e.toString();
-            s_logger.warn(msg);
-        }
-    }
 
     public CreateAnswer execute(CreateCommand cmd) {
         Connection conn = getConnection();
@@ -6707,54 +6619,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return new Answer(cmd, true, "Success");
     }
 
-    public CopyVolumeAnswer execute(final CopyVolumeCommand cmd) {
-        Connection conn = getConnection();
-        String volumeUUID = cmd.getVolumePath();
-        StorageFilerTO poolTO = cmd.getPool();
-        String secondaryStorageURL = cmd.getSecondaryStorageURL();
-        boolean toSecondaryStorage = cmd.toSecondaryStorage();
-        int wait = cmd.getWait();
-        try {
-            URI uri = new URI(secondaryStorageURL);
-            String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/";
-            String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/";
-            String mountpoint = remoteVolumesMountPath + volumeFolder;
-            SR primaryStoragePool = getStorageRepository(conn, poolTO.getUuid());
-            String srUuid = primaryStoragePool.getUuid(conn);
-            if (toSecondaryStorage) {
-                // Create the volume folder
-                if (!createSecondaryStorageFolder(conn, remoteVolumesMountPath, volumeFolder)) {
-                    throw new InternalErrorException("Failed to create the volume folder.");
-                }
-                SR secondaryStorage = null;
-                try {
-                    // Create a SR for the volume UUID folder
-                    secondaryStorage = createNfsSRbyURI(conn, new URI(secondaryStorageURL + "/volumes/" + volumeFolder), false);
-                    // Look up the volume on the source primary storage pool
-                    VDI srcVolume = getVDIbyUuid(conn, volumeUUID);
-                    // Copy the volume to secondary storage
-                    VDI destVolume = cloudVDIcopy(conn, srcVolume, secondaryStorage, wait);
-                    String destVolumeUUID = destVolume.getUuid(conn);
-                    return new CopyVolumeAnswer(cmd, true, null, null, destVolumeUUID);
-                } finally {
-                    removeSR(conn, secondaryStorage);
-                }
-            } else {
-                try {
-                    String volumePath = mountpoint + "/" + volumeUUID + ".vhd";
-                    String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait);
-                    return new CopyVolumeAnswer(cmd, true, null, srUuid, uuid);
-                } finally {
-                    deleteSecondaryStorageFolder(conn, remoteVolumesMountPath, volumeFolder);
-                }
-            }
-        } catch (Exception e) {
-            String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
-            s_logger.warn(msg, e);
-            return new CopyVolumeAnswer(cmd, false, msg, null, null);
-        }
-    }
-
     protected VDI createVdi(SR sr, String vdiNameLabel, Long volumeSize) throws Types.XenAPIException, XmlRpcException {
         VDI vdi = null;
 
@@ -7276,140 +7140,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type);
     }
 
-    protected ManageSnapshotAnswer execute(final ManageSnapshotCommand cmd) {
-        Connection conn = getConnection();
-        long snapshotId = cmd.getSnapshotId();
-        String snapshotName = cmd.getSnapshotName();
-
-        // By default assume failure
-        boolean success = false;
-        String cmdSwitch = cmd.getCommandSwitch();
-        String snapshotOp = "Unsupported snapshot command." + cmdSwitch;
-        if (cmdSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
-            snapshotOp = "create";
-        } else if (cmdSwitch.equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
-            snapshotOp = "destroy";
-        }
-        String details = "ManageSnapshotCommand operation: " + snapshotOp + " Failed for snapshotId: " + snapshotId;
-        String snapshotUUID = null;
-
-        try {
-            if (cmdSwitch.equals(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
-                // Look up the volume
-                String volumeUUID = cmd.getVolumePath();
-                VDI volume = VDI.getByUuid(conn, volumeUUID);
-
-                // Create a snapshot
-                VDI snapshot = volume.snapshot(conn, new HashMap<String, String>());
-
-                if (snapshotName != null) {
-                    snapshot.setNameLabel(conn, snapshotName);
-                }
-                // Determine the UUID of the snapshot
-
-                snapshotUUID = snapshot.getUuid(conn);
-                String preSnapshotUUID = cmd.getSnapshotPath();
-                //check if it is a empty snapshot
-                if (preSnapshotUUID != null) {
-                    SR sr = volume.getSR(conn);
-                    String srUUID = sr.getUuid(conn);
-                    String type = sr.getType(conn);
-                    Boolean isISCSI = IsISCSI(type);
-                    String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI);
-
-                    String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI);
-                    if (snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) {
-                        // this is empty snapshot, remove it
-                        snapshot.destroy(conn);
-                        snapshotUUID = preSnapshotUUID;
-                    }
-
-                }
-                success = true;
-                details = null;
-            } else if (cmd.getCommandSwitch().equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
-                // Look up the snapshot
-                snapshotUUID = cmd.getSnapshotPath();
-                VDI snapshot = getVDIbyUuid(conn, snapshotUUID);
-
-                snapshot.destroy(conn);
-                snapshotUUID = null;
-                success = true;
-                details = null;
-            }
-        } catch (XenAPIException e) {
-            details += ", reason: " + e.toString();
-            s_logger.warn(details, e);
-        } catch (Exception e) {
-            details += ", reason: " + e.toString();
-            s_logger.warn(details, e);
-        }
-        return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, success, details);
-    }
-
-    protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromVolumeCommand cmd) {
-        Connection conn = getConnection();
-        String secondaryStoragePoolURL = cmd.getSecondaryStorageUrl();
-        String volumeUUID = cmd.getVolumePath();
-        Long accountId = cmd.getAccountId();
-        String userSpecifiedName = cmd.getTemplateName();
-        Long templateId = cmd.getTemplateId();
-        int wait = cmd.getWait();
-        String details = null;
-        SR tmpltSR = null;
-        boolean result = false;
-        String secondaryStorageMountPath = null;
-        String installPath = null;
-        try {
-            URI uri = new URI(secondaryStoragePoolURL);
-            secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
-            installPath = "template/tmpl/" + accountId + "/" + templateId;
-            if (!createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
-                details = " Filed to create folder " + installPath + " in secondary storage";
-                s_logger.warn(details);
-                return new CreatePrivateTemplateAnswer(cmd, false, details);
-            }
-
-            VDI volume = getVDIbyUuid(conn, volumeUUID);
-            // create template SR
-            URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
-            tmpltSR = createNfsSRbyURI(conn, tmpltURI, false);
-
-            // copy volume to template SR
-            VDI tmpltVDI = cloudVDIcopy(conn, volume, tmpltSR, wait);
-            // scan makes XenServer pick up VDI physicalSize
-            tmpltSR.scan(conn);
-            if (userSpecifiedName != null) {
-                tmpltVDI.setNameLabel(conn, userSpecifiedName);
-            }
-
-            String tmpltUUID = tmpltVDI.getUuid(conn);
-            String tmpltFilename = tmpltUUID + ".vhd";
-            long virtualSize = tmpltVDI.getVirtualSize(conn);
-            long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
-            // create the template.properties file
-            String templatePath = secondaryStorageMountPath + "/" + installPath;
-            result = postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, templateId);
-            if (!result) {
-                throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
-            }
-            installPath = installPath + "/" + tmpltFilename;
-            removeSR(conn, tmpltSR);
-            tmpltSR = null;
-            return new CreatePrivateTemplateAnswer(cmd, true, null, installPath, virtualSize, physicalSize, tmpltUUID, ImageFormat.VHD);
-        } catch (Exception e) {
-            if (tmpltSR != null) {
-                removeSR(conn, tmpltSR);
-            }
-            if (secondaryStorageMountPath != null) {
-                deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
-            }
-            details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
-            s_logger.error(details, e);
-        }
-        return new CreatePrivateTemplateAnswer(cmd, result, details);
-    }
-
     protected Answer execute(final UpgradeSnapshotCommand cmd) {
 
         String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
@@ -7439,60 +7169,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return new Answer(cmd, false, "failure");
     }
 
-    protected CreatePrivateTemplateAnswer execute(final CreatePrivateTemplateFromSnapshotCommand cmd) {
-        Connection conn = getConnection();
-        Long accountId = cmd.getAccountId();
-        Long volumeId = cmd.getVolumeId();
-        String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
-        String backedUpSnapshotUuid = cmd.getSnapshotUuid();
-        Long newTemplateId = cmd.getNewTemplateId();
-        String userSpecifiedName = cmd.getTemplateName();
-        int wait = cmd.getWait();
-        // By default, assume failure
-        String details = null;
-        boolean result = false;
-        String secondaryStorageMountPath = null;
-        String installPath = null;
-        try {
-            URI uri = new URI(secondaryStorageUrl);
-            secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
-            installPath = "template/tmpl/" + accountId + "/" + newTemplateId;
-            if (!createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
-                details = " Filed to create folder " + installPath + " in secondary storage";
-                s_logger.warn(details);
-                return new CreatePrivateTemplateAnswer(cmd, false, details);
-            }
-            String templatePath = secondaryStorageMountPath + "/" + installPath;
-            // create snapshot SR
-            String filename = backedUpSnapshotUuid;
-            if (!filename.startsWith("VHD-") && !filename.endsWith(".vhd")) {
-                filename = backedUpSnapshotUuid + ".vhd";
-            }
-            String snapshotPath = secondaryStorageMountPath + "/snapshots/" + accountId + "/" + volumeId + "/" + filename;
-            String results = createTemplateFromSnapshot(conn, templatePath, snapshotPath, wait);
-            String[] tmp = results.split("#");
-            String tmpltUuid = tmp[1];
-            long physicalSize = Long.parseLong(tmp[2]);
-            long virtualSize = Long.parseLong(tmp[3]) * 1024 * 1024;
-            String tmpltFilename = tmpltUuid + ".vhd";
-
-            // create the template.properties file
-            result = postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUuid, userSpecifiedName, null, physicalSize, virtualSize, newTemplateId);
-            if (!result) {
-                throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templatePath);
-            }
-            installPath = installPath + "/" + tmpltFilename;
-            return new CreatePrivateTemplateAnswer(cmd, true, null, installPath, virtualSize, physicalSize, tmpltUuid, ImageFormat.VHD);
-        } catch (Exception e) {
-            if (secondaryStorageMountPath != null) {
-                deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
-            }
-            details = "Creating template from snapshot " + backedUpSnapshotUuid + " failed due to " + e.toString();
-            s_logger.error(details, e);
-        }
-        return new CreatePrivateTemplateAnswer(cmd, result, details);
-    }
-
     private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid) {
         try {
             VDI volume = getVDIbyUuid(conn, volumeUuid);
@@ -7523,203 +7199,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return false;
     }
 
-    protected BackupSnapshotAnswer execute(final BackupSnapshotCommand cmd) {
-        Connection conn = getConnection();
-        String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
-        Long dcId = cmd.getDataCenterId();
-        Long accountId = cmd.getAccountId();
-        Long volumeId = cmd.getVolumeId();
-        String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
-        String snapshotUuid = cmd.getSnapshotUuid(); // not null: Precondition.
-        String prevBackupUuid = cmd.getPrevBackupUuid();
-        String prevSnapshotUuid = cmd.getPrevSnapshotUuid();
-        int wait = cmd.getWait();
-        Long secHostId = cmd.getSecHostId();
-        // By default assume failure
-        String details = null;
-        boolean success = false;
-        String snapshotBackupUuid = null;
-        boolean fullbackup = true;
-        try {
-            SR primaryStorageSR = getSRByNameLabelandHost(conn, primaryStorageNameLabel);
-            if (primaryStorageSR == null) {
-                throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " +
-                    primaryStorageNameLabel);
-            }
-            String psUuid = primaryStorageSR.getUuid(conn);
-            Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn));
-            URI uri = new URI(secondaryStorageUrl);
-            String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
-            VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid);
-            String snapshotPaUuid = null;
-            if (prevBackupUuid != null) {
-                try {
-                    snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI);
-                    if (snapshotPaUuid != null) {
-                        String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI);
-                        String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI);
-                        if (snashotPaPaPaUuid != null && prevSnashotPaUuid != null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) {
-                            fullbackup = false;
-                        }
-                    }
-                } catch (Exception e) {
-                }
-            }
-
-            if (fullbackup) {
-                // the first snapshot is always a full snapshot
-                String folder = "snapshots/" + accountId + "/" + volumeId;
-                if (!createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) {
-                    details = " Filed to create folder " + folder + " in secondary storage";
-                    s_logger.warn(details);
-                    return new BackupSnapshotAnswer(cmd, false, details, null, false);
-                }
-                String snapshotMountpoint = secondaryStorageUrl + "/" + folder;
-                SR snapshotSr = null;
-                try {
-                    snapshotSr = createNfsSRbyURI(conn, new URI(snapshotMountpoint), false);
-                    VDI backedVdi = cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait);
-                    snapshotBackupUuid = backedVdi.getUuid(conn);
-                    if (cmd.getSwift() != null) {
-                        try {
-                            swiftBackupSnapshot(conn, cmd.getSwift(), snapshotSr.getUuid(conn), snapshotBackupUuid, "S-" + volumeId.toString(), false, wait);
-                            snapshotBackupUuid = snapshotBackupUuid + ".vhd";
-                        } finally {
-                            deleteSnapshotBackup(conn, dcId, accountId, volumeId, secondaryStorageMountPath, snapshotBackupUuid);
-                        }
-                    } else if (cmd.getS3() != null) {
-                        try {
-                            backupSnapshotToS3(conn, cmd.getS3(), snapshotSr.getUuid(conn), snapshotBackupUuid, isISCSI, wait);
-                            snapshotBackupUuid = snapshotBackupUuid + ".vhd";
-                        } finally {
-                            deleteSnapshotBackup(conn, dcId, accountId, volumeId, secondaryStorageMountPath, snapshotBackupUuid);
-                        }
-                    }
-                    success = true;
-                } finally {
-                    if (snapshotSr != null) {
-                        removeSR(conn, snapshotSr);
-                    }
-                }
-            } else {
-                String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
-                if (cmd.getSwift() != null) {
-                    swiftBackupSnapshot(conn, cmd.getSwift(), primaryStorageSRUuid, snapshotPaUuid, "S-" + volumeId.toString(), isISCSI, wait);
-                    if (isISCSI) {
-                        snapshotBackupUuid = "VHD-" + snapshotPaUuid;
-                    } else {
-                        snapshotBackupUuid = snapshotPaUuid + ".vhd";
-                    }
-                    success = true;
-                } else if (cmd.getS3() != null) {
-                    backupSnapshotToS3(conn, cmd.getS3(), primaryStorageSRUuid, snapshotPaUuid, isISCSI, wait);
-                } else {
-                    snapshotBackupUuid =
-                        backupSnapshot(conn, primaryStorageSRUuid, dcId, accountId, volumeId, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait,
-                            secHostId);
-                    success = (snapshotBackupUuid != null);
-                }
-            }
-            String volumeUuid = cmd.getVolumePath();
-            destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
-            if (success) {
-                details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
-
-            }
-        } catch (XenAPIException e) {
-            details = "BackupSnapshot Failed due to " + e.toString();
-            s_logger.warn(details, e);
-        } catch (Exception e) {
-            details = "BackupSnapshot Failed due to " + e.getMessage();
-            s_logger.warn(details, e);
-        }
-
-        return new BackupSnapshotAnswer(cmd, success, details, snapshotBackupUuid, fullbackup);
-    }
-
-    private boolean
-        backupSnapshotToS3(final Connection connection, final S3TO s3, final String srUuid, final String snapshotUuid, final Boolean iSCSIFlag, final int wait) {
-
-        final String filename = iSCSIFlag ? "VHD-" + snapshotUuid : snapshotUuid + ".vhd";
-        final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-" : "/var/run/sr-mount/") + srUuid;
-        final String key = String.format("/snapshots/%1$s", snapshotUuid);
-
-        try {
-
-            final List<String> parameters = newArrayList(flattenProperties(s3, S3Utils.ClientOptions.class));
-            // https workaround for Introspector bug that does not
-            // recognize Boolean accessor methods ...
-            parameters.addAll(Arrays.asList("operation", "put", "filename", dir + "/" + filename, "iSCSIFlag", iSCSIFlag.toString(), "bucket", s3.getBucketName(), "key",
-                key, "https", s3.isHttps() != null ? s3.isHttps().toString() : "null"));
-            final String result = callHostPluginAsync(connection, "s3xen", "s3", wait, parameters.toArray(new String[parameters.size()]));
-
-            if (result != null && result.equals("true")) {
-                return true;
-            }
-
-        } catch (Exception e) {
-            s_logger.error(String.format("S3 upload failed of snapshot %1$s due to %2$s.", snapshotUuid, e.toString()), e);
-        }
-
-        return false;
-
-    }
-
-    protected CreateVolumeFromSnapshotAnswer execute(final CreateVolumeFromSnapshotCommand cmd) {
-        Connection conn = getConnection();
-        String primaryStorageNameLabel = cmd.getPrimaryStoragePoolNameLabel();
-        Long accountId = cmd.getAccountId();
-        Long volumeId = cmd.getVolumeId();
-        String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
-        String backedUpSnapshotUuid = cmd.getSnapshotUuid();
-        int wait = cmd.getWait();
-        boolean result = false;
-        // Generic error message.
-        String details = null;
-        String volumeUUID = null;
-        SR snapshotSR = null;
-
-        if (secondaryStorageUrl == null) {
-            details += " because the URL passed: " + secondaryStorageUrl + " is invalid.";
-            return new CreateVolumeFromSnapshotAnswer(cmd, result, details, volumeUUID);
-        }
-        try {
-            SR primaryStorageSR = getSRByNameLabelandHost(conn, primaryStorageNameLabel);
-            if (primaryStorageSR == null) {
-                throw new InternalErrorException("Could not create volume from snapshot because the primary Storage SR could not be created from the name label: " +
-                    primaryStorageNameLabel);
-            }
-            // Get the absolute path of the snapshot on the secondary storage.
-            URI snapshotURI = new URI(secondaryStorageUrl + "/snapshots/" + accountId + "/" + volumeId);
-            String filename = backedUpSnapshotUuid;
-            if (!filename.startsWith("VHD-") && !filename.endsWith(".vhd")) {
-                filename = backedUpSnapshotUuid + ".vhd";
-            }
-            String snapshotPath = snapshotURI.getHost() + ":" + snapshotURI.getPath() + "/" + filename;
-            String srUuid = primaryStorageSR.getUuid(conn);
-            volumeUUID = copy_vhd_from_secondarystorage(conn, snapshotPath, srUuid, wait);
-            result = true;
-        } catch (XenAPIException e) {
-            details += " due to " + e.toString();
-            s_logger.warn(details, e);
-        } catch (Exception e) {
-            details += " due to " + e.getMessage();
-            s_logger.warn(details, e);
-        } finally {
-            // In all cases, if the temporary SR was created, forget it.
-            if (snapshotSR != null) {
-                removeSR(conn, snapshotSR);
-            }
-        }
-        if (!result) {
-            // Is this logged at a higher level?
-            s_logger.error(details);
-        }
-
-        // In all cases return something.
-        return new CreateVolumeFromSnapshotAnswer(cmd, result, details, volumeUUID);
-    }
-
     protected VM getVM(Connection conn, String vmName) {
         // Look up VMs with the specified name
         Set<VM> vms;
@@ -7919,27 +7398,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return parentUuid;
     }
 
-    protected boolean destroySnapshotOnPrimaryStorage(Connection conn, String snapshotUuid) {
-        // Precondition snapshotUuid != null
-        try {
-            VDI snapshot = getVDIbyUuid(conn, snapshotUuid);
-            if (snapshot == null) {
-                throw new InternalErrorException("Could not destroy snapshot " + snapshotUuid + " because the snapshot VDI was null");
-            }
-            snapshot.destroy(conn);
-            s_logger.debug("Successfully destroyed snapshotUuid: " + snapshotUuid + " on primary storage");
-            return true;
-        } catch (XenAPIException e) {
-            String msg = "Destroy snapshotUuid: " + snapshotUuid + " on primary storage failed due to " + e.toString();
-            s_logger.error(msg, e);
-        } catch (Exception e) {
-            String msg = "Destroy snapshotUuid: " + snapshotUuid + " on primary storage failed due to " + e.getMessage();
-            s_logger.warn(msg, e);
-        }
-
-        return false;
-    }
-
     protected String deleteSnapshotBackup(Connection conn, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath, String backupUUID) {
 
         // If anybody modifies the formatting below again, I'll skin them
@@ -7950,10 +7408,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return result;
     }
 
-    protected boolean deleteSnapshotsDir(Connection conn, Long dcId, Long accountId, Long volumeId, String secondaryStorageMountPath) {
-        return deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, "snapshots" + "/" + accountId.toString() + "/" + volumeId.toString());
-    }
-
     @Override
     public boolean start() {
         return true;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
index d685c3f..767d77e 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
@@ -51,6 +51,11 @@ public class XenServerPoolVms {
         return pv == null ? State.Stopped : pv.second(); // if a VM is absent on the cluster, it is effectively in stopped state.
     }
 
+    public Ternary<String, State, String> get(String clusterId, String name) {
+        HashMap<String, Ternary<String, State, String>> vms = getClusterVmState(clusterId);
+        return vms.get(name);
+    }
+
     public void put(String clusterId, String hostUuid, String name, State state, String platform) {
         HashMap<String, Ternary<String, State, String>> vms = getClusterVmState(clusterId);
         vms.put(name, new Ternary<String, State, String>(hostUuid, state, platform));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/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 9171152..0d5eec8 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
@@ -90,7 +90,7 @@ import com.cloud.utils.storage.encoding.Decoder;
 public class XenServerStorageProcessor implements StorageProcessor {
     private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
     protected CitrixResourceBase hypervisorResource;
-    private String BaseMountPointOnHost = "/var/run/cloud_mount";
+    protected String BaseMountPointOnHost = "/var/run/cloud_mount";
 
     public XenServerStorageProcessor(CitrixResourceBase resource) {
         hypervisorResource = resource;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8caf52c6/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver625Resource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver625Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver625Resource.java
new file mode 100644
index 0000000..7d2a2a1
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/Xenserver625Resource.java
@@ -0,0 +1,112 @@
+/*
+ * 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 com.cloud.hypervisor.xen.resource;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+
+import org.apache.cloudstack.hypervisor.xenserver.XenServerResourceNewBase;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.resource.ServerResource;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.Script;
+import com.xensource.xenapi.Connection;
+
+@Local(value=ServerResource.class)
+public class Xenserver625Resource extends XenServerResourceNewBase {
+    private static final Logger s_logger = Logger.getLogger(XenServer620Resource.class);
+
+    public Xenserver625Resource() {
+        super();
+    }
+
+    @Override
+    protected void fillHostInfo(Connection conn, StartupRoutingCommand cmd) {
+        super.fillHostInfo(conn, cmd);
+        Map<String, String> details = cmd.getHostDetails();
+        details.put("Xenserer620HotFix", "Xenserver-Vdi-Copy-HotFix");
+    }
+
+    @Override
+    protected String getGuestOsType(String stdType, boolean bootFromCD) {
+        return CitrixHelper.getXenServer620GuestOsType(stdType, bootFromCD);
+    }
+
+    @Override
+    protected List<File> getPatchFiles() {
+        List<File> files = new ArrayList<File>();
+        String patch = "scripts/vm/hypervisor/xenserver/xenserver62/patch";
+        String patchfilePath = Script.findScript("", patch);
+        if (patchfilePath == null) {
+            throw new CloudRuntimeException("Unable to find patch file " + patch);
+        }
+        File file = new File(patchfilePath);
+        files.add(file);
+        return files;
+    }
+
+    @Override
+    public long getStaticMax(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){
+        long recommendedValue = CitrixHelper.getXenServer620StaticMax(os, b);
+        if(recommendedValue == 0){
+            s_logger.warn("No recommended value found for dynamic max, setting static max and dynamic max equal");
+            return dynamicMaxRam;
+        }
+        long staticMax = Math.min(recommendedValue, 4l * dynamicMinRam);  // XS constraint for stability
+        if (dynamicMaxRam > staticMax){ // XS contraint that dynamic max <= static max
+            s_logger.warn("dynamixMax " + dynamicMaxRam + " cant be greater than static max " + staticMax + ", can lead to stability issues. Setting static max as much as dynamic max ");
+            return dynamicMaxRam;
+        }
+        return staticMax;
+    }
+
+    @Override
+    public long getStaticMin(String os, boolean b, long dynamicMinRam, long dynamicMaxRam){
+        long recommendedValue = CitrixHelper.getXenServer620StaticMin(os, b);
+        if(recommendedValue == 0){
+            s_logger.warn("No recommended value found for dynamic min");
+            return dynamicMinRam;
+        }
+
+        if(dynamicMinRam < recommendedValue){   // XS contraint that dynamic min > static min
+            s_logger.warn("Vm is set to dynamixMin " + dynamicMinRam + " less than the recommended static min " + recommendedValue + ", could lead to stability issues");
+        }
+        return dynamicMinRam;
+    }
+
+    @Override
+    protected StorageSubsystemCommandHandler getStorageHandler() {
+        XenServerStorageProcessor processor = new Xenserver625StorageProcessor(this);
+        return new StorageSubsystemCommandHandlerBase(processor);
+    }
+
+    @Override
+    protected void umountSnapshotDir(Connection conn, Long dcId) {
+
+    }
+
+}
\ No newline at end of file