Home > AWS/Boto3/Python > Boto3 Script to create and attach an EBS Volume to an EC2

Boto3 Script to create and attach an EBS Volume to an EC2


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

Categories: AWS/Boto3/Python
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: