Handle the case where the volume a snapshot was created from is removed from the database

This commit is contained in:
Mike Tutkowski 2014-11-06 17:43:07 -07:00
parent 05bec59c14
commit ebb96f5e2f
3 changed files with 66 additions and 9 deletions

View File

@ -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();

View File

@ -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

View File

@ -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);
long storagePoolId = volumeVO.getPoolId();
if (snapshotStore == null) {
return DataStoreRole.Image;
}
long storagePoolId = snapshotStore.getDataStoreId();
DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();