Amazon webservices is one among the popular cloud service providers. I am using almost all services provided by AWS. While using the cloud services, we have to be careful about the cost. We should stop or terminate all the unused services, otherwise it may result in huge money loss. This is a small python utility for getting the summary of EC2 instances and EMR clusters across all regions in an aws account. I scheduled this utility as a cron job for getting periodic emails. Similar to this code, you can create the summary utility for all the other services in AWS. This code is working fine at the time of development. The API changes may happen, you have to make the changes in the code accordingly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__author__ = 'Amal G Jose' | |
import sys | |
import smtplib | |
import time | |
import boto | |
import boto.ses | |
from email.mime.text import MIMEText | |
from email.mime.application import MIMEApplication | |
from email.mime.multipart import MIMEMultipart | |
from ConfigParser import SafeConfigParser | |
from boto.regioninfo import RegionInfo | |
from boto.emr.connection import EmrConnection | |
BASE_HTML = """<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
table, th, td { | |
border: 1px solid black; | |
border-collapse: collapse; | |
} | |
th, td { | |
padding: 5px; | |
text-align: left; | |
} | |
</style> | |
</head> | |
<body> | |
""" | |
END_HTML = """ | |
</body> | |
</html> | |
""" | |
EMR_HEADER = """ | |
<table style="width:100%"> | |
<caption><b>EMR Cluster Details</b></caption> | |
<tr> | |
<th>Cluster Name</th> | |
<th>Number of Nodes</th> | |
<th>Instance Type</th> | |
<th>Cluster Creation Date</th> | |
<th>Region</th> | |
</tr> | |
""" | |
EC2_HEADER = """ | |
<table style="width:100%"> | |
<caption><b>EC2 Instance Details</b></caption> | |
<tr> | |
<th>EC2 Name</th> | |
<th>Instance Id</th> | |
<th>Instance Type</th> | |
<th>Region</th> | |
</tr> | |
""" | |
TABLE_END = """</table>""" | |
LINE_BREAK = "<br> <br> <br>" | |
class GetSummary(object): | |
##Initializer | |
def __init__(self): | |
self.from_email_id = "sender@email.com" | |
self.email_password = "xxxxxxxxxxxx" | |
self.aws_access_key = 'XXXXXXXXXXXXXXXXXX' | |
self.aws_secret_key = 'XXXXXXXXXXXXXXXXXX' | |
to_address = "receiver1@email.com,receiver2@email.com,receiver3@email.com" | |
self.receiver_email = to_address.split(',') | |
##Method for getting the details of EMR | |
def get_all_emr(self, regions): | |
try: | |
html_data = EMR_HEADER | |
for region in regions: | |
emr_conn = EmrConnection(self.aws_access_key, self.aws_secret_key, | |
region=RegionInfo(name=region, | |
endpoint=region + '.elasticmapreduce.amazonaws.com')) | |
cluster_list = emr_conn.describe_jobflows() | |
for cluster in cluster_list: | |
if cluster.state in ['RUNNING', 'WAITING', 'STARTING', 'BOOTSTRAPPING']: | |
try: | |
row_html = """<tr> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
</tr>""" % (cluster.name, str(cluster.instancecount), cluster.masterinstancetype, cluster.creationdatetime, region) | |
html_data += row_html + "\n" | |
except: | |
pass | |
return html_data + TABLE_END | |
except Exception, e: | |
print "Exception occurred while getting the details of EMR cluster : " + str(e) | |
##Method for getting the details of EC2 | |
def get_all_running_instances(self, regions): | |
try: | |
emr_groups = ['ElasticMapReduce-slave', 'ElasticMapReduce-master'] | |
html_data = EC2_HEADER | |
for region in regions: | |
conn = boto.ec2.connect_to_region(region, | |
aws_access_key_id=self.aws_access_key, | |
aws_secret_access_key=self.aws_secret_key) | |
##List all running EC2 instances | |
reservations = conn.get_all_reservations() | |
for reservation in reservations: | |
for instance in reservation.instances: | |
if instance.state in ['running'] and (instance.groups[0].name not in emr_groups): | |
try: | |
row_html = """<tr> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
</tr>""" % (instance.tags['Name'], instance.id, instance.instance_type,region ) | |
except: | |
row_html = """<tr> | |
<td>Unknown</td> | |
<td>%s</td> | |
<td>%s</td> | |
<td>%s</td> | |
</tr>""" % (instance.id, instance.instance_type, region) | |
html_data += row_html + '\n' | |
return html_data + TABLE_END | |
except Exception, e: | |
print "Error occurred while getting EC2 instance details : " + str(e) | |
##Method to send email alerts | |
def send_email(self, email_body): | |
SUBJECT = "AWS Account Summary" | |
try: | |
localtime = time.asctime( time.localtime(time.time())) | |
recepients = ','.join(self.receiver_email) | |
msg = MIMEMultipart('alternative') | |
msg['Subject'] = SUBJECT + " " + str(localtime) | |
msg['From'] = self.from_email_id | |
msg['To'] = recepients | |
msg_part = MIMEText(email_body, 'html') | |
msg.attach(msg_part) | |
server = smtplib.SMTP("smtp.gmail.com", 587) | |
server.ehlo() | |
server.starttls() | |
server.login(self.from_email_id, self.email_password) | |
server.sendmail(self.from_email_id, self.receiver_email, msg.as_string()) | |
server.close() | |
print 'Email Sent Successfully' | |
except Exception, e: | |
print "Failed to send email : " + str(e) | |
if __name__== '__main__': | |
get_summary = GetSummary() | |
regions = ['ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1', | |
'us-east-1','us-west-1', 'us-west-2','eu-west-1', 'sa-east-1'] | |
ec2_details = get_summary.get_all_running_instances(regions) | |
emr_details = get_summary.get_all_emr(regions) | |
complete_details = BASE_HTML + emr_details + LINE_BREAK + ec2_details + END_HTML | |
get_summary.send_email(complete_details) |