You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/02/21 20:23:49 UTC
[23/28] git commit: refs/heads/master - add copy volume and create
volume from snapshot
add copy volume and create volume from snapshot
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/020be66f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/020be66f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/020be66f
Branch: refs/heads/master
Commit: 020be66f9d8025198e9f6dc0d15d54349eeb61a5
Parents: 621a779
Author: Edison Su <su...@gmail.com>
Authored: Fri Feb 8 18:22:00 2013 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Thu Feb 21 11:22:49 2013 -0800
----------------------------------------------------------------------
api/src/com/cloud/storage/VolumeApiService.java | 3 +-
.../api/command/user/volume/MigrateVolumeCmd.java | 2 +-
.../storage/motion/AncientDataMotionStrategy.java | 58 ++++-
.../storage/volume/VolumeServiceImpl.java | 97 +++++++-
server/src/com/cloud/storage/VolumeManager.java | 8 +-
.../src/com/cloud/storage/VolumeManagerImpl.java | 212 +++------------
.../cloud/storage/snapshot/SnapshotManager.java | 3 +-
.../storage/snapshot/SnapshotManagerImpl.java | 2 +-
.../com/cloud/vm/VirtualMachineManagerImpl.java | 2 +-
9 files changed, 205 insertions(+), 182 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/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 92880f4..8517988 100644
--- a/api/src/com/cloud/storage/VolumeApiService.java
+++ b/api/src/com/cloud/storage/VolumeApiService.java
@@ -21,6 +21,7 @@ package com.cloud.storage;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
@@ -61,7 +62,7 @@ public interface VolumeApiService {
*/
Volume resizeVolume(ResizeVolumeCmd cmd);
- Volume migrateVolume(Long volumeId, Long storagePoolId) throws ConcurrentOperationException;
+ Volume migrateVolume(MigrateVolumeCmd cmd) throws ConcurrentOperationException;
/**
* Uploads the volume to secondary storage
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/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 8c09f8f..287241a 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
@@ -92,7 +92,7 @@ public class MigrateVolumeCmd extends BaseAsyncCmd {
public void execute(){
Volume result;
try {
- result = _volumeService.migrateVolume(getVolumeId(), getStoragePoolId());
+ result = _volumeService.migrateVolume(this);
if (result != null) {
VolumeResponse response = _responseGenerator.createVolumeResponse(result);
response.setResponseName(getCommandName());
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 70f65c7..ed3ca6a 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -329,6 +329,59 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
return errMsg;
}
+
+ protected String copyVolumeBetweenPools(DataObject srcData, DataObject destData) {
+ VolumeInfo volume = (VolumeInfo)srcData;
+ VolumeInfo destVolume = (VolumeInfo)destData;
+ String secondaryStorageURL = this.templateMgr.getSecondaryStorageURL(volume
+ .getDataCenterId());
+ StoragePool srcPool = (StoragePool)this.dataStoreMgr.getDataStore(volume
+ .getPoolId(), DataStoreRole.Primary);
+
+ StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destVolume.getPoolId(), DataStoreRole.Primary);
+
+ String value = this.configDao.getValue(Config.CopyVolumeWait.toString());
+ int _copyvolumewait = NumbersUtil.parseInt(value,
+ Integer.parseInt(Config.CopyVolumeWait.getDefaultValue()));
+ CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(),
+ volume.getPath(), srcPool, secondaryStorageURL, true,
+ _copyvolumewait);
+ CopyVolumeAnswer cvAnswer;
+ try {
+ cvAnswer = (CopyVolumeAnswer) this.storagMgr.sendToPool(srcPool, cvCmd);
+ } catch (StorageUnavailableException e1) {
+ throw new CloudRuntimeException(
+ "Failed to copy the volume from the source primary storage pool to secondary storage.",
+ e1);
+ }
+
+ if (cvAnswer == null || !cvAnswer.getResult()) {
+ throw new CloudRuntimeException(
+ "Failed to copy the volume from the source primary storage pool to secondary storage.");
+ }
+
+ String secondaryStorageVolumePath = cvAnswer.getVolumePath();
+
+ cvCmd = new CopyVolumeCommand(volume.getId(),
+ secondaryStorageVolumePath, destPool,
+ secondaryStorageURL, false, _copyvolumewait);
+ try {
+ cvAnswer = (CopyVolumeAnswer) this.storagMgr.sendToPool(destPool, cvCmd);
+ } catch (StorageUnavailableException e1) {
+ throw new CloudRuntimeException(
+ "Failed to copy the volume from secondary storage to the destination primary storage pool.");
+ }
+
+ if (cvAnswer == null || !cvAnswer.getResult()) {
+ throw new CloudRuntimeException(
+ "Failed to copy the volume from secondary storage to the destination primary storage pool.");
+ }
+
+ VolumeVO destVol = this.volDao.findById(destVolume.getId());
+ destVol.setPath(cvAnswer.getVolumePath());
+ this.volDao.update(destVol.getId(), destVol);
+ return null;
+ }
@Override
public Void copyAsync(DataObject srcData, DataObject destData,
@@ -336,7 +389,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
String errMsg = null;
try {
if (destData.getType() == DataObjectType.VOLUME
- && srcData.getType() == DataObjectType.VOLUME) {
+ && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Image) {
errMsg = copyVolumeFromImage(srcData, destData);
} else if (destData.getType() == DataObjectType.TEMPLATE
&& srcData.getType() == DataObjectType.TEMPLATE) {
@@ -353,6 +406,9 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
} else if (srcData.getType() == DataObjectType.TEMPLATE
&& destData.getType() == DataObjectType.VOLUME) {
errMsg = cloneVolume(srcData, destData);
+ } else if (destData.getType() == DataObjectType.VOLUME
+ && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
+ errMsg = copyVolumeBetweenPools(srcData, destData);
}
} catch (Exception e) {
s_logger.debug("copy failed", e);
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/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 891ad12..ef99a49 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
@@ -45,12 +45,14 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.utils.db.DB;
+import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
@@ -420,14 +422,105 @@ public class VolumeServiceImpl implements VolumeService {
@Override
public AsyncCallFuture<VolumeApiResult> createVolumeFromSnapshot(
VolumeInfo volume, DataStore store, SnapshotInfo snapshot) {
- // TODO Auto-generated method stub
+ AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
+ VolumeApiResult result = new VolumeApiResult(volume);
return null;
}
+
+ protected VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePool pool) {
+ Long lastPoolId = volume.getPoolId();
+ VolumeVO newVol = new VolumeVO(volume);
+ newVol.setPoolId(pool.getId());
+ newVol.setFolder(pool.getPath());
+ newVol.setPodId(pool.getPodId());
+ newVol.setPoolId(pool.getId());
+ newVol.setLastPoolId(lastPoolId);
+ newVol.setPodId(pool.getPodId());
+ return this.volDao.persist(newVol);
+ }
+
+ private class CopyVolumeContext<T> extends AsyncRpcConext<T> {
+ final VolumeInfo srcVolume;
+ final VolumeInfo destVolume;
+ final DataStore destStore;
+ final AsyncCallFuture<VolumeApiResult> future;
+ /**
+ * @param callback
+ */
+ public CopyVolumeContext(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> copyVolume(VolumeInfo srcVolume,
DataStore destStore) {
- // TODO Auto-generated method stub
+ AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>();
+ VolumeApiResult res = new VolumeApiResult(srcVolume);
+ try {
+ if (!this.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);
+
+ 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);
+ } catch (Exception e) {
+ s_logger.debug("Failed to copy volume", e);
+ res.setResult(e.toString());
+ future.complete(res);
+ }
+ return future;
+ }
+
+ protected Void copyVolumeCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) {
+ VolumeInfo srcVolume = context.srcVolume;
+ VolumeInfo destVolume = context.destVolume;
+ CopyCommandResult result = callback.getResult();
+ AsyncCallFuture<VolumeApiResult> future = context.future;
+ VolumeApiResult res = new VolumeApiResult(destVolume);
+ try {
+ if (result.isFailed()) {
+ res.setResult(result.getResult());
+ destVolume.processEvent(Event.OperationFailed);
+ srcVolume.processEvent(Event.OperationFailed);
+ AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(destVolume);
+ destroyFuture.get();
+ future.complete(res);
+ return null;
+ }
+ srcVolume.processEvent(Event.OperationSuccessed);
+ destVolume.processEvent(Event.OperationSuccessed);
+ AsyncCallFuture<VolumeApiResult> destroyFuture = this.expungeVolumeAsync(srcVolume);
+ destroyFuture.get();
+ future.complete(res);
+ return null;
+ } catch (Exception e) {
+ s_logger.debug("Failed to process copy volume callback",e);
+ res.setResult(e.toString());
+ future.complete(res);
+ }
+
return null;
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/server/src/com/cloud/storage/VolumeManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java
index 41434f4..ebb9e54 100644
--- a/server/src/com/cloud/storage/VolumeManager.java
+++ b/server/src/com/cloud/storage/VolumeManager.java
@@ -21,6 +21,7 @@ package com.cloud.storage;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
@@ -76,12 +77,11 @@ public interface VolumeManager extends VolumeApiService {
void cleanupVolumes(long vmId) throws ConcurrentOperationException;
- Volume migrateVolume(Long volumeId, Long storagePoolId)
- throws ConcurrentOperationException;
+ Volume migrateVolume(MigrateVolumeCmd cmd);
- boolean StorageMigration(
+ boolean storageMigration(
VirtualMachineProfile<? extends VirtualMachine> vm,
- StoragePool destPool) throws ConcurrentOperationException;
+ StoragePool destPool);
void prepareForMigration(
VirtualMachineProfile<? extends VirtualMachine> vm,
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/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 8c0e142..573b8e9 100644
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@ -39,6 +39,7 @@ import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
+import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@@ -351,11 +352,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
throw new CloudRuntimeException(
"Failed to find a storage pool with enough capacity to move the volume to.");
}
-
- List<Volume> vols = new ArrayList<Volume>();
- vols.add(volume);
- migrateVolumes(vols, destPool);
- return this.volFactory.getVolume(volume.getId());
+
+ Volume newVol = migrateVolume(volume, destPool);
+ return this.volFactory.getVolume(newVol.getId());
}
/*
@@ -1012,10 +1011,15 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
@DB
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_RESIZE, eventDescription = "resizing volume", async = true)
public VolumeVO resizeVolume(ResizeVolumeCmd cmd) {
- VolumeVO volume = _volsDao.findById(cmd.getEntityId());
Long newSize = null;
boolean shrinkOk = cmd.getShrinkOk();
boolean success = false;
+
+ VolumeVO volume = _volsDao.findById(cmd.getEntityId());
+ if (volume == null) {
+ throw new InvalidParameterValueException("No such volume");
+ }
+
DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume
.getDiskOfferingId());
DiskOfferingVO newDiskOffering = null;
@@ -1039,9 +1043,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
"Cloudstack currently only supports volumes marked as KVM or XenServer hypervisor for resize");
}
- if (volume == null) {
- throw new InvalidParameterValueException("No such volume");
- }
if (volume.getState() != Volume.State.Ready) {
throw new InvalidParameterValueException(
@@ -1995,8 +1996,10 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
@DB
@Override
- public Volume migrateVolume(Long volumeId, Long storagePoolId)
- throws ConcurrentOperationException {
+ public Volume migrateVolume(MigrateVolumeCmd cmd) {
+ Long volumeId = cmd.getVolumeId();
+ Long storagePoolId = cmd.getStoragePoolId();
+
VolumeVO vol = _volsDao.findById(volumeId);
if (vol == null) {
throw new InvalidParameterValueException(
@@ -2025,171 +2028,36 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
"Migration of volume from local storage pool is not supported");
}
- List<Volume> vols = new ArrayList<Volume>();
- vols.add(vol);
-
- migrateVolumes(vols, destPool);
- return vol;
+ Volume newVol = migrateVolume(vol, destPool);
+ return newVol;
}
+
+
@DB
- public boolean migrateVolumes(List<Volume> volumes, StoragePool destPool)
- throws ConcurrentOperationException {
- Transaction txn = Transaction.currentTxn();
- txn.start();
-
- boolean transitResult = false;
- long checkPointTaskId = -1;
- try {
- List<Long> volIds = new ArrayList<Long>();
- for (Volume volume : volumes) {
- if (!_snapshotMgr.canOperateOnVolume((VolumeVO) volume)) {
- throw new CloudRuntimeException(
- "There are snapshots creating on this volume, can not move this volume");
- }
-
- try {
- if (!stateTransitTo(volume, Volume.Event.MigrationRequested)) {
- throw new ConcurrentOperationException(
- "Failed to transit volume state");
- }
- } catch (NoTransitionException e) {
- s_logger.debug("Failed to set state into migrate: "
- + e.toString());
- throw new CloudRuntimeException(
- "Failed to set state into migrate: " + e.toString());
- }
- volIds.add(volume.getId());
- }
-
- transitResult = true;
- } finally {
- if (!transitResult) {
- txn.rollback();
- } else {
- txn.commit();
- }
- }
-
- // At this stage, nobody can modify volumes. Send the copyvolume command
- List<Pair<StoragePool, DestroyCommand>> destroyCmds = new ArrayList<Pair<StoragePool, DestroyCommand>>();
- List<CopyVolumeAnswer> answers = new ArrayList<CopyVolumeAnswer>();
+ protected Volume migrateVolume(Volume volume, StoragePool destPool) {
+ VolumeInfo vol = this.volFactory.getVolume(volume.getId());
+ AsyncCallFuture<VolumeApiResult> future = this.volService.copyVolume(vol, (DataStore)destPool);
try {
- for (Volume volume : volumes) {
- String secondaryStorageURL = this._tmpltMgr.getSecondaryStorageURL(volume
- .getDataCenterId());
- StoragePool srcPool = (StoragePool)this.dataStoreMgr.getDataStore(volume
- .getPoolId(), DataStoreRole.Primary);
- CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(),
- volume.getPath(), srcPool, secondaryStorageURL, true,
- _copyvolumewait);
- CopyVolumeAnswer cvAnswer;
- try {
- cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(srcPool, cvCmd);
- } catch (StorageUnavailableException e1) {
- throw new CloudRuntimeException(
- "Failed to copy the volume from the source primary storage pool to secondary storage.",
- e1);
- }
-
- if (cvAnswer == null || !cvAnswer.getResult()) {
- throw new CloudRuntimeException(
- "Failed to copy the volume from the source primary storage pool to secondary storage.");
- }
-
- String secondaryStorageVolumePath = cvAnswer.getVolumePath();
-
- // Copy the volume from secondary storage to the destination
- // storage
- // pool
- cvCmd = new CopyVolumeCommand(volume.getId(),
- secondaryStorageVolumePath, destPool,
- secondaryStorageURL, false, _copyvolumewait);
- try {
- cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool, cvCmd);
- } catch (StorageUnavailableException e1) {
- throw new CloudRuntimeException(
- "Failed to copy the volume from secondary storage to the destination primary storage pool.");
- }
-
- if (cvAnswer == null || !cvAnswer.getResult()) {
- throw new CloudRuntimeException(
- "Failed to copy the volume from secondary storage to the destination primary storage pool.");
- }
-
- answers.add(cvAnswer);
- destroyCmds.add(new Pair<StoragePool, DestroyCommand>(
- srcPool, new DestroyCommand(srcPool, volume, null)));
- }
- } finally {
- if (answers.size() != volumes.size()) {
- // this means one of copying volume failed
- for (Volume volume : volumes) {
- try {
- stateTransitTo(volume, Volume.Event.OperationFailed);
- } catch (NoTransitionException e) {
- s_logger.debug("Failed to change volume state: "
- + e.toString());
- }
- }
- } else {
- // Need a transaction, make sure all the volumes get migrated to
- // new storage pool
- txn = Transaction.currentTxn();
- txn.start();
-
- transitResult = false;
- try {
- for (int i = 0; i < volumes.size(); i++) {
- CopyVolumeAnswer answer = answers.get(i);
- VolumeVO volume = (VolumeVO) volumes.get(i);
- Long oldPoolId = volume.getPoolId();
- volume.setPath(answer.getVolumePath());
- volume.setFolder(destPool.getPath());
- volume.setPodId(destPool.getPodId());
- volume.setPoolId(destPool.getId());
- volume.setLastPoolId(oldPoolId);
- volume.setPodId(destPool.getPodId());
- try {
- stateTransitTo(volume,
- Volume.Event.OperationSucceeded);
- } catch (NoTransitionException e) {
- s_logger.debug("Failed to change volume state: "
- + e.toString());
- throw new CloudRuntimeException(
- "Failed to change volume state: "
- + e.toString());
- }
- }
- transitResult = true;
- } finally {
- if (!transitResult) {
- txn.rollback();
- } else {
- txn.commit();
- }
- }
-
- }
- }
-
- // all the volumes get migrated to new storage pool, need to delete the
- // copy on old storage pool
- for (Pair<StoragePool, DestroyCommand> cmd : destroyCmds) {
- try {
- Answer cvAnswer = this.storageMgr.sendToPool(cmd.first(), cmd.second());
- } catch (StorageUnavailableException e) {
- s_logger.debug("Unable to delete the old copy on storage pool: "
- + e.toString());
+ VolumeApiResult result = future.get();
+ if (result.isFailed()) {
+ s_logger.debug("migrate volume failed:" + result.getResult());
+ return null;
}
+ return result.getVolume();
+ } catch (InterruptedException e) {
+ s_logger.debug("migrate volume failed", e);
+ return null;
+ } catch (ExecutionException e) {
+ s_logger.debug("migrate volume failed", e);
+ return null;
}
- return true;
}
@Override
- public boolean StorageMigration(
+ public boolean storageMigration(
VirtualMachineProfile<? extends VirtualMachine> vm,
- StoragePool destPool) throws ConcurrentOperationException {
+ StoragePool destPool) {
List<VolumeVO> vols = _volsDao.findUsableVolumesForInstance(vm.getId());
List<Volume> volumesNeedToMigrate = new ArrayList<Volume>();
@@ -2215,7 +2083,13 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
return true;
}
- return migrateVolumes(volumesNeedToMigrate, destPool);
+ for (Volume vol : volumesNeedToMigrate) {
+ Volume result = migrateVolume(vol, destPool);
+ if (result == null) {
+ return false;
+ }
+ }
+ return true;
}
@Override
@@ -2452,9 +2326,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
vol = task.volume;
} else if (task.type == VolumeTaskType.MIGRATE) {
pool = (StoragePool)dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary);
- List<Volume> volumes = new ArrayList<Volume>();
- volumes.add(task.volume);
- migrateVolumes(volumes, pool);
+ migrateVolume(task.volume, pool);
vol = task.volume;
} else if (task.type == VolumeTaskType.RECREATE) {
Pair<VolumeVO, DataStore> result = recreateVolume(task.volume, vm, dest);
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/server/src/com/cloud/storage/snapshot/SnapshotManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
index a7692de..72e8163 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java
@@ -22,6 +22,7 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.host.HostVO;
import com.cloud.storage.SnapshotPolicyVO;
import com.cloud.storage.SnapshotVO;
+import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
import com.cloud.utils.db.Filter;
@@ -138,5 +139,5 @@ public interface SnapshotManager {
void deleteSnapshotsDirForVolume(String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId);
- boolean canOperateOnVolume(VolumeVO volume);
+ boolean canOperateOnVolume(Volume volume);
}
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 6b48b82..58ca9a4 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -1578,7 +1578,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
}
@Override
- public boolean canOperateOnVolume(VolumeVO volume) {
+ public boolean canOperateOnVolume(Volume volume) {
List<SnapshotVO> snapshots = _snapshotDao.listByStatus(volume.getId(), Snapshot.State.Creating,
Snapshot.State.CreatedOnPrimary, Snapshot.State.BackingUp);
if (snapshots.size() > 0) {
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/020be66f/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 5d48f14..4b7a4db 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -1226,7 +1226,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
VirtualMachineProfile<VMInstanceVO> profile = new VirtualMachineProfileImpl<VMInstanceVO>(vm);
boolean migrationResult = false;
try {
- migrationResult = this.volumeMgr.StorageMigration(profile, destPool);
+ migrationResult = this.volumeMgr.storageMigration(profile, destPool);
if (migrationResult) {
//if the vm is migrated to different pod in basic mode, need to reallocate ip