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/10/26 03:24:56 UTC

[2/5] git commit: updated refs/heads/master to 465c9ec

move a lot of code into vmsnapshot strategy

fix compile

fix compile

add vm_snapshot_details table in db

add vmsnapshot test cases


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

Branch: refs/heads/master
Commit: a6ce66e55a65eb0fbae9ead92de6ceac7a87c531
Parents: 5c5326f
Author: Edison Su <su...@gmail.com>
Authored: Thu Oct 10 18:00:21 2013 -0700
Committer: Edison Su <su...@gmail.com>
Committed: Fri Oct 25 15:09:04 2013 -0700

----------------------------------------------------------------------
 client/tomcatconf/applicationContext.xml.in     |  12 +-
 .../cloud/agent/api/CreateVMSnapshotAnswer.java |  12 +-
 .../agent/api/CreateVMSnapshotCommand.java      |   4 +-
 .../cloud/agent/api/DeleteVMSnapshotAnswer.java |  12 +-
 .../agent/api/DeleteVMSnapshotCommand.java      |   3 +-
 .../agent/api/RevertToVMSnapshotAnswer.java     |  14 +-
 .../agent/api/RevertToVMSnapshotCommand.java    |   3 +-
 .../cloud/agent/api/VMSnapshotBaseCommand.java  |  10 +-
 .../cloudstack/storage/to/VolumeObjectTO.java   |  12 +
 .../api/storage/VMSnapshotStrategy.java         |  28 ++
 .../cloud/vm/snapshot/VMSnapshotDetailsVO.java  |  87 ++++
 .../src/com/cloud/vm/snapshot/VMSnapshotVO.java |   2 +-
 .../vm/snapshot/dao/VMSnapshotDetailsDao.java   |  28 ++
 .../snapshot/dao/VMSnapshotDetailsDaoImpl.java  |  52 ++
 .../motion/AncientDataMotionStrategy.java       |  26 -
 .../vm/snapshot/dao/VmSnapshotDaoTest.java      |  46 ++
 .../storage/test/ChildTestConfiguration.java    |  47 +-
 .../cloudstack/storage/test/SnapshotTest.java   | 100 ++--
 .../test/resources/storageContext.xml           |   2 +
 engine/storage/snapshot/pom.xml                 |  32 ++
 .../storage/snapshot/SnapshotServiceImpl.java   |  44 +-
 .../snapshot/XenserverSnapshotStrategy.java     |  27 +-
 .../vmsnapshot/DefaultVMSnapshotStrategy.java   | 369 ++++++++++++++
 .../storage/vmsnapshot/VMSnapshotHelper.java    |  38 ++
 .../vmsnapshot/VMSnapshotHelperImpl.java        | 148 ++++++
 .../test/src/VMSnapshotStrategyTest.java        | 256 ++++++++++
 .../storage/volume/VolumeServiceImpl.java       |  85 ++--
 .../manager/VmwareStorageManagerImpl.java       |  87 ++--
 .../xen/resource/CitrixResourceBase.java        |  28 +-
 .../storage/snapshot/SnapshotManagerImpl.java   |  97 ----
 .../vm/snapshot/VMSnapshotManagerImpl.java      | 484 +++----------------
 .../vm/snapshot/VMSnapshotManagerTest.java      |   7 -
 setup/db/db/schema-421to430.sql                 |   9 +
 33 files changed, 1398 insertions(+), 813 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/client/tomcatconf/applicationContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 2a3520b..13ab71e 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -365,6 +365,7 @@
   <bean id="vMReservationDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMReservationDaoImpl" />
   <bean id="vMRootDiskTagDaoImpl" class="org.apache.cloudstack.engine.cloud.entity.api.db.dao.VMRootDiskTagDaoImpl" />
   <bean id="vMSnapshotDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl" />
+  <bean id="vMSnapshotDetailsDaoImpl" class="com.cloud.vm.snapshot.dao.VMSnapshotDetailsDaoImpl" />
   <bean id="vMTemplateDetailsDaoImpl" class="com.cloud.storage.dao.VMTemplateDetailsDaoImpl" />
   <bean id="vMTemplateHostDaoImpl" class="com.cloud.storage.dao.VMTemplateHostDaoImpl" />
   <bean id="vMTemplatePoolDaoImpl" class="com.cloud.storage.dao.VMTemplatePoolDaoImpl" />
@@ -882,8 +883,17 @@
   <bean id="ApplicationLoadBalancerService" class="org.apache.cloudstack.network.lb.ApplicationLoadBalancerManagerImpl" />
   <bean id="InternalLoadBalancerVMManager" class="org.apache.cloudstack.network.lb.InternalLoadBalancerVMManagerImpl" />
 
-  <bean id="vMSnapshotManagerImpl" class="com.cloud.vm.snapshot.VMSnapshotManagerImpl" />
+  <!--VM snapshot Strategies-->
+  <bean id='vmSnapshotHelper' class="org.apache.cloudstack.storage.vmsnapshot.VMSnapshotHelperImpl" />
+  <bean id='defaultVMSnapshotStrategy' class="org.apache.cloudstack.storage.vmsnapshot.DefaultVMSnapshotStrategy"/>
 
+  <bean id="vMSnapshotManagerImpl" class="com.cloud.vm.snapshot.VMSnapshotManagerImpl">
+    <property name="vmSnapshotStrategies">
+      <list>
+        <ref local="defaultVMSnapshotStrategy"/>
+      </list>
+    </property>
+  </bean>
 
 <!--=======================================================================================================-->
 <!--                                                                                                       -->

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/CreateVMSnapshotAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/CreateVMSnapshotAnswer.java b/core/src/com/cloud/agent/api/CreateVMSnapshotAnswer.java
index f9fb164..8b8e69e 100644
--- a/core/src/com/cloud/agent/api/CreateVMSnapshotAnswer.java
+++ b/core/src/com/cloud/agent/api/CreateVMSnapshotAnswer.java
@@ -17,21 +17,21 @@
 
 package com.cloud.agent.api;
 
-import java.util.List;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
-import com.cloud.agent.api.to.VolumeTO;
+import java.util.List;
 
 public class CreateVMSnapshotAnswer extends Answer {
 
-    private List<VolumeTO> volumeTOs;
+    private List<VolumeObjectTO> volumeTOs;
     private VMSnapshotTO vmSnapshotTo;
     
  
-	public List<VolumeTO> getVolumeTOs() {
+	public List<VolumeObjectTO> getVolumeTOs() {
         return volumeTOs;
     }
 
-    public void setVolumeTOs(List<VolumeTO> volumeTOs) {
+    public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
         this.volumeTOs = volumeTOs;
     }
 
@@ -53,7 +53,7 @@ public class CreateVMSnapshotAnswer extends Answer {
     }
 
     public CreateVMSnapshotAnswer(CreateVMSnapshotCommand cmd,
-    		VMSnapshotTO vmSnapshotTo, List<VolumeTO> volumeTOs) {
+    		VMSnapshotTO vmSnapshotTo, List<VolumeObjectTO> volumeTOs) {
         super(cmd, true, "");
         this.vmSnapshotTo = vmSnapshotTo;
         this.volumeTOs = volumeTOs;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/CreateVMSnapshotCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/CreateVMSnapshotCommand.java b/core/src/com/cloud/agent/api/CreateVMSnapshotCommand.java
index 478987d..bfbc21d 100644
--- a/core/src/com/cloud/agent/api/CreateVMSnapshotCommand.java
+++ b/core/src/com/cloud/agent/api/CreateVMSnapshotCommand.java
@@ -18,12 +18,14 @@ package com.cloud.agent.api;
 
 import java.util.List;
 
+import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.vm.VirtualMachine;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 public class CreateVMSnapshotCommand extends VMSnapshotBaseCommand {
 
-    public CreateVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType, VirtualMachine.State vmState) {
+    public CreateVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType, VirtualMachine.State vmState) {
         super(vmName, snapshot, volumeTOs, guestOSType);
         this.vmState  = vmState;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/DeleteVMSnapshotAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/DeleteVMSnapshotAnswer.java b/core/src/com/cloud/agent/api/DeleteVMSnapshotAnswer.java
index 8f4ecad..d6ae95c 100644
--- a/core/src/com/cloud/agent/api/DeleteVMSnapshotAnswer.java
+++ b/core/src/com/cloud/agent/api/DeleteVMSnapshotAnswer.java
@@ -16,12 +16,12 @@
 // under the License.
 package com.cloud.agent.api;
 
-import java.util.List;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
-import com.cloud.agent.api.to.VolumeTO;
+import java.util.List;
 
 public class DeleteVMSnapshotAnswer extends Answer {
-    private List<VolumeTO> volumeTOs;
+    private List<VolumeObjectTO> volumeTOs;
 
     public DeleteVMSnapshotAnswer() {
     }
@@ -32,16 +32,16 @@ public class DeleteVMSnapshotAnswer extends Answer {
     }
 
     public DeleteVMSnapshotAnswer(DeleteVMSnapshotCommand cmd,
-            List<VolumeTO> volumeTOs) {
+            List<VolumeObjectTO> volumeTOs) {
         super(cmd, true, "");
         this.volumeTOs = volumeTOs;
     }
 
-    public List<VolumeTO> getVolumeTOs() {
+    public List<VolumeObjectTO> getVolumeTOs() {
         return volumeTOs;
     }
 
-    public void setVolumeTOs(List<VolumeTO> volumeTOs) {
+    public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
         this.volumeTOs = volumeTOs;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/DeleteVMSnapshotCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/DeleteVMSnapshotCommand.java b/core/src/com/cloud/agent/api/DeleteVMSnapshotCommand.java
index c213448..1c64a2b 100644
--- a/core/src/com/cloud/agent/api/DeleteVMSnapshotCommand.java
+++ b/core/src/com/cloud/agent/api/DeleteVMSnapshotCommand.java
@@ -19,10 +19,11 @@ package com.cloud.agent.api;
 import java.util.List;
 
 import com.cloud.agent.api.to.VolumeTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 
 public class DeleteVMSnapshotCommand extends VMSnapshotBaseCommand {
-    public DeleteVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
+    public DeleteVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
         super( vmName,  snapshot, volumeTOs, guestOSType);
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/RevertToVMSnapshotAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/RevertToVMSnapshotAnswer.java b/core/src/com/cloud/agent/api/RevertToVMSnapshotAnswer.java
index 848ffc0..6170864 100644
--- a/core/src/com/cloud/agent/api/RevertToVMSnapshotAnswer.java
+++ b/core/src/com/cloud/agent/api/RevertToVMSnapshotAnswer.java
@@ -17,14 +17,14 @@
 
 package com.cloud.agent.api;
 
-import java.util.List;
-
-import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.vm.VirtualMachine;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+
+import java.util.List;
 
 public class RevertToVMSnapshotAnswer extends Answer {
 
-    private List<VolumeTO> volumeTOs;
+    private List<VolumeObjectTO> volumeTOs;
     private VirtualMachine.State vmState;
 
     public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd, boolean result,
@@ -37,7 +37,7 @@ public class RevertToVMSnapshotAnswer extends Answer {
     }
 
     public RevertToVMSnapshotAnswer(RevertToVMSnapshotCommand cmd,
-            List<VolumeTO> volumeTOs,
+            List<VolumeObjectTO> volumeTOs,
             VirtualMachine.State vmState) {
         super(cmd, true, "");
         this.volumeTOs = volumeTOs;
@@ -48,11 +48,11 @@ public class RevertToVMSnapshotAnswer extends Answer {
         return vmState;
     }
 
-    public List<VolumeTO> getVolumeTOs() {
+    public List<VolumeObjectTO> getVolumeTOs() {
         return volumeTOs;
     }
 
-    public void setVolumeTOs(List<VolumeTO> volumeTOs) {
+    public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
         this.volumeTOs = volumeTOs;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/RevertToVMSnapshotCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/RevertToVMSnapshotCommand.java b/core/src/com/cloud/agent/api/RevertToVMSnapshotCommand.java
index 429a186..1e5fd6c 100644
--- a/core/src/com/cloud/agent/api/RevertToVMSnapshotCommand.java
+++ b/core/src/com/cloud/agent/api/RevertToVMSnapshotCommand.java
@@ -19,10 +19,11 @@ package com.cloud.agent.api;
 import java.util.List;
 
 import com.cloud.agent.api.to.VolumeTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 public class RevertToVMSnapshotCommand extends VMSnapshotBaseCommand {
 
-    public RevertToVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
+    public RevertToVMSnapshotCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
         super(vmName, snapshot, volumeTOs, guestOSType);
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java b/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java
index 2120f2f..b2c5241 100644
--- a/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java
+++ b/core/src/com/cloud/agent/api/VMSnapshotBaseCommand.java
@@ -19,27 +19,29 @@ package com.cloud.agent.api;
 
 import java.util.List;
 
+import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.VolumeTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
 
 public class VMSnapshotBaseCommand extends Command{
-    protected List<VolumeTO> volumeTOs;
+    protected List<VolumeObjectTO> volumeTOs;
     protected VMSnapshotTO target;
     protected String vmName;
     protected String guestOSType;
     
     
-    public VMSnapshotBaseCommand(String vmName, VMSnapshotTO snapshot, List<VolumeTO> volumeTOs, String guestOSType) {
+    public VMSnapshotBaseCommand(String vmName, VMSnapshotTO snapshot, List<VolumeObjectTO> volumeTOs, String guestOSType) {
         this.vmName = vmName;
         this.target = snapshot;
         this.volumeTOs = volumeTOs;
         this.guestOSType = guestOSType;
     }
     
-    public List<VolumeTO> getVolumeTOs() {
+    public List<VolumeObjectTO> getVolumeTOs() {
         return volumeTOs;
     }
 
-    public void setVolumeTOs(List<VolumeTO> volumeTOs) {
+    public void setVolumeTOs(List<VolumeObjectTO> volumeTOs) {
         this.volumeTOs = volumeTOs;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
----------------------------------------------------------------------
diff --git a/core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java b/core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
index 5685fad..46659a3 100644
--- a/core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
+++ b/core/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
@@ -38,6 +38,8 @@ public class VolumeObjectTO implements DataTO {
     private String chainInfo;
     private Storage.ImageFormat format;
     private long id;
+
+    private Long deviceId;
     private Long bytesReadRate;
     private Long bytesWriteRate;
     private Long iopsReadRate;
@@ -70,6 +72,7 @@ public class VolumeObjectTO implements DataTO {
         this.iopsReadRate = volume.getIopsReadRate();
         this.iopsWriteRate = volume.getIopsWriteRate();
         this.hypervisorType = volume.getHypervisorType();
+        setDeviceId(volume.getDeviceId());
     }
 
     public String getUuid() {
@@ -220,4 +223,13 @@ public class VolumeObjectTO implements DataTO {
         return iopsWriteRate;
     }
 
+    public Long getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(Long deviceId) {
+        this.deviceId = deviceId;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VMSnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VMSnapshotStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VMSnapshotStrategy.java
new file mode 100644
index 0000000..8dd6eca
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VMSnapshotStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.engine.subsystem.api.storage;
+
+import com.cloud.vm.snapshot.VMSnapshot;
+
+public interface VMSnapshotStrategy {
+    VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot);
+    boolean deleteVMSnapshot(VMSnapshot vmSnapshot);
+    boolean revertVMSnapshot(VMSnapshot vmSnapshot);
+    boolean canHandle(VMSnapshot vmSnapshot);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotDetailsVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotDetailsVO.java b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotDetailsVO.java
new file mode 100644
index 0000000..934dd92
--- /dev/null
+++ b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotDetailsVO.java
@@ -0,0 +1,87 @@
+/*
+ * 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.vm.snapshot;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+@Entity
+@Table(name = "vm_snapshot_details")
+public class VMSnapshotDetailsVO implements InternalIdentity {
+    @Id
+    @TableGenerator(name = "vm_snapshot_details_seq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshot_details_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.TABLE)
+    @Column(name = "id")
+    private long id;
+
+    @Column(name = "vm_snapshot_id")
+    Long vmSnapshotId;
+
+    @Column(name = "name")
+    String name;
+
+    @Column(name = "value")
+    String value;
+
+    public VMSnapshotDetailsVO() {
+
+    }
+
+    public VMSnapshotDetailsVO(Long vmSnapshotId, String name, String value) {
+        this.vmSnapshotId = vmSnapshotId;
+        this.name = name;
+        this.value = value;
+    }
+
+    public Long getVmSnapshotId() {
+        return this.vmSnapshotId;
+    }
+
+    public void setVmSnapshotId(Long vmSnapshotId) {
+        this.vmSnapshotId = vmSnapshotId;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public long getId() {
+       return id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java
index 03d4945..477148c 100644
--- a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java
+++ b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java
@@ -41,7 +41,7 @@ public class VMSnapshotVO implements VMSnapshot {
     @TableGenerator(name = "vm_snapshots_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshots_seq", allocationSize = 1)
     @GeneratedValue(strategy = GenerationType.TABLE)
     @Column(name = "id")
-    long id;
+    Long id;
 
     @Column(name = "uuid")
     String uuid = UUID.randomUUID().toString();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDao.java b/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDao.java
new file mode 100644
index 0000000..e84178c
--- /dev/null
+++ b/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDao.java
@@ -0,0 +1,28 @@
+/*
+ * 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.vm.snapshot.dao;
+
+import com.cloud.utils.db.GenericDao;
+import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
+
+import java.util.Map;
+
+public interface VMSnapshotDetailsDao extends GenericDao<VMSnapshotDetailsVO, Long> {
+    Map<String, String> getDetails(Long vmSnapshotId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDaoImpl.java b/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDaoImpl.java
new file mode 100644
index 0000000..b528b39
--- /dev/null
+++ b/engine/schema/src/com/cloud/vm/snapshot/dao/VMSnapshotDetailsDaoImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.vm.snapshot.dao;
+
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class VMSnapshotDetailsDaoImpl extends GenericDaoBase<VMSnapshotDetailsVO, Long> implements VMSnapshotDetailsDao {
+    protected final SearchBuilder<VMSnapshotDetailsVO> searchDetails;
+
+    protected VMSnapshotDetailsDaoImpl() {
+        super();
+        searchDetails = createSearchBuilder();
+        searchDetails.and("vmsnapshotId", searchDetails.entity().getVmSnapshotId(), SearchCriteria.Op.EQ);
+        searchDetails.done();
+    }
+    @Override
+    public Map<String, String> getDetails(Long vmSnapshotId) {
+        SearchCriteria<VMSnapshotDetailsVO> sc = searchDetails.create();
+        sc.setParameters("vmsnapshotId", vmSnapshotId);
+
+        List<VMSnapshotDetailsVO> details = listBy(sc);
+        Map<String, String> detailsMap = new HashMap<String, String>();
+        for (VMSnapshotDetailsVO detail : details) {
+            detailsMap.put(detail.getName(), detail.getValue());
+        }
+
+        return detailsMap;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/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 5f5f01e..7b5b7fc 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
@@ -87,38 +87,12 @@ AncientDataMotionStrategy implements DataMotionStrategy {
     @Inject
     EndPointSelector selector;
     @Inject
-    TemplateManager templateMgr;
-    @Inject
-    VolumeDataStoreDao volumeStoreDao;
-    @Inject
-    HostDao hostDao;
-    @Inject
     ConfigurationDao configDao;
     @Inject
-    StorageManager storageMgr;
-    @Inject
     VolumeDao volDao;
     @Inject
-    VMTemplateDao templateDao;
-    @Inject
-    SnapshotManager snapshotMgr;
-    @Inject
-    SnapshotDao snapshotDao;
-    @Inject
-    SnapshotDataStoreDao _snapshotStoreDao;
-    @Inject
-    PrimaryDataStoreDao primaryDataStoreDao;
-    @Inject
     DataStoreManager dataStoreMgr;
     @Inject
-    TemplateDataStoreDao templateStoreDao;
-    @Inject
-    DiskOfferingDao diskOfferingDao;
-    @Inject
-    VMTemplatePoolDao templatePoolDao;
-    @Inject
-    VolumeOrchestrationService volumeMgr;
-    @Inject
     StorageCacheManager cacheMgr;
     @Inject
     ManagementService _mgmtServer;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/integration-test/test/com/cloud/vm/snapshot/dao/VmSnapshotDaoTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/com/cloud/vm/snapshot/dao/VmSnapshotDaoTest.java b/engine/storage/integration-test/test/com/cloud/vm/snapshot/dao/VmSnapshotDaoTest.java
new file mode 100644
index 0000000..fc52f89
--- /dev/null
+++ b/engine/storage/integration-test/test/com/cloud/vm/snapshot/dao/VmSnapshotDaoTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.vm.snapshot.dao;
+
+import com.cloud.vm.snapshot.VMSnapshotDetailsVO;
+import junit.framework.Assert;
+import org.apache.cloudstack.storage.test.CloudStackTestNGBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.inject.Inject;
+import java.util.Map;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = "classpath:/storageContext.xml")
+public class VmSnapshotDaoTest extends CloudStackTestNGBase {
+    @Inject
+    VMSnapshotDetailsDao vmsnapshotDetailsDao;
+
+    @Test
+    public void testVmSnapshotDetails() {
+        VMSnapshotDetailsVO detailsVO = new VMSnapshotDetailsVO(1L, "test", "foo");
+        vmsnapshotDetailsDao.persist(detailsVO);
+        Map<String, String> details = vmsnapshotDetailsDao.getDetails(1L);
+        Assert.assertTrue(details.containsKey("test"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
index d5eea85..228b957 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
@@ -16,30 +16,6 @@
 // under the License.
 package org.apache.cloudstack.storage.test;
 
-import java.io.IOException;
-
-import com.cloud.event.ActionEventUtils;
-import com.cloud.event.dao.EventDaoImpl;
-import org.apache.cloudstack.acl.APIChecker;
-import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
-import org.apache.cloudstack.engine.service.api.OrchestrationService;
-import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
-import org.apache.cloudstack.framework.rpc.RpcProvider;
-import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl;
-import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
-import org.apache.cloudstack.test.utils.SpringUtils;
-
-import org.mockito.Mockito;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.ComponentScan.Filter;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.FilterType;
-import org.springframework.core.type.classreading.MetadataReader;
-import org.springframework.core.type.classreading.MetadataReaderFactory;
-import org.springframework.core.type.filter.TypeFilter;
-
 import com.cloud.agent.AgentManager;
 import com.cloud.alert.AlertManager;
 import com.cloud.capacity.dao.CapacityDaoImpl;
@@ -55,6 +31,8 @@ import com.cloud.dc.dao.DcDetailsDaoImpl;
 import com.cloud.dc.dao.HostPodDaoImpl;
 import com.cloud.dc.dao.PodVlanDaoImpl;
 import com.cloud.domain.dao.DomainDaoImpl;
+import com.cloud.event.ActionEventUtils;
+import com.cloud.event.dao.EventDaoImpl;
 import com.cloud.host.dao.HostDao;
 import com.cloud.host.dao.HostDaoImpl;
 import com.cloud.host.dao.HostDetailsDaoImpl;
@@ -80,7 +58,6 @@ import com.cloud.storage.dao.VolumeDaoImpl;
 import com.cloud.storage.dao.VolumeHostDaoImpl;
 import com.cloud.storage.download.DownloadMonitorImpl;
 import com.cloud.storage.secondary.SecondaryStorageVmManager;
-import com.cloud.storage.snapshot.SnapshotManager;
 import com.cloud.tags.dao.ResourceTagsDaoImpl;
 import com.cloud.template.TemplateManager;
 import com.cloud.user.AccountManager;
@@ -96,6 +73,26 @@ import com.cloud.vm.dao.UserVmDaoImpl;
 import com.cloud.vm.dao.UserVmDetailsDaoImpl;
 import com.cloud.vm.dao.VMInstanceDaoImpl;
 import com.cloud.vm.snapshot.dao.VMSnapshotDaoImpl;
+import org.apache.cloudstack.acl.APIChecker;
+import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
+import org.apache.cloudstack.engine.service.api.OrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
+import org.apache.cloudstack.framework.rpc.RpcProvider;
+import org.apache.cloudstack.storage.cache.manager.StorageCacheManagerImpl;
+import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
+import org.apache.cloudstack.test.utils.SpringUtils;
+import org.mockito.Mockito;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.ComponentScan.Filter;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.core.type.filter.TypeFilter;
+
+import java.io.IOException;
 
 @Configuration
 @ComponentScan(basePackageClasses = { NicDaoImpl.class, VMInstanceDaoImpl.class, VMTemplateHostDaoImpl.class,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
index 81f77d6..36bc912 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
@@ -18,16 +18,42 @@
  */
 package org.apache.cloudstack.storage.test;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-
-import javax.inject.Inject;
-
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Command;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.HypervisorGuruManager;
+import com.cloud.org.Cluster.ClusterType;
+import com.cloud.org.Managed.ManagedState;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.ScopeType;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.Storage;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.StoragePoolStatus;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.component.ComponentContext;
 import junit.framework.Assert;
-
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -39,13 +65,14 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
+import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
-import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
 import org.apache.cloudstack.framework.async.AsyncCallFuture;
 import org.apache.cloudstack.storage.LocalHostEndpoint;
@@ -64,41 +91,12 @@ import org.springframework.test.context.ContextConfiguration;
 import org.testng.AssertJUnit;
 import org.testng.annotations.Test;
 
-import com.cloud.agent.AgentManager;
-import com.cloud.agent.api.Command;
-import com.cloud.dc.ClusterVO;
-import com.cloud.dc.DataCenter.NetworkType;
-import com.cloud.dc.DataCenterVO;
-import com.cloud.dc.HostPodVO;
-import com.cloud.dc.dao.ClusterDao;
-import com.cloud.dc.dao.DataCenterDao;
-import com.cloud.dc.dao.HostPodDao;
-import com.cloud.host.Host;
-import com.cloud.host.Host.Type;
-import com.cloud.host.HostVO;
-import com.cloud.host.dao.HostDao;
-import com.cloud.hypervisor.Hypervisor.HypervisorType;
-import com.cloud.hypervisor.HypervisorGuruManager;
-import com.cloud.org.Cluster.ClusterType;
-import com.cloud.org.Managed.ManagedState;
-import com.cloud.resource.ResourceManager;
-import com.cloud.resource.ResourceState;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.ScopeType;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.Storage;
-import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.storage.Storage.StoragePoolType;
-import com.cloud.storage.Storage.TemplateType;
-import com.cloud.storage.StoragePoolStatus;
-import com.cloud.storage.VMTemplateVO;
-import com.cloud.storage.Volume;
-import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.VMTemplateDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.utils.component.ComponentContext;
+import javax.inject.Inject;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
 
 @ContextConfiguration(locations = { "classpath:/storageContext.xml" })
 public class SnapshotTest extends CloudStackTestNGBase {
@@ -404,7 +402,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
         StrategyPriority.sortStrategies(snapshotStrategies, snapshot);
 
         for (SnapshotStrategy strategy : this.snapshotStrategies) {
-            if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+            if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                 snapshot = strategy.takeSnapshot(snapshot);
                 result = true;
             }
@@ -429,7 +427,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
         StrategyPriority.sortStrategies(snapshotStrategies, newSnapshot);
 
         for (SnapshotStrategy strategy : this.snapshotStrategies) {
-            if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+            if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                 newSnapshot = strategy.takeSnapshot(snapshot);
             }
         }
@@ -437,7 +435,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
 
         // create another snapshot
         for (SnapshotStrategy strategy : this.snapshotStrategies) {
-            if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+            if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                 strategy.deleteSnapshot(newSnapshot.getId());
             }
         }
@@ -454,7 +452,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
         StrategyPriority.sortStrategies(snapshotStrategies, snapshot);
 
         for (SnapshotStrategy strategy : this.snapshotStrategies) {
-            if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+            if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                 snapshot = strategy.takeSnapshot(snapshot);
                 result = true;
             }
@@ -487,7 +485,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
         StrategyPriority.sortStrategies(snapshotStrategies, newSnapshot);
 
         for (SnapshotStrategy strategy : this.snapshotStrategies) {
-            if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+            if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                 newSnapshot = strategy.takeSnapshot(snapshot);
             }
         }
@@ -499,7 +497,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
 
         try {
             for (SnapshotStrategy strategy : this.snapshotStrategies) {
-                if (strategy.canHandle(snapshot) != Priority.CANT_HANDLE) {
+                if (strategy.canHandle(snapshot) != StrategyPriority.Priority.CANT_HANDLE) {
                     boolean res = strategy.deleteSnapshot(newSnapshot.getId());
                     Assert.assertTrue(res);
                 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/integration-test/test/resources/storageContext.xml
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/resources/storageContext.xml b/engine/storage/integration-test/test/resources/storageContext.xml
index 664f1e3..884e813 100644
--- a/engine/storage/integration-test/test/resources/storageContext.xml
+++ b/engine/storage/integration-test/test/resources/storageContext.xml
@@ -85,4 +85,6 @@
   <bean id="AccountGuestVlanMapDaoImpl" class="com.cloud.network.dao.AccountGuestVlanMapDaoImpl" />
   <bean id="StorageCacheReplacementAlgorithm" class="org.apache.cloudstack.storage.cache.manager.StorageCacheReplacementAlgorithmLRU" />
   <bean id="ServiceOfferingDetailsDao" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl" />
+  <bean id="vmsnapshotDetailsDao" class="com.cloud.vm.snapshot.dao.VMSnapshotDetailsDaoImpl" />
+  <bean id="snapshotManager" class="com.cloud.storage.snapshot.SnapshotManagerImpl" />
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/snapshot/pom.xml
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/pom.xml b/engine/storage/snapshot/pom.xml
index 8a84704..808d0c2 100644
--- a/engine/storage/snapshot/pom.xml
+++ b/engine/storage/snapshot/pom.xml
@@ -30,5 +30,37 @@
       <artifactId>cloud-engine-api</artifactId>
       <version>${project.version}</version>
     </dependency>
+      <dependency>
+          <groupId>org.apache.cloudstack</groupId>
+          <artifactId>cloud-api</artifactId>
+          <version>${project.version}</version>
+          <type>test-jar</type>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>testCompile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>integration-test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
index a4014b0..0799721 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java
@@ -17,11 +17,10 @@
 
 package org.apache.cloudstack.storage.snapshot;
 
-import java.util.concurrent.ExecutionException;
-
-import javax.inject.Inject;
-
-import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
 import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
@@ -41,57 +40,26 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 import org.apache.cloudstack.framework.async.AsyncRpcContext;
 import org.apache.cloudstack.storage.command.CommandResult;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
-import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
-import com.cloud.dc.dao.ClusterDao;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.dao.VolumeDao;
-import com.cloud.storage.snapshot.SnapshotManager;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
-import com.cloud.vm.dao.UserVmDao;
-import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+import javax.inject.Inject;
+import java.util.concurrent.ExecutionException;
 
 @Component
 public class SnapshotServiceImpl implements SnapshotService {
     private static final Logger s_logger = Logger.getLogger(SnapshotServiceImpl.class);
     @Inject
-    protected VolumeDao _volsDao;
-    @Inject
-    protected UserVmDao _vmDao;
-    @Inject
-    protected PrimaryDataStoreDao _storagePoolDao;
-    @Inject
-    protected ClusterDao _clusterDao;
-    @Inject
-    protected SnapshotDao _snapshotDao;
-    @Inject
     protected SnapshotDataStoreDao _snapshotStoreDao;
-
-    @Inject
-    protected SnapshotManager snapshotMgr;
-    @Inject
-    protected VolumeOrchestrationService volumeMgr;
-    @Inject
-    protected SnapshotStateMachineManager stateMachineManager;
     @Inject
     SnapshotDataFactory snapshotfactory;
     @Inject
     DataStoreManager dataStoreMgr;
     @Inject
     DataMotionService motionSrv;
-    @Inject
-    ObjectInDataStoreManager objInStoreMgr;
-    @Inject
-    VMSnapshotDao _vmSnapshotDao;
 
     static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
         final SnapshotInfo snapshot;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/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 6a874d6..403f113 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
@@ -16,8 +16,17 @@
 // under the License.
 package org.apache.cloudstack.storage.snapshot;
 
-import javax.inject.Inject;
-
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.Volume;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
 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;
@@ -36,25 +45,13 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
-import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Snapshot;
-import com.cloud.storage.SnapshotVO;
-import com.cloud.storage.Volume;
-import com.cloud.storage.dao.SnapshotDao;
-import com.cloud.storage.snapshot.SnapshotManager;
-import com.cloud.utils.NumbersUtil;
-import com.cloud.utils.db.DB;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.fsm.NoTransitionException;
+import javax.inject.Inject;
 
 @Component
 public class XenserverSnapshotStrategy extends SnapshotStrategyBase {
     private static final Logger s_logger = Logger.getLogger(XenserverSnapshotStrategy.class);
 
     @Inject
-    SnapshotManager snapshotMgr;
-    @Inject
     SnapshotService snapshotSvr;
     @Inject
     DataStoreManager dataStoreMgr;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
new file mode 100644
index 0000000..6b5e5fb
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/DefaultVMSnapshotStrategy.java
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.vmsnapshot;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CreateVMSnapshotAnswer;
+import com.cloud.agent.api.CreateVMSnapshotCommand;
+import com.cloud.agent.api.DeleteVMSnapshotAnswer;
+import com.cloud.agent.api.DeleteVMSnapshotCommand;
+import com.cloud.agent.api.RevertToVMSnapshotAnswer;
+import com.cloud.agent.api.RevertToVMSnapshotCommand;
+import com.cloud.agent.api.VMSnapshotTO;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.storage.DiskOfferingVO;
+import com.cloud.storage.GuestOSVO;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.DiskOfferingDao;
+import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.snapshot.VMSnapshot;
+import com.cloud.vm.snapshot.VMSnapshotVO;
+import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+
+public class DefaultVMSnapshotStrategy extends ManagerBase implements VMSnapshotStrategy {
+    private static final Logger s_logger = Logger.getLogger(DefaultVMSnapshotStrategy.class);
+    @Inject
+    VMSnapshotHelper vmSnapshotHelper;
+    @Inject
+    GuestOSDao guestOSDao;
+    @Inject
+    UserVmDao userVmDao;
+    @Inject
+    VMSnapshotDao vmSnapshotDao;
+    int _wait;
+    @Inject
+    ConfigurationDao configurationDao;
+    @Inject
+    AgentManager agentMgr;
+    @Inject
+    VolumeDao volumeDao;
+    @Inject
+    DiskOfferingDao diskOfferingDao;
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        String value = configurationDao.getValue("vmsnapshot.create.wait");
+        _wait = NumbersUtil.parseInt(value, 1800);
+        return true;
+    }
+
+    public VMSnapshot takeVMSnapshot(VMSnapshot vmSnapshot) {
+        Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
+        UserVm userVm = userVmDao.findById(vmSnapshot.getVmId());
+        VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
+        try {
+            vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.CreateRequested);
+        } catch (NoTransitionException e) {
+            throw new CloudRuntimeException(e.getMessage());
+        }
+
+        CreateVMSnapshotAnswer answer = null;
+        boolean result = false;
+        try {
+            GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
+
+            List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(userVm.getId());
+
+            VMSnapshotTO current = null;
+            VMSnapshotVO currentSnapshot = vmSnapshotDao.findCurrentSnapshotByVmId(userVm.getId());
+            if (currentSnapshot != null)
+                current = vmSnapshotHelper.getSnapshotWithParents(currentSnapshot);
+            VMSnapshotTO target = new VMSnapshotTO(vmSnapshot.getId(),  vmSnapshot.getName(), vmSnapshot.getType(), null, vmSnapshot.getDescription(), false,
+                    current);
+            if (current == null)
+                vmSnapshotVO.setParent(null);
+            else
+                vmSnapshotVO.setParent(current.getId());
+
+            CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(userVm.getInstanceName(),target ,volumeTOs, guestOS.getDisplayName(),userVm.getState());
+            ccmd.setWait(_wait);
+
+            answer = (CreateVMSnapshotAnswer)agentMgr.send(hostId, ccmd);
+            if (answer != null && answer.getResult()) {
+                processAnswer(vmSnapshotVO, userVm, answer, hostId);
+                s_logger.debug("Create vm snapshot " + vmSnapshot.getName() + " succeeded for vm: " + userVm.getInstanceName());
+                result = true;
+
+                for (VolumeObjectTO volumeTo : answer.getVolumeTOs()){
+                    publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_CREATE,vmSnapshot,userVm,volumeTo);
+                }
+                return vmSnapshot;
+            } else {
+                String errMsg = "Creating VM snapshot: " + vmSnapshot.getName() + " failed";
+                if(answer != null && answer.getDetails() != null)
+                    errMsg = errMsg + " due to " + answer.getDetails();
+                s_logger.error(errMsg);
+                throw new CloudRuntimeException(errMsg);
+            }
+        } catch (OperationTimedoutException e) {
+            s_logger.debug("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
+            throw new CloudRuntimeException("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
+        } catch (AgentUnavailableException e) {
+            s_logger.debug("Creating VM snapshot: " + vmSnapshot.getName() + " failed", e);
+            throw new CloudRuntimeException("Creating VM snapshot: " + vmSnapshot.getName() + " failed: " + e.toString());
+        } finally{
+            if (!result) {
+                try {
+                    vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
+                } catch (NoTransitionException e1) {
+                    s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean deleteVMSnapshot(VMSnapshot vmSnapshot) {
+        UserVmVO userVm = userVmDao.findById(vmSnapshot.getVmId());
+        VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
+        try {
+            vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot,VMSnapshot.Event.ExpungeRequested);
+        } catch (NoTransitionException e) {
+            s_logger.debug("Failed to change vm snapshot state with event ExpungeRequested");
+            throw new CloudRuntimeException("Failed to change vm snapshot state with event ExpungeRequested: " + e.getMessage());
+        }
+
+        try {
+            Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
+
+            List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(vmSnapshot.getVmId());
+
+            String vmInstanceName = userVm.getInstanceName();
+            VMSnapshotTO parent = vmSnapshotHelper.getSnapshotWithParents(vmSnapshotVO).getParent();
+            VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(vmSnapshot.getId(), vmSnapshot.getName(), vmSnapshot.getType(),
+                    vmSnapshot.getCreated().getTime(), vmSnapshot.getDescription(), vmSnapshot.getCurrent(), parent);
+            GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
+            DeleteVMSnapshotCommand deleteSnapshotCommand = new DeleteVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs,guestOS.getDisplayName());
+
+            Answer answer = agentMgr.send(hostId, deleteSnapshotCommand);
+
+            if (answer != null && answer.getResult()) {
+                DeleteVMSnapshotAnswer deleteVMSnapshotAnswer = (DeleteVMSnapshotAnswer)answer;
+                processAnswer(vmSnapshotVO, userVm, answer, hostId);
+                for (VolumeObjectTO volumeTo : deleteVMSnapshotAnswer.getVolumeTOs()){
+                    publishUsageEvent(EventTypes.EVENT_VM_SNAPSHOT_DELETE,vmSnapshot,userVm,volumeTo);
+                }
+                return true;
+            } else {
+                String errMsg = (answer == null) ? null : answer.getDetails();
+                s_logger.error("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + errMsg);
+                throw new  CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + errMsg);
+            }
+        } catch (OperationTimedoutException e) {
+            throw new CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + e.getMessage());
+        } catch (AgentUnavailableException e) {
+            throw new CloudRuntimeException("Delete vm snapshot " + vmSnapshot.getName() + " of vm " + userVm.getInstanceName() + " failed due to " + e.getMessage());
+        }
+    }
+
+    @DB
+    protected void processAnswer(VMSnapshotVO vmSnapshot, UserVm userVm, Answer as, Long hostId) {
+        final Transaction txn = Transaction.currentTxn();
+        try {
+            txn.start();
+            if (as instanceof CreateVMSnapshotAnswer) {
+                CreateVMSnapshotAnswer answer = (CreateVMSnapshotAnswer) as;
+                finalizeCreate(vmSnapshot, answer.getVolumeTOs());
+                vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
+            } else if (as instanceof RevertToVMSnapshotAnswer) {
+                RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) as;
+                finalizeRevert(vmSnapshot, answer.getVolumeTOs());
+                vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationSucceeded);
+            } else if (as instanceof DeleteVMSnapshotAnswer) {
+                DeleteVMSnapshotAnswer answer = (DeleteVMSnapshotAnswer) as;
+                finalizeDelete(vmSnapshot, answer.getVolumeTOs());
+                vmSnapshotDao.remove(vmSnapshot.getId());
+            }
+            txn.commit();
+        } catch (Exception e) {
+            String errMsg = "Error while process answer: " + as.getClass() + " due to " + e.getMessage();
+            s_logger.error(errMsg, e);
+            txn.rollback();
+            throw new CloudRuntimeException(errMsg);
+        } finally {
+            txn.close();
+        }
+    }
+
+    protected void finalizeDelete(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> VolumeTOs) {
+        // update volumes path
+        updateVolumePath(VolumeTOs);
+
+        // update children's parent snapshots
+        List<VMSnapshotVO> children= vmSnapshotDao.listByParent(vmSnapshot.getId());
+        for (VMSnapshotVO child : children) {
+            child.setParent(vmSnapshot.getParent());
+            vmSnapshotDao.persist(child);
+        }
+
+        // update current snapshot
+        VMSnapshotVO current = vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
+        if(current != null && current.getId() == vmSnapshot.getId() && vmSnapshot.getParent() != null){
+            VMSnapshotVO parent = vmSnapshotDao.findById(vmSnapshot.getParent());
+            parent.setCurrent(true);
+            vmSnapshotDao.persist(parent);
+        }
+        vmSnapshot.setCurrent(false);
+        vmSnapshotDao.persist(vmSnapshot);
+    }
+
+    protected void finalizeCreate(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> VolumeTOs) {
+        // update volumes path
+        updateVolumePath(VolumeTOs);
+
+        vmSnapshot.setCurrent(true);
+
+        // change current snapshot
+        if (vmSnapshot.getParent() != null) {
+            VMSnapshotVO previousCurrent = vmSnapshotDao.findById(vmSnapshot.getParent());
+            previousCurrent.setCurrent(false);
+            vmSnapshotDao.persist(previousCurrent);
+        }
+        vmSnapshotDao.persist(vmSnapshot);
+    }
+
+    protected void finalizeRevert(VMSnapshotVO vmSnapshot, List<VolumeObjectTO> volumeToList) {
+        // update volumes path
+        updateVolumePath(volumeToList);
+
+        // update current snapshot, current snapshot is the one reverted to
+        VMSnapshotVO previousCurrent = vmSnapshotDao.findCurrentSnapshotByVmId(vmSnapshot.getVmId());
+        if(previousCurrent != null){
+            previousCurrent.setCurrent(false);
+            vmSnapshotDao.persist(previousCurrent);
+        }
+        vmSnapshot.setCurrent(true);
+        vmSnapshotDao.persist(vmSnapshot);
+    }
+
+    private void updateVolumePath(List<VolumeObjectTO> volumeTOs) {
+        for (VolumeObjectTO volume : volumeTOs) {
+            if (volume.getPath() != null) {
+                VolumeVO volumeVO = volumeDao.findById(volume.getId());
+                volumeVO.setPath(volume.getPath());
+                volumeVO.setVmSnapshotChainSize(volume.getSize());
+                volumeDao.persist(volumeVO);
+            }
+        }
+    }
+
+    private void publishUsageEvent(String type, VMSnapshot vmSnapshot, UserVm userVm, VolumeObjectTO volumeTo){
+        VolumeVO volume = volumeDao.findById(volumeTo.getId());
+        Long diskOfferingId = volume.getDiskOfferingId();
+        Long offeringId = null;
+        if (diskOfferingId != null) {
+            DiskOfferingVO offering = diskOfferingDao.findById(diskOfferingId);
+            if (offering != null
+                    && (offering.getType() == DiskOfferingVO.Type.Disk)) {
+                offeringId = offering.getId();
+            }
+        }
+        UsageEventUtils.publishUsageEvent(
+                type,
+                vmSnapshot.getAccountId(),
+                userVm.getDataCenterId(),
+                userVm.getId(),
+                vmSnapshot.getName(),
+                offeringId,
+                volume.getId(), // save volume's id into templateId field
+                volumeTo.getSize(),
+                VMSnapshot.class.getName(), vmSnapshot.getUuid());
+    }
+
+    @Override
+    public boolean revertVMSnapshot(VMSnapshot vmSnapshot) {
+        VMSnapshotVO vmSnapshotVO = (VMSnapshotVO)vmSnapshot;
+        UserVmVO userVm = userVmDao.findById(vmSnapshot.getVmId());
+        try {
+            vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshotVO, VMSnapshot.Event.RevertRequested);
+        } catch (NoTransitionException e) {
+            throw new CloudRuntimeException(e.getMessage());
+        }
+
+        boolean result = false;
+        try {
+            VMSnapshotVO snapshot = vmSnapshotDao.findById(vmSnapshotVO.getId());
+            List<VolumeObjectTO> volumeTOs = vmSnapshotHelper.getVolumeTOList(userVm.getId());
+            String vmInstanceName = userVm.getInstanceName();
+            VMSnapshotTO parent = vmSnapshotHelper.getSnapshotWithParents(snapshot).getParent();
+
+            VMSnapshotTO vmSnapshotTO = new VMSnapshotTO(snapshot.getId(), snapshot.getName(), snapshot.getType(),
+                    snapshot.getCreated().getTime(), snapshot.getDescription(), snapshot.getCurrent(), parent);
+            Long hostId = vmSnapshotHelper.pickRunningHost(vmSnapshot.getVmId());
+            GuestOSVO guestOS = guestOSDao.findById(userVm.getGuestOSId());
+            RevertToVMSnapshotCommand revertToSnapshotCommand = new RevertToVMSnapshotCommand(vmInstanceName, vmSnapshotTO, volumeTOs, guestOS.getDisplayName());
+
+            RevertToVMSnapshotAnswer answer = (RevertToVMSnapshotAnswer) agentMgr.send(hostId, revertToSnapshotCommand);
+            if (answer != null && answer.getResult()) {
+                processAnswer(vmSnapshotVO, userVm, answer, hostId);
+                result = true;
+            } else {
+                String errMsg = "Revert VM: " + userVm.getInstanceName() + " to snapshot: "+ vmSnapshotVO.getName() + " failed";
+                if(answer != null && answer.getDetails() != null)
+                    errMsg = errMsg + " due to " + answer.getDetails();
+                s_logger.error(errMsg);
+                throw new CloudRuntimeException(errMsg);
+            }
+        } catch (OperationTimedoutException e) {
+            s_logger.debug("Failed to revert vm snapshot", e);
+            throw new CloudRuntimeException(e.getMessage());
+        } catch (AgentUnavailableException e) {
+            s_logger.debug("Failed to revert vm snapshot", e);
+            throw new CloudRuntimeException(e.getMessage());
+        } finally {
+            if (!result) {
+                try {
+                    vmSnapshotHelper.vmSnapshotStateTransitTo(vmSnapshot, VMSnapshot.Event.OperationFailed);
+                } catch (NoTransitionException e1) {
+                    s_logger.error("Cannot set vm snapshot state due to: " + e1.getMessage());
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public boolean canHandle(VMSnapshot vmSnapshot) {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java
new file mode 100644
index 0000000..1437f80
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelper.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.vmsnapshot;
+
+import com.cloud.agent.api.VMSnapshotTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.vm.snapshot.VMSnapshot;
+import com.cloud.vm.snapshot.VMSnapshotVO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+
+import java.util.List;
+
+public interface VMSnapshotHelper {
+  boolean vmSnapshotStateTransitTo(VMSnapshot vsnp, VMSnapshot.Event event) throws NoTransitionException;
+
+    Long pickRunningHost(Long vmId);
+
+    List<VolumeObjectTO> getVolumeTOList(Long vmId);
+
+    VMSnapshotTO getSnapshotWithParents(VMSnapshotVO snapshot);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6ce66e5/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java
new file mode 100644
index 0000000..320a59c
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/vmsnapshot/VMSnapshotHelperImpl.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.vmsnapshot;
+
+import com.cloud.agent.api.VMSnapshotTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.snapshot.VMSnapshot;
+import com.cloud.vm.snapshot.VMSnapshotVO;
+import com.cloud.vm.snapshot.dao.VMSnapshotDao;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class VMSnapshotHelperImpl implements VMSnapshotHelper {
+    @Inject
+    VMSnapshotDao _vmSnapshotDao;
+    @Inject
+    UserVmDao userVmDao;
+    @Inject
+    HostDao hostDao;
+    @Inject
+    VolumeDao volumeDao;
+    @Inject
+    PrimaryDataStoreDao primaryDataStoreDao;
+    @Inject
+    VolumeDataFactory volumeDataFactory;
+
+    StateMachine2<VMSnapshot.State, VMSnapshot.Event, VMSnapshot> _vmSnapshottateMachine ;
+    public VMSnapshotHelperImpl() {
+        _vmSnapshottateMachine   = VMSnapshot.State.getStateMachine();
+    }
+    @Override
+    public boolean vmSnapshotStateTransitTo(VMSnapshot vsnp, VMSnapshot.Event event) throws NoTransitionException {
+        return _vmSnapshottateMachine.transitTo(vsnp, event, null, _vmSnapshotDao);
+    }
+
+    @Override
+    public Long pickRunningHost(Long vmId) {
+        UserVmVO vm = userVmDao.findById(vmId);
+        // use VM's host if VM is running
+        if(vm.getState() == VirtualMachine.State.Running)
+            return vm.getHostId();
+
+        // check if lastHostId is available
+        if(vm.getLastHostId() != null){
+            HostVO lastHost =  hostDao.findById(vm.getLastHostId());
+            if(lastHost.getStatus() == com.cloud.host.Status.Up && !lastHost.isInMaintenanceStates())
+                return lastHost.getId();
+        }
+
+        List<VolumeVO> listVolumes = volumeDao.findByInstance(vmId);
+        if (listVolumes == null || listVolumes.size() == 0) {
+            throw new InvalidParameterValueException("vmInstance has no volumes");
+        }
+        VolumeVO volume = listVolumes.get(0);
+        Long poolId = volume.getPoolId();
+        if (poolId == null) {
+            throw new InvalidParameterValueException("pool id is not found");
+        }
+        StoragePoolVO storagePool = primaryDataStoreDao.findById(poolId);
+        if (storagePool == null) {
+            throw new InvalidParameterValueException("storage pool is not found");
+        }
+        List<HostVO> listHost = hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, storagePool.getClusterId(), storagePool.getPodId(),
+                storagePool.getDataCenterId(), null);
+        if (listHost == null || listHost.size() == 0) {
+            throw new InvalidParameterValueException("no host in up state is found");
+        }
+        return listHost.get(0).getId();
+    }
+
+    @Override
+    public List<VolumeObjectTO> getVolumeTOList(Long vmId) {
+        List<VolumeObjectTO> volumeTOs = new ArrayList<VolumeObjectTO>();
+        List<VolumeVO> volumeVos = volumeDao.findByInstance(vmId);
+        VolumeInfo volumeInfo = null;
+        for (VolumeVO volume : volumeVos) {
+            volumeInfo = volumeDataFactory.getVolume(volume.getId());
+
+            volumeTOs.add((VolumeObjectTO)volumeInfo.getTO());
+        }
+        return volumeTOs;
+    }
+
+
+    private VMSnapshotTO convert2VMSnapshotTO(VMSnapshotVO vo) {
+        return new VMSnapshotTO(vo.getId(), vo.getName(),  vo.getType(), vo.getCreated().getTime(), vo.getDescription(),
+                vo.getCurrent(), null);
+    }
+
+    @Override
+    public VMSnapshotTO getSnapshotWithParents(VMSnapshotVO snapshot) {
+        Map<Long, VMSnapshotVO> snapshotMap = new HashMap<Long, VMSnapshotVO>();
+        List<VMSnapshotVO> allSnapshots = _vmSnapshotDao.findByVm(snapshot.getVmId());
+        for (VMSnapshotVO vmSnapshotVO : allSnapshots) {
+            snapshotMap.put(vmSnapshotVO.getId(), vmSnapshotVO);
+        }
+
+        VMSnapshotTO currentTO = convert2VMSnapshotTO(snapshot);
+        VMSnapshotTO result = currentTO;
+        VMSnapshotVO current = snapshot;
+        while (current.getParent() != null) {
+            VMSnapshotVO parent = snapshotMap.get(current.getParent());
+            currentTO.setParent(convert2VMSnapshotTO(parent));
+            current = snapshotMap.get(current.getParent());
+            currentTO = currentTO.getParent();
+        }
+        return result;
+    }
+
+}