Merge "Changes in vROPs Plugin. 1.Added specifications for Create, Update, Delete...
[osm/MON.git] / plugins / CloudWatch / metric_alarms.py
index c58987d..bd76c81 100644 (file)
@@ -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