Handle the case where the volume a snapshot was created from is removed from the database
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/ebb96f5e Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/ebb96f5e Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/ebb96f5e Branch: refs/heads/statscollector-graphite Commit: ebb96f5e2f533802107492e5e7741786d6266a3b Parents: 05bec59 Author: Mike Tutkowski <mike.tutkow...@solidfire.com> Authored: Thu Nov 6 17:43:07 2014 -0700 Committer: Mike Tutkowski <mike.tutkow...@solidfire.com> Committed: Thu Nov 6 19:44:46 2014 -0700 ---------------------------------------------------------------------- .../snapshot/StorageSystemSnapshotStrategy.java | 20 +++++++++- server/src/com/cloud/api/ApiResponseHelper.java | 42 +++++++++++++++++--- .../com/cloud/template/TemplateManagerImpl.java | 13 ++++-- 3 files changed, 66 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebb96f5e/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java ---------------------------------------------------------------------- diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java index 9a6c51b..2367825 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/StorageSystemSnapshotStrategy.java @@ -37,6 +37,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer; import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.agent.AgentManager; @@ -76,6 +78,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase { @Inject private PrimaryDataStoreDao _storagePoolDao; @Inject private SnapshotDao _snapshotDao; @Inject private SnapshotDataFactory _snapshotDataFactory; + @Inject private SnapshotDataStoreDao _snapshotStoreDao; @Inject private SnapshotDetailsDao _snapshotDetailsDao; @Inject private VMInstanceDao _vmInstanceDao; @Inject private VolumeDao _volumeDao; @@ -400,7 +403,22 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase { long volumeId = snapshot.getVolumeId(); VolumeVO volumeVO = _volumeDao.findById(volumeId); - long storagePoolId = volumeVO.getPoolId(); + long storagePoolId; + + if (volumeVO == null) { + SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary); + + if (snapshotStore != null) { + storagePoolId = snapshotStore.getDataStoreId(); + } + else { + throw new CloudRuntimeException("Unable to determine the storage pool of the snapshot"); + } + } + else { + storagePoolId = volumeVO.getPoolId(); + } + DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebb96f5e/server/src/com/cloud/api/ApiResponseHelper.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 4c22127..8172987 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -149,8 +149,10 @@ import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.usage.UsageService; import org.apache.cloudstack.usage.UsageTypes; @@ -295,6 +297,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; import com.cloud.utils.db.EntityManager; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; import com.cloud.vm.ConsoleProxyVO; @@ -333,7 +336,9 @@ public class ApiResponseHelper implements ResponseGenerator { @Inject private DataStoreManager _dataStoreMgr; @Inject - SnapshotDataStoreDao _snapshotStoreDao; + private SnapshotDataStoreDao _snapshotStoreDao; + @Inject + private PrimaryDataStoreDao _storagePoolDao; @Override public UserResponse createUserResponse(User user) { @@ -1447,14 +1452,41 @@ public class ApiResponseHelper implements ResponseGenerator { @Override public List<TemplateResponse> createTemplateResponses(ResponseView view, long templateId, Long snapshotId, Long volumeId, boolean readyOnly) { - VolumeVO volume = null; + Long zoneId = null; + if (snapshotId != null) { Snapshot snapshot = ApiDBUtils.findSnapshotById(snapshotId); - volume = findVolumeById(snapshot.getVolumeId()); + VolumeVO volume = findVolumeById(snapshot.getVolumeId()); + + // it seems that the volume can actually be removed from the DB at some point if it's deleted + // if volume comes back null, use another technique to try to discover the zone + if (volume == null) { + SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary); + + if (snapshotStore != null) { + long storagePoolId = snapshotStore.getDataStoreId(); + + StoragePoolVO storagePool = _storagePoolDao.findById(storagePoolId); + + if (storagePool != null) { + zoneId = storagePool.getDataCenterId(); + } + } + } + else { + zoneId = volume.getDataCenterId(); + } } else { - volume = findVolumeById(volumeId); + VolumeVO volume = findVolumeById(volumeId); + + zoneId = volume.getDataCenterId(); } - return createTemplateResponses(view, templateId, volume.getDataCenterId(), readyOnly); + + if (zoneId == null) { + throw new CloudRuntimeException("Unable to determine the zone ID"); + } + + return createTemplateResponses(view, templateId, zoneId, readyOnly); } @Override http://git-wip-us.apache.org/repos/asf/cloudstack/blob/ebb96f5e/server/src/com/cloud/template/TemplateManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index e495eb9..da3940c 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -80,6 +80,8 @@ import org.apache.cloudstack.storage.command.AttachCommand; import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; @@ -245,6 +247,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, private EndPointSelector _epSelector; @Inject private UserVmJoinDao _userVmJoinDao; + @Inject + private SnapshotDataStoreDao _snapshotStoreDao; @Inject MessageBus _messageBus; @@ -1470,10 +1474,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } private DataStoreRole getDataStoreRole(Snapshot snapshot) { - long volumeId = snapshot.getVolumeId(); - VolumeVO volumeVO = _volumeDao.findById(volumeId); + SnapshotDataStoreVO snapshotStore = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Primary); + + if (snapshotStore == null) { + return DataStoreRole.Image; + } - long storagePoolId = volumeVO.getPoolId(); + long storagePoolId = snapshotStore.getDataStoreId(); DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();