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;
      }
    }
  }