Updated Branches:
  refs/heads/object_store 98af42405 -> 3ec52807f

CLOUDSTACK-2593: fix migrate volume between pools through secondary storage


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

Branch: refs/heads/object_store
Commit: 3ec52807f1403129d353e8489636b60beeaf80db
Parents: 98af424
Author: Edison Su <[email protected]>
Authored: Thu May 23 18:25:25 2013 -0700
Committer: Edison Su <[email protected]>
Committed: Thu May 23 18:26:16 2013 -0700

----------------------------------------------------------------------
 api/src/com/cloud/storage/VolumeApiService.java    |    2 +-
 .../api/command/user/volume/MigrateVolumeCmd.java  |   21 ++--
 engine/schema/src/com/cloud/storage/VolumeVO.java  |    2 +-
 .../allocator/StorageCacheRandomAllocator.java     |   10 ++-
 .../storage/motion/AncientDataMotionStrategy.java  |   85 ++++++++++++---
 .../cloudstack/storage/volume/VolumeObject.java    |    3 +
 .../storage/volume/VolumeServiceImpl.java          |    2 +-
 .../xen/resource/XenServerStorageProcessor.java    |    3 +-
 .../src/com/cloud/storage/VolumeManagerImpl.java   |    6 +-
 9 files changed, 98 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/api/src/com/cloud/storage/VolumeApiService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/VolumeApiService.java 
b/api/src/com/cloud/storage/VolumeApiService.java
index aa52cf7..31b5c95 100644
--- a/api/src/com/cloud/storage/VolumeApiService.java
+++ b/api/src/com/cloud/storage/VolumeApiService.java
@@ -58,7 +58,7 @@ public interface VolumeApiService {
      */
     Volume resizeVolume(ResizeVolumeCmd cmd) throws 
ResourceAllocationException;
 
-    Volume migrateVolume(MigrateVolumeCmd cmd) throws 
ConcurrentOperationException;
+    Volume migrateVolume(MigrateVolumeCmd cmd);
 
     /**
      * Uploads the volume to secondary storage

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
----------------------------------------------------------------------
diff --git 
a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java 
b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
index ce40f0d..40e6123 100644
--- 
a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
+++ 
b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java
@@ -98,18 +98,15 @@ public class MigrateVolumeCmd extends BaseAsyncCmd {
 
     @Override
     public void execute(){
-        Volume result;
-        try {
-            result = _volumeService.migrateVolume(this);
-             if (result != null) {
-                 VolumeResponse response = 
_responseGenerator.createVolumeResponse(result);
-                 response.setResponseName(getCommandName());
-                 this.setResponseObject(response);
-             }
-        } catch (ConcurrentOperationException e) {
-            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed 
to migrate volume: ");
-        }
-
+       Volume result;
+       result = _volumeService.migrateVolume(this);
+       if (result != null) {
+               VolumeResponse response = 
_responseGenerator.createVolumeResponse(result);
+               response.setResponseName(getCommandName());
+               this.setResponseObject(response);
+       } else {
+               throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, 
"Failed to migrate volume");
+       }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/engine/schema/src/com/cloud/storage/VolumeVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java 
b/engine/schema/src/com/cloud/storage/VolumeVO.java
index a230991..d939910 100755
--- a/engine/schema/src/com/cloud/storage/VolumeVO.java
+++ b/engine/schema/src/com/cloud/storage/VolumeVO.java
@@ -154,7 +154,7 @@ public class VolumeVO implements Volume {
         this.uuid = UUID.randomUUID().toString();
     }
 
-    public VolumeVO(String name, long dcId, long podId, long accountId, long 
domainId, Long instanceId, String folder, String path, long size, Volume.Type 
vType) {
+    public VolumeVO(String name, Long dcId, Long podId, long accountId, long 
domainId, Long instanceId, String folder, String path, long size, Volume.Type 
vType) {
         this.name = name;
         this.accountId = accountId;
         this.domainId = domainId;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java
 
b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java
index 462f13f..f8232b8 100644
--- 
a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java
+++ 
b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/allocator/StorageCacheRandomAllocator.java
@@ -25,26 +25,30 @@ import javax.inject.Inject;
 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.Scope;
+import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import com.cloud.storage.ScopeType;
-import com.cloud.utils.exception.CloudRuntimeException;
 
 import edu.emory.mathcs.backport.java.util.Collections;
 
 @Component
 public class StorageCacheRandomAllocator implements StorageCacheAllocator {
+       private static final Logger s_logger = Logger
+            .getLogger(StorageCacheRandomAllocator.class);
     @Inject
     DataStoreManager dataStoreMgr;
     @Override
     public DataStore getCacheStore(Scope scope) {
         if (scope.getScopeType() != ScopeType.ZONE) {
-            throw new CloudRuntimeException("Can only support zone wide cache 
storage");
+            s_logger.debug("Can only support zone wide cache storage");
+            return null;
         }
        
         List<DataStore> cacheStores = dataStoreMgr.getImageCacheStores(scope);
         if (cacheStores.size() <= 0) {
-            throw new CloudRuntimeException("Can't find cache storage in zone: 
" + scope.getScopeId());
+            s_logger.debug("Can't find cache storage in zone: " + 
scope.getScopeId());
+            return null;
         }
         
         Collections.shuffle(cacheStores);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
 
b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 1e99e9e..65beb40 100644
--- 
a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -31,6 +31,7 @@ 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.DataStoreManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
+import 
org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
 import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
 import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
@@ -39,11 +40,13 @@ import 
org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.command.CopyCommand;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
+import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.to.DataObjectType;
@@ -57,6 +60,7 @@ import com.cloud.exception.StorageUnavailableException;
 import com.cloud.host.Host;
 import com.cloud.host.dao.HostDao;
 import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.ImageStore;
 import com.cloud.storage.StorageManager;
 import com.cloud.storage.StoragePool;
 import com.cloud.storage.VolumeManager;
@@ -136,6 +140,20 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
         }
         return true;
     }
+    
+    private Scope getZoneScope(Scope destScope) {
+       ZoneScope zoneScope = null;
+        if (destScope instanceof ClusterScope) {
+            ClusterScope clusterScope = (ClusterScope) destScope;
+            zoneScope = new ZoneScope(clusterScope.getZoneId());
+        } else if (destScope instanceof HostScope) {
+            HostScope hostScope = (HostScope) destScope;
+            zoneScope = new ZoneScope(hostScope.getZoneId());
+        } else {
+               zoneScope = (ZoneScope)destScope;
+        }
+        return zoneScope;
+    }
 
     protected Answer copyObject(DataObject srcData, DataObject destData) {
         String value = 
configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
@@ -145,14 +163,7 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
         try {
             if (needCacheStorage(srcData, destData)) {
                 // need to copy it to image cache store
-                Scope destScope = destData.getDataStore().getScope();
-                if (destScope instanceof ClusterScope) {
-                    ClusterScope clusterScope = (ClusterScope) destScope;
-                    destScope = new ZoneScope(clusterScope.getZoneId());
-                } else if (destScope instanceof HostScope) {
-                    HostScope hostScope = (HostScope) destScope;
-                    destScope = new ZoneScope(hostScope.getZoneId());
-                }
+                Scope destScope = 
getZoneScope(destData.getDataStore().getScope());
                 cacheData = cacheMgr.createCacheObject(srcData, destScope);
                 CopyCommand cmd = new CopyCommand(cacheData.getTO(), 
destData.getTO(), _primaryStorageDownloadWait);
                 EndPoint ep = selector.select(cacheData, destData);
@@ -248,11 +259,57 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
         int _copyvolumewait = NumbersUtil.parseInt(value,
                 Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
 
-        DataObject cacheData = cacheMgr.createCacheObject(srcData, 
destData.getDataStore().getScope());
-        CopyCommand cmd = new CopyCommand(cacheData.getTO(), destData.getTO(), 
_copyvolumewait);
-        EndPoint ep = selector.select(cacheData, destData);
-        Answer answer = ep.sendMessage(cmd);
-        return answer;
+        Scope destScope = getZoneScope(destData.getDataStore().getScope());
+        DataStore cacheStore = cacheMgr.getCacheStorage(destScope);
+        if (cacheStore == null) {
+               //need to find a nfs image store, assuming that can't copy 
volume directly to s3
+               ImageStoreEntity imageStore = 
(ImageStoreEntity)this.dataStoreMgr.getImageStore(destScope.getScopeId());
+               if (!imageStore.getProtocol().equalsIgnoreCase("nfs")) {
+                       s_logger.debug("can't find a nfs image store");
+                       return null;
+               }
+
+               DataObject objOnImageStore = imageStore.create(srcData);
+               objOnImageStore.processEvent(Event.CreateOnlyRequested);
+
+               Answer answer = this.copyObject(srcData, objOnImageStore);
+               if (answer == null || !answer.getResult()) {
+                       if (answer != null) {
+                               s_logger.debug("copy to image store failed: " + 
answer.getDetails());
+                       }
+                       objOnImageStore.processEvent(Event.OperationFailed);
+                       imageStore.delete(objOnImageStore);
+                       return answer;
+               }
+
+               objOnImageStore.processEvent(Event.OperationSuccessed, answer);
+
+               objOnImageStore.processEvent(Event.CopyingRequested);
+
+               CopyCommand cmd = new CopyCommand(objOnImageStore.getTO(), 
destData.getTO(), _copyvolumewait);
+               EndPoint ep = selector.select(objOnImageStore, destData);
+               answer = ep.sendMessage(cmd);
+               
+               if (answer == null || !answer.getResult()) {
+                       if (answer != null) {
+                               s_logger.debug("copy to primary store failed: " 
+ answer.getDetails());
+                       }
+                       objOnImageStore.processEvent(Event.OperationFailed);
+                       imageStore.delete(objOnImageStore);
+                       return answer;
+               }
+               
+               objOnImageStore.processEvent(Event.OperationSuccessed);
+               imageStore.delete(objOnImageStore);
+               return answer;
+        } else {
+               DataObject cacheData = cacheMgr.createCacheObject(srcData, 
destScope);
+               CopyCommand cmd = new CopyCommand(cacheData.getTO(), 
destData.getTO(), _copyvolumewait);
+               EndPoint ep = selector.select(cacheData, destData);
+               Answer answer = ep.sendMessage(cmd);
+               return answer;
+        }
+
     }
 
     @Override
@@ -273,7 +330,7 @@ public class AncientDataMotionStrategy implements 
DataMotionStrategy {
                answer = cloneVolume(srcData, destData);
             } else if (destData.getType() == DataObjectType.VOLUME
                     && srcData.getType() == DataObjectType.VOLUME && 
srcData.getDataStore().getRole() == DataStoreRole.Primary && 
destData.getDataStore().getRole() == DataStoreRole.Primary) {
-               answer = copyVolumeBetweenPools(srcData, destData);
+               answer = copyVolumeBetweenPools(srcData, destData);
             } else if (srcData.getType() == DataObjectType.SNAPSHOT &&
                        destData.getType() == DataObjectType.SNAPSHOT) {
                answer = copySnapshot(srcData, destData);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
index da5e80b..c5ba6db 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
@@ -193,6 +193,9 @@ public class VolumeObject implements VolumeInfo {
             }
             if (this.dataStore.getRole() == DataStoreRole.Image) {
                 objectInStoreMgr.update(this, event);
+                if (this.volumeVO.getState() == Volume.State.Migrating) {
+                       return;
+                }
                 if (event == 
ObjectInDataStoreStateMachine.Event.CreateRequested) {
                     volEvent = Volume.Event.UploadRequested;
                 } else if (event == 
ObjectInDataStoreStateMachine.Event.OperationSuccessed) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index ba4693c..a8d7103 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -615,7 +615,7 @@ public class VolumeServiceImpl implements VolumeService {
             .setContext(context);
             motionSrv.copyAsync(srcVolume, destVolume, caller);
         } catch (Exception e) {
-            s_logger.debug("Failed to copy volume", e);
+            s_logger.debug("Failed to copy volume" + e);
             res.setResult(e.toString());
             future.complete(res);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
 
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
index 29ffa4e..399e234 100644
--- 
a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
+++ 
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
@@ -957,7 +957,8 @@ public class XenServerStorageProcessor implements 
StorageProcessor {
             try {
                 SR primaryStoragePool = 
hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
                 String srUuid = primaryStoragePool.getUuid(conn);
-                String volumePath = nfsStore.getUrl() + ":" + 
srcVolume.getPath();
+                URI uri = new URI(nfsStore.getUrl());
+                String volumePath = uri.getHost() + ":" + uri.getPath() + 
File.separator + srcVolume.getPath();
                 String uuid = copy_vhd_from_secondarystorage(conn, volumePath, 
srUuid, wait );
                 VolumeObjectTO newVol = new VolumeObjectTO();
                 newVol.setPath(uuid);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3ec52807/server/src/com/cloud/storage/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java 
b/server/src/com/cloud/storage/VolumeManagerImpl.java
index e98939d..17d5ee8 100644
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@ -719,7 +719,7 @@ public class VolumeManagerImpl extends ManagerBase 
implements VolumeManager {
         Transaction txn = Transaction.currentTxn();
         txn.start();
 
-        VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1,
+        VolumeVO volume = new VolumeVO(volumeName, zoneId, -1L, -1L, -1,
                 new Long(-1), null, null, 0, Volume.Type.DATADISK);
         Account owner = (caller.getId() == ownerId) ? caller : _accountMgr
                           .getActiveAccountById(ownerId);
@@ -965,7 +965,7 @@ public class VolumeManagerImpl extends ManagerBase 
implements VolumeManager {
         Transaction txn = Transaction.currentTxn();
         txn.start();
 
-        VolumeVO volume = new VolumeVO(userSpecifiedName, -1, -1, -1, -1,
+        VolumeVO volume = new VolumeVO(userSpecifiedName, -1L, -1L, -1, -1,
                 new Long(-1), null, null, 0, Volume.Type.DATADISK);
         volume.setPoolId(null);
         volume.setDataCenterId(zoneId);
@@ -2095,7 +2095,7 @@ public class VolumeManagerImpl extends ManagerBase 
implements VolumeManager {
         try {
             VolumeApiResult result = future.get();
             if (result.isFailed()) {
-                s_logger.debug("migrate volume failed:" + result.getResult());
+                s_logger.error("migrate volume failed:" + result.getResult());
                 return null;
             }
             return result.getVolume();

Reply via email to