package org.ovirt.engine.core.bll.storage.disk.cinder;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.InternalCommandAttribute;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.storage.disk.image.ImagesHandler;
import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.CreateCinderSnapshotParameters;
import org.ovirt.engine.core.common.businessentities.Snapshot;
import org.ovirt.engine.core.common.businessentities.SubjectEntity;
import org.ovirt.engine.core.common.businessentities.storage.CinderDisk;
import org.ovirt.engine.core.common.businessentities.storage.ImageStatus;
import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DiskDao;
import org.ovirt.engine.core.dao.ImageDao;
import org.ovirt.engine.core.di.Injector;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;
@InternalCommandAttribute
public class TryBackToCinderSnapshotCommand<T extends CreateCinderSnapshotParameters> extends CreateCinderSnapshotCommand<T> {
@Inject
private DiskDao diskDao;
@Inject
private ImageDao imageDao;
private CinderDisk oldActiveDisk;
public TryBackToCinderSnapshotCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
}
/**
* Remove old image vm map.
*/
@Override
protected void processOldImageFromDb() {
updateOldImageAsActive(Snapshot.SnapshotType.PREVIEW, false);
}
@Override
protected void executeCommand() {
final CinderDisk newCinderVolume = createVolumeFromSnapshotInCinder();
TransactionSupport.executeInNewTransaction(() -> {
processOldImageFromDb();
addDiskImageToDb(newCinderVolume, getCompensationContext(), Boolean.TRUE);
return null;
});
getParameters().setDestinationImageId(newCinderVolume.getImageId());
getParameters().setImageId(newCinderVolume.getImageId());
getReturnValue().setActionReturnValue(newCinderVolume);
persistCommand(getParameters().getParentCommand(), true);
setSucceeded(true);
return;
}
private CinderDisk createVolumeFromSnapshotInCinder() {
Guid newVolumeId = cinderCloneDiskFromSnapshot();
CinderDisk clonedDiskFromSnapshot = initializeNewCinderVolumeDisk(newVolumeId);
// Setting this for the callback from coco.
getParameters().setDestinationImageId(newVolumeId);
return clonedDiskFromSnapshot;
}
private CinderDisk initializeNewCinderVolumeDisk(Guid newVolumeId) {
CinderDisk clonedDiskFromSnapshot = (CinderDisk) diskDao.get(getParameters().getContainerId());
// override volume type and volume format to Unassigned and unassigned for Cinder.
clonedDiskFromSnapshot.setVolumeType(VolumeType.Unassigned);
clonedDiskFromSnapshot.setVolumeFormat(VolumeFormat.Unassigned);
clonedDiskFromSnapshot.setImageStatus(ImageStatus.LOCKED);
clonedDiskFromSnapshot.setCreationDate(new Date());
clonedDiskFromSnapshot.setVmSnapshotId(getParameters().getVmSnapshotId());
clonedDiskFromSnapshot.setLastModifiedDate(new Date());
clonedDiskFromSnapshot.setQuotaId(getParameters().getQuotaId());
clonedDiskFromSnapshot.setDiskProfileId(getParameters().getDiskProfileId());
clonedDiskFromSnapshot.setImageId(newVolumeId);
clonedDiskFromSnapshot.setParentId(getImageId());
return clonedDiskFromSnapshot;
}
private Guid cinderCloneDiskFromSnapshot() {
CinderDisk activeCinderVolume = getOldActiveDisk();
String newVolumeId = getCinderBroker().cloneVolumeFromSnapshot(activeCinderVolume, getImageId());
return Guid.createGuidFromString(newVolumeId);
}
protected CinderDisk getOldActiveDisk() {
if (oldActiveDisk == null) {
oldActiveDisk = (CinderDisk) diskDao.get(getParameters().getContainerId());
}
return oldActiveDisk;
}
@Override
public Guid getStorageDomainId() {
return getOldActiveDisk().getStorageIds().get(0);
}
@Override
protected void lockImage() {
ImagesHandler.updateImageStatus(getParameters().getImageId(), ImageStatus.LOCKED);
}
@Override
public CommandCallback getCallback() {
return Injector.injectMembers(new CloneSingleCinderDiskCommandCallback());
}
@Override
protected void endSuccessfully() {
ImagesHandler.updateImageStatus(getParameters().getDestinationImageId(), ImageStatus.OK);
ImagesHandler.updateImageStatus(getParameters().getImageId(), ImageStatus.OK);
if (!getParameters().isLeaveLocked()) {
getDestinationDiskImage().setImageStatus(ImageStatus.OK);
imageDao.update(getDestinationDiskImage().getImage());
}
setSucceeded(true);
}
@Override
protected void endWithFailure() {
ImagesHandler.updateImageStatus(getParameters().getDestinationImageId(), ImageStatus.ILLEGAL);
ImagesHandler.updateImageStatus(getParameters().getImageId(), ImageStatus.OK);
updateOldImageAsActive(Snapshot.SnapshotType.ACTIVE, true);
// Remove destination, unlock source:
undoActionOnSourceAndDestination();
setSucceeded(true);
}
@Override
protected Collection<SubjectEntity> getSubjectEntities() {
return Collections.singleton(new SubjectEntity(VdcObjectType.Storage,
getStorageDomainId()));
}
}