/**
  * Remove all illegal disks which were associated with the given snapshot. This is done in order
  * to be able to switch correctly between snapshots where illegal images might be present.
  *
  * @param snapshotId The ID of the snapshot for who to remove illegal images for.
  */
 public void removeAllIllegalDisks(Guid snapshotId) {
   for (DiskImage diskImage : getDiskImageDao().getAllSnapshotsForVmSnapshot(snapshotId)) {
     if (diskImage.getimageStatus() == ImageStatus.ILLEGAL) {
       ImagesHandler.removeDiskImage(diskImage);
     }
   }
 }
  private List<DiskImage> getVmImageDisks() {
    if (cachedVmImageDisks == null) {
      cachedVmImageDisks = ImagesHandler.filterImageDisks(getVmDisks(), true, false, false);
    }

    return cachedVmImageDisks;
  }
  /**
   * Check storage domains. Storage domain status and disk space are checked only for non-HA VMs.
   *
   * @param vm The VM to run
   * @param message The error messages to append to
   * @param isInternalExecution Command is internal?
   * @param vmImages The VM's image disks
   * @return <code>true</code> if the VM can be run, <code>false</code> if not
   */
  protected ValidationResult validateStorageDomains(
      VM vm, boolean isInternalExecution, List<DiskImage> vmImages) {
    if (vmImages.isEmpty()) {
      return ValidationResult.VALID;
    }

    if (!vm.isAutoStartup() || !isInternalExecution) {
      Set<Guid> storageDomainIds = ImagesHandler.getAllStorageIdsForImageIds(vmImages);
      MultipleStorageDomainsValidator storageDomainValidator =
          new MultipleStorageDomainsValidator(vm.getStoragePoolId(), storageDomainIds);

      ValidationResult result = storageDomainValidator.allDomainsExistAndActive();
      if (!result.isValid()) {
        return result;
      }

      result =
          !vm.isAutoStartup()
              ? storageDomainValidator.allDomainsWithinThresholds()
              : ValidationResult.VALID;
      if (!result.isValid()) {
        return result;
      }
    }

    return ValidationResult.VALID;
  }
  /**
   * check that we can create snapshots for all disks return true if all storage domains have enough
   * space to create snapshots for this VM plugged disks
   */
  protected ValidationResult hasSpaceForSnapshots() {
    Set<Guid> sdIds = ImagesHandler.getAllStorageIdsForImageIds(getVmImageDisks());

    MultipleStorageDomainsValidator msdValidator = getStorageDomainsValidator(sdIds);
    ValidationResult retVal = msdValidator.allDomainsWithinThresholds();
    if (retVal == ValidationResult.VALID) {
      return msdValidator.allDomainsHaveSpaceForNewDisks(getVmImageDisks());
    }
    return retVal;
  }
  /**
   * Synchronize the VM's Disks with the images from the snapshot:<br>
   *
   * <ul>
   *   <li>Existing disks are updated.
   *   <li>Disks that don't exist anymore get re-added.
   *       <ul>
   *         <li>If the image is still in the DB, the disk is linked to it.
   *         <li>If the image is not in the DB anymore, the disk will be marked as "broken"
   *       </ul>
   * </ul>
   *
   * @param vmId The VM ID is needed to re-add disks.
   * @param snapshotId The snapshot ID is used to find only the VM disks at the time.
   * @param disksFromSnapshot The disks that existed in the snapshot.
   */
  protected void synchronizeDisksFromSnapshot(
      Guid vmId, Guid snapshotId, Guid activeSnapshotId, List<DiskImage> disksFromSnapshot) {
    List<Guid> diskIdsFromSnapshot = new ArrayList<Guid>();

    // Sync disks that exist or existed in the snapshot.
    for (DiskImage diskImage : disksFromSnapshot) {
      diskIdsFromSnapshot.add(diskImage.getimage_group_id());
      Disk disk = diskImage.getDisk();
      if (getDiskDao().exists(disk.getId())) {
        getDiskDao().update(disk);
      } else {

        // If can't find the image, insert it as illegal so that it can't be used and make the
        // device unplugged.
        if (getDiskImageDao().getSnapshotById(diskImage.getId()) == null) {
          diskImage.setimageStatus(ImageStatus.ILLEGAL);
          diskImage.setvm_snapshot_id(activeSnapshotId);

          ImagesHandler.addImage(
              diskImage,
              true,
              new image_storage_domain_map(diskImage.getId(), diskImage.getstorage_ids().get(0)));
        }

        ImagesHandler.addDiskToVm(disk, vmId);
      }
    }

    // Remove all disks that didn't exist in the snapshot.
    for (VmDevice vmDevice :
        getVmDeviceDao()
            .getVmDeviceByVmIdTypeAndDevice(
                vmId, VmDeviceType.DISK.getName(), VmDeviceType.DISK.getName())) {
      if (!diskIdsFromSnapshot.contains(vmDevice.getDeviceId())) {
        getDiskDao().remove(vmDevice.getDeviceId());
        getVmDeviceDao().remove(vmDevice.getId());
      }
    }
  }