Example #1
0
def collect_aws_instance_data(
    services: list = ['ec2', 'rds'],
    all_regions: bool = True,
    regions: list = None,
    target_profile: str = None,
    log_wrapper=LogWrapper()) -> AWSInstanceCollection:
    instance_data_collection = AWSInstanceCollection(log_wrapper=log_wrapper)
    try:
        for service in services:
            if all_regions is True:
                regions = get_regions_by_service(service=service,
                                                 log_wrapper=log_wrapper)
            log_wrapper.info('Checking regions: {}'.format(regions))
            for region in regions:
                log_wrapper.info('Now checking region "{}"'.format(region))
                client = get_service_client_default(
                    service=service,
                    region=region,
                    target_profile=target_profile,
                    log_wrapper=log_wrapper)
                instances = list()
                if service == 'ec2':
                    instances = get_ec2_instances(aws_client=client,
                                                  log_wrapper=log_wrapper)
                if service == 'rds':
                    instances = get_rds_instances(aws_client=client,
                                                  log_wrapper=log_wrapper)
                if len(instances) > 0:
                    for instance in instances:
                        instance_data_collection.instances.append(instance)
                log_wrapper.info('Added {} instances'.format(len(instances)))
    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    return instance_data_collection
Example #2
0
def dict_to_json(
    dict_obj: dict, log_wrapper: LogWrapper = LogWrapper()) -> str:
    final_str = ''
    try:
        if isinstance(dict_obj, dict):
            final_str = json.dumps(dict_obj,
                                   default=convert_unknown_obj,
                                   indent=4,
                                   sort_keys=True)
        else:
            log_wrapper.error(
                message='dict_obj incorrect type: {}'.format(type(dict_obj)))
    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    return final_str
Example #3
0
def get_regions_by_service(service='ec2', log_wrapper=LogWrapper()) -> list:
    try:
        return list(boto3.session.Session().get_available_regions(service))
    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    return ['us-east-1']
Example #4
0
def get_service_client_default(service='ec2',
                               region: str = 'us-east-1',
                               target_profile: str = None,
                               log_wrapper=LogWrapper()):
    client = None
    try:
        if service not in INSTANCE_CLASSES:
            raise Exception(
                'Service "{}" not supported for this application yet'.format(
                    service))
        if region not in get_regions_by_service(service=service,
                                                log_wrapper=log_wrapper):
            raise Exception(
                'Service "{}" not available in selected region "{}"'.format(
                    service, region))
        if target_profile is not None:
            session = boto3.Session(profile_name=target_profile)
            client = session.client(service, region_name=region)
        else:
            client = boto3.client(service, region_name=region)
    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    if client is not None:
        log_wrapper.info(
            message='AWS Client connected to region "{}" for service "{}"'.
            format(region, service))
    else:
        log_wrapper.error(
            message=
            'AWS Client could NOT connected to region "{}" for service "{}"'.
            format(region, service))
    return client
Example #5
0
 def __init__(self,
              instance_class: str = 'ec2',
              log_wrapper: LogWrapper = LogWrapper()):
     self.instance_class = instance_class
     self.log_wrapper = log_wrapper
     self.last_update = None
     self.raw_instance_data = None
     self.instance_id = 'unknown'
     self.instance_type = 'unknown'
     self.state = 'unknown'
     self.region = 'unknown'
     self.tags = dict()
     self.metrics = list()
     self.metric_statistics = dict()
Example #6
0
def get_instance_metric_statistics(
    aws_client,
    instance_id: str,
    service_name: str = 'ec2',
    metric_name: str = 'CPUUtilization',
    start_timestamp: datetime = _get_start_timestamp(),
    end_timestamp: datetime = _get_end_timestamp(),
    period: int = 300,
    log_wrapper=LogWrapper()) -> dict:
    result = dict()
    result[metric_name] = dict()
    if service_name not in AWS_CLOUDWATCH_NAMESPACE_MAPPING:
        log_wrapper.error(message='Invalid service name.')
        return result
    dimension_name = AWS_CLOUDWATCH_DIMENSION_NAME_MAPPING[service_name]
    name_space = AWS_CLOUDWATCH_NAMESPACE_MAPPING[service_name]
    try:
        log_wrapper.info('Retrieving metrics data for "{}/{}/{}/{}/{}"'.format(
            service_name, name_space, dimension_name, instance_id,
            metric_name))
        response = aws_client.get_metric_statistics(Namespace=name_space,
                                                    MetricName=metric_name,
                                                    Dimensions=[
                                                        {
                                                            'Name':
                                                            dimension_name,
                                                            'Value':
                                                            instance_id
                                                        },
                                                    ],
                                                    StartTime=start_timestamp,
                                                    EndTime=end_timestamp,
                                                    Period=period,
                                                    Statistics=[
                                                        'Average',
                                                        'Maximum',
                                                    ])
        if 'Datapoints' in response:
            result[metric_name] = response['Datapoints']
    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    log_wrapper.info(
        message='Metric Statistics for "{}/{}/{}/{}/{}": {} bytes of JSON data'
        .format(service_name, name_space, dimension_name, instance_id,
                metric_name, len(dict_to_json(result))))
    return result
Example #7
0
def get_rds_instance_tags(
    aws_client, db_instance_arn: str, log_wrapper=LogWrapper()) -> dict:
    tags = dict()
    try:
        log_wrapper.info(message='Retrieving tags for RDS instance "{}"'.
                         format(db_instance_arn))
        response = aws_client.list_tags_for_resource(
            ResourceName=db_instance_arn)
        if 'TagList' in response:
            for tag in response['TagList']:
                if 'Key' in tag and 'Value' in tag:
                    tags[tag['Key']] = tag['Value']

    except:
        log_wrapper.error(
            message='EXCEPTION: {}'.format(traceback.format_exc()))
    return tags
Example #8
0
def get_instance_cloudwatch_metrics(
    aws_client,
    instance_id: str,
    service_name: str = 'ec2',
    next_token: str = None,
    log_wrapper=LogWrapper()) -> list:
    instance_metrics = list()
    if service_name not in INSTANCE_CLASSES:
        log_wrapper.error(message='Invalid service name.')
    else:
        try:
            response = dict()
            if next_token is not None:
                response = aws_client.list_metrics(
                    Namespace=AWS_CLOUDWATCH_NAMESPACE_MAPPING[service_name],
                    Dimensions=[{
                        'Name':
                        AWS_CLOUDWATCH_DIMENSION_NAME_MAPPING[service_name],
                        'Value':
                        instance_id
                    }],
                    NextToken=next_token)
            else:
                response = aws_client.list_metrics(
                    Namespace=AWS_CLOUDWATCH_NAMESPACE_MAPPING[service_name],
                    Dimensions=[{
                        'Name':
                        AWS_CLOUDWATCH_DIMENSION_NAME_MAPPING[service_name],
                        'Value':
                        instance_id
                    }],
                )
            if 'Metrics' in response:
                for metric in response['Metrics']:
                    if 'MetricName' in metric:
                        instance_metrics.append(metric['MetricName'])
        except:
            log_wrapper.error(
                message='EXCEPTION: {}'.format(traceback.format_exc()))
    log_wrapper.info(message='Metrics for "{}/{}": {}'.format(
        service_name, instance_id, instance_metrics))
    return instance_metrics
Example #9
0
import os
from aws_metrics_collector import LogWrapper
from aws_metrics_collector.aws import collect_aws_instance_data
from aws_metrics_collector.utils import dict_to_json

database_file = '{}{}aws_instance_metric_statistics.sqlite'.format(
    os.getcwd(), os.sep)
dump_raw_json_to_file = True
json_file = '{}{}data.json'.format(os.getcwd(), os.sep)
services = ['ec2', 'rds']
all_regions = True
regions = None
target_profile = None
log_wrapper = LogWrapper()


def run():
    log_wrapper.info(message='START')
    log_wrapper.info(
        message='Database file to be used: {}'.format(database_file))
    data = collect_aws_instance_data(services=services,
                                     all_regions=all_regions,
                                     regions=regions,
                                     target_profile=target_profile,
                                     log_wrapper=log_wrapper)
    if dump_raw_json_to_file is True:
        if os.path.exists(json_file):
            log_wrapper.info(
                message='Removing exiting data file "{}"'.format(json_file))
            os.unlink(json_file)
        log_wrapper.info(
Example #10
0
 def __init__(self, log_wrapper: LogWrapper = LogWrapper()):
     super().__init__(instance_class='rds', log_wrapper=log_wrapper)
Example #11
0
def get_rds_instances(
    aws_client,
    next_token: str = None,
    max_results_per_iteration: int = MAX_RESULTS_DEFAULT,
    log_wrapper=LogWrapper()
) -> list:
    '''Using boto3, get the list of RDS instances and create a AwsRDSInstance 
    instance of each, storing the collection in a result which is then returned.
    '''
    result = list()
    if aws_client is not None:
        try:
            if next_token is not None:
                response = aws_client.describe_db_instances(
                    MaxRecords=max_results_per_iteration, Marker=next_token)
            else:
                response = aws_client.describe_db_instances(
                    MaxRecords=max_results_per_iteration)
            ### Main processing ###

            if 'DBInstances' in response:
                for db_instance_data in response['DBInstances']:
                    rds_instance = AwsRDSInstance(log_wrapper=log_wrapper)
                    rds_instance.store_raw_instance_data(
                        instance_data=db_instance_data)
                    if 'DBInstanceArn' in db_instance_data:
                        rds_instance.tags = get_rds_instance_tags(
                            aws_client=aws_client,
                            db_instance_arn=db_instance_data['DBInstanceArn'],
                            log_wrapper=log_wrapper)
                    else:
                        log_wrapper.warning(
                            message=
                            'The data set did not contain an ARN - tags will NOT be retrieved.'
                        )
                    if rds_instance.raw_instance_data is not None:
                        rds_instance.region = aws_client.meta.region_name
                        rds_instance.metrics = get_instance_cloudwatch_metrics(
                            aws_client=get_service_client_default(
                                service='cloudwatch',
                                region=aws_client.meta.region_name),
                            instance_id=rds_instance.instance_id,
                            service_name='rds',
                            next_token=None,
                            log_wrapper=log_wrapper)
                        if len(rds_instance.metrics) > 0:
                            for metric in rds_instance.metrics:
                                metric_statistics = get_instance_metric_statistics(
                                    aws_client=get_service_client_default(
                                        service='cloudwatch',
                                        region=aws_client.meta.region_name),
                                    instance_id=rds_instance.instance_id,
                                    service_name='rds',
                                    metric_name=metric,
                                    start_timestamp=_get_start_timestamp(),
                                    end_timestamp=_get_end_timestamp(),
                                    period=300,
                                    log_wrapper=log_wrapper)
                                rds_instance.metric_statistics[
                                    metric] = metric_statistics[metric]
                        result.append(rds_instance)

            ### end main processing ###
            if 'Marker' in response:
                if isinstance(response['Marker'], str):
                    if len(response['Marker']) > 0:
                        next_result = get_rds_instances(
                            aws_client=aws_client,
                            next_token=response['Marker'],
                            max_results_per_iteration=max_results_per_iteration,
                            log_wrapper=log_wrapper)
                        result = result + next_result
        except:
            log_wrapper.error(
                message='EXCEPTION: {}'.format(traceback.format_exc()))
    else:
        log_wrapper.warning(
            message=
            'No RDS instances were fetched because the aws_client was not defined - failing gracefully...'
        )
    return result
Example #12
0
def get_ec2_instances(
    aws_client,
    next_token: str = None,
    max_results_per_iteration: int = MAX_RESULTS_DEFAULT,
    log_wrapper=LogWrapper()
) -> list:
    '''Using boto3, get the list of EC2 instances and create a AwsEC2Instance 
    instance of each, storing the collection in a result which is then returned.
    '''
    result = list()
    if aws_client is not None:
        try:
            if next_token is not None:
                response = aws_client.describe_instances(
                    MaxResults=max_results_per_iteration, NextToken=next_token)
            else:
                response = aws_client.describe_instances(
                    MaxResults=max_results_per_iteration)
            ### Main processing ###
            if 'Reservations' in response:
                for reservation in response['Reservations']:
                    if 'Instances' in reservation:
                        for instance_data in reservation['Instances']:
                            ec2instance = AwsEC2Instance(
                                log_wrapper=log_wrapper)
                            ec2instance.store_raw_instance_data(
                                instance_data=instance_data)
                            if ec2instance.raw_instance_data is not None:
                                ec2instance.region = aws_client.meta.region_name
                                ec2instance.metrics = get_instance_cloudwatch_metrics(
                                    aws_client=get_service_client_default(
                                        service='cloudwatch',
                                        region=aws_client.meta.region_name),
                                    instance_id=ec2instance.instance_id,
                                    service_name='ec2',
                                    next_token=None,
                                    log_wrapper=log_wrapper)
                                if len(ec2instance.metrics) > 0:
                                    for metric in ec2instance.metrics:
                                        metric_statistics = get_instance_metric_statistics(
                                            aws_client=
                                            get_service_client_default(
                                                service='cloudwatch',
                                                region=aws_client.meta.
                                                region_name),
                                            instance_id=ec2instance.
                                            instance_id,
                                            service_name='ec2',
                                            metric_name=metric,
                                            start_timestamp=
                                            _get_start_timestamp(),
                                            end_timestamp=_get_end_timestamp(),
                                            period=300,
                                            log_wrapper=log_wrapper)
                                        ec2instance.metric_statistics[
                                            metric] = metric_statistics[metric]
                                result.append(ec2instance)

            ### end main processing ###
            if 'NextToken' in response:
                if isinstance(response['NextToken'], str):
                    if len(response['NextToken']) > 0:
                        next_result = get_ec2_instances(
                            aws_client=aws_client,
                            next_token=response['NextToken'],
                            max_results_per_iteration=max_results_per_iteration,
                            log_wrapper=log_wrapper)
                        result = result + next_result
        except:
            log_wrapper.error(
                message='EXCEPTION: {}'.format(traceback.format_exc()))
    else:
        log_wrapper.warning(
            message=
            'No EC2 instances were fetched because the aws_client was not defined - failing gracefully...'
        )
    return result
Example #13
0
 def __init__(self, log_wrapper: LogWrapper = LogWrapper()):
     self.instances = list()
     self.log_wrapper = log_wrapper