server: protect against stray snapshot-details without snapshot (#4924)

This PR makes sure no orphaned snapshot details are considered in the cleanup at startup job.
a real solution would be to implement some kind of cascading delete, but as the parent record is "only" marked as removed this would be a bit com

Co-authored-by: Daan Hoogland <dahn@onecht.net>
This commit is contained in:
dahn 2021-04-29 17:10:29 +02:00 committed by GitHub
parent 39cb2bf0af
commit be255e4203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 14 additions and 15 deletions

View File

@ -200,9 +200,11 @@ public class DataMigrationUtility {
snapshotVO != null && snapshotVO.getHypervisorType() != Hypervisor.HypervisorType.Simulator snapshotVO != null && snapshotVO.getHypervisorType() != Hypervisor.HypervisorType.Simulator
&& snapshot.getParentSnapshotId() == 0 ) { && snapshot.getParentSnapshotId() == 0 ) {
SnapshotInfo snap = snapshotFactory.getSnapshot(snapshotVO.getSnapshotId(), DataStoreRole.Image); SnapshotInfo snap = snapshotFactory.getSnapshot(snapshotVO.getSnapshotId(), DataStoreRole.Image);
if (snap != null) {
files.add(snap); files.add(snap);
} }
} }
}
for (SnapshotInfo parent : files) { for (SnapshotInfo parent : files) {
List<SnapshotInfo> chain = new ArrayList<>(); List<SnapshotInfo> chain = new ArrayList<>();

View File

@ -87,6 +87,9 @@ public class SnapshotDataFactoryImpl implements SnapshotDataFactory {
@Override @Override
public SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role) { public SnapshotInfo getSnapshot(long snapshotId, DataStoreRole role) {
SnapshotVO snapshot = snapshotDao.findById(snapshotId); SnapshotVO snapshot = snapshotDao.findById(snapshotId);
if (snapshot == null) {
return null;
}
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshotId, role); SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findBySnapshot(snapshotId, role);
if (snapshotStore == null) { if (snapshotStore == null) {
snapshotStore = snapshotStoreDao.findByVolume(snapshot.getVolumeId(), role); snapshotStore = snapshotStoreDao.findByVolume(snapshot.getVolumeId(), role);

View File

@ -142,7 +142,10 @@ public class SnapshotObject implements SnapshotInfo {
List<SnapshotInfo> children = new ArrayList<>(); List<SnapshotInfo> children = new ArrayList<>();
if (vos != null) { if (vos != null) {
for (SnapshotDataStoreVO vo : vos) { for (SnapshotDataStoreVO vo : vos) {
children.add(snapshotFactory.getSnapshot(vo.getSnapshotId(), DataStoreRole.Image)); SnapshotInfo info = snapshotFactory.getSnapshot(vo.getSnapshotId(), DataStoreRole.Image);
if (info != null) {
children.add(info);
}
} }
} }
return children; return children;

View File

@ -1097,6 +1097,10 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager,
final List<SnapshotDetailsVO> snapshotList = _snapshotDetailsDao.findDetails(AsyncJob.Constants.MS_ID, Long.toString(msid), false); final List<SnapshotDetailsVO> snapshotList = _snapshotDetailsDao.findDetails(AsyncJob.Constants.MS_ID, Long.toString(msid), false);
for (final SnapshotDetailsVO snapshotDetailsVO : snapshotList) { for (final SnapshotDetailsVO snapshotDetailsVO : snapshotList) {
SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotDetailsVO.getResourceId(), DataStoreRole.Primary); SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotDetailsVO.getResourceId(), DataStoreRole.Primary);
if (snapshot == null) {
_snapshotDetailsDao.remove(snapshotDetailsVO.getId());
continue;
}
snapshotSrv.processEventOnSnapshotObject(snapshot, Snapshot.Event.OperationFailed); snapshotSrv.processEventOnSnapshotObject(snapshot, Snapshot.Event.OperationFailed);
_snapshotDetailsDao.removeDetail(snapshotDetailsVO.getResourceId(), AsyncJob.Constants.MS_ID); _snapshotDetailsDao.removeDetail(snapshotDetailsVO.getResourceId(), AsyncJob.Constants.MS_ID);
} }

View File

@ -24,7 +24,6 @@ import org.apache.cloudstack.framework.config.Configurable;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command; import com.cloud.agent.api.Command;
import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceAllocationException;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO; import com.cloud.storage.SnapshotVO;
import com.cloud.storage.Volume; import com.cloud.storage.Volume;
@ -83,7 +82,5 @@ public interface SnapshotManager extends Configurable {
SnapshotVO getParentSnapshot(VolumeInfo volume); SnapshotVO getParentSnapshot(VolumeInfo volume);
Snapshot backupSnapshot(Long snapshotId);
SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException; SnapshotInfo takeSnapshot(VolumeInfo volume) throws ResourceAllocationException;
} }

View File

@ -420,16 +420,6 @@ public class SnapshotManagerImpl extends MutualExclusiveIdsManagerBase implement
return snapshotOnSecondary; return snapshotOnSecondary;
} }
@Override
public Snapshot backupSnapshot(Long snapshotId) {
SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Image);
if (snapshot != null) {
throw new CloudRuntimeException("Already in the backup snapshot:" + snapshotId);
}
return snapshotSrv.backupSnapshot(snapshot);
}
@Override @Override
public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long volumeId, Long vmSnapshotId) { public Snapshot backupSnapshotFromVmSnapshot(Long snapshotId, Long vmId, Long volumeId, Long vmSnapshotId) {
VMInstanceVO vm = _vmDao.findById(vmId); VMInstanceVO vm = _vmDao.findById(vmId);