X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=plugins%2FCloudWatch%2Fmetric_alarms.py;h=bd76c81847b020beefa4c175f48391688bd2baf5;hb=b9bcdc37e0c5d4fc27916ac0e4f7e59a1257f369;hp=c58987db42480b02a988b0e760a8876ea0b17579;hpb=f6064437ba352d7fee6b4a7a4e7cb2582ef5cd32;p=osm%2FMON.git diff --git a/plugins/CloudWatch/metric_alarms.py b/plugins/CloudWatch/metric_alarms.py index c58987d..bd76c81 100644 --- a/plugins/CloudWatch/metric_alarms.py +++ b/plugins/CloudWatch/metric_alarms.py @@ -1,13 +1,41 @@ +## +# Copyright 2017 xFlow Research Pvt. Ltd +# This file is part of MON module +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact with: wajeeha.hamid@xflowresearch.com +## + +''' Handling of alarms requests via BOTO 2.48 ''' + +__author__ = "Wajeeha Hamid" +__date__ = "18-September-2017" + import sys import os import re import datetime import random +import json import logging as log from random import randint from operator import itemgetter from connection import Connection + try: import boto import boto.ec2 @@ -19,31 +47,35 @@ except: class MetricAlarm(): - """Alarms Functionality Handler -- Cloudwatch """ - - def config_alarm(self,cloudwatch_conn,alarm_info): - """Configure or Create a new alarm""" + """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """ + def __init__(self): + self.alarm_resp = dict() + self.del_resp = dict() + def config_alarm(self,cloudwatch_conn,create_info): + """Configure or Create a new alarm""" + inner_dict = dict() """ Alarm Name to ID Mapping """ - alarm_id = alarm_info['alarm_name'] + "_" + alarm_info['resource_id'] - if self.is_present(cloudwatch_conn,alarm_id) == True: + alarm_info = create_info['alarm_create_request'] + alarm_id = alarm_info['alarm_name'] + "_" + alarm_info['resource_uuid'] + if self.is_present(cloudwatch_conn,alarm_id)['status'] == True: alarm_id = None log.debug ("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'") else: try: alarm = boto.ec2.cloudwatch.alarm.MetricAlarm( connection = cloudwatch_conn, - name = alarm_info['alarm_name'] + "_" + alarm_info['resource_id'], - metric = alarm_info['alarm_metric'], - namespace = alarm_info['instance_type'], - statistic = alarm_info['alarm_statistics'], - comparison = alarm_info['alarm_comparison'], - threshold = alarm_info['alarm_threshold'], - period = alarm_info['alarm_period'], - evaluation_periods = alarm_info['alarm_evaluation_period'], - unit=alarm_info['alarm_unit'], - description = alarm_info['alarm_severity'] + ";" + alarm_info['alarm_description'], - dimensions = {'InstanceId':alarm_info['resource_id']}, + name = alarm_info['alarm_name'] + "_" + alarm_info['resource_uuid'], + metric = alarm_info['metric_name'], + namespace = "AWS/EC2", + statistic = alarm_info['statistic'], + comparison = alarm_info['operation'], + threshold = alarm_info['threshold_value'], + period = 60, + evaluation_periods = 1, + unit=alarm_info['unit'], + description = alarm_info['severity'] + ";" + alarm_id + ";" + alarm_info['description'], + dimensions = {'InstanceId':alarm_info['resource_uuid']}, alarm_actions = None, ok_actions = None, insufficient_data_actions = None) @@ -51,126 +83,181 @@ class MetricAlarm(): """Setting Alarm Actions : alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']""" - cloudwatch_conn.put_metric_alarm(alarm) + status=cloudwatch_conn.put_metric_alarm(alarm) + log.debug ("Alarm Configured Succesfully") - print "created" - print "\n" + self.alarm_resp['schema_version'] = str(create_info['schema_version']) + self.alarm_resp['schema_type'] = 'create_alarm_response' + + inner_dict['correlation_id'] = str(alarm_info['correlation_id']) + inner_dict['alarm_uuid'] = str(alarm_id) + inner_dict['status'] = status + + self.alarm_resp['alarm_create_response'] = inner_dict + if status == True: + return self.alarm_resp + else: + return None + except Exception as e: log.error("Alarm Configuration Failed: " + str(e)) - return alarm_id + #----------------------------------------------------------------------------------------------------------------------------- - def update_alarm(self,cloudwatch_conn,alarm_info): + def update_alarm(self,cloudwatch_conn,update_info): """Update or reconfigure an alarm""" - + inner_dict = dict() + alarm_info = update_info['alarm_update_request'] + """Alarm Name to ID Mapping""" - alarm_id = alarm_info['alarm_name'] + "_" + alarm_info['resource_id'] + alarm_id = alarm_info['alarm_uuid'] + status = self.is_present(cloudwatch_conn,alarm_id) """Verifying : Alarm exists already""" - if self.is_present(cloudwatch_conn,alarm_id) == False: + if status['status'] == False: alarm_id = None - log.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'") + log.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'") + return alarm_id else: try: alarm = boto.ec2.cloudwatch.alarm.MetricAlarm( - connection = cloudwatch_conn, - name = alarm_info['alarm_name'] + "_" + alarm_info['resource_id'], - metric = alarm_info['alarm_metric'], - namespace = alarm_info['instance_type'], - statistic = alarm_info['alarm_statistics'], - comparison = alarm_info['alarm_comparison'], - threshold = alarm_info['alarm_threshold'], - period = alarm_info['alarm_period'], - evaluation_periods = alarm_info['alarm_evaluation_period'], - unit=alarm_info['alarm_unit'], - description = alarm_info['alarm_severity'] + ";" + alarm_info['alarm_description'], - dimensions = {'InstanceId':alarm_info['resource_id']}, - alarm_actions = None, - ok_actions = None, - insufficient_data_actions = None) - cloudwatch_conn.put_metric_alarm(alarm) + connection = cloudwatch_conn, + name = status['info'].name , + metric = alarm_info['metric_name'], + namespace = "AWS/EC2", + statistic = alarm_info['statistic'], + comparison = alarm_info['operation'], + threshold = alarm_info['threshold_value'], + period = 60, + evaluation_periods = 1, + unit=alarm_info['unit'], + description = alarm_info['severity'] + ";" + alarm_id + ";" + alarm_info['description'], + dimensions = {'InstanceId':str(status['info'].dimensions['InstanceId']).split("'")[1]}, + alarm_actions = None, + ok_actions = None, + insufficient_data_actions = None) + + """Setting Alarm Actions : + alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']""" + + status=cloudwatch_conn.put_metric_alarm(alarm) log.debug("Alarm %s Updated ",alarm.name) - print "updated" + self.alarm_resp['schema_version'] = str(update_info['schema_version']) + self.alarm_resp['schema_type'] = 'update_alarm_response' + + inner_dict['correlation_id'] = str(alarm_info['correlation_id']) + inner_dict['alarm_uuid'] = str(alarm_id) + inner_dict['status'] = status + + self.alarm_resp['alarm_update_response'] = inner_dict + return self.alarm_resp except Exception as e: log.error ("Error in Updating Alarm " + str(e)) - return alarm_id + #----------------------------------------------------------------------------------------------------------------------------- - def delete_Alarm(self,cloudwatch_conn,alarm_id): + def delete_Alarm(self,cloudwatch_conn,del_info_all): + """Deletes an Alarm with specified alarm_id""" + inner_dict = dict() + del_info = del_info_all['alarm_delete_request'] + status = self.is_present(cloudwatch_conn,del_info['alarm_uuid']) try: - if self.is_present(cloudwatch_conn,alarm_id) == True: - deleted_alarm=cloudwatch_conn.delete_alarms(alarm_id) - return alarm_id + if status['status'] == True: + del_status=cloudwatch_conn.delete_alarms(status['info'].name) + self.del_resp['schema_version'] = str(del_info_all['schema_version']) + self.del_resp['schema_type'] = 'delete_alarm_response' + inner_dict['correlation_id'] = str(del_info['correlation_id']) + inner_dict['alarm_id'] = str(del_info['alarm_uuid']) + inner_dict['status'] = del_status + self.del_resp['alarm_deletion_response'] = inner_dict + return self.del_resp return None except Exception as e: log.error("Alarm Not Deleted: " + str(e)) #----------------------------------------------------------------------------------------------------------------------------- - def alarms_list(self,cloudwatch_conn,instance_id): + def alarms_list(self,cloudwatch_conn,list_info): - """Get a list of alarms that are present on a particular VM instance""" - try: - log.debug("Getting Alarm list for %s",instance_id) - alarm_dict = dict() - alarm_list = [] + """Get a list of alarms that are present on a particular VIM type""" + alarm_list = [] + alarm_info = dict() + try: #id vim alarms = cloudwatch_conn.describe_alarms() itr = 0 for alarm in alarms: - if str(alarm.dimensions['InstanceId']).split("'")[1] == instance_id: - alarm_list.insert(itr,str(alarm.name)) - itr += 1 - alarm_dict['alarm_names'] = alarm_list - alarm_dict['resource_id'] = instance_id - return alarm_dict + list_info['alarm_list_request']['alarm_uuid'] = str(alarm.description).split(';')[1] + alarm_list.insert(itr,self.alarm_details(cloudwatch_conn,list_info)) + itr += 1 + + alarm_info['schema_version'] = str(list_info['schema_version']) + alarm_info['schema_type'] = 'list_alarm_response' + alarm_info['list_alarm_resp'] = json.dumps(alarm_list) + + return alarm_info except Exception as e: log.error("Error in Getting List : %s",str(e)) #----------------------------------------------------------------------------------------------------------------------------- - def alarm_details(self,cloudwatch_conn,alarm_name): + def alarm_details(self,cloudwatch_conn,ack_info): """Get an individual alarm details specified by alarm_name""" try: - alarms_details=cloudwatch_conn.describe_alarm_history() + alarms_details=cloudwatch_conn.describe_alarm_history() + alarm_details_all = dict() alarm_details_dict = dict() + ack_info_all = ack_info + + + if 'ack_details' in ack_info: + ack_info = ack_info['ack_details'] + elif 'alarm_list_request' in ack_info: + ack_info = ack_info['alarm_list_request'] + is_present = self.is_present(cloudwatch_conn,ack_info['alarm_uuid']) + for itr in range (len(alarms_details)): - if alarms_details[itr].name == alarm_name and 'created' in alarms_details[itr].summary :#name, timestamp, summary - status = alarms_details[itr].summary.split() + if alarms_details[itr].name == is_present['info'].name :#name, timestamp, summary + if 'created' in alarms_details[itr].summary: + alarm_details_dict['status'] = "New" + elif 'updated' in alarms_details[itr].summary: + alarm_details_dict['status'] = "Update" + elif 'deleted' in alarms_details[itr].summary: + alarm_details_dict['status'] = "Canceled" + + status = alarms_details[itr].summary.split() alarms = cloudwatch_conn.describe_alarms() for alarm in alarms: - if alarm.name == alarm_name: - alarm_details_dict['alarm_id'] = alarm_name - alarm_details_dict['resource_id'] = str(alarm.dimensions['InstanceId']).split("'")[1] - alarm_details_dict['severity'] = str(alarm.description) - alarm_details_dict['start_date_time'] = str(alarms_details[x].timestamp) + if str(alarm.description).split(';')[1] == ack_info['alarm_uuid']: + alarm_details_dict['alarm_uuid'] = str(ack_info['alarm_uuid']) + alarm_details_dict['resource_uuid'] = str(alarm.dimensions['InstanceId']).split("'")[1] + alarm_details_dict['description'] = str(alarm.description).split(';')[1] + alarm_details_dict['severity'] = str(alarm.description).split(';')[0] + alarm_details_dict['start_date_time'] = str(alarms_details[itr].timestamp) + alarm_details_dict['vim_type'] = str(ack_info_all['vim_type']) + #TODO : tenant id + if 'ack_details' in ack_info_all: + alarm_details_all['schema_version'] = str(ack_info_all['schema_version']) + alarm_details_all['schema_type'] = 'notify_alarm' + alarm_details_all['notify_details'] = alarm_details_dict + return alarm_details_all - return alarm_details_dict + elif 'alarm_list_request' in ack_info_all: + return alarm_details_dict except Exception as e: log.error("Error getting alarm details: %s",str(e)) #----------------------------------------------------------------------------------------------------------------------------- - def metrics_data(self,cloudwatch_conn,metric_name,instance_id,period,metric_unit): - - """Getting Metrics Stats for an Hour. Time interval can be modified using Timedelta value""" - metric_data= dict() - metric_stats=cloudwatch_conn.get_metric_statistics(period, datetime.datetime.utcnow() - datetime.timedelta(seconds=3600), - datetime.datetime.utcnow(),metric_name,'AWS/EC2', 'Maximum', - dimensions={'InstanceId':instance_id}, unit=metric_unit) - - for itr in range (len(metric_stats)): - metric_data['metric_name'] = metric_name - metric_data['Resource_id'] = instance_id - metric_data['Unit'] = metric_stats[itr]['Unit'] - metric_data['Timestamp'] = metric_stats[itr]['Timestamp'] - return metric_data - -#----------------------------------------------------------------------------------------------------------------------------- - def is_present(self,cloudwatch_conn,alarm_name): - """Finding Alarm exists or not""" + def is_present(self,cloudwatch_conn,alarm_id): + """Finding alarm from already configured alarms""" + alarm_info = dict() try: alarms = cloudwatch_conn.describe_alarms() for alarm in alarms: - if alarm.name == alarm_name: - return True - return False + if str(alarm.description).split(';')[1] == alarm_id: + alarm_info['status'] = True + alarm_info['info'] = alarm + return alarm_info + alarm_info['status'] = False + return alarm_info except Exception as e: log.error("Error Finding Alarm",str(e)) #----------------------------------------------------------------------------------------------------------------------------- + \ No newline at end of file