private void updateTags(final List<String> images) throws Exception {
   for (final String imageId : images) {
     try {
       final ImageInfo image = Images.lookupImage(imageId);
       final ImageMetadata.State imgState = image.getState();
       final String taskId = ((MachineImageInfo) image).getImageConversionId();
       if (ImageMetadata.State.pending_available.equals(
           imgState)) {; // do nothing for images not yet in conversion
       } else if (ImageMetadata.State.pending_conversion.equals(imgState)) {
         String message = "";
         try {
           Optional<DiskImageConversionTask> task = conversionTaskCache.get(taskId);
           if (task.isPresent()) {
             message = task.get().getStatusMessage();
           }
         } catch (final Exception ex) {;
         }
         // if needed, we can add messages as well; not sure yet if the messages are clear
         this.tagResources(imageId, "active", message);
         taggedImages.add(imageId);
       } else if (ImageMetadata.State.available.equals(imgState)
           && taggedImages.contains(imageId)) {
         try {
           this.removeTags(imageId);
         } catch (final Exception ex) {;
         } finally {
           taggedImages.remove(imageId);
         }
       }
     } catch (final Exception ex) {
       LOG.error("Failed to update tags for resources in conversion", ex);
     }
   }
 }
  private void removeTags(final String imageId) throws Exception {
    final ImageInfo image = Images.lookupImage(imageId);
    final String imageOwnerId = image.getOwnerUserId();

    DeleteTagsTask task =
        new DeleteTagsTask(
            imageOwnerId,
            Lists.newArrayList(image.getDisplayName()),
            Lists.newArrayList(TAG_KEY_STATE, TAG_KEY_MESSAGE));
    CheckedListenableFuture<Boolean> result = task.dispatch();
    if (result.get()) {;
    }
    final List<VmInstance> instances = this.lookupInstances(imageId);
    for (final VmInstance instance : instances) {
      final String instanceId = instance.getInstanceId();
      final String instanceOwnerId = instance.getOwnerUserId();
      try {
        task =
            new DeleteTagsTask(
                instanceOwnerId,
                Lists.newArrayList(instanceId),
                Lists.newArrayList(TAG_KEY_STATE, TAG_KEY_MESSAGE));
        result = task.dispatch();
        if (result.get()) {;
        }
      } catch (final Exception ex) {;
      }
    }
  }
  private void resetImagePendingAvailable(final String imageId, final String reason) {
    String taskMessage = "";
    /// tag image and instances with proper message
    try {
      final ImageInfo image = Images.lookupImage(imageId);
      final String taskId = ((MachineImageInfo) image).getImageConversionId();
      if (taskId != null) {
        conversionTaskCache.invalidate(taskId);
        Optional<DiskImageConversionTask> task = conversionTaskCache.get(taskId);
        if (task.isPresent()) taskMessage = task.get().getStatusMessage();
      }
      final String tagMessage = reason != null ? reason : taskMessage;
      this.tagResources(imageId, "failed", tagMessage);
    } catch (final Exception ex) {;
    } finally {
      taggedImages.remove(imageId);
    }

    try (final TransactionResource db = Entities.transactionFor(ImageInfo.class)) {
      try {
        final ImageInfo entity = Entities.uniqueResult(Images.exampleWithImageId(imageId));
        entity.setState(ImageMetadata.State.pending_available);
        entity.setImageFormat(ImageMetadata.ImageFormat.partitioned.name());
        ((MachineImageInfo) entity).setImageConversionId(null);
        Entities.persist(entity);
        db.commit();
      } catch (final Exception ex) {
        LOG.error("Failed to mark the image state available for conversion: " + imageId, ex);
      }
    }
  }
 private void updateTags(final List<String> images) throws Exception {
   for (final String imageId : images) {
     try {
       final ImageInfo image = Images.lookupImage(imageId);
       final ImageMetadata.State imgState = image.getState();
       final String taskId = ((MachineImageInfo) image).getImageConversionId();
       if (ImageMetadata.State.pending_available.equals(
           imgState)) {; // do nothing for images not yet in conversion
       } else if (ImageMetadata.State.pending_conversion.equals(imgState)) {
         String message = "";
         try {
           Optional<DiskImageConversionTask> task = conversionTaskCache.get(taskId);
           if (task.isPresent()) {
             message = task.get().getStatusMessage();
           }
         } catch (final Exception ex) {;
         }
         // if needed, we can add messages as well; not sure yet if the messages are clear
         this.tagResources(imageId, "active", message);
         taggedImages.add(imageId);
       } else if (ImageMetadata.State.available.equals(imgState)
           && taggedImages.contains(imageId)) {
         try {
           this.removeTags(imageId);
         } catch (final Exception ex) {;
         } finally {
           taggedImages.remove(imageId);
         }
       } else if (ImageMetadata.State.failed.equals(imgState) && taggedImages.contains(imageId)) {
         String message = "";
         try {
           conversionTaskCache.invalidate(taskId);
           Optional<DiskImageConversionTask> task = conversionTaskCache.get(taskId);
           if (task.isPresent()) message = task.get().getStatusMessage();
         } catch (final Exception ex) {;
         } finally {
           taggedImages.remove(imageId);
         }
         this.tagResources(imageId, "failed", message);
         try (final TransactionResource db = Entities.transactionFor(ImageInfo.class)) {
           try {
             final ImageInfo entity = Entities.uniqueResult(Images.exampleWithImageId(imageId));
             entity.setState(ImageMetadata.State.pending_available);
             entity.setImageFormat(ImageMetadata.ImageFormat.partitioned.name());
             ((MachineImageInfo) entity).setImageConversionId(null);
             Entities.persist(entity);
             db.commit();
           } catch (final Exception ex) {
             LOG.error("Failed to mark the image state available for conversion", ex);
           }
         }
       }
     } catch (final Exception ex) {
       LOG.error("Failed to update tags for resources in conversion", ex);
     }
   }
 }
  /**
   * @see com.eucalyptus.util.Mappable#getName()
   * @see com.eucalyptus.cloud.UserMetadata#equals(java.lang.Object)
   * @param o
   * @return
   */
  @Override
  public boolean equals(final Object o) {
    if (this == o) return true;
    if ((o == null) || (this.getClass() != o.getClass())) return false;

    final ImageInfo imageInfo = (ImageInfo) o;

    if (!this.getDisplayName().equals(imageInfo.getDisplayName())) return false;

    return true;
  }
 @SuppressWarnings("unchecked")
 public ImageInfo grantPermission(final Account account) {
   EntityTransaction db = Entities.get(ImageInfo.class);
   try {
     ImageInfo entity = Entities.merge(this);
     entity.getPermissions().add(account.getAccountNumber());
     db.commit();
   } catch (Exception ex) {
     Logs.exhaust().error(ex, ex);
     db.rollback();
   }
   return this;
 }
  public boolean addProductCode(final String prodCode) {

    EntityTransaction db = Entities.get(ImageInfo.class);
    try {
      ImageInfo entity = Entities.merge(this);
      entity.getProductCodes().add(prodCode);
      db.commit();
      return true;
    } catch (Exception ex) {
      Logs.exhaust().error(ex, ex);
      db.rollback();
      return false;
    }
  }
  private void tagResources(final String imageId, final String state, String statusMessage)
      throws Exception {
    final ImageInfo image = Images.lookupImage(imageId);
    final String imageOwnerId = image.getOwnerUserId();

    final List<VmInstance> instances = this.lookupInstances(imageId);
    if (tagState.containsKey(imageId) && state.equals(tagState.get(imageId))) {;
    } else {
      resetTag(imageOwnerId, imageId, TAG_KEY_STATE, state);
      tagState.put(imageId, state);
    }
    for (final VmInstance instance : instances) {
      final String instanceId = instance.getInstanceId();
      final String instanceOwnerId = instance.getOwnerUserId();
      if (tagState.containsKey(instanceId) && state.equals(tagState.get(instanceId))) {;
      } else {
        resetTag(instanceOwnerId, instanceId, TAG_KEY_STATE, state);
        tagState.put(instanceId, state);
      }
    }

    if (statusMessage == null) statusMessage = "";

    if (tagMessage.containsKey(imageId) && statusMessage.equals(tagMessage.get(imageId))) {;
    } else {
      resetTag(imageOwnerId, imageId, TAG_KEY_MESSAGE, statusMessage);
      tagMessage.put(imageId, statusMessage);
    }
    for (final VmInstance instance : instances) {
      final String instanceId = instance.getInstanceId();
      final String instanceOwnerId = instance.getOwnerUserId();
      if (tagMessage.containsKey(instanceId) && statusMessage.equals(tagMessage.get(instanceId))) {;
      } else {
        resetTag(instanceOwnerId, instanceId, TAG_KEY_MESSAGE, statusMessage);
        tagMessage.put(instanceId, statusMessage);
      }
    }
  }
 public ImageInfo resetProductCodes() {
   try {
     Transactions.one(
         ImageInfo.self(this),
         new Callback<ImageInfo>() {
           @Override
           public void fire(final ImageInfo t) {
             t.getProductCodes().clear();
           }
         });
   } catch (final ExecutionException e) {
     LOG.debug(e, e);
   }
   return this;
 }
 static ImageInfo self(final ImageInfo image) {
   return new ImageInfo(image.getDisplayName());
 }
  private void checkConversion(final List<ImageInfo> images) {
    for (final ImageInfo image : images) {
      if (!(image instanceof MachineImageInfo)) continue;
      try {
        final MachineImageInfo machineImage = (MachineImageInfo) image;
        final String taskId = machineImage.getImageConversionId();
        if (taskId == null || taskId.length() <= 0)
          throw new Exception(
              "Image " + machineImage.getDisplayName() + " has no conversion task Id");

        final DescribeConversionTasks task =
            new DescribeConversionTasks(Lists.newArrayList(machineImage.getImageConversionId()));

        final CheckedListenableFuture<Boolean> result = task.dispatch();
        List<DiskImageConversionTask> ctasks = null;
        if (result.get()) {
          ctasks = task.getTasks();
        }
        boolean conversionSuccess = true;
        String errorMessage = null;
        if (ctasks.size() <= 0) {
          /// consider this task as done when describe tasks has no result
          conversionSuccess = true;
        } else {
          DiskImageConversionTask ct = ctasks.get(0);
          if ("completed".equals(ct.getState())) {
            conversionSuccess = true;
          } else if ("active".equals(ct.getState())) {
            continue;
          } else {
            conversionSuccess = false;
            errorMessage = ct.getStatusMessage();
          }
        }
        if (conversionSuccess) {
          /// if user deregistered the image while in conversion
          if (ImageMetadata.State.deregistered_cleanup.equals(image.getState())) {
            try {
              this.cleanupBuckets(Lists.newArrayList(image), true);
            } catch (final Exception ex) {;
            }
          } else {
            Images.setImageFormat(
                machineImage.getDisplayName(), ImageMetadata.ImageFormat.fulldisk);
            /// the service and the backend (NC) rely on virtualizationType=HVM when they prepare
            // full-disk type instances
            Images.setImageState(machineImage.getDisplayName(), ImageMetadata.State.available);
            try {
              generateDownloadManifests(machineImage.getDisplayName());
            } catch (final Exception ex) {;
            }
          }
        } else {
          LOG.warn(
              "Conversion task for image "
                  + image.getDisplayName()
                  + " has failed: "
                  + errorMessage);
          try {
            this.cleanupBuckets(Lists.newArrayList(image), false);
            this.resetImagePendingAvailable(image.getDisplayName(), null);
          } catch (final Exception ex) {
            LOG.error(
                "Failed to cleanup the image's system bucket; setting image state failed: "
                    + image.getDisplayName());
            Images.setImageState(machineImage.getDisplayName(), ImageMetadata.State.failed);
          }
        }
      } catch (final Exception ex) {
        LOG.warn("Conversion task for image " + image.getDisplayName() + " has failed: ", ex);
        try {
          this.cleanupBuckets(Lists.newArrayList(image), false);
          this.resetImagePendingAvailable(
              image.getDisplayName(), "Failed to check conversion status");
        } catch (final Exception ex2) {
          LOG.error(
              "Failed to cleanup the image's system bucket; setting image state failed: "
                  + image.getDisplayName());
          try {
            Images.setImageState(image.getDisplayName(), ImageMetadata.State.failed);
          } catch (final Exception ex3) {;
          }
        }
      }
    }
  }
  private void convertImages(final List<ImageInfo> images) {
    for (final ImageInfo image : images) {
      if (!(image instanceof MachineImageInfo)) continue;
      try {
        final MachineImageInfo machineImage = (MachineImageInfo) image;
        final String kernelId = machineImage.getKernelId();
        final String ramdiskId = machineImage.getRamdiskId();
        if (kernelId == null || ramdiskId == null) {
          LOG.warn(
              String.format(
                  "Kernel and ramdisk are not found for the image %s", image.getDisplayName()));
          continue;
        }

        final KernelImageInfo kernel = Images.lookupKernel(kernelId);
        final RamdiskImageInfo ramdisk = Images.lookupRamdisk(ramdiskId);
        final ServiceConfiguration osg = Topology.lookup(ObjectStorage.class);
        final URI osgUri = osg.getUri();
        final String osgPrefix =
            String.format(
                "%s://%s:%d%s",
                osgUri.getScheme(), osgUri.getHost(), osgUri.getPort(), osgUri.getPath());

        final String kernelManifest =
            String.format("%s/%s", osgPrefix, kernel.getManifestLocation());
        final String ramdiskManifest =
            String.format("%s/%s", osgPrefix, ramdisk.getManifestLocation());
        final String machineManifest =
            String.format("%s/%s", osgPrefix, machineImage.getManifestLocation());
        final String[] tokens = machineImage.getRunManifestLocation().split("/");
        final String bucket = tokens[0];
        final String prefix = tokens[1].replace(".manifest.xml", "");

        String taskId = null;
        try {
          final ImportImageBuilder builder = new ImportImageBuilder();
          final ImportImageTask task =
              new ImportImageTask(
                  builder
                      .withArchitecture(machineImage.getArchitecture().name())
                      .withBucket(bucket)
                      .withPrefix(prefix)
                      .withKernel(
                          kernel.getDisplayName(), kernelManifest, kernel.getImageSizeBytes())
                      .withRamdisk(
                          ramdisk.getDisplayName(), ramdiskManifest, ramdisk.getImageSizeBytes())
                      .withMachineImage(
                          machineImage.getDisplayName(),
                          machineManifest,
                          machineImage.getImageSizeBytes())
                      .withBucketUploadPolicy(bucket, prefix));
          final CheckedListenableFuture<Boolean> result = task.dispatch();
          if (result.get()) {
            taskId = task.getTaskId();
          }
        } catch (final Exception ex) {
          throw ex;
        }
        if (taskId == null) throw new Exception("ImportImage Task id is null");
        Images.setConversionTaskId(machineImage.getDisplayName(), taskId);
      } catch (final Exception ex) {
        LOG.error("Failed to convert the image: " + image.getDisplayName(), ex);
        try {
          this.cleanupBuckets(Lists.newArrayList(image), false);
          resetImagePendingAvailable(image.getDisplayName(), "Failed to request conversion");
        } catch (final Exception ex2) {
          LOG.error(
              "Failed to cleanup the image's system bucket; setting image state failed: "
                  + image.getDisplayName());
          try {
            Images.setImageState(image.getDisplayName(), ImageMetadata.State.failed);
          } catch (final Exception ex3) {;
          }
        }
      }
    }
  }
  private void cleanupBuckets(final List<ImageInfo> images, boolean deregister) {
    Set<String> systemBuckets = null;
    if (images.size() > 0) {
      try {
        final ListBucketsTask task = new ListBucketsTask();
        final CheckedListenableFuture<Boolean> result = task.dispatch();
        if (result.get()) {
          final List<String> bucketNames = task.getBuckets();
          systemBuckets = Sets.newHashSet();
          systemBuckets.addAll(bucketNames);
        }
      } catch (final Exception ex) {;
      }
    }

    for (final ImageInfo image : images) {
      if (!(image instanceof MachineImageInfo)) continue;
      try {
        final MachineImageInfo machineImage = (MachineImageInfo) image;
        final String runManifestPath = machineImage.getRunManifestLocation();
        final String manifestPath = machineImage.getManifestLocation();

        if (runManifestPath == null || runManifestPath.length() <= 0) continue;
        if (runManifestPath.equals(
            manifestPath)) // should not delete if runManifest is not system-generated one
        continue;

        final String[] tokens = runManifestPath.split("/");
        final String bucket = tokens[0];
        if (!systemBuckets.contains(bucket)) continue;

        final ListObjectsInBucketTask listObjTask = new ListObjectsInBucketTask(bucket);
        CheckedListenableFuture<Boolean> result = listObjTask.dispatch();
        List<String> keysInBucket = null;
        if (result.get()) {
          keysInBucket = listObjTask.getKeyNames();
        } else throw new Exception("Failed to list bucket");

        for (final String key : keysInBucket) {
          final DeleteObjectTask delObjTask = new DeleteObjectTask(bucket, key);
          final CheckedListenableFuture<Boolean> delResult = delObjTask.dispatch();
          if (delResult.get()) {;
          } else {
            throw new Exception("Failed to delete object " + bucket + ":" + key);
          }
        }

        final DeleteBucketTask delBucketTask = new DeleteBucketTask(bucket);
        result = delBucketTask.dispatch();
        if (result.get()) {;
        } else throw new Exception("Failed to delete the bucket " + bucket);

        if (deregister)
          Images.setImageState(image.getDisplayName(), ImageMetadata.State.deregistered);
      } catch (final Exception ex) {
        LOG.error(
            "Failed to cleanup buckets and objects of deregistered image " + image.getDisplayName(),
            ex);
      }
    }
  }
  private void createBuckets(final List<ImageInfo> images) throws Exception {
    Set<String> systemBuckets = null;
    if (images.size() > 0) {
      try {
        final ListBucketsTask task = new ListBucketsTask();
        final CheckedListenableFuture<Boolean> result = task.dispatch();
        if (result.get()) {
          final List<String> bucketNames = task.getBuckets();
          systemBuckets = Sets.newHashSet();
          systemBuckets.addAll(bucketNames);
        }
      } catch (final Exception ex) {
        throw new Exception("Failed to check the existing buckets", ex);
      }
    }

    String newBucket = null;
    for (final ImageInfo image : images) {
      try {
        if (!(image instanceof MachineImageInfo)) continue;
        final MachineImageInfo machineImage = (MachineImageInfo) image;

        final String manifestLocation = machineImage.getManifestLocation();
        final String[] tokens = manifestLocation.split("/");
        final String bucketName = tokens[0];
        final String prefix = tokens[1].replace(".manifest.xml", "");
        do {
          newBucket =
              String.format(
                  "%s-%s-%s", BUCKET_PREFIX, Crypto.generateAlphanumericId(5, ""), bucketName);
          if (newBucket.length() > 63) {
            newBucket = String.format("%s-%s", BUCKET_PREFIX, Crypto.generateAlphanumericId(8, ""));
          }
          newBucket = newBucket.toLowerCase();
        } while (systemBuckets.contains(newBucket));

        try {
          final CreateBucketTask task = new CreateBucketTask(newBucket);
          final CheckedListenableFuture<Boolean> result = task.dispatch();
          if (result.get()) {;
          }
        } catch (final Exception ex) {
          throw new Exception("Failed to create a system-owned bucket for converted image", ex);
        }

        // set run manifest path
        final String runManifestPath = String.format("%s/%s.manifest.xml", newBucket, prefix);
        try {
          machineImage.setRunManifestLocation(runManifestPath);
          Images.setRunManifestLocation(machineImage.getDisplayName(), runManifestPath);
        } catch (final Exception ex) {
          throw new Exception("Failed to update run manifest location");
        }
      } catch (final Exception ex) {
        LOG.error(
            String.format(
                "Unable to create the bucket %s for image %s", newBucket, image.getDisplayName()));
        resetImagePendingAvailable(image.getDisplayName(), "Failed to create bucket");
        throw ex;
      }
    }
  }