Skip to content

Instantly share code, notes, and snippets.

@res0nat0r
Created April 6, 2017 22:38
Show Gist options
  • Select an option

  • Save res0nat0r/d708a1a39ea13a1d4b72eb6a7901c949 to your computer and use it in GitHub Desktop.

Select an option

Save res0nat0r/d708a1a39ea13a1d4b72eb6a7901c949 to your computer and use it in GitHub Desktop.
EBS Volume Report
#! /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)
@rengadevsecops
Copy link
Copy Markdown

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment