package org.ovirt.engine.core.bll; import java.util.List; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.ImagesContainterParametersBase; import org.ovirt.engine.core.common.action.MergeSnapshotParamenters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.errors.VdcBLLException; import org.ovirt.engine.core.common.errors.VdcBllErrors; 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.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.linq.All; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.linq.Predicate; public class MergeSnapshotCommand<T extends MergeSnapshotParamenters> extends VmCommand<T> { public MergeSnapshotCommand(T parameters) { super(parameters); if (getVm() == null) { setVm(DbFacade.getInstance().getVmDAO().getById(getVmId())); setVmId(getVm().getvm_guid()); String name = ""; if (getParameters() != null) { List<DiskImage> images = DbFacade .getInstance() .getDiskImageDAO() .getAllSnapshotsForVmSnapshot( getParameters().getSourceVmSnapshotId()); if (images.size() > 0) { name = images.get(0).getdescription(); } } setSnapshotName(name); } } @Override public Guid getVmId() { if (getParameters() != null) { return getParameters().getVmId(); } return super.getVmId(); } private List<DiskImage> _sourceImages = null; private List<DiskImage> getSourceImages() { if (_sourceImages == null) { _sourceImages = DbFacade .getInstance() .getDiskImageDAO() .getAllSnapshotsForVmSnapshot( getParameters().getSourceVmSnapshotId()); } return _sourceImages; } @Override protected void executeCommand() { if (getVm().getstatus() != VMStatus.Down) { log.error("Cannot merge VM snapshot. Vm is not Down"); throw new VdcBLLException(VdcBllErrors.IRS_IMAGE_STATUS_ILLEGAL); } VmHandler.LockVm(getVm().getDynamicData(), getCompensationContext()); getParameters().setEntityId(getVmId()); List<DiskImage> destImages = null; if (getParameters().getDestVmSnapshotId() != null) { destImages = DbFacade.getInstance().getDiskImageDAO().getAllSnapshotsForVmSnapshot( getParameters().getDestVmSnapshotId().getValue()); } for (final DiskImage source : getSourceImages()) { DiskImage dest; // if the MergeSnapshotParameters.DestImage is null // we assume that the source->parent is the dest if (getParameters().getDestVmSnapshotId() == null) { // The following line is ok because we have tested in the // candoaction that the vm // is not a template and the vm is not in preview mode and that // this is not the active snapshot. dest = DbFacade.getInstance().getDiskImageDAO().getAllSnapshotsForParent(source.getId()).get(0); } else { // LINQ 29456 // dest = destImages.Where(a => a.internal_drive_mapping == // source.internal_drive_mapping).FirstOrDefault(); List<DiskImage> images = LinqUtils.filter(destImages, new Predicate<DiskImage>() { @Override public boolean eval(DiskImage a) { return a.getinternal_drive_mapping().equals(source.getinternal_drive_mapping()); } }); dest = LinqUtils.firstOrNull(images, new All<DiskImage>()); // LINQ 29456 } ImagesContainterParametersBase tempVar = new ImagesContainterParametersBase(source.getId(), source.getinternal_drive_mapping(), getVmId()); tempVar.setDestinationImageId(dest.getId()); tempVar.setEntityId(getParameters().getEntityId()); ImagesContainterParametersBase p = tempVar; VdcReturnValueBase vdcReturnValue = Backend.getInstance().runInternalAction( VdcActionType.MergeSnapshotSingleDisk, p); getParameters().getImagesParameters().add(p); if (vdcReturnValue != null && vdcReturnValue.getInternalTaskIdList() != null) { getReturnValue().getTaskIdList().addAll(vdcReturnValue.getInternalTaskIdList()); } } setSucceeded(true); } @Override protected boolean canDoAction() { // Since 'VmId' is overriden, 'Vm' should be retrieved manually. setVm(DbFacade.getInstance().getVmDAO().getById(getVmId())); getReturnValue().setCanDoAction( ImagesHandler.PerformImagesChecks(getParameters().getVmId(), getReturnValue().getCanDoActionMessages(), getVm().getstorage_pool_id(), getSourceImages().get(0).getstorage_id().getValue(), true, true, true, true, true, true, true)); // check that we are not deleting the template if (DbFacade.getInstance().getVmTemplateDAO().get(getSourceImages().get(0).getId()) != null) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_CANNOT_REMOVE_IMAGE_TEMPLATE); getReturnValue().setCanDoAction(false); } // check that we are not deleting the vm working snapshot if (DbFacade.getInstance().getDiskImageDAO().get(getSourceImages().get(0).getId()) != null) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_CANNOT_REMOVE_ACTIVE_IMAGE); getReturnValue().setCanDoAction(false); } if (!getReturnValue().getCanDoAction()) { addCanDoActionMessage(VdcBllMessages.VAR__TYPE__SNAPSHOT); addCanDoActionMessage(VdcBllMessages.VAR__ACTION__MERGE); } return getReturnValue().getCanDoAction(); } @Override public AuditLogType getAuditLogTypeValue() { switch (getActionState()) { case EXECUTE: return getSucceeded() ? AuditLogType.USER_MERGE_SNAPSHOT : AuditLogType.USER_FAILED_MERGE_SNAPSHOT; case END_SUCCESS: return getSucceeded() ? AuditLogType.USER_MERGE_SNAPSHOT_FINISHED_SUCCESS : AuditLogType.USER_MERGE_SNAPSHOT_FINISHED_FAILURE; default: return AuditLogType.USER_MERGE_SNAPSHOT_FINISHED_FAILURE; } } @Override protected VdcActionType getChildActionType() { return VdcActionType.MergeSnapshotSingleDisk; } private static LogCompat log = LogFactoryCompat.getLog(TryBackToAllSnapshotsOfVmCommand.class); }