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

[21/29] git commit: updated refs/heads/pluggable_vm_snapshot to 77fca0c

Updates to revertSnapshot API Added revertSnapshot API action to UI


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

Branch: refs/heads/pluggable_vm_snapshot
Commit: 350c94474b6abe4ce097e7616798d45952ed9253
Parents: 4747b2a
Author: Chris Suich <ch...@netapp.com>
Authored: Mon Oct 7 16:04:48 2013 -0400
Committer: Edison Su <su...@gmail.com>
Committed: Mon Oct 14 15:19:51 2013 -0700

----------------------------------------------------------------------
 .../user/snapshot/RevertSnapshotCmd.java        | 11 ++--
 .../classes/resources/messages.properties       |  3 +
 client/tomcatconf/commands.properties.in        |  2 +-
 .../storage/snapshot/SnapshotServiceImpl.java   | 59 ++++++++++++++++++++
 .../com/cloud/server/ManagementServerImpl.java  | 11 ++--
 .../storage/snapshot/SnapshotManagerImpl.java   | 12 ++++
 ui/dictionary.jsp                               |  3 +
 ui/scripts/storage.js                           | 34 +++++++++++
 8 files changed, 125 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java
index 946eebd..6e790e1 100644
--- a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java
@@ -18,9 +18,6 @@
  */
 package org.apache.cloudstack.api.command.user.snapshot;
 
-import com.cloud.event.EventTypes;
-import com.cloud.storage.Snapshot;
-import com.cloud.user.Account;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiCommandJobType;
 import org.apache.cloudstack.api.ApiConstants;
@@ -33,7 +30,11 @@ import org.apache.cloudstack.api.response.SnapshotResponse;
 import org.apache.cloudstack.api.response.SuccessResponse;
 import org.apache.cloudstack.context.CallContext;
 
-@APICommand(name = "RevertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class)
+import com.cloud.event.EventTypes;
+import com.cloud.storage.Snapshot;
+import com.cloud.user.Account;
+
+@APICommand(name = "revertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class)
 public class RevertSnapshotCmd extends BaseAsyncCmd {
     private static final String s_name = "revertsnapshotresponse";
     @Parameter(name= ApiConstants.ID, type= BaseCmd.CommandType.UUID, entityType = SnapshotResponse.class,
@@ -70,10 +71,12 @@ public class RevertSnapshotCmd extends BaseAsyncCmd {
         return  "revert snapshot: " + getId();
     }
 
+    @Override
     public ApiCommandJobType getInstanceType() {
         return ApiCommandJobType.Snapshot;
     }
 
+    @Override
     public Long getInstanceId() {
         return getId();
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/client/WEB-INF/classes/resources/messages.properties
----------------------------------------------------------------------
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index 7970369..c075bf8 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -251,6 +251,8 @@ label.action.stop.systemvm.processing=Stopping System VM....
 label.action.stop.systemvm=Stop System VM
 label.action.take.snapshot.processing=Taking Snapshot....
 label.action.take.snapshot=Take Snapshot
+label.action.revert.snapshot.processing=Reverting to Snapshot...
+label.action.revert.snapshot=Revert to Snapshot
 label.action.unmanage.cluster.processing=Unmanaging Cluster....
 label.action.unmanage.cluster=Unmanage Cluster
 label.action.update.OS.preference.processing=Updating OS Preference....
@@ -1297,6 +1299,7 @@ message.action.stop.instance=Please confirm that you want to stop this instance.
 message.action.stop.router=All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.
 message.action.stop.systemvm=Please confirm that you want to stop this system VM.
 message.action.take.snapshot=Please confirm that you want to take a snapshot of this volume.
+message.action.revert.snapshot=Please confirm that you want to revert the owning volume to this snapshot.
 message.action.unmanage.cluster=Please confirm that you want to unmanage the cluster.
 message.action.vmsnapshot.delete=Please confirm that you want to delete this VM snapshot.
 message.action.vmsnapshot.revert=Revert VM snapshot

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/client/tomcatconf/commands.properties.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in
index 58c770d..96e841a 100644
--- a/client/tomcatconf/commands.properties.in
+++ b/client/tomcatconf/commands.properties.in
@@ -79,7 +79,7 @@ deleteSnapshot=15
 createSnapshotPolicy=15
 deleteSnapshotPolicies=15
 listSnapshotPolicies=15
-
+revertSnapshot=15
 
 #### template commands
 createTemplate=15

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/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 c09adca..a4014b0 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
@@ -42,6 +42,7 @@ import org.apache.cloudstack.framework.async.AsyncRpcContext;
 import org.apache.cloudstack.storage.command.CommandResult;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
@@ -132,6 +133,19 @@ public class SnapshotServiceImpl implements SnapshotService {
 
     }
 
+    static private class RevertSnapshotContext<T> extends AsyncRpcContext<T> {
+        final SnapshotInfo snapshot;
+        final AsyncCallFuture<SnapshotResult> future;
+
+        public RevertSnapshotContext(AsyncCompletionCallback<T> callback, SnapshotInfo snapshot,
+                AsyncCallFuture<SnapshotResult> future) {
+            super(callback);
+            this.snapshot = snapshot;
+            this.future = future;
+        }
+
+    }
+
     protected Void createSnapshotAsyncCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CreateCmdResult> callback,
             CreateSnapshotContext<CreateCmdResult> context) {
         CreateCmdResult result = callback.getResult();
@@ -364,6 +378,28 @@ public class SnapshotServiceImpl implements SnapshotService {
         return null;
     }
 
+    protected Void revertSnapshotCallback(AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> callback,
+            RevertSnapshotContext<CommandResult> context) {
+
+        CommandResult result = callback.getResult();
+        AsyncCallFuture<SnapshotResult> future = context.future;
+        SnapshotResult res = null;
+        try {
+            if (result.isFailed()) {
+                s_logger.debug("revert snapshot failed" + result.getResult());
+                res = new SnapshotResult(context.snapshot, null);
+                res.setResult(result.getResult());
+            } else {
+                res = new SnapshotResult(context.snapshot, null);
+            }
+        } catch (Exception e) {
+            s_logger.debug("Failed to in revertSnapshotCallback", e);
+            res.setResult(e.toString());
+        }
+        future.complete(res);
+        return null;
+    }
+
     @Override
     public boolean deleteSnapshot(SnapshotInfo snapInfo) {
         snapInfo.processEvent(ObjectInDataStoreStateMachine.Event.DestroyRequested);
@@ -394,6 +430,29 @@ public class SnapshotServiceImpl implements SnapshotService {
 
     @Override
     public boolean revertSnapshot(Long snapshotId) {
+        SnapshotInfo snapshot = snapshotfactory.getSnapshot(snapshotId, DataStoreRole.Primary);
+        PrimaryDataStore store = (PrimaryDataStore)snapshot.getDataStore();
+
+        AsyncCallFuture<SnapshotResult> future = new AsyncCallFuture<SnapshotResult>();
+        RevertSnapshotContext<CommandResult> context = new RevertSnapshotContext<CommandResult>(null, snapshot, future);
+        AsyncCallbackDispatcher<SnapshotServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().revertSnapshotCallback(null, null)).setContext(context);
+
+        ((PrimaryDataStoreDriver)store.getDriver()).revertSnapshot(snapshot, caller);
+
+        SnapshotResult result = null;
+        try {
+            result = future.get();
+            if (result.isFailed()) {
+                throw new CloudRuntimeException(result.getResult());
+            }
+            return true;
+        } catch (InterruptedException e) {
+            s_logger.debug("revert snapshot is failed: " + e.toString());
+        } catch (ExecutionException e) {
+            s_logger.debug("revert snapshot is failed: " + e.toString());
+        }
+
         return false;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 0a0fcdc..7173044 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -42,9 +42,6 @@ import javax.crypto.spec.SecretKeySpec;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
-import org.apache.commons.codec.binary.Base64;
-import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.acl.ControlledEntity;
 import org.apache.cloudstack.acl.SecurityChecker.AccessType;
 import org.apache.cloudstack.affinity.AffinityGroupProcessor;
@@ -339,6 +336,7 @@ import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotCmd;
 import org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotPoliciesCmd;
 import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotPoliciesCmd;
 import org.apache.cloudstack.api.command.user.snapshot.ListSnapshotsCmd;
+import org.apache.cloudstack.api.command.user.snapshot.RevertSnapshotCmd;
 import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
 import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
 import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
@@ -438,6 +436,8 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.log4j.Logger;
 
 import com.cloud.agent.AgentManager;
 import com.cloud.agent.api.GetVncPortAnswer;
@@ -2731,6 +2731,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         cmdList.add(DeleteSnapshotPoliciesCmd.class);
         cmdList.add(ListSnapshotPoliciesCmd.class);
         cmdList.add(ListSnapshotsCmd.class);
+        cmdList.add(RevertSnapshotCmd.class);
         cmdList.add(CreateSSHKeyPairCmd.class);
         cmdList.add(DeleteSSHKeyPairCmd.class);
         cmdList.add(ListSSHKeyPairsCmd.class);
@@ -3164,7 +3165,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
     }
 
     @Override
-    @ActionEvent(eventType = "", eventDescription = "", async = true)    
+    @ActionEvent(eventType = "", eventDescription = "", async = true)
     public VMInstanceVO destroySystemVM(DestroySystemVmCmd cmd) {
         VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(cmd.getId(), VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm);
 
@@ -3640,7 +3641,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         String password = vm.getDetail("Encrypted.Password");
         if (password == null || password.equals("")) {
             InvalidParameterValueException ex = new InvalidParameterValueException("No password for VM with specified id found. " +
-                "If VM is created from password enabled template and SSH keypair is assigned to VM then only password can be retrieved.");
+                    "If VM is created from password enabled template and SSH keypair is assigned to VM then only password can be retrieved.");
             ex.addProxyObject(vm.getUuid(), "vmId");
             throw ex;
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 0b53cfd..a50d89c 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -264,6 +264,18 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
             throw new InvalidParameterValueException("No such snapshot");
         }
 
+        Volume volume = _volsDao.findById(snapshot.getVolumeId());
+        Long instanceId = volume.getInstanceId();
+
+        // If this volume is attached to an VM, then the VM needs to be in the stopped state
+        // in order to revert the volume
+        if (instanceId != null) {
+            UserVmVO vm = _vmDao.findById(instanceId);
+            if (vm.getState() != State.Stopped && vm.getState() != State.Shutdowned) {
+                throw new InvalidParameterValueException("The VM the specified disk is attached to is not in the shutdown state.");
+            }
+        }
+
         SnapshotStrategy snapshotStrategy = null;
         for (SnapshotStrategy strategy : snapshotStrategies) {
             if (strategy.canHandle(snapshot)) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/ui/dictionary.jsp
----------------------------------------------------------------------
diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp
index 3563376..80aab6f 100644
--- a/ui/dictionary.jsp
+++ b/ui/dictionary.jsp
@@ -260,6 +260,8 @@ dictionary = {
 'label.action.stop.systemvm.processing': '<fmt:message key="label.action.stop.systemvm.processing" />',
 'label.action.take.snapshot': '<fmt:message key="label.action.take.snapshot" />',
 'label.action.take.snapshot.processing': '<fmt:message key="label.action.take.snapshot.processing" />',
+'label.action.revert.snapshot': '<fmt:message key="label.action.revert.snapshot" />',
+'label.action.revert.snapshot.processing': '<fmt:message key="label.action.revert.snapshot.processing" />',
 'label.action.unmanage.cluster': '<fmt:message key="label.action.unmanage.cluster" />',
 'label.action.unmanage.cluster.processing': '<fmt:message key="label.action.unmanage.cluster.processing" />',
 'label.action.update.OS.preference': '<fmt:message key="label.action.update.OS.preference" />',
@@ -1264,6 +1266,7 @@ dictionary = {
 'message.action.stop.router': '<fmt:message key="message.action.stop.router" />',
 'message.action.stop.systemvm': '<fmt:message key="message.action.stop.systemvm" />',
 'message.action.take.snapshot': '<fmt:message key="message.action.take.snapshot" />',
+'message.action.revert.snapshot': '<fmt:message key="message.action.revert.snapshot" />',
 'message.action.unmanage.cluster': '<fmt:message key="message.action.unmanage.cluster" />',
 'message.action.vmsnapshot.delete': '<fmt:message key="message.action.vmsnapshot.delete" />',
 'message.action.vmsnapshot.revert': '<fmt:message key="message.action.vmsnapshot.revert" />',

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/350c9447/ui/scripts/storage.js
----------------------------------------------------------------------
diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js
index 88fb9f2..b16f4d4 100644
--- a/ui/scripts/storage.js
+++ b/ui/scripts/storage.js
@@ -1760,6 +1760,36 @@
                                 }
                             },
 
+                            revertSnapshot: {
+                                label: 'label.action.revert.snapshot',
+                                messages: {
+                                    confirm: function(args) {
+                                        return 'message.action.revert.snapshot';
+                                    },
+                                    notification: function(args) {
+                                        return 'label.action.revert.snapshot';
+                                    }
+                                },
+                                action: function(args) {
+                                    $.ajax({
+                                        url: createURL("revertSnapshot&id="+args.context.snapshots[0].id),
+                                        dataType: "json",
+                                        async: true,
+                                        success: function(json) {
+                                            var jid = json.revertsnapshotresponse.jobid;
+                                            args.response.success({
+                                                _custom: {
+                                                    jobId: jid
+                                                }
+                                            });
+                                        }
+                                    });
+                                },
+                                notification: {
+                                    poll: pollAsyncJobResult
+                                }
+                            },
+
                             remove: {
                                 label: 'label.action.delete.snapshot',
                                 messages: {
@@ -1929,6 +1959,10 @@
         if (jsonObj.state == "BackedUp") {
             allowedActions.push("createTemplate");
             allowedActions.push("createVolume");
+
+            if (args.context.volumes[0].vmstate == "Stopped") {
+                allowedActions.push("revertSnapshot");
+            }
         }
         allowedActions.push("remove");