cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ahu...@apache.org
Subject [42/50] [abbrv] Merged
Date Fri, 10 May 2013 23:33:25 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
----------------------------------------------------------------------
diff --cc engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
index 4c6dd0f,0000000..8e96bff
mode 100644,000000..100644
--- a/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/RemoteHostEndPoint.java
@@@ -1,119 -1,0 +1,168 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.cloudstack.storage;
 +
 +import java.util.concurrent.Executors;
 +import java.util.concurrent.ScheduledExecutorService;
 +import java.util.concurrent.TimeUnit;
 +
 +import javax.inject.Inject;
 +
 +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
 +import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 +import org.apache.log4j.Logger;
 +
 +import com.cloud.agent.AgentManager;
 +import com.cloud.agent.Listener;
++import com.cloud.agent.api.AgentControlAnswer;
++import com.cloud.agent.api.AgentControlCommand;
 +import com.cloud.agent.api.Answer;
 +import com.cloud.agent.api.Command;
++import com.cloud.agent.api.StartupCommand;
 +import com.cloud.agent.manager.Commands;
 +import com.cloud.exception.AgentUnavailableException;
++import com.cloud.exception.ConnectionException;
 +import com.cloud.exception.OperationTimedoutException;
++import com.cloud.host.Host;
++import com.cloud.host.Status;
 +import com.cloud.utils.component.ComponentContext;
 +import com.cloud.utils.exception.CloudRuntimeException;
 +
 +public class RemoteHostEndPoint implements EndPoint {
 +    private static final Logger s_logger = Logger.getLogger(RemoteHostEndPoint.class);
 +    private  long hostId;
 +    private  String hostAddress;
 +    @Inject
 +    AgentManager agentMgr;
 +    @Inject
 +    HostEndpointRpcServer rpcServer;
 +    private ScheduledExecutorService executor;
 +
 +    public RemoteHostEndPoint() {
 +    	executor = Executors.newScheduledThreadPool(10);
 +    }
 +
 +    private void configure(long hostId, String hostAddress) {
 +        this.hostId = hostId;
 +        this.hostAddress = hostAddress;
 +    }
 +
 +    public static RemoteHostEndPoint getHypervisorHostEndPoint(long hostId, String hostAddress) {
 +        RemoteHostEndPoint ep = ComponentContext.inject(RemoteHostEndPoint.class);
 +        ep.configure(hostId, hostAddress);
 +        return ep;
 +    }
 +
 +    @Override
 +    public String getHostAddr() {
 +        return this.hostAddress;
 +    }
 +
++    @Override
 +    public long getId() {
 +        return this.hostId;
 +    }
 +
 +    @Override
 +    public Answer sendMessage(Command cmd) {
 +    	String errMsg = null;
 +    	try {
 +			return agentMgr.send(getId(), cmd);
 +		} catch (AgentUnavailableException e) {
 +			errMsg = e.toString();
 +			s_logger.debug("Failed to send command, due to Agent:" + getId() + ", " + e.toString());
 +		} catch (OperationTimedoutException e) {
 +			errMsg = e.toString();
 +			s_logger.debug("Failed to send command, due to Agent:" + getId() + ", " + e.toString());
 +		}
 +    	throw new CloudRuntimeException("Failed to send command, due to Agent:" + getId() + ", " + errMsg);
 +    }
 +
-     private class CmdRunner implements Runnable {
- 		final Command cmd;
++    private class CmdRunner implements Listener, Runnable {
 +		final AsyncCompletionCallback<Answer> callback;
- 		public CmdRunner(Command cmd, AsyncCompletionCallback<Answer> callback) {
- 			this.cmd = cmd;
++        Answer answer;
++
++        public CmdRunner(AsyncCompletionCallback<Answer> callback) {
 +			this.callback = callback;
 +		}
- 		@Override
- 		public void run() {
- 			Answer answer = sendMessage(cmd);
- 			callback.complete(answer);
- 		}
 +
++        @Override
++        public boolean processAnswers(long agentId, long seq, Answer[] answers) {
++            this.answer = answers[0];
++            executor.schedule(this, 10, TimeUnit.SECONDS);
++            return true;
++        }
++
++        @Override
++        public boolean processCommands(long agentId, long seq, Command[] commands) {
++            // TODO Auto-generated method stub
++            return false;
++        }
++
++        @Override
++        public AgentControlAnswer processControlCommand(long agentId, AgentControlCommand cmd) {
++            // TODO Auto-generated method stub
++            return null;
++        }
++
++        @Override
++        public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
++            // TODO Auto-generated method stub
++
++        }
++
++        @Override
++        public boolean processDisconnect(long agentId, Status state) {
++            // TODO Auto-generated method stub
++            return false;
++        }
++
++        @Override
++        public boolean isRecurring() {
++            // TODO Auto-generated method stub
++            return false;
++        }
++
++        @Override
++        public int getTimeout() {
++            // TODO Auto-generated method stub
++            return 0;
++        }
++
++        @Override
++        public boolean processTimeout(long agentId, long seq) {
++            // TODO Auto-generated method stub
++            return false;
++        }
++
++        @Override
++        public void run() {
++            callback.complete(answer);
++        }
 +	}
 +
 +    @Override
 +    public void sendMessageAsync(Command cmd, AsyncCompletionCallback<Answer> callback) {
-     	executor.schedule(new CmdRunner(cmd, callback), 10, TimeUnit.SECONDS);
-     }
- 
-     @Override
-     public void sendMessageAsyncWithListener(Command cmd, Listener listener) {
-     	try {
-     		this.agentMgr.send(getId(), new Commands(cmd), listener);
-     	} catch (AgentUnavailableException e) {
-     		s_logger.debug("Failed to send command: " + e.toString());
-     		throw new CloudRuntimeException("Failed to send command: " + e.toString());
-     	}
++        try {
++            agentMgr.send(this.hostId, new Commands(cmd), new CmdRunner(callback));
++        } catch (AgentUnavailableException e) {
++            throw new CloudRuntimeException("Unable to send message", e);
++        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
----------------------------------------------------------------------
diff --cc engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
index be7bd12,ea31be3..6be3399
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
@@@ -201,9 -176,11 +201,11 @@@ public class VolumeObject implements Vo
                      volEvent = Volume.Event.CreateRequested;
                  } else if (event == ObjectInDataStoreStateMachine.Event.CopyingRequested) {
                      volEvent = Volume.Event.CopyRequested;
+                 } else if (event == ObjectInDataStoreStateMachine.Event.MigrationRequested) {
+                     volEvent = Volume.Event.MigrationRequested;
                  }
              }
 -            
 +
              if (event == ObjectInDataStoreStateMachine.Event.DestroyRequested) {
                  volEvent = Volume.Event.DestroyRequested;
              } else if (event == ObjectInDataStoreStateMachine.Event.ExpungeRequested) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
diff --cc engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index 833f079,b39502b..414f802
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@@ -25,15 -24,14 +25,18 @@@ import java.util.Map
  
  import javax.inject.Inject;
  
++import org.apache.log4j.Logger;
++import org.springframework.stereotype.Component;
++
  import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity;
 -import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
 +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
  import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
 -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
  import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
@@@ -48,23 -45,15 +51,23 @@@ import org.apache.cloudstack.storage.da
  import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
  import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
  import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
 -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 -import org.apache.cloudstack.storage.motion.DataMotionService;
 -import org.apache.log4j.Logger;
 -import org.springframework.stereotype.Component;
 +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
 +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
- import org.apache.log4j.Logger;
- import org.springframework.stereotype.Component;
  
 +import com.cloud.agent.AgentManager;
 +import com.cloud.agent.api.Answer;
 +import com.cloud.agent.api.storage.ListVolumeAnswer;
 +import com.cloud.agent.api.storage.ListVolumeCommand;
+ import com.cloud.agent.api.to.VirtualMachineTO;
 +import com.cloud.alert.AlertManager;
 +import com.cloud.configuration.Config;
 +import com.cloud.configuration.Resource.ResourceType;
 +import com.cloud.configuration.dao.ConfigurationDao;
  import com.cloud.exception.ConcurrentOperationException;
 +import com.cloud.exception.ResourceAllocationException;
+ import com.cloud.host.Host;
  import com.cloud.storage.StoragePool;
 +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
  import com.cloud.storage.Volume;
  import com.cloud.storage.Volume.Type;
  import com.cloud.storage.VolumeVO;
@@@ -82,8 -66,8 +85,7 @@@ import com.cloud.vm.dao.VMInstanceDao
  
  @Component
  public class VolumeServiceImpl implements VolumeService {
--    private static final Logger s_logger = Logger
--            .getLogger(VolumeServiceImpl.class);
++    private static final Logger s_logger = Logger.getLogger(VolumeServiceImpl.class);
      @Inject
      VolumeDao volDao;
      @Inject
@@@ -121,11 -87,11 +123,11 @@@
  
      public VolumeServiceImpl() {
      }
 -    
 +
      private class CreateVolumeContext<T> extends AsyncRpcConext<T> {
  
--        private DataObject volume;
--        private AsyncCallFuture<VolumeApiResult> future;
++        private final DataObject volume;
++        private final AsyncCallFuture<VolumeApiResult> future;
          /**
           * @param callback
           */
@@@ -177,10 -143,10 +179,10 @@@
          context.getFuture().complete(volResult);
          return null;
      }
 -    
 +
      private class DeleteVolumeContext<T> extends AsyncRpcConext<T> {
          private final VolumeObject volume;
--        private AsyncCallFuture<VolumeApiResult> future;
++        private final AsyncCallFuture<VolumeApiResult> future;
          /**
           * @param callback
           */
@@@ -205,13 -171,13 +207,13 @@@
          AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
          VolumeApiResult result = new VolumeApiResult(volume);
          if (volume.getDataStore() == null) {
--            this.volDao.remove(volume.getId());
++            volDao.remove(volume.getId());
              future.complete(result);
              return future;
          }
 -        
 +
          String vmName = null;
--        VolumeVO vol = this.volDao.findById(volume.getId());
++        VolumeVO vol = volDao.findById(volume.getId());
          if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) {
              VirtualMachine vm = vmDao.findByIdIncludingRemoved(vol
                      .getInstanceId());
@@@ -227,7 -193,7 +229,7 @@@
                  s_logger.debug("Marking volume that was never created as destroyed: "
                          + vol);
              }
--            this.volDao.remove(vol.getId());
++            volDao.remove(vol.getId());
              future.complete(result);
              return future;
          }
@@@ -487,13 -414,13 +489,13 @@@
      @DB
      public boolean destroyVolume(long volumeId)
              throws ConcurrentOperationException {
 -        
 -        VolumeInfo vol = this.volFactory.getVolume(volumeId);
 +
-         VolumeInfo vol = this.volFactory.getVolume(volumeId);
++        VolumeInfo vol = volFactory.getVolume(volumeId);
          vol.processEvent(Event.DestroyRequested);
--        this.snapshotMgr.deletePoliciesForVolume(volumeId);
++        snapshotMgr.deletePoliciesForVolume(volumeId);
  
          vol.processEvent(Event.OperationSuccessed);
 -             
 +
          return true;
      }
  
@@@ -505,13 -432,12 +507,13 @@@
          try {
          	DataObject volumeOnStore = store.create(volume);
          	volume.processEvent(Event.CreateOnlyRequested);
 -        	 CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, 
 -        			 (VolumeObject)volume, store, volumeOnStore, future);
 +        	snapshot.processEvent(Event.CopyingRequested);
 +        	 CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null,
-         			 (VolumeObject)volume, store, volumeOnStore, future, snapshot);
++        			 volume, store, volumeOnStore, future, snapshot);
               AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller =  AsyncCallbackDispatcher.create(this);
               caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null))
               .setContext(context);
--        	this.motionSrv.copyAsync(snapshot, volumeOnStore, caller);
++        	motionSrv.copyAsync(snapshot, volumeOnStore, caller);
          } catch (Exception e) {
          	s_logger.debug("create volume from snapshot failed", e);
          	VolumeApiResult result = new VolumeApiResult(volume);
@@@ -558,9 -482,9 +560,9 @@@
          newVol.setPoolId(pool.getId());
          newVol.setLastPoolId(lastPoolId);
          newVol.setPodId(pool.getPodId());
--        return this.volDao.persist(newVol);
++        return volDao.persist(newVol);
      }
 -    
 +
  
      private class CopyVolumeContext<T> extends AsyncRpcConext<T> {
          final VolumeInfo srcVolume;
@@@ -586,27 -510,27 +588,27 @@@
          AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
          VolumeApiResult res = new VolumeApiResult(srcVolume);
          try {
--            if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) {
++            if (!snapshotMgr.canOperateOnVolume(srcVolume)) {
                  s_logger.debug(
                          "There are snapshots creating on this volume, can not move this volume");
 -                
 +
                  res.setResult("There are snapshots creating on this volume, can not move this volume");
                  future.complete(res);
                  return future;
              }
  
              VolumeVO destVol = duplicateVolumeOnAnotherStorage(srcVolume, (StoragePool)destStore);
--            VolumeInfo destVolume = this.volFactory.getVolume(destVol.getId(), destStore);
-             destVolume.processEvent(Event.CreateOnlyRequested);
-             srcVolume.processEvent(Event.CopyingRequested);
++            VolumeInfo destVolume = volFactory.getVolume(destVol.getId(), destStore);
+             destVolume.processEvent(Event.MigrationRequested);
+             srcVolume.processEvent(Event.MigrationRequested);
  
 -            CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume, 
 +            CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume,
                      destVolume,
                      destStore);
              AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
              caller.setCallback(caller.getTarget().copyVolumeCallBack(null, null))
              .setContext(context);
--            this.motionSrv.copyAsync(srcVolume, destVolume, caller);
++            motionSrv.copyAsync(srcVolume, destVolume, caller);
          } catch (Exception e) {
              s_logger.debug("Failed to copy volume", e);
              res.setResult(e.toString());
@@@ -626,14 -550,18 +628,18 @@@
                  res.setResult(result.getResult());
                  destVolume.processEvent(Event.OperationFailed);
                  srcVolume.processEvent(Event.OperationFailed);
-                 AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(destVolume);
+                 destroyVolume(destVolume.getId());
 -                destVolume = this.volFactory.getVolume(destVolume.getId());
 -                AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(destVolume);
++                destVolume = volFactory.getVolume(destVolume.getId());
++                AsyncCallFuture<VolumeApiResult> destroyFuture = expungeVolumeAsync(destVolume);
                  destroyFuture.get();
                  future.complete(res);
                  return null;
              }
              srcVolume.processEvent(Event.OperationSuccessed);
 -            destVolume.processEvent(Event.OperationSuccessed);
 +            destVolume.processEvent(Event.OperationSuccessed, result.getAnswer());
-             AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(srcVolume);
+             destroyVolume(srcVolume.getId());
 -            srcVolume = this.volFactory.getVolume(srcVolume.getId());
 -            AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(srcVolume);
++            srcVolume = volFactory.getVolume(srcVolume.getId());
++            AsyncCallFuture<VolumeApiResult> destroyFuture = expungeVolumeAsync(srcVolume);
              destroyFuture.get();
              future.complete(res);
              return null;
@@@ -646,15 -574,169 +652,173 @@@
          return null;
      }
  
++
+     private class MigrateVolumeContext<T> extends AsyncRpcConext<T> {
+         final VolumeInfo srcVolume;
+         final VolumeInfo destVolume;
+         final DataStore destStore;
+         final AsyncCallFuture<VolumeApiResult> future;
+         /**
+          * @param callback
+          */
+         public MigrateVolumeContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<VolumeApiResult> future,
+                 VolumeInfo srcVolume, VolumeInfo destVolume, DataStore destStore) {
+             super(callback);
+             this.srcVolume = srcVolume;
+             this.destVolume = destVolume;
+             this.destStore = destStore;
+             this.future = future;
+         }
+     }
+ 
+     @Override
+     public AsyncCallFuture<VolumeApiResult> migrateVolume(VolumeInfo srcVolume, DataStore destStore) {
+         AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
+         VolumeApiResult res = new VolumeApiResult(srcVolume);
+         try {
 -            if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) {
++            if (!snapshotMgr.canOperateOnVolume(srcVolume)) {
+                 s_logger.debug("Snapshots are being created on this volume. This volume cannot be migrated now.");
+                 res.setResult("Snapshots are being created on this volume. This volume cannot be migrated now.");
+                 future.complete(res);
+                 return future;
+             }
+ 
 -            VolumeInfo destVolume = this.volFactory.getVolume(srcVolume.getId(), destStore);
++            VolumeInfo destVolume = volFactory.getVolume(srcVolume.getId(), destStore);
+             srcVolume.processEvent(Event.MigrationRequested);
+             MigrateVolumeContext<VolumeApiResult> context = new MigrateVolumeContext<VolumeApiResult>(null, future,
+                     srcVolume, destVolume, destStore);
+             AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
+             caller.setCallback(caller.getTarget().migrateVolumeCallBack(null, null)).setContext(context);
 -            this.motionSrv.copyAsync(srcVolume, destVolume, caller);
++            motionSrv.copyAsync(srcVolume, destVolume, caller);
+         } catch (Exception e) {
+             s_logger.debug("Failed to copy volume", e);
+             res.setResult(e.toString());
+             future.complete(res);
+         }
+         return future;
+     }
+ 
+     protected Void migrateVolumeCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
+             MigrateVolumeContext<VolumeApiResult> context) {
+         VolumeInfo srcVolume = context.srcVolume;
+         VolumeInfo destVolume = context.destVolume;
+         CopyCommandResult result = callback.getResult();
+         AsyncCallFuture<VolumeApiResult> future = context.future;
+         VolumeApiResult res = new VolumeApiResult(srcVolume);
+         try {
+             if (result.isFailed()) {
+                 res.setResult(result.getResult());
+                 srcVolume.processEvent(Event.OperationFailed);
+                 future.complete(res);
+             } else {
+                 srcVolume.processEvent(Event.OperationSuccessed);
+                 future.complete(res);
+             }
+         } catch (Exception e) {
+             s_logger.error("Failed to process copy volume callback", e);
+             res.setResult(e.toString());
+             future.complete(res);
+         }
+ 
+         return null;
+     }
+ 
+     private class MigrateVmWithVolumesContext<T> extends AsyncRpcConext<T> {
+         final Map<VolumeInfo, DataStore> volumeToPool;
+         final AsyncCallFuture<CommandResult> future;
+         /**
+          * @param callback
+          */
+         public MigrateVmWithVolumesContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<CommandResult> future,
+                 Map<VolumeInfo, DataStore> volumeToPool) {
+             super(callback);
+             this.volumeToPool = volumeToPool;
+             this.future = future;
+         }
+     }
+ 
+     @Override
+     public AsyncCallFuture<CommandResult> migrateVolumes(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo,
+             Host srcHost, Host destHost) {
+         AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
+         CommandResult res = new CommandResult();
+         try {
+             // Check to make sure there are no snapshot operations on a volume and
+             // put it in the migrating state.
+             List<VolumeInfo> volumesMigrating = new ArrayList<VolumeInfo>();
+             for (Map.Entry<VolumeInfo, DataStore> entry : volumeMap.entrySet()) {
+                 VolumeInfo volume = entry.getKey();
 -                if (!this.snapshotMgr.canOperateOnVolume(volume)) {
++                if (!snapshotMgr.canOperateOnVolume(volume)) {
+                     s_logger.debug("Snapshots are being created on a volume. Volumes cannot be migrated now.");
+                     res.setResult("Snapshots are being created on a volume. Volumes cannot be migrated now.");
+                     future.complete(res);
+ 
+                     // All the volumes that are already in migrating state need to be put back in ready state.
+                     for (VolumeInfo volumeMigrating : volumesMigrating) {
+                         volumeMigrating.processEvent(Event.OperationFailed);
+                     }
+                     return future;
+                 } else {
+                     volume.processEvent(Event.MigrationRequested);
+                     volumesMigrating.add(volume);
+                 }
+             }
+ 
+             MigrateVmWithVolumesContext<CommandResult> context = new MigrateVmWithVolumesContext<CommandResult>(null,
+                     future, volumeMap);
+             AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
+             caller.setCallback(caller.getTarget().migrateVmWithVolumesCallBack(null, null)).setContext(context);
 -            this.motionSrv.copyAsync(volumeMap, vmTo, srcHost, destHost, caller);
++            motionSrv.copyAsync(volumeMap, vmTo, srcHost, destHost, caller);
+ 
+         } catch (Exception e) {
+             s_logger.debug("Failed to copy volume", e);
+             res.setResult(e.toString());
+             future.complete(res);
+         }
+ 
+         return future;
+     }
+ 
+     protected Void migrateVmWithVolumesCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback,
+             MigrateVmWithVolumesContext<CommandResult> context) {
+         Map<VolumeInfo, DataStore> volumeToPool = context.volumeToPool;
+         CopyCommandResult result = callback.getResult();
+         AsyncCallFuture<CommandResult> future = context.future;
+         CommandResult res = new CommandResult();
+         try {
+             if (result.isFailed()) {
+                 res.setResult(result.getResult());
+                 for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+                     VolumeInfo volume = entry.getKey();
+                     volume.processEvent(Event.OperationFailed);
+                 }
+                 future.complete(res);
+             } else {
+                 for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+                     VolumeInfo volume = entry.getKey();
+                     volume.processEvent(Event.OperationSuccessed);
+                 }
+                 future.complete(res);
+             }
+         } catch (Exception e) {
+             s_logger.error("Failed to process copy volume callback", e);
+             res.setResult(e.toString());
+             future.complete(res);
+         }
+ 
+         return null;
+     }
+ 
++
      @Override
      public AsyncCallFuture<VolumeApiResult> registerVolume(VolumeInfo volume, DataStore store) {
 -        
 +
          AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
 -        VolumeObject vo = (VolumeObject) volume;
 +        DataObject volumeOnStore = store.create(volume);
  
 -        CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, vo, future);
 +        volumeOnStore.processEvent(Event.CreateOnlyRequested);
 +
 +        CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, volumeOnStore, future);
          AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this);
          caller.setCallback(caller.getTarget().registerVolumeCallback(null, null))
          .setContext(context);
@@@ -727,151 -805,13 +891,151 @@@
  			future.complete(res);
  			return null;
  		}
 -		
 +
  		VolumeApiResult res = new VolumeApiResult(volume);
  		future.complete(res);
 -		
 +
  		return null;
  	}
 -	
 -	
 +
 +    @Override
 +    public void handleVolumeSync(DataStore store) {
 +        if (store == null) {
 +            s_logger.warn("Huh? ssHost is null");
 +            return;
 +        }
 +        long storeId = store.getId();
 +        Long zoneId = store.getScope().getScopeId();
 +
 +
 +        Map<Long, TemplateProp> volumeInfos = listVolume(store);
 +        if (volumeInfos == null) {
 +            return;
 +        }
 +
 +        List<VolumeDataStoreVO> dbVolumes = _volumeStoreDao.listByStoreId(storeId);
 +        List<VolumeDataStoreVO> toBeDownloaded = new ArrayList<VolumeDataStoreVO>(dbVolumes);
 +        for (VolumeDataStoreVO volumeStore : dbVolumes){
 +            VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId());
 +            //Exists then don't download
 +            if (volumeInfos.containsKey(volume.getId())){
 +                TemplateProp volInfo = volumeInfos.remove(volume.getId());
 +                toBeDownloaded.remove(volumeStore);
 +                s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table");
 +                if (volumeStore.getDownloadState() != Status.DOWNLOADED) {
 +                    volumeStore.setErrorString("");
 +                }
 +                if (volInfo.isCorrupted()) {
 +                    volumeStore.setDownloadState(Status.DOWNLOAD_ERROR);
 +                    String msg = "Volume " + volume.getUuid() + " is corrupted on image store ";
 +                    volumeStore.setErrorString(msg);
 +                    s_logger.info("msg");
 +                    if (volumeStore.getDownloadUrl() == null) {
 +                        msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in image store: " + volumeStore.getDataStoreId();
 +                        s_logger.warn(msg);
 +                    } else {
 +                        toBeDownloaded.add(volumeStore);
 +                    }
 +
 +                } else { // Put them in right status
 +                    volumeStore.setDownloadPercent(100);
 +                    volumeStore.setDownloadState(Status.DOWNLOADED);
 +                    volumeStore.setInstallPath(volInfo.getInstallPath());
 +                    volumeStore.setSize(volInfo.getSize());
 +                    volumeStore.setPhysicalSize(volInfo.getPhysicalSize());
 +                    volumeStore.setLastUpdated(new Date());
 +                    _volumeStoreDao.update(volumeStore.getId(), volumeStore);
 +
 +                    if (volume.getSize() == 0) {
 +                        // Set volume size in volumes table
 +                        volume.setSize(volInfo.getSize());
 +                        _volumeDao.update(volumeStore.getVolumeId(), volume);
 +                    }
 +
 +                    if (volInfo.getSize() > 0) {
 +                        try {
 +                            String url = _volumeStoreDao.findByVolume(volume.getId()).getDownloadUrl();
 +                            _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()),
 +                                    com.cloud.configuration.Resource.ResourceType.secondary_storage,
 +                                    volInfo.getSize() - UriUtils.getRemoteSize(url));
 +                        } catch (ResourceAllocationException e) {
 +                            s_logger.warn(e.getMessage());
 +                            _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(),
 +                                    volume.getPodId(), e.getMessage(), e.getMessage());
 +                        } finally {
 +                            _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(),
 +                                    com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal());
 +                        }
 +                    }
 +                }
 +                continue;
 +            }
 +            // Volume is not on secondary but we should download.
 +            if (volumeStore.getDownloadState() != Status.DOWNLOADED) {
 +                s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId + ", will request download to start/resume shortly");
 +                toBeDownloaded.add(volumeStore);
 +            }
 +        }
 +
 +        //Download volumes which haven't been downloaded yet.
 +        if (toBeDownloaded.size() > 0) {
 +            for (VolumeDataStoreVO volumeHost : toBeDownloaded) {
 +                if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download
 +                    continue;
 +                }
 +                s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + store.getName());
 +                //TODO: pass a callback later
-                 VolumeInfo vol = this.volFactory.getVolume(volumeHost.getVolumeId());
-                 this.createVolumeAsync(vol, store);
++                VolumeInfo vol = volFactory.getVolume(volumeHost.getVolumeId());
++                createVolumeAsync(vol, store);
 +            }
 +        }
 +
 +        //Delete volumes which are not present on DB.
 +        for (Long uniqueName : volumeInfos.keySet()) {
 +            TemplateProp vInfo = volumeInfos.get(uniqueName);
-             this.expungeVolumeAsync(this.volFactory.getVolume(vInfo.getId(), store));
++            expungeVolumeAsync(volFactory.getVolume(vInfo.getId(), store));
 +
 +            String description = "Deleted volume " + vInfo.getTemplateName() + " on image store " + storeId;
 +            s_logger.info(description);
 +        }
 +
 +    }
 +
 +    private Map<Long, TemplateProp> listVolume(DataStore store) {
 +        ListVolumeCommand cmd = new ListVolumeCommand(store.getTO(), store.getUri());
 +        EndPoint ep = _epSelector.select(store);
 +        Answer answer = ep.sendMessage(cmd);
 +        if (answer != null && answer.getResult()) {
 +            ListVolumeAnswer tanswer = (ListVolumeAnswer)answer;
 +            return tanswer.getTemplateInfo();
 +        } else {
 +            if (s_logger.isDebugEnabled()) {
 +                s_logger.debug("Can not list volumes for image store " + store.getId());
 +            }
 +        }
 +
 +        return null;
 +    }
 +
 +    @Override
 +    public SnapshotInfo takeSnapshot(VolumeInfo volume) {
 +    	VolumeObject vol = (VolumeObject)volume;
 +    	vol.stateTransit(Volume.Event.SnapshotRequested);
 +
 +    	SnapshotInfo snapshot = null;
 +    	try {
-     		snapshot = this.snapshotMgr.takeSnapshot(volume);
++    		snapshot = snapshotMgr.takeSnapshot(volume);
 +		} catch (Exception e) {
 +			s_logger.debug("Take snapshot: " + volume.getId() + " failed: " + e.toString());
 +		} finally {
 +			if (snapshot != null) {
 +				vol.stateTransit(Volume.Event.OperationSucceeded);
 +			} else {
 +				vol.stateTransit(Volume.Event.OperationFailed);
 +			}
 +		}
 +
 +    	return snapshot;
 +    }
  
  }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
index f67a818,ab6eec3..081aa5a
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java
@@@ -16,12 -16,74 +16,75 @@@
  // under the License.
  package com.cloud.agent.manager;
  
- import com.cloud.agent.api.*;
+ import java.util.HashMap;
+ import java.util.Map;
+ 
+ import javax.ejb.Local;
+ import javax.inject.Inject;
+ import javax.naming.ConfigurationException;
+ 
+ import org.apache.log4j.Logger;
+ import org.springframework.stereotype.Component;
+ 
++import org.apache.cloudstack.storage.command.DownloadCommand;
++import org.apache.cloudstack.storage.command.DownloadProgressCommand;
++
+ import com.cloud.agent.api.Answer;
+ import com.cloud.agent.api.AttachIsoCommand;
+ import com.cloud.agent.api.AttachVolumeCommand;
+ import com.cloud.agent.api.BackupSnapshotCommand;
+ import com.cloud.agent.api.BumpUpPriorityCommand;
+ import com.cloud.agent.api.CheckHealthCommand;
+ import com.cloud.agent.api.CheckNetworkCommand;
+ import com.cloud.agent.api.CheckRouterCommand;
+ import com.cloud.agent.api.CheckVirtualMachineCommand;
+ import com.cloud.agent.api.CleanupNetworkRulesCmd;
+ import com.cloud.agent.api.ClusterSyncCommand;
+ import com.cloud.agent.api.Command;
+ import com.cloud.agent.api.ComputeChecksumCommand;
+ import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
+ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
+ import com.cloud.agent.api.CreateStoragePoolCommand;
+ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
+ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
+ import com.cloud.agent.api.DeleteStoragePoolCommand;
+ import com.cloud.agent.api.GetDomRVersionCmd;
+ import com.cloud.agent.api.GetHostStatsCommand;
+ import com.cloud.agent.api.GetStorageStatsCommand;
+ import com.cloud.agent.api.GetVmStatsCommand;
+ import com.cloud.agent.api.GetVncPortCommand;
+ import com.cloud.agent.api.MaintainCommand;
+ import com.cloud.agent.api.ManageSnapshotCommand;
+ import com.cloud.agent.api.MigrateCommand;
+ import com.cloud.agent.api.ModifyStoragePoolCommand;
+ import com.cloud.agent.api.NetworkUsageCommand;
+ import com.cloud.agent.api.PingTestCommand;
+ import com.cloud.agent.api.PrepareForMigrationCommand;
+ import com.cloud.agent.api.RebootCommand;
+ import com.cloud.agent.api.SecStorageSetupCommand;
+ import com.cloud.agent.api.SecStorageVMSetupCommand;
+ import com.cloud.agent.api.SecurityGroupRulesCmd;
+ import com.cloud.agent.api.StartCommand;
+ import com.cloud.agent.api.StopCommand;
+ import com.cloud.agent.api.StoragePoolInfo;
  import com.cloud.agent.api.check.CheckSshCommand;
  import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand;
  import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand;
- import com.cloud.agent.api.routing.*;
- import com.cloud.agent.api.storage.*;
+ import com.cloud.agent.api.routing.DhcpEntryCommand;
+ import com.cloud.agent.api.routing.IpAssocCommand;
+ import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
+ import com.cloud.agent.api.routing.SavePasswordCommand;
+ import com.cloud.agent.api.routing.SetFirewallRulesCommand;
+ import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
+ import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
+ import com.cloud.agent.api.routing.VmDataCommand;
+ import com.cloud.agent.api.storage.CopyVolumeCommand;
+ import com.cloud.agent.api.storage.CreateCommand;
+ import com.cloud.agent.api.storage.DeleteTemplateCommand;
+ import com.cloud.agent.api.storage.DestroyCommand;
 -import com.cloud.agent.api.storage.DownloadCommand;
 -import com.cloud.agent.api.storage.DownloadProgressCommand;
+ import com.cloud.agent.api.storage.ListTemplateCommand;
+ import com.cloud.agent.api.storage.ListVolumeCommand;
+ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
  import com.cloud.simulator.MockConfigurationVO;
  import com.cloud.simulator.MockHost;
  import com.cloud.simulator.MockVMVO;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
index 83ee150,562a7fe..536a1f8
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/discoverer/XcpServerDiscoverer.java
@@@ -425,10 -427,13 +425,13 @@@ public class XcpServerDiscoverer extend
      		prodVersion = prodVersion.trim();
      	}
  
-         if(prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") ||  prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4") || prodVersion.startsWith("1.6")))
-             return new XcpServerResource();
+         if(prodBrand.equals("XCP") && (prodVersion.equals("1.0.0") ||  prodVersion.equals("1.1.0") || prodVersion.equals("5.6.100") || prodVersion.startsWith("1.4"))) {
+             return new XcpServerResource("1.1");
+         } else if (prodBrand.equals("XCP") && prodVersion.startsWith("1.6")) {
+         	return new XcpServerResource("1.6");
+         }
  
 -    	if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0")) 
 +    	if(prodBrand.equals("XenServer") && prodVersion.equals("5.6.0"))
      		return new XenServer56Resource();
  
      	if (prodBrand.equals("XenServer") && prodVersion.equals("6.0.0"))

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java
----------------------------------------------------------------------
diff --cc plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java
index 0000000,353f2b5..e92b818
mode 000000,100644..100644
--- a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java
+++ b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java
@@@ -1,0 -1,239 +1,241 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one
+  * or more contributor license agreements.  See the NOTICE file
+  * distributed with this work for additional information
+  * regarding copyright ownership.  The ASF licenses this file
+  * to you under the Apache License, Version 2.0 (the
+  * "License"); you may not use this file except in compliance
+  * with the License.  You may obtain a copy of the License at
+  *
+  *   http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing,
+  * software distributed under the License is distributed on an
+  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  * KIND, either express or implied.  See the License for the
+  * specific language governing permissions and limitations
+  * under the License.
+  */
+ package org.apache.cloudstack.storage.motion;
+ 
+ import java.util.HashMap;
 -import java.util.Map;
+ import java.util.List;
++import java.util.Map;
+ 
+ import javax.inject.Inject;
+ 
++import org.apache.log4j.Logger;
++import org.springframework.stereotype.Component;
++
+ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
++import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
+ import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
+ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
+ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 -import org.apache.log4j.Logger;
 -import org.springframework.stereotype.Component;
+ 
+ import com.cloud.agent.AgentManager;
+ import com.cloud.agent.api.Answer;
+ import com.cloud.agent.api.MigrateWithStorageAnswer;
+ import com.cloud.agent.api.MigrateWithStorageCommand;
+ import com.cloud.agent.api.MigrateWithStorageCompleteAnswer;
+ import com.cloud.agent.api.MigrateWithStorageCompleteCommand;
+ import com.cloud.agent.api.MigrateWithStorageReceiveAnswer;
+ import com.cloud.agent.api.MigrateWithStorageReceiveCommand;
+ import com.cloud.agent.api.MigrateWithStorageSendAnswer;
+ import com.cloud.agent.api.MigrateWithStorageSendCommand;
+ import com.cloud.agent.api.to.StorageFilerTO;
+ import com.cloud.agent.api.to.VirtualMachineTO;
+ import com.cloud.agent.api.to.VolumeTO;
+ import com.cloud.exception.AgentUnavailableException;
+ import com.cloud.exception.OperationTimedoutException;
+ import com.cloud.host.Host;
+ import com.cloud.storage.StoragePool;
+ import com.cloud.storage.VolumeVO;
+ import com.cloud.storage.dao.VolumeDao;
+ import com.cloud.utils.exception.CloudRuntimeException;
+ import com.cloud.vm.VMInstanceVO;
+ import com.cloud.vm.dao.VMInstanceDao;
+ 
+ @Component
+ public class XenServerStorageMotionStrategy implements DataMotionStrategy {
+     private static final Logger s_logger = Logger.getLogger(XenServerStorageMotionStrategy.class);
+     @Inject AgentManager agentMgr;
+     @Inject VolumeDao volDao;
+     @Inject VolumeDataFactory volFactory;
+     @Inject PrimaryDataStoreDao storagePoolDao;
+     @Inject VMInstanceDao instanceDao;
+ 
+     @Override
+     public boolean canHandle(DataObject srcData, DataObject destData) {
+         return false;
+     }
+ 
+     @Override
+     public boolean canHandle(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
+         return true;
+     }
+ 
+     @Override
+     public Void copyAsync(DataObject srcData, DataObject destData,
+             AsyncCompletionCallback<CopyCommandResult> callback) {
+         CopyCommandResult result = new CopyCommandResult(null, null);
+         result.setResult("Unsupported operation requested for copying data.");
+         callback.complete(result);
+ 
+         return null;
+     }
+ 
+     @Override
+     public Void copyAsync(Map<VolumeInfo, DataStore> volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost,
+             AsyncCompletionCallback<CopyCommandResult> callback) {
+         Answer answer = null;
+         String errMsg = null;
+         try {
+             VMInstanceVO instance = instanceDao.findById(vmTo.getId());
+             if (instance != null) {
+                 if (srcHost.getClusterId() == destHost.getClusterId()) {
+                     answer = migrateVmWithVolumesWithinCluster(instance, vmTo, srcHost, destHost, volumeMap);
+                 } else {
+                     answer = migrateVmWithVolumesAcrossCluster(instance, vmTo, srcHost, destHost, volumeMap);
+                 }
+             } else {
+                 throw new CloudRuntimeException("Unsupported operation requested for moving data.");
+             }
+         } catch (Exception e) {
+             s_logger.error("copy failed", e);
+             errMsg = e.toString();
+         }
+ 
+         CopyCommandResult result = new CopyCommandResult(null, answer);
+         result.setResult(errMsg);
+         callback.complete(result);
+         return null;
+     }
+ 
+     private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost,
+             Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException {
+ 
+         // Initiate migration of a virtual machine with it's volumes.
+         try {
+             Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO, StorageFilerTO>();
+             for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+                 VolumeInfo volume = entry.getKey();
+                 VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId()));
+                 StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue());
+                 volumeToFilerto.put(volumeTo, filerTo);
+             }
+ 
+             // Migration across cluster needs to be done in three phases.
+             // 1. Send a migrate receive command to the destination host so that it is ready to receive a vm.
+             // 2. Send a migrate send command to the source host. This actually migrates the vm to the destination.
+             // 3. Complete the process. Update the volume details.
+             MigrateWithStorageReceiveCommand receiveCmd = new MigrateWithStorageReceiveCommand(to, volumeToFilerto);
+             MigrateWithStorageReceiveAnswer receiveAnswer = (MigrateWithStorageReceiveAnswer) agentMgr.send(
+                     destHost.getId(), receiveCmd);
+             if (receiveAnswer == null) {
+                 s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost + " failed.");
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
+             } else if (!receiveAnswer.getResult()) {
+                 s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + receiveAnswer.getDetails());
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost +
+                         ". " + receiveAnswer.getDetails());
+             }
+ 
+             MigrateWithStorageSendCommand sendCmd = new MigrateWithStorageSendCommand(to, receiveAnswer.getVolumeToSr(),
+                     receiveAnswer.getNicToNetwork(), receiveAnswer.getToken());
+             MigrateWithStorageSendAnswer sendAnswer = (MigrateWithStorageSendAnswer) agentMgr.send(
+                     srcHost.getId(), sendCmd);
+             if (sendAnswer == null) {
+                 s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost + " failed.");
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
+             } else if (!sendAnswer.getResult()) {
+                 s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + sendAnswer.getDetails());
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost +
+                         ". " + sendAnswer.getDetails());
+             }
+ 
+             MigrateWithStorageCompleteCommand command = new MigrateWithStorageCompleteCommand(to);
+             MigrateWithStorageCompleteAnswer answer = (MigrateWithStorageCompleteAnswer) agentMgr.send(
+                     destHost.getId(), command);
+             if (answer == null) {
+                 s_logger.error("Migration with storage of vm " + vm + " failed.");
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
+             } else if (!answer.getResult()) {
+                 s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails());
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost +
+                         ". " + answer.getDetails());
+             } else {
+                 // Update the volume details after migration.
+                 updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos());
+             }
+ 
+             return answer;
+         } catch (OperationTimedoutException e) {
+             s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
+             throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId());
+         }
+     }
+ 
+     private Answer migrateVmWithVolumesWithinCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost,
+             Host destHost, Map<VolumeInfo, DataStore> volumeToPool) throws AgentUnavailableException {
+ 
+         // Initiate migration of a virtual machine with it's volumes.
+         try {
+             Map<VolumeTO, StorageFilerTO> volumeToFilerto = new HashMap<VolumeTO, StorageFilerTO>();
+             for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+                 VolumeInfo volume = entry.getKey();
+                 VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId()));
+                 StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue());
+                 volumeToFilerto.put(volumeTo, filerTo);
+             }
+ 
+             MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto);
+             MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer) agentMgr.send(destHost.getId(), command);
+             if (answer == null) {
+                 s_logger.error("Migration with storage of vm " + vm + " failed.");
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost);
+             } else if (!answer.getResult()) {
+                 s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails());
+                 throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost +
+                         ". " + answer.getDetails());
+             } else {
+                 // Update the volume details after migration.
+                 updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos());
+             }
+ 
+             return answer;
+         } catch (OperationTimedoutException e) {
+             s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e);
+             throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId());
+         }
+     }
+ 
+     private void updateVolumePathsAfterMigration(Map<VolumeInfo, DataStore> volumeToPool, List<VolumeTO> volumeTos) {
+         for (Map.Entry<VolumeInfo, DataStore> entry : volumeToPool.entrySet()) {
+             boolean updated = false;
+             VolumeInfo volume = entry.getKey();
+             StoragePool pool = (StoragePool)entry.getValue();
+             for (VolumeTO volumeTo : volumeTos) {
+                 if (volume.getId() == volumeTo.getId()) {
+                     VolumeVO volumeVO = volDao.findById(volume.getId());
+                     Long oldPoolId = volumeVO.getPoolId();
+                     volumeVO.setPath(volumeTo.getPath());
+                     volumeVO.setFolder(pool.getPath());
+                     volumeVO.setPodId(pool.getPodId());
+                     volumeVO.setPoolId(pool.getId());
+                     volumeVO.setLastPoolId(oldPoolId);
+                     volDao.update(volume.getId(), volumeVO);
+                     updated = true;
+                     break;
+                 }
+             }
+ 
+             if (!updated) {
+                 s_logger.error("Volume path wasn't updated for volume " + volume + " after it was migrated.");
+             }
+         }
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/30479293/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --cc plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
index 1865068,0000000..c0675e7
mode 100644,000000..100644
--- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
+++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
@@@ -1,393 -1,0 +1,392 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.cloudstack.storage.datastore.driver;
 +
 +import java.util.Date;
 +import java.util.List;
 +import java.util.Set;
 +
 +import javax.inject.Inject;
 +
++import org.apache.log4j.Logger;
++
 +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
 +import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 +import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
 +import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
- import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
 +import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 +import org.apache.cloudstack.framework.async.AsyncRpcConext;
 +import org.apache.cloudstack.storage.command.CommandResult;
 +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
 +import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
 +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
 +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
 +import org.apache.cloudstack.storage.image.ImageStoreDriver;
 +import org.apache.cloudstack.storage.image.store.ImageStoreImpl;
 +import org.apache.cloudstack.storage.image.store.TemplateObject;
 +import org.apache.cloudstack.storage.snapshot.SnapshotObject;
- import org.apache.log4j.Logger;
 +
 +import com.cloud.agent.AgentManager;
 +import com.cloud.agent.api.Answer;
 +import com.cloud.agent.api.storage.DeleteTemplateCommand;
 +import com.cloud.agent.api.storage.DeleteVolumeCommand;
 +import com.cloud.agent.api.storage.DownloadAnswer;
 +import com.cloud.agent.api.to.DataStoreTO;
 +import com.cloud.agent.api.to.NfsTO;
 +import com.cloud.event.EventTypes;
 +import com.cloud.event.UsageEventUtils;
 +import com.cloud.host.dao.HostDao;
 +import com.cloud.storage.DataStoreRole;
- import com.cloud.storage.RegisterVolumePayload;
- import com.cloud.storage.Storage.ImageFormat;
 +import com.cloud.storage.SnapshotVO;
++import com.cloud.storage.Storage.ImageFormat;
 +import com.cloud.storage.VMTemplateStorageResourceAssoc;
 +import com.cloud.storage.VMTemplateVO;
 +import com.cloud.storage.VMTemplateZoneVO;
 +import com.cloud.storage.VolumeVO;
 +import com.cloud.storage.dao.SnapshotDao;
 +import com.cloud.storage.dao.VMTemplateDao;
 +import com.cloud.storage.dao.VMTemplateZoneDao;
 +import com.cloud.storage.dao.VolumeDao;
 +import com.cloud.storage.download.DownloadMonitor;
 +import com.cloud.storage.s3.S3Manager;
 +import com.cloud.storage.secondary.SecondaryStorageVmManager;
 +import com.cloud.storage.snapshot.SnapshotManager;
 +import com.cloud.storage.swift.SwiftManager;
 +import com.cloud.user.Account;
 +import com.cloud.user.dao.AccountDao;
 +import com.cloud.utils.exception.CloudRuntimeException;
 +import com.cloud.vm.UserVmVO;
 +import com.cloud.vm.dao.UserVmDao;
 +
 +public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
 +    private static final Logger s_logger = Logger
 +            .getLogger(CloudStackImageStoreDriverImpl.class);
 +    @Inject
 +    VMTemplateZoneDao templateZoneDao;
 +    @Inject
 +    VMTemplateDao templateDao;
 +    @Inject DownloadMonitor _downloadMonitor;
 +    @Inject VolumeDao volumeDao;
 +    @Inject VolumeDataStoreDao _volumeStoreDao;
 +    @Inject HostDao hostDao;
 +    @Inject SnapshotDao snapshotDao;
 +    @Inject AgentManager agentMgr;
 +    @Inject SnapshotManager snapshotMgr;
 +	@Inject
 +    private SwiftManager _swiftMgr;
 +    @Inject
 +    private S3Manager _s3Mgr;
 +    @Inject AccountDao _accountDao;
 +    @Inject UserVmDao _userVmDao;
 +    @Inject
 +    SecondaryStorageVmManager _ssvmMgr;
 +    @Inject
 +    private AgentManager _agentMgr;
 +    @Inject TemplateDataStoreDao _templateStoreDao;
 +    @Inject EndPointSelector _epSelector;
 +    @Inject DataStoreManager _dataStoreMgr;
 +
 +
 +    @Override
 +    public String grantAccess(DataObject data, EndPoint ep) {
 +        // TODO Auto-generated method stub
 +        return null;
 +    }
 +
 +    @Override
 +    public DataTO getTO(DataObject data) {
 +        return null;
 +    }
 +
 +
 +    @Override
 +    public DataStoreTO getStoreTO(DataStore store) {
 +        ImageStoreImpl nfsStore = (ImageStoreImpl)store;
 +        NfsTO nfsTO = new NfsTO();
 +        nfsTO.setRole(store.getRole());
 +        nfsTO.setUrl(nfsStore.getUri());
 +        return nfsTO;
 +    }
 +
 +    @Override
 +    public boolean revokeAccess(DataObject data, EndPoint ep) {
 +        // TODO Auto-generated method stub
 +        return false;
 +    }
 +
 +    @Override
 +    public Set<DataObject> listObjects(DataStore store) {
 +        // TODO Auto-generated method stub
 +        return null;
 +    }
 +
 +    class CreateContext<T> extends AsyncRpcConext<T> {
 +        final DataObject data;
 +        public CreateContext(AsyncCompletionCallback<T> callback, DataObject data) {
 +            super(callback);
 +            this.data = data;
 +        }
 +    }
 +
 +
 +    @Override
 +    public void createAsync(DataObject data,
 +            AsyncCompletionCallback<CreateCmdResult> callback) {
 +    	CreateContext<CreateCmdResult> context = new CreateContext<CreateCmdResult>(callback, data);
 +        AsyncCallbackDispatcher<CloudStackImageStoreDriverImpl, DownloadAnswer> caller =
 +        		AsyncCallbackDispatcher.create(this);
 +        caller.setContext(context);
 +        caller.setCallback(caller.getTarget().createAsyncCallback(null, null));
 +
 +
 +        if (data.getType() == DataObjectType.TEMPLATE) {
 +            _downloadMonitor.downloadTemplateToStorage(data, caller);
 +        } else if (data.getType() == DataObjectType.VOLUME) {
 +            _downloadMonitor.downloadVolumeToStorage(data, caller);
 +        }
 +    }
 +
 +    protected Void createAsyncCallback(AsyncCallbackDispatcher<CloudStackImageStoreDriverImpl, DownloadAnswer> callback,
 +    		CreateContext<CreateCmdResult> context) {
 +    	DownloadAnswer answer = callback.getResult();
 +    	DataObject obj = context.data;
 +    	DataStore store = obj.getDataStore();
 +
 +    	TemplateDataStoreVO tmpltStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(),obj.getId());
 +        if (tmpltStoreVO != null) {
 +            TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate();
 +            updateBuilder.setDownloadPercent(answer.getDownloadPct());
 +            updateBuilder.setDownloadState(answer.getDownloadStatus());
 +            updateBuilder.setLastUpdated(new Date());
 +            updateBuilder.setErrorString(answer.getErrorString());
 +            updateBuilder.setJobId(answer.getJobId());
 +            updateBuilder.setLocalDownloadPath(answer.getDownloadPath());
 +            updateBuilder.setInstallPath(answer.getInstallPath());
 +            updateBuilder.setSize(answer.getTemplateSize());
 +            updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
 +            _templateStoreDao.update(tmpltStoreVO.getId(), updateBuilder);
 +            // update size in vm_template table
 +            VMTemplateVO tmlptUpdater = templateDao.createForUpdate();
 +            tmlptUpdater.setSize(answer.getTemplateSize());
 +            templateDao.update(obj.getId(), tmlptUpdater);
 +        }
 +
 +    	AsyncCompletionCallback<CreateCmdResult> caller = context.getParentCallback();
 +
 +    	if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR ||
 +    			answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED ||
 +    			answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) {
 +    		CreateCmdResult result = new CreateCmdResult(null, null);
-     		result.setSucess(false);
++            result.setSuccess(false);
 +    		result.setResult(answer.getErrorString());
 +    		caller.complete(result);
 +    	} else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
 +    		if (answer.getCheckSum() != null) {
 +    			VMTemplateVO templateDaoBuilder = templateDao.createForUpdate();
 +    			templateDaoBuilder.setChecksum(answer.getCheckSum());
 +    			templateDao.update(obj.getId(), templateDaoBuilder);
 +    		}
 +
 +
 +    		CreateCmdResult result = new CreateCmdResult(null, null);
 +    		caller.complete(result);
 +    	}
 +    	return null;
 +    }
 +
 +    private void deleteVolume(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
 +        VolumeVO vol = volumeDao.findById(data.getId());
 +        if (s_logger.isDebugEnabled()) {
 +            s_logger.debug("Expunging " + vol);
 +        }
 +
 +        // Find out if the volume is present on secondary storage
 +        VolumeDataStoreVO volumeStore = _volumeStoreDao.findByVolume(vol.getId());
 +        if (volumeStore != null) {
 +            if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
-                 DataStore store = this._dataStoreMgr.getDataStore(volumeStore.getDataStoreId(), DataStoreRole.Image);
++                DataStore store = _dataStoreMgr.getDataStore(volumeStore.getDataStoreId(), DataStoreRole.Image);
 +                EndPoint ep = _epSelector.select(store);
 +                DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(
 +                        store.getTO(), volumeStore.getVolumeId(), volumeStore.getInstallPath());
 +                Answer answer = ep.sendMessage(dtCommand);
 +                if (answer == null || !answer.getResult()) {
 +                    s_logger.debug("Failed to delete "
 +                            + volumeStore
 +                            + " due to "
 +                            + ((answer == null) ? "answer is null" : answer
 +                                    .getDetails()));
 +                    return;
 +                }
 +            } else if (volumeStore.getDownloadState() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_IN_PROGRESS) {
 +                s_logger.debug("Volume: " + vol.getName()
 +                        + " is currently being uploaded; cant' delete it.");
 +                throw new CloudRuntimeException(
 +                        "Please specify a volume that is not currently being uploaded.");
 +            }
 +            _volumeStoreDao.remove(volumeStore.getId());
 +            volumeDao.remove(vol.getId());
 +            CommandResult result = new CommandResult();
 +            callback.complete(result);
 +            return;
 +        }
 +    }
 +
 +    private void deleteTemplate(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
 +
 +        TemplateObject templateObj = (TemplateObject) data;
 +        VMTemplateVO template = templateObj.getImage();
 +        ImageStoreImpl store = (ImageStoreImpl) templateObj.getDataStore();
 +        long storeId = store.getId();
 +        Long sZoneId = store.getDataCenterId();
 +        long templateId = template.getId();
 +
 +        Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId());
 +        String eventType = "";
 +
 +        if (template.getFormat().equals(ImageFormat.ISO)) {
 +            eventType = EventTypes.EVENT_ISO_DELETE;
 +        } else {
 +            eventType = EventTypes.EVENT_TEMPLATE_DELETE;
 +        }
 +
 +        // TODO: need to understand why we need to mark destroyed in
 +        // template_store_ref table here instead of in callback.
 +        // Currently I did that in callback, so I removed previous code to mark template_host_ref
 +
 +        UsageEventUtils.publishUsageEvent(eventType, account.getId(), sZoneId, templateId, null, null, null);
 +
 +        List<UserVmVO> userVmUsingIso = _userVmDao.listByIsoId(templateId);
 +        // check if there is any VM using this ISO.
 +        if (userVmUsingIso == null || userVmUsingIso.isEmpty()) {
 +             // get installpath of this template on image store
 +            TemplateDataStoreVO tmplStore = _templateStoreDao.findByStoreTemplate(storeId, templateId);
 +            String installPath = tmplStore.getInstallPath();
 +            if (installPath != null) {
 +                DeleteTemplateCommand cmd = new DeleteTemplateCommand(store.getTO(), installPath, template.getId(), template.getAccountId());
 +                EndPoint ep = _epSelector.select(templateObj);
 +                Answer answer = ep.sendMessage(cmd);
 +
 +                if (answer == null || !answer.getResult()) {
 +                    s_logger.debug("Failed to deleted template at store: " + store.getName());
 +                    CommandResult result = new CommandResult();
-                     result.setSucess(false);
++                    result.setSuccess(false);
 +                    result.setResult("Delete template failed");
 +                    callback.complete(result);
 +
 +                } else {
 +                    s_logger.debug("Deleted template at: " + installPath);
 +                    CommandResult result = new CommandResult();
-                     result.setSucess(true);
++                    result.setSuccess(true);
 +                    callback.complete(result);
 +                }
 +
 +                List<VMTemplateZoneVO> templateZones = templateZoneDao.listByZoneTemplate(sZoneId, templateId);
 +                if (templateZones != null) {
 +                    for (VMTemplateZoneVO templateZone : templateZones) {
 +                        templateZoneDao.remove(templateZone.getId());
 +                    }
 +                }
 +             }
 +        }
 +
 +    }
 +
 +    private void deleteSnapshot(DataObject data, AsyncCompletionCallback<CommandResult> callback) {
 +        SnapshotObject snapshotObj = (SnapshotObject)data;
 +        DataStore secStore = snapshotObj.getDataStore();
 +        CommandResult result = new CommandResult();
 +     	SnapshotVO snapshot = snapshotObj.getSnapshotVO();
 +
 +    	if (snapshot == null) {
 +    		s_logger.debug("Destroying snapshot " + snapshotObj.getId() + " backup failed due to unable to find snapshot ");
 +    		result.setResult("Unable to find snapshot: " + snapshotObj.getId());
 +    		callback.complete(result);
 +    		return;
 +    	}
 +
 +    	try {
 +    		/*String secondaryStoragePoolUrl = secStore.getUri();
 +    		Long dcId = snapshot.getDataCenterId();
 +    		Long accountId = snapshot.getAccountId();
 +    		Long volumeId = snapshot.getVolumeId();
 +
 +    		String backupOfSnapshot = snapshotObj;
 +    		if (backupOfSnapshot == null) {
 +    			callback.complete(result);
 +    			return;
 +    		}
 +
 +    		DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand(
 +    				secStore.getTO(), secondaryStoragePoolUrl, dcId, accountId, volumeId,
 +    				backupOfSnapshot, false);
 +    		EndPoint ep = _epSelector.select(secStore);
 +    		Answer answer = ep.sendMessage(cmd);
 +
 +    		if ((answer != null) && answer.getResult()) {
 +    			snapshot.setBackupSnapshotId(null);
 +    			snapshotDao.update(snapshotObj.getId(), snapshot);
 +    		} else if (answer != null) {
 +    			result.setResult(answer.getDetails());
 +    		}*/
 +    	} catch (Exception e) {
 +    		s_logger.debug("failed to delete snapshot: " + snapshotObj.getId() + ": " + e.toString());
 +    		result.setResult(e.toString());
 +    	}
 +    	callback.complete(result);
 +    }
 +
 +    @Override
 +    public void deleteAsync(DataObject data,
 +            AsyncCompletionCallback<CommandResult> callback) {
 +        if (data.getType() == DataObjectType.VOLUME) {
 +            deleteVolume(data, callback);
 +        } else if (data.getType() == DataObjectType.TEMPLATE) {
 +            deleteTemplate(data, callback);
 +        } else if (data.getType() == DataObjectType.SNAPSHOT) {
 +        	deleteSnapshot(data, callback);
 +        }
 +    }
 +
 +    @Override
 +    public void copyAsync(DataObject srcdata, DataObject destData,
 +            AsyncCompletionCallback<CopyCommandResult> callback) {
 +        // TODO Auto-generated method stub
 +
 +    }
 +
 +    @Override
 +    public boolean canCopy(DataObject srcData, DataObject destData) {
 +        // TODO Auto-generated method stub
 +        return false;
 +    }
 +
 +	@Override
 +	public void resize(DataObject data,
 +			AsyncCompletionCallback<CreateCmdResult> callback) {
 +		// TODO Auto-generated method stub
 +
 +	}
 +
 +}


Mime
View raw message