private void generateDownloadManifests(final String imageId) {
   // lookup all reservations that reference the newly available image id
   final List<VmInstance> pendingInstances =
       VmInstances.list(
           new Predicate<VmInstance>() {
             @Override
             public boolean apply(VmInstance arg0) {
               return imageId.equals(arg0.getBootRecord().getMachineImageId())
                   && VmState.PENDING.equals(arg0.getState());
             }
           });
   for (final VmInstance instance : pendingInstances) {
     final String reservationId = instance.getReservationId();
     final String partitionName = instance.getPartition();
     final Partition partition = Partitions.lookupByName(partitionName);
     final MachineImageInfo machineImage = LookupMachine.INSTANCE.apply(imageId);
     try {
       final String manifestLocation =
           DownloadManifestFactory.generateDownloadManifest(
               new ImageManifestFile(
                   machineImage.getRunManifestLocation(), BundleImageManifest.INSTANCE),
               partition.getNodeCertificate().getPublicKey(),
               reservationId);
       LOG.debug(
           String.format(
               "Generated download manifest for instance %s", instance.getDisplayName()));
     } catch (final Exception ex) {
       LOG.error(
           String.format(
               "Failed to generate download manifest for instance %s", instance.getDisplayName()),
           ex);
     }
   }
 }
    @Override
    public void allocate(Allocation allocInfo) throws Exception {
      Partition reqPartition = allocInfo.getPartition();
      String zoneName = reqPartition.getName();
      String vmTypeName = allocInfo.getVmType().getName();

      /* Validate min and max amount */
      final int minAmount = allocInfo.getMinCount();
      final int maxAmount = allocInfo.getMaxCount();
      if (minAmount > maxAmount)
        throw new RuntimeException(
            "Maximum instance count must not be smaller than minimum instance count");

      /* Retrieve our context and list of clusters associated with this zone */
      List<Cluster> authorizedClusters = this.doPrivilegedLookup(zoneName, vmTypeName);

      int remaining = maxAmount;
      int allocated = 0;
      int available;

      LOG.info(
          "Found authorized clusters: "
              + Iterables.transform(authorizedClusters, HasName.GET_NAME));

      /* Do we have any VM available throughout our clusters? */
      if ((available = checkAvailability(vmTypeName, authorizedClusters)) < minAmount) {
        throw new NotEnoughResourcesException(
            "Not enough resources ("
                + available
                + " in "
                + zoneName
                + " < "
                + minAmount
                + "): vm instances.");
      } else {
        for (Cluster cluster : authorizedClusters) {
          if (remaining <= 0) {
            break;
          } else {
            ResourceState state = cluster.getNodeState();
            Partition partition = cluster.getConfiguration().lookupPartition();

            /* Has a partition been set if the AZ was not specified? */
            if (allocInfo.getPartition().equals(Partition.DEFAULT)) {
              /*
               * Ok, do we have enough slots in this partition to support our request? We should have at least
               * the minimum. The list is sorted in order of resource availability from the cluster with the most
               * available to the cluster with the least amount available. This is why we don't check against the
               * maxAmount value since its a best effort at this point. If we select the partition here and we
               * can't fit maxAmount, based on the sorting order, the next partition will not fit maxAmount anyway.
               */
              int zoneAvailable = checkZoneAvailability(vmTypeName, partition, authorizedClusters);
              if (zoneAvailable < minAmount) continue;

              /* Lets use this partition */
              allocInfo.setPartition(partition);
            } else if (!allocInfo.getPartition().equals(partition)) {
              /* We should only pick clusters that are part of the selected AZ */
              continue;
            }

            if (allocInfo.getBootSet().getMachine() instanceof BlockStorageImageInfo) {
              try {
                Topology.lookup(Storage.class, partition);
              } catch (Exception ex) {
                allocInfo.abort();
                allocInfo.setPartition(reqPartition);
                throw new NotEnoughResourcesException(
                    "Not enough resources: Cannot run EBS instances in partition w/o a storage controller: "
                        + ex.getMessage(),
                    ex);
              }
            }

            try {
              int tryAmount =
                  (remaining > state.getAvailability(vmTypeName).getAvailable())
                      ? state.getAvailability(vmTypeName).getAvailable()
                      : remaining;

              List<ResourceToken> tokens =
                  this.requestResourceToken(allocInfo, tryAmount, maxAmount);
              remaining -= tokens.size();
              allocated += tokens.size();
            } catch (Exception t) {
              LOG.error(t);
              Logs.extreme().error(t, t);

              allocInfo.abort();
              allocInfo.setPartition(reqPartition);

              /* if we still have some allocation remaining AND no more resources are available */
              if (((available = checkZoneAvailability(vmTypeName, partition, authorizedClusters))
                      < remaining)
                  && (remaining > 0)) {
                throw new NotEnoughResourcesException(
                    "Not enough resources ("
                        + available
                        + " in "
                        + zoneName
                        + " < "
                        + minAmount
                        + "): vm instances.",
                    t);
              } else {
                throw new NotEnoughResourcesException(t.getMessage(), t);
              }
            }
          }
        }

        /* Were we able to meet our minimum requirements? */
        if ((allocated < minAmount) && (remaining > 0)) {
          allocInfo.abort();
          allocInfo.setPartition(reqPartition);

          if (reqPartition.equals(Partition.DEFAULT)) {
            throw new NotEnoughResourcesException(
                "Not enough resources available in all zone for " + minAmount + "): vm instances.");
          } else {
            available = checkZoneAvailability(vmTypeName, reqPartition, authorizedClusters);
            throw new NotEnoughResourcesException(
                "Not enough resources ("
                    + available
                    + " in "
                    + zoneName
                    + " < "
                    + minAmount
                    + "): vm instances.");
          }
        }
      }
    }