You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by GitBox <gi...@apache.org> on 2017/10/19 00:31:17 UTC

[GitHub] asfgit closed pull request #2081: CLOUDSTACK-9894 Separate creation and backup operations for a volume snapshot

asfgit closed pull request #2081: CLOUDSTACK-9894 Separate creation and backup operations for a volume snapshot
URL: https://github.com/apache/cloudstack/pull/2081
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/api/src/com/cloud/storage/Snapshot.java b/api/src/com/cloud/storage/Snapshot.java
index 9e44e57e021..2f3a59541d9 100644
--- a/api/src/com/cloud/storage/Snapshot.java
+++ b/api/src/com/cloud/storage/Snapshot.java
@@ -79,6 +79,8 @@ public boolean equals(String status) {
 
     String getName();
 
+    long getSnapshotId();
+
     Date getCreated();
 
     Type getRecurringType();
diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java
index 673fffca7cd..d5a31d3365d 100644
--- a/api/src/com/cloud/storage/VolumeApiService.java
+++ b/api/src/com/cloud/storage/VolumeApiService.java
@@ -82,7 +82,7 @@
 
     Volume detachVolumeFromVM(DetachVolumeCmd cmd);
 
-    Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType) throws ResourceAllocationException;
+    Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup) throws ResourceAllocationException;
 
     Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName, Snapshot.LocationType locationType) throws ResourceAllocationException;
 
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 0a8a112d737..fdad4631ad3 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -26,6 +26,7 @@
     public static final String ALGORITHM = "algorithm";
     public static final String ALLOCATED_ONLY = "allocatedonly";
     public static final String API_KEY = "apikey";
+    public static final String ASYNC_BACKUP = "asyncbackup";
     public static final String USER_API_KEY = "userapikey";
     public static final String APPLIED = "applied";
     public static final String LIST_LB_VMIPS = "lbvmips";
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
index e79feb75632..d66b6499399 100644
--- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java
@@ -79,6 +79,9 @@
     @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "the name of the snapshot")
     private String snapshotName;
 
+    @Parameter(name = ApiConstants.ASYNC_BACKUP, type = CommandType.BOOLEAN, required = false, description = "asynchronous backup if true")
+    private Boolean asyncBackup;
+
     private String syncObjectType = BaseAsyncCmd.snapshotHostSyncObject;
 
     // ///////////////////////////////////////////////////
@@ -200,7 +203,7 @@ public void execute() {
         Snapshot snapshot;
         try {
             snapshot =
-                _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType());
+                _volumeService.takeSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()), getQuiescevm(), getLocationType(), getAsyncBackup());
 
             if (snapshot != null) {
                 SnapshotResponse response = _responseGenerator.createSnapshotResponse(snapshot);
@@ -246,4 +249,12 @@ public Long getSyncObjId() {
         }
         return null;
     }
+
+    public Boolean getAsyncBackup() {
+        if (asyncBackup == null) {
+            return false;
+        } else {
+            return asyncBackup;
+        }
+    }
 }
diff --git a/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
index 5e2b2228fab..bc2beb6cb66 100644
--- a/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
+++ b/api/test/org/apache/cloudstack/api/command/test/CreateSnapshotCmdTest.java
@@ -82,7 +82,7 @@ public void testCreateSuccess() {
         try {
 
             Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(),
-                    any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class))).thenReturn(snapshot);
+                    any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean())).thenReturn(snapshot);
 
         } catch (Exception e) {
             Assert.fail("Received exception when success expected " + e.getMessage());
@@ -115,7 +115,7 @@ public void testCreateFailure() {
 
         try {
                 Mockito.when(volumeApiService.takeSnapshot(anyLong(), anyLong(), anyLong(),
-                        any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class))).thenReturn(null);
+                        any(Account.class), anyBoolean(), isNull(Snapshot.LocationType.class), anyBoolean())).thenReturn(null);
         } catch (Exception e) {
             Assert.fail("Received exception when success expected " + e.getMessage());
         }
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 0f05ca186f3..5541b362547 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
@@ -31,6 +31,10 @@
 
     Object getPayload();
 
+    void setFullBackup(Boolean fullBackup);
+
+    Boolean getFullBackup();
+
     Long getDataCenterId();
 
     ObjectInDataStoreStateMachine.State getStatus();
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
index 322de77503a..053e0cdd134 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/SnapshotService.java
@@ -17,6 +17,8 @@
 
 package org.apache.cloudstack.engine.subsystem.api.storage;
 
+import com.cloud.storage.Snapshot.Event;
+
 public interface SnapshotService {
     SnapshotResult takeSnapshot(SnapshotInfo snapshot);
 
@@ -29,4 +31,8 @@
     void syncVolumeSnapshotsToRegionStore(long volumeId, DataStore store);
 
     void cleanupVolumeDuringSnapshotFailure(Long volumeId, Long snapshotId);
+
+    void processEventOnSnapshotObject(SnapshotInfo snapshot, Event event);
+
+    void cleanupOnSnapshotBackupFailure(SnapshotInfo snapshot);
 }
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
index fbf60041ac9..62c4c20ec7b 100644
--- 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
@@ -19,6 +19,7 @@
 import com.cloud.storage.Snapshot;
 
 public interface SnapshotStrategy {
+
     enum SnapshotOperation {
         TAKE, BACKUP, DELETE, REVERT
     }
@@ -32,4 +33,6 @@
     boolean revertSnapshot(SnapshotInfo snapshot);
 
     StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op);
+
+    void postSnapshotCreation(SnapshotInfo snapshot);
 }
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java b/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
index 495dc4638fb..6d6264406de 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkTakeVolumeSnapshot.java
@@ -27,15 +27,17 @@
     private Long snapshotId;
     private boolean quiesceVm;
     private Snapshot.LocationType locationType;
+    private boolean asyncBackup;
 
     public VmWorkTakeVolumeSnapshot(long userId, long accountId, long vmId, String handlerName,
-            Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm, Snapshot.LocationType locationType) {
+            Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm, Snapshot.LocationType locationType, boolean asyncBackup) {
         super(userId, accountId, vmId, handlerName);
         this.volumeId = volumeId;
         this.policyId = policyId;
         this.snapshotId = snapshotId;
         this.quiesceVm = quiesceVm;
         this.locationType = locationType;
+        this.asyncBackup = asyncBackup;
     }
 
     public Long getVolumeId() {
@@ -55,4 +57,8 @@ public boolean isQuiesceVm() {
     }
 
     public Snapshot.LocationType getLocationType() { return locationType; }
+
+    public boolean isAsyncBackup() {
+        return asyncBackup;
+    }
 }
diff --git a/engine/schema/src/com/cloud/storage/SnapshotVO.java b/engine/schema/src/com/cloud/storage/SnapshotVO.java
index 8e5c0b6d6fa..f1041590fb7 100644
--- a/engine/schema/src/com/cloud/storage/SnapshotVO.java
+++ b/engine/schema/src/com/cloud/storage/SnapshotVO.java
@@ -163,6 +163,11 @@ public String getName() {
     }
 
     @Override
+    public long getSnapshotId() {
+        return id;
+    }
+
+    @Override
     public short getsnapshotType() {
         return snapshotType;
     }
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 57e4181aaf9..7a1daba910d 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
@@ -520,10 +520,10 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) {
 
         DataObject cacheData = null;
         SnapshotInfo snapshotInfo = (SnapshotInfo)srcData;
-        Object payload = snapshotInfo.getPayload();
+        Boolean snapshotFullBackup = snapshotInfo.getFullBackup();
         Boolean fullSnapshot = true;
-        if (payload != null) {
-            fullSnapshot = (Boolean)payload;
+        if (snapshotFullBackup != null) {
+            fullSnapshot = snapshotFullBackup;
         }
         Map<String, String> options = new HashMap<String, String>();
         options.put("fullSnapshot", fullSnapshot.toString());
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java
new file mode 100644
index 00000000000..33b5aaa0673
--- /dev/null
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotBackupException.java
@@ -0,0 +1,29 @@
+/*
+ * 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 com.cloud.utils.SerialVersionUID;
+
+public class SnapshotBackupException extends Exception {
+    private static final long serialVersionUID = SerialVersionUID.SnapshotBackupException;
+
+    public SnapshotBackupException(String msg) {
+        super(msg);
+    }
+}
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 b47f0cf251b..23e1650ffa0 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
@@ -62,6 +62,7 @@
     private SnapshotVO snapshot;
     private DataStore store;
     private Object payload;
+    private Boolean fullBackup;
     @Inject
     protected SnapshotDao snapshotDao;
     @Inject
@@ -231,6 +232,11 @@ public String getName() {
     }
 
     @Override
+    public long getSnapshotId() {
+        return snapshot.getSnapshotId();
+    }
+
+    @Override
     public Date getCreated() {
         return snapshot.getCreated();
     }
@@ -389,6 +395,16 @@ public Object getPayload() {
     }
 
     @Override
+    public void setFullBackup(Boolean data) {
+        fullBackup = data;
+    }
+
+    @Override
+    public Boolean getFullBackup() {
+        return fullBackup;
+    }
+
+    @Override
     public boolean delete() {
         if (store != null) {
             return store.delete(this);
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 d13df9288a5..85c25f18839 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
@@ -24,7 +24,6 @@
 
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
-
 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;
@@ -44,16 +43,22 @@
 import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 import org.apache.cloudstack.framework.async.AsyncRpcContext;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
 import org.apache.cloudstack.storage.command.CommandResult;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 
+import com.cloud.storage.CreateSnapshotPayload;
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
 import com.cloud.storage.template.TemplateConstants;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.fsm.NoTransitionException;
 
@@ -72,6 +77,8 @@
     DataMotionService motionSrv;
     @Inject
     StorageCacheManager _cacheMgr;
+    @Inject
+    private SnapshotDetailsDao _snapshotDetailsDao;
 
     static private class CreateSnapshotContext<T> extends AsyncRpcContext<T> {
         final SnapshotInfo snapshot;
@@ -226,9 +233,9 @@ public SnapshotResult takeSnapshot(SnapshotInfo snap) {
     // we are taking delta snapshot
     private DataStore findSnapshotImageStore(SnapshotInfo snapshot) {
         Boolean fullSnapshot = true;
-        Object payload = snapshot.getPayload();
-        if (payload != null) {
-            fullSnapshot = (Boolean)payload;
+        Boolean snapshotFullBackup = snapshot.getFullBackup();
+        if (snapshotFullBackup != null) {
+            fullSnapshot = snapshotFullBackup;
         }
         if (fullSnapshot) {
             return dataStoreMgr.getImageStore(snapshot.getDataCenterId());
@@ -300,19 +307,22 @@ protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotService
         CopyCommandResult result = callback.getResult();
         SnapshotInfo destSnapshot = context.destSnapshot;
         SnapshotObject srcSnapshot = (SnapshotObject)context.srcSnapshot;
+        Object payload = srcSnapshot.getPayload();
+        CreateSnapshotPayload createSnapshotPayload = (CreateSnapshotPayload)payload;
         AsyncCallFuture<SnapshotResult> future = context.future;
         SnapshotResult snapResult = new SnapshotResult(destSnapshot, result.getAnswer());
         if (result.isFailed()) {
             try {
-                destSnapshot.processEvent(Event.OperationFailed);
-                //if backup snapshot failed, mark srcSnapshot in snapshot_store_ref as failed also
-                srcSnapshot.processEvent(Event.DestroyRequested);
-                srcSnapshot.processEvent(Event.OperationSuccessed);
-
-                srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
-                _snapshotDao.remove(srcSnapshot.getId());
-            } catch (NoTransitionException e) {
-                s_logger.debug("Failed to update state: " + e.toString());
+                if (createSnapshotPayload.getAsyncBackup()) {
+                    destSnapshot.processEvent(Event.OperationFailed);
+                    throw new SnapshotBackupException("Failed in creating backup of snapshot with ID "+srcSnapshot.getId());
+                } else {
+                    destSnapshot.processEvent(Event.OperationFailed);
+                    //if backup snapshot failed, mark srcSnapshot in snapshot_store_ref as failed also
+                    cleanupOnSnapshotBackupFailure(context.srcSnapshot);
+                }
+            } catch (SnapshotBackupException e) {
+                s_logger.debug("Failed to create backup: " + e.toString());
             }
             snapResult.setResult(result.getResult());
             future.complete(snapResult);
@@ -547,4 +557,38 @@ protected Void syncSnapshotCallBack(AsyncCallbackDispatcher<SnapshotServiceImpl,
 
         return null;
     }
+
+    @Override
+    public void processEventOnSnapshotObject(SnapshotInfo snapshot, Snapshot.Event event) {
+        SnapshotObject object = (SnapshotObject)snapshot;
+        try {
+            object.processEvent(event);
+        } catch (NoTransitionException e) {
+            s_logger.debug("Unable to update the state " + e.toString());
+        }
+    }
+
+    @Override
+    public void cleanupOnSnapshotBackupFailure(SnapshotInfo snapshot) {
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                try {
+                    SnapshotObject srcSnapshot = (SnapshotObject)snapshot;
+                    srcSnapshot.processEvent(Event.DestroyRequested);
+                    srcSnapshot.processEvent(Event.OperationSuccessed);
+
+                    srcSnapshot.processEvent(Snapshot.Event.OperationFailed);
+
+                    _snapshotDetailsDao.removeDetail(srcSnapshot.getId(), AsyncJob.Constants.MS_ID);
+                    _snapshotDao.remove(srcSnapshot.getId());
+                } catch (NoTransitionException ex) {
+                    s_logger.debug("Failed to create backup " + ex.toString());
+                    throw new CloudRuntimeException("Failed to backup snapshot" + snapshot.getId());
+                }
+            }
+        });
+
+    }
+
 }
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
index 9c6e3796887..413762b1fb6 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotStateMachineManagerImpl.java
@@ -53,6 +53,7 @@ public SnapshotStateMachineManagerImpl() {
         stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationSucceeded, Snapshot.State.Destroyed);
         stateMachine.addTransition(Snapshot.State.Destroying, Event.OperationFailed, State.BackedUp);
         stateMachine.addTransition(Snapshot.State.Destroying, Event.DestroyRequested, Snapshot.State.Destroying);
+        stateMachine.addTransition(Snapshot.State.BackingUp, Event.BackupToSecondary, Snapshot.State.BackingUp);
 
         stateMachine.registerListener(new SnapshotStateListener());
     }
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
index 2742da6dc61..185cf567fa0 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java
@@ -214,7 +214,6 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
 
         SnapshotResult result = null;
         SnapshotInfo snapshotOnPrimary = null;
-        SnapshotInfo backedUpSnapshot = null;
 
         try {
             volumeInfo.stateTransit(Volume.Event.SnapshotRequested);
@@ -250,23 +249,10 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
             }
 
             snapshotOnPrimary = result.getSnapshot();
-            backedUpSnapshot = backupSnapshot(snapshotOnPrimary);
-
-            updateLocationTypeInDb(backedUpSnapshot);
         }
         finally {
             if (result != null && result.isSuccess()) {
                 volumeInfo.stateTransit(Volume.Event.OperationSucceeded);
-
-                if (snapshotOnPrimary != null && snapshotInfo.getLocationType() == Snapshot.LocationType.SECONDARY) {
-                    // remove the snapshot on primary storage
-                    try {
-                        snapshotSvr.deleteSnapshot(snapshotOnPrimary);
-                    } catch (Exception e) {
-                        s_logger.warn("Failed to clean up snapshot on primary Id:" + snapshotOnPrimary.getId() + " "
-                                + e.getMessage());
-                    }
-                }
             } else {
                 volumeInfo.stateTransit(Volume.Event.OperationFailed);
             }
@@ -274,7 +260,22 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshotInfo) {
 
         snapshotDao.releaseFromLockTable(snapshotInfo.getId());
 
-        return backedUpSnapshot;
+        return snapshotOnPrimary;
+    }
+
+    @Override
+    public void postSnapshotCreation(SnapshotInfo snapshot) {
+        updateLocationTypeInDb(snapshot);
+
+        if (snapshot.getLocationType() == Snapshot.LocationType.SECONDARY) {
+            // remove the snapshot on primary storage
+            try {
+                snapshotSvr.deleteSnapshot(snapshot);
+            } catch (Exception e) {
+                s_logger.warn("Failed to clean up snapshot '" + snapshot.getId() + "' on primary storage: " + e.getMessage());
+            }
+        }
+
     }
 
     private void updateLocationTypeInDb(SnapshotInfo snapshotInfo) {
@@ -604,4 +605,5 @@ public StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op) {
 
         return StrategyPriority.CANT_HANDLE;
     }
+
 }
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 165d3564b75..a673a462375 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
@@ -33,13 +33,15 @@
 import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
+import org.apache.cloudstack.framework.jobs.dao.SyncQueueItemDao;
 import org.apache.cloudstack.storage.command.CreateObjectAnswer;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
 import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
 
-import com.cloud.configuration.Config;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.hypervisor.Hypervisor;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
@@ -52,7 +54,11 @@
 import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
 import com.cloud.storage.dao.VolumeDao;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionStatus;
 import com.cloud.storage.snapshot.SnapshotManager;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.StoragePoolType;
@@ -81,6 +87,10 @@
     SnapshotDataFactory snapshotDataFactory;
     @Inject
     private SnapshotDao _snapshotDao;
+    @Inject
+    private SnapshotDetailsDao _snapshotDetailsDao;
+    @Inject
+    private SyncQueueItemDao _syncQueueItemDao;
 
     @Override
     public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
@@ -159,7 +169,7 @@ public SnapshotInfo backupSnapshot(SnapshotInfo snapshot) {
             }
         }
 
-        snapshot.addPayload(fullBackup);
+        snapshot.setFullBackup(fullBackup);
         return snapshotSvr.backupSnapshot(snapshot);
     }
 
@@ -356,9 +366,11 @@ public boolean revertSnapshot(SnapshotInfo snapshot) {
     @Override
     @DB
     public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
+        SnapshotInfo snapshotOnPrimary = null;
         Object payload = snapshot.getPayload();
+        CreateSnapshotPayload createSnapshotPayload = null;
         if (payload != null) {
-            CreateSnapshotPayload createSnapshotPayload = (CreateSnapshotPayload)payload;
+            createSnapshotPayload = (CreateSnapshotPayload)payload;
             if (createSnapshotPayload.getQuiescevm()) {
                 throw new InvalidParameterValueException("can't handle quiescevm equal true for volume snapshot");
             }
@@ -386,58 +398,53 @@ public SnapshotInfo takeSnapshot(SnapshotInfo snapshot) {
                     volumeInfo.stateTransit(Volume.Event.OperationFailed);
                 }
             }
+            snapshotOnPrimary = result.getSnapshot();
+            snapshotOnPrimary.addPayload(snapshot.getPayload());
 
-            snapshot = result.getSnapshot();
-            DataStore primaryStore = snapshot.getDataStore();
-            boolean backupFlag = Boolean.parseBoolean(configDao.getValue(Config.BackupSnapshotAfterTakingSnapshot.toString()));
-
-            SnapshotInfo backupedSnapshot;
-            if(backupFlag) {
-                backupedSnapshot = backupSnapshot(snapshot);
-            } else {
-                // Fake it to get the transitions to fire in the proper order
-                s_logger.debug("skipping backup of snapshot due to configuration "+Config.BackupSnapshotAfterTakingSnapshot.toString());
-
-                SnapshotObject snapObj = (SnapshotObject)snapshot;
-                try {
-                    snapObj.processEvent(Snapshot.Event.OperationNotPerformed);
-                } catch (NoTransitionException e) {
-                    s_logger.debug("Failed to change state: " + snapshot.getId() + ": " + e.toString());
-                    throw new CloudRuntimeException(e.toString());
-                }
-                backupedSnapshot = snapshot;
+            /*The Management Server ID is stored in snapshot_details table with the snapshot id and (name, value): (MS_ID, <ms_id>), to know which snapshots have not been completed in case of some failure situation like
+             *  Mgmt server down etc. and by fetching the entries on restart the cleaning up of failed snapshots is done*/
+            _snapshotDetailsDao.addDetail(((SnapshotObject)snapshotOnPrimary).getId(), AsyncJob.Constants.MS_ID, Long.toString(ManagementServerNode.getManagementServerId()), false);
+            return snapshotOnPrimary;
+        } finally {
+            if (snapshotVO != null) {
+                snapshotDao.releaseFromLockTable(snapshot.getId());
             }
+        }
+    }
 
-            try {
-                SnapshotInfo parent = snapshot.getParent();
-                if (backupedSnapshot != null && parent != null && primaryStore instanceof PrimaryDataStoreImpl) {
-                    if (((PrimaryDataStoreImpl)primaryStore).getPoolType() != StoragePoolType.RBD) {
-                        Long parentSnapshotId = parent.getId();
-                        while (parentSnapshotId != null && parentSnapshotId != 0L) {
-                            SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId);
-                            if (snapshotDataStoreVO != null) {
-                                parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
-                                snapshotStoreDao.remove(snapshotDataStoreVO.getId());
-                            } else {
-                                parentSnapshotId = null;
+    @Override
+    public void postSnapshotCreation(SnapshotInfo snapshotOnPrimary) {
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                _snapshotDetailsDao.removeDetail(((SnapshotObject)snapshotOnPrimary).getId(), AsyncJob.Constants.MS_ID);
+                DataStore primaryStore = snapshotOnPrimary.getDataStore();
+                try {
+                    SnapshotInfo parent = snapshotOnPrimary.getParent();
+                    if (parent != null && primaryStore instanceof PrimaryDataStoreImpl) {
+                        if (((PrimaryDataStoreImpl)primaryStore).getPoolType() != StoragePoolType.RBD) {
+                            Long parentSnapshotId = parent.getId();
+                            while (parentSnapshotId != null && parentSnapshotId != 0L) {
+                                SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), parentSnapshotId);
+                                if (snapshotDataStoreVO != null) {
+                                    parentSnapshotId = snapshotDataStoreVO.getParentSnapshotId();
+                                    snapshotStoreDao.remove(snapshotDataStoreVO.getId());
+                                } else {
+                                    parentSnapshotId = null;
+                                }
                             }
                         }
+                        SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), snapshotOnPrimary.getId());
+                        if (snapshotDataStoreVO != null) {
+                            snapshotDataStoreVO.setParentSnapshotId(0L);
+                            snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
+                        }
                     }
-                    SnapshotDataStoreVO snapshotDataStoreVO = snapshotStoreDao.findByStoreSnapshot(primaryStore.getRole(), primaryStore.getId(), snapshot.getId());
-                    if (snapshotDataStoreVO != null) {
-                        snapshotDataStoreVO.setParentSnapshotId(0L);
-                        snapshotStoreDao.update(snapshotDataStoreVO.getId(), snapshotDataStoreVO);
-                    }
+                } catch (Exception e) {
+                    s_logger.debug("Failed to clean up snapshots on primary storage", e);
                 }
-            } catch (Exception e) {
-                s_logger.debug("Failed to clean up snapshots on primary storage", e);
             }
-            return backupedSnapshot;
-        } finally {
-            if (snapshotVO != null) {
-                snapshotDao.releaseFromLockTable(snapshot.getId());
-            }
-        }
+        });
     }
 
     @Override
@@ -455,4 +462,5 @@ public StrategyPriority canHandle(Snapshot snapshot, SnapshotOperation op) {
 
         return StrategyPriority.DEFAULT;
     }
+
 }
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 3cea3eae9b9..24e77a8a544 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java
@@ -95,6 +95,12 @@ public String getName() {
     }
 
     @Override
+    public long getSnapshotId() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
     public Date getCreated() {
         // TODO Auto-generated method stub
         return null;
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
index 0ad49e1e7bf..b8200bf8221 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJob.java
@@ -41,6 +41,8 @@
         // is defined
         public static final int SIGNAL_MASK_WAKEUP = 1;
 
+        public static final String MS_ID = "MS_ID";
+
         public static final String SYNC_LOCK_NAME = "SyncLock";
     }
 
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
index 42e15b51774..7f2e1567d7a 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
@@ -39,6 +39,9 @@
 import org.apache.log4j.NDC;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.context.CallContext;
+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.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
 import org.apache.cloudstack.framework.jobs.AsyncJob;
@@ -60,6 +63,11 @@
 
 import com.cloud.cluster.ClusterManagerListener;
 import com.cloud.cluster.ManagementServerHost;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Snapshot;
+import com.cloud.storage.dao.SnapshotDao;
+import com.cloud.storage.dao.SnapshotDetailsDao;
+import com.cloud.storage.dao.SnapshotDetailsVO;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Predicate;
@@ -126,6 +134,14 @@
     private VolumeDetailsDao _volumeDetailsDao;
     @Inject
     private VolumeDao _volsDao;
+    @Inject
+    private SnapshotDao _snapshotDao;
+    @Inject
+    private SnapshotService snapshotSrv;
+    @Inject
+    private SnapshotDataFactory snapshotFactory;
+    @Inject
+    private SnapshotDetailsDao _snapshotDetailsDao;
 
     private volatile long _executionRunNumber = 1;
 
@@ -1029,6 +1045,12 @@ public void doInTransactionWithoutResult(TransactionStatus status) {
                             }
                         }
                     }
+                    List<SnapshotDetailsVO> snapshotList = _snapshotDetailsDao.findDetails(AsyncJob.Constants.MS_ID, Long.toString(msid), false);
+                    for (SnapshotDetailsVO snapshotDetailsVO : snapshotList) {
+                        SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotDetailsVO.getResourceId(), DataStoreRole.Primary);
+                        snapshotSrv.processEventOnSnapshotObject(snapshot, Snapshot.Event.OperationFailed);
+                        _snapshotDetailsDao.removeDetail(snapshotDetailsVO.getResourceId(), AsyncJob.Constants.MS_ID);
+                    }
                 }
             });
         } catch (Throwable e) {
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index fbf97b2efe2..81a670bf0b0 100644
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -491,14 +491,6 @@
             "The time interval in seconds when the management server polls for snapshots to be scheduled.",
             null),
     SnapshotDeltaMax("Snapshots", SnapshotManager.class, Integer.class, "snapshot.delta.max", "16", "max delta snapshots between two full snapshots.", null),
-    BackupSnapshotAfterTakingSnapshot(
-            "Snapshots",
-            SnapshotManager.class,
-            Boolean.class,
-            "snapshot.backup.rightafter",
-            "true",
-            "backup snapshot right after snapshot is taken",
-            null),
     KVMSnapshotEnabled("Hidden", SnapshotManager.class, Boolean.class, "kvm.snapshot.enabled", "false", "whether snapshot is enabled for KVM hosts", null),
 
     // Advanced
diff --git a/server/src/com/cloud/storage/CreateSnapshotPayload.java b/server/src/com/cloud/storage/CreateSnapshotPayload.java
index 3e9368d8c6f..b0bb9eafb2e 100644
--- a/server/src/com/cloud/storage/CreateSnapshotPayload.java
+++ b/server/src/com/cloud/storage/CreateSnapshotPayload.java
@@ -24,6 +24,7 @@
     private Account account;
     private boolean quiescevm;
     private Snapshot.LocationType locationType;
+    private boolean asyncBackup;
 
     public Long getSnapshotPolicyId() {
         return snapshotPolicyId;
@@ -58,4 +59,12 @@ public boolean getQuiescevm() {
     public Snapshot.LocationType getLocationType() { return this.locationType; }
 
     public void setLocationType(Snapshot.LocationType locationType) { this.locationType = locationType; }
+
+    public void setAsyncBackup(boolean asyncBackup) {
+        this.asyncBackup = asyncBackup;
+    }
+
+    public boolean getAsyncBackup() {
+        return this.asyncBackup;
+    }
 }
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 3330cc74a26..6dadc7c438a 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -109,6 +109,7 @@
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonParseException;
+
 import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
 import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
 import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
@@ -163,6 +164,7 @@
 import org.joda.time.DateTimeZone;
 
 import javax.inject.Inject;
+
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -844,11 +846,16 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep
         boolean shrinkOk = cmd.getShrinkOk();
 
         VolumeVO volume = _volsDao.findById(cmd.getEntityId());
-
         if (volume == null) {
             throw new InvalidParameterValueException("No such volume");
         }
 
+        // checking if there are any ongoing snapshots on the volume which is to be resized
+        List<SnapshotVO> ongoingSnapshots = _snapshotDao.listByStatus(cmd.getId(), Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
+        if (ongoingSnapshots.size() > 0) {
+            throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on this volume, resize volume is not permitted, please try again later.");
+        }
+
         /* Does the caller have authority to act on this volume? */
         _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume);
 
@@ -2061,7 +2068,7 @@ protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) throws S
 
     @Override
     @ActionEvent(eventType = EventTypes.EVENT_SNAPSHOT_CREATE, eventDescription = "taking snapshot", async = true)
-    public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType)
+    public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup)
             throws ResourceAllocationException {
         VolumeInfo volume = volFactory.getVolume(volumeId);
         if (volume == null) {
@@ -2090,13 +2097,13 @@ public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Acco
                 VmWorkJobVO placeHolder = null;
                 placeHolder = createPlaceHolderWork(vm.getId());
                 try {
-                    return orchestrateTakeVolumeSnapshot(volumeId, policyId, snapshotId, account, quiescevm, locationType);
+                    return orchestrateTakeVolumeSnapshot(volumeId, policyId, snapshotId, account, quiescevm, locationType, asyncBackup);
                 } finally {
                     _workJobDao.expunge(placeHolder.getId());
                 }
 
             } else {
-                Outcome<Snapshot> outcome = takeVolumeSnapshotThroughJobQueue(vm.getId(), volumeId, policyId, snapshotId, account.getId(), quiescevm, locationType);
+                Outcome<Snapshot> outcome = takeVolumeSnapshotThroughJobQueue(vm.getId(), volumeId, policyId, snapshotId, account.getId(), quiescevm, locationType, asyncBackup);
 
                 try {
                     outcome.get();
@@ -2124,13 +2131,14 @@ else if (jobResult instanceof Throwable)
             payload.setSnapshotPolicyId(policyId);
             payload.setAccount(account);
             payload.setQuiescevm(quiescevm);
+            payload.setAsyncBackup(asyncBackup);
             volume.addPayload(payload);
             return volService.takeSnapshot(volume);
         }
     }
 
     private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account,
-                                                   boolean quiescevm, Snapshot.LocationType locationType)
+                                                   boolean quiescevm, Snapshot.LocationType locationType, boolean asyncBackup)
             throws ResourceAllocationException {
 
         VolumeInfo volume = volFactory.getVolume(volumeId);
@@ -2150,7 +2158,7 @@ private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Lon
         payload.setAccount(account);
         payload.setQuiescevm(quiescevm);
         payload.setLocationType(locationType);
-
+        payload.setAsyncBackup(asyncBackup);
         volume.addPayload(payload);
 
         return volService.takeSnapshot(volume);
@@ -2965,7 +2973,7 @@ protected Snapshot retrieve() {
     }
 
     public Outcome<Snapshot> takeVolumeSnapshotThroughJobQueue(final Long vmId, final Long volumeId,
-            final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, final Snapshot.LocationType locationType) {
+            final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm, final Snapshot.LocationType locationType, final boolean asyncBackup) {
 
         final CallContext context = CallContext.current();
         final User callingUser = context.getCallingUser();
@@ -2988,7 +2996,7 @@ protected Snapshot retrieve() {
         // save work context info (there are some duplications)
         VmWorkTakeVolumeSnapshot workInfo = new VmWorkTakeVolumeSnapshot(
                 callingUser.getId(), accountId != null ? accountId : callingAccount.getId(), vm.getId(),
-                VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, policyId, snapshotId, quiesceVm, locationType);
+                VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, policyId, snapshotId, quiesceVm, locationType, asyncBackup);
         workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
 
         _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
@@ -3038,7 +3046,7 @@ protected Snapshot retrieve() {
     private Pair<JobInfo.Status, String> orchestrateTakeVolumeSnapshot(VmWorkTakeVolumeSnapshot work) throws Exception {
         Account account = _accountDao.findById(work.getAccountId());
         orchestrateTakeVolumeSnapshot(work.getVolumeId(), work.getPolicyId(), work.getSnapshotId(),
-                account, work.isQuiesceVm(), work.getLocationType());
+                account, work.isQuiesceVm(), work.getLocationType(), work.isAsyncBackup());
         return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
                 _jobMgr.marshallResultObject(work.getSnapshotId()));
     }
@@ -3066,4 +3074,5 @@ private VmWorkJobVO createPlaceHolderWork(long instanceId) {
 
         return workJob;
     }
+
 }
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index 9b6eb8841ea..c27c6992dcb 100644
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -18,6 +18,8 @@
 
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
@@ -25,13 +27,13 @@
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.SnapshotVO;
 import com.cloud.storage.Volume;
-import org.apache.cloudstack.framework.config.ConfigKey;
 
 /**
  *
  *
  */
-public interface SnapshotManager {
+public interface SnapshotManager extends Configurable {
+
     public static final int HOURLYMAX = 8;
     public static final int DAILYMAX = 8;
     public static final int WEEKLYMAX = 8;
@@ -48,6 +50,12 @@
             "Maximum recurring monthly snapshots to be retained for a volume. If the limit is reached, snapshots from the beginning of the month are deleted so that newer ones can be saved. This limit does not apply to manual snapshots. If set to 0, recurring monthly snapshots can not be scheduled.", false, ConfigKey.Scope.Global, null);
     static final ConfigKey<Boolean> usageSnapshotSelection = new ConfigKey<Boolean>("Usage", Boolean.class, "usage.snapshot.virtualsize.select", "false",
             "Set the value to true if snapshot usage need to consider virtual size, else physical size is considered ", false);
+    public static final ConfigKey<Integer> BackupRetryAttempts = new ConfigKey<Integer>(Integer.class, "backup.retry", "Advanced", "3",
+            "Number of times to retry in creating backup of snapshot on secondary", false, ConfigKey.Scope.Global, null);
+
+    public static final ConfigKey<Integer> BackupRetryInterval = new ConfigKey<Integer>(Integer.class, "backup.retry.interval", "Advanced", "300",
+            "Time in seconds between retries in backing up snapshot to secondary", false, ConfigKey.Scope.Global, null);
+
     void deletePoliciesForVolume(Long volumeId);
 
     /**
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index b2caa818a46..f074c332e3c 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -76,6 +76,7 @@
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
 import com.cloud.utils.Ternary;
+import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.JoinBuilder;
@@ -114,6 +115,7 @@
 import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.Configurable;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
@@ -128,6 +130,9 @@
 import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 @Component
 public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implements SnapshotManager, SnapshotApiService, Configurable {
@@ -189,6 +194,19 @@
 
     private int _totalRetries;
     private int _pauseInterval;
+    private int snapshotBackupRetries, snapshotBackupRetryInterval;
+
+    private ScheduledExecutorService backupSnapshotExecutor;
+
+    @Override
+    public String getConfigComponentName() {
+        return SnapshotManager.class.getSimpleName();
+    }
+
+    @Override
+    public ConfigKey<?>[] getConfigKeys() {
+        return new ConfigKey<?>[] {BackupRetryAttempts, BackupRetryInterval, SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection};
+    }
 
     @Override
     public Answer sendToPool(Volume vol, Command cmd) {
@@ -1093,7 +1111,15 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
                 throw new CloudRuntimeException("Can't find snapshot strategy to deal with snapshot:" + snapshotId);
             }
 
-            snapshotStrategy.takeSnapshot(snapshot);
+            SnapshotInfo snapshotOnPrimary = snapshotStrategy.takeSnapshot(snapshot);
+            if (payload.getAsyncBackup()) {
+                backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshotOnPrimary, snapshotBackupRetries - 1, snapshotStrategy), 0, TimeUnit.SECONDS);
+            } else {
+                SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshotOnPrimary);
+                if (backupedSnapshot != null) {
+                    snapshotStrategy.postSnapshotCreation(snapshotOnPrimary);
+                }
+            }
 
             try {
                 postCreateSnapshot(volume.getId(), snapshotId, payload.getSnapshotPolicyId());
@@ -1134,6 +1160,39 @@ public SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationExc
         return snapshot;
     }
 
+    protected class BackupSnapshotTask extends ManagedContextRunnable {
+        SnapshotInfo snapshot;
+        int attempts;
+        SnapshotStrategy snapshotStrategy;
+
+        public BackupSnapshotTask(SnapshotInfo snap, int maxRetries, SnapshotStrategy strategy) {
+            snapshot = snap;
+            attempts = maxRetries;
+            snapshotStrategy = strategy;
+        }
+
+        @Override
+        protected void runInContext() {
+            try {
+                s_logger.debug("Value of attempts is " + (snapshotBackupRetries-attempts));
+
+                SnapshotInfo backupedSnapshot = snapshotStrategy.backupSnapshot(snapshot);
+
+                if (backupedSnapshot != null) {
+                    snapshotStrategy.postSnapshotCreation(snapshot);
+                }
+            } catch (final Exception e) {
+                if (attempts >= 0) {
+                    s_logger.debug("Backing up of snapshot failed, for snapshot with ID "+snapshot.getSnapshotId()+", left with "+attempts+" more attempts");
+                    backupSnapshotExecutor.schedule(new BackupSnapshotTask(snapshot, --attempts, snapshotStrategy), snapshotBackupRetryInterval, TimeUnit.SECONDS);
+                } else {
+                    s_logger.debug("Done with "+snapshotBackupRetries+" attempts in  backing up of snapshot with ID "+snapshot.getSnapshotId());
+                    snapshotSrv.cleanupOnSnapshotBackupFailure(snapshot);
+                }
+            }
+        }
+    }
+
     private void updateSnapshotPayload(long storagePoolId, CreateSnapshotPayload payload) {
         StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
 
@@ -1185,6 +1244,9 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
         _totalRetries = NumbersUtil.parseInt(_configDao.getValue("total.retries"), 4);
         _pauseInterval = 2 * NumbersUtil.parseInt(_configDao.getValue("ping.interval"), 60);
 
+        snapshotBackupRetries = BackupRetryAttempts.value();
+        snapshotBackupRetryInterval = BackupRetryInterval.value();
+        backupSnapshotExecutor = Executors.newScheduledThreadPool(10, new NamedThreadFactory("BackupSnapshotTask"));
         s_logger.info("Snapshot Manager is configured.");
 
         return true;
@@ -1208,6 +1270,7 @@ public boolean start() {
 
     @Override
     public boolean stop() {
+        backupSnapshotExecutor.shutdown();
         return true;
     }
 
@@ -1330,14 +1393,4 @@ public Snapshot allocSnapshot(Long volumeId, Long policyId, String snapshotName,
         _resourceLimitMgr.incrementResourceCount(volume.getAccountId(), ResourceType.secondary_storage, new Long(volume.getSize()));
         return snapshot;
     }
-
-
-    @Override
-    public String getConfigComponentName() {
-        return SnapshotManager.class.getSimpleName();
-    }
-
-    @Override
-    public ConfigKey<?>[] getConfigKeys() {
-        return new ConfigKey<?>[] { SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection}; }
 }
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index a19d4fa8bd5..e4fc56fe6af 100644
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -227,6 +227,7 @@
 import com.cloud.storage.Storage;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.Snapshot;
 import com.cloud.storage.StorageManager;
 import com.cloud.storage.StoragePool;
 import com.cloud.storage.StoragePoolStatus;
@@ -2677,10 +2678,22 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C
         if (expunge && !_accountMgr.isAdmin(ctx.getCallingAccount().getId()) && !AllowUserExpungeRecoverVm.valueIn(cmd.getEntityOwnerId())) {
             throw new PermissionDeniedException("Parameter " + ApiConstants.EXPUNGE + " can be passed by Admin only. Or when the allow.user.expunge.recover.vm key is set.");
         }
+        // check if VM exists
+        UserVmVO vm = _vmDao.findById(vmId);
+
+        if (vm == null) {
+            throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
+        }
+
+        // check if there are active volume snapshots tasks
+        s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
+        if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
+            throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, vm destroy is not permitted, please try again later.");
+        }
+        s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
 
         UserVm destroyedVm = destroyVm(vmId, expunge);
         if (expunge) {
-            UserVmVO vm = _vmDao.findById(vmId);
             if (!expunge(vm, ctx.getCallingUserId(), ctx.getCallingAccount())) {
                 throw new CloudRuntimeException("Failed to expunge vm " + destroyedVm);
             }
@@ -4915,6 +4928,12 @@ public VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) thr
             throw new VirtualMachineMigrationException("Destination host, hostId: " + destinationHost.getId()
                             + " already has max Running VMs(count includes system VMs), cannot migrate to this host");
         }
+        //check if there are any ongoing volume snapshots on the volumes associated with the VM.
+        s_logger.debug("Checking if there are any ongoing snapshots volumes associated with VM with ID " + vmId);
+        if (checkStatusOfVolumeSnapshots(vmId, null)) {
+            throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on volume(s) attached to this VM, VM Migration is not permitted, please try again later.");
+        }
+        s_logger.debug("Found no ongoing snapshots on volumes associated with the vm with id " + vmId);
 
         UserVmVO uservm = _vmDao.findById(vmId);
         if (uservm != null) {
@@ -5780,6 +5799,12 @@ public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException,
 
         _accountMgr.checkAccess(caller, null, true, vm);
 
+        //check if there are any active snapshots on volumes associated with the VM
+        s_logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId);
+        if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) {
+            throw new CloudRuntimeException("There is/are unbacked up snapshot(s) on ROOT volume, Re-install VM is not permitted, please try again later.");
+        }
+        s_logger.debug("Found no ongoing snapshots on volume of type ROOT, for the vm with id " + vmId);
         return restoreVMInternal(caller, vm, newTemplateId);
     }
 
@@ -6124,4 +6149,28 @@ public boolean isDisplayResourceEnabled(Long vmId) {
 
         return true; // no info then default to true
     }
+
+    private boolean checkStatusOfVolumeSnapshots(long vmId, Volume.Type type) {
+        List<VolumeVO> listVolumes = null;
+        if (type == Volume.Type.ROOT) {
+            listVolumes = _volsDao.findByInstanceAndType(vmId, type);
+        } else if (type == Volume.Type.DATADISK) {
+            listVolumes = _volsDao.findByInstanceAndType(vmId, type);
+        } else {
+            listVolumes = _volsDao.findByInstance(vmId);
+        }
+        s_logger.debug("Found "+listVolumes.size()+" no. of volumes of type "+type+" for vm with VM ID "+vmId);
+        for (VolumeVO volume : listVolumes) {
+            Long volumeId = volume.getId();
+            s_logger.debug("Checking status of snapshots for Volume with Volume Id: "+volumeId);
+            List<SnapshotVO> ongoingSnapshots = _snapshotDao.listByStatus(volumeId, Snapshot.State.Creating, Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
+            int ongoingSnapshotsCount = ongoingSnapshots.size();
+            s_logger.debug("The count of ongoing Snapshots for VM with ID "+vmId+" and disk type "+type+" is "+ongoingSnapshotsCount);
+            if (ongoingSnapshotsCount > 0) {
+                s_logger.debug("Found "+ongoingSnapshotsCount+" no. of snapshots, on volume of type "+type+", which snapshots are not yet backed up");
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
index 35df0db89a3..16f39bcddff 100644
--- a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
+++ b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
@@ -386,7 +386,7 @@ public void testTakeSnapshotF1() throws ResourceAllocationException {
         when(_volFactory.getVolume(anyLong())).thenReturn(volumeInfoMock);
         when(volumeInfoMock.getState()).thenReturn(Volume.State.Allocated);
         when(volumeInfoMock.getPoolId()).thenReturn(1L);
-        _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null);
+        _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
     }
 
     @Test
@@ -396,7 +396,7 @@ public void testTakeSnapshotF2() throws ResourceAllocationException {
         when(volumeInfoMock.getInstanceId()).thenReturn(null);
         when(volumeInfoMock.getPoolId()).thenReturn(1L);
         when (volService.takeSnapshot(Mockito.any(VolumeInfo.class))).thenReturn(snapshotInfoMock);
-        _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null);
+        _svc.takeSnapshot(5L, Snapshot.MANUAL_POLICY_ID, 3L, null, false, null, false);
     }
 
     @Test
diff --git a/setup/db/db/schema-41000to41100-cleanup.sql b/setup/db/db/schema-41000to41100-cleanup.sql
index 60bc535fbc8..1307173148a 100644
--- a/setup/db/db/schema-41000to41100-cleanup.sql
+++ b/setup/db/db/schema-41000to41100-cleanup.sql
@@ -19,5 +19,6 @@
 -- Schema upgrade cleanup from 4.10.0.0 to 4.11.0.0
 --;
 
+DELETE FROM `cloud`.`configuration` WHERE name='snapshot.backup.rightafter';
 -- CLOUDSTACK-9914: Alter quota_tariff to support currency values up to 5 decimal places
 ALTER TABLE `cloud_usage`.`quota_tariff` MODIFY `currency_value` DECIMAL(15,5) not null
diff --git a/test/integration/component/test_separate_backup_from_snapshot.py b/test/integration/component/test_separate_backup_from_snapshot.py
new file mode 100644
index 00000000000..c0bfe68daf6
--- /dev/null
+++ b/test/integration/component/test_separate_backup_from_snapshot.py
@@ -0,0 +1,177 @@
+# 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.
+""" P1 tests for Snapshots
+"""
+# Import Local Modules
+from nose.plugins.attrib import attr
+from marvin.cloudstackTestCase import cloudstackTestCase
+from marvin.config.test_data import test_data
+
+from marvin.lib.base import (Snapshot,
+                             VirtualMachine,
+                             Account,
+                             ServiceOffering,
+                             DiskOffering)
+
+from marvin.lib.common import (get_domain,
+                               get_zone,
+                               get_template,
+                               list_volumes,
+                               list_snapshots,
+                               )
+
+from marvin.lib.utils import (cleanup_resources,
+                              get_hypervisor_type)
+
+
+class TestSnapshots(cloudstackTestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.testClient = super(TestSnapshots, cls).getClsTestClient()
+        cls.api_client = cls.testClient.getApiClient()
+
+        cls.services = test_data
+        # Get Zone, Domain and templates
+        cls.domain = get_domain(cls.api_client)
+        cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
+        cls._cleanup = []
+        cls.unsupportedHypervisor = False
+        cls.hypervisor = str(get_hypervisor_type(cls.api_client)).lower()
+        if cls.hypervisor.lower() in ['hyperv', 'lxc']:
+            cls.unsupportedHypervisor = True
+            return
+        cls.disk_offering = DiskOffering.create(
+            cls.api_client,
+            cls.services["disk_offering"]
+        )
+        cls.template = get_template(
+            cls.api_client,
+            cls.zone.id,
+            cls.services["ostype"]
+        )
+
+        cls.services["small"]["zoneid"] = cls.zone.id
+        cls.services["small"]["diskoffering"] = cls.disk_offering.id
+
+        cls.service_offering = ServiceOffering.create(
+            cls.api_client,
+            cls.services["service_offering"]
+        )
+
+        cls._cleanup = [
+            cls.service_offering,
+            cls.disk_offering
+        ]
+        return
+
+    @classmethod
+    def tearDownClass(cls):
+        try:
+            # Cleanup resources used
+            cleanup_resources(cls.api_client, cls._cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    def setUp(self):
+        self.apiclient = self.testClient.getApiClient()
+        self.dbclient = self.testClient.getDbConnection()
+        self.cleanup = []
+
+        if self.unsupportedHypervisor:
+            self.skipTest("Skipping test because unsupported hypervisor: %s" %
+                    self.hypervisor)
+
+
+        # Create VMs, NAT Rules etc
+        self.account = Account.create(
+            self.apiclient,
+            self.services["account"],
+            domainid=self.domain.id
+        )
+        self.cleanup.append(self.account)
+        self.virtual_machine_with_disk = VirtualMachine.create(
+                self.api_client,
+                self.services["small"],
+                templateid=self.template.id,
+                accountid=self.account.name,
+                domainid=self.account.domainid,
+                serviceofferingid=self.service_offering.id,
+                mode=self.zone.networktype
+            )
+        return
+
+    def tearDown(self):
+        try:
+            # Clean up, terminate the created instance, volumes and snapshots
+            cleanup_resources(self.apiclient, self.cleanup)
+        except Exception as e:
+            raise Exception("Warning: Exception during cleanup : %s" % e)
+        return
+
+    @attr(speed="slow")
+    @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
+    def test_01_snapshot_data_disk(self):
+        """Test Snapshot Data Disk
+        """
+
+        volume = list_volumes(
+            self.apiclient,
+            virtualmachineid=self.virtual_machine_with_disk.id,
+            type='DATADISK',
+            listall=True
+        )
+        self.assertEqual(
+            isinstance(volume, list),
+            True,
+            "Check list response returns a valid list"
+        )
+
+        self.debug("Creating a Snapshot from data volume: %s" % volume[0].id)
+        snapshot = Snapshot.create(
+            self.apiclient,
+            volume[0].id,
+            account=self.account.name,
+            domainid=self.account.domainid,
+            asyncbackup=True
+        )
+        snapshots = list_snapshots(
+            self.apiclient,
+            id=snapshot.id
+        )
+        self.assertEqual(
+            isinstance(snapshots, list),
+            True,
+            "Check list response returns a valid list"
+        )
+        self.assertNotEqual(
+            snapshots,
+            None,
+            "Check if result exists in list item call"
+        )
+        self.assertEqual(
+            snapshots[0].id,
+            snapshot.id,
+            "Check resource id in list resources call"
+        )
+        self.assertEqual(
+            snapshot.state,
+            "BackingUp",
+            "Check resource state in list resources call"
+        )
+        return
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index ffe1e01f922..f0af048dd21 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -1105,7 +1105,7 @@ def __init__(self, items):
 
     @classmethod
     def create(cls, apiclient, volume_id, account=None,
-               domainid=None, projectid=None, locationtype=None):
+               domainid=None, projectid=None, locationtype=None, asyncbackup=None):
         """Create Snapshot"""
         cmd = createSnapshot.createSnapshotCmd()
         cmd.volumeid = volume_id
@@ -1117,6 +1117,8 @@ def create(cls, apiclient, volume_id, account=None,
             cmd.projectid = projectid
         if locationtype:
             cmd.locationtype = locationtype
+	if asyncbackup:
+	    cmd.asyncbackup = asyncbackup
         return Snapshot(apiclient.createSnapshot(cmd).__dict__)
 
     def delete(self, apiclient):
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index 39e70727ba1..410f762e098 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -45,6 +45,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
 "image.directory":"Image Directory",
 "inline":"Inline",
 "instances.actions.reboot.label":"Reboot instance",
+"label.async.backup":"Async Backup",
 "label.CIDR.list":"CIDR list",
 "label.CIDR.of.destination.network":"CIDR of destination network",
 "label.CPU.cap":"CPU Cap",
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index b71dbe2ec2f..639f8a98b7c 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -813,13 +813,18 @@
                                         },
                                         name: {
                                             label: 'label.name'
+                                        },
+                                        asyncBackup: {
+						label: 'label.async.backup',
+						isBoolean: true
                                         }
                                     }
                                 },
                                 action: function(args) {
                                     var data = {
                                         volumeId: args.context.volumes[0].id,
-                                        quiescevm: (args.data.quiescevm == 'on' ? true: false)
+                                        quiescevm: (args.data.quiescevm == 'on' ? true: false),
+                                        asyncBackup: (args.data.asyncBackup == 'on' ? true: false)
                                     };
                                     if (args.data.name != null && args.data.name.length > 0) {
                                         $.extend(data, {
diff --git a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
index b45e028a550..4dd5add28dd 100644
--- a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
+++ b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java
@@ -67,4 +67,5 @@
     public static final long AffinityConflictException = Base | 0x2a;
     public static final long NioConnectionException = Base | 0x2c;
     public static final long TaskExecutionException = Base | 0x2d;
+    public static final long SnapshotBackupException = Base | 0x2e;
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services