diff --git a/scripts/storage/qcow2/managesnapshot.sh b/scripts/storage/qcow2/managesnapshot.sh index 4d777bba157..22cda03d7da 100755 --- a/scripts/storage/qcow2/managesnapshot.sh +++ b/scripts/storage/qcow2/managesnapshot.sh @@ -33,10 +33,10 @@ usage() { } qemu_img="cloud-qemu-img" -which $qemu_img +which $qemu_img >& /dev/null if [ $? -gt 0 ] then - which qemu-img + which qemu-img >& /dev/null if [ $? -eq 0 ] then qemu_img="qemu-img" diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 7a6da7fea09..c6fe6544b65 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -1567,15 +1567,7 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag @Override public VolumeVO moveVolume(VolumeVO volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType) throws ConcurrentOperationException { - List snapshots = _snapshotDao.listByVolumeId(volume.getId()); - if (snapshots != null && snapshots.size() > 0) { - throw new CloudRuntimeException("Unable to move volume " + volume.getId() + " due to there are snapshots for this volume"); - } - - List snapshotPolicys = _snapshotPolicyDao.listByVolumeId(volume.getId()); - if (snapshotPolicys != null && snapshotPolicys.size() > 0) { - throw new CloudRuntimeException("Unable to move volume " + volume.getId() + " due to there are snapshot policyes for this volume"); - } + // Find a destination storage pool with the specified criteria DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); @@ -2440,6 +2432,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag throw new InvalidParameterValueException("Unable to aquire volume with ID: " + volumeId); } + if (!_snapshotMgr.canOperateOnVolume(volume)) { + throw new InvalidParameterValueException("There are snapshot creating on it, Unable to delete the volume"); + } + //permission check _accountMgr.checkAccess(caller, null, volume); @@ -2622,6 +2618,10 @@ public class StorageManagerImpl implements StorageManager, StorageService, Manag boolean transitResult = false; try { 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"); diff --git a/server/src/com/cloud/storage/dao/SnapshotDao.java b/server/src/com/cloud/storage/dao/SnapshotDao.java index 1a0609c737d..99ac51d3935 100644 --- a/server/src/com/cloud/storage/dao/SnapshotDao.java +++ b/server/src/com/cloud/storage/dao/SnapshotDao.java @@ -21,6 +21,7 @@ package com.cloud.storage.dao; import java.util.List; import com.cloud.storage.Snapshot; +import com.cloud.storage.Snapshot.Status; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Snapshot.Type; import com.cloud.utils.db.Filter; @@ -42,4 +43,5 @@ public interface SnapshotDao extends GenericDao { List listByHostId(long hostId); public Long countSnapshotsForAccount(long accountId); List listByInstanceId(long instanceId, Snapshot.Status... status); + List listByStatus(long volumeId, Snapshot.Status... status); } diff --git a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java index bad7b6e5c55..73b7fe4833a 100644 --- a/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java +++ b/server/src/com/cloud/storage/dao/SnapshotDaoImpl.java @@ -60,6 +60,7 @@ public class SnapshotDaoImpl extends GenericDaoBase implements private final SearchBuilder HostIdSearch; private final SearchBuilder AccountIdSearch; private final SearchBuilder InstanceIdSearch; + private final SearchBuilder StatusSearch; private final GenericSearchBuilder CountSnapshotsByAccount; protected final VMInstanceDaoImpl _instanceDao = ComponentLocator.inject(VMInstanceDaoImpl.class); @@ -168,6 +169,11 @@ public class SnapshotDaoImpl extends GenericDaoBase implements AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); AccountIdSearch.done(); + StatusSearch = createSearchBuilder(); + StatusSearch.and("volumeId", StatusSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + StatusSearch.and("status", StatusSearch.entity().getStatus(), SearchCriteria.Op.IN); + StatusSearch.done(); + CountSnapshotsByAccount = createSearchBuilder(Long.class); CountSnapshotsByAccount.select(null, Func.COUNT, null); CountSnapshotsByAccount.and("account", CountSnapshotsByAccount.entity().getAccountId(), SearchCriteria.Op.EQ); @@ -270,12 +276,20 @@ public class SnapshotDaoImpl extends GenericDaoBase implements public List listByInstanceId(long instanceId, Snapshot.Status... status) { SearchCriteria sc = this.InstanceIdSearch.create(); - if (status != null) { - sc.setParameters("status", status.toString()); + if (status != null && status.length != 0) { + sc.setParameters("status", (Object[])status); } sc.setJoinParameters("instanceSnapshots", "state", Volume.State.Ready); sc.setJoinParameters("instanceVolumes", "instanceId", instanceId); return listBy(sc, null); } + + @Override + public List listByStatus(long volumeId, Snapshot.Status... status) { + SearchCriteria sc = this.StatusSearch.create(); + sc.setParameters("volumeId", volumeId); + sc.setParameters("status", (Object[])status); + return listBy(sc, null); + } } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManager.java b/server/src/com/cloud/storage/snapshot/SnapshotManager.java index 0aa53fe0250..7b4ee22d92f 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManager.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManager.java @@ -137,4 +137,6 @@ public interface SnapshotManager { void deleteSnapshotsForVolume (String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId ); void deleteSnapshotsDirForVolume(String secondaryStoragePoolUrl, Long dcId, Long accountId, Long volumeId); + + boolean canOperateOnVolume(VolumeVO volume); } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index b982b36cbce..abe167d7111 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -372,6 +372,10 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma throw new InvalidParameterValueException("No such volume exist"); } + if (volume.getState() != Volume.State.Ready) { + throw new InvalidParameterValueException("Volume is not in ready state"); + } + SnapshotVO snapshot = null; boolean backedUp = false; @@ -1506,5 +1510,14 @@ public class SnapshotManagerImpl implements SnapshotManager, SnapshotService, Ma } return false; } + + @Override + public boolean canOperateOnVolume(VolumeVO volume) { + List snapshots = _snapshotDao.listByStatus(volume.getId(), Status.Creating, Status.CreatedOnPrimary, Status.BackingUp); + if (snapshots.size() > 0) { + return false; + } + return true; + } }