Created
April 6, 2017 22:38
-
-
Save res0nat0r/d708a1a39ea13a1d4b72eb6a7901c949 to your computer and use it in GitHub Desktop.
EBS Volume Report
This file contains hidden or 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
| #! /usr/bin/python | |
| ################################################################################ | |
| ## ebs-report - Creates a CSV report for EBS volumes, including some snapshot information | |
| ## Written by N2W Software | |
| ## Date: July 2014 | |
| ## License: You can use/modify/circulate or do whatever you want. | |
| ## Just note that this script is given "As Is" without any warranty | |
| ## | |
| ## Usage: see README file | |
| ## | |
| ################################################################################ | |
| import csv | |
| import os, sys | |
| import datetime | |
| import argparse | |
| from boto import ec2 | |
| from boto.exception import EC2ResponseError | |
| # Defaults, can be modified | |
| AWS_ACCESS_KEY = None | |
| AWS_SECRET_KEY = None | |
| AWS_REGIONS = u'us-east-1|us-west-1|us-west-2|eu-west-1|ap-southeast-1|ap-northeast-1|ap-southeast-2|sa-east-1' | |
| def open_file (filepath): | |
| """ | |
| Opens the output files, promts whether to overwrite | |
| """ | |
| goaheadandopen = True | |
| if os.path.exists (filepath): | |
| if os.path.isfile (filepath): | |
| valid = {'yes':True, 'y':True, | |
| 'no':False, 'n':False} | |
| while True: | |
| sys.stdout.write ('file %s exists, overwrite it? [y/n] ' % filepath) | |
| choice = raw_input().lower() | |
| if choice in valid.keys (): | |
| if not valid[choice]: | |
| goaheadandopen = False | |
| break | |
| sys.stdout.write ('Please respond with \'yes\' or \'no\' (or \'y\' or \'n\').\n') | |
| else: # folder | |
| sys.stdout.write ('%s exists but nt a regular file. Aborting...\n') | |
| goaheadandopen = False | |
| if not goaheadandopen: | |
| return None | |
| try: | |
| f = file(filepath, 'wt') | |
| except Exception, e: | |
| f = None | |
| sys.stderr.write ('Could not open file %s. reason: %s\n' % (filepath, e)) | |
| return f | |
| def ec2_connect (access_key, secret_key, region): | |
| """ | |
| Connects to EC2, returns a connection object | |
| """ | |
| try: | |
| conn = ec2.connect_to_region (region, | |
| aws_access_key_id=access_key, | |
| aws_secret_access_key=secret_key) | |
| except Exception, e: | |
| sys.stderr.write ('Could not connect to region: %s. Exception: %s\n' % (region, e)) | |
| conn = None | |
| return conn | |
| def create_ebs_report (regions, access_key, secret_key, filepath): | |
| """ | |
| Creates the actual report, first into a python data structure | |
| Then write into a csv file | |
| """ | |
| # opens file | |
| f = open_file (filepath) | |
| if not f: | |
| return False | |
| region_list = regions.split('|') | |
| volume_dict = {} | |
| # go over all regions in list | |
| for region in region_list: | |
| # connects to ec2 | |
| conn = ec2_connect (access_key, secret_key, region) | |
| if not conn: | |
| sys.stderr.write ('Could not connect to region: %s. Skipping\n' % region) | |
| continue | |
| # get all volumes and snapshots | |
| try: | |
| volumes = conn.get_all_volumes () | |
| snapshots = conn.get_all_snapshots (owner='self') | |
| except EC2ResponseError, e: | |
| sys.stderr.write ('Could not get volumes or snapshots for region: %s. Skipping (problem: %s)\n' % (region, e.error_message)) | |
| continue | |
| volume_types_map = { u'standard' : u'Standard/Magnetic', u'io1' : u'Provisioned IOPS (SSD)', u'gp2' : u'General Purpose SSD'} | |
| volume_dict [region] = {} | |
| # goes over volumes and insert relevant data into a python dictionary | |
| for vol in volumes: | |
| try: | |
| name = vol.tags['Name'] | |
| except: | |
| name = u'' | |
| try: | |
| iops = vol.iops | |
| except: | |
| iops = 0 | |
| if vol.attachment_state() == u'attached': | |
| instance_id = vol.attach_data.instance_id | |
| device = vol.attach_data.device | |
| else: | |
| instance_id = u'N/A' | |
| device = 'N/A' | |
| if iops == None : iops = 0 | |
| if vol.encrypted: | |
| encrypted = u'yes' | |
| else: | |
| encrypted = u'no' | |
| volume_dict [region][vol.id] = { 'name' : name, | |
| 'size' : vol.size, | |
| 'zone' : vol.zone, | |
| 'type' : volume_types_map[vol.type], | |
| 'iops' : iops, | |
| 'orig_snap' : vol.snapshot_id, | |
| 'encrypted' : encrypted, | |
| 'instance' : instance_id, | |
| 'device' : device, | |
| 'num_snapshots' : 0, | |
| 'first_snap_time' : u'', | |
| 'first_snap_id' : u'N/A', | |
| 'last_snap_time' : u'', | |
| 'last_snap_id' : u'N/A' | |
| } | |
| #go over snapshots and match to volumes structure | |
| for snap in snapshots: | |
| start_time = datetime.datetime.strptime (snap.start_time.split('.')[0],'%Y-%m-%dT%H:%M:%S') | |
| if volume_dict[region].has_key (snap.volume_id): | |
| vol=volume_dict[region][snap.volume_id] | |
| vol['num_snapshots']+=1 | |
| if vol['first_snap_time'] == u'' or start_time < vol['first_snap_time']: | |
| vol['first_snap_time'] = start_time | |
| vol['first_snap_id'] = snap.id | |
| if vol['last_snap_time'] == u'' or start_time > vol['last_snap_time']: | |
| vol['last_snap_time'] = start_time | |
| vol['last_snap_id'] = snap.id | |
| else: | |
| sys.stdout.write ('Region %s: Could not find volume %s for snapshot %s. Volume was deleted or snapshot copied from another region \n' % \ | |
| (region, snap.volume_id, snap.id)) | |
| # starts the csv file | |
| writer = csv.writer (f) | |
| # header | |
| writer.writerow (['Region','volume ID','Volume Name','Volume Type','iops','Size (GiB)', \ | |
| 'Created from Snapshot','Attached to','Device','Encrypted','Number of Snapshots', \ | |
| 'Earliest Snapshot Time','Earliest Snapshot','Most Recent Snapshot Time','Most Recent Snapshot']) | |
| # writes actual data | |
| for region in volume_dict.keys (): | |
| for volume_id in volume_dict[region].keys (): | |
| volume = volume_dict[region][volume_id] | |
| writer.writerow ([region, volume_id, volume['name'],volume['type'],volume['iops'],volume['size'], \ | |
| volume['orig_snap'],volume['instance'],volume['device'],volume['encrypted'], \ | |
| volume['num_snapshots'],volume['first_snap_time'],volume['first_snap_id'], \ | |
| volume['last_snap_time'],volume['last_snap_id']]) | |
| f.close () | |
| return True | |
| if __name__ == '__main__': | |
| # Define command line argument parser | |
| parser = argparse.ArgumentParser(description='Creates a CSV report about EBS volumes and tracks snapshots on them.') | |
| parser.add_argument('--regions', default = AWS_REGIONS, help='AWS regions to create the report on, can add multiple with | as separator. Default will assume all regions') | |
| parser.add_argument('--access_key', default = AWS_ACCESS_KEY, help='AWS API access key. If missing default is used') | |
| parser.add_argument('--secret_key', default = AWS_SECRET_KEY, help='AWS API secret key. If missing default is used') | |
| parser.add_argument('--file', required=True, help='Path for output CSV file') | |
| args = parser.parse_args () | |
| # creates the report | |
| retval = create_ebs_report (args.regions, args.access_key, args.secret_key, args.file) | |
| if retval: | |
| sys.exit (0) | |
| else: | |
| sys.exit (1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Got this error.
[-h] [--regions REGIONS] [--access_key ACCESS_KEY] [--secret_key SECRET_KEY] --file FILE
ebs-report.py: error: the following arguments are required: --file