import boto3
import logging
import datetime
import argparse
import time
from datetime import datetime
from botocore.exceptions import ClientError
logger = logging.getLogger()
logger.setLevel(logging.INFO)
VolumeList=[]
expirationDate = expiration_Date = ""
DEFAULT_AWS_Account_ID = "1111222222"
DEFAULT_REGION = "us-east-1"
def parse_commandline_arguments():
global REGION
global AWS_Account_ID
global instance_id
global server_name
global size_of_volume
global kms_key
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description='Boto 2 Scritp to create and attach volume to a given Ec2 Instance.')
parser.add_argument("-accountID", "--ownerID", dest="aws_ID", type=str, default=DEFAULT_AWS_Account_ID,
help="The AWS Account ID where volume tagging is to be done")
parser.add_argument("-r", "--region", dest="region", type=str,
default=DEFAULT_REGION, help="Specify the region of the AWS Account")
parser.add_argument("-server_name", "--ServerName", dest="servername", type=str,
help="Specify the Instance Name to be terminated")
parser.add_argument("-volume_size","--Volume_Size",dest="volumesize", type=int,
help="Specify the size of new volume to be created and attached")
parser.add_argument("-kmsId","--KMS_ID",dest="kms_key_id",type=str,
help="Specify the KMS Key ID to encrypt the volume")
args = parser.parse_args()
REGION = args.region
AWS_Account_ID = args.aws_ID
server_name = args.servername
size_of_volume = args.volumesize
kms_key = args.kms_key_id
def ec2_client(region):
"""
Connects to EC2, returns a connection object
"""
try:
conn = boto3.client('ec2', region_name=region)
except Exception as e:
sys.stderr.write(
'Could not connect to region: %s. Exception: %s\n' % (region, e))
conn = None
return conn
def wait_for_state (instance, target_state):
# Waits for instance to move to desired state
# Vol Creation State: 'creating'|'available'|'in-use'|'deleting'|'deleted'|'error'
# Vol Attachment State: 'attaching'|'attached'|'detaching'|'detached'
status = ec2.Instance(instance).state['Name']
while status != target_state:
print("Waiting for Instance - {} to come in {} state" .format(instance,target_state))
time.sleep (5)
status = ec2.Instance(instance).state['Name']
def create_and_attach_volume(client,serverName,volSize,kmsId):
global VolumeList
device = "/dev/sdh"
print(serverName)
# Get Instance ID from the given Instance Name
filters = [ {'Name': 'tag:Name',
'Values': [serverName]}
]
for attempt in range(5):
try:
response = client.describe_instances(Filters=filters)["Reservations"]
#response = client.describe_instances()
instanceid = response[0]['Instances'][0]['InstanceId']
avaialbilityZone = response[0]['Instances'][0]['Placement']['AvailabilityZone']
print(instanceid + ":" + avaialbilityZone)
except BaseException as err:
logger.error(err)
logger.info("*** ERROR *** during EC2 Describe proceess - retry...")
time.sleep(0.5)
else:
logger.info("--> Done")
break
else:
logger.error("*** ERROR *** - All attempt to describe instance failed - exit with error")
raise Exception("*** ERROR *** - Can't describe instance")
# Create volume
for attempt in range(5):
try:
response = client.create_volume(
AvailabilityZone=avaialbilityZone,
Encrypted=True,
KmsKeyId=kmsId,
Size=volSize,
VolumeType='gp3' ## Default Volume Type
)
#print(response)
except BaseException as err:
logger.error(err)
logger.info("*** ERROR *** during EC2 Volume creation proceess - retry...")
time.sleep(0.5)
else:
logger.info("--> Done")
break
else:
logger.error("*** ERROR *** - All attempt to create EC2 Volume failed - exit with error")
raise Exception("*** ERROR *** - Can't create EBS Volume")
if response['ResponseMetadata']['HTTPStatusCode']== 200:
volume_id= response['VolumeId']
print('***volume:', volume_id)
client.get_waiter('volume_available').wait(
VolumeIds=[volume_id]
)
print('***Success!! volume:', volume_id, 'created...')
VolumeList.append(volume_id)
print(VolumeList)
# Add tag on newly created Volumes
logger.info("Tagging for deletion following Volumes:")
for volume in VolumeToDelList:
logger.info("- " + volume)
for attempt in range(5):
try:
print("creating Tag for Volume ID {}" .format(VolumeToDelList))
client.create_tags(
Resources=VolumeToDelList,
Tags=[
{
'Key': 'InsntanceId',
'Value': instanceid
}
]
)
except BaseException as err:
logger.error(err)
logger.error("*** ERROR *** during tagging Volumes - retry...")
time.sleep(0.6)
else:
logger.info("--> Done")
break
else:
logger.error("*** ERROR *** - All attempt to tagging volumes - exit with error")
raise Exception("*** ERROR *** - Can't tagging Volumes")
# Attach Volume to EC2 Instance
logger.info("--> Attaching volume to EC2")
for attempt in range(5):
try:
if volume_id:
print('***attaching volume:', volume_id, 'to:', instanceid)
response = client.attach_volume(
Device=device,
InstanceId=instanceid,
VolumeId=volume_id,
DryRun=False
)
if response['ResponseMetadata']['HTTPStatusCode']== 200:
client.get_waiter('volume_in_use').wait(
VolumeIds=[volume_id],
DryRun=False
)
print('***Success!! volume:', volume_id, 'is attached to instance:', instanceid)
except BaseException as err:
logger.error(err)
logger.error("*** ERROR *** during EC2 Volume attachment process - retry...")
time.sleep(0.6) # second
else:
logger.info("--> Done")
break
else:
logger.error("*** ERROR *** - All attempt to attach volume to instance failed - exit with error")
raise Exception("*** ERROR *** - Can't attach volume to EC2")
if __name__ == '__main__':
try:
parse_commandline_arguments()
client=ec2_client(REGION)
create_and_attach_volume(client,server_name,size_of_volume,kms_key)
except Exception as error:
logging.error(error)
print(str(error))
Happy Reading !!!!
-Anand M
Leave a comment