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/02/21 20:15:16 UTC

[39/45] git commit: refs/heads/storage_refactor - refactor snapshot, move existing snapshot code into its own snapshotstrategy

refactor snapshot, move existing snapshot code into its own snapshotstrategy


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

Branch: refs/heads/storage_refactor
Commit: 222c99d82a37d0f0921c167663d3b55a7f6bd891
Parents: 36efd77
Author: Edison Su <ed...@citrix.com>
Authored: Wed Feb 13 11:11:45 2013 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Thu Feb 21 10:03:39 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/storage/Snapshot.java            |   18 +-
 core/src/com/cloud/storage/SnapshotVO.java         |    2 +-
 .../subsystem/api/storage/CopyCommandResult.java   |   10 +-
 .../subsystem/api/storage/DataObjectInStore.java   |    1 +
 .../subsystem/api/storage/DataStoreDriver.java     |    1 +
 .../api/storage/ObjectInDataStoreStateMachine.java |    1 +
 .../api/storage/PrimaryDataStoreDriver.java        |   26 +
 .../engine/subsystem/api/storage/SnapshotInfo.java |    6 +-
 .../subsystem/api/storage/SnapshotStrategy.java    |   10 +
 .../engine/subsystem/api/storage/VolumeInfo.java   |    3 +
 .../subsystem/api/storage/VolumeService.java       |    2 +
 .../driver/AncientImageDataStoreDriverImpl.java    |   69 ++-
 .../driver/DefaultImageDataStoreDriverImpl.java    |    7 +
 .../image/motion/DefaultImageMotionStrategy.java   |    6 +-
 .../storage/test/MockStorageMotionStrategy.java    |    2 +-
 .../storage/snapshot/SnapshotDataFactoryImpl.java  |   34 +-
 .../storage/snapshot/SnapshotObject.java           |  169 +++-
 .../storage/snapshot/SnapshotServiceImpl.java      |    6 +
 .../snapshot/SnapshotStateMachineManager.java      |    9 +
 .../snapshot/SnapshotStateMachineManagerImpl.java  |   37 +
 .../snapshot/strategy/AncientSnasphotStrategy.java |  562 ++++++++++++
 .../snapshot/strategy/HypervisorBasedSnapshot.java |   44 -
 .../snapshot/strategy/StorageBasedSnapshot.java    |   42 -
 .../datastore/PrimaryDataStoreProviderManager.java |    2 +-
 .../storage/motion/AncientDataMotionStrategy.java  |  148 +++-
 .../storage/snapshot/SnapshotEntityImpl.java       |   13 +-
 .../storage/snapshot/SnapshotStrategy.java         |   25 -
 .../storage/volume/PrimaryDataStoreDriver.java     |   29 -
 .../storage/datastore/DefaultPrimaryDataStore.java |    2 +-
 .../driver/AncientPrimaryDataStoreDriverImpl.java  |  490 ++++++-----
 .../driver/DefaultPrimaryDataStoreDriverImpl.java  |   23 +-
 ...DefaultPrimaryDataStoreProviderManagerImpl.java |    2 +-
 .../AncientPrimaryDataStoreProviderImpl.java       |    2 +-
 .../DefaultPrimaryDatastoreProviderImpl.java       |    2 +-
 .../cloudstack/storage/volume/VolumeObject.java    |   17 +
 .../storage/volume/VolumeServiceImpl.java          |  104 ++-
 .../driver/SolidfirePrimaryDataStoreDriver.java    |   22 +-
 server/src/com/cloud/api/ApiDBUtils.java           |    2 +-
 server/src/com/cloud/api/ApiResponseHelper.java    |    2 +-
 server/src/com/cloud/configuration/Config.java     |    3 +-
 .../src/com/cloud/storage/ResizeVolumePayload.java |   14 +
 server/src/com/cloud/storage/VolumeManager.java    |    4 +-
 .../src/com/cloud/storage/VolumeManagerImpl.java   |   92 +--
 server/src/com/cloud/storage/dao/SnapshotDao.java  |    2 +-
 .../src/com/cloud/storage/dao/SnapshotDaoImpl.java |    2 +-
 .../storage/listener/SnapshotStateListener.java    |   28 +-
 .../cloud/storage/snapshot/SnapshotManager.java    |   95 +--
 .../storage/snapshot/SnapshotManagerImpl.java      |  694 +++------------
 48 files changed, 1656 insertions(+), 1230 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/api/src/com/cloud/storage/Snapshot.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java
index 3f6b8f5..9c2217e 100644
--- a/api/src/com/cloud/storage/Snapshot.java
+++ b/api/src/com/cloud/storage/Snapshot.java
@@ -61,22 +61,6 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
         BackedUp,
         Error;
 
-        private final static StateMachine2<State, Event, Snapshot> s_fsm = new StateMachine2<State, Event, Snapshot>();
-
-        public static StateMachine2<State, Event, Snapshot> getStateMachine() {
-            return s_fsm;
-        }
-
-        static {
-            s_fsm.addTransition(null, Event.CreateRequested, Creating);
-            s_fsm.addTransition(Creating, Event.OperationSucceeded, CreatedOnPrimary);
-            s_fsm.addTransition(Creating, Event.OperationNotPerformed, BackedUp);
-            s_fsm.addTransition(Creating, Event.OperationFailed, Error);
-            s_fsm.addTransition(CreatedOnPrimary, Event.BackupToSecondary, BackingUp);
-            s_fsm.addTransition(BackingUp, Event.OperationSucceeded, BackedUp);
-            s_fsm.addTransition(BackingUp, Event.OperationFailed, Error);
-        }
-
         public String toString() {
             return this.name();
         }
@@ -107,7 +91,7 @@ public interface Snapshot extends ControlledEntity, Identity, InternalIdentity,
 
     Date getCreated();
 
-    Type getType();
+    Type getRecurringType();
 
     State getState();
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/core/src/com/cloud/storage/SnapshotVO.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/SnapshotVO.java b/core/src/com/cloud/storage/SnapshotVO.java
index f44212f..1bb0854 100644
--- a/core/src/com/cloud/storage/SnapshotVO.java
+++ b/core/src/com/cloud/storage/SnapshotVO.java
@@ -175,7 +175,7 @@ public class SnapshotVO implements Snapshot {
     }
 
     @Override
-    public Type getType() {
+    public Type getRecurringType() {
         if (snapshotType < 0 || snapshotType >= Type.values().length) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
index 100fd4e..571a77c 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CopyCommandResult.java
@@ -18,14 +18,22 @@
  */
 package org.apache.cloudstack.engine.subsystem.api.storage;
 
+import com.cloud.agent.api.Answer;
+
 public class CopyCommandResult extends CommandResult {
     private final String path;
-    public CopyCommandResult(String path) {
+    private final Answer answer;
+    public CopyCommandResult(String path, Answer answer) {
         super();
         this.path = path;
+        this.answer = answer;
     }
     
     public String getPath() {
         return this.path;
     }
+    
+    public Answer getAnswer() {
+    	return this.answer;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
index 60dfb9f..32ea996 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectInStore.java
@@ -23,4 +23,5 @@ import com.cloud.utils.fsm.StateObject;
 
 public interface DataObjectInStore extends StateObject<ObjectInDataStoreStateMachine.State> {
     public String getInstallPath();
+    public void setInstallPath(String path);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
index 4aba9bf..cf5759b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
@@ -30,4 +30,5 @@ public interface DataStoreDriver {
     public void deleteAsync(DataObject data, AsyncCompletionCallback<CommandResult> callback);
     public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
     public boolean canCopy(DataObject srcData, DataObject destData);
+    public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
index af9974e..726ce08 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java
@@ -49,6 +49,7 @@ public interface ObjectInDataStoreStateMachine extends StateObject<ObjectInDataS
         OperationSuccessed,
         OperationFailed,
         CopyingRequested,
+        ResizeRequested,
         ExpungeRequested
         
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
new file mode 100644
index 0000000..78a1014
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+
+public interface PrimaryDataStoreDriver extends DataStoreDriver {
+    public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CreateCmdResult> callback);
+    public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
index 30cf182..b90404c 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotInfo.java
@@ -16,9 +16,13 @@
 // under the License.
 package org.apache.cloudstack.engine.subsystem.api.storage;
 
+import com.cloud.storage.Snapshot;
 
-public interface SnapshotInfo extends DataObject {
+
+public interface SnapshotInfo extends DataObject, Snapshot {
 	public SnapshotInfo getParent();
 	public SnapshotInfo getChild();
 	public VolumeInfo getBaseVolume();
+    Long getDataCenterId();
+    public Long getPrevSnapshotId();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
new file mode 100644
index 0000000..f854f6b
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotStrategy.java
@@ -0,0 +1,10 @@
+package org.apache.cloudstack.engine.subsystem.api.storage;
+
+
+public interface SnapshotStrategy {
+	public boolean canHandle(SnapshotInfo snapshot);
+	public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId);
+	public SnapshotInfo backupSnapshot(SnapshotInfo snapshot);
+	public boolean deleteSnapshot(SnapshotInfo snapshot);
+	public boolean revertSnapshot(SnapshotInfo snapshot);
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
index f2a3d5e..349325a 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
@@ -18,10 +18,13 @@
  */
 package org.apache.cloudstack.engine.subsystem.api.storage;
 
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.Volume;
 
 public interface VolumeInfo extends DataObject, Volume {
 	public boolean isAttachedVM();
 	public void addPayload(Object data);
 	public Object getpayload();
+	public HypervisorType getHypervisorType();
+	public Long getLastPoolId();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
index 58258eb..102c471 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java
@@ -74,5 +74,7 @@ public interface VolumeService {
     boolean destroyVolume(long volumeId) throws ConcurrentOperationException;
 
     AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store);
+    
+    AsyncCallFuture<VolumeApiResult> resize(VolumeInfo volume);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
index 2c19c7f..97ea6c4 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java
@@ -38,22 +38,30 @@ import org.apache.log4j.Logger;
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.DeleteSnapshotBackupCommand;
 import com.cloud.agent.api.storage.DeleteVolumeCommand;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.SwiftTO;
 import com.cloud.host.HostVO;
 import com.cloud.host.dao.HostDao;
 import com.cloud.storage.RegisterVolumePayload;
 import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.VMTemplateStorageResourceAssoc;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.VMTemplateZoneVO;
 import com.cloud.storage.VolumeHostVO;
 import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VMTemplateHostDao;
 import com.cloud.storage.dao.VMTemplateZoneDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.dao.VolumeHostDao;
 import com.cloud.storage.download.DownloadMonitor;
+import com.cloud.storage.s3.S3Manager;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
 import com.cloud.utils.exception.CloudRuntimeException;
 
 public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
@@ -69,7 +77,13 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
     @Inject VolumeDao volumeDao;
     @Inject VolumeHostDao volumeHostDao;
     @Inject HostDao hostDao;
+    @Inject SnapshotDao snapshotDao;
     @Inject AgentManager agentMgr;
+    @Inject SnapshotManager snapshotMgr;
+	@Inject
+    private SwiftManager _swiftMgr;
+    @Inject 
+    private S3Manager _s3Mgr; 
     @Override
     public String grantAccess(DataObject data, EndPoint ep) {
         // TODO Auto-generated method stub
@@ -158,6 +172,49 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
         
     }
     
+    private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
+    	Long snapshotId = data.getId();
+    	SnapshotVO snapshot = this.snapshotDao.findByIdIncludingRemoved(snapshotId);
+    	CommandResult result = new CommandResult();
+    	if (snapshot == null) {
+    		s_logger.debug("Destroying snapshot " + snapshotId + " backup failed due to unable to find snapshot ");
+    		result.setResult("Unable to find snapshot: " + snapshotId);
+    		callback.complete(result);
+    		return;
+    	}
+
+    	try {
+    		String secondaryStoragePoolUrl = this.snapshotMgr.getSecondaryStorageURL(snapshot);
+    		Long dcId = snapshot.getDataCenterId();
+    		Long accountId = snapshot.getAccountId();
+    		Long volumeId = snapshot.getVolumeId();
+
+    		String backupOfSnapshot = snapshot.getBackupSnapshotId();
+    		if (backupOfSnapshot == null) {
+    			callback.complete(result);
+    			return;
+    		}
+    		SwiftTO swift = _swiftMgr.getSwiftTO(snapshot.getSwiftId());
+    		S3TO s3 = _s3Mgr.getS3TO();
+
+    		DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(
+    				swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId,
+    				backupOfSnapshot, false);
+    		Answer answer = agentMgr.sendToSSVM(dcId, cmd);
+
+    		if ((answer != null) && answer.getResult()) {
+    			snapshot.setBackupSnapshotId(null);
+    			snapshotDao.update(snapshotId, snapshot);
+    		} else if (answer != null) {
+    			result.setResult(answer.getDetails());
+    		}
+    	} catch (Exception e) {
+    		s_logger.debug("failed to delete snapshot: " + snapshotId + ": " + e.toString());
+    		result.setResult(e.toString());
+    	}
+    	callback.complete(result);
+    }
+    
     @Override
     public void deleteAsync(DataObject data,
             AsyncCompletionCallback<CommandResult> callback) {
@@ -165,10 +222,9 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
             deleteVolume(data, callback);
         } else if (data.getType() == DataObjectType.TEMPLATE) {
             deleteTemplate(data, callback);
+        } else if (data.getType() == DataObjectType.SNAPSHOT) {
+        	deleteSnapshot(data, callback);
         }
-       
-
-       
     }
 
     @Override
@@ -184,4 +240,11 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver {
         return false;
     }
 
+	@Override
+	public void resize(DataObject data,
+			AsyncCompletionCallback<CreateCmdResult> callback) {
+		// TODO Auto-generated method stub
+		
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
index 1a506fa..3d46c73 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/DefaultImageDataStoreDriverImpl.java
@@ -116,4 +116,11 @@ public class DefaultImageDataStoreDriverImpl implements ImageDataStoreDriver {
         // TODO Auto-generated method stub
         
     }
+
+	@Override
+	public void resize(DataObject data,
+			AsyncCompletionCallback<CreateCmdResult> callback) {
+		// TODO Auto-generated method stub
+		
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
index 561c1cb..c49a521 100644
--- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
+++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java
@@ -101,7 +101,7 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
         DataStore destStore = destData.getDataStore();
         DataStore srcStore = srcData.getDataStore();
         EndPoint ep = selector.select(srcData, destData);
-        CopyCommandResult result = new CopyCommandResult("");
+        CopyCommandResult result = new CopyCommandResult("", null);
         if (ep == null) {
             result.setResult("can't find end point");
             callback.complete(result);
@@ -125,12 +125,12 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy {
         AsyncCompletionCallback<CopyCommandResult> parentCall = context.getParentCallback();
         Answer answer = (Answer)callback.getResult();
         if (!answer.getResult()) {
-            CopyCommandResult result = new CopyCommandResult("");
+            CopyCommandResult result = new CopyCommandResult("", null);
             result.setResult(answer.getDetails());
             parentCall.complete(result);
         } else {
             CopyCmdAnswer ans = (CopyCmdAnswer)answer;
-            CopyCommandResult result = new CopyCommandResult(ans.getPath());
+            CopyCommandResult result = new CopyCommandResult(ans.getPath(), null);
             parentCall.complete(result);
         }
         return null;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
index e2e8f94..b619ee9 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java
@@ -34,7 +34,7 @@ public class MockStorageMotionStrategy implements DataMotionStrategy {
     @Override
     public Void copyAsync(DataObject srcData, DataObject destData,
             AsyncCompletionCallback<CopyCommandResult> callback) {
-        CopyCommandResult result = new CopyCommandResult("something");
+        CopyCommandResult result = new CopyCommandResult("something", null);
         callback.complete(result);
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
index 0953209..5af5260 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotDataFactoryImpl.java
@@ -25,39 +25,55 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 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.DataStoreRole;
 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.VolumeDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotDao2;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotVO;
 import org.springframework.stereotype.Component;
 
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+
 @Component
 public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
     @Inject
-    SnapshotDao2 snapshotDao;
+    SnapshotDao snapshotDao;
     @Inject
     ObjectInDataStoreManager objMap;
     @Inject
     DataStoreManager storeMgr;
+    @Inject
+    VolumeDataFactory volumeFactory;
     @Override
     public SnapshotInfo getSnapshot(long snapshotId, DataStore store) {
-        SnapshotVO snapshot = snapshotDao.findById(snapshotId);
+        SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
         DataObjectInStore obj = objMap.findObject(snapshot.getUuid(), DataObjectType.SNAPSHOT, store.getUuid(), store.getRole());
         if (obj == null) {
             return null;
         }
-        SnapshotObject so = new SnapshotObject(snapshot, store);
+        SnapshotObject so =  SnapshotObject.getSnapshotObject(snapshot, store);
         return so;
     }
     @Override
     public SnapshotInfo getSnapshot(long snapshotId) {
-        // TODO Auto-generated method stub
-        return null;
+    	SnapshotVO snapshot = snapshotDao.findByIdIncludingRemoved(snapshotId);
+    	SnapshotObject so = null;
+    	if (snapshot.getState() == Snapshot.State.BackedUp) {
+    		DataStore store = objMap.findStore(snapshot.getUuid(), DataObjectType.SNAPSHOT, DataStoreRole.Image);
+    		so =  SnapshotObject.getSnapshotObject(snapshot, store);
+    	} else {
+    		VolumeInfo volume = this.volumeFactory.getVolume(snapshot.getVolumeId());
+    		so = SnapshotObject.getSnapshotObject(snapshot, volume.getDataStore());
+    	}
+    	return so;
     }
+    
     @Override
     public SnapshotInfo getSnapshot(DataObject obj, DataStore store) {
-        // TODO Auto-generated method stub
-        return null;
+        throw new CloudRuntimeException("not implemented yet");
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index d9fc8aa..a82be6d 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -18,21 +18,54 @@
  */
 package org.apache.cloudstack.storage.snapshot;
 
+import java.util.Date;
+
+import javax.inject.Inject;
+
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+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.disktype.DiskFormat;
-import org.apache.cloudstack.storage.snapshot.db.SnapshotVO;
+import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.log4j.Logger;
+
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.component.ComponentContext;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.fsm.NoTransitionException;
 
 public class SnapshotObject implements SnapshotInfo {
+	private static final Logger s_logger = Logger.getLogger(SnapshotObject.class);
     private SnapshotVO snapshot;
     private DataStore store;
-
-    public SnapshotObject(SnapshotVO snapshot, DataStore store) {
-        this.snapshot = snapshot;
-        this.store = store;
+    @Inject
+    protected SnapshotDao snapshotDao; 
+    @Inject
+    protected VolumeDao volumeDao;
+    @Inject protected VolumeDataFactory volFactory;
+    @Inject protected SnapshotStateMachineManager stateMachineMgr;
+    @Inject
+    ObjectInDataStoreManager ojbectInStoreMgr;
+    protected SnapshotObject() {
+      
+    }
+    
+    protected void configure(SnapshotVO snapshot, DataStore store) {
+    	this.snapshot = snapshot;
+    	this.store = store;
+    }
+    
+    public static SnapshotObject getSnapshotObject(SnapshotVO snapshot, DataStore store) {
+    	SnapshotObject snapObj = ComponentContext.inject(SnapshotObject.class);
+    	snapObj.configure(snapshot, store);
+    	return snapObj;
     }
 
     public DataStore getStore() {
@@ -53,56 +86,138 @@ public class SnapshotObject implements SnapshotInfo {
 
     @Override
     public VolumeInfo getBaseVolume() {
-        // TODO Auto-generated method stub
-        return null;
+        return volFactory.getVolume(this.snapshot.getVolumeId());
     }
 
     @Override
     public long getId() {
-        // TODO Auto-generated method stub
-        return 0;
+       return this.snapshot.getId();
     }
 
     @Override
     public String getUri() {
-        // TODO Auto-generated method stub
-        return null;
+        return this.snapshot.getUuid();
     }
 
     @Override
     public DataStore getDataStore() {
-        // TODO Auto-generated method stub
-        return null;
+        return this.store;
     }
 
     @Override
     public Long getSize() {
-        // TODO Auto-generated method stub
-        return 0L;
+    	return this.getSize();
     }
 
     @Override
     public DataObjectType getType() {
-        // TODO Auto-generated method stub
-        return null;
+    	return DataObjectType.SNAPSHOT;
     }
 
     @Override
     public DiskFormat getFormat() {
-        // TODO Auto-generated method stub
         return null;
     }
 
     @Override
     public String getUuid() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void processEvent(Event event) {
-        // TODO Auto-generated method stub
-        
+        return this.snapshot.getUuid();
     }
 
+	@Override
+	public void processEvent(
+			ObjectInDataStoreStateMachine.Event event) {
+		try {
+			ojbectInStoreMgr.update(this, event);
+		} catch (Exception e) {
+			s_logger.debug("Failed to update state:" + e.toString());
+			throw new CloudRuntimeException("Failed to update state: " + e.toString());
+		}
+	}
+
+	@Override
+	public long getAccountId() {
+		return this.snapshot.getAccountId();
+	}
+
+	@Override
+	public long getVolumeId() {
+		return this.snapshot.getVolumeId();
+	}
+
+	@Override
+	public String getPath() {
+		return this.snapshot.getPath();
+	}
+	
+	public void setPath(String path) {
+		this.snapshot.setPath(path);
+	}
+
+	@Override
+	public String getName() {
+		return this.snapshot.getName();
+	}
+
+	@Override
+	public Date getCreated() {
+		return this.snapshot.getCreated();
+	}
+
+	@Override
+	public Type getRecurringType() {
+		return this.snapshot.getRecurringType();
+	}
+
+	@Override
+	public State getState() {
+		return this.snapshot.getState();
+	}
+
+	@Override
+	public HypervisorType getHypervisorType() {
+		return this.snapshot.getHypervisorType();
+	}
+
+	@Override
+	public boolean isRecursive() {
+		return this.snapshot.isRecursive();
+	}
+
+	@Override
+	public short getsnapshotType() {
+		return this.snapshot.getsnapshotType();
+	}
+
+	@Override
+	public long getDomainId() {
+		return this.snapshot.getDomainId();
+	}
+	
+	public void setPrevSnapshotId(Long id) {
+		this.snapshot.setPrevSnapshotId(id);
+	}
+
+	@Override
+	public Long getDataCenterId() {
+		return this.snapshot.getDataCenterId();
+	}
+	
+	public void processEvent(Snapshot.Event event)
+			throws NoTransitionException {
+		stateMachineMgr.processEvent(this.snapshot, event);
+	}
+
+	@Override
+	public Long getPrevSnapshotId() {
+		return this.snapshot.getPrevSnapshotId();
+	}
+	
+	public void setBackupSnapshotId(String id) {
+		this.snapshot.setBackupSnapshotId(id);
+	}
+	
+	public String getBackupSnapshotId() {
+		return this.snapshot.getBackupSnapshotId();
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/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 bd3caf4..1b64fd0 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
@@ -22,6 +22,10 @@ import org.springframework.stereotype.Component;
 
 @Component
 public class SnapshotServiceImpl implements SnapshotService {
+	
+	public SnapshotServiceImpl() {
+		
+	}
 
 	@Override
 	public SnapshotEntity getSnapshotEntity(long snapshotId) {
@@ -46,5 +50,7 @@ public class SnapshotServiceImpl implements SnapshotService {
 		// TODO Auto-generated method stub
 		return false;
 	}
+	
+	
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
new file mode 100644
index 0000000..1c3ac28
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManager.java
@@ -0,0 +1,9 @@
+package org.apache.cloudstack.storage.snapshot;
+
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.utils.fsm.NoTransitionException;
+
+public interface SnapshotStateMachineManager {
+	public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
new file mode 100644
index 0000000..a20a2c8
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
@@ -0,0 +1,37 @@
+package org.apache.cloudstack.storage.snapshot;
+
+import javax.inject.Inject;
+
+import org.springframework.stereotype.Component;
+
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.Snapshot.Event;
+import com.cloud.storage.Snapshot.State;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.listener.SnapshotStateListener;
+import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.utils.fsm.StateMachine2;
+
+@Component
+public class SnapshotStateMachineManagerImpl implements
+SnapshotStateMachineManager {
+	private StateMachine2<State, Event, SnapshotVO> stateMachine = new StateMachine2<State, Event, SnapshotVO>();
+    @Inject
+    protected SnapshotDao snapshotDao; 
+	public SnapshotStateMachineManagerImpl() {
+		stateMachine.addTransition(null, Event.CreateRequested, Snapshot.State.Creating);
+		stateMachine.addTransition(Snapshot.State.Creating, Event.OperationSucceeded, Snapshot.State.CreatedOnPrimary);
+		stateMachine.addTransition(Snapshot.State.Creating, Event.OperationNotPerformed, Snapshot.State.BackedUp);
+		stateMachine.addTransition(Snapshot.State.Creating, Event.OperationFailed, Snapshot.State.Error);
+		stateMachine.addTransition(Snapshot.State.CreatedOnPrimary, Event.BackupToSecondary, Snapshot.State.BackingUp);
+		stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationSucceeded, Snapshot.State.BackedUp);
+		stateMachine.addTransition(Snapshot.State.BackingUp, Event.OperationFailed, Snapshot.State.Error);
+		
+		stateMachine.registerListener(new SnapshotStateListener());
+	}
+	
+	public void processEvent(SnapshotVO snapshot, Event event) throws NoTransitionException {
+		stateMachine.transitTo(snapshot, event, null, snapshotDao);
+	}
+} 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
new file mode 100644
index 0000000..2e3b90f
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/AncientSnasphotStrategy.java
@@ -0,0 +1,562 @@
+package org.apache.cloudstack.storage.snapshot.strategy;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
+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.DataObject;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
+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.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
+import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
+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.SnapshotStrategy;
+import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.framework.async.AsyncCallFuture;
+import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.framework.async.AsyncRpcConext;
+import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.cloudstack.storage.motion.DataMotionService;
+import org.apache.cloudstack.storage.snapshot.SnapshotObject;
+import org.apache.cloudstack.storage.snapshot.SnapshotStateMachineManager;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.DeleteSnapshotBackupCommand;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.SwiftTO;
+import com.cloud.configuration.Resource.ResourceType;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.event.EventTypes;
+import com.cloud.event.UsageEventUtils;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.HostVO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.StoragePool;
+import com.cloud.storage.VolumeManager;
+import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.StoragePoolDao;
+import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.s3.S3Manager;
+import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
+import com.cloud.utils.NumbersUtil;
+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.VirtualMachine.State;
+import com.cloud.vm.dao.UserVmDao;
+
+@Component
+public class AncientSnasphotStrategy implements SnapshotStrategy {
+	private static final Logger s_logger = Logger.getLogger(AncientSnasphotStrategy.class);
+	@Inject
+	protected VolumeDao _volsDao;
+	@Inject
+	protected UserVmDao _vmDao;
+	@Inject
+	protected StoragePoolDao _storagePoolDao;
+	@Inject
+	protected ClusterDao _clusterDao;
+	@Inject
+	protected SnapshotDao snapshotDao;
+	@Inject
+	private ResourceManager _resourceMgr;
+	@Inject
+	protected SnapshotDao _snapshotDao;
+	@Inject
+	protected SnapshotManager snapshotMgr;
+	@Inject
+	protected VolumeManager volumeMgr;
+	@Inject
+	private ConfigurationDao _configDao;
+	@Inject
+	protected SnapshotStateMachineManager stateMachineManager;
+	@Inject
+	private VolumeDao volumeDao;
+	@Inject
+	SnapshotDataFactory snapshotfactory;
+	@Inject
+	DataStoreManager dataStoreMgr;
+	@Inject
+	DataMotionService motionSrv;
+	@Inject
+	ObjectInDataStoreManager objInStoreMgr;
+
+
+	@Override
+	public boolean canHandle(SnapshotInfo snapshot) {
+		return true;
+	}
+
+	static private class CreateSnapshotContext<T> extends AsyncRpcConext<T> {
+		final VolumeInfo volume;
+		final SnapshotInfo snapshot;
+		final AsyncCallFuture<SnapshotResult> future;
+		public CreateSnapshotContext(AsyncCompletionCallback<T> callback, VolumeInfo volume,
+				SnapshotInfo snapshot,
+				AsyncCallFuture<SnapshotResult> future) {
+			super(callback);
+			this.volume = volume;
+			this.snapshot = snapshot;
+			this.future = future;
+		}
+	}
+	
+	static private class DeleteSnapshotContext<T> extends AsyncRpcConext<T> {
+		final SnapshotInfo snapshot;
+		final AsyncCallFuture<SnapshotResult> future;
+		public DeleteSnapshotContext(AsyncCompletionCallback<T> callback, SnapshotInfo snapshot,
+				AsyncCallFuture<SnapshotResult> future) {
+			super(callback);
+			this.snapshot = snapshot;
+			this.future = future;
+		}
+		
+	}
+
+	static private class CopySnapshotContext<T> extends AsyncRpcConext<T> {
+		final SnapshotInfo srcSnapshot;
+		final SnapshotInfo destSnapshot;
+		final AsyncCallFuture<SnapshotResult> future;
+		public CopySnapshotContext(AsyncCompletionCallback<T> callback,
+				SnapshotInfo srcSnapshot,
+				SnapshotInfo destSnapshot,
+				AsyncCallFuture<SnapshotResult> future) {
+			super(callback);
+			this.srcSnapshot = srcSnapshot;
+			this.destSnapshot = destSnapshot;
+			this.future = future;
+		}
+
+	}
+
+	protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher<AncientSnasphotStrategy, CreateCmdResult> callback, 
+			CreateSnapshotContext<CreateCmdResult> context) {
+		CreateCmdResult result = callback.getResult();
+		SnapshotObject snapshot = (SnapshotObject)context.snapshot;
+		VolumeInfo volume = context.volume;
+		AsyncCallFuture<SnapshotResult> future = context.future;
+		SnapshotResult snapResult = new SnapshotResult(snapshot);
+		if (result.isFailed()) {
+			s_logger.debug("create snapshot " + context.snapshot.getName() + " failed: " + result.getResult());
+			try {
+				snapshot.processEvent(Snapshot.Event.OperationFailed);
+			} catch (NoTransitionException nte) {
+				s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+			}
+
+
+			snapResult.setResult(result.getResult());
+			future.complete(snapResult);
+			return null;
+		}
+
+		try {
+			SnapshotVO preSnapshotVO = this.snapshotMgr.getParentSnapshot(volume, snapshot);
+			String preSnapshotPath = preSnapshotVO.getPath();
+			SnapshotVO snapshotVO = this.snapshotDao.findById(snapshot.getId());
+			// The snapshot was successfully created
+			if (preSnapshotPath != null && preSnapshotPath.equals(result.getPath())) {
+				// empty snapshot
+				s_logger.debug("CreateSnapshot: this is empty snapshot ");
+
+				snapshotVO.setPath(preSnapshotPath);
+				snapshotVO.setBackupSnapshotId(preSnapshotVO.getBackupSnapshotId());
+				snapshotVO.setSwiftId(preSnapshotVO.getSwiftId());
+				snapshotVO.setPrevSnapshotId(preSnapshotVO.getId());
+				snapshotVO.setSecHostId(preSnapshotVO.getSecHostId());
+				snapshot.processEvent(Snapshot.Event.OperationNotPerformed);
+			} else {
+				long preSnapshotId = 0;
+
+				if (preSnapshotVO != null && preSnapshotVO.getBackupSnapshotId() != null) {
+					preSnapshotId = preSnapshotVO.getId();
+					int _deltaSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("snapshot.delta.max"), SnapshotManager.DELTAMAX);
+					int deltaSnap = _deltaSnapshotMax;
+
+					int i;
+					for (i = 1; i < deltaSnap; i++) {
+						String prevBackupUuid = preSnapshotVO.getBackupSnapshotId();
+						// previous snapshot doesn't have backup, create a full snapshot
+						if (prevBackupUuid == null) {
+							preSnapshotId = 0;
+							break;
+						}
+						long preSSId = preSnapshotVO.getPrevSnapshotId();
+						if (preSSId == 0) {
+							break;
+						}
+						preSnapshotVO = _snapshotDao.findByIdIncludingRemoved(preSSId);
+					}
+					if (i >= deltaSnap) {
+						preSnapshotId = 0;
+					}
+				}
+
+				//If the volume is moved around, backup a full snapshot to secondary storage
+				if (volume.getLastPoolId() != null && !volume.getLastPoolId().equals(volume.getPoolId())) {
+					preSnapshotId = 0;
+					//TODO: fix this hack
+					VolumeVO volumeVO = this.volumeDao.findById(volume.getId());
+					volumeVO.setLastPoolId(volume.getPoolId());
+					this.volumeDao.update(volume.getId(), volumeVO);
+				}
+
+				snapshot.setPath(result.getPath());
+				snapshot.setPrevSnapshotId(preSnapshotId);
+
+				snapshot.processEvent(Snapshot.Event.OperationSucceeded);
+				snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(snapshot.getId()));
+			} 
+		} catch (Exception e) {
+			s_logger.debug("Failed to create snapshot: ", e);
+			snapResult.setResult(e.toString());
+		}
+
+		future.complete(snapResult);
+		return null;
+	} 
+
+	class SnapshotResult extends CommandResult {
+		SnapshotInfo snashot;
+		public SnapshotResult(SnapshotInfo snapshot) {
+			this.snashot = snapshot;
+		}
+	}
+
+	protected SnapshotInfo createSnapshotOnPrimary(VolumeInfo volume, Long snapshotId) {
+		SnapshotObject snapshot = (SnapshotObject)this.snapshotfactory.getSnapshot(snapshotId);
+		if (snapshot == null) {
+			throw new CloudRuntimeException("Can not find snapshot " + snapshotId);
+		}
+
+		try {
+			snapshot.processEvent(Snapshot.Event.CreateRequested);
+		} catch (NoTransitionException nte) {
+			s_logger.debug("Failed to update snapshot state due to " + nte.getMessage());
+			throw new CloudRuntimeException("Failed to update snapshot state due to " + nte.getMessage());
+		}
+		AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+
+		CreateSnapshotContext<CommandResult> context = new CreateSnapshotContext<CommandResult>(
+				null, volume, snapshot, future);
+		AsyncCallbackDispatcher<AncientSnasphotStrategy, CreateCmdResult> caller = AsyncCallbackDispatcher
+				.create(this);
+		caller.setCallback(
+				caller.getTarget().createSnapshotAsyncCallback(null, null))
+				.setContext(context);
+		PrimaryDataStoreDriver primaryStore = (PrimaryDataStoreDriver)volume.getDataStore().getDriver();
+
+		primaryStore.takeSnapshot(snapshot, caller);
+		SnapshotResult result;
+		try {
+			result = future.get();
+			if (result.isFailed()) {
+				s_logger.debug("Failed to create snapshot:" + result.getResult());
+				throw new CloudRuntimeException(result.getResult());
+			}
+			return result.snashot;
+		} catch (InterruptedException e) {
+			s_logger.debug("Failed to create snapshot", e);
+			throw new CloudRuntimeException("Failed to create snapshot", e);
+		} catch (ExecutionException e) {
+			s_logger.debug("Failed to create snapshot", e);
+			throw new CloudRuntimeException("Failed to create snapshot", e);
+		}
+
+	}
+
+	private boolean hostSupportSnapsthot(HostVO host) {
+		if (host.getHypervisorType() != HypervisorType.KVM) {
+			return true;
+		}
+		// Determine host capabilities
+		String caps = host.getCapabilities();
+
+		if (caps != null) {
+			String[] tokens = caps.split(",");
+			for (String token : tokens) {
+				if (token.contains("snapshot")) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+	protected boolean supportedByHypervisor(VolumeInfo volume) {
+		if (volume.getHypervisorType().equals(HypervisorType.KVM)) {
+			StoragePool storagePool = (StoragePool)volume.getDataStore();
+			ClusterVO cluster = _clusterDao.findById(storagePool.getClusterId());
+			List<HostVO> hosts = _resourceMgr.listAllHostsInCluster(cluster.getId());
+			if (hosts != null && !hosts.isEmpty()) {
+				HostVO host = hosts.get(0);
+				if (!hostSupportSnapsthot(host)) {
+					throw new CloudRuntimeException("KVM Snapshot is not supported on cluster: " + host.getId());
+				}
+			}
+		}
+
+		// if volume is attached to a vm in destroyed or expunging state; disallow
+		if (volume.getInstanceId() != null) {
+			UserVmVO userVm = _vmDao.findById(volume.getInstanceId());
+			if (userVm != null) {
+				if (userVm.getState().equals(State.Destroyed) || userVm.getState().equals(State.Expunging)) {
+					throw new CloudRuntimeException("Creating snapshot failed due to volume:" + volume.getId() + " is associated with vm:" + userVm.getInstanceName() + " is in "
+							+ userVm.getState().toString() + " state");
+				}
+
+				if(userVm.getHypervisorType() == HypervisorType.VMware || userVm.getHypervisorType() == HypervisorType.KVM) {
+					List<SnapshotVO> activeSnapshots = _snapshotDao.listByInstanceId(volume.getInstanceId(), Snapshot.State.Creating,  Snapshot.State.CreatedOnPrimary,  Snapshot.State.BackingUp);
+					if(activeSnapshots.size() > 1)
+						throw new CloudRuntimeException("There is other active snapshot tasks on the instance to which the volume is attached, please try again later");
+				}
+				
+				List<VMSnapshotVO> activeVMSnapshots = _vmSnapshotDao.listByInstanceId(userVm.getId(),
+                        VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging);
+                if (activeVMSnapshots.size() > 0) {
+                    throw new CloudRuntimeException(
+                            "There is other active vm snapshot tasks on the instance to which the volume is attached, please try again later");
+                }           
+			}
+		}
+
+		return true;
+	}
+
+	@Override
+	public SnapshotInfo takeSnapshot(VolumeInfo volume, Long snapshotId) {
+
+		supportedByHypervisor(volume);
+
+		SnapshotInfo snapshot = createSnapshotOnPrimary(volume, snapshotId);
+		return snapshot;
+	}
+
+	@Override
+	public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
+		SnapshotObject snapObj = (SnapshotObject)snapshot;
+		AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+		SnapshotResult result = new SnapshotResult(snapshot);
+		try {
+
+			snapObj.processEvent(Snapshot.Event.BackupToSecondary);
+
+			ZoneScope scope = new ZoneScope(snapshot.getDataCenterId());
+			List<DataStore> stores = this.dataStoreMgr.getImageStores(scope);
+			if (stores.size() != 1) {
+				throw new CloudRuntimeException("find out more than one image stores");
+			}
+
+			DataStore imageStore = stores.get(0);
+			SnapshotInfo snapshotOnImageStore = (SnapshotInfo)imageStore.create(snapshot);
+
+			snapshotOnImageStore.processEvent(Event.CreateOnlyRequested);
+			CopySnapshotContext<CommandResult> context = new CopySnapshotContext<CommandResult>(null, snapshot,
+					snapshotOnImageStore, future);
+			AsyncCallbackDispatcher<AncientSnasphotStrategy, CopyCommandResult> caller = AsyncCallbackDispatcher
+					.create(this);
+			caller.setCallback(
+					caller.getTarget().copySnapshotAsyncCallback(null, null))
+					.setContext(context);
+			this.motionSrv.copyAsync(snapshot, snapshotOnImageStore, caller);
+		} catch (Exception e) {
+			s_logger.debug("Failed to copy snapshot", e);
+			result.setResult("Failed to copy snapshot:" +e.toString());
+			future.complete(result);
+		}
+
+		try {
+			SnapshotResult res = future.get();
+			SnapshotInfo destSnapshot = res.snashot;
+			return destSnapshot;
+		} catch (InterruptedException e) {
+			s_logger.debug("failed copy snapshot", e);
+			throw new CloudRuntimeException("Failed to copy snapshot" , e);
+		} catch (ExecutionException e) {
+			s_logger.debug("Failed to copy snapshot", e);
+			throw new CloudRuntimeException("Failed to copy snapshot" , e);
+		}
+
+	}
+
+	protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<AncientSnasphotStrategy, CopyCommandResult> callback, 
+			CopySnapshotContext<CommandResult> context) {
+		CopyCommandResult result = callback.getResult();
+		SnapshotInfo destSnapshot = context.destSnapshot;
+		SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
+		AsyncCallFuture<SnapshotResult> future = context.future;
+		SnapshotResult snapResult = new SnapshotResult(destSnapshot);
+		if (result.isFailed()) {
+			snapResult.setResult(result.getResult());
+			future.complete(snapResult);
+			return null;
+		}
+
+		try {
+			BackupSnapshotAnswer answer = (BackupSnapshotAnswer)result.getAnswer();
+			
+			DataObjectInStore dataInStore =  objInStoreMgr.findObject(destSnapshot, destSnapshot.getDataStore());
+			dataInStore.setInstallPath(answer.getBackupSnapshotName());
+			objInStoreMgr.update(destSnapshot, Event.OperationSuccessed);
+			
+			srcSnapshot.processEvent(Snapshot.Event.OperationSucceeded);
+			snapResult = new SnapshotResult(this.snapshotfactory.getSnapshot(destSnapshot.getId()));
+			future.complete(snapResult);
+		} catch (Exception e) {
+			s_logger.debug("Failed to update snapshot state", e);
+			snapResult.setResult(e.toString());
+			future.complete(snapResult);
+		}
+		return null;
+	}
+
+	@DB
+	protected boolean destroySnapshotBackUp(SnapshotVO snapshot) {
+		DataStore store = objInStoreMgr.findStore(snapshot.getUuid(), DataObjectType.SNAPSHOT, DataStoreRole.Image);
+		if (store == null) {
+			s_logger.debug("Can't find snapshot" + snapshot.getId() + " backed up into image store");
+			return false;
+		}
+
+		try {
+			SnapshotInfo snapshotInfo = this.snapshotfactory.getSnapshot(snapshot.getId(), store);
+			snapshotInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
+			
+			AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+			DeleteSnapshotContext<CommandResult> context = new DeleteSnapshotContext<CommandResult>(null,
+					snapshotInfo, future);
+			AsyncCallbackDispatcher<AncientSnasphotStrategy, CommandResult> caller = AsyncCallbackDispatcher
+					.create(this);
+			caller.setCallback(
+					caller.getTarget().deleteSnapshotCallback(null, null))
+					.setContext(context);
+			
+			store.getDriver().deleteAsync(snapshotInfo, caller);
+			
+			SnapshotResult result = future.get();
+			if (result.isFailed()) {
+				s_logger.debug("Failed to delete snapsoht: " + result.getResult());
+			}
+			return result.isSuccess();
+		} catch (Exception e) {
+			s_logger.debug("Failed to delete snapshot", e);
+			return false;
+		}
+	}
+	
+	protected Void deleteSnapshotCallback(AsyncCallbackDispatcher<AncientSnasphotStrategy, CommandResult> callback, 
+			DeleteSnapshotContext<CommandResult> context) {
+		CommandResult result = callback.getResult();
+		AsyncCallFuture<SnapshotResult> future = context.future;
+		SnapshotInfo snapshot = context.snapshot;
+		if (result.isFailed()) {
+			s_logger.debug("delete snapshot failed" + result.getResult());
+			snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed);
+			SnapshotResult res = new SnapshotResult(context.snapshot);
+			future.complete(res);
+			return null;
+		}
+		snapshot.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed);
+		SnapshotResult res = new SnapshotResult(context.snapshot);
+		future.complete(res);
+		return null;
+	}
+
+	@Override
+	public boolean deleteSnapshot(SnapshotInfo snapInfo) {
+		Long snapshotId = snapInfo.getId();
+		SnapshotObject snapshot = (SnapshotObject)snapInfo;
+
+		if (!Snapshot.State.BackedUp.equals(snapshot.getState())) {
+			throw new InvalidParameterValueException("Can't delete snapshotshot " + snapshotId + " due to it is not in BackedUp Status");
+		}
+		
+		if (s_logger.isDebugEnabled()) {
+			s_logger.debug("Calling deleteSnapshot for snapshotId: " + snapshotId);
+		}
+		SnapshotVO lastSnapshot = null;
+		if (snapshot.getBackupSnapshotId() != null) {
+			List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(snapshot.getVolumeId(), snapshot.getBackupSnapshotId());
+			if (snaps != null && snaps.size() > 1) {
+				snapshot.setBackupSnapshotId(null);
+				SnapshotVO snapshotVO = this._snapshotDao.findById(snapshotId);
+				_snapshotDao.update(snapshot.getId(), snapshotVO);
+			}
+		}
+		
+		_snapshotDao.remove(snapshotId);
+
+		long lastId = snapshotId;
+		boolean destroy = false;
+		while (true) {
+			lastSnapshot = _snapshotDao.findNextSnapshot(lastId);
+			if (lastSnapshot == null) {
+				// if all snapshots after this snapshot in this chain are removed, remove those snapshots.
+				destroy = true;
+				break;
+			}
+			if (lastSnapshot.getRemoved() == null) {
+				// if there is one child not removed, then can not remove back up snapshot.
+				break;
+			}
+			lastId = lastSnapshot.getId();
+		}
+		if (destroy) {
+			lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
+			while (lastSnapshot.getRemoved() != null) {
+				String BackupSnapshotId = lastSnapshot.getBackupSnapshotId();
+				if (BackupSnapshotId != null) {
+					List<SnapshotVO> snaps = _snapshotDao.listByBackupUuid(lastSnapshot.getVolumeId(), BackupSnapshotId);
+					if (snaps != null && snaps.size() > 1) {
+						lastSnapshot.setBackupSnapshotId(null);
+						_snapshotDao.update(lastSnapshot.getId(), lastSnapshot);
+					} else {
+						if (destroySnapshotBackUp(lastSnapshot)) {
+
+						} else {
+							s_logger.debug("Destroying snapshot backup failed " + lastSnapshot);
+							break;
+						}
+					}
+				}
+				lastId = lastSnapshot.getPrevSnapshotId();
+				if (lastId == 0) {
+					break;
+				}
+				lastSnapshot = _snapshotDao.findByIdIncludingRemoved(lastId);
+			}
+		}
+		return true;
+
+	}
+
+	@Override
+	public boolean revertSnapshot(SnapshotInfo snapshot) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
deleted file mode 100644
index 8ef0927..0000000
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/HypervisorBasedSnapshot.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.snapshot.strategy;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.storage.snapshot.SnapshotStrategy;
-import org.springframework.stereotype.Component;
-
-@Component
-public class HypervisorBasedSnapshot implements SnapshotStrategy {
-
-	@Override
-	public boolean takeSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean revertSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean deleteSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
deleted file mode 100644
index 7af395a..0000000
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/strategy/StorageBasedSnapshot.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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.snapshot.strategy;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.storage.snapshot.SnapshotStrategy;
-
-public class StorageBasedSnapshot implements SnapshotStrategy {
-
-	@Override
-	public boolean takeSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean revertSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean deleteSnapshot(SnapshotInfo snapshot) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
index 664c2d1..d1c26e1 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreProviderManager.java
@@ -19,7 +19,7 @@
 package org.apache.cloudstack.storage.datastore;
 
 import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
-import org.apache.cloudstack.storage.volume.PrimaryDataStoreDriver;
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
 
 
 public interface PrimaryDataStoreProviderManager {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index ed3ca6a..c067a1b 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -28,6 +28,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@@ -36,6 +37,8 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.BackupSnapshotCommand;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
 import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
@@ -47,7 +50,9 @@ 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.to.S3TO;
 import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.SwiftTO;
 import com.cloud.configuration.Config;
 import com.cloud.configuration.dao.ConfigurationDao;
 import com.cloud.exception.StorageUnavailableException;
@@ -72,7 +77,9 @@ import com.cloud.storage.dao.VMTemplateHostDao;
 import com.cloud.storage.dao.VMTemplatePoolDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.storage.dao.VolumeHostDao;
+import com.cloud.storage.s3.S3Manager;
 import com.cloud.storage.snapshot.SnapshotManager;
+import com.cloud.storage.swift.SwiftManager;
 import com.cloud.template.TemplateManager;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.db.DB;
@@ -112,6 +119,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     @Inject VMTemplatePoolDao templatePoolDao;
     @Inject
     VolumeManager volumeMgr;
+    @Inject
+    private SwiftManager _swiftMgr;
+    @Inject 
+    private S3Manager _s3Mgr;
 
     @Override
     public boolean canHandle(DataObject srcData, DataObject destData) {
@@ -120,7 +131,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     }
 
     @DB
-    protected String copyVolumeFromImage(DataObject srcData, DataObject destData) {
+    protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) {
         String value = configDao.getValue(Config.RecreateSystemVmEnabled.key());
         int _copyvolumewait = NumbersUtil.parseInt(value,
                 Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
@@ -162,16 +173,17 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
         this.volDao.update(vol.getId(), vol);
         volumeHostDao.remove(volumeHostVO.getId());
         txn.commit();
-        return errMsg;
+        return cvAnswer;
     }
 
-    private void copyTemplate(DataObject srcData, DataObject destData) {
+    private Answer copyTemplate(DataObject srcData, DataObject destData) {
         VMTemplateVO template = this.templateDao.findById(srcData.getId());
         templateMgr.prepareTemplateForCreate(template,
                 (StoragePool) destData.getDataStore());
+        return null;
     }
 
-    protected String copyFromSnapshot(DataObject snapObj, DataObject volObj) {
+    protected Answer copyFromSnapshot(DataObject snapObj, DataObject volObj) {
         SnapshotVO snapshot = this.snapshotDao.findById(snapObj.getId());
         StoragePool pool = (StoragePool) volObj.getDataStore();
         String vdiUUID = null;
@@ -227,8 +239,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
                 if ((answer != null) && answer.getResult()) {
                     snapshotDao.updateSnapshotVersion(volumeId, "2.1", "2.2");
                 } else {
-                    return "Unable to upgrade snapshot from 2.1 to 2.2 for "
-                            + snapshot.getId();
+                    throw new CloudRuntimeException("Unable to upgrade snapshot from 2.1 to 2.2 for "
+                            + snapshot.getId());
                 }
             }
         }
@@ -277,11 +289,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
                 snapshotMgr.deleteSnapshotsDirForVolume(
                         secondaryStoragePoolUrl, dcId, accountId, volumeId);
             }
-            snapshotDao.unlockFromLockTable(snapshotId.toString());
         }
     }
     
-    protected String cloneVolume(DataObject template, DataObject volume) {
+    protected Answer cloneVolume(DataObject template, DataObject volume) {
         VolumeInfo volInfo = (VolumeInfo)volume;
         DiskOfferingVO offering = diskOfferingDao.findById(volInfo.getDiskOfferingId());
         VMTemplateStoragePoolVO  tmpltStoredOn =  templatePoolDao.findByPoolTemplate(template.getDataStore().getId(), template.getId());
@@ -298,8 +309,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
             answer = storagMgr.sendToPool(pool, null, cmd);
         } catch (StorageUnavailableException e) {
             s_logger.debug("Failed to send to storage pool", e);
-            errMsg = e.toString();
-            return errMsg;
+            throw new CloudRuntimeException("Failed to send to storage pool", e);
         }
         
         if (answer.getResult()) {
@@ -327,10 +337,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
             errMsg = answer.getDetails();
         }
         
-        return errMsg;
+        return answer;
     }
     
-    protected String copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
+    protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
         VolumeInfo volume = (VolumeInfo)srcData;
         VolumeInfo destVolume = (VolumeInfo)destData;
         String secondaryStorageURL = this.templateMgr.getSecondaryStorageURL(volume
@@ -380,41 +390,45 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
         VolumeVO destVol = this.volDao.findById(destVolume.getId());
         destVol.setPath(cvAnswer.getVolumePath());
         this.volDao.update(destVol.getId(), destVol);
-        return null;
+        return cvAnswer;
     }
 
     @Override
     public Void copyAsync(DataObject srcData, DataObject destData,
             AsyncCompletionCallback<CopyCommandResult> callback) {
+        Answer answer = null;
         String errMsg = null;
         try {
             if (destData.getType() == DataObjectType.VOLUME
                     && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Image) {
-                errMsg = copyVolumeFromImage(srcData, destData);
+            	answer = copyVolumeFromImage(srcData, destData);
             } else if (destData.getType() == DataObjectType.TEMPLATE
                     && srcData.getType() == DataObjectType.TEMPLATE) {
-                copyTemplate(srcData, destData);
+            	answer = copyTemplate(srcData, destData);
             } else if (srcData.getType() == DataObjectType.SNAPSHOT
                     && destData.getType() == DataObjectType.VOLUME) {
-                errMsg = copyFromSnapshot(srcData, destData);
+            	answer = copyFromSnapshot(srcData, destData);
             } else if (srcData.getType() == DataObjectType.SNAPSHOT
                     && destData.getType() == DataObjectType.TEMPLATE) {
-                errMsg = createTemplateFromSnashot(srcData, destData);
+            	answer = createTemplateFromSnashot(srcData, destData);
             } else if (srcData.getType() == DataObjectType.VOLUME
                     && destData.getType() == DataObjectType.TEMPLATE) {
-                errMsg = createTemplateFromVolume(srcData, destData);
+            	answer = createTemplateFromVolume(srcData, destData);
             } else if (srcData.getType() == DataObjectType.TEMPLATE 
                     && destData.getType() == DataObjectType.VOLUME) {
-                errMsg = cloneVolume(srcData, destData);
+            	answer = cloneVolume(srcData, destData);
             } else if (destData.getType() == DataObjectType.VOLUME
                     && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
-                errMsg = copyVolumeBetweenPools(srcData, destData);
+            	answer = copyVolumeBetweenPools(srcData, destData);
+            } else if (srcData.getType() == DataObjectType.SNAPSHOT &&
+            		destData.getType() == DataObjectType.SNAPSHOT) {
+            	answer = copySnapshot(srcData, destData);
             }
         } catch (Exception e) {
             s_logger.debug("copy failed", e);
             errMsg = e.toString();
         }
-        CopyCommandResult result = new CopyCommandResult(null);
+        CopyCommandResult result = new CopyCommandResult(null, answer);
         result.setResult(errMsg);
         callback.complete(result);
 
@@ -422,7 +436,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     }
 
     @DB
-    protected String createTemplateFromSnashot(DataObject srcData,
+    protected Answer createTemplateFromSnashot(DataObject srcData,
             DataObject destData) {
         long snapshotId = srcData.getId();
         SnapshotVO snapshot = snapshotDao.findById(snapshotId);
@@ -538,7 +552,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     }
 
     @DB
-    protected String sendCommand(Command cmd, StoragePool pool,
+    protected Answer sendCommand(Command cmd, StoragePool pool,
             long templateId, long zoneId, long hostId) {
 
         CreatePrivateTemplateAnswer answer = null;
@@ -551,11 +565,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
                     e);
         }
 
-        if (answer == null) {
-            return "Failed to execute CreatePrivateTemplateFromSnapshotCommand";
-        } else if (!answer.getResult()) {
-            return "Failed to execute CreatePrivateTemplateFromSnapshotCommand"
-                    + answer.getDetails();
+        if (answer == null || !answer.getResult()) {
+        	return answer;
         }
 
         VMTemplateVO privateTemplate = templateDao.findById(templateId);
@@ -594,10 +605,10 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
         templateHostVO.setPhysicalSize(answer.getphysicalSize());
         templateHostDao.persist(templateHostVO);
         txn.close();
-        return null;
+        return answer;
     }
 
-    private String createTemplateFromVolume(DataObject srcObj,
+    private Answer createTemplateFromVolume(DataObject srcObj,
             DataObject destObj) {
         long volumeId = srcObj.getId();
         VolumeVO volume = this.volDao.findById(volumeId);
@@ -633,5 +644,82 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
         return sendCommand(cmd, pool, template.getId(), zoneId,
                 secondaryStorageHost.getId());
     }
+    
+    private HostVO getSecHost(long volumeId, long dcId) {
+        Long id = snapshotDao.getSecHostId(volumeId);
+        if ( id != null) { 
+            return hostDao.findById(id);
+        }
+        return this.templateMgr.getSecondaryStorageHost(dcId);
+    }
+    
+    protected Answer copySnapshot(DataObject srcObject, DataObject destObject) {
+    	SnapshotInfo srcSnapshot = (SnapshotInfo)srcObject;
+    	VolumeInfo baseVolume = srcSnapshot.getBaseVolume();
+    	 Long dcId = baseVolume.getDataCenterId();
+         Long accountId = baseVolume.getAccountId();
+         
+         HostVO secHost = getSecHost(baseVolume.getId(), baseVolume.getDataCenterId());
+         
+         String secondaryStoragePoolUrl = secHost.getStorageUrl();
+         String snapshotUuid = srcSnapshot.getPath();
+         // In order to verify that the snapshot is not empty,
+         // we check if the parent of the snapshot is not the same as the parent of the previous snapshot.
+         // We pass the uuid of the previous snapshot to the plugin to verify this.
+         SnapshotVO prevSnapshot = null;
+         String prevSnapshotUuid = null;
+         String prevBackupUuid = null;
+
+
+         SwiftTO swift = _swiftMgr.getSwiftTO();
+         S3TO s3 = _s3Mgr.getS3TO();
+         
+         long prevSnapshotId = srcSnapshot.getPrevSnapshotId();
+         if (prevSnapshotId > 0) {
+             prevSnapshot = snapshotDao.findByIdIncludingRemoved(prevSnapshotId);
+             if ( prevSnapshot.getBackupSnapshotId() != null && swift == null) {
+                 if (prevSnapshot.getVersion() != null && prevSnapshot.getVersion().equals("2.2")) {                   
+                     prevBackupUuid = prevSnapshot.getBackupSnapshotId();
+                     prevSnapshotUuid = prevSnapshot.getPath();
+                 }
+             } else if ((prevSnapshot.getSwiftId() != null && swift != null)
+                     || (prevSnapshot.getS3Id() != null && s3 != null)) {
+                 prevBackupUuid = prevSnapshot.getBackupSnapshotId();
+                 prevSnapshotUuid = prevSnapshot.getPath();
+             }
+         }
+         boolean isVolumeInactive = this.volumeMgr.volumeInactive(baseVolume);
+         String vmName = this.volumeMgr.getVmNameOnVolume(baseVolume);
+         StoragePool srcPool = (StoragePool)dataStoreMgr.getPrimaryDataStore(baseVolume.getPoolId());
+         String value = configDao.getValue(Config.BackupSnapshotWait.toString());
+         int _backupsnapshotwait = NumbersUtil.parseInt(value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue()));
+         BackupSnapshotCommand backupSnapshotCommand = new BackupSnapshotCommand(secondaryStoragePoolUrl, dcId, accountId, baseVolume.getId(), srcSnapshot.getId(), baseVolume.getPath(), srcPool, snapshotUuid,
+        		 srcSnapshot.getName(), prevSnapshotUuid, prevBackupUuid, isVolumeInactive, vmName, _backupsnapshotwait);
+
+         if ( swift != null ) {
+             backupSnapshotCommand.setSwift(swift);
+         } else if (s3 != null) {
+             backupSnapshotCommand.setS3(s3);
+         }
+         BackupSnapshotAnswer answer = (BackupSnapshotAnswer) this.snapshotMgr.sendToPool(baseVolume, backupSnapshotCommand);
+         if (answer != null && answer.getResult()) {
+        	 SnapshotVO snapshotVO = this.snapshotDao.findById(srcSnapshot.getId());
+        	 if (backupSnapshotCommand.getSwift() != null ) {
+        		 snapshotVO.setSwiftId(swift.getId());
+        		 snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+        	 } else if (backupSnapshotCommand.getS3() != null) {
+        		 snapshotVO.setS3Id(s3.getId());
+        		 snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+        	 } else {
+        		 snapshotVO.setSecHostId(secHost.getId());
+        		 snapshotVO.setBackupSnapshotId(answer.getBackupSnapshotName());
+        	 }
+ 			if (answer.isFull()) {
+ 				snapshotVO.setPrevSnapshotId(0L);
+			}
+        	 this.snapshotDao.update(srcSnapshot.getId(), snapshotVO);
+         }
+         return answer;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
index 6a7d78a..0a91186 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
@@ -106,13 +106,6 @@ public class SnapshotEntityImpl implements SnapshotEntity {
 	}
 
 	@Override
-	public Type getType() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-
-	@Override
 	public HypervisorType getHypervisorType() {
 		// TODO Auto-generated method stub
 		return null;
@@ -190,4 +183,10 @@ public class SnapshotEntityImpl implements SnapshotEntity {
 		return null;
 	}
 
+	@Override
+	public Type getRecurringType() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
deleted file mode 100644
index 8c4c815..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotStrategy.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.snapshot;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-
-public interface SnapshotStrategy {
-	public boolean takeSnapshot(SnapshotInfo snapshot);
-	public boolean revertSnapshot(SnapshotInfo snapshot);
-	public boolean deleteSnapshot(SnapshotInfo snapshot); 
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/222c99d8/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java b/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
deleted file mode 100644
index 2b49eee..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/PrimaryDataStoreDriver.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.volume;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
-import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
-import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
-
-public interface PrimaryDataStoreDriver extends DataStoreDriver {
-    public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
-    public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback<CommandResult> callback);
-}