def main(): parser = optparse.OptionParser('Usage: %prog <options>') parser.add_option('-e', '--email', dest='email', help='The email address to send notifications to whenever an ' 'alert is triggered.') parser.add_option('-n', '--name', dest='name', help='The name of the alarm (e.g., BillingAlarm-1000).') parser.add_option('-t', '--threshold', dest='threshold', help='The dollar amount of estimated monthly charges which, ' 'when exceeded, causes an alert to be triggered.') parser.add_option('-p', '--period', dest='period', default=Defaults.PREIOD, help='The period in seconds over which the estimated monthly ' 'charges statistic is applied.') (opts, args) = parser.parse_args() if (0 != len(args) or opts.email is None or opts.threshold is None): parser.print_help() return 1 try: sns = boto.connect_sns() topic = sns.create_topic('BillingNotifications') \ ['CreateTopicResponse'] \ ['CreateTopicResult'] \ ['TopicArn'] res = sns.subscribe(topic, 'email', opts.email) \ ['SubscribeResponse'] \ ['SubscribeResult'] \ ['SubscriptionArn'] if res == 'pending confirmation': raw_input('Please confirm subscription. Press [ENTER] when done...') cloudwatch = boto.connect_cloudwatch() alarm = MetricAlarm(name=opts.name if opts.name is not None else 'BillingAlarm-{0}'.format(opts.threshold), description='Estimated Monthly Charges', alarm_actions=[topic], metric=Defaults.METRIC, namespace='AWS/Billing', statistic=Defaults.STATISTIC, dimensions={'Currency':'USD'}, period=opts.period, evaluation_periods=1, threshold=int(opts.threshold), comparison='>=') cloudwatch.create_alarm(alarm) except Error, err: sys.stderr.write('[ERROR] {0}\n'.format(err)) return 1
def cw_alarm(self, cw_conn, instance_id, email_add): """ Create cloudwatch alarm on an instance when CPU utilisation is less than or equal to 40% for five minutes, and send sns alert to an email address """ sns = boto.sns.connect_to_region('eu-west-1') topic_name = 'cpu_alarm'+instance_id new_sns_topic = sns.create_topic(topic_name) sns_arn = self.get_sns_arn(new_sns_topic) sns.subscribe(sns_arn, 'email', email_add) metrics = cw_conn.list_metrics(dimensions={'InstanceId': instance_id}, metric_name="CPUUtilization") ec2_alarm = metrics[0].create_alarm(name=topic_name, comparison='<=', threshold=40.0, period=300, evaluation_periods=2, statistic='Average', alarm_actions=[sns_arn]) if ec2_alarm: print 'cloudwatch alarm created'
def create_alarm(instance_id): global alarmed if alarmed == False: sns = boto.sns.connect_to_region('eu-west-1') sns.create_topic('DavidK_Network_Problem') # Create a topic arn = 'arn:aws:sns:eu-west-1:808146113457:DavidK_Network_Problem' #Amazon Resource Name, uniquely identify AWS resources sns.subscribe(arn, "email", "*****@*****.**") # subscribe my email to the topic cloudwatch = boto.ec2.cloudwatch.connect_to_region('eu-west-1') # create a list holding the metric that the alarm will be based on metrics = cloudwatch.list_metrics(dimensions={'InstanceId' : instance_id},metric_name='NetworkIn') # call to create the autoscaling group and to get policy arn for the alarm as_policy_arn = create_auto_scaling(instance_id) # create the alarm alarm = metrics[0].create_alarm(name='Network_Usage_Alarm', comparison='>=', threshold=500000, period=60, evaluation_periods=1, statistic='Average', alarm_actions=[arn,as_policy_arn]) if alarm: print '\n----------' print 'Alarm set' print '----------\n' alarmed = True else: print '\nAlarm has not been set\n'
for aws_region in regions: if aws_region in ['cn-north-1', 'us-gov-west-1']: logging.debug('Ignoring restricted region: ' + aws_region) else: logging.info( '********************************************************************************' ) logging.info(' Starting to create CloudTrail resources in region: ' + aws_region) if arguments['--generate_topics']: logging.info('Generating topic for CloudTrail in region: ' + aws_region) sns = boto.sns.connect_to_region(aws_region) logging.debug('Connected to SNS API in region: ' + aws_region) arguments['topic_name'] = sns.create_topic( arguments['--topic_name'] )['CreateTopicResponse']['CreateTopicResult']['TopicArn'] ct = boto.cloudtrail.connect_to_region(aws_region) logging.debug('Connected to CloudTrail API in region: ' + aws_region) if len( ct.describe_trails( trail_name_list=[arguments.get('--trail_name', 'Default') ]).get('trailList', [])) == 0: logging.info('Creating new trail in region ' + aws_region) ct.create_trail(name=arguments.get('--trail_name', 'Default'), s3_bucket_name=output_variables.get( 'bucketName', ''), s3_key_prefix=arguments.get('--s3_key_prefix'), sns_topic_name=arguments.get('topic_name'), include_global_service_events=global_logging)
parser.add_argument("topic", help="A topic name") parser.add_argument( "-d", "--display_name", help= "Override the topics display name (will get region suffix) [default: topic name]" ) args = parser.parse_args() # process common command line arguments log = logging.getLogger('botocross') bc.configure_logging(log, args.log_level) credentials = bc.parse_credentials(args) regions = bc.filter_regions(boto.sns.regions(), args.region) # execute business logic log.info("Creating SNS topics named '" + args.topic + "':") for region in regions: pprint(region.name, indent=2) try: sns = boto.connect_sns(region=region, **credentials) topic = sns.create_topic(args.topic) arn = topic['CreateTopicResponse']['CreateTopicResult']['TopicArn'] print arn display_name = args.display_name if args.display_name else args.topic display_name += '-' + region.name sns.set_topic_attributes(arn, 'DisplayName', display_name) except boto.exception.BotoServerError, e: log.error(e.error_message)
logging.debug('Regions:' + json.dumps(regions)) global_logging = True for aws_region in regions: if aws_region in ['cn-north-1', 'us-gov-west-1']: logging.debug('Ignoring restricted region: ' + aws_region) else: logging.info('********************************************************************************') logging.info(' Starting to create CloudTrail resources in region: ' + aws_region) if arguments['--generate_topics']: logging.info('Generating topic for CloudTrail in region: ' + aws_region) sns = boto.sns.connect_to_region(aws_region) logging.debug('Connected to SNS API in region: ' + aws_region) arguments['topic_name'] = sns.create_topic(arguments['--topic_name'])['CreateTopicResponse']['CreateTopicResult']['TopicArn'] ct = boto.cloudtrail.connect_to_region(aws_region) logging.debug('Connected to CloudTrail API in region: ' + aws_region) if len(ct.describe_trails(trail_name_list=[arguments.get('--trail_name', 'Default')]).get('trailList',[])) == 0: logging.info('Creating new trail in region ' + aws_region) ct.create_trail(name=arguments.get('--trail_name', 'Default'), s3_bucket_name=output_variables.get('bucketName', ''), s3_key_prefix=arguments.get('--s3_key_prefix'), sns_topic_name=arguments.get('topic_name'), include_global_service_events=global_logging) ct.start_logging(name=arguments.get('--trail_name', 'Default')) if global_logging == True: global_logging = False elif ct.get_trail_status('Default').get('IsLogging') == False: logging.info('Updating Trail in region ' + aws_region) ct.update_trail(name=arguments.get('--trail_name', 'Default'), s3_bucket_name=output_variables.get('bucketName', ''), s3_key_prefix=arguments.get('--s3_key_prefix'), sns_topic_name=arguments.get('topic_name'), include_global_service_events=global_logging) if global_logging == True: global_logging = False ct.start_logging(name=arguments.get('--trail_name', 'Default'))
parser.add_argument("--access_key_id", dest='aws_access_key_id', help="Your AWS Access Key ID") parser.add_argument("--secret_access_key", dest='aws_secret_access_key', help="Your AWS Secret Access Key") args = parser.parse_args() credentials = {'aws_access_key_id': args.aws_access_key_id, 'aws_secret_access_key': args.aws_secret_access_key} def isSelected(region): return True if region.name.find(args.region) != -1 else False # execute business logic heading = "Creating SNS topics named '" + args.topic + "'" regions = boto.sns.regions() if args.region: heading += " (filtered by region '" + args.region + "')" regions = filter(isSelected, regions) print heading + ":" for region in regions: pprint(region.name, indent=2) try: sns = boto.connect_sns(region=region, **credentials) print 'Creating topic ' + args.topic topic = sns.create_topic(args.topic) arn = topic['CreateTopicResponse']['CreateTopicResult']['TopicArn'] print('... topic ARN is ' + arn) display_name = args.display_name if args.display_name else args.topic display_name += '-' + region.name sns.set_topic_attributes(arn, 'DisplayName', display_name) except boto.exception.BotoServerError, e: print e.error_message
def alarmProcessor(): # Firstly we need to connect to the Simple Notification Service and CloudWatch service - this was a bit tricky and again the documentation was unclear. I thought you would use boto.connect_sns(region=reg) # which seems to successfully connect and is similar to how we connected to S3 and EC2 services. However calling methods e.g. get_all_topics() yields the error "The requested version (2010-03-31) of # service AmazonEC2 does not exist". On further investigation I found that to connect use boto.sns.connect_to_region(). You have to supply the region as an argument - note that it expected a string # not a region object - which again is inconsistent with EC2. To connect to the CloudWatch service as with SNS you have to use the connect_to_region() method sns = boto.sns.connect_to_region("eu-west-1") cw = boto.ec2.cloudwatch.connect_to_region("eu-west-1") if (not args.clear): print "\nCreating new topics (+ subscription) and alarms:\n" # Once connected we create a topic which is basically an access point composed of an identifier and recipients to send message to. create_topic() returns a unique ARN (Amazon Resource Name) which # will include the service name (SNS), region, AWS ID of the user and the topic name - this is a dict so we need to go three levels in to get the actual ARN number. We will use the arn when # we create a subscription which is how we link a topic to an endpoint like an email address. topicName = 'TopicStephenCIT-1-UID'+str(random.randrange(1000000)) response = sns.create_topic(topicName) topicARN = response['CreateTopicResponse']['CreateTopicResult']['TopicArn'] print '\tTopic ARN created: ',topicARN #Subscribe links a topic with an endpoint - in this case an email address sns.subscribe(topicARN, 'email', args.email) #We now have topic/subscription - the email address supplied will have to accept the AWS Notification Subscription Confirmation email message to ensure they get alerts # We will now create a unique alarm per instance. We can use the create_alarm method which expects a boto.ec2.cloudwatch.alarm.MetricAlarm object. This object defines # all the properties of the alarm - name,metric,topic etc. We loop through all the instance and create an alarm for each instance. Note we use the ARN that was created # above which ties the alarm to notification logic for index, inst in enumerate(instances): alarmName = "StephenMurrayCPU-" + str(index) + inst.id +'-UID' + str(random.randrange(1000000)) alarm = boto.ec2.cloudwatch.MetricAlarm(name=alarmName, namespace='AWS/EC2',metric='CPUUtilization', statistic='Average',comparison='<', threshold='40',period='60', evaluation_periods=2, dimensions = {"InstanceId": inst.id}, alarm_actions= topicARN) cw.create_alarm(alarm) print "\tAlarm created", alarmName else: print "\nClearing topics, subscriptions (confirmed) and alarms:\n" #Get all topics returnAllTopicsObject = sns.get_all_topics() #to access the ARN field we need have to go 3 levels deep into returned object topics = returnAllTopicsObject['ListTopicsResponse']['ListTopicsResult']['Topics'] #now we have a list containing dicts where the only value is the TopicArn which is what we need to supply the delete method # only do action if list is not empty - there has to be some topics to delete if topics: for t in (topics): topicARNDelete = t['TopicArn'] #delete topics sns.delete_topic(topicARNDelete) print "\tTopic Deleted: ", topicARNDelete else: print "\tNo topics found" # Get all subscriptions # Very similar to topics - get subscriptions, extract relevant parameter from retuned dict object, loop through, get SubscriptionArn # and send for deletion - also do a check to ensure subscriptions exist returnAllSubObject = sns.get_all_subscriptions() #to access the Sub ARN field we need have to go 3 levels deep into returned object subscriptions = returnAllSubObject['ListSubscriptionsResponse']['ListSubscriptionsResult']['Subscriptions'] if subscriptions: for s in (subscriptions): subARNDelete = s['SubscriptionArn'] #delete subscription only if returned value is not equal to PendingConfirmation if (subARNDelete != 'PendingConfirmation'): sns.unsubscribe(subARNDelete) print "\tSunscription Deleted: ", subARNDelete else: print "\tNo subscriptions found" #Get all alarms #describe_alarms() returns a list of boto.ec2.cloudwatch.alarm.MetricAlarms object from which we can extract the alarm name (.name method) which we can # use to delete it - Note in this case we do not require the ARN to delete - on testing with IDLE it was noted that when a complete arn # arn:aws:cloudwatch:eu-west-1:135577527805:alarm:StephenMurrayCPU0i-690b332b was supplied the delete_alarms() method returned True even though it was # not deleted...this is not good as as when StephenMurrayCPU0i-690b332b was supplied it deleted the alarm and also returned True. alarms = cw.describe_alarms() if alarms: for a in (alarms): cw.delete_alarms(a.name) print "\tAlarms Deleted: ", a.name else: print "\tNo alarms found"
def main(): parser = optparse.OptionParser('Usage: %prog <options>') parser.add_option( '-e', '--email', dest='email', help='The email address to send notifications to whenever an ' 'alert is triggered.') parser.add_option('-n', '--name', dest='name', help='The name of the alarm (e.g., BillingAlarm-1000).') parser.add_option( '-t', '--threshold', dest='threshold', help='The dollar amount of estimated monthly charges which, ' 'when exceeded, causes an alert to be triggered.') parser.add_option( '-p', '--period', dest='period', default=Defaults.PREIOD, help='The period in seconds over which the estimated monthly ' 'charges statistic is applied.') (opts, args) = parser.parse_args() if (0 != len(args) or opts.email is None or opts.threshold is None): parser.print_help() return 1 try: sns = boto.connect_sns() topic = sns.create_topic('BillingNotifications') \ ['CreateTopicResponse'] \ ['CreateTopicResult'] \ ['TopicArn'] res = sns.subscribe(topic, 'email', opts.email) \ ['SubscribeResponse'] \ ['SubscribeResult'] \ ['SubscriptionArn'] if res == 'pending confirmation': raw_input( 'Please confirm subscription. Press [ENTER] when done...') cloudwatch = boto.connect_cloudwatch() alarm = MetricAlarm(name=opts.name if opts.name is not None else 'BillingAlarm-{0}'.format(opts.threshold), description='Estimated Monthly Charges', alarm_actions=[topic], metric=Defaults.METRIC, namespace='AWS/Billing', statistic=Defaults.STATISTIC, dimensions={'Currency': 'USD'}, period=opts.period, evaluation_periods=1, threshold=int(opts.threshold), comparison='>=') cloudwatch.create_alarm(alarm) except Error, err: sys.stderr.write('[ERROR] {0}\n'.format(err)) return 1