package org.ovirt.engine.core.bll.snapshots; import javax.inject.Inject; import org.ovirt.engine.core.bll.InternalCommandAttribute; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.CreateSnapshotFromTemplateParameters; import org.ovirt.engine.core.common.action.RemoveImageParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.asynctasks.EntityInfo; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.ImageDbOperationScope; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.BaseDiskDao; import org.ovirt.engine.core.dao.DiskImageDynamicDao; /** * This command responsible to creating new snapshot. Usually it will be called * during new vm creation. In the case of create snapshot from template new * image created from master image aka image template so new created image * it_guid will be equal to master image guid. * * Parameters: Guid imageId - id of ImageTemplate, snapshot will be created from * Guid containerId - id of VmTemplate, contains ImageTemplate */ @InternalCommandAttribute public class CreateSnapshotFromTemplateCommand<T extends CreateSnapshotFromTemplateParameters> extends CreateSnapshotCommand<T> { @Inject private BaseDiskDao baseDiskDao; @Inject private DiskImageDynamicDao diskImageDynamicDao; public CreateSnapshotFromTemplateCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); super.setVmId(parameters.getVmId()); setImageGroupId(Guid.newGuid()); } public CreateSnapshotFromTemplateCommand(Guid guid) { super(guid); } /** * Old image not have to be changed */ @Override protected void processOldImageFromDb() { } @Override protected DiskImage cloneDiskImage(Guid newImageGuid) { DiskImage returnValue = super.cloneDiskImage(newImageGuid); returnValue.setImageTemplateId(getImage().getImageId()); return returnValue; } @Override protected Guid getDestinationStorageDomainId() { Guid storageDomainId = getParameters().getDestStorageDomainId(); if (getParameters().getDestinationImageId() == null || Guid.Empty.equals(getParameters().getDestStorageDomainId())) { storageDomainId = getParameters().getStorageDomainId(); } storageDomainId = (storageDomainId == null) ? Guid.Empty : storageDomainId; return !Guid.Empty.equals(storageDomainId) ? storageDomainId : super.getDestinationStorageDomainId(); } @Override protected void endWithFailure() { if (getDestinationDiskImage() != null) { //TODO: removeImage() is under that condition as it will perform only if the disk exits in the db. // The flow should be changed so that the disk is added in transaction and then the copy flow is initiated. // The disk should be removed from the db only in case of successful removal (otherwise it should remain // illegal to let the user attempt to delete it again). removeImage(); baseDiskDao.remove(getDestinationDiskImage().getId()); if (diskImageDynamicDao.get(getDestinationDiskImage().getImageId()) != null) { diskImageDynamicDao.remove(getDestinationDiskImage().getImageId()); } } super.endWithFailure(); } private void removeImage() { RemoveImageParameters removeImageParams = new RemoveImageParameters(getParameters().getDestinationImageId()); removeImageParams.setStorageDomainId(getDestinationStorageDomainId()); removeImageParams.setDbOperationScope(ImageDbOperationScope.NONE); removeImageParams.setShouldLockImage(false); removeImageParams.setEntityInfo(new EntityInfo(VdcObjectType.Disk, getDestinationDiskImage().getId())); VdcReturnValueBase returnValue = runInternalActionWithTasksContext( VdcActionType.RemoveImage, removeImageParams); if (!returnValue.getSucceeded()) { addAuditLogOnRemoveFailure(); } } private void addAuditLogOnRemoveFailure() { addCustomValue("DiskAlias", getParameters().getDiskAlias()); AuditLogType logType = AuditLogType.USER_COPY_IMAGE_GROUP_FAILED_TO_DELETE_DST_IMAGE; auditLogDirector.log(this, logType); } @Override protected void revertTasks() { } }