You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ke...@apache.org on 2014/01/09 23:33:49 UTC

[01/13] git commit: updated refs/heads/master to 1e2e1ea

Updated Branches:
  refs/heads/master a298f6fce -> 1e2e1ea05


CLOUDSTACK-5672: Fix VM work job serialization issues in Add/Remove nic


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

Branch: refs/heads/master
Commit: 0965adb003905fa56dd642f48c632acae4b2c4fc
Parents: 87381d4
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Jan 3 17:20:09 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 api/src/com/cloud/network/Network.java          |  3 +-
 api/src/com/cloud/vm/NicProfile.java            |  5 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 76 +++++++++-----------
 .../src/com/cloud/vm/VmWorkAddVmToNetwork.java  | 12 ++--
 .../src/com/cloud/vm/VmWorkRemoveNicFromVm.java | 10 +--
 5 files changed, 51 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0965adb0/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java
index d2c8ac0..0b76789 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.network;
 
+import java.io.Serializable;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,7 +34,7 @@ import com.cloud.utils.fsm.StateObject;
 /**
  * owned by an account.
  */
-public interface Network extends ControlledEntity, StateObject<Network.State>, InternalIdentity, Identity {
+public interface Network extends ControlledEntity, StateObject<Network.State>, InternalIdentity, Identity, Serializable {
 
     public enum GuestType {
         Shared, Isolated

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0965adb0/api/src/com/cloud/vm/NicProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/NicProfile.java b/api/src/com/cloud/vm/NicProfile.java
index 2058803..4dd7f68 100644
--- a/api/src/com/cloud/vm/NicProfile.java
+++ b/api/src/com/cloud/vm/NicProfile.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.vm;
 
+import java.io.Serializable;
 import java.net.URI;
 
 import org.apache.cloudstack.api.InternalIdentity;
@@ -27,7 +28,9 @@ import com.cloud.network.Networks.Mode;
 import com.cloud.network.Networks.TrafficType;
 import com.cloud.vm.Nic.ReservationStrategy;
 
-public class NicProfile implements InternalIdentity {
+public class NicProfile implements InternalIdentity, Serializable {
+    private static final long serialVersionUID = 4997005771736090304L;
+
     long id;
     long networkId;
     BroadcastDomainType broadcastType;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0965adb0/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index d0adabf..0653747 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -58,7 +58,6 @@ import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 import org.apache.cloudstack.framework.jobs.Outcome;
 import org.apache.cloudstack.framework.jobs.dao.VmWorkJobDao;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
-import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
 import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl;
 import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
 import org.apache.cloudstack.framework.messagebus.MessageBus;
@@ -3097,25 +3096,21 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, outcome.getJob().getId());
-            if (jobVo.getResultCode() == JobInfo.Status.SUCCEEDED.ordinal()) {
-
-                NicProfile nic = (NicProfile)JobSerializerHelper.fromObjectSerializedString(jobVo.getResult());
-                return nic;
-            } else {
-                Object jobException = _jobMgr.unmarshallResultObject(outcome.getJob());
-                if (jobException != null) {
-                    if (jobException instanceof ResourceUnavailableException)
-                        throw (ResourceUnavailableException)jobException;
-                    else if (jobException instanceof ConcurrentOperationException)
-                        throw (ConcurrentOperationException)jobException;
-                    else if (jobException instanceof InsufficientCapacityException)
-                        throw (InsufficientCapacityException)jobException;
-                    else if (jobException instanceof RuntimeException)
-                        throw (RuntimeException)jobException;
-                }
-                throw new RuntimeException("Job failed with unhandled exception");
+            Object jobException = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobException != null) {
+                if (jobException instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobException;
+                else if (jobException instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobException;
+                else if (jobException instanceof InsufficientCapacityException)
+                    throw (InsufficientCapacityException)jobException;
+                else if (jobException instanceof RuntimeException)
+                    throw (RuntimeException)jobException;
+                else if (jobException instanceof Long)
+                    return requested;
             }
+
+            throw new RuntimeException("Unexpected job execution result");
         }
     }
 
@@ -3204,24 +3199,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, outcome.getJob().getId());
-
-            if (jobVo.getResultCode() == JobInfo.Status.SUCCEEDED.ordinal()) {
-                Boolean result = (Boolean)JobSerializerHelper.fromObjectSerializedString(jobVo.getResult());
-                return result;
-            } else {
-                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
-                if (jobResult != null) {
-                    if (jobResult instanceof ResourceUnavailableException)
-                        throw (ResourceUnavailableException)jobResult;
-                    else if (jobResult instanceof ConcurrentOperationException)
-                        throw (ConcurrentOperationException)jobResult;
-                    else if (jobResult instanceof RuntimeException)
-                        throw (RuntimeException)jobResult;
-                }
-
-                throw new RuntimeException("Job failed with un-handled exception");
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof RuntimeException)
+                    throw (RuntimeException)jobResult;
+                else if (jobResult instanceof Boolean)
+                    return (Boolean)jobResult;
             }
+
+            throw new RuntimeException("Job failed with un-handled exception");
         }
     }
 
@@ -4529,7 +4519,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     // save work context info (there are some duplications)
                     VmWorkAddVmToNetwork workInfo = new VmWorkAddVmToNetwork(user.getId(), account.getId(), vm.getId(),
-                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, network, requested);
+                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, network.getId(), requested);
                     workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
@@ -4578,7 +4568,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     // save work context info (there are some duplications)
                     VmWorkRemoveNicFromVm workInfo = new VmWorkRemoveNicFromVm(user.getId(), account.getId(), vm.getId(),
-                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, nic);
+                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, nic.getId());
                     workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
@@ -4768,9 +4758,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.info("Unable to find vm " + work.getVmId());
         }
         assert (vm != null);
-        NicProfile nic = orchestrateAddVmToNetwork(vm, work.getNetwork(),
+
+        Network network = _networkDao.findById(work.getNetworkId());
+        NicProfile nic = orchestrateAddVmToNetwork(vm, network,
                 work.getRequestedNicProfile());
-        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(nic));
+
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(new Long(nic.getId())));
     }
 
     private Pair<JobInfo.Status, String> orchestrateRemoveNicFromVm(VmWorkRemoveNicFromVm work) throws Exception {
@@ -4779,7 +4772,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.info("Unable to find vm " + work.getVmId());
         }
         assert (vm != null);
-        boolean result = orchestrateRemoveNicFromVm(vm, work.getNic());
+        NicVO nic = _entityMgr.findById(NicVO.class, work.getNicId());
+        boolean result = orchestrateRemoveNicFromVm(vm, nic);
         return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
                 _jobMgr.marshallResultObject(new Boolean(result)));
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0965adb0/engine/orchestration/src/com/cloud/vm/VmWorkAddVmToNetwork.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkAddVmToNetwork.java b/engine/orchestration/src/com/cloud/vm/VmWorkAddVmToNetwork.java
index bb3b496..a56259b 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkAddVmToNetwork.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkAddVmToNetwork.java
@@ -16,24 +16,22 @@
 // under the License.
 package com.cloud.vm;
 
-import com.cloud.network.Network;
-
 public class VmWorkAddVmToNetwork extends VmWork {
     private static final long serialVersionUID = 8861516006586736813L;
 
-    Network network;
+    Long networkId;
     NicProfile requstedNicProfile;
 
     public VmWorkAddVmToNetwork(long userId, long accountId, long vmId, String handlerName,
-            Network network, NicProfile requested) {
+            Long networkId, NicProfile requested) {
         super(userId, accountId, vmId, handlerName);
 
-        this.network = network;
+        this.networkId = networkId;
         requstedNicProfile = requested;
     }
 
-    public Network getNetwork() {
-        return network;
+    public Long getNetworkId() {
+        return networkId;
     }
 
     public NicProfile getRequestedNicProfile() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/0965adb0/engine/orchestration/src/com/cloud/vm/VmWorkRemoveNicFromVm.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkRemoveNicFromVm.java b/engine/orchestration/src/com/cloud/vm/VmWorkRemoveNicFromVm.java
index 29264e6..50f158e 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkRemoveNicFromVm.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkRemoveNicFromVm.java
@@ -19,15 +19,15 @@ package com.cloud.vm;
 public class VmWorkRemoveNicFromVm extends VmWork {
     private static final long serialVersionUID = -4265657031064437923L;
 
-    Nic nic;
+    Long nicId;
 
-    public VmWorkRemoveNicFromVm(long userId, long accountId, long vmId, String handlerName, Nic nic) {
+    public VmWorkRemoveNicFromVm(long userId, long accountId, long vmId, String handlerName, Long nicId) {
         super(userId, accountId, vmId, handlerName);
 
-        this.nic = nic;
+        this.nicId = nicId;
     }
 
-    public Nic getNic() {
-        return nic;
+    public Long getNicId() {
+        return nicId;
     }
 }


[05/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-669: Convert volume snapshot orchestration flow to make it be serialized with other VM operations


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

Branch: refs/heads/master
Commit: 8c93bd60806101edea78d8c2d43e2ba0b08142ca
Parents: bf9a554
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Dec 27 16:40:20 2013 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 api/src/com/cloud/storage/DataStoreRole.java    |   4 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java |  22 ++-
 .../cloud/storage/VmWorkTakeVolumeSnapshot.java |  54 +++++++
 .../com/cloud/storage/VolumeApiServiceImpl.java | 159 ++++++++++++++++++-
 .../vm/snapshot/VMSnapshotManagerImpl.java      |  18 +--
 5 files changed, 228 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8c93bd60/api/src/com/cloud/storage/DataStoreRole.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/DataStoreRole.java b/api/src/com/cloud/storage/DataStoreRole.java
index 0a62a56..cc20cc0 100644
--- a/api/src/com/cloud/storage/DataStoreRole.java
+++ b/api/src/com/cloud/storage/DataStoreRole.java
@@ -24,13 +24,13 @@ public enum DataStoreRole {
     Primary("primary"), Image("image"), ImageCache("imagecache"), Backup("backup");
 
     public boolean isImageStore() {
-        return (this.role.equalsIgnoreCase("image") || this.role.equalsIgnoreCase("imagecache")) ? true : false;
+        return (role.equalsIgnoreCase("image") || role.equalsIgnoreCase("imagecache")) ? true : false;
     }
 
     private final String role;
 
     DataStoreRole(String type) {
-        this.role = type;
+        role = type;
     }
 
     public static DataStoreRole getRole(String role) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8c93bd60/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 34bdbfa..323cdf9 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -4097,10 +4097,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-    public class VmJobSyncOutcome extends OutcomeImpl<VirtualMachine> {
+    public class VmJobVirtualMachineOutcome extends OutcomeImpl<VirtualMachine> {
         private long _vmId;
 
-        public VmJobSyncOutcome(final AsyncJob job, final long vmId) {
+        public VmJobVirtualMachineOutcome(final AsyncJob job, final long vmId) {
             super(VirtualMachine.class, job, VmJobCheckInterval.value(), new Predicate() {
                 @Override
                 public boolean checkCondition() {
@@ -4281,8 +4281,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
-                vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        	vm.getId());
     }
 
     public Outcome<VirtualMachine> migrateVmThroughJobQueue(final String vmUuid, final long srcHostId, final DeployDestination dest) {
@@ -4439,7 +4439,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     public Outcome<VirtualMachine> migrateVmStorageThroughJobQueue(
@@ -4491,7 +4491,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     public Outcome<VirtualMachine> addVmToNetworkThroughJobQueue(
@@ -4541,7 +4541,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     public Outcome<VirtualMachine> removeNicFromVmThroughJobQueue(
@@ -4591,7 +4591,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     public Outcome<VirtualMachine> removeVmFromNetworkThroughJobQueue(
@@ -4641,7 +4641,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     public Outcome<VirtualMachine> reconfigureVmThroughJobQueue(
@@ -4690,9 +4690,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
-        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8c93bd60/server/src/com/cloud/storage/VmWorkTakeVolumeSnapshot.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VmWorkTakeVolumeSnapshot.java b/server/src/com/cloud/storage/VmWorkTakeVolumeSnapshot.java
new file mode 100644
index 0000000..8b23808
--- /dev/null
+++ b/server/src/com/cloud/storage/VmWorkTakeVolumeSnapshot.java
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.storage;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkTakeVolumeSnapshot extends VmWork {
+
+    private static final long serialVersionUID = 341816293003023823L;
+
+    private Long volumeId;
+    private Long policyId;
+    private Long snapshotId;
+    private boolean quiesceVm;
+
+    public VmWorkTakeVolumeSnapshot(long userId, long accountId, long vmId, String handlerName,
+            Long volumeId, Long policyId, Long snapshotId, boolean quiesceVm) {
+        super(userId, accountId, vmId, handlerName);
+        this.volumeId = volumeId;
+        this.policyId = policyId;
+        this.snapshotId = snapshotId;
+        this.quiesceVm = quiesceVm;
+    }
+
+    public Long getVolumeId() {
+        return volumeId;
+    }
+
+    public Long getPolicyId() {
+        return policyId;
+    }
+
+    public Long getSnapshotId() {
+        return snapshotId;
+    }
+
+    public boolean isQuiesceVm() {
+        return quiesceVm;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8c93bd60/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index f65084a..0da8ebd 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -1631,6 +1631,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
     @Override
     public Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm) throws ResourceAllocationException {
+
         VolumeInfo volume = volFactory.getVolume(volumeId);
         if (volume == null) {
             throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
@@ -1640,6 +1641,63 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
             throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
         }
 
+        VMInstanceVO vm = null;
+        if (volume.getInstanceId() != null)
+            vm = _vmInstanceDao.findById(volume.getInstanceId());
+
+        if (vm != null) {
+            // serialize VM operation
+            AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+            if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+                // avoid re-entrance
+                return orchestrateTakeVolumeSnapshot(volumeId, policyId, snapshotId, account, quiescevm);
+            } else {
+                Outcome<Snapshot> outcome = takeVolumeSnapshotThroughJobQueue(vm.getId(), volumeId, policyId, snapshotId, account.getId(), quiescevm);
+
+                try {
+                    outcome.get();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException("Operation is interrupted", e);
+                } catch (java.util.concurrent.ExecutionException e) {
+                    throw new RuntimeException("Execution excetion", e);
+                }
+
+                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+                if (jobResult != null) {
+                    if (jobResult instanceof ConcurrentOperationException)
+                        throw (ConcurrentOperationException)jobResult;
+                    else if (jobResult instanceof ResourceAllocationException)
+                        throw (ResourceAllocationException)jobResult;
+                    else if (jobResult instanceof Throwable)
+                        throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+                }
+
+                return _snapshotDao.findById(snapshotId);
+            }
+        } else {
+            CreateSnapshotPayload payload = new CreateSnapshotPayload();
+            payload.setSnapshotId(snapshotId);
+            payload.setSnapshotPolicyId(policyId);
+            payload.setAccount(account);
+            payload.setQuiescevm(quiescevm);
+            volume.addPayload(payload);
+            return volService.takeSnapshot(volume);
+        }
+    }
+
+    private Snapshot orchestrateTakeVolumeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account account, boolean quiescevm)
+            throws ResourceAllocationException {
+
+        VolumeInfo volume = volFactory.getVolume(volumeId);
+
+        if (volume == null) {
+            throw new InvalidParameterValueException("Creating snapshot failed due to volume:" + volumeId + " doesn't exist");
+        }
+
+        if (volume.getState() != Volume.State.Ready) {
+            throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + ". Cannot take snapshot.");
+        }
+
         CreateSnapshotPayload payload = new CreateSnapshotPayload();
         payload.setSnapshotId(snapshotId);
         payload.setSnapshotPolicyId(policyId);
@@ -2019,10 +2077,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         _storagePoolAllocators = storagePoolAllocators;
     }
 
-    public class VmJobSyncOutcome extends OutcomeImpl<Volume> {
+    public class VmJobVolumeOutcome extends OutcomeImpl<Volume> {
         private long _volumeId;
 
-        public VmJobSyncOutcome(final AsyncJob job, final long volumeId) {
+        public VmJobVolumeOutcome(final AsyncJob job, final long volumeId) {
             super(Volume.class, job, VmJobCheckInterval.value(), new Predicate() {
                 @Override
                 public boolean checkCondition() {
@@ -2043,6 +2101,30 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         }
     }
 
+    public class VmJobSnapshotOutcome extends OutcomeImpl<Snapshot> {
+        private long _snapshotId;
+
+        public VmJobSnapshotOutcome(final AsyncJob job, final long snapshotId) {
+            super(Snapshot.class, job, VmJobCheckInterval.value(), new Predicate() {
+                @Override
+                public boolean checkCondition() {
+                    AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId());
+                    assert (jobVo != null);
+                    if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS)
+                        return true;
+
+                    return false;
+                }
+            }, AsyncJob.Topics.JOB_STATE);
+            _snapshotId = snapshotId;
+        }
+
+        @Override
+        protected Snapshot retrieve() {
+            return _snapshotDao.findById(_snapshotId);
+        }
+    }
+
     public Outcome<Volume> attachVolumeToVmThroughJobQueue(final Long vmId, final Long volumeId, final Long deviceId) {
 
         final CallContext context = CallContext.current();
@@ -2084,7 +2166,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), volumeId);
+        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                volumeId);
     }
 
     public Outcome<Volume> detachVolumeFromVmThroughJobQueue(final Long vmId, final Long volumeId) {
@@ -2127,7 +2210,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), volumeId);
+        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                volumeId);
     }
 
     public Outcome<Volume> resizeVolumeThroughJobQueue(final Long vmId, final long volumeId,
@@ -2172,7 +2256,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 volumeId);
     }
 
@@ -2218,10 +2302,57 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 volumeId);
     }
 
+    public Outcome<Snapshot> takeVolumeSnapshotThroughJobQueue(final Long vmId, final Long volumeId,
+            final Long policyId, final Long snapshotId, final Long accountId, final boolean quiesceVm) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkTakeVolumeSnapshot.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // 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);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                snapshotId);
+    }
+
     @Override
     public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
         VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
@@ -2287,6 +2418,22 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                         + ", volId: " + migrateWork.getVolumeId() + ", destPoolId: " + migrateWork.getDestPoolId() + ", live: " + migrateWork.isLiveMigrate());
 
             return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Long(newVol.getId())));
+        } else if (work instanceof VmWorkTakeVolumeSnapshot) {
+            VmWorkTakeVolumeSnapshot snapshotWork = (VmWorkTakeVolumeSnapshot)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Take-Volume-Snapshot within VM work job context. vmId: " + snapshotWork.getVmId()
+                        + ", volId: " + snapshotWork.getVolumeId() + ", policyId: " + snapshotWork.getPolicyId() + ", quiesceVm: " + snapshotWork.isQuiesceVm());
+
+            Account account = _accountDao.findById(snapshotWork.getAccountId());
+            orchestrateTakeVolumeSnapshot(snapshotWork.getVolumeId(), snapshotWork.getPolicyId(), snapshotWork.getSnapshotId(),
+                    account, snapshotWork.isQuiesceVm());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing Take-Volume-Snapshot within VM work job context. vmId: " + snapshotWork.getVmId()
+                        + ", volId: " + snapshotWork.getVolumeId() + ", policyId: " + snapshotWork.getPolicyId() + ", quiesceVm: " + snapshotWork.isQuiesceVm());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(snapshotWork.getSnapshotId()));
         } else {
             RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
             String exceptionJson = JobSerializerHelper.toSerializedString(e);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8c93bd60/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 1b66ff8..6a954de 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -129,7 +129,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
     // TODO
     static final ConfigKey<Boolean> VmJobEnabled = new ConfigKey<Boolean>("Advanced",
-            Boolean.class, "vm.job.enabled", "false",
+            Boolean.class, "vm.job.enabled", "true",
             "True to enable new VM sync model. false to use the old way", false);
     static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced",
             Long.class, "vm.job.check.interval", "3000",
@@ -757,10 +757,10 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         return false;
     }
 
-    public class VmJobSyncOutcome extends OutcomeImpl<VMSnapshot> {
+    public class VmJobVMSnapshotOutcome extends OutcomeImpl<VMSnapshot> {
         private long _vmSnapshotId;
 
-        public VmJobSyncOutcome(final AsyncJob job, final long vmSnapshotId) {
+        public VmJobVMSnapshotOutcome(final AsyncJob job, final long vmSnapshotId) {
             super(VMSnapshot.class, job, VmJobCheckInterval.value(), new Predicate() {
                 @Override
                 public boolean checkCondition() {
@@ -781,10 +781,10 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         }
     }
 
-    public class VmJobSyncVirtualMachineOutcome extends OutcomeImpl<VirtualMachine> {
+    public class VmJobVirtualMachineOutcome extends OutcomeImpl<VirtualMachine> {
         long vmId;
 
-        public VmJobSyncVirtualMachineOutcome(final AsyncJob job, final long vmId) {
+        public VmJobVirtualMachineOutcome(final AsyncJob job, final long vmId) {
             super(VirtualMachine.class, job, VmJobCheckInterval.value(), new Predicate() {
                 @Override
                 public boolean checkCondition() {
@@ -845,7 +845,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 vmSnapshotId);
     }
 
@@ -890,7 +890,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 vmSnapshotId);
     }
 
@@ -935,7 +935,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 vmSnapshotId);
     }
 
@@ -980,7 +980,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         final long jobId = (Long)context.getContextParameter("jobId");
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSyncVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
                 vmId);
     }
 


[04/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-669: covert VMsnapshot orchestration flows to make them be serialized with other VM operations


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

Branch: refs/heads/master
Commit: bf9a5545224548fad3f8321868b5372a6f1bd797
Parents: a298f6f
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Dec 20 16:45:08 2013 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 ...spring-engine-orchestration-core-context.xml |   1 +
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 130 ++---
 .../framework/jobs/AsyncJobManager.java         |  12 +-
 .../jobs/impl/AsyncJobManagerImpl.java          |  16 +
 .../com/cloud/storage/VmWorkMigrateVolume.java  |  46 ++
 .../com/cloud/storage/VmWorkResizeVolume.java   |  61 ++
 .../com/cloud/storage/VolumeApiServiceImpl.java | 243 +++++++-
 .../vm/snapshot/VMSnapshotManagerImpl.java      | 571 ++++++++++++++++++-
 .../vm/snapshot/VmWorkCreateVMSnapshot.java     |  41 ++
 .../vm/snapshot/VmWorkDeleteAllVMSnapshots.java |  35 ++
 .../vm/snapshot/VmWorkDeleteVMSnapshot.java     |  35 ++
 .../vm/snapshot/VmWorkRevertToVMSnapshot.java   |  35 ++
 12 files changed, 1098 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
----------------------------------------------------------------------
diff --git a/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml b/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
index 2e35ae5..7445102 100644
--- a/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
+++ b/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
@@ -81,6 +81,7 @@
             <map>
                 <entry key="VirtualMachineManagerImpl" value-ref="clusteredVirtualMachineManagerImpl" />
                 <entry key="VolumeApiServiceImpl" value-ref="volumeApiServiceImpl" />
+                <entry key="VMSnapshotManagerImpl" value-ref="vMSnapshotManagerImpl" />
             </map>
         </property>
     </bean>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index a81fea8..34bdbfa 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -42,7 +42,6 @@ import javax.naming.ConfigurationException;
 
 import org.apache.log4j.Logger;
 
-import com.cloud.deploy.DeploymentPlanner;
 import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@@ -119,6 +118,7 @@ import com.cloud.dc.dao.HostPodDao;
 import com.cloud.deploy.DataCenterDeployment;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.deploy.DeploymentPlan;
+import com.cloud.deploy.DeploymentPlanner;
 import com.cloud.deploy.DeploymentPlanner.ExcludeList;
 import com.cloud.deploy.DeploymentPlanningManager;
 import com.cloud.domain.dao.DomainDao;
@@ -726,12 +726,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else if (jobException instanceof ResourceUnavailableException)
-                    throw (ResourceUnavailableException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
             }
         }
     }
@@ -739,7 +739,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     @Override
     public void orchestrateStart(String vmUuid, Map<VirtualMachineProfile.Param, Object> params, DeploymentPlan planToDeploy, DeploymentPlanner planner)
-        throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
+            throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
 
         CallContext cctxt = CallContext.current();
         Account account = cctxt.getCallingAccount();
@@ -1248,14 +1248,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof AgentUnavailableException)
-                    throw (AgentUnavailableException)jobException;
-                else if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else if (jobException instanceof OperationTimedoutException)
-                    throw (OperationTimedoutException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof AgentUnavailableException)
+                    throw (AgentUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof OperationTimedoutException)
+                    throw (OperationTimedoutException)jobResult;
             }
         }
     }
@@ -1540,10 +1540,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof RuntimeException)
-                    throw (RuntimeException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof RuntimeException)
+                    throw (RuntimeException)jobResult;
             }
         }
     }
@@ -1622,14 +1622,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ResourceUnavailableException)
-                    throw (ResourceUnavailableException)jobException;
-                else if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else if (jobException instanceof RuntimeException)
-                    throw (RuntimeException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof RuntimeException)
+                    throw (RuntimeException)jobResult;
             }
         }
     }
@@ -1893,7 +1893,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
+            Object jobException = _jobMgr.unmarshallResultObject(outcome.getJob());
             if (jobException != null) {
                 if (jobException instanceof ResourceUnavailableException)
                     throw (ResourceUnavailableException)jobException;
@@ -2172,14 +2172,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ResourceUnavailableException)
-                    throw (ResourceUnavailableException)jobException;
-                else if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else if (jobException instanceof InsufficientCapacityException)
-                    throw (InsufficientCapacityException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof InsufficientCapacityException)
+                    throw (InsufficientCapacityException)jobResult;
             }
         }
     }
@@ -3099,7 +3099,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 NicProfile nic = (NicProfile)JobSerializerHelper.fromObjectSerializedString(jobVo.getResult());
                 return nic;
             } else {
-                Throwable jobException = retrieveExecutionException(outcome.getJob());
+                Object jobException = _jobMgr.unmarshallResultObject(outcome.getJob());
                 if (jobException != null) {
                     if (jobException instanceof ResourceUnavailableException)
                         throw (ResourceUnavailableException)jobException;
@@ -3206,14 +3206,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 Boolean result = (Boolean)JobSerializerHelper.fromObjectSerializedString(jobVo.getResult());
                 return result;
             } else {
-                Throwable jobException = retrieveExecutionException(outcome.getJob());
-                if (jobException != null) {
-                    if (jobException instanceof ResourceUnavailableException)
-                        throw (ResourceUnavailableException)jobException;
-                    else if (jobException instanceof ConcurrentOperationException)
-                        throw (ConcurrentOperationException)jobException;
-                    else if (jobException instanceof RuntimeException)
-                        throw (RuntimeException)jobException;
+                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+                if (jobResult != null) {
+                    if (jobResult instanceof ResourceUnavailableException)
+                        throw (ResourceUnavailableException)jobResult;
+                    else if (jobResult instanceof ConcurrentOperationException)
+                        throw (ConcurrentOperationException)jobResult;
+                    else if (jobResult instanceof RuntimeException)
+                        throw (RuntimeException)jobResult;
                 }
 
                 throw new RuntimeException("Job failed with un-handled exception");
@@ -3444,12 +3444,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ResourceUnavailableException)
-                    throw (ResourceUnavailableException)jobException;
-                else if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
             }
         }
     }
@@ -3698,12 +3698,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             if (jobVo.getResultCode() == JobInfo.Status.SUCCEEDED.ordinal()) {
                 return _entityMgr.findById(VMInstanceVO.class, vm.getId());
             } else {
-                Throwable jobException = retrieveExecutionException(outcome.getJob());
-                if (jobException != null) {
-                    if (jobException instanceof ResourceUnavailableException)
-                        throw (ResourceUnavailableException)jobException;
-                    else if (jobException instanceof ConcurrentOperationException)
-                        throw (ConcurrentOperationException)jobException;
+                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+                if (jobResult != null) {
+                    if (jobResult instanceof ResourceUnavailableException)
+                        throw (ResourceUnavailableException)jobResult;
+                    else if (jobResult instanceof ConcurrentOperationException)
+                        throw (ConcurrentOperationException)jobResult;
                 }
 
                 throw new RuntimeException("Failed with un-handled exception");
@@ -4121,20 +4121,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-    public Throwable retrieveExecutionException(AsyncJob job) {
-        assert (job != null);
-        assert (job.getDispatcher().equals(VmWorkConstants.VM_WORK_JOB_DISPATCHER));
-
-        AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId());
-        if (jobVo != null && jobVo.getResult() != null) {
-            Object obj = JobSerializerHelper.fromSerializedString(job.getResult());
-
-            if (obj != null && obj instanceof Throwable)
-                return (Throwable)obj;
-        }
-        return null;
-    }
-
     //
     // TODO build a common pattern to reduce code duplication in following methods
     // no time for this at current iteration

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobManager.java
----------------------------------------------------------------------
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobManager.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobManager.java
index d1a4a9d..67733ed 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobManager.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobManager.java
@@ -16,6 +16,7 @@
 // under the License.
 package org.apache.cloudstack.framework.jobs;
 
+import java.io.Serializable;
 import java.util.List;
 
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
@@ -41,8 +42,8 @@ public interface AsyncJobManager extends Manager {
     void updateAsyncJobStatus(long jobId, int processStatus, String resultObject);
 
     void updateAsyncJobAttachment(long jobId, String instanceType, Long instanceId);
-
-    void logJobJournal(long jobId, AsyncJob.JournalType journalType, String journalText, String journalObjJson);
+    void logJobJournal(long jobId, AsyncJob.JournalType journalType, String
+            journalText, String journalObjJson);
 
     /**
      * A running thread inside management server can have a 1:1 linked pseudo job.
@@ -81,8 +82,8 @@ public interface AsyncJobManager extends Manager {
      * @param wakeupIntervalInMilliSeconds
      * @param timeoutInMilliSeconds
      */
-    void joinJob(long jobId, long joinJobId, String wakeupHandler, String wakupDispatcher, String[] wakeupTopicsOnMessageBus, long wakeupIntervalInMilliSeconds,
-        long timeoutInMilliSeconds);
+    void joinJob(long jobId, long joinJobId, String wakeupHandler, String wakupDispatcher,
+            String[] wakeupTopicsOnMessageBus, long wakeupIntervalInMilliSeconds, long timeoutInMilliSeconds);
 
     /**
      * Dis-join two related jobs
@@ -124,4 +125,7 @@ public interface AsyncJobManager extends Manager {
 
     AsyncJob queryJob(long jobId, boolean updatePollTime);
 
+    String marshallResultObject(Serializable obj);
+
+    Object unmarshallResultObject(AsyncJob job);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
----------------------------------------------------------------------
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 d98d832..e9442ec 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
@@ -17,6 +17,7 @@
 
 package org.apache.cloudstack.framework.jobs.impl;
 
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -611,6 +612,21 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
         return false;
     }
 
+    @Override
+    public String marshallResultObject(Serializable obj) {
+        if (obj != null)
+            return JobSerializerHelper.toObjectSerializedString(obj);
+
+        return null;
+    }
+
+    @Override
+    public Object unmarshallResultObject(AsyncJob job) {
+        if(job.getResult() != null)
+            return JobSerializerHelper.fromObjectSerializedString(job.getResult());
+        return null;
+    }
+
     private void checkQueue(long queueId) {
         while (true) {
             try {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/storage/VmWorkMigrateVolume.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VmWorkMigrateVolume.java b/server/src/com/cloud/storage/VmWorkMigrateVolume.java
new file mode 100644
index 0000000..c83e02d
--- /dev/null
+++ b/server/src/com/cloud/storage/VmWorkMigrateVolume.java
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.storage;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkMigrateVolume extends VmWork {
+    private static final long serialVersionUID = -565778516928408602L;
+
+    private long volumeId;
+    private long destPoolId;
+    private boolean liveMigrate;
+
+    public VmWorkMigrateVolume(long userId, long accountId, long vmId, String handlerName, long volumeId, long destPoolId, boolean liveMigrate) {
+        super(userId, accountId, vmId, handlerName);
+        this.volumeId = volumeId;
+        this.destPoolId = destPoolId;
+        this.liveMigrate = liveMigrate;
+    }
+
+    public long getVolumeId() {
+        return volumeId;
+    }
+
+    public long getDestPoolId() {
+        return destPoolId;
+    }
+
+    public boolean isLiveMigrate() {
+        return liveMigrate;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/storage/VmWorkResizeVolume.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VmWorkResizeVolume.java b/server/src/com/cloud/storage/VmWorkResizeVolume.java
new file mode 100644
index 0000000..3ccaecd
--- /dev/null
+++ b/server/src/com/cloud/storage/VmWorkResizeVolume.java
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.storage;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkResizeVolume extends VmWork {
+    private static final long serialVersionUID = 6112366316907642498L;
+
+    private long volumeId;
+    private long currentSize;
+    private long newSize;
+    private Long newServiceOfferingId;
+    private boolean shrinkOk;
+
+    public VmWorkResizeVolume(long userId, long accountId, long vmId, String handlerName,
+            long volumeId, long currentSize, long newSize, Long newServiceOfferingId, boolean shrinkOk) {
+
+        super(userId, accountId, vmId, handlerName);
+
+        this.volumeId = volumeId;
+        this.currentSize = currentSize;
+        this.newSize = newSize;
+        this.newServiceOfferingId = newServiceOfferingId;
+        this.shrinkOk = shrinkOk;
+    }
+
+    public long getVolumeId() {
+        return volumeId;
+    }
+
+    public long getCurrentSize() {
+        return currentSize;
+    }
+
+    public long getNewSize() {
+        return newSize;
+    }
+
+    public Long getNewServiceOfferingId() {
+        return newServiceOfferingId;
+    }
+
+    public boolean isShrinkOk() {
+        return shrinkOk;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index e1d1c7c..f65084a 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -906,6 +906,43 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                     - currentSize));
         }
 
+        if (userVm != null) {
+            // serialize VM operation
+            AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+            if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+                // avoid re-entrance
+                return orchestrateResizeVolume(volume.getId(), currentSize, newSize,
+                        newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
+            } else {
+                Outcome<Volume> outcome = resizeVolumeThroughJobQueue(userVm.getId(), volume.getId(), currentSize, newSize,
+                        newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
+
+                Volume vol = null;
+                try {
+                    vol = outcome.get();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException("Operation is interrupted", e);
+                } catch (java.util.concurrent.ExecutionException e) {
+                    throw new RuntimeException("Execution excetion", e);
+                }
+
+                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+                if (jobResult != null) {
+                    if (jobResult instanceof ConcurrentOperationException)
+                        throw (ConcurrentOperationException)jobResult;
+                    else if (jobResult instanceof Throwable)
+                        throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+                }
+                return volume;
+            }
+        }
+        return orchestrateResizeVolume(volume.getId(), currentSize, newSize,
+                newDiskOffering != null ? cmd.getNewDiskOfferingId() : null, shrinkOk);
+    }
+
+    private VolumeVO orchestrateResizeVolume(long volumeId, long currentSize, long newSize, Long newDiskOfferingId, boolean shrinkOk) {
+        VolumeVO volume = _volsDao.findById(volumeId);
+        UserVmVO userVm = _userVmDao.findById(volume.getInstanceId());
         /*
          * get a list of hosts to send the commands to, try the system the
          * associated vm is running on first, then the last known place it ran.
@@ -943,8 +980,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
             volume = _volsDao.findById(volume.getId());
 
-            if (newDiskOffering != null) {
-                volume.setDiskOfferingId(cmd.getNewDiskOfferingId());
+            if (newDiskOfferingId != null) {
+                volume.setDiskOfferingId(newDiskOfferingId);
             }
             _volsDao.update(volume.getId(), volume);
             // Log usage event for volumes belonging user VM's only
@@ -1078,12 +1115,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else
-                    throw new RuntimeException("Unexpected exception", jobException);
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
             }
             return vol;
         }
@@ -1383,12 +1420,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            Throwable jobException = retrieveExecutionException(outcome.getJob());
-            if (jobException != null) {
-                if (jobException instanceof ConcurrentOperationException)
-                    throw (ConcurrentOperationException)jobException;
-                else
-                    throw new RuntimeException("Unexpected exception", jobException);
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
             }
             return vol;
         }
@@ -1517,6 +1554,48 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
             throw new InvalidParameterValueException("Migration of volume from local storage pool is not supported");
         }
 
+        if (vm != null) {
+            // serialize VM operation
+            AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+            if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+                // avoid re-entrance
+                return orchestrateMigrateVolume(vol.getId(), destPool.getId(), liveMigrateVolume);
+            } else {
+                Outcome<Volume> outcome = migrateVolumeThroughJobQueue(vm.getId(), vol.getId(), destPool.getId(), liveMigrateVolume);
+
+                try {
+                    outcome.get();
+                } catch (InterruptedException e) {
+                    throw new RuntimeException("Operation is interrupted", e);
+                } catch (java.util.concurrent.ExecutionException e) {
+                    throw new RuntimeException("Execution excetion", e);
+                }
+
+                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+                if (jobResult != null) {
+                    if (jobResult instanceof ConcurrentOperationException)
+                        throw (ConcurrentOperationException)jobResult;
+                    else if (jobResult instanceof Throwable)
+                        throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+                }
+
+                // retrieve the migrated new volume from job result
+                if (jobResult != null && jobResult instanceof Long) {
+                    return _entityMgr.findById(VolumeVO.class, ((Long)jobResult).longValue());
+                }
+                return null;
+            }
+        }
+
+        return orchestrateMigrateVolume(vol.getId(), destPool.getId(), liveMigrateVolume);
+    }
+
+    private Volume orchestrateMigrateVolume(long volumeId, long destPoolId, boolean liveMigrateVolume) {
+        VolumeVO vol = _volsDao.findById(volumeId);
+        assert (vol != null);
+        StoragePool destPool = (StoragePool)dataStoreMgr.getDataStore(destPoolId, DataStoreRole.Primary);
+        assert (destPool != null);
+
         Volume newVol = null;
         if (liveMigrateVolume) {
             newVol = liveMigrateVolume(vol, destPool);
@@ -1940,20 +2019,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         _storagePoolAllocators = storagePoolAllocators;
     }
 
-    public Throwable retrieveExecutionException(AsyncJob job) {
-        assert (job != null);
-        assert (job.getDispatcher().equals(VmWorkConstants.VM_WORK_JOB_DISPATCHER));
-
-        AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId());
-        if (jobVo != null && jobVo.getResult() != null) {
-            Object obj = JobSerializerHelper.fromSerializedString(job.getResult());
-
-            if (obj != null && obj instanceof Throwable)
-                return (Throwable)obj;
-        }
-        return null;
-    }
-
     public class VmJobSyncOutcome extends OutcomeImpl<Volume> {
         private long _volumeId;
 
@@ -2065,6 +2130,98 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"), volumeId);
     }
 
+    public Outcome<Volume> resizeVolumeThroughJobQueue(final Long vmId, final long volumeId,
+            final long currentSize, final long newSize, final Long newServiceOfferingId, final boolean shrinkOk) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkResizeVolume.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkResizeVolume workInfo = new VmWorkResizeVolume(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, currentSize, newSize, newServiceOfferingId, shrinkOk);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                volumeId);
+    }
+
+    public Outcome<Volume> migrateVolumeThroughJobQueue(final Long vmId, final long volumeId,
+            final long destPoolId, final boolean liveMigrate) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkMigrateVolume.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkMigrateVolume workInfo = new VmWorkMigrateVolume(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId, destPoolId, liveMigrate);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                volumeId);
+    }
+
     @Override
     public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
         VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
@@ -2100,6 +2257,36 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 s_logger.debug("Done executing Detach-Volume within VM work job context. vmId: " + detachWork.getVmId() + ", volId: " + detachWork.getVolumeId());
 
             return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+        } else if (work instanceof VmWorkResizeVolume) {
+            VmWorkResizeVolume resizeWork = (VmWorkResizeVolume)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Resize-Volume within VM work job context. vmId: " + resizeWork.getVmId()
+                        + ", volId: " + resizeWork.getVolumeId() + ", size " + resizeWork.getCurrentSize() + " -> " + resizeWork.getNewSize());
+
+            orchestrateResizeVolume(resizeWork.getVolumeId(), resizeWork.getCurrentSize(), resizeWork.getNewSize(),
+                    resizeWork.getNewServiceOfferingId(), resizeWork.isShrinkOk());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing Resize-Volume within VM work job context. vmId: " + resizeWork.getVmId()
+                        + ", volId: " + resizeWork.getVolumeId() + ", size " + resizeWork.getCurrentSize() + " -> " + resizeWork.getNewSize());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+
+        } else if (work instanceof VmWorkMigrateVolume) {
+            VmWorkMigrateVolume migrateWork = (VmWorkMigrateVolume)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Migrate-Volume within VM work job context. vmId: " + migrateWork.getVmId()
+                        + ", volId: " + migrateWork.getVolumeId() + ", destPoolId: " + migrateWork.getDestPoolId() + ", live: " + migrateWork.isLiveMigrate());
+
+            Volume newVol = orchestrateMigrateVolume(migrateWork.getVolumeId(), migrateWork.getDestPoolId(), migrateWork.isLiveMigrate());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing Migrate-Volume within VM work job context. vmId: " + migrateWork.getVmId()
+                        + ", volId: " + migrateWork.getVolumeId() + ", destPoolId: " + migrateWork.getDestPoolId() + ", live: " + migrateWork.isLiveMigrate());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Long(newVol.getId())));
         } else {
             RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
             String exceptionJson = JobSerializerHelper.toSerializedString(e);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 93c845a..1b66ff8 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -35,7 +35,17 @@ import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotOptions;
 import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotStrategy;
+import org.apache.cloudstack.framework.config.ConfigKey;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJob;
+import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.Outcome;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
+import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
+import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl;
+import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
+import org.apache.cloudstack.jobs.JobInfo;
 
 import com.cloud.event.ActionEvent;
 import com.cloud.event.EventTypes;
@@ -55,15 +65,22 @@ import com.cloud.storage.dao.SnapshotDao;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
+import com.cloud.user.User;
 import com.cloud.user.dao.AccountDao;
 import com.cloud.uservm.UserVm;
 import com.cloud.utils.DateUtil;
 import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.Predicate;
 import com.cloud.utils.Ternary;
 import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.EntityManager;
 import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
+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.vm.UserVmVO;
 import com.cloud.vm.VMInstanceVO;
@@ -71,40 +88,53 @@ import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.State;
 import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.VmWork;
+import com.cloud.vm.VmWorkConstants;
+import com.cloud.vm.VmWorkJobHandler;
+import com.cloud.vm.VmWorkSerializer;
 import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.dao.VMInstanceDao;
 import com.cloud.vm.snapshot.dao.VMSnapshotDao;
 
 @Component
-@Local(value = {VMSnapshotManager.class, VMSnapshotService.class})
-public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotManager, VMSnapshotService {
+@Local(value = { VMSnapshotManager.class, VMSnapshotService.class })
+public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotManager, VMSnapshotService, VmWorkJobHandler {
     private static final Logger s_logger = Logger.getLogger(VMSnapshotManagerImpl.class);
+
+    public static final String VM_WORK_JOB_HANDLER = VMSnapshotManagerImpl.class.getSimpleName();
+
     String _name;
     @Inject
-    VMSnapshotDao _vmSnapshotDao;
-    @Inject
-    VolumeDao _volumeDao;
-    @Inject
-    AccountDao _accountDao;
-    @Inject
-    UserVmDao _userVMDao;
-    @Inject
-    AccountManager _accountMgr;
-    @Inject
-    GuestOSDao _guestOSDao;
+    VMInstanceDao _vmInstanceDao;
+    @Inject VMSnapshotDao _vmSnapshotDao;
+    @Inject VolumeDao _volumeDao;
+    @Inject AccountDao _accountDao;
+    @Inject UserVmDao _userVMDao;
+    @Inject AccountManager _accountMgr;
+    @Inject GuestOSDao _guestOSDao;
+    @Inject SnapshotDao _snapshotDao;
+    @Inject VirtualMachineManager _itMgr;
+    @Inject ConfigurationDao _configDao;
+    @Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
     @Inject
-    SnapshotDao _snapshotDao;
-    @Inject
-    VirtualMachineManager _itMgr;
-    @Inject
-    ConfigurationDao _configDao;
+    StorageStrategyFactory storageStrategyFactory;
+
     @Inject
-    HypervisorCapabilitiesDao _hypervisorCapabilitiesDao;
+    EntityManager _entityMgr;
     @Inject
-    StorageStrategyFactory storageStrategyFactory;
+    AsyncJobManager _jobMgr;
 
     int _vmSnapshotMax;
     int _wait;
 
+    // TODO
+    static final ConfigKey<Boolean> VmJobEnabled = new ConfigKey<Boolean>("Advanced",
+            Boolean.class, "vm.job.enabled", "false",
+            "True to enable new VM sync model. false to use the old way", false);
+    static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced",
+            Long.class, "vm.job.check.interval", "3000",
+            "Interval in milliseconds to check if the job is complete", false);
+
     @Override
     public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
         _name = name;
@@ -249,7 +279,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
             throw new InvalidParameterValueException("Creating vm snapshot failed due to VM:" + vmId + " is not in the running or Stopped state");
         }
 
-        if (snapshotMemory && userVmVo.getState() == VirtualMachine.State.Stopped) {
+        if(snapshotMemory && userVmVo.getState() == VirtualMachine.State.Stopped){
             throw new InvalidParameterValueException("Can not snapshot memory when VM is in stopped state");
         }
 
@@ -327,6 +357,46 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         if (vmSnapshot == null) {
             throw new CloudRuntimeException("VM snapshot id: " + vmSnapshotId + " can not be found");
         }
+
+        // serialize VM operation
+        AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+        if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+            // avoid re-entrance
+            return orchestrateCreateVMSnapshot(vmId, vmSnapshotId, quiescevm);
+        } else {
+            Outcome<VMSnapshot> outcome = createVMSnapshotThroughJobQueue(vmId, vmSnapshotId, quiescevm);
+
+            VMSnapshot result = null;
+            try {
+                result = outcome.get();
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Operation is interrupted", e);
+            } catch (java.util.concurrent.ExecutionException e) {
+                throw new RuntimeException("Execution excetion", e);
+            }
+
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+            }
+
+            return result;
+        }
+    }
+
+    private VMSnapshot orchestrateCreateVMSnapshot(Long vmId, Long vmSnapshotId, Boolean quiescevm) {
+        UserVmVO userVm = _userVMDao.findById(vmId);
+        if (userVm == null) {
+            throw new InvalidParameterValueException("Create vm to snapshot failed due to vm: " + vmId + " is not found");
+        }
+        VMSnapshotVO vmSnapshot = _vmSnapshotDao.findById(vmSnapshotId);
+        if (vmSnapshot == null) {
+            throw new CloudRuntimeException("VM snapshot id: " + vmSnapshotId + " can not be found");
+        }
+
         VMSnapshotOptions options = new VMSnapshotOptions(quiescevm);
         vmSnapshot.setOptions(options);
         try {
@@ -376,6 +446,62 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 throw new InvalidParameterValueException("There is other active vm snapshot tasks on the instance, please try again later");
         }
 
+        // serialize VM operation
+        AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+        if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+            // avoid re-entrance
+            return orchestrateDeleteVMSnapshot(vmSnapshotId);
+        } else {
+            Outcome<VMSnapshot> outcome = deleteVMSnapshotThroughJobQueue(vmSnapshot.getVmId(), vmSnapshotId);
+
+            VMSnapshot result = null;
+            try {
+                result = outcome.get();
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Operation is interrupted", e);
+            } catch (java.util.concurrent.ExecutionException e) {
+                throw new RuntimeException("Execution excetion", e);
+            }
+
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+            }
+
+            if (jobResult instanceof Boolean)
+                return ((Boolean)jobResult).booleanValue();
+
+            return false;
+        }
+    }
+
+    public boolean orchestrateDeleteVMSnapshot(Long vmSnapshotId) {
+        Account caller = getCaller();
+
+        VMSnapshotVO vmSnapshot = _vmSnapshotDao.findById(vmSnapshotId);
+        if (vmSnapshot == null) {
+            throw new InvalidParameterValueException("unable to find the vm snapshot with id " + vmSnapshotId);
+        }
+
+        _accountMgr.checkAccess(caller, null, true, vmSnapshot);
+
+        // check VM snapshot states, only allow to delete vm snapshots in created and error state
+        if (VMSnapshot.State.Ready != vmSnapshot.getState() && VMSnapshot.State.Expunging != vmSnapshot.getState() && VMSnapshot.State.Error != vmSnapshot.getState()) {
+            throw new InvalidParameterValueException("Can't delete the vm snapshotshot " + vmSnapshotId + " due to it is not in Created or Error, or Expunging State");
+        }
+
+        // check if there are other active VM snapshot tasks
+        if (hasActiveVMSnapshotTasks(vmSnapshot.getVmId())) {
+            List<VMSnapshotVO> expungingSnapshots = _vmSnapshotDao.listByInstanceId(vmSnapshot.getVmId(), VMSnapshot.State.Expunging);
+            if (expungingSnapshots.size() > 0 && expungingSnapshots.get(0).getId() == vmSnapshot.getId())
+                s_logger.debug("Target VM snapshot already in expunging state, go on deleting it: " + vmSnapshot.getDisplayName());
+            else
+                throw new InvalidParameterValueException("There is other active vm snapshot tasks on the instance, please try again later");
+        }
+
         if (vmSnapshot.getState() == VMSnapshot.State.Allocated) {
             return _vmSnapshotDao.remove(vmSnapshot.getId());
         } else {
@@ -414,6 +540,77 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         _accountMgr.checkAccess(caller, null, true, vmSnapshotVo);
 
         // VM should be in running or stopped states
+        if (userVm.getState() != VirtualMachine.State.Running
+                && userVm.getState() != VirtualMachine.State.Stopped) {
+            throw new InvalidParameterValueException(
+                    "VM Snapshot reverting failed due to vm is not in the state of Running or Stopped.");
+        }
+
+        // if snapshot is not created, error out
+        if (vmSnapshotVo.getState() != VMSnapshot.State.Ready) {
+            throw new InvalidParameterValueException(
+                    "VM Snapshot reverting failed due to vm snapshot is not in the state of Created.");
+        }
+
+        // serialize VM operation
+        AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+        if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+            // avoid re-entrance
+            return orchestrateRevertToVMSnapshot(vmSnapshotId);
+        } else {
+            Outcome<VMSnapshot> outcome = revertToVMSnapshotThroughJobQueue(vmSnapshotVo.getVmId(), vmSnapshotId);
+
+            VMSnapshot result = null;
+            try {
+                result = outcome.get();
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Operation is interrupted", e);
+            } catch (java.util.concurrent.ExecutionException e) {
+                throw new RuntimeException("Execution excetion", e);
+            }
+
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof InsufficientCapacityException)
+                    throw (InsufficientCapacityException)jobResult;
+                else if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+            }
+
+            return userVm;
+        }
+    }
+
+    public UserVm orchestrateRevertToVMSnapshot(Long vmSnapshotId) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException {
+
+        // check if VM snapshot exists in DB
+        VMSnapshotVO vmSnapshotVo = _vmSnapshotDao.findById(vmSnapshotId);
+        if (vmSnapshotVo == null) {
+            throw new InvalidParameterValueException(
+                    "unable to find the vm snapshot with id " + vmSnapshotId);
+        }
+        Long vmId = vmSnapshotVo.getVmId();
+        UserVmVO userVm = _userVMDao.findById(vmId);
+        // check if VM exists
+        if (userVm == null) {
+            throw new InvalidParameterValueException("Revert vm to snapshot: "
+                    + vmSnapshotId + " failed due to vm: " + vmId
+                    + " is not found");
+        }
+
+        // check if there are other active VM snapshot tasks
+        if (hasActiveVMSnapshotTasks(vmId)) {
+            throw new InvalidParameterValueException("There is other active vm snapshot tasks on the instance, please try again later");
+        }
+
+        Account caller = getCaller();
+        _accountMgr.checkAccess(caller, null, true, vmSnapshotVo);
+
+        // VM should be in running or stopped states
         if (userVm.getState() != VirtualMachine.State.Running && userVm.getState() != VirtualMachine.State.Stopped) {
             throw new InvalidParameterValueException("VM Snapshot reverting failed due to vm is not in the state of Running or Stopped.");
         }
@@ -481,6 +678,38 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
     @Override
     public boolean deleteAllVMSnapshots(long vmId, VMSnapshot.Type type) {
+        // serialize VM operation
+        AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
+        if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
+            // avoid re-entrance
+            return orchestrateDeleteAllVMSnapshots(vmId, type);
+        } else {
+            Outcome<VirtualMachine> outcome = deleteAllVMSnapshotsThroughJobQueue(vmId, type);
+
+            try {
+                outcome.get();
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Operation is interrupted", e);
+            } catch (java.util.concurrent.ExecutionException e) {
+                throw new RuntimeException("Execution excetion", e);
+            }
+
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof Throwable)
+                    throw new RuntimeException("Unexpected exception", (Throwable)jobResult);
+            }
+
+            if (jobResult instanceof Boolean)
+                return (Boolean)jobResult;
+
+            return false;
+        }
+    }
+
+    private boolean orchestrateDeleteAllVMSnapshots(long vmId, VMSnapshot.Type type) {
         boolean result = true;
         List<VMSnapshotVO> listVmSnapshots = _vmSnapshotDao.findByVm(vmId);
         if (listVmSnapshots == null || listVmSnapshots.isEmpty()) {
@@ -501,14 +730,13 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
     @Override
     public boolean syncVMSnapshot(VMInstanceVO vm, Long hostId) {
-        try {
+        try{
 
             UserVmVO userVm = _userVMDao.findById(vm.getId());
             if (userVm == null)
                 return false;
 
-            List<VMSnapshotVO> vmSnapshotsInExpungingStates =
-                _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
+            List<VMSnapshotVO> vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Reverting, VMSnapshot.State.Creating);
             for (VMSnapshotVO vmSnapshotVO : vmSnapshotsInExpungingStates) {
                 VMSnapshotStrategy strategy = findVMSnapshotStrategy(vmSnapshotVO);
                 if (vmSnapshotVO.getState() == VMSnapshot.State.Expunging) {
@@ -529,4 +757,299 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         return false;
     }
 
+    public class VmJobSyncOutcome extends OutcomeImpl<VMSnapshot> {
+        private long _vmSnapshotId;
+
+        public VmJobSyncOutcome(final AsyncJob job, final long vmSnapshotId) {
+            super(VMSnapshot.class, job, VmJobCheckInterval.value(), new Predicate() {
+                @Override
+                public boolean checkCondition() {
+                    AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId());
+                    assert (jobVo != null);
+                    if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS)
+                        return true;
+
+                    return false;
+                }
+            }, AsyncJob.Topics.JOB_STATE);
+            _vmSnapshotId = vmSnapshotId;
+        }
+
+        @Override
+        protected VMSnapshot retrieve() {
+            return _vmSnapshotDao.findById(_vmSnapshotId);
+        }
+    }
+
+    public class VmJobSyncVirtualMachineOutcome extends OutcomeImpl<VirtualMachine> {
+        long vmId;
+
+        public VmJobSyncVirtualMachineOutcome(final AsyncJob job, final long vmId) {
+            super(VirtualMachine.class, job, VmJobCheckInterval.value(), new Predicate() {
+                @Override
+                public boolean checkCondition() {
+                    AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId());
+                    assert (jobVo != null);
+                    if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS)
+                        return true;
+
+                    return false;
+                }
+            }, AsyncJob.Topics.JOB_STATE);
+        }
+
+        @Override
+        protected VirtualMachine retrieve() {
+            return _vmInstanceDao.findById(vmId);
+        }
+    }
+
+    public Outcome<VMSnapshot> createVMSnapshotThroughJobQueue(final Long vmId, final Long vmSnapshotId, final boolean quiesceVm) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkCreateVMSnapshot.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkCreateVMSnapshot workInfo = new VmWorkCreateVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VMSnapshotManagerImpl.VM_WORK_JOB_HANDLER, vmSnapshotId, quiesceVm);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                vmSnapshotId);
+    }
+
+    public Outcome<VMSnapshot> deleteVMSnapshotThroughJobQueue(final Long vmId, final Long vmSnapshotId) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkDeleteVMSnapshot.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkDeleteVMSnapshot workInfo = new VmWorkDeleteVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VMSnapshotManagerImpl.VM_WORK_JOB_HANDLER, vmSnapshotId);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                vmSnapshotId);
+    }
+
+    public Outcome<VMSnapshot> revertToVMSnapshotThroughJobQueue(final Long vmId, final Long vmSnapshotId) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkRevertToVMSnapshot.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkRevertToVMSnapshot workInfo = new VmWorkRevertToVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VMSnapshotManagerImpl.VM_WORK_JOB_HANDLER, vmSnapshotId);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                vmSnapshotId);
+    }
+
+    public Outcome<VirtualMachine> deleteAllVMSnapshotsThroughJobQueue(final Long vmId, final VMSnapshot.Type type) {
+
+        final CallContext context = CallContext.current();
+        final User callingUser = context.getCallingUser();
+        final Account callingAccount = context.getCallingAccount();
+
+        final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
+
+        Transaction.execute(new TransactionCallbackNoReturn() {
+            @Override
+            public void doInTransactionWithoutResult(TransactionStatus status) {
+                VmWorkJobVO workJob = null;
+
+                _vmInstanceDao.lockRow(vm.getId(), true);
+                workJob = new VmWorkJobVO(context.getContextId());
+
+                workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER);
+                workJob.setCmd(VmWorkDeleteAllVMSnapshots.class.getName());
+
+                workJob.setAccountId(callingAccount.getId());
+                workJob.setUserId(callingUser.getId());
+                workJob.setStep(VmWorkJobVO.Step.Starting);
+                workJob.setVmType(vm.getType());
+                workJob.setVmInstanceId(vm.getId());
+
+                // save work context info (there are some duplications)
+                VmWorkDeleteAllVMSnapshots workInfo = new VmWorkDeleteAllVMSnapshots(callingUser.getId(), callingAccount.getId(), vm.getId(),
+                        VMSnapshotManagerImpl.VM_WORK_JOB_HANDLER, type);
+                workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
+
+                _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
+
+                // Transaction syntax sugar has a cost here
+                context.putContextParameter("workJob", workJob);
+                context.putContextParameter("jobId", new Long(workJob.getId()));
+            }
+        });
+
+        final long jobId = (Long)context.getContextParameter("jobId");
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobSyncVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+                vmId);
+    }
+
+    @Override
+    public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
+
+        if (work instanceof VmWorkCreateVMSnapshot) {
+            VmWorkCreateVMSnapshot createWork = (VmWorkCreateVMSnapshot)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Create-VM-Snapshot within VM work job context. vmId: " + createWork.getVmId()
+                        + ", VM snapshotId: " + createWork.getVmSnapshotId() + "quiesce: " + createWork.isQuiesceVm());
+
+            VMSnapshot vmSnapshot = orchestrateCreateVMSnapshot(createWork.getVmId(), createWork.getVmSnapshotId(), createWork.isQuiesceVm());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Create-VM-Snapshot within VM work job context. vmId: " + createWork.getVmId()
+                        + ", VM snapshotId: " + createWork.getVmSnapshotId() + "quiesce: " + createWork.isQuiesceVm());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Long(vmSnapshot.getId())));
+        } else if (work instanceof VmWorkDeleteVMSnapshot) {
+            VmWorkDeleteVMSnapshot deleteWork = (VmWorkDeleteVMSnapshot)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Delete-VM-Snapshot within VM work job context. vmId: " + deleteWork.getVmId()
+                        + ", VM snapshotId: " + deleteWork.getVmSnapshotId());
+
+            boolean result = orchestrateDeleteVMSnapshot(deleteWork.getVmSnapshotId());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing Delete-VM-Snapshot within VM work job context. vmId: " + deleteWork.getVmId()
+                        + ", VM snapshotId: " + deleteWork.getVmSnapshotId());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
+
+        } else if (work instanceof VmWorkRevertToVMSnapshot) {
+            VmWorkRevertToVMSnapshot revertWork = (VmWorkRevertToVMSnapshot)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Revert-VM-Snapshot within VM work job context. vmId: " + revertWork.getVmId()
+                        + ", VM snapshotId: " + revertWork.getVmSnapshotId());
+
+            orchestrateRevertToVMSnapshot(revertWork.getVmSnapshotId());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing Revert-VM-Snapshot within VM work job context. vmId: " + revertWork.getVmId()
+                        + ", VM snapshotId: " + revertWork.getVmSnapshotId());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+
+        } else if (work instanceof VmWorkDeleteAllVMSnapshots) {
+            VmWorkDeleteAllVMSnapshots deleteAllWork = (VmWorkDeleteAllVMSnapshots)work;
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Delete-All-VM-Snapshot within VM work job context. vmId: " + deleteAllWork.getVmId());
+
+            boolean result = orchestrateDeleteAllVMSnapshots(deleteAllWork.getVmId(), deleteAllWork.getSnapshotType());
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute Delete-All-VM-Snapshot within VM work job context. vmId: " + deleteAllWork.getVmId());
+
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
+
+        } else {
+
+            RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
+            String exceptionJson = JobSerializerHelper.toSerializedString(e);
+            s_logger.error("Serialize exception object into json: " + exceptionJson);
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/vm/snapshot/VmWorkCreateVMSnapshot.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VmWorkCreateVMSnapshot.java b/server/src/com/cloud/vm/snapshot/VmWorkCreateVMSnapshot.java
new file mode 100644
index 0000000..3371802
--- /dev/null
+++ b/server/src/com/cloud/vm/snapshot/VmWorkCreateVMSnapshot.java
@@ -0,0 +1,41 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.snapshot;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkCreateVMSnapshot extends VmWork {
+    private static final long serialVersionUID = 124386202146049838L;
+
+    private Long vmSnapshotId;
+    private boolean quiesceVm;
+
+    public VmWorkCreateVMSnapshot(long userId, long accountId, long vmId, String handlerName, Long vmSnapshotId, boolean quiesceVm) {
+        super(userId, accountId, vmId, handlerName);
+
+        this.vmSnapshotId = vmSnapshotId;
+        this.quiesceVm = quiesceVm;
+    }
+
+    public Long getVmSnapshotId() {
+        return vmSnapshotId;
+    }
+
+    public boolean isQuiesceVm() {
+        return quiesceVm;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/vm/snapshot/VmWorkDeleteAllVMSnapshots.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VmWorkDeleteAllVMSnapshots.java b/server/src/com/cloud/vm/snapshot/VmWorkDeleteAllVMSnapshots.java
new file mode 100644
index 0000000..ce20dfc
--- /dev/null
+++ b/server/src/com/cloud/vm/snapshot/VmWorkDeleteAllVMSnapshots.java
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.snapshot;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkDeleteAllVMSnapshots extends VmWork {
+    private static final long serialVersionUID = -6010083039865471888L;
+
+    private VMSnapshot.Type type;
+
+    public VmWorkDeleteAllVMSnapshots(long userId, long accountId, long vmId, String handlerName, VMSnapshot.Type type) {
+        super(userId, accountId, vmId, handlerName);
+
+        this.type = type;
+    }
+
+    public VMSnapshot.Type getSnapshotType() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/vm/snapshot/VmWorkDeleteVMSnapshot.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VmWorkDeleteVMSnapshot.java b/server/src/com/cloud/vm/snapshot/VmWorkDeleteVMSnapshot.java
new file mode 100644
index 0000000..1a80e39
--- /dev/null
+++ b/server/src/com/cloud/vm/snapshot/VmWorkDeleteVMSnapshot.java
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.snapshot;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkDeleteVMSnapshot extends VmWork {
+    private static final long serialVersionUID = 7168101866614517508L;
+
+    private Long vmSnapshotId;
+
+    public VmWorkDeleteVMSnapshot(long userId, long accountId, long vmId, String handlerName, Long vmSnapshotId) {
+        super(userId, accountId, vmId, handlerName);
+
+        this.vmSnapshotId = vmSnapshotId;
+    }
+
+    public Long getVmSnapshotId() {
+        return vmSnapshotId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/bf9a5545/server/src/com/cloud/vm/snapshot/VmWorkRevertToVMSnapshot.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VmWorkRevertToVMSnapshot.java b/server/src/com/cloud/vm/snapshot/VmWorkRevertToVMSnapshot.java
new file mode 100644
index 0000000..f7beee5
--- /dev/null
+++ b/server/src/com/cloud/vm/snapshot/VmWorkRevertToVMSnapshot.java
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm.snapshot;
+
+import com.cloud.vm.VmWork;
+
+public class VmWorkRevertToVMSnapshot extends VmWork {
+    private static final long serialVersionUID = -3406543280278986843L;
+
+    private Long vmSnapshotId;
+
+    public VmWorkRevertToVMSnapshot(long userId, long accountId, long vmId, String handlerName, Long vmSnapshotId) {
+        super(userId, accountId, vmId, handlerName);
+
+        this.vmSnapshotId = vmSnapshotId;
+    }
+
+    public Long getVmSnapshotId() {
+        return vmSnapshotId;
+    }
+}


[11/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
Fix a typo caused problem in attach-volume process


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

Branch: refs/heads/master
Commit: 737a382c385ae371a69fd2c773344584355176c4
Parents: ac0faeb
Author: Kelven Yang <ke...@gmail.com>
Authored: Tue Dec 31 15:12:54 2013 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java | 4 +---
 .../src/com/cloud/vm/VmWorkJobWakeupDispatcher.java            | 6 ++++++
 server/src/com/cloud/storage/VolumeApiServiceImpl.java         | 2 +-
 3 files changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/737a382c/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
index ce10a83..574e60f 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
@@ -116,10 +116,8 @@ public class VmWorkJobHandlerProxy implements VmWorkJobHandler {
 
                 // legacy CloudStack code relies on checked exception for error handling
                 // we need to re-throw the real exception here
-                if (e.getCause() != null && e.getCause() instanceof Exception) {
-                    s_logger.info("Rethrow exception " + e.getCause());
+                if (e.getCause() != null && e.getCause() instanceof Exception)
                     throw (Exception)e.getCause();
-                }
 
                 throw e;
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/737a382c/engine/orchestration/src/com/cloud/vm/VmWorkJobWakeupDispatcher.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkJobWakeupDispatcher.java b/engine/orchestration/src/com/cloud/vm/VmWorkJobWakeupDispatcher.java
index 5704f97..520a550 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkJobWakeupDispatcher.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkJobWakeupDispatcher.java
@@ -40,6 +40,12 @@ import com.cloud.user.dao.AccountDao;
 import com.cloud.utils.component.AdapterBase;
 import com.cloud.vm.dao.VMInstanceDao;
 
+/**
+ * Please note: VmWorkJobWakeupDispatcher is not currently in use. It is designed for event-driven based
+ * job processing model.
+ *
+ * Current code base uses blocking calls to wait for job completion
+ */
 public class VmWorkJobWakeupDispatcher extends AdapterBase implements AsyncJobDispatcher {
     private static final Logger s_logger = Logger.getLogger(VmWorkJobWakeupDispatcher.class);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/737a382c/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 179a10c..f453289 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -2360,7 +2360,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
         return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
     }
 
-    private Pair<JobInfo.Status, String> orchestrateDetachVolumeFromVM(VmWorkAttachVolume work) throws Exception {
+    private Pair<JobInfo.Status, String> orchestrateDetachVolumeFromVM(VmWorkDetachVolume work) throws Exception {
         orchestrateDetachVolumeFromVM(work.getVmId(), work.getVolumeId());
         return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
     }


[08/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
Fix auto-merge caused issues


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

Branch: refs/heads/master
Commit: ac0faeb0917bf6872070f2b455f4338d586f4044
Parents: 0587382
Author: Kelven Yang <ke...@gmail.com>
Authored: Thu Jan 9 11:33:47 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../src/com/cloud/vm/VmWorkJobHandlerProxy.java | 36 +++++++++++++-------
 .../com/cloud/storage/VolumeApiServiceImpl.java |  1 +
 2 files changed, 25 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ac0faeb0/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
index 6550281..ce10a83 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.vm;
 
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
@@ -98,24 +99,35 @@ public class VmWorkJobHandlerProxy implements VmWorkJobHandler {
 
         Method method = getHandlerMethod(work.getClass());
         if (method != null) {
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
 
-            Object obj = method.invoke(_target, work);
+            try {
+                if (s_logger.isDebugEnabled())
+                    s_logger.debug("Execute VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
 
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+                Object obj = method.invoke(_target, work);
 
-            assert (obj instanceof Pair);
-            return (Pair<JobInfo.Status, String>)obj;
+                if (s_logger.isDebugEnabled())
+                    s_logger.debug("Done executing VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+
+                assert (obj instanceof Pair);
+                return (Pair<JobInfo.Status, String>)obj;
+            } catch (InvocationTargetException e) {
+                s_logger.error("Invocation exception, caused by: " + e.getCause());
+
+                // legacy CloudStack code relies on checked exception for error handling
+                // we need to re-throw the real exception here
+                if (e.getCause() != null && e.getCause() instanceof Exception) {
+                    s_logger.info("Rethrow exception " + e.getCause());
+                    throw (Exception)e.getCause();
+                }
+
+                throw e;
+            }
         } else {
             s_logger.error("Unable to find handler for VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
 
-            RuntimeException e = new RuntimeException("Unsupported VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
-            String exceptionJson = JobSerializerHelper.toSerializedString(e);
-
-            s_logger.error("Serialize exception object into json: " + exceptionJson);
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
+            RuntimeException ex = new RuntimeException("Unable to find handler for VM work job: " + work.getClass().getName());
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, JobSerializerHelper.toObjectSerializedString(ex));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ac0faeb0/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index e7d5164..179a10c 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -165,6 +165,7 @@ import com.cloud.vm.VirtualMachineManager;
 import com.cloud.vm.VmWork;
 import com.cloud.vm.VmWorkConstants;
 import com.cloud.vm.VmWorkJobHandler;
+import com.cloud.vm.VmWorkJobHandlerProxy;
 import com.cloud.vm.VmWorkSerializer;
 import com.cloud.vm.dao.ConsoleProxyDao;
 import com.cloud.vm.dao.DomainRouterDao;


[03/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5669: Always retrieve the most recent job result in OutComeImpl


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

Branch: refs/heads/master
Commit: 832c8e4728c896f359c9189ae4f49657a495ebe9
Parents: 737a382
Author: Kelven Yang <ke...@gmail.com>
Authored: Thu Jan 2 11:46:54 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java   | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/832c8e47/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java
----------------------------------------------------------------------
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java
index 7fd28db..bf7d54a 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/OutcomeImpl.java
@@ -51,7 +51,9 @@ public class OutcomeImpl<T> implements Outcome<T> {
 
     @Override
     public AsyncJob getJob() {
-        return _job;
+        // always reload job so that we retrieve the latest job result
+        AsyncJob job = s_jobMgr.getAsyncJob(_job.getId());
+        return job;
     }
 
     @Override


[07/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-669: Finalize VM work dispatching mechanism to avoid big switch statement


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

Branch: refs/heads/master
Commit: 0587382265ea5adec3fa382f5c278459ca71c52a
Parents: a6f126d
Author: Kelven Yang <ke...@gmail.com>
Authored: Tue Dec 31 10:50:43 2013 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../src/com/cloud/vm/VmWorkJobHandler.java      |   3 +-
 .../src/com/cloud/vm/VmWorkJobHandlerProxy.java | 121 ++++++++++++
 .../cloud/vm/snapshot/VMSnapshotManager.java    |   1 -
 ...spring-engine-orchestration-core-context.xml |   2 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 193 ++++++++++++-------
 .../src/com/cloud/vm/VmWorkJobDispatcher.java   |   7 +-
 .../com/cloud/storage/VolumeApiServiceImpl.java | 113 +++--------
 .../vm/snapshot/VMSnapshotManagerImpl.java      |  93 +++------
 8 files changed, 311 insertions(+), 222 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/components-api/src/com/cloud/vm/VmWorkJobHandler.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkJobHandler.java b/engine/components-api/src/com/cloud/vm/VmWorkJobHandler.java
index 6ab1bbc..d49a041 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkJobHandler.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkJobHandler.java
@@ -16,11 +16,10 @@
 // under the License.
 package com.cloud.vm;
 
-import org.apache.cloudstack.framework.jobs.AsyncJob;
 import org.apache.cloudstack.jobs.JobInfo;
 
 import com.cloud.utils.Pair;
 
 public interface VmWorkJobHandler {
-    Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception;
+    Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
new file mode 100644
index 0000000..6550281
--- /dev/null
+++ b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.vm;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import com.google.gson.Gson;
+
+import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
+import org.apache.cloudstack.jobs.JobInfo;
+
+import com.cloud.serializer.GsonHelper;
+import com.cloud.utils.Pair;
+
+/**
+ * VmWorkJobHandlerProxy can not be used as standalone due to run-time
+ * reflection usage in its implementation, run-time reflection conflicts with Spring proxy mode.
+ * It means that we can not instantiate VmWorkJobHandlerProxy beans directly in Spring and expect
+ * it can handle VmWork directly from there.
+ *
+ */
+public class VmWorkJobHandlerProxy implements VmWorkJobHandler {
+
+    private static final Logger s_logger = Logger.getLogger(VmWorkJobHandlerProxy.class);
+
+    private Object _target;
+    private Map<Class<?>, Method> _handlerMethodMap = new HashMap<Class<?>, Method>();
+
+    private Gson _gsonLogger;
+
+    public VmWorkJobHandlerProxy(Object target) {
+        _gsonLogger = GsonHelper.getGsonLogger();
+
+        buildLookupMap(target.getClass());
+        _target = target;
+    }
+
+    private void buildLookupMap(Class<?> hostClass) {
+        Class<?> clz = hostClass;
+        while (clz != null && clz != Object.class) {
+            Method[] hostHandlerMethods = clz.getDeclaredMethods();
+
+            for (Method method : hostHandlerMethods) {
+                if (isVmWorkJobHandlerMethod(method)) {
+                    Class<?> paramType = method.getParameterTypes()[0];
+                    assert (_handlerMethodMap.get(paramType) == null);
+
+                    method.setAccessible(true);
+                    _handlerMethodMap.put(paramType, method);
+                }
+            }
+
+            clz = clz.getSuperclass();
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private boolean isVmWorkJobHandlerMethod(Method method) {
+        if (method.getParameterTypes().length != 1)
+            return false;
+
+        Class<?> returnType = method.getReturnType();
+        if (!Pair.class.isAssignableFrom(returnType))
+            return false;
+
+        Class<?> paramType = method.getParameterTypes()[0];
+        if (!VmWork.class.isAssignableFrom(paramType))
+            return false;
+
+        return true;
+    }
+
+    private Method getHandlerMethod(Class<?> paramType) {
+        return _handlerMethodMap.get(paramType);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception {
+
+        Method method = getHandlerMethod(work.getClass());
+        if (method != null) {
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Execute VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+
+            Object obj = method.invoke(_target, work);
+
+            if (s_logger.isDebugEnabled())
+                s_logger.debug("Done executing VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+
+            assert (obj instanceof Pair);
+            return (Pair<JobInfo.Status, String>)obj;
+        } else {
+            s_logger.error("Unable to find handler for VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+
+            RuntimeException e = new RuntimeException("Unsupported VM work job: " + work.getClass().getName() + _gsonLogger.toJson(work));
+            String exceptionJson = JobSerializerHelper.toSerializedString(e);
+
+            s_logger.error("Serialize exception object into json: " + exceptionJson);
+            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java b/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
index 7d233ca..e7e3372 100644
--- a/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
+++ b/engine/components-api/src/com/cloud/vm/snapshot/VMSnapshotManager.java
@@ -42,5 +42,4 @@ public interface VMSnapshotManager extends VMSnapshotService, Manager {
     boolean syncVMSnapshot(VMInstanceVO vm, Long hostId);
 
     boolean hasActiveVMSnapshotTasks(Long vmId);
-
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
----------------------------------------------------------------------
diff --git a/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml b/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
index 7445102..fd5299c 100644
--- a/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
+++ b/engine/orchestration/resources/META-INF/cloudstack/core/spring-engine-orchestration-core-context.xml
@@ -72,7 +72,7 @@
     <bean id="virtualMachineEntityImpl" class="org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntityImpl" />
     
     <bean id="virtualMachinePowerStateSyncImpl" class="com.cloud.vm.VirtualMachinePowerStateSyncImpl" />
-      
+    
     <bean id= "vmWorkJobDispatcher" class="com.cloud.vm.VmWorkJobDispatcher">
         <property name="name">
             <util:constant static-field="com.cloud.vm.VmWorkConstants.VM_WORK_JOB_DISPATCHER"/>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 430a4a4..71952dd 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -316,6 +316,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Inject
     protected AsyncJobManager _jobMgr;
 
+    VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
+
     Map<VirtualMachine.Type, VirtualMachineGuru> _vmGurus = new HashMap<VirtualMachine.Type, VirtualMachineGuru>();
     protected StateMachine2<State, VirtualMachine.Event, VirtualMachine> _stateMachine;
 
@@ -526,6 +528,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     @Override
     public boolean start() {
+        // TODO, initial delay is hardcoded
+        _executor.scheduleAtFixedRate(new TransitionTask(), 5000, VmJobStateReportInterval.value(), TimeUnit.SECONDS);
         _executor.scheduleAtFixedRate(new CleanupTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS);
         cancelWorkItems(_nodeId);
         return true;
@@ -2942,9 +2946,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 return;
             }
             try {
-                lock.addRef();
-                List<VMInstanceVO> instances =
-                    _vmDao.findVMInTransition(new Date(new Date().getTime() - (AgentManager.Wait.value() * 1000)), State.Starting, State.Stopping);
+                scanStalledVMInTransitionStateOnDisconnectedHosts();
+
+                List<VMInstanceVO> instances = _vmDao.findVMInTransition(new Date(new Date().getTime() - (AgentManager.Wait.value() * 1000)), State.Starting, State.Stopping);
                 for (VMInstanceVO instance : instances) {
                     State state = instance.getState();
                     if (state == State.Stopping) {
@@ -3974,7 +3978,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-
     // VMs that in transitional state without recent power state report
     private List<Long> listStalledVMInTransitionStateOnUpHost(long hostId, Date cutTime) {
         String sql = "SELECT i.* FROM vm_instance as i, host as h WHERE h.status = 'UP' " +
@@ -4693,74 +4696,132 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
     }
 
-    @Override
-    public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
+    private Pair<JobInfo.Status, String> orchestrateStart(VmWorkStart work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+
+        orchestrateStart(vm.getUuid(), work.getParams(), work.getPlan(), null);
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
 
+    private Pair<JobInfo.Status, String> orchestrateStop(VmWorkStop work) throws Exception {
         VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
         if (vm == null) {
             s_logger.info("Unable to find vm " + work.getVmId());
         }
         assert (vm != null);
-        if (work instanceof VmWorkStart) {
-            VmWorkStart workStart = (VmWorkStart)work;
-            orchestrateStart(vm.getUuid(), workStart.getParams(), workStart.getPlan(), null);
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkStop) {
-            VmWorkStop workStop = (VmWorkStop)work;
-            orchestrateStop(vm.getUuid(), workStop.isCleanup());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkMigrate) {
-            VmWorkMigrate workMigrate = (VmWorkMigrate)work;
-            orchestrateMigrate(vm.getUuid(), workMigrate.getSrcHostId(), workMigrate.getDeployDestination());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkMigrateWithStorage) {
-            VmWorkMigrateWithStorage workMigrateWithStorage = (VmWorkMigrateWithStorage)work;
-            orchestrateMigrateWithStorage(vm.getUuid(),
-                    workMigrateWithStorage.getSrcHostId(),
-                    workMigrateWithStorage.getDestHostId(),
-                    workMigrateWithStorage.getVolumeToPool());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkMigrateForScale) {
-            VmWorkMigrateForScale workMigrateForScale = (VmWorkMigrateForScale)work;
-            orchestrateMigrateForScale(vm.getUuid(),
-                    workMigrateForScale.getSrcHostId(),
-                    workMigrateForScale.getDeployDestination(),
-                    workMigrateForScale.getNewServiceOfferringId());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkReboot) {
-            VmWorkReboot workReboot = (VmWorkReboot)work;
-            orchestrateReboot(vm.getUuid(), workReboot.getParams());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkAddVmToNetwork) {
-            VmWorkAddVmToNetwork workAddVmToNetwork = (VmWorkAddVmToNetwork)work;
-            NicProfile nic = orchestrateAddVmToNetwork(vm, workAddVmToNetwork.getNetwork(),
-                    workAddVmToNetwork.getRequestedNicProfile());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(nic));
-        } else if (work instanceof VmWorkRemoveNicFromVm) {
-            VmWorkRemoveNicFromVm workRemoveNicFromVm = (VmWorkRemoveNicFromVm)work;
-            boolean result = orchestrateRemoveNicFromVm(vm, workRemoveNicFromVm.getNic());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
-                    JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
-        } else if (work instanceof VmWorkRemoveVmFromNetwork) {
-            VmWorkRemoveVmFromNetwork workRemoveVmFromNetwork = (VmWorkRemoveVmFromNetwork)work;
-            boolean result = orchestrateRemoveVmFromNetwork(vm,
-                    workRemoveVmFromNetwork.getNetwork(), workRemoveVmFromNetwork.getBroadcastUri());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
-                    JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
-        } else if (work instanceof VmWorkReconfigure) {
-            VmWorkReconfigure workReconfigure = (VmWorkReconfigure)work;
-            reConfigureVm(vm.getUuid(), workReconfigure.getNewServiceOffering(),
-                    workReconfigure.isSameHost());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkStorageMigration) {
-            VmWorkStorageMigration workStorageMigration = (VmWorkStorageMigration)work;
-            orchestrateStorageMigration(vm.getUuid(), workStorageMigration.getDestStoragePool());
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else {
-            RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
-            String exceptionJson = JobSerializerHelper.toSerializedString(e);
-            s_logger.error("Serialize exception object into json: " + exceptionJson);
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
+
+        orchestrateStop(vm.getUuid(), work.isCleanup());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateMigrate(VmWorkMigrate work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+
+        orchestrateMigrate(vm.getUuid(), work.getSrcHostId(), work.getDeployDestination());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateMigrateWithStorage(VmWorkMigrateWithStorage work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        orchestrateMigrateWithStorage(vm.getUuid(),
+                work.getSrcHostId(),
+                work.getDestHostId(),
+                work.getVolumeToPool());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateMigrateForScale(VmWorkMigrateForScale work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        orchestrateMigrateForScale(vm.getUuid(),
+                work.getSrcHostId(),
+                work.getDeployDestination(),
+                work.getNewServiceOfferringId());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateReboot(VmWorkReboot work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
         }
+        assert (vm != null);
+        orchestrateReboot(vm.getUuid(), work.getParams());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateAddVmToNetwork(VmWorkAddVmToNetwork work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        NicProfile nic = orchestrateAddVmToNetwork(vm, work.getNetwork(),
+                work.getRequestedNicProfile());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(nic));
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateRemoveNicFromVm(VmWorkRemoveNicFromVm work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        boolean result = orchestrateRemoveNicFromVm(vm, work.getNic());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Boolean(result)));
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateRemoveVmFromNetwork(VmWorkRemoveVmFromNetwork work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        boolean result = orchestrateRemoveVmFromNetwork(vm,
+                work.getNetwork(), work.getBroadcastUri());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Boolean(result)));
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateReconfigure(VmWorkReconfigure work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        reConfigureVm(vm.getUuid(), work.getNewServiceOffering(),
+                work.isSameHost());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    private Pair<JobInfo.Status, String> orchestrateStorageMigration(VmWorkStorageMigration work) throws Exception {
+        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
+        if (vm == null) {
+            s_logger.info("Unable to find vm " + work.getVmId());
+        }
+        assert (vm != null);
+        orchestrateStorageMigration(vm.getUuid(), work.getDestStoragePool());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
+
+    @Override
+    public Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception {
+        return _jobHandlerProxy.handleVmWorkJob(work);
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
index dea64da..1af0dac 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
@@ -74,8 +74,8 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
             }
 
             work = VmWorkSerializer.deserialize(workClz, job.getCmdInfo());
-            assert (work != null);
-            if (work == null) {
+            assert(work != null);
+            if(work == null) {
                 s_logger.error("Unable to deserialize VM work " + job.getCmd() + ", job info: " + job.getCmdInfo());
                 _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, "Unable to deserialize VM work");
                 return;
@@ -97,8 +97,9 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
 
             CallContext.register(work.getUserId(), work.getAccountId(), job.getRelated());
 
-            Pair<JobInfo.Status, String> result = handler.handleVmWorkJob(job, work);
+            Pair<JobInfo.Status, String> result = handler.handleVmWorkJob(work);
             _asyncJobMgr.completeAsyncJob(job.getId(), result.first(), 0, result.second());
+
         } catch(Throwable e) {
             s_logger.error("Unable to complete " + job, e);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 0da8ebd..e7d5164 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -61,7 +61,6 @@ import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
 import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 import org.apache.cloudstack.framework.jobs.Outcome;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
-import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
 import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl;
 import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
 import org.apache.cloudstack.jobs.JobInfo;
@@ -329,6 +328,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
     @Inject
     protected AsyncJobManager _jobMgr;
 
+    VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
+
     // TODO
     static final ConfigKey<Boolean> VmJobEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.job.enabled", "false",
             "True to enable new VM sync model. false to use the old way", false);
@@ -2353,92 +2354,38 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 snapshotId);
     }
 
-    @Override
-    public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
-        VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId());
-        if (vm == null) {
-            s_logger.info("Unable to find vm " + work.getVmId());
-        }
-        assert (vm != null);
-
-        if (work instanceof VmWorkAttachVolume) {
-
-            VmWorkAttachVolume attachWork = (VmWorkAttachVolume)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Attach-Volume within VM work job context. vmId: " + attachWork.getVmId() + ", volId: " + attachWork.getVolumeId() + ", deviceId: "
-                        + attachWork.getDeviceId());
-
-            orchestrateAttachVolumeToVM(attachWork.getVmId(), attachWork.getVolumeId(), attachWork.getDeviceId());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Attach-Volume within VM work job context. vmId: " + attachWork.getVmId() + ", volId: " + attachWork.getVolumeId() + ", deviceId: "
-                        + attachWork.getDeviceId());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkDetachVolume) {
-            VmWorkDetachVolume detachWork = (VmWorkDetachVolume)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Detach-Volume within VM work job context. vmId: " + detachWork.getVmId() + ", volId: " + detachWork.getVolumeId());
-
-            orchestrateDetachVolumeFromVM(detachWork.getVmId(), detachWork.getVolumeId());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Detach-Volume within VM work job context. vmId: " + detachWork.getVmId() + ", volId: " + detachWork.getVolumeId());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-        } else if (work instanceof VmWorkResizeVolume) {
-            VmWorkResizeVolume resizeWork = (VmWorkResizeVolume)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Resize-Volume within VM work job context. vmId: " + resizeWork.getVmId()
-                        + ", volId: " + resizeWork.getVolumeId() + ", size " + resizeWork.getCurrentSize() + " -> " + resizeWork.getNewSize());
-
-            orchestrateResizeVolume(resizeWork.getVolumeId(), resizeWork.getCurrentSize(), resizeWork.getNewSize(),
-                    resizeWork.getNewServiceOfferingId(), resizeWork.isShrinkOk());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Resize-Volume within VM work job context. vmId: " + resizeWork.getVmId()
-                        + ", volId: " + resizeWork.getVolumeId() + ", size " + resizeWork.getCurrentSize() + " -> " + resizeWork.getNewSize());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-
-        } else if (work instanceof VmWorkMigrateVolume) {
-            VmWorkMigrateVolume migrateWork = (VmWorkMigrateVolume)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Migrate-Volume within VM work job context. vmId: " + migrateWork.getVmId()
-                        + ", volId: " + migrateWork.getVolumeId() + ", destPoolId: " + migrateWork.getDestPoolId() + ", live: " + migrateWork.isLiveMigrate());
-
-            Volume newVol = orchestrateMigrateVolume(migrateWork.getVolumeId(), migrateWork.getDestPoolId(), migrateWork.isLiveMigrate());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Migrate-Volume within VM work job context. vmId: " + migrateWork.getVmId()
-                        + ", volId: " + migrateWork.getVolumeId() + ", destPoolId: " + migrateWork.getDestPoolId() + ", live: " + migrateWork.isLiveMigrate());
+    private Pair<JobInfo.Status, String> orchestrateAttachVolumeToVM(VmWorkAttachVolume work) throws Exception {
+        orchestrateAttachVolumeToVM(work.getVmId(), work.getVolumeId(), work.getDeviceId());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
 
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Long(newVol.getId())));
-        } else if (work instanceof VmWorkTakeVolumeSnapshot) {
-            VmWorkTakeVolumeSnapshot snapshotWork = (VmWorkTakeVolumeSnapshot)work;
+    private Pair<JobInfo.Status, String> orchestrateDetachVolumeFromVM(VmWorkAttachVolume work) throws Exception {
+        orchestrateDetachVolumeFromVM(work.getVmId(), work.getVolumeId());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
 
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Take-Volume-Snapshot within VM work job context. vmId: " + snapshotWork.getVmId()
-                        + ", volId: " + snapshotWork.getVolumeId() + ", policyId: " + snapshotWork.getPolicyId() + ", quiesceVm: " + snapshotWork.isQuiesceVm());
+    private Pair<JobInfo.Status, String> orchestrateResizeVolume(VmWorkResizeVolume work) throws Exception {
+        orchestrateResizeVolume(work.getVolumeId(), work.getCurrentSize(), work.getNewSize(),
+                work.getNewServiceOfferingId(), work.isShrinkOk());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
 
-            Account account = _accountDao.findById(snapshotWork.getAccountId());
-            orchestrateTakeVolumeSnapshot(snapshotWork.getVolumeId(), snapshotWork.getPolicyId(), snapshotWork.getSnapshotId(),
-                    account, snapshotWork.isQuiesceVm());
+    private Pair<JobInfo.Status, String> orchestrateMigrateVolume(VmWorkMigrateVolume work) throws Exception {
+        Volume newVol = orchestrateMigrateVolume(work.getVolumeId(), work.getDestPoolId(), work.isLiveMigrate());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Long(newVol.getId())));
+    }
 
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Take-Volume-Snapshot within VM work job context. vmId: " + snapshotWork.getVmId()
-                        + ", volId: " + snapshotWork.getVolumeId() + ", policyId: " + snapshotWork.getPolicyId() + ", quiesceVm: " + snapshotWork.isQuiesceVm());
+    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());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(work.getSnapshotId()));
+    }
 
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(snapshotWork.getSnapshotId()));
-        } else {
-            RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
-            String exceptionJson = JobSerializerHelper.toSerializedString(e);
-            s_logger.error("Serialize exception object into json: " + exceptionJson);
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
-        }
+    @Override
+    public Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception {
+        return _jobHandlerProxy.handleVmWorkJob(work);
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/05873822/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 6a954de..f7c1120 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -42,7 +42,6 @@ import org.apache.cloudstack.framework.jobs.AsyncJobExecutionContext;
 import org.apache.cloudstack.framework.jobs.AsyncJobManager;
 import org.apache.cloudstack.framework.jobs.Outcome;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
-import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
 import org.apache.cloudstack.framework.jobs.impl.OutcomeImpl;
 import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO;
 import org.apache.cloudstack.jobs.JobInfo;
@@ -91,6 +90,7 @@ import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.VmWork;
 import com.cloud.vm.VmWorkConstants;
 import com.cloud.vm.VmWorkJobHandler;
+import com.cloud.vm.VmWorkJobHandlerProxy;
 import com.cloud.vm.VmWorkSerializer;
 import com.cloud.vm.dao.UserVmDao;
 import com.cloud.vm.dao.VMInstanceDao;
@@ -124,6 +124,8 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
     @Inject
     AsyncJobManager _jobMgr;
 
+    VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
+
     int _vmSnapshotMax;
     int _wait;
 
@@ -478,7 +480,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         }
     }
 
-    public boolean orchestrateDeleteVMSnapshot(Long vmSnapshotId) {
+    private boolean orchestrateDeleteVMSnapshot(Long vmSnapshotId) {
         Account caller = getCaller();
 
         VMSnapshotVO vmSnapshot = _vmSnapshotDao.findById(vmSnapshotId);
@@ -585,7 +587,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
         }
     }
 
-    public UserVm orchestrateRevertToVMSnapshot(Long vmSnapshotId) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException {
+    private UserVm orchestrateRevertToVMSnapshot(Long vmSnapshotId) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException {
 
         // check if VM snapshot exists in DB
         VMSnapshotVO vmSnapshotVo = _vmSnapshotDao.findById(vmSnapshotId);
@@ -984,72 +986,31 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 vmId);
     }
 
-    @Override
-    public Pair<JobInfo.Status, String> handleVmWorkJob(AsyncJob job, VmWork work) throws Exception {
-
-        if (work instanceof VmWorkCreateVMSnapshot) {
-            VmWorkCreateVMSnapshot createWork = (VmWorkCreateVMSnapshot)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Create-VM-Snapshot within VM work job context. vmId: " + createWork.getVmId()
-                        + ", VM snapshotId: " + createWork.getVmSnapshotId() + "quiesce: " + createWork.isQuiesceVm());
-
-            VMSnapshot vmSnapshot = orchestrateCreateVMSnapshot(createWork.getVmId(), createWork.getVmSnapshotId(), createWork.isQuiesceVm());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Create-VM-Snapshot within VM work job context. vmId: " + createWork.getVmId()
-                        + ", VM snapshotId: " + createWork.getVmSnapshotId() + "quiesce: " + createWork.isQuiesceVm());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Long(vmSnapshot.getId())));
-        } else if (work instanceof VmWorkDeleteVMSnapshot) {
-            VmWorkDeleteVMSnapshot deleteWork = (VmWorkDeleteVMSnapshot)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Delete-VM-Snapshot within VM work job context. vmId: " + deleteWork.getVmId()
-                        + ", VM snapshotId: " + deleteWork.getVmSnapshotId());
-
-            boolean result = orchestrateDeleteVMSnapshot(deleteWork.getVmSnapshotId());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Delete-VM-Snapshot within VM work job context. vmId: " + deleteWork.getVmId()
-                        + ", VM snapshotId: " + deleteWork.getVmSnapshotId());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
-
-        } else if (work instanceof VmWorkRevertToVMSnapshot) {
-            VmWorkRevertToVMSnapshot revertWork = (VmWorkRevertToVMSnapshot)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Revert-VM-Snapshot within VM work job context. vmId: " + revertWork.getVmId()
-                        + ", VM snapshotId: " + revertWork.getVmSnapshotId());
-
-            orchestrateRevertToVMSnapshot(revertWork.getVmSnapshotId());
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Done executing Revert-VM-Snapshot within VM work job context. vmId: " + revertWork.getVmId()
-                        + ", VM snapshotId: " + revertWork.getVmSnapshotId());
-
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
-
-        } else if (work instanceof VmWorkDeleteAllVMSnapshots) {
-            VmWorkDeleteAllVMSnapshots deleteAllWork = (VmWorkDeleteAllVMSnapshots)work;
-
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Delete-All-VM-Snapshot within VM work job context. vmId: " + deleteAllWork.getVmId());
-
-            boolean result = orchestrateDeleteAllVMSnapshots(deleteAllWork.getVmId(), deleteAllWork.getSnapshotType());
+    public Pair<JobInfo.Status, String> orchestrateCreateVMSnapshot(VmWorkCreateVMSnapshot work) throws Exception {
+        VMSnapshot snapshot = orchestrateCreateVMSnapshot(work.getVmId(), work.getVmSnapshotId(), work.isQuiesceVm());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Long(snapshot.getId())));
+    }
 
-            if (s_logger.isDebugEnabled())
-                s_logger.debug("Execute Delete-All-VM-Snapshot within VM work job context. vmId: " + deleteAllWork.getVmId());
+    public Pair<JobInfo.Status, String> orchestrateDeleteVMSnapshot(VmWorkDeleteVMSnapshot work) {
+        boolean result = orchestrateDeleteVMSnapshot(work.getVmSnapshotId());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Boolean(result)));
+    }
 
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, JobSerializerHelper.toObjectSerializedString(new Boolean(result)));
+    public Pair<JobInfo.Status, String> orchestrateRevertToVMSnapshot(VmWorkRevertToVMSnapshot work) throws Exception {
+        orchestrateRevertToVMSnapshot(work.getVmSnapshotId());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
+    }
 
-        } else {
+    public Pair<JobInfo.Status, String> orchestrateDeleteAllVMSnapshots(VmWorkDeleteAllVMSnapshots work) {
+        boolean result = orchestrateDeleteAllVMSnapshots(work.getVmId(), work.getSnapshotType());
+        return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED,
+                _jobMgr.marshallResultObject(new Boolean(result)));
+    }
 
-            RuntimeException e = new RuntimeException("Unsupported VM work command: " + job.getCmd());
-            String exceptionJson = JobSerializerHelper.toSerializedString(e);
-            s_logger.error("Serialize exception object into json: " + exceptionJson);
-            return new Pair<JobInfo.Status, String>(JobInfo.Status.FAILED, exceptionJson);
-        }
+    @Override
+    public Pair<JobInfo.Status, String> handleVmWorkJob(VmWork work) throws Exception {
+        return _jobHandlerProxy.handleVmWorkJob(work);
     }
 }


[10/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5767: Remove the logic of using underlying job related fields for volume specific logic.


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

Branch: refs/heads/master
Commit: ad6454d2bfff4b517b8dfca21b02f923ac8e9a51
Parents: 69f4983
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Jan 3 13:10:17 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 134 +++++++++----------
 .../com/cloud/storage/VolumeApiServiceImpl.java |  67 ++++------
 .../vm/snapshot/VMSnapshotManagerImpl.java      |  50 +++----
 3 files changed, 109 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ad6454d2/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 71952dd..9d4cb04 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -183,7 +183,7 @@ import com.cloud.utils.db.DB;
 import com.cloud.utils.db.EntityManager;
 import com.cloud.utils.db.GlobalLock;
 import com.cloud.utils.db.Transaction;
-import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionCallback;
 import com.cloud.utils.db.TransactionCallbackWithException;
 import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn;
 import com.cloud.utils.db.TransactionLegacy;
@@ -4138,9 +4138,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmDao.lockRow(vm.getId(), true);
@@ -4171,16 +4171,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmStateSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmStateSyncOutcome((VmWorkJobVO)result[0],
                 VirtualMachine.PowerState.PowerOn, vm.getId(), null);
     }
 
@@ -4191,9 +4189,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 _vmDao.lockRow(vm.getId(), true);
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
@@ -4223,15 +4221,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
 
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmStateSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmStateSyncOutcome((VmWorkJobVO)result[0],
                 VirtualMachine.PowerState.PowerOff, vm.getId(), null);
     }
 
@@ -4244,9 +4241,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 _vmDao.lockRow(vm.getId(), true);
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
@@ -4276,15 +4273,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
 
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0],
                 vm.getId());
     }
 
@@ -4295,10 +4291,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4326,15 +4321,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmStateSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmStateSyncOutcome((VmWorkJobVO)result[0],
                 VirtualMachine.PowerState.PowerOn, vm.getId(), vm.getPowerHostId());
     }
 
@@ -4348,9 +4342,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 _vmDao.lockRow(vm.getId(), true);
 
@@ -4381,15 +4375,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmStateSyncOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmStateSyncOutcome((VmWorkJobVO)result[0],
                 VirtualMachine.PowerState.PowerOn, vm.getId(), destHostId);
     }
 
@@ -4402,10 +4395,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4434,15 +4426,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     public Outcome<VirtualMachine> migrateVmStorageThroughJobQueue(
@@ -4454,10 +4446,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4486,15 +4477,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     public Outcome<VirtualMachine> addVmToNetworkThroughJobQueue(
@@ -4504,10 +4495,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final User user = context.getCallingUser();
         final Account account = context.getCallingAccount();
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4536,15 +4526,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     public Outcome<VirtualMachine> removeNicFromVmThroughJobQueue(
@@ -4554,10 +4543,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final User user = context.getCallingUser();
         final Account account = context.getCallingAccount();
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4586,15 +4574,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     public Outcome<VirtualMachine> removeVmFromNetworkThroughJobQueue(
@@ -4604,10 +4591,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         final User user = context.getCallingUser();
         final Account account = context.getCallingAccount();
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4636,15 +4622,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     public Outcome<VirtualMachine> reconfigureVmThroughJobQueue(
@@ -4656,10 +4641,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         final VMInstanceVO vm = _vmDao.findByUuid(vmUuid);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
-                _vmDao.lockRow(vm.getId(), true);
+            public Object[] doInTransaction(TransactionStatus status) {
 
                 List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs(
                         VirtualMachine.Type.Instance, vm.getId(),
@@ -4688,12 +4672,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
                 }
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"), vm.getId());
+        final long jobId = (Long)result[1];
+        AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
+
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0], vm.getId());
     }
 
     private Pair<JobInfo.Status, String> orchestrateStart(VmWorkStart work) throws Exception {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ad6454d2/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index f453289..0200233 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -28,7 +28,6 @@ import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
 
-import org.apache.cloudstack.api.BaseCmd;
 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;
@@ -150,7 +149,6 @@ import com.cloud.utils.db.DB;
 import com.cloud.utils.db.EntityManager;
 import com.cloud.utils.db.Transaction;
 import com.cloud.utils.db.TransactionCallback;
-import com.cloud.utils.db.TransactionCallbackNoReturn;
 import com.cloud.utils.db.TransactionStatus;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.fsm.NoTransitionException;
@@ -1282,7 +1280,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
             }
 
             _asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volumeId);
-            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, Long.toString(volumeId));
         }
 
         VolumeVO newVol = _volumeDao.findById(volumeOnPrimaryStorage.getId());
@@ -1403,7 +1400,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
             }
 
             _asyncMgr.updateAsyncJobAttachment(job.getId(), "volume", volumeId);
-            _asyncMgr.updateAsyncJobStatus(job.getId(), BaseCmd.PROGRESS_INSTANCE_CREATED, volumeId.toString());
         }
 
         AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
@@ -2135,9 +2131,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -2159,16 +2155,17 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                AsyncJobVO jobVo = _jobMgr.getAsyncJob(workJob.getId());
+                s_logger.debug("New job " + workJob.getId() + ", result field: " + jobVo.getResult());
+
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)result[0],
                 volumeId);
     }
 
@@ -2180,9 +2177,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -2203,16 +2200,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)result[0],
                 volumeId);
     }
 
@@ -2225,9 +2220,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -2249,16 +2244,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)result[0],
                 volumeId);
     }
 
@@ -2271,9 +2264,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -2295,16 +2288,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVolumeOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVolumeOutcome((VmWorkJobVO)result[0],
                 volumeId);
     }
 
@@ -2317,9 +2308,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -2342,16 +2333,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobSnapshotOutcome((VmWorkJobVO)result[0],
                 snapshotId);
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ad6454d2/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index f7c1120..40476d0 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -78,7 +78,7 @@ import com.cloud.utils.db.Filter;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.Transaction;
-import com.cloud.utils.db.TransactionCallbackNoReturn;
+import com.cloud.utils.db.TransactionCallback;
 import com.cloud.utils.db.TransactionStatus;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.vm.UserVmVO;
@@ -814,9 +814,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -838,16 +838,14 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)result[0],
                 vmSnapshotId);
     }
 
@@ -859,9 +857,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -883,16 +881,14 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)result[0],
                 vmSnapshotId);
     }
 
@@ -904,9 +900,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -928,16 +924,14 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVMSnapshotOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVMSnapshotOutcome((VmWorkJobVO)result[0],
                 vmSnapshotId);
     }
 
@@ -949,9 +943,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
         final VMInstanceVO vm = _vmInstanceDao.findById(vmId);
 
-        Transaction.execute(new TransactionCallbackNoReturn() {
+        Object[] result = Transaction.execute(new TransactionCallback<Object[]>() {
             @Override
-            public void doInTransactionWithoutResult(TransactionStatus status) {
+            public Object[] doInTransaction(TransactionStatus status) {
                 VmWorkJobVO workJob = null;
 
                 _vmInstanceDao.lockRow(vm.getId(), true);
@@ -973,16 +967,14 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
                 _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
 
-                // Transaction syntax sugar has a cost here
-                context.putContextParameter("workJob", workJob);
-                context.putContextParameter("jobId", new Long(workJob.getId()));
+                return new Object[] {workJob, new Long(workJob.getId())};
             }
         });
 
-        final long jobId = (Long)context.getContextParameter("jobId");
+        final long jobId = (Long)result[1];
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
-        return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
+        return new VmJobVirtualMachineOutcome((VmWorkJobVO)result[0],
                 vmId);
     }
 


[06/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
Fix a style-check problem after cherry-pick


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

Branch: refs/heads/master
Commit: a6f126d24e5cadb30032a2bdacb4a7565a1d9051
Parents: 8c93bd6
Author: Kelven Yang <ke...@gmail.com>
Authored: Thu Jan 9 11:06:51 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a6f126d2/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 323cdf9..430a4a4 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -4282,7 +4282,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(jobId);
 
         return new VmJobVirtualMachineOutcome((VmWorkJobVO)context.getContextParameter("workJob"),
-        	vm.getId());
+                vm.getId());
     }
 
     public Outcome<VirtualMachine> migrateVmThroughJobQueue(final String vmUuid, final long srcHostId, final DeployDestination dest) {


[12/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5765: cleanup internal serialization and exception propagation issues


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

Branch: refs/heads/master
Commit: 1e2e1ea0515178d40efc536dfa3328de4b8d48e1
Parents: a05d71a
Author: Kelven Yang <ke...@gmail.com>
Authored: Tue Jan 7 17:11:48 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:13 2014 -0800

----------------------------------------------------------------------
 api/src/com/cloud/deploy/DeployDestination.java | 21 +++++----
 api/src/com/cloud/deploy/DeploymentPlanner.java |  5 +-
 api/src/com/cloud/exception/CloudException.java |  5 +-
 .../exception/OperationTimedoutException.java   | 10 +++-
 .../src/com/cloud/vm/VirtualMachineManager.java |  4 +-
 .../src/com/cloud/vm/VmWorkJobHandlerProxy.java |  4 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 36 +++++++-------
 .../src/com/cloud/vm/VmWorkJobDispatcher.java   |  6 +--
 .../src/com/cloud/vm/VmWorkReconfigure.java     | 11 ++---
 .../com/cloud/service/ServiceOfferingVO.java    | 26 +++++------
 .../vm/snapshot/VMSnapshotManagerImpl.java      |  2 +-
 .../utils/exception/CloudRuntimeException.java  | 49 +++++++++++++++++++-
 .../utils/exception/ExceptionProxyObject.java   | 14 ++++--
 13 files changed, 131 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/api/src/com/cloud/deploy/DeployDestination.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/deploy/DeployDestination.java b/api/src/com/cloud/deploy/DeployDestination.java
index 05625d6..4ded5eb 100644
--- a/api/src/com/cloud/deploy/DeployDestination.java
+++ b/api/src/com/cloud/deploy/DeployDestination.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.deploy;
 
+import java.io.Serializable;
 import java.util.Map;
 
 import com.cloud.dc.DataCenter;
@@ -26,7 +27,9 @@ import com.cloud.storage.StoragePool;
 import com.cloud.storage.Volume;
 import com.cloud.utils.NumbersUtil;
 
-public class DeployDestination {
+public class DeployDestination implements Serializable {
+    private static final long serialVersionUID = 7113840781939014695L;
+
     DataCenter _dc;
     Pod _pod;
     Cluster _cluster;
@@ -76,28 +79,28 @@ public class DeployDestination {
     @Override
     public boolean equals(Object obj) {
         DeployDestination that = (DeployDestination)obj;
-        if (this._dc == null || that._dc == null) {
+        if (_dc == null || that._dc == null) {
             return false;
         }
-        if (this._dc.getId() != that._dc.getId()) {
+        if (_dc.getId() != that._dc.getId()) {
             return false;
         }
-        if (this._pod == null || that._pod == null) {
+        if (_pod == null || that._pod == null) {
             return false;
         }
-        if (this._pod.getId() != that._pod.getId()) {
+        if (_pod.getId() != that._pod.getId()) {
             return false;
         }
-        if (this._cluster == null || that._cluster == null) {
+        if (_cluster == null || that._cluster == null) {
             return false;
         }
-        if (this._cluster.getId() != that._cluster.getId()) {
+        if (_cluster.getId() != that._cluster.getId()) {
             return false;
         }
-        if (this._host == null || that._host == null) {
+        if (_host == null || that._host == null) {
             return false;
         }
-        return this._host.getId() == that._host.getId();
+        return _host.getId() == that._host.getId();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/api/src/com/cloud/deploy/DeploymentPlanner.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/deploy/DeploymentPlanner.java b/api/src/com/cloud/deploy/DeploymentPlanner.java
index 35f406d..0dccf3d 100644
--- a/api/src/com/cloud/deploy/DeploymentPlanner.java
+++ b/api/src/com/cloud/deploy/DeploymentPlanner.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.deploy;
 
+import java.io.Serializable;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
@@ -89,7 +90,9 @@ public interface DeploymentPlanner extends Adapter {
         Shared, Dedicated;
     }
 
-    public static class ExcludeList {
+    public static class ExcludeList implements Serializable {
+        private static final long serialVersionUID = -482175549460148301L;
+
         private Set<Long> _dcIds;
         private Set<Long> _podIds;
         private Set<Long> _clusterIds;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/api/src/com/cloud/exception/CloudException.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/exception/CloudException.java b/api/src/com/cloud/exception/CloudException.java
index f898719..f35249b 100644
--- a/api/src/com/cloud/exception/CloudException.java
+++ b/api/src/com/cloud/exception/CloudException.java
@@ -27,6 +27,7 @@ import com.cloud.utils.exception.CSExceptionErrorCode;
  */
 
 public class CloudException extends Exception {
+    private static final long serialVersionUID = 8784427323859682503L;
 
     // This holds a list of uuids and their names. Add uuid:fieldname pairs
     protected ArrayList<String> idList = new ArrayList<String>();
@@ -58,10 +59,10 @@ public class CloudException extends Exception {
     }
 
     public void setCSErrorCode(int cserrcode) {
-        this.csErrorCode = cserrcode;
+        csErrorCode = cserrcode;
     }
 
     public int getCSErrorCode() {
-        return this.csErrorCode;
+        return csErrorCode;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/api/src/com/cloud/exception/OperationTimedoutException.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/exception/OperationTimedoutException.java b/api/src/com/cloud/exception/OperationTimedoutException.java
index d531c32..fe27408 100644
--- a/api/src/com/cloud/exception/OperationTimedoutException.java
+++ b/api/src/com/cloud/exception/OperationTimedoutException.java
@@ -28,7 +28,15 @@ public class OperationTimedoutException extends CloudException {
     long _agentId;
     long _seqId;
     int _time;
-    Command[] _cmds;
+
+    // TODO
+    // I did a reference search on usage of getCommands() and found none
+    //
+    // to prevent serialization problems across boundaries, I'm disabling serialization of _cmds here
+    // getCommands() will still be available within the same serialization boundary, but it will be lost
+    // when exception is propagated across job boundaries.
+    //
+    transient Command[] _cmds;
     boolean _isActive;
 
     public OperationTimedoutException(Command[] cmds, long agentId, long seqId, int time, boolean isActive) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/api/src/com/cloud/vm/VirtualMachineManager.java
----------------------------------------------------------------------
diff --git a/engine/api/src/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
index 0de5156..ac79860 100644
--- a/engine/api/src/com/cloud/vm/VirtualMachineManager.java
+++ b/engine/api/src/com/cloud/vm/VirtualMachineManager.java
@@ -190,7 +190,9 @@ public interface VirtualMachineManager extends Manager {
      */
     VirtualMachineTO toVmTO(VirtualMachineProfile profile);
 
-    VirtualMachine reConfigureVm(String vmUuid, ServiceOffering newServiceOffering, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException;
+    VirtualMachine reConfigureVm(String vmUuid, ServiceOffering newServiceOffering, boolean sameHost) throws ResourceUnavailableException, ConcurrentOperationException,
+            InsufficientServerCapacityException;
+
     void findHostAndMigrate(String vmUuid, Long newSvcOfferingId, DeploymentPlanner.ExcludeList excludeHostList) throws InsufficientCapacityException,
         ConcurrentOperationException, ResourceUnavailableException;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
index 574e60f..ce10a83 100644
--- a/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
+++ b/engine/components-api/src/com/cloud/vm/VmWorkJobHandlerProxy.java
@@ -116,8 +116,10 @@ public class VmWorkJobHandlerProxy implements VmWorkJobHandler {
 
                 // legacy CloudStack code relies on checked exception for error handling
                 // we need to re-throw the real exception here
-                if (e.getCause() != null && e.getCause() instanceof Exception)
+                if (e.getCause() != null && e.getCause() instanceof Exception) {
+                    s_logger.info("Rethrow exception " + e.getCause());
                     throw (Exception)e.getCause();
+                }
 
                 throw e;
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 0653747..c553607 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -3670,7 +3670,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Override
     public VMInstanceVO reConfigureVm(String vmUuid, ServiceOffering oldServiceOffering,
             boolean reconfiguringOnExistingHost)
-            throws ResourceUnavailableException, ConcurrentOperationException {
+            throws ResourceUnavailableException, InsufficientServerCapacityException, ConcurrentOperationException {
 
         AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext();
         if (!VmJobEnabled.value() || jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) {
@@ -3688,20 +3688,21 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 throw new RuntimeException("Execution excetion", e);
             }
 
-            AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, outcome.getJob().getId());
-            if (jobVo.getResultCode() == JobInfo.Status.SUCCEEDED.ordinal()) {
-                return _entityMgr.findById(VMInstanceVO.class, vm.getId());
-            } else {
-                Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
-                if (jobResult != null) {
-                    if (jobResult instanceof ResourceUnavailableException)
-                        throw (ResourceUnavailableException)jobResult;
-                    else if (jobResult instanceof ConcurrentOperationException)
-                        throw (ConcurrentOperationException)jobResult;
+            Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob());
+            if (jobResult != null) {
+                if (jobResult instanceof ResourceUnavailableException)
+                    throw (ResourceUnavailableException)jobResult;
+                else if (jobResult instanceof ConcurrentOperationException)
+                    throw (ConcurrentOperationException)jobResult;
+                else if (jobResult instanceof InsufficientServerCapacityException)
+                    throw (InsufficientServerCapacityException)jobResult;
+                else if (jobResult instanceof Throwable) {
+                    s_logger.error("Unhandled exception", (Throwable)jobResult);
+                    throw new RuntimeException("Unhandled exception", (Throwable)jobResult);
                 }
-
-                throw new RuntimeException("Failed with un-handled exception");
             }
+
+            return (VMInstanceVO)vm;
         }
     }
 
@@ -4633,7 +4634,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
     public Outcome<VirtualMachine> reconfigureVmThroughJobQueue(
-            final String vmUuid, final ServiceOffering oldServiceOffering, final boolean reconfiguringOnExistingHost) {
+            final String vmUuid, final ServiceOffering newServiceOffering, final boolean reconfiguringOnExistingHost) {
 
         final CallContext context = CallContext.current();
         final User user = context.getCallingUser();
@@ -4668,7 +4669,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                     // save work context info (there are some duplications)
                     VmWorkReconfigure workInfo = new VmWorkReconfigure(user.getId(), account.getId(), vm.getId(),
-                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, oldServiceOffering, reconfiguringOnExistingHost);
+                            VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, newServiceOffering.getId(), reconfiguringOnExistingHost);
                     workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo));
 
                     _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vm.getId());
@@ -4796,7 +4797,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
             s_logger.info("Unable to find vm " + work.getVmId());
         }
         assert (vm != null);
-        reConfigureVm(vm.getUuid(), work.getNewServiceOffering(),
+
+        ServiceOffering newServiceOffering = _offeringDao.findById(vm.getId(), work.getNewServiceOfferingId());
+
+        reConfigureVm(vm.getUuid(), newServiceOffering,
                 work.isSameHost());
         return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, null);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
index 95314e3..285c8a2 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
@@ -26,7 +26,6 @@ import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.jobs.AsyncJob;
 import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
 import org.apache.cloudstack.framework.jobs.AsyncJobManager;
-import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
 import org.apache.cloudstack.jobs.JobInfo;
 
 import com.cloud.utils.Pair;
@@ -105,9 +104,8 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
         } catch(Throwable e) {
             s_logger.error("Unable to complete " + job + ", job origin:" + job.getRelated(), e);
 
-            String exceptionJson = JobSerializerHelper.toSerializedString(e);
-            s_logger.info("Serialize exception object into json: " + exceptionJson + ", job origin: " + job.getRelated());
-            _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, exceptionJson);
+            RuntimeException ex = new RuntimeException("Job failed due to exception " + e.getMessage());
+            _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, _asyncJobMgr.marshallResultObject(ex));
         } finally {
             CallContext.unregister();
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/orchestration/src/com/cloud/vm/VmWorkReconfigure.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkReconfigure.java b/engine/orchestration/src/com/cloud/vm/VmWorkReconfigure.java
index 4c564d5..17abeb2 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkReconfigure.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkReconfigure.java
@@ -16,25 +16,24 @@
 // under the License.
 package com.cloud.vm;
 
-import com.cloud.offering.ServiceOffering;
 
 public class VmWorkReconfigure extends VmWork {
     private static final long serialVersionUID = -4517030323758086615L;
 
-    ServiceOffering newServiceOffering;
+    Long newServiceOfferingId;
     boolean sameHost;
 
     public VmWorkReconfigure(long userId, long accountId, long vmId, String handlerName,
-            ServiceOffering newServiceOffering, boolean sameHost) {
+            Long newServiceOfferingId, boolean sameHost) {
 
         super(userId, accountId, vmId, handlerName);
 
-        this.newServiceOffering = newServiceOffering;
+        this.newServiceOfferingId = newServiceOfferingId;
         this.sameHost = sameHost;
     }
 
-    public ServiceOffering getNewServiceOffering() {
-        return newServiceOffering;
+    public Long getNewServiceOfferingId() {
+        return newServiceOfferingId;
     }
 
     public boolean isSameHost() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
index b554a23..3873dd2 100755
--- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
+++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java
@@ -97,8 +97,8 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
         this.rateMbps = rateMbps;
         this.multicastRateMbps = multicastRateMbps;
         this.offerHA = offerHA;
-        this.limitCpuUse = false;
-        this.volatileVm = false;
+        limitCpuUse = false;
+        volatileVm = false;
         this.defaultUse = defaultUse;
         this.vmType = vmType == null ? null : vmType.toString().toLowerCase();
     }
@@ -174,16 +174,16 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
             offering.getSystemUse(),
             true,
             offering.getDomainId());
-        this.cpu = offering.getCpu();
-        this.ramSize = offering.getRamSize();
-        this.speed = offering.getSpeed();
-        this.rateMbps = offering.getRateMbps();
-        this.multicastRateMbps = offering.getMulticastRateMbps();
-        this.offerHA = offering.getOfferHA();
-        this.limitCpuUse = offering.getLimitCpuUse();
-        this.volatileVm = offering.getVolatileVm();
-        this.hostTag = offering.getHostTag();
-        this.vmType = offering.getSystemVmType();
+        cpu = offering.getCpu();
+        ramSize = offering.getRamSize();
+        speed = offering.getSpeed();
+        rateMbps = offering.getRateMbps();
+        multicastRateMbps = offering.getMulticastRateMbps();
+        offerHA = offering.getOfferHA();
+        limitCpuUse = offering.getLimitCpuUse();
+        volatileVm = offering.getVolatileVm();
+        hostTag = offering.getHostTag();
+        vmType = offering.getSystemVmType();
     }
 
     @Override
@@ -325,6 +325,6 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering
     }
 
     public void setDynamicFlag(boolean isdynamic) {
-        this.isDynamic = isdynamic;
+        isDynamic = isdynamic;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 2a5009e..7d6e0ec 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -131,7 +131,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
 
     // TODO
     static final ConfigKey<Boolean> VmJobEnabled = new ConfigKey<Boolean>("Advanced",
-            Boolean.class, "vm.job.enabled", "true",
+            Boolean.class, "vm.job.enabled", "false",
             "True to enable new VM sync model. false to use the old way", false);
     static final ConfigKey<Long> VmJobCheckInterval = new ConfigKey<Long>("Advanced",
             Long.class, "vm.job.check.interval", "3000",

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/utils/src/com/cloud/utils/exception/CloudRuntimeException.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java
index f2608ed..148c25b 100755
--- a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java
+++ b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java
@@ -16,6 +16,9 @@
 // under the License.
 package com.cloud.utils.exception;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,9 +33,9 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont
     private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException;
 
     // This holds a list of uuids and their descriptive names.
-    protected ArrayList<ExceptionProxyObject> idList = new ArrayList<ExceptionProxyObject>();
+    transient protected ArrayList<ExceptionProxyObject> idList = new ArrayList<ExceptionProxyObject>();
 
-    protected ArrayList<Pair<Class<?>, String>> uuidList = new ArrayList<Pair<Class<?>, String>>();
+    transient protected ArrayList<Pair<Class<?>, String>> uuidList = new ArrayList<Pair<Class<?>, String>>();
 
     protected int csErrorCode;
 
@@ -48,6 +51,7 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont
 
     protected CloudRuntimeException() {
         super();
+
         setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName()));
     }
 
@@ -90,4 +94,45 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont
     public List<Pair<Class<?>, String>> getEntitiesInError() {
         return uuidList;
     }
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+
+        int idListSize = idList.size();
+        out.writeInt(idListSize);
+        for (ExceptionProxyObject proxy : idList) {
+            out.writeObject(proxy);
+        }
+
+        int uuidListSize = uuidList.size();
+        out.writeInt(uuidListSize);
+        for (Pair<Class<?>, String> entry : uuidList) {
+            out.writeObject(entry.first().getCanonicalName());
+            out.writeObject(entry.second());
+        }
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+
+        int idListSize = in.readInt();
+        if (idList == null)
+            idList = new ArrayList<ExceptionProxyObject>();
+        if (uuidList == null)
+            uuidList = new ArrayList<Pair<Class<?>, String>>();
+
+        for (int i = 0; i < idListSize; i++) {
+            ExceptionProxyObject proxy = (ExceptionProxyObject)in.readObject();
+
+            idList.add(proxy);
+        }
+
+        int uuidListSize = in.readInt();
+        for (int i = 0; i < uuidListSize; i++) {
+            String clzName = (String)in.readObject();
+            String val = (String)in.readObject();
+
+            uuidList.add(new Pair<Class<?>, String>(Class.forName(clzName), val));
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1e2e1ea0/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java
index ef84a14..0f1b4e0 100644
--- a/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java
+++ b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java
@@ -16,17 +16,22 @@
 // under the License.
 package com.cloud.utils.exception;
 
-public class ExceptionProxyObject {
+import java.io.Serializable;
+
+
+public class ExceptionProxyObject implements Serializable {
+    private static final long serialVersionUID = -7514266713085362352L;
+
     private String uuid;
     private String description;
 
-    public ExceptionProxyObject() {
+    public ExceptionProxyObject(){
 
     }
 
-    public ExceptionProxyObject(String uuid, String desc) {
+    public ExceptionProxyObject(String uuid, String desc){
         this.uuid = uuid;
-        this.description = desc;
+        description = desc;
     }
 
     public String getUuid() {
@@ -44,5 +49,4 @@ public class ExceptionProxyObject {
     public void setDescription(String description) {
         this.description = description;
     }
-
 }


[02/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5726: Using runtime discovered dao (in AsyncJobManagerImpl.submitAsyncJob) to persist record has a problem to locate the right DAO instance, it causes corrupted field value be stored in database. Put in a work-around fix first to always initialize record fields in all cases


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

Branch: refs/heads/master
Commit: 69f49839d3f4d4de137acf33e4afb18f3ec51124
Parents: 832c8e4
Author: Kelven Yang <ke...@gmail.com>
Authored: Thu Jan 2 15:13:00 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/69f49839/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java
----------------------------------------------------------------------
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 e9442ec..bfd9f18 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
@@ -241,6 +241,8 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
 
                 if (resultObject != null) {
                     job.setResult(resultObject);
+                } else {
+                    job.setResult(null);
                 }
 
                 job.setLastUpdated(DateUtil.currentGMTTime());


[13/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5752: Use pesudo job context when API dispather directly calls into orchestration flow


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

Branch: refs/heads/master
Commit: a05d71a80c16628d8cb15c419c3a794df16ec6ff
Parents: 0965adb
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Jan 3 18:05:31 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:13 2014 -0800

----------------------------------------------------------------------
 .../cloudstack/framework/jobs/AsyncJobExecutionContext.java      | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a05d71a8/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
----------------------------------------------------------------------
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
index 05b7bf8..f558e01 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
@@ -150,6 +150,10 @@ public class AsyncJobExecutionContext {
 
     public static AsyncJobExecutionContext getCurrentExecutionContext() {
         AsyncJobExecutionContext context = s_currentExectionContext.get();
+        if (context == null) {
+            context = registerPseudoExecutionContext(CallContext.current().getCallingAccountId(),
+                    CallContext.current().getCallingUserId());
+        }
         return context;
     }
 


[09/13] git commit: updated refs/heads/master to 1e2e1ea

Posted by ke...@apache.org.
CLOUDSTACK-5725: put origin flow context id into log4j context prefix to link jobs with the orchestration work flow in logging


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

Branch: refs/heads/master
Commit: 87381d42364d4b2ea0c78e1cf46ace9aa8ef2e8a
Parents: ad6454d
Author: Kelven Yang <ke...@gmail.com>
Authored: Fri Jan 3 15:46:46 2014 -0800
Committer: Kelven Yang <ke...@gmail.com>
Committed: Thu Jan 9 14:29:12 2014 -0800

----------------------------------------------------------------------
 .../src/com/cloud/vm/VirtualMachineManagerImpl.java | 11 +++++++++++
 .../src/com/cloud/vm/VmWorkJobDispatcher.java       | 16 +++++++++-------
 .../framework/jobs/AsyncJobExecutionContext.java    | 15 +++++++++++----
 .../src/com/cloud/storage/VolumeApiServiceImpl.java |  5 +++++
 .../cloud/vm/snapshot/VMSnapshotManagerImpl.java    |  4 ++++
 5 files changed, 40 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/87381d42/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 9d4cb04..d0adabf 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -4161,6 +4161,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setStep(VmWorkJobVO.Step.Starting);
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkStart workInfo = new VmWorkStart(callingUser.getId(), callingAccount.getId(), vm.getId(), VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER);
@@ -4213,6 +4214,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setStep(VmWorkJobVO.Step.Prepare);
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkStop workInfo = new VmWorkStop(user.getId(), account.getId(), vm.getId(), VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, cleanup);
@@ -4265,6 +4267,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setStep(VmWorkJobVO.Step.Prepare);
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkReboot workInfo = new VmWorkReboot(user.getId(), account.getId(), vm.getId(), VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, params);
@@ -4314,6 +4317,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkMigrate workInfo = new VmWorkMigrate(user.getId(), account.getId(), vm.getId(), VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, srcHostId, dest);
@@ -4367,6 +4371,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkMigrateWithStorage workInfo = new VmWorkMigrateWithStorage(user.getId(), account.getId(), vm.getId(),
@@ -4418,6 +4423,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkMigrateForScale workInfo = new VmWorkMigrateForScale(user.getId(), account.getId(), vm.getId(),
@@ -4469,6 +4475,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkStorageMigration workInfo = new VmWorkStorageMigration(user.getId(), account.getId(), vm.getId(),
@@ -4518,6 +4525,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkAddVmToNetwork workInfo = new VmWorkAddVmToNetwork(user.getId(), account.getId(), vm.getId(),
@@ -4566,6 +4574,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkRemoveNicFromVm workInfo = new VmWorkRemoveNicFromVm(user.getId(), account.getId(), vm.getId(),
@@ -4614,6 +4623,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkRemoveVmFromNetwork workInfo = new VmWorkRemoveVmFromNetwork(user.getId(), account.getId(), vm.getId(),
@@ -4664,6 +4674,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     workJob.setUserId(user.getId());
                     workJob.setVmType(vm.getType());
                     workJob.setVmInstanceId(vm.getId());
+                    workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                     // save work context info (there are some duplications)
                     VmWorkReconfigure workInfo = new VmWorkReconfigure(user.getId(), account.getId(), vm.getId(),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/87381d42/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
index 1af0dac..95314e3 100644
--- a/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
+++ b/engine/orchestration/src/com/cloud/vm/VmWorkJobDispatcher.java
@@ -62,13 +62,13 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
             assert (cmd != null);
 
             if (s_logger.isDebugEnabled())
-                s_logger.debug("Run VM work job: " + cmd);
+                s_logger.debug("Run VM work job: " + cmd + ", job origin: " + job.getRelated());
 
             Class<?> workClz = null;
             try {
                 workClz = Class.forName(job.getCmd());
             } catch (ClassNotFoundException e) {
-                s_logger.error("VM work class " + cmd + " is not found", e);
+                s_logger.error("VM work class " + cmd + " is not found" + ", job origin: " + job.getRelated(), e);
                 _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, e.getMessage());
                 return;
             }
@@ -76,13 +76,14 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
             work = VmWorkSerializer.deserialize(workClz, job.getCmdInfo());
             assert(work != null);
             if(work == null) {
-                s_logger.error("Unable to deserialize VM work " + job.getCmd() + ", job info: " + job.getCmdInfo());
+                s_logger.error("Unable to deserialize VM work " + job.getCmd() + ", job info: " + job.getCmdInfo() + ", job origin: " + job.getRelated());
                 _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, "Unable to deserialize VM work");
                 return;
             }
 
             if (_handlers == null || _handlers.isEmpty()) {
-                s_logger.error("Invalid startup configuration, no work job handler is found. cmd: " + job.getCmd() + ", job info: " + job.getCmdInfo());
+                s_logger.error("Invalid startup configuration, no work job handler is found. cmd: " + job.getCmd() + ", job info: " + job.getCmdInfo()
+                        + ", job origin: " + job.getRelated());
                 _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, "Invalid startup configuration. no job handler is found");
                 return;
             }
@@ -90,7 +91,8 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
             VmWorkJobHandler handler = _handlers.get(work.getHandlerName());
 
             if (handler == null) {
-                s_logger.error("Unable to find work job handler. handler name: " + work.getHandlerName() + ", job cmd: " + job.getCmd() + ", job info: " + job.getCmdInfo());
+                s_logger.error("Unable to find work job handler. handler name: " + work.getHandlerName() + ", job cmd: " + job.getCmd()
+                        + ", job info: " + job.getCmdInfo() + ", job origin: " + job.getRelated());
                 _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, "Unable to find work job handler");
                 return;
             }
@@ -101,10 +103,10 @@ public class VmWorkJobDispatcher extends AdapterBase implements AsyncJobDispatch
             _asyncJobMgr.completeAsyncJob(job.getId(), result.first(), 0, result.second());
 
         } catch(Throwable e) {
-            s_logger.error("Unable to complete " + job, e);
+            s_logger.error("Unable to complete " + job + ", job origin:" + job.getRelated(), e);
 
             String exceptionJson = JobSerializerHelper.toSerializedString(e);
-            s_logger.info("Serialize exception object into json: " + exceptionJson);
+            s_logger.info("Serialize exception object into json: " + exceptionJson + ", job origin: " + job.getRelated());
             _asyncJobMgr.completeAsyncJob(job.getId(), JobInfo.Status.FAILED, 0, exceptionJson);
         } finally {
             CallContext.unregister();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/87381d42/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
----------------------------------------------------------------------
diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
index 31fd827..05b7bf8 100644
--- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
+++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/AsyncJobExecutionContext.java
@@ -18,6 +18,7 @@ package org.apache.cloudstack.framework.jobs;
 
 import org.apache.log4j.Logger;
 
+import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao;
 import org.apache.cloudstack.framework.jobs.impl.AsyncJobJoinMapVO;
 import org.apache.cloudstack.framework.jobs.impl.JobSerializerHelper;
@@ -103,17 +104,19 @@ public class AsyncJobExecutionContext {
         s_jobMgr.joinJob(_job.getId(), joinJobId);
     }
 
-    public void joinJob(long joinJobId, String wakeupHandler, String wakeupDispatcher, String[] wakeupTopcisOnMessageBus, long wakeupIntervalInMilliSeconds,
-        long timeoutInMilliSeconds) {
+    public void joinJob(long joinJobId, String wakeupHandler, String wakeupDispatcher,
+            String[] wakeupTopcisOnMessageBus, long wakeupIntervalInMilliSeconds, long timeoutInMilliSeconds) {
         assert (_job != null);
-        s_jobMgr.joinJob(_job.getId(), joinJobId, wakeupHandler, wakeupDispatcher, wakeupTopcisOnMessageBus, wakeupIntervalInMilliSeconds, timeoutInMilliSeconds);
+        s_jobMgr.joinJob(_job.getId(), joinJobId, wakeupHandler, wakeupDispatcher, wakeupTopcisOnMessageBus,
+                wakeupIntervalInMilliSeconds, timeoutInMilliSeconds);
     }
 
     //
     // check failure exception before we disjoin the worker job
     // TODO : it is ugly and this will become unnecessary after we switch to full-async mode
     //
-    public void disjoinJob(long joinedJobId) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
+    public void disjoinJob(long joinedJobId) throws InsufficientCapacityException,
+            ConcurrentOperationException, ResourceUnavailableException {
         assert (_job != null);
 
         AsyncJobJoinMapVO record = s_joinMapDao.getJoinRecord(_job.getId(), joinedJobId);
@@ -171,4 +174,8 @@ public class AsyncJobExecutionContext {
     public static void setCurrentExecutionContext(AsyncJobExecutionContext currentContext) {
         s_currentExectionContext.set(currentContext);
     }
+
+    public static String getOriginJobContextId() {
+        return String.valueOf(CallContext.current().getContextId());
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/87381d42/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 0200233..7ab5887 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -2147,6 +2147,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkAttachVolume workInfo = new VmWorkAttachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId,
@@ -2193,6 +2194,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkDetachVolume workInfo = new VmWorkDetachVolume(callingUser.getId(), callingAccount.getId(), vm.getId(), VolumeApiServiceImpl.VM_WORK_JOB_HANDLER, volumeId);
@@ -2236,6 +2238,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkResizeVolume workInfo = new VmWorkResizeVolume(callingUser.getId(), callingAccount.getId(), vm.getId(),
@@ -2280,6 +2283,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkMigrateVolume workInfo = new VmWorkMigrateVolume(callingUser.getId(), callingAccount.getId(), vm.getId(),
@@ -2324,6 +2328,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkTakeVolumeSnapshot workInfo = new VmWorkTakeVolumeSnapshot(

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/87381d42/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
index 40476d0..2a5009e 100644
--- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
+++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java
@@ -830,6 +830,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkCreateVMSnapshot workInfo = new VmWorkCreateVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
@@ -873,6 +874,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkDeleteVMSnapshot workInfo = new VmWorkDeleteVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
@@ -916,6 +918,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkRevertToVMSnapshot workInfo = new VmWorkRevertToVMSnapshot(callingUser.getId(), callingAccount.getId(), vm.getId(),
@@ -959,6 +962,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana
                 workJob.setStep(VmWorkJobVO.Step.Starting);
                 workJob.setVmType(vm.getType());
                 workJob.setVmInstanceId(vm.getId());
+                workJob.setRelated(AsyncJobExecutionContext.getOriginJobContextId());
 
                 // save work context info (there are some duplications)
                 VmWorkDeleteAllVMSnapshots workInfo = new VmWorkDeleteAllVMSnapshots(callingUser.getId(), callingAccount.getId(), vm.getId(),