/* * 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); } }
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; } } } }