package org.ovirt.engine.core.bll.storage.disk.image;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.InternalCommandAttribute;
import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.snapshots.CreateSnapshotCommand;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.AddImageFromScratchParameters;
import org.ovirt.engine.core.common.action.CreateVolumeParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase.EndProcedure;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.ImageStatus;
import org.ovirt.engine.core.common.businessentities.storage.VolumeType;
import org.ovirt.engine.core.common.vdscommands.CreateImageVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DiskImageDynamicDao;
import org.ovirt.engine.core.utils.transaction.TransactionSupport;
@InternalCommandAttribute
@NonTransactiveCommandAttribute(forceCompensation = true)
public class AddImageFromScratchCommand<T extends AddImageFromScratchParameters> extends CreateSnapshotCommand<T> {
@Inject
private DiskImageDynamicDao diskImageDynamicDao;
public AddImageFromScratchCommand(T parameters, CommandContext commandContext) {
super(parameters, commandContext);
setVmId(getParameters().getMasterVmId());
getParameters().setCommandType(getActionType());
setStoragePoolId(getParameters().getStoragePoolId());
}
public AddImageFromScratchCommand(Guid commandId) {
super(commandId);
}
@Override
protected void executeCommand() {
setImageGroupId(getParameters().getDiskInfo().getId());
if (Guid.isNullOrEmpty(getDestinationImageId())) {
setDestinationImageId(Guid.newGuid());
}
newDiskImage = new DiskImage();
newDiskImage.setImageId(getDestinationImageId());
newDiskImage.setPropagateErrors(getParameters().getDiskInfo().getPropagateErrors());
newDiskImage.setWipeAfterDelete(getParameters().getDiskInfo().isWipeAfterDelete());
newDiskImage.setDiskAlias(getParameters().getDiskInfo().getDiskAlias());
newDiskImage.setDiskDescription(getParameters().getDiskInfo().getDiskDescription());
newDiskImage.setShareable(getParameters().getDiskInfo().isShareable());
newDiskImage.setId(getImageGroupId());
newDiskImage.setStoragePoolId(getParameters().getStoragePoolId());
newDiskImage.setStorageIds(new ArrayList<>(Arrays.asList(getParameters().getStorageDomainId())));
newDiskImage.setSize(getParameters().getDiskInfo().getSize());
newDiskImage.setVolumeType(getParameters().getDiskInfo().getVolumeType());
newDiskImage.setVolumeFormat(getParameters().getDiskInfo().getVolumeFormat());
newDiskImage.setDescription("");
newDiskImage.setCreationDate(new Date());
newDiskImage.setLastModified(new Date());
newDiskImage.setActive(true);
newDiskImage.setImageStatus(ImageStatus.LOCKED);
newDiskImage.setVmSnapshotId(getParameters().getVmSnapshotId());
newDiskImage.setQuotaId(getParameters().getQuotaId());
newDiskImage.setDiskProfileId(getParameters().getDiskProfileId());
newDiskImage.setContentType(getParameters().getDiskInfo().getContentType());
TransactionSupport.executeInNewTransaction(() -> {
if (!getParameters().isShouldRemainIllegalOnFailedExecution()) {
addDiskImageToDb(newDiskImage, getCompensationContext(), Boolean.TRUE);
} else {
addDiskImageToDb(newDiskImage, null, Boolean.TRUE);
getCompensationContext().snapshotEntityStatus(newDiskImage.getImage(), ImageStatus.ILLEGAL);
}
return null;
});
freeLock();
if (getParameters().isShouldRemainIllegalOnFailedExecution()) {
getReturnValue().setActionReturnValue(newDiskImage);
}
processImageInIrs();
getReturnValue().setActionReturnValue(newDiskImage);
setSucceeded(true);
}
protected boolean processImageInIrs() {
Guid taskId = persistAsyncTaskPlaceHolder(getParameters().getParentCommand());
VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.CreateImage,
getCreateImageVDSCommandParameters());
if (vdsReturnValue.getSucceeded()) {
getParameters().setVdsmTaskIds(new ArrayList<>());
getParameters().getVdsmTaskIds().add(
createTask(taskId,
vdsReturnValue.getCreationInfo(),
getParameters().getParentCommand(),
VdcObjectType.Storage,
getParameters().getStorageDomainId()));
getTaskIdList().add(getParameters().getVdsmTaskIds().get(0));
return true;
}
return false;
}
private Long getInitialSize() {
DiskImage diskImage = getParameters().getDiskInfo();
Long initialSize = null;
if (ImagesHandler.isImageInitialSizeSupported(getStorageDomain().getStorageType()) &&
diskImage.getImage().getVolumeType().equals(VolumeType.Sparse) &&
diskImage.getActualSizeInBytes() != 0) {
initialSize = diskImage.getActualSizeInBytes();
}
return initialSize;
}
private CreateImageVDSCommandParameters getCreateImageVDSCommandParameters() {
CreateImageVDSCommandParameters parameters =
new CreateImageVDSCommandParameters(getParameters().getStoragePoolId(),
getParameters()
.getStorageDomainId(), getImageGroupId(), getParameters().getDiskInfo().getSize(),
getParameters().getDiskInfo().getVolumeType(), getParameters().getDiskInfo()
.getVolumeFormat(), getDestinationImageId(),
getJsonDiskDescription(getParameters().getDiskInfo()));
parameters.setImageInitialSizeInBytes(Optional.ofNullable(getInitialSize()).orElse(0L));
return parameters;
}
private CreateVolumeParameters getCreateVolumeParameters() {
CreateVolumeParameters createVolumeParameters =
new CreateVolumeParameters(getParameters().getStoragePoolId(),
getParameters().getStorageDomainId(),
getImageGroupId(),
getDestinationImageId(),
Guid.Empty, Guid.Empty,
getParameters().getDiskInfo().getSize(),
getInitialSize(),
getParameters().getDiskInfo().getVolumeFormat(),
getParameters().getDiskInfo().getVolumeType(),
getJsonDiskDescription(getParameters().getDiskInfo()));
createVolumeParameters.setParentCommand(getActionType());
createVolumeParameters.setParentParameters(getParameters());
createVolumeParameters.setEndProcedure(EndProcedure.COMMAND_MANAGED);
return createVolumeParameters;
}
@Override
protected DiskImage getImage() {
return null;
}
@Override
protected void endWithFailure() {
if (getDestinationDiskImage() != null) {
if (getParameters().isShouldRemainIllegalOnFailedExecution()) {
setImageStatus(ImageStatus.ILLEGAL, getDestinationDiskImage());
} else {
diskImageDynamicDao.remove(getDestinationDiskImage().getImageId());
super.endWithFailure();
}
}
setSucceeded(true);
}
@Override
protected void endSuccessfully() {
super.endSuccessfully();
setActionReturnValue(getDestinationDiskImage());
}
}