private boolean removeVm() {
    final List<DiskImage> diskImages =
        DisksFilter.filterImageDisks(getVm().getDiskList(), ONLY_NOT_SHAREABLE, ONLY_ACTIVE);

    final List<LunDisk> lunDisks =
        DisksFilter.filterLunDisks(getVm().getDiskMap().values(), ONLY_NOT_SHAREABLE);

    for (VmNic nic : getInterfaces()) {
      new ExternalNetworkManager(nic).deallocateIfExternal();
    }

    removeMemoryVolumes();

    TransactionSupport.executeInNewTransaction(
        () -> {
          removeVmFromDb();
          if (getParameters().isRemoveDisks()) {
            for (DiskImage image : diskImages) {
              getCompensationContext().snapshotEntityStatus(image.getImage(), ImageStatus.ILLEGAL);
              ImagesHandler.updateImageStatus(image.getImage().getId(), ImageStatus.LOCKED);
            }

            for (LunDisk lunDisk : lunDisks) {
              ImagesHandler.removeLunDisk(lunDisk);
            }

            getCompensationContext().stateChanged();
          } else {
            for (DiskImage image : diskImages) {
              imageDao.updateImageVmSnapshotId(image.getImageId(), null);
            }
          }
          return null;
        });

    Collection<DiskImage> unremovedDisks = Collections.emptyList();
    if (getParameters().isRemoveDisks()) {
      if (!diskImages.isEmpty()) {
        unremovedDisks = removeVmImages(diskImages).getActionReturnValue();
      }
      unremovedDisks.addAll(removeCinderDisks());
      if (!unremovedDisks.isEmpty()) {
        processUnremovedDisks(unremovedDisks);
        return false;
      }
    }

    vmDeleted.fire(getVmId());
    return true;
  }
 /**
  * Add image and related entities to DB (Adds image, disk image dynamic and image storage domain
  * map)
  *
  * @param image the image to add
  * @param active if true the image will be active
  * @param imageStorageDomainMap entry of mapping between the storage domain and the image
  */
 public static void addImage(
     DiskImage image, boolean active, ImageStorageDomainMap imageStorageDomainMap) {
   image.setActive(active);
   DbFacade.getInstance().getImageDao().save(image.getImage());
   DiskImageDynamic diskDynamic = new DiskImageDynamic();
   diskDynamic.setId(image.getImageId());
   diskDynamic.setActualSize(image.getActualSizeInBytes());
   DbFacade.getInstance().getDiskImageDynamicDao().save(diskDynamic);
   if (imageStorageDomainMap != null) {
     DbFacade.getInstance().getImageStorageDomainMapDao().save(imageStorageDomainMap);
   }
 }
  public static void updateAllDiskImagesSnapshotsStatusInTransactionWithCompensation(
      final Collection<Guid> diskIds,
      final ImageStatus status,
      ImageStatus statusForCompensation,
      final CompensationContext compensationContext) {
    if (compensationContext != null) {
      for (Guid diskId : diskIds) {
        List<DiskImage> diskSnapshots =
            DbFacade.getInstance().getDiskImageDao().getAllSnapshotsForImageGroup(diskId);
        for (DiskImage diskSnapshot : diskSnapshots) {
          diskSnapshot.setImageStatus(statusForCompensation);
          compensationContext.snapshotEntityStatus(diskSnapshot.getImage());
        }
      }

      TransactionSupport.executeInScope(
          TransactionScopeOption.Required,
          () -> {
            for (Guid diskId : diskIds) {
              DbFacade.getInstance()
                  .getImageDao()
                  .updateStatusOfImagesByImageGroupId(diskId, status);
            }
            compensationContext.stateChanged();
            return null;
          });
    } else {

      TransactionSupport.executeInScope(
          TransactionScopeOption.Required,
          () -> {
            for (Guid diskId : diskIds) {
              updateAllDiskImageSnapshotsStatus(diskId, status);
            }
            return null;
          });
    }
  }
  /**
   * After merging the snapshots, update the image and snapshot records in the database to reflect
   * the changes. This handles either forward or backwards merge (detected). It will either then
   * remove the images, or mark them illegal (to handle the case where image deletion failed).
   *
   * @param removeImages Remove the images from the database, or if false, only mark them illegal
   */
  private void syncDbRecords(boolean removeImages) {
    // If deletion failed after a backwards merge, the snapshots' images need to be swapped
    // as they would upon success.  Instead of removing them, mark them illegal.
    DiskImage baseImage = getDiskImage();
    DiskImage topImage = getDestinationDiskImage();

    // The vdsm merge verb may decide to perform a forward or backward merge.
    if (topImage == null) {
      log.debug("No merge destination image, not updating image/snapshot association");
    } else if (getParameters().getMergeStatusReturnValue().getBlockJobType()
        == VmBlockJobType.PULL) {
      // For forward merge, the volume format and type may change.
      topImage.setvolumeFormat(baseImage.getVolumeFormat());
      topImage.setVolumeType(baseImage.getVolumeType());
      topImage.setParentId(baseImage.getParentId());
      topImage.setImageStatus(ImageStatus.OK);

      getBaseDiskDao().update(topImage);
      getImageDao().update(topImage.getImage());
      updateDiskImageDynamic(topImage);

      updateVmConfigurationForImageRemoval(
          baseImage.getImage().getSnapshotId(), baseImage.getImageId());
    } else {
      // For backwards merge, the prior base image now has the data associated with the newer
      // snapshot we want to keep.  Re-associate this older image with the newer snapshot.
      // The base snapshot is deleted if everything went well.  In case it's not deleted, we
      // hijack it to preserve a link to the broken image.  This makes the image discoverable
      // so that we can retry the deletion later, yet doesn't corrupt the VM image chain.
      List<DiskImage> children =
          DbFacade.getInstance().getDiskImageDao().getAllSnapshotsForParent(topImage.getImageId());
      if (!children.isEmpty()) {
        DiskImage childImage = children.get(0);
        childImage.setParentId(baseImage.getImageId());
        getImageDao().update(childImage.getImage());
      }

      Image oldTopImage = topImage.getImage();
      topImage.setImage(baseImage.getImage());
      baseImage.setImage(oldTopImage);

      Guid oldTopSnapshotId = topImage.getImage().getSnapshotId();
      topImage.getImage().setSnapshotId(baseImage.getImage().getSnapshotId());
      baseImage.getImage().setSnapshotId(oldTopSnapshotId);

      boolean oldTopIsActive = topImage.getImage().isActive();
      topImage.getImage().setActive(baseImage.getImage().isActive());
      VolumeClassification baseImageVolumeClassification =
          VolumeClassification.getVolumeClassificationByActiveFlag(baseImage.getImage().isActive());
      topImage.getImage().setVolumeClassification(baseImageVolumeClassification);
      baseImage.getImage().setActive(oldTopIsActive);
      VolumeClassification oldTopVolumeClassification =
          VolumeClassification.getVolumeClassificationByActiveFlag(oldTopIsActive);
      topImage.getImage().setVolumeClassification(oldTopVolumeClassification);

      topImage.setSize(baseImage.getSize());
      topImage.setImageStatus(ImageStatus.OK);
      getBaseDiskDao().update(topImage);
      getImageDao().update(topImage.getImage());
      updateDiskImageDynamic(topImage);

      getBaseDiskDao().update(baseImage);
      getImageDao().update(baseImage.getImage());

      updateVmConfigurationForImageChange(
          topImage.getImage().getSnapshotId(), baseImage.getImageId(), topImage);
      updateVmConfigurationForImageRemoval(
          baseImage.getImage().getSnapshotId(), topImage.getImageId());
    }

    Set<Guid> imagesToUpdate = getParameters().getMergeStatusReturnValue().getImagesToRemove();
    if (imagesToUpdate == null) {
      log.error("Failed to update orphaned images in db: image list could not be retrieved");
      return;
    }
    for (Guid imageId : imagesToUpdate) {
      if (removeImages) {
        getImageDao().remove(imageId);
      } else {
        // The (illegal && no-parent && no-children) status indicates an orphaned image.
        Image image = getImageDao().get(imageId);
        image.setStatus(ImageStatus.ILLEGAL);
        image.setParentId(Guid.Empty);
        getImageDao().update(image);
      }
    }
  }