package org.ovirt.engine.core.bll; import org.ovirt.engine.core.common.action.CreateImageTemplateParameters; 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.CopyVolumeType; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.DiskImageDynamic; import org.ovirt.engine.core.common.businessentities.DiskImageTemplate; import org.ovirt.engine.core.common.businessentities.async_tasks; import org.ovirt.engine.core.common.vdscommands.CopyImageVDSCommandParameters; 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.dal.dbbroker.DbFacade; /** * This command responcible to create new Image Template from image. */ @InternalCommandAttribute public class CreateImageTemplateCommand<T extends CreateImageTemplateParameters> extends BaseImagesCommand<T> { public CreateImageTemplateCommand(T parameters) { super(parameters); super.setVmTemplateId(parameters.getVmTemplateId()); super.setVmTemplateName(parameters.getVmTemplateName()); } @Override protected Guid getImageContainerId() { return getParameters() != null ? getParameters().getVmTemplateId() : super.getImageContainerId(); } @Override protected String CalculateImageDescription() { return String.format("_%1$s_%2$s_template", getVmTemplateName(), new java.util.Date()); } @Override protected void executeCommand() { super.executeCommand(); Guid storagePoolId = getDiskImage().getstorage_pool_id() != null ? getDiskImage().getstorage_pool_id() .getValue() : Guid.Empty; Guid imageGroupId = getDiskImage().getimage_group_id() != null ? getDiskImage().getimage_group_id().getValue() : Guid.Empty; Guid snapshotId = getDiskImage().getId(); // Create new image group id and image id: Guid destinationImageGroupID = Guid.NewGuid(); setDestinationImageId(Guid.NewGuid()); getDiskImage().getSnapshots().addAll( ImagesHandler.getAllImageSnapshots(getDiskImage().getId(), getDiskImage().getit_guid())); setDiskImage(getDiskImage().getSnapshots().get(getDiskImage().getSnapshots().size() - 1)); DiskImage newImage = CloneDiskImage(getDestinationImageId()); newImage.setstorage_id(getParameters().getDestinationStorageDomainId()); fillVolumeInformation(newImage); VDSReturnValue vdsReturnValue = Backend .getInstance() .getResourceManager() .RunVdsCommand( VDSCommandType.CopyImage, new CopyImageVDSCommandParameters(storagePoolId, getParameters().getStorageDomainId(), getParameters().getVmId(), imageGroupId, snapshotId, destinationImageGroupID, getDestinationImageId(), newImage.getdescription(), getParameters() .getDestinationStorageDomainId(), CopyVolumeType.SharedVol, newImage .getvolume_format(), newImage.getvolume_type(), getDiskImage() .getwipe_after_delete(), false, getStoragePool().getcompatibility_version() .toString())); getReturnValue().getInternalTaskIdList().add( CreateTask(vdsReturnValue.getCreationInfo(), VdcActionType.AddVmTemplate)); newImage.setimage_group_id(destinationImageGroupID); newImage.setvm_snapshot_id(getParameters().getVmSnapshotId()); newImage.setParentId(ImagesHandler.BlankImageTemplateId); newImage.setit_guid(ImagesHandler.BlankImageTemplateId); // Note ImageGuid copied to DiskImage template twise due bug: // 1. as vtmid_guid // 2. as it_guid // TODO: review it after bug will be fixed DiskImageTemplate dt = new DiskImageTemplate(newImage.getId(), getImageContainerId(), newImage.getinternal_drive_mapping(), newImage.getId(), "", "", getNow(), newImage.getactual_size(), newImage.getdescription(), null); DbFacade.getInstance().getDiskImageTemplateDAO().save(dt); DbFacade.getInstance().getDiskImageDAO().save(newImage); DiskImageDynamic diskDynamic = new DiskImageDynamic(); diskDynamic.setId(newImage.getId()); diskDynamic.setactual_size(getDiskImage().getactual_size()); DbFacade.getInstance().getDiskImageDynamicDAO().save(diskDynamic); // set source image as locked: LockImage(); setSucceeded(true); } /** * Fill the volume information from the image ancestor (if available, if not then from the father image). * * @param disk * The disk to fill the volume details in. */ private void fillVolumeInformation(DiskImage disk) { DiskImage ancestor = DbFacade.getInstance().getDiskImageDAO().getAncestor(getDiskImage().getId()); if (ancestor == null) { log.warnFormat("Can't find ancestor of Disk with ID {0}, using original disk for volume info.", getDiskImage().getId()); ancestor = getDiskImage(); } disk.setvolume_format(ancestor.getvolume_format()); disk.setvolume_type(ancestor.getvolume_type()); } @Override protected Guid ConcreteCreateTask(AsyncTaskCreationInfo asyncTaskCreationInfo, VdcActionType parentCommand) { VdcActionParametersBase paramsForTask = getParametersForTask(parentCommand,getParameters()); AsyncTaskParameters p = new AsyncTaskParameters(asyncTaskCreationInfo, new async_tasks(parentCommand, AsyncTaskResultEnum.success, AsyncTaskStatusEnum.running, asyncTaskCreationInfo.getTaskID(), paramsForTask)); p.setEntityId(getParameters().getEntityId()); Guid ret = AsyncTaskManager.getInstance().CreateTask(AsyncTaskType.copyImage, p, false); return ret; } @Override protected void EndWithFailure() { UnLockImage(); setVmTemplate(DbFacade.getInstance().getVmTemplateDAO() .get(getVmTemplateId())); DbFacade.getInstance().getDiskImageTemplateDAO().remove(getDestinationImageId()); DbFacade.getInstance().getDiskImageDAO().remove(getDestinationImageId()); if (getDestinationDiskImage() != null) { if (DbFacade.getInstance().getDiskImageDynamicDAO().get(getDestinationDiskImage().getId()) != null) { DbFacade.getInstance().getDiskImageDynamicDAO().remove(getDestinationDiskImage().getId()); } } setSucceeded(true); } }