package org.ovirt.engine.core.bll.storage.disk.cinder; import java.util.Collection; import java.util.Collections; import java.util.concurrent.ExecutionException; import javax.inject.Inject; import org.ovirt.engine.core.bll.InternalCommandAttribute; import org.ovirt.engine.core.bll.SerialChildCommandsExecutionCallback; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.RemoveCinderDiskParameters; import org.ovirt.engine.core.common.action.RemoveCinderDiskVolumeParameters; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.SubjectEntity; import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.TransactionScopeOption; import org.ovirt.engine.core.dao.DiskImageDao; import org.ovirt.engine.core.dao.ImageDao; import org.ovirt.engine.core.utils.transaction.TransactionSupport; @InternalCommandAttribute public class RestoreFromCinderSnapshotCommand<T extends RemoveCinderDiskParameters> extends RemoveCinderVolumeParentCommand<T> { @Inject private ImageDao imageDao; @Inject private DiskImageDao diskImageDao; public RestoreFromCinderSnapshotCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); } @Override protected void executeCommand() { setStorageDomainId(getParameters().getStorageDomainId()); removeCinderVolume(); setSucceeded(true); } private void removeCinderVolume() { CinderDisk cinderSnapshotToRemove = (CinderDisk) diskImageDao.getSnapshotById(getParameters().getImageId()); // Update the volume with active=false, so removeDiskFromDb will not set active volume on the first volume. cinderSnapshotToRemove.setActive(false); imageDao.update(cinderSnapshotToRemove.getImage()); removeDescendentSnapshots(cinderSnapshotToRemove); removeCinderVolume(cinderSnapshotToRemove.getStorageIds().get(0), 0); } protected boolean removeCinderVolume(Guid storageId, int removedVolumeIndex) { RemoveCinderDiskVolumeParameters param = getParameters().getChildCommandsParameters().get(removedVolumeIndex); try { VdcReturnValueBase vdcReturnValueBase = getFutureRemoveCinderDiskVolume(storageId, removedVolumeIndex).get(); if (vdcReturnValueBase == null || !vdcReturnValueBase.getSucceeded()) { handleExecutionFailure(param.getRemovedVolume(), vdcReturnValueBase); return false; } } catch (InterruptedException | ExecutionException e) { log.error("Error removing Cinder volume", e); return false; } return true; } /** * Remove the snapshot's descendants. For example if we plan to commit snapshot A we should delete all the snapshots * which were created after it (like snapshot B). */ private void removeDescendentSnapshots(CinderDisk cinderDiskSnapshot) { initCinderDiskVolumesParametersList(cinderDiskSnapshot); } @Override public void removeDiskFromDbCallBack(final CinderDisk cinderVolume) { TransactionSupport.executeInScope(TransactionScopeOption.Required, () -> { removeDiskFromDb(cinderVolume, null); return null; }); } @Override public CommandCallback getCallback() { return new SerialChildCommandsExecutionCallback(); } @Override protected Collection<SubjectEntity> getSubjectEntities() { return Collections.singleton(new SubjectEntity(VdcObjectType.Storage, getStorageDomainId())); } }