Esempio n. 1
0
 @Override
 public boolean apply(Allocation allocInfo) throws MetadataException {
   RunInstancesType request = allocInfo.getRequest();
   String zoneName = request.getAvailabilityZone();
   if (Clusters.getInstance().listValues().isEmpty()) {
     LOG.debug("enabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     LOG.debug("disabled values: " + Joiner.on("\n").join(Clusters.getInstance().listValues()));
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   } else if (Partitions.exists(zoneName)) {
     Partition partition = Partitions.lookupByName(zoneName);
     allocInfo.setPartition(partition);
   } else if (Partition.DEFAULT_NAME.equals(zoneName)) {
     Partition partition = Partition.DEFAULT;
     allocInfo.setPartition(partition);
   } else {
     throw new VerificationException(
         "Not enough resources: no cluster controller is currently available to run instances.");
   }
   return true;
 }
Esempio n. 2
0
    @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.");
          }
        }
      }
    }