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"
29 log
= logging
.getLogger(__name__
)
35 import boto
.ec2
.cloudwatch
36 import boto
.ec2
.connection
38 exit("Boto not avialable. Try activating your virtualenv OR `pip install boto`")
44 "COUNT": "SampleCount",
56 """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """
59 self
.alarm_resp
= dict()
60 self
.del_resp
= dict()
62 def config_alarm(self
, cloudwatch_conn
, create_info
):
63 """Configure or Create a new alarm"""
65 """ Alarm Name to ID Mapping """
66 alarm_info
= create_info
['alarm_create_request']
67 alarm_id
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid']
68 if self
.is_present(cloudwatch_conn
, alarm_id
)['status'] == True:
70 log
.debug("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'")
74 if alarm_info
['statistic'] in STATISTICS
:
75 if alarm_info
['operation'] in OPERATIONS
:
76 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
77 connection
=cloudwatch_conn
,
78 name
=alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
79 metric
=alarm_info
['metric_name'],
81 statistic
=STATISTICS
[alarm_info
['statistic']],
82 comparison
=OPERATIONS
[alarm_info
['operation']],
83 threshold
=alarm_info
['threshold_value'],
86 unit
=alarm_info
['unit'],
87 description
=alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
88 dimensions
={'InstanceId': alarm_info
['resource_uuid']},
91 insufficient_data_actions
=None)
93 """Setting Alarm Actions :
94 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
96 status
= cloudwatch_conn
.put_metric_alarm(alarm
)
98 log
.debug("Alarm Configured Succesfully")
99 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
100 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
102 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
103 inner_dict
['alarm_uuid'] = str(alarm_id
)
104 inner_dict
['status'] = status
106 self
.alarm_resp
['alarm_create_response'] = inner_dict
109 return self
.alarm_resp
113 log
.error("Operation not supported")
116 log
.error("Statistic not supported")
118 except Exception as e
:
119 log
.error("Alarm Configuration Failed: " + str(e
))
121 def update_alarm(self
, cloudwatch_conn
, update_info
):
123 """Update or reconfigure an alarm"""
125 alarm_info
= update_info
['alarm_update_request']
127 """Alarm Name to ID Mapping"""
128 alarm_id
= alarm_info
['alarm_uuid']
129 status
= self
.is_present(cloudwatch_conn
, alarm_id
)
131 """Verifying : Alarm exists already"""
132 if status
['status'] == False:
134 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
138 if alarm_info
['statistic'] in STATISTICS
:
139 if alarm_info
['operation'] in OPERATIONS
:
140 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
141 connection
=cloudwatch_conn
,
142 name
=status
['info'].name
,
143 metric
=alarm_info
['metric_name'],
145 statistic
=STATISTICS
[alarm_info
['statistic']],
146 comparison
=OPERATIONS
[alarm_info
['operation']],
147 threshold
=alarm_info
['threshold_value'],
149 evaluation_periods
=1,
150 unit
=alarm_info
['unit'],
151 description
=alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
152 dimensions
={'InstanceId': str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
155 insufficient_data_actions
=None)
157 """Setting Alarm Actions :
158 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
160 status
= cloudwatch_conn
.put_metric_alarm(alarm
)
161 log
.debug("Alarm %s Updated ", alarm
.name
)
162 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
163 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
165 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
166 inner_dict
['alarm_uuid'] = str(alarm_id
)
167 inner_dict
['status'] = status
169 self
.alarm_resp
['alarm_update_response'] = inner_dict
170 return self
.alarm_resp
172 log
.error("Operation not supported")
175 log
.error("Statistic not supported")
177 except Exception as e
:
178 log
.error("Error in Updating Alarm " + str(e
))
180 def delete_Alarm(self
, cloudwatch_conn
, del_info_all
):
182 """Deletes an Alarm with specified alarm_id"""
184 del_info
= del_info_all
['alarm_delete_request']
185 status
= self
.is_present(cloudwatch_conn
, del_info
['alarm_uuid'])
187 if status
['status'] == True:
188 del_status
= cloudwatch_conn
.delete_alarms(status
['info'].name
)
189 self
.del_resp
['schema_version'] = str(del_info_all
['schema_version'])
190 self
.del_resp
['schema_type'] = 'delete_alarm_response'
191 inner_dict
['correlation_id'] = str(del_info
['correlation_id'])
192 inner_dict
['alarm_id'] = str(del_info
['alarm_uuid'])
193 inner_dict
['status'] = del_status
194 self
.del_resp
['alarm_deletion_response'] = inner_dict
197 except Exception as e
:
198 log
.error("Alarm Not Deleted: " + str(e
))
200 def alarms_list(self
, cloudwatch_conn
, list_info
):
202 """Get a list of alarms that are present on a particular VIM type"""
205 inner_dict
= list_info
['alarm_list_request']
207 alarms
= cloudwatch_conn
.describe_alarms()
210 list_info
['alarm_list_request']['alarm_uuid'] = str(alarm
.description
).split(';')[1]
212 # Severity = alarm_name = resource_uuid = ""
213 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
[
214 'resource_uuid'] == "":
215 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
217 # alarm_name = resource_uuid = ""
218 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and \
219 inner_dict
['resource_uuid'] == "":
220 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
222 # severity = resource_uuid = ""
223 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
[
224 'resource_uuid'] == "":
225 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
227 # severity = alarm_name = ""
228 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == \
229 str(alarm
.dimensions
['InstanceId']).split("'")[1]:
230 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
233 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
[
234 'alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
235 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
238 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and \
239 inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
240 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
243 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
[
244 'resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
245 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
247 # Everything provided
248 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
[
249 'alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == \
250 str(alarm
.dimensions
['InstanceId']).split("'")[1]:
251 alarm_list
.insert(itr
, self
.alarm_details(cloudwatch_conn
, list_info
))
254 alarm_info
['schema_version'] = str(list_info
['schema_version'])
255 alarm_info
['schema_type'] = 'list_alarm_response'
256 alarm_info
['list_alarm_response'] = alarm_list
259 except Exception as e
:
260 log
.error("Error in Getting List : %s", str(e
))
262 def alarm_details(self
, cloudwatch_conn
, ack_info
):
264 """Get an individual alarm details specified by alarm_name"""
266 alarms_details
= cloudwatch_conn
.describe_alarm_history()
267 alarm_details_all
= dict()
268 alarm_details_dict
= dict()
269 ack_info_all
= ack_info
271 if 'ack_details' in ack_info
:
272 ack_info
= ack_info
['ack_details']
273 elif 'alarm_list_request' in ack_info
:
274 ack_info
= ack_info
['alarm_list_request']
276 is_present
= self
.is_present(cloudwatch_conn
, ack_info
['alarm_uuid'])
278 for itr
in range(len(alarms_details
)):
279 if alarms_details
[itr
].name
== is_present
['info'].name
: # name, timestamp, summary
280 if 'created' in alarms_details
[itr
].summary
:
281 alarm_details_dict
['status'] = "New"
282 elif 'updated' in alarms_details
[itr
].summary
:
283 alarm_details_dict
['status'] = "Update"
284 elif 'deleted' in alarms_details
[itr
].summary
:
285 alarm_details_dict
['status'] = "Canceled"
287 status
= alarms_details
[itr
].summary
.split()
288 alarms
= cloudwatch_conn
.describe_alarms()
290 if str(alarm
.description
).split(';')[1] == ack_info
['alarm_uuid']:
291 alarm_details_dict
['alarm_uuid'] = str(ack_info
['alarm_uuid'])
292 alarm_details_dict
['resource_uuid'] = str(alarm
.dimensions
['InstanceId']).split("'")[1]
293 alarm_details_dict
['description'] = str(alarm
.description
).split(';')[1]
294 alarm_details_dict
['severity'] = str(alarm
.description
).split(';')[0]
295 alarm_details_dict
['start_date_time'] = str(alarms_details
[itr
].timestamp
)
296 alarm_details_dict
['vim_type'] = str(ack_info_all
['vim_type'])
298 if 'ack_details' in ack_info_all
:
299 alarm_details_all
['schema_version'] = str(ack_info_all
['schema_version'])
300 alarm_details_all
['schema_type'] = 'notify_alarm'
301 alarm_details_all
['notify_details'] = alarm_details_dict
302 return alarm_details_all
304 elif 'alarm_list_request' in ack_info_all
:
305 return alarm_details_dict
307 except Exception as e
:
308 log
.error("Error getting alarm details: %s", str(e
))
310 def is_present(self
, cloudwatch_conn
, alarm_id
):
311 """Finding alarm from already configured alarms"""
314 alarms
= cloudwatch_conn
.describe_alarms()
316 if str(alarm
.description
).split(';')[1] == alarm_id
:
317 alarm_info
['status'] = True
318 alarm_info
['info'] = alarm
320 alarm_info
['status'] = False
322 except Exception as e
:
323 log
.error("Error Finding Alarm", str(e
))