package org.ovirt.engine.core.bll;
import org.ovirt.engine.core.common.action.ImagesActionsParametersBase;
import org.ovirt.engine.core.common.action.ImagesContainterParametersBase;
import org.ovirt.engine.core.common.action.VdcActionParametersBase;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.asynctasks.AsyncTaskCreationInfo;
import org.ovirt.engine.core.common.asynctasks.AsyncTaskParameters;
import org.ovirt.engine.core.common.asynctasks.AsyncTaskType;
import org.ovirt.engine.core.common.businessentities.AsyncTaskResultEnum;
import org.ovirt.engine.core.common.businessentities.AsyncTaskStatusEnum;
import org.ovirt.engine.core.common.businessentities.DiskImage;
import org.ovirt.engine.core.common.businessentities.VolumeFormat;
import org.ovirt.engine.core.common.businessentities.VolumeType;
import org.ovirt.engine.core.common.businessentities.async_tasks;
import org.ovirt.engine.core.common.businessentities.image_vm_map;
import org.ovirt.engine.core.common.businessentities.image_vm_map_id;
import org.ovirt.engine.core.common.errors.VdcBLLException;
import org.ovirt.engine.core.common.errors.VdcBllErrors;
import org.ovirt.engine.core.common.vdscommands.CreateSnapshotVDSCommandParameters;
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.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
/**
* This command responsible to creating snapshot from existing image and replace it to VM, holds the image. This command
* legal only for images, appeared in Db
*/
// C# TO JAVA CONVERTER TODO TASK: Java annotations will not correspond to .NET
// attributes:
@InternalCommandAttribute
public class CreateSnapshotCommand<T extends ImagesActionsParametersBase> extends BaseImagesCommand<T> {
protected DiskImage mNewCreatedDiskImage;
private String mDescription = "";
// internal CreateSnapshotCommand(ImagesContainterParametersBase parameters)
// : base(parameters)
// {
// mDescription = parameters.Description;
// }
public CreateSnapshotCommand(T parameters) {
super(parameters);
mDescription = parameters.getDescription();
setSnapshotName(mDescription);
}
protected ImagesContainterParametersBase getImagesContainterParameters() {
VdcActionParametersBase tempVar = getParameters();
return (ImagesContainterParametersBase) ((tempVar instanceof ImagesContainterParametersBase) ? tempVar : null);
}
@Override
protected void executeCommand() {
super.executeCommand();
if (CanCreateSnapshot()) {
if (CreateSnapshotInIrsServer()) {
/**
* Vitaly TODO: think about transactivity in DB
*/
ProcessOldImageFromDb();
AddDiskImageToDb(mNewCreatedDiskImage);
setSucceeded(true);
}
} else {
setActionReturnValue(Guid.Empty);
}
}
protected Guid getDestinationStorageDomainId() {
return mNewCreatedDiskImage.getstorage_id() != null ? mNewCreatedDiskImage.getstorage_id().getValue()
: Guid.Empty;
}
protected boolean CreateSnapshotInIrsServer() {
setDestinationImageId(Guid.NewGuid());
mNewCreatedDiskImage = CloneDiskImage(getDestinationImageId());
mNewCreatedDiskImage.setstorage_id(getDestinationStorageDomainId());
setStoragePoolId(mNewCreatedDiskImage.getstorage_pool_id() != null ? mNewCreatedDiskImage.getstorage_pool_id()
.getValue() : Guid.Empty);
getParameters().setStoragePoolId(getStoragePoolId().getValue());
// override volume type and volume format to sparse and cow according to
// storage team request
mNewCreatedDiskImage.setvolume_type(VolumeType.Sparse);
mNewCreatedDiskImage.setvolume_format(VolumeFormat.COW);
try {
VDSReturnValue vdsReturnValue =
Backend
.getInstance()
.getResourceManager()
.RunVdsCommand(
VDSCommandType.CreateSnapshot,
new CreateSnapshotVDSCommandParameters(getStoragePoolId().getValue(),
getDestinationStorageDomainId(),
getImageGroupId(),
getImage().getId(),
getDiskImage().getsize(),
mNewCreatedDiskImage.getvolume_type(),
mNewCreatedDiskImage.getvolume_format(),
mNewCreatedDiskImage.getdisk_type(),
getDiskImage().getimage_group_id().getValue(),
getDestinationImageId(),
CalculateImageDescription(),
getStoragePool().getcompatibility_version().toString()));
if (vdsReturnValue.getSucceeded()) {
getParameters().setTaskIds(new java.util.ArrayList<Guid>());
getParameters().getTaskIds().add(
CreateTask(vdsReturnValue.getCreationInfo(), getParameters().getParentCommand()));
getReturnValue().getInternalTaskIdList().add(getParameters().getTaskIds().get(0));
// Shouldn't happen anymore:
if (getDestinationImageId().equals(Guid.Empty)) {
throw new RuntimeException();
}
}
else {
return false;
}
} catch (java.lang.Exception e) {
log.errorFormat(
"CreateSnapshotCommand::CreateSnapshotInIrsServer::Failed creating snapshot from image id -'{0}'",
getImage().getId());
throw new VdcBLLException(VdcBllErrors.VolumeCreationError);
}
return true;
}
@Override
protected Guid ConcreteCreateTask(AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) {
VdcActionParametersBase parametersForTask = getParametersForTask(parentCommand, getParameters());
AsyncTaskParameters p =
new AsyncTaskParameters(asyncTaskCreationInfo, new async_tasks(parentCommand,
AsyncTaskResultEnum.success,
AsyncTaskStatusEnum.running,
asyncTaskCreationInfo.getTaskID(),
parametersForTask));
p.setEntityId(getParameters().getEntityId());
Guid ret = AsyncTaskManager.getInstance().CreateTask(AsyncTaskType.createVolume, p, false);
//
// VmId != Guid.Empty ? VmId :
// ImageContainerId != Guid.Empty ? ImageContainerId :
// DbFacade.Instance.GetVmByImageId(DiskImage.image_guid).vm_guid),
//
return ret;
}
/**
* By default old image must be replaced by new one
*/
protected void ProcessOldImageFromDb() {
// removing the old C drive from image table
/**
* Vitaly TODO: check if can use Image variable
*/
if (!StringHelper.EqOp(mDescription, "")) {
getParameters().setOldDescription(getImage().getdescription());
getImage().setdescription(mDescription);
}
getParameters().setOldLastModifiedValue(getDiskImage().getlastModified());
getDiskImage().setlastModified(getNow());
DbFacade.getInstance().getDiskImageDAO().update(getDiskImage());
DbFacade.getInstance()
.getImageVmMapDAO()
.remove(new image_vm_map_id(getImage().getId(), getImageContainerId()));
}
@Override
protected void EndWithFailure() {
RevertTasks();
if (getDestinationDiskImage() != null
&& DbFacade.getInstance().getVmStaticDAO().get(getDestinationDiskImage().getcontainer_guid()) != null) {
DbFacade.getInstance()
.getImageVmMapDAO()
.remove(new image_vm_map_id(
getDestinationImageId(), getDestinationDiskImage().getcontainer_guid()));
// Empty Guid, means new disk rather than snapshot, so no need to add a map to the db for new disk.
if (!getDestinationDiskImage().getParentId().equals(Guid.Empty)) {
DbFacade.getInstance().getImageVmMapDAO().save(
new image_vm_map(true, getDestinationDiskImage().getParentId(), getDestinationDiskImage()
.getcontainer_guid()));
if (!getDestinationDiskImage().getParentId().equals(getDestinationDiskImage().getit_guid())) {
// If the old description of the snapshot got overriden, we should restore the previous description
if (getParameters().getOldDescription() != null
&& !getParameters().getDescription().equals(getParameters().getOldDescription())) {
DiskImage previousSnapshot =
DbFacade.getInstance().getDiskImageDAO().get(getDestinationDiskImage().getParentId());
previousSnapshot.setdescription(getParameters().getOldDescription());
previousSnapshot.setlastModified(getParameters().getOldLastModifiedValue());
DbFacade.getInstance().getDiskImageDAO().update(previousSnapshot);
}
}
}
}
super.EndWithFailure();
}
private static LogCompat log = LogFactoryCompat.getLog(CreateSnapshotCommand.class);
}