Example #1
0
    /*
     * Check the current Spot price of the selected instance type for the selected region
     */
    public FormValidation doCurrentSpotPrice(
        @QueryParameter boolean useInstanceProfileForCredentials,
        @QueryParameter String credentialsId,
        @QueryParameter String region,
        @QueryParameter String type,
        @QueryParameter String zone)
        throws IOException, ServletException {

      String cp = "";
      String zoneStr = "";

      // Connect to the EC2 cloud with the access id, secret key, and
      // region queried from the created cloud
      AWSCredentialsProvider credentialsProvider =
          EC2Cloud.createCredentialsProvider(useInstanceProfileForCredentials, credentialsId);
      AmazonEC2 ec2 =
          EC2Cloud.connect(credentialsProvider, AmazonEC2Cloud.getEc2EndpointUrl(region));

      if (ec2 != null) {

        try {
          // Build a new price history request with the currently
          // selected type
          DescribeSpotPriceHistoryRequest request = new DescribeSpotPriceHistoryRequest();
          // If a zone is specified, set the availability zone in the
          // request
          // Else, proceed with no availability zone which will result
          // with the cheapest Spot price
          if (getAvailabilityZones(ec2).contains(zone)) {
            request.setAvailabilityZone(zone);
            zoneStr = zone + " availability zone";
          } else {
            zoneStr = region + " region";
          }

          /*
           * Iterate through the AWS instance types to see if can find a match for the databound String type.
           * This is necessary because the AWS API needs the instance type string formatted a particular way
           * to retrieve prices and the form gives us the strings in a different format. For example "T1Micro"
           * vs "t1.micro".
           */
          InstanceType ec2Type = null;

          for (InstanceType it : InstanceType.values()) {
            if (it.name().equals(type)) {
              ec2Type = it;
              break;
            }
          }

          /*
           * If the type string cannot be matched with an instance type, throw a Form error
           */
          if (ec2Type == null) {
            return FormValidation.error("Could not resolve instance type: " + type);
          }

          Collection<String> instanceType = new ArrayList<String>();
          instanceType.add(ec2Type.toString());
          request.setInstanceTypes(instanceType);
          request.setStartTime(new Date());

          // Retrieve the price history request result and store the
          // current price
          DescribeSpotPriceHistoryResult result = ec2.describeSpotPriceHistory(request);

          if (!result.getSpotPriceHistory().isEmpty()) {
            SpotPrice currentPrice = result.getSpotPriceHistory().get(0);

            cp = currentPrice.getSpotPrice();
          }

        } catch (AmazonServiceException e) {
          return FormValidation.error(e.getMessage());
        }
      }
      /*
       * If we could not return the current price of the instance display an error Else, remove the additional
       * zeros from the current price and return it to the interface in the form of a message
       */
      if (cp.isEmpty()) {
        return FormValidation.error("Could not retrieve current Spot price");
      } else {
        cp = cp.substring(0, cp.length() - 3);

        return FormValidation.ok(
            "The current Spot price for a " + type + " in the " + zoneStr + " is $" + cp);
      }
    }
Example #2
0
  public void run() {
    logger.debug("started GridManager");
    System.out.println("started GridManager");
    AmazonSQSClient sqsClient = new AmazonSQSClient(papa.getCredentials());
    AmazonEC2Client ec2Client = new AmazonEC2Client(papa.getCredentials());

    // Get current imageID from the metadata table
    String imageID = Constants.imageID; // get the default imageID from Constants
    try {
      Connection conn = PooledConnectionFactory.INSTANCE.getCumulusConnection();
      Statement stmt = conn.createStatement();
      String imageQuery = "SELECT mvalue FROM cumulus.metadata WHERE mkey='imageID';";
      ResultSet results = stmt.executeQuery(imageQuery);
      results.next(); // move the cursor into the results
      imageID = results.getString(1);
    } catch (SQLException e) {
      logger.warn(e);
    }
    if (imageID == null
        || imageID.equals("")) { // if we get an empty imageID revert to the hardcoded one
      imageID = Constants.imageID;
    }
    logger.debug(imageID);
    System.out.println(imageID);

    while (true) { // loop from startup to shutdown
      // check the number of messages in the queue.
      GetQueueAttributesRequest sqsRequest =
          new GetQueueAttributesRequest(papa.getDispatchQueue())
              .withAttributeNames("ApproximateNumberOfMessages");
      Integer sqsResult = null;
      try {
        sqsResult =
            Integer.valueOf(
                sqsClient
                    .getQueueAttributes(sqsRequest)
                    .getAttributes()
                    .get("ApproximateNumberOfMessages"));
      } catch (AmazonServiceException e) {
        // Write out any exceptions that may have occurred.
        System.err.println("Error getting list of instances");
        System.err.println("Caught Exception: " + e.getMessage());
        System.err.println("Reponse Status Code: " + e.getStatusCode());
        System.err.println("Error Code: " + e.getErrorCode());
        System.err.println("Request ID: " + e.getRequestId());
      } catch (AmazonClientException e) {
        logger.warn(e);
        continue; // if the error is due to being unable to connect to sqs it is likely transient,
                  // and we should keep going until SQS comes back
      } catch (Exception e) {
        // caught another exception
        System.err.println(e);
        System.err.println("Did not exit cleanly");
        // System.exit(1);
      }
      if (sqsResult == null) {
        System.err.println(
            "Couldn't get the number of items in the queue reverting to static functioning");
        logger.error(
            "Couldn't get the number of items in the queue reverting to static functioning");
        break;
      }
      System.out.println("Queue size=" + sqsResult);
      // check the number of running instances.
      DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest();
      // get the number of running instances with our image ID
      describeInstancesRequest.withFilters(
          new Filter("image-id").withValues(imageID),
          new Filter("instance-state-name").withValues("running"));
      logger.debug("Getting list of active cumulus drones");
      Integer numInstances = null;
      Integer numSpotRequests = null;
      Initializer.serialize("/tmp/dump.obj", papa.unitsOnServer); // TODO test this.
      // check number of open spot requests
      DescribeSpotInstanceRequestsRequest describeSpotInstancesRequest =
          new DescribeSpotInstanceRequestsRequest();
      describeSpotInstancesRequest.withFilters(new Filter("state").withValues("open"));
      try {
        // Parse returned instances
        DescribeInstancesResult describeInstancesResult =
            ec2Client.describeInstances(describeInstancesRequest);
        if (describeInstancesResult.getReservations().size() == 0) {
          numInstances = 0;
        } else {
          Integer totalInstances = 0;
          for (Reservation i : describeInstancesResult.getReservations()) {
            totalInstances += i.getInstances().size();
          }
          numInstances = totalInstances;
        }
        // Parse returned open spot requests
        DescribeSpotInstanceRequestsResult describeSpotReservationsResult =
            ec2Client.describeSpotInstanceRequests(describeSpotInstancesRequest);
        if (describeSpotReservationsResult.getSpotInstanceRequests().size() == 0) {
          numSpotRequests = 0;
        } else {
          Integer totalInstances = 0;
          for (SpotInstanceRequest i : describeSpotReservationsResult.getSpotInstanceRequests()) {
            totalInstances++;
          }
          numSpotRequests = totalInstances;
        }

        // System.out.println("num instances="+numInstances);
      } catch (AmazonServiceException e) {
        // Write out any exceptions that may have occurred.
        System.err.println("Error getting list of instances");
        System.err.println("Caught Exception: " + e.getMessage());
        System.err.println("Reponse Status Code: " + e.getStatusCode());
        System.err.println("Error Code: " + e.getErrorCode());
        System.err.println("Request ID: " + e.getRequestId());
        // System.exit(1);
      } catch (Exception e) {
        // caught another exception
        System.err.println(e);
        System.err.println("Did not exit cleanly");
        // System.exit(1);
      }
      if (numInstances == null || numSpotRequests == null) {
        logger.error(
            "Couldn't get the number of machines or requests reverting to static functioning");
        break;
      }
      System.out.println("num instances=" + (numInstances + numSpotRequests));

      // if queue is longer than the number of instances * idealMaxUnitsPerInstance
      Integer idealMaxUnitsPerInstance = Integer.valueOf(Constants.idealMaxUnitsPerInstance);
      if (sqsResult
          > (numInstances + numSpotRequests)
              * idealMaxUnitsPerInstance) { // we count pending spot instances too.
        Integer numToCreate = (sqsResult / idealMaxUnitsPerInstance) - numInstances + 1;
        // check current pricing of spot instances
        DescribeSpotPriceHistoryRequest historyRequest =
            new DescribeSpotPriceHistoryRequest()
                .withAvailabilityZone("us-east-1c")
                .withInstanceTypes(Constants.instanceType)
                .withProductDescriptions("Linux/UNIX (Amazon VPC)")
                .withStartTime(new Date(System.currentTimeMillis()));
        DescribeSpotPriceHistoryResult result = ec2Client.describeSpotPriceHistory(historyRequest);
        Double nowPrice = Double.valueOf(result.getSpotPriceHistory().get(0).getSpotPrice());
        // If spot price is < constants.spotPrice launch numToCreate*Constants.percentSpot spot
        // instances
        Integer spotToCreate = 0;
        if (nowPrice < Double.valueOf(Constants.spotPrice)) {
          Double percentSpot = Double.valueOf(Constants.percentSpot);
          spotToCreate = (int) (numToCreate * percentSpot);
          numToCreate = (int) (numToCreate * (1 - percentSpot));
        }
        try {
          System.out.println("regular instances: " + numToCreate);
          System.out.println("spot instances: " + spotToCreate);
          // Create regular and spot instances
          if (numToCreate > 0) {
            papa.createInstances(ec2Client, numToCreate, imageID);
          }
          if (spotToCreate > 0) {
            papa.createSpotInstances(ec2Client, spotToCreate, Constants.imageID); // FIXME
          }
          System.out.println("created instances");
        } catch (Exception e) {
          // Report ec2 exceptions
          logger.error(e);
          e.printStackTrace();
          continue;
        }
      }
      try {
        Thread.sleep(60000); // we wait for any new servers to start up
      } catch (InterruptedException e) {
        logger.error("Sqslistener was interrupted");
        if (papa.getShuttingDown()) {
          break;
        } else {
          continue;
        }
      }
    }
  }