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) {;
      }
    }
  }
 @Override
 public Optional<DiskImageConversionTask> load(String taskId) throws Exception {
   try {
     final DescribeConversionTasks task =
         new DescribeConversionTasks(Lists.newArrayList(taskId));
     final CheckedListenableFuture<Boolean> result = task.dispatch();
     if (result.get()) {
       return Optional.of(task.getTasks().get(0));
     }
   } catch (final Exception ex) {
     LOG.error("Failed to call describe-conversion-task: " + taskId);
   }
   return Optional.absent();
 }
 private void resetTag(
     final String userId, final String resourceId, final String tagKey, final String tagValue)
     throws Exception {
   /// try deleting tags
   try {
     final DeleteTagsTask task =
         new DeleteTagsTask(userId, Lists.newArrayList(resourceId), Lists.newArrayList(tagKey));
     final CheckedListenableFuture<Boolean> result = task.dispatch();
     if (result.get()) {;
     }
   } catch (final Exception ex) {;
   }
   // create tag
   final Map<String, String> tag = Maps.newHashMap();
   tag.put(tagKey, tagValue);
   final CreateTagsTask task = new CreateTagsTask(userId, Lists.newArrayList(resourceId), tag);
   final CheckedListenableFuture<Boolean> result = task.dispatch();
   if (result.get()) {;
   } else
     throw new Exception(
         String.format("Failed to create tag (%s-%s:%s)", resourceId, tagKey, tagValue));
 }
  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;
      }
    }
  }