https://github.com/jvivian/one_off_scripts
Tip revision: 3ad04be99cd01e6a047c1b530cc8a1de82bd862e authored by John Vivian on 02 February 2017, 01:31:18 UTC
Refactor SRA pipeline to use faster method than fastq-dump
Refactor SRA pipeline to use faster method than fastq-dump
Tip revision: 3ad04be
calculate_ec2_spot_instance.py
#!/usr/bin/env python2.7
"""
Author: John Vivian
Date: 12-15-15
Ideas taken from:
andPei - http://stackoverflow.com/questions/20854533/how-to-find-out-when-an-ec2-instance-was-last-stopped
"""
import argparse
import boto.ec2
import time
import datetime
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def get_start_and_stop(instance_id, region='us-west-2'):
"""
calculates start and stop time of an instance
:returns: strs startTime, endTime
"""
logging.info('Acquiring start and stop time of instance...')
start, stop = 0, 0
conn = boto.ec2.connect_to_region(region)
reservations = conn.get_all_instances(instance_id)
for r in reservations:
for i in r.instances:
start = i.launch_time
if i.state == 'terminated' or i.state == 'stopped':
# Convert stop to proper format
stop = i.reason.split('(')[1].split(')')[0]
stop = stop.split()
stop = stop[0] + 'T' + stop[1] + '.000Z'
else:
logging.info('Instance not stopped or terminated yet. Using current UTC time.')
t = datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S')
stop = t[:4] + '-' + t[4:6] + '-' + t[6:8] + 'T' + t[8:10] + ':' + t[10:12] + ':' + t[12:14] + '.000Z'
if start == 0:
raise RuntimeError('Spot Instance {} not found'.format(instance_id))
return start, stop
def calculate_cost(instance_type, avail_zone, instance_id=None, start_time=None, end_time=None, region='us-west-2'):
if start_time is None or end_time is None:
assert instance_id, 'If start_time or end_time not supplied, an instance_id must be supplied'
start_time, end_time = get_start_and_stop(instance_id)
# Some values
logging.info('Calculating costs...')
total, n = 0.0, 0
min_time = float("inf")
# Connect to EC2 -- requires ~/.boto
conn = boto.ec2.connect_to_region(region)
# Get prices for instance, AZ and time range
try:
prices = conn.get_spot_price_history(instance_type=instance_type, start_time=start_time,
end_time=end_time, availability_zone=avail_zone)
# Output the prices
for price in prices:
total += price.price
n += 1
# Difference b/w first and last returned times
stop = time.mktime(datetime.datetime.strptime(end_time, "%Y-%m-%dT%H:%M:%S.000Z").timetuple())
start = time.mktime(datetime.datetime.strptime(start_time, "%Y-%m-%dT%H:%M:%S.000Z").timetuple())
time_diff = (stop - start) / 3600
# Output aggregate, average and max results
print "For one: {} in Zone: {}".format(instance_type, avail_zone)
print "From: {} to {}".format(start_time, end_time)
print "\tTotal cost = $" + str(time_diff * (total/n))
print "\tAvg hourly cost = $" + str(total / n)
return str(time_diff * (total/n)), str(total / n)
except:
logging.info('Failed to fetch prices. Paging not in effect, check start / stop time.')
logging.info('start: {}\nstop: {}'.format(start_time, end_time))
return 0.0, 0.0
def main():
"""
Computes the spot market cost for a stopped or terminated instance given 3 values:
instance_type, instance_id, avail_zone
Example:
python calculate_ec2_spot_instance.py -t c3.8xlarge -i i-b3a1cd6a -a us-west-2a
"""
parser = argparse.ArgumentParser(description=main.__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-t', '--instance_type', default='c3.8xlarge', help='e.g. m4.large or c3.8xlarge.')
parser.add_argument('-i', '--instance_id', required=True, help='Instance ID is the second column in EC2 browser.')
parser.add_argument('-a', '--avail_zone', default='us-west-2a',
help='Availability Zone found in instance description.')
params = parser.parse_args()
calculate_cost(params.instance_type, params.instance_id, params.avail_zone)
if __name__ == '__main__':
main()