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",
55 """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """
57 self
.alarm_resp
= dict()
58 self
.del_resp
= dict()
60 def config_alarm(self
,cloudwatch_conn
,create_info
):
61 """Configure or Create a new alarm"""
63 """ Alarm Name to ID Mapping """
64 alarm_info
= create_info
['alarm_create_request']
65 alarm_id
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid']
66 if self
.is_present(cloudwatch_conn
,alarm_id
)['status'] == True:
68 log
.debug ("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'")
72 if alarm_info
['statistic'] in STATISTICS
:
73 if alarm_info
['operation'] in OPERATIONS
:
74 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
75 connection
= cloudwatch_conn
,
76 name
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
77 metric
= alarm_info
['metric_name'],
78 namespace
= "AWS/EC2",
79 statistic
= STATISTICS
[alarm_info
['statistic']],
80 comparison
= OPERATIONS
[alarm_info
['operation']],
81 threshold
= alarm_info
['threshold_value'],
83 evaluation_periods
= 1,
84 unit
=alarm_info
['unit'],
85 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
86 dimensions
= {'InstanceId':alarm_info
['resource_uuid']},
89 insufficient_data_actions
= None)
91 """Setting Alarm Actions :
92 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
94 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
96 log
.debug ("Alarm Configured Succesfully")
97 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
98 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
100 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
101 inner_dict
['alarm_uuid'] = str(alarm_id
)
102 inner_dict
['status'] = status
104 self
.alarm_resp
['alarm_create_response'] = inner_dict
107 return self
.alarm_resp
111 log
.error("Operation not supported")
114 log
.error("Statistic not supported")
116 except Exception as e
:
117 log
.error("Alarm Configuration Failed: " + str(e
))
119 #-----------------------------------------------------------------------------------------------------------------------------
120 def update_alarm(self
,cloudwatch_conn
,update_info
):
122 """Update or reconfigure an alarm"""
124 alarm_info
= update_info
['alarm_update_request']
126 """Alarm Name to ID Mapping"""
127 alarm_id
= alarm_info
['alarm_uuid']
128 status
= self
.is_present(cloudwatch_conn
,alarm_id
)
130 """Verifying : Alarm exists already"""
131 if status
['status'] == False:
133 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
137 if alarm_info
['statistic'] in STATISTICS
:
138 if alarm_info
['operation'] in OPERATIONS
:
139 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
140 connection
= cloudwatch_conn
,
141 name
= status
['info'].name
,
142 metric
= alarm_info
['metric_name'],
143 namespace
= "AWS/EC2",
144 statistic
= STATISTICS
[alarm_info
['statistic']],
145 comparison
= OPERATIONS
[alarm_info
['operation']],
146 threshold
= alarm_info
['threshold_value'],
148 evaluation_periods
= 1,
149 unit
=alarm_info
['unit'],
150 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
151 dimensions
= {'InstanceId':str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
152 alarm_actions
= None,
154 insufficient_data_actions
= None)
156 """Setting Alarm Actions :
157 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
159 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
160 log
.debug("Alarm %s Updated ",alarm
.name
)
161 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
162 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
164 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
165 inner_dict
['alarm_uuid'] = str(alarm_id
)
166 inner_dict
['status'] = status
168 self
.alarm_resp
['alarm_update_response'] = inner_dict
169 return self
.alarm_resp
171 log
.error("Operation not supported")
174 log
.error("Statistic not supported")
176 except Exception as e
:
177 log
.error ("Error in Updating Alarm " + str(e
))
179 #-----------------------------------------------------------------------------------------------------------------------------
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
))
199 #-----------------------------------------------------------------------------------------------------------------------------
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
['resource_uuid'] == "":
214 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
216 #alarm_name = resource_uuid = ""
217 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
218 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
220 #severity = resource_uuid = ""
221 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
222 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
224 #severity = alarm_name = ""
225 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
226 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
229 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
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
['alarm_name'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
234 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
237 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
238 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
241 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]:
242 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
245 alarm_info
['schema_version'] = str(list_info
['schema_version'])
246 alarm_info
['schema_type'] = 'list_alarm_response'
247 alarm_info
['list_alarm_response'] = alarm_list
250 except Exception as e
:
251 log
.error("Error in Getting List : %s",str(e
))
252 #-----------------------------------------------------------------------------------------------------------------------------
253 def alarm_details(self
,cloudwatch_conn
,ack_info
):
255 """Get an individual alarm details specified by alarm_name"""
257 alarms_details
=cloudwatch_conn
.describe_alarm_history()
258 alarm_details_all
= dict()
259 alarm_details_dict
= dict()
260 ack_info_all
= ack_info
263 if 'ack_details' in ack_info
:
264 ack_info
= ack_info
['ack_details']
265 elif 'alarm_list_request' in ack_info
:
266 ack_info
= ack_info
['alarm_list_request']
268 is_present
= self
.is_present(cloudwatch_conn
,ack_info
['alarm_uuid'])
270 for itr
in range (len(alarms_details
)):
271 if alarms_details
[itr
].name
== is_present
['info'].name
:#name, timestamp, summary
272 if 'created' in alarms_details
[itr
].summary
:
273 alarm_details_dict
['status'] = "New"
274 elif 'updated' in alarms_details
[itr
].summary
:
275 alarm_details_dict
['status'] = "Update"
276 elif 'deleted' in alarms_details
[itr
].summary
:
277 alarm_details_dict
['status'] = "Canceled"
279 status
= alarms_details
[itr
].summary
.split()
280 alarms
= cloudwatch_conn
.describe_alarms()
282 if str(alarm
.description
).split(';')[1] == ack_info
['alarm_uuid']:
283 alarm_details_dict
['alarm_uuid'] = str(ack_info
['alarm_uuid'])
284 alarm_details_dict
['resource_uuid'] = str(alarm
.dimensions
['InstanceId']).split("'")[1]
285 alarm_details_dict
['description'] = str(alarm
.description
).split(';')[1]
286 alarm_details_dict
['severity'] = str(alarm
.description
).split(';')[0]
287 alarm_details_dict
['start_date_time'] = str(alarms_details
[itr
].timestamp
)
288 alarm_details_dict
['vim_type'] = str(ack_info_all
['vim_type'])
290 if 'ack_details' in ack_info_all
:
291 alarm_details_all
['schema_version'] = str(ack_info_all
['schema_version'])
292 alarm_details_all
['schema_type'] = 'notify_alarm'
293 alarm_details_all
['notify_details'] = alarm_details_dict
294 return alarm_details_all
296 elif 'alarm_list_request' in ack_info_all
:
297 return alarm_details_dict
299 except Exception as e
:
300 log
.error("Error getting alarm details: %s",str(e
))
301 #-----------------------------------------------------------------------------------------------------------------------------
302 def is_present(self
,cloudwatch_conn
,alarm_id
):
303 """Finding alarm from already configured alarms"""
306 alarms
= cloudwatch_conn
.describe_alarms()
308 if str(alarm
.description
).split(';')[1] == alarm_id
:
309 alarm_info
['status'] = True
310 alarm_info
['info'] = alarm
312 alarm_info
['status'] = False
314 except Exception as e
:
315 log
.error("Error Finding Alarm",str(e
))
316 #-----------------------------------------------------------------------------------------------------------------------------