package org.ovirt.engine.core.bll.storage.disk.image; import static org.ovirt.engine.core.bll.storage.disk.image.DisksFilter.ONLY_ACTIVE; import static org.ovirt.engine.core.bll.storage.disk.image.DisksFilter.ONLY_NOT_SHAREABLE; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.inject.Inject; import org.ovirt.engine.core.bll.InternalCommandAttribute; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.VmCommand; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.common.action.RemoveAllVmImagesParameters; 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.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainType; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.ImageStatus; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.TransactionScopeOption; import org.ovirt.engine.core.dao.DiskDao; import org.ovirt.engine.core.dao.DiskImageDao; import org.ovirt.engine.core.dao.ImageDao; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.utils.transaction.TransactionSupport; /** * This command removes all Vm images and all created snapshots both from Irs * and Db. */ @InternalCommandAttribute @NonTransactiveCommandAttribute public class RemoveAllVmImagesCommand<T extends RemoveAllVmImagesParameters> extends VmCommand<T> { @Inject private StorageDomainDao storageDomainDao; @Inject private DiskDao diskDao; @Inject private DiskImageDao diskImageDao; @Inject private ImageDao imageDao; public RemoveAllVmImagesCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); } @Override protected void executeVmCommand() { Set<Guid> imagesToBeRemoved = new HashSet<>(); List<DiskImage> images = getParameters().getImages(); if (images == null) { images = DisksFilter.filterImageDisks(diskDao.getAllForVm(getVmId()), ONLY_NOT_SHAREABLE, ONLY_ACTIVE); } for (DiskImage image : images) { if (Boolean.TRUE.equals(image.getActive())) { imagesToBeRemoved.add(image.getImageId()); } } Collection<DiskImage> failedRemoving = new LinkedList<>(); for (final DiskImage image : images) { if (imagesToBeRemoved.contains(image.getImageId())) { VdcReturnValueBase vdcReturnValue = runInternalActionWithTasksContext( VdcActionType.RemoveImage, buildRemoveImageParameters(image) ); if (vdcReturnValue.getSucceeded()) { getReturnValue().getInternalVdsmTaskIdList().addAll(vdcReturnValue.getInternalVdsmTaskIdList()); } else { StorageDomain domain = storageDomainDao.get(image.getStorageIds().get(0)); failedRemoving.add(image); log.error("Can't remove image id '{}' for VM id '{}' from domain id '{}' due to: {}.", image.getImageId(), getParameters().getVmId(), image.getStorageIds().get(0), vdcReturnValue.getFault().getMessage()); if (domain.getStorageDomainType() == StorageDomainType.Data) { log.info("Image id '{}' will be set at illegal state with no snapshot id.", image.getImageId()); TransactionSupport.executeInScope(TransactionScopeOption.Required, () -> { // If VDSM task didn't succeed to initiate a task we change the disk to at illegal // state. updateDiskImagesToIllegal(image); return true; }); } else { log.info("Image id '{}' is not on a data domain and will not be marked as illegal.", image.getImageId()); } } } } setActionReturnValue(failedRemoving); setSucceeded(true); } private RemoveImageParameters buildRemoveImageParameters(DiskImage image) { RemoveImageParameters result = new RemoveImageParameters(image.getImageId()); result.setParentCommand(getParameters().getParentCommand()); result.setParentParameters(getParameters().getParentParameters()); result.setDiskImage(image); result.setEntityInfo(getParameters().getEntityInfo()); result.setForceDelete(getParameters().getForceDelete()); result.setShouldLockImage(false); return result; } /** * Update all disks images of specific disk image to illegal state, and set the vm snapshot id to null, since now * they are not connected to any VM. * * @param diskImage - The disk to update. */ private void updateDiskImagesToIllegal(DiskImage diskImage) { List<DiskImage> snapshotDisks = diskImageDao.getAllSnapshotsForImageGroup(diskImage.getId()); for (DiskImage diskSnapshot : snapshotDisks) { diskSnapshot.setVmSnapshotId(null); diskSnapshot.setImageStatus(ImageStatus.ILLEGAL); imageDao.update(diskSnapshot.getImage()); } } @Override protected void endVmCommand() { setSucceeded(true); } }