2 # Copyright 2017 xFlow Research Pvt. Ltd
3 # This file is part of MON module
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
18 # For those usages not covered by the Apache License, Version 2.0 please
19 # contact with: wajeeha.hamid@xflowresearch.com
22 ''' Handling of alarms requests via BOTO 2.48 '''
24 __author__
= "Wajeeha Hamid"
25 __date__
= "18-September-2017"
34 from random
import randint
35 from operator
import itemgetter
36 from connection
import Connection
43 import boto
.ec2
.cloudwatch
44 import boto
.ec2
.connection
46 exit("Boto not avialable. Try activating your virtualenv OR `pip install boto`")
52 "COUNT" : "SampleCount",
63 """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """
65 self
.alarm_resp
= dict()
66 self
.del_resp
= dict()
68 def config_alarm(self
,cloudwatch_conn
,create_info
):
69 """Configure or Create a new alarm"""
71 """ Alarm Name to ID Mapping """
72 alarm_info
= create_info
['alarm_create_request']
73 alarm_id
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid']
74 if self
.is_present(cloudwatch_conn
,alarm_id
)['status'] == True:
76 log
.debug ("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'")
79 if alarm_info
['statistic'] in STATISTICS
:
80 if alarm_info
['operation'] in OPERATIONS
:
81 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
82 connection
= cloudwatch_conn
,
83 name
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
84 metric
= alarm_info
['metric_name'],
85 namespace
= "AWS/EC2",
86 statistic
= STATISTICS
[alarm_info
['statistic']],
87 comparison
= OPERATIONS
[alarm_info
['operation']],
88 threshold
= alarm_info
['threshold_value'],
90 evaluation_periods
= 1,
91 unit
=alarm_info
['unit'],
92 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
93 dimensions
= {'InstanceId':alarm_info
['resource_uuid']},
96 insufficient_data_actions
= None)
98 """Setting Alarm Actions :
99 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
101 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
103 log
.debug ("Alarm Configured Succesfully")
104 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
105 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
107 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
108 inner_dict
['alarm_uuid'] = str(alarm_id
)
109 inner_dict
['status'] = status
111 self
.alarm_resp
['alarm_create_response'] = inner_dict
114 return self
.alarm_resp
118 log
.error("Operation not supported")
121 log
.error("Statistic not supported")
123 except Exception as e
:
124 log
.error("Alarm Configuration Failed: " + str(e
))
126 #-----------------------------------------------------------------------------------------------------------------------------
127 def update_alarm(self
,cloudwatch_conn
,update_info
):
129 """Update or reconfigure an alarm"""
131 alarm_info
= update_info
['alarm_update_request']
133 """Alarm Name to ID Mapping"""
134 alarm_id
= alarm_info
['alarm_uuid']
135 status
= self
.is_present(cloudwatch_conn
,alarm_id
)
137 """Verifying : Alarm exists already"""
138 if status
['status'] == False:
140 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
144 if alarm_info
['statistic'] in STATISTICS
:
145 if alarm_info
['operation'] in OPERATIONS
:
146 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
147 connection
= cloudwatch_conn
,
148 name
= status
['info'].name
,
149 metric
= alarm_info
['metric_name'],
150 namespace
= "AWS/EC2",
151 statistic
= STATISTICS
[alarm_info
['statistic']],
152 comparison
= OPERATIONS
[alarm_info
['operation']],
153 threshold
= alarm_info
['threshold_value'],
155 evaluation_periods
= 1,
156 unit
=alarm_info
['unit'],
157 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
158 dimensions
= {'InstanceId':str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
159 alarm_actions
= None,
161 insufficient_data_actions
= None)
163 """Setting Alarm Actions :
164 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
166 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
167 log
.debug("Alarm %s Updated ",alarm
.name
)
168 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
169 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
171 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
172 inner_dict
['alarm_uuid'] = str(alarm_id
)
173 inner_dict
['status'] = status
175 self
.alarm_resp
['alarm_update_response'] = inner_dict
176 return self
.alarm_resp
178 log
.error("Operation not supported")
181 log
.error("Statistic not supported")
183 except Exception as e
:
184 log
.error ("Error in Updating Alarm " + str(e
))
186 #-----------------------------------------------------------------------------------------------------------------------------
187 def delete_Alarm(self
,cloudwatch_conn
,del_info_all
):
189 """Deletes an Alarm with specified alarm_id"""
191 del_info
= del_info_all
['alarm_delete_request']
192 status
= self
.is_present(cloudwatch_conn
,del_info
['alarm_uuid'])
194 if status
['status'] == True:
195 del_status
=cloudwatch_conn
.delete_alarms(status
['info'].name
)
196 self
.del_resp
['schema_version'] = str(del_info_all
['schema_version'])
197 self
.del_resp
['schema_type'] = 'delete_alarm_response'
198 inner_dict
['correlation_id'] = str(del_info
['correlation_id'])
199 inner_dict
['alarm_id'] = str(del_info
['alarm_uuid'])
200 inner_dict
['status'] = del_status
201 self
.del_resp
['alarm_deletion_response'] = inner_dict
204 except Exception as e
:
205 log
.error("Alarm Not Deleted: " + str(e
))
206 #-----------------------------------------------------------------------------------------------------------------------------
207 def alarms_list(self
,cloudwatch_conn
,list_info
):
209 """Get a list of alarms that are present on a particular VIM type"""
212 inner_dict
= list_info
['alarm_list_request']
214 alarms
= cloudwatch_conn
.describe_alarms()
217 list_info
['alarm_list_request']['alarm_uuid'] = str(alarm
.description
).split(';')[1]
219 #Severity = alarm_name = resource_uuid = ""
220 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
221 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
223 #alarm_name = resource_uuid = ""
224 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
225 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
227 #severity = resource_uuid = ""
228 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
229 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
231 #severity = alarm_name = ""
232 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
233 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
236 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
237 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
240 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
241 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
244 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
245 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
248 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
249 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
252 alarm_info
['schema_version'] = str(list_info
['schema_version'])
253 alarm_info
['schema_type'] = 'list_alarm_response'
254 alarm_info
['list_alarm_resp'] = alarm_list
257 except Exception as e
:
258 log
.error("Error in Getting List : %s",str(e
))
259 #-----------------------------------------------------------------------------------------------------------------------------
260 def alarm_details(self
,cloudwatch_conn
,ack_info
):
262 """Get an individual alarm details specified by alarm_name"""
264 alarms_details
=cloudwatch_conn
.describe_alarm_history()
265 alarm_details_all
= dict()
266 alarm_details_dict
= dict()
267 ack_info_all
= ack_info
270 if 'ack_details' in ack_info
:
271 ack_info
= ack_info
['ack_details']
272 elif 'alarm_list_request' in ack_info
:
273 ack_info
= ack_info
['alarm_list_request']
275 is_present
= self
.is_present(cloudwatch_conn
,ack_info
['alarm_uuid'])
277 for itr
in range (len(alarms_details
)):
278 if alarms_details
[itr
].name
== is_present
['info'].name
:#name, timestamp, summary
279 if 'created' in alarms_details
[itr
].summary
:
280 alarm_details_dict
['status'] = "New"
281 elif 'updated' in alarms_details
[itr
].summary
:
282 alarm_details_dict
['status'] = "Update"
283 elif 'deleted' in alarms_details
[itr
].summary
:
284 alarm_details_dict
['status'] = "Canceled"
286 status
= alarms_details
[itr
].summary
.split()
287 alarms
= cloudwatch_conn
.describe_alarms()
289 if str(alarm
.description
).split(';')[1] == ack_info
['alarm_uuid']:
290 alarm_details_dict
['alarm_uuid'] = str(ack_info
['alarm_uuid'])
291 alarm_details_dict
['resource_uuid'] = str(alarm
.dimensions
['InstanceId']).split("'")[1]
292 alarm_details_dict
['description'] = str(alarm
.description
).split(';')[1]
293 alarm_details_dict
['severity'] = str(alarm
.description
).split(';')[0]
294 alarm_details_dict
['start_date_time'] = str(alarms_details
[itr
].timestamp
)
295 alarm_details_dict
['vim_type'] = str(ack_info_all
['vim_type'])
297 if 'ack_details' in ack_info_all
:
298 alarm_details_all
['schema_version'] = str(ack_info_all
['schema_version'])
299 alarm_details_all
['schema_type'] = 'notify_alarm'
300 alarm_details_all
['notify_details'] = alarm_details_dict
301 return alarm_details_all
303 elif 'alarm_list_request' in ack_info_all
:
304 return alarm_details_dict
306 except Exception as e
:
307 log
.error("Error getting alarm details: %s",str(e
))
308 #-----------------------------------------------------------------------------------------------------------------------------
309 def is_present(self
,cloudwatch_conn
,alarm_id
):
310 """Finding alarm from already configured alarms"""
313 alarms
= cloudwatch_conn
.describe_alarms()
315 if str(alarm
.description
).split(';')[1] == alarm_id
:
316 alarm_info
['status'] = True
317 alarm_info
['info'] = alarm
319 alarm_info
['status'] = False
321 except Exception as e
:
322 log
.error("Error Finding Alarm",str(e
))
323 #-----------------------------------------------------------------------------------------------------------------------------