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
38 log
= logging
.getLogger(__name__
)
44 import boto
.ec2
.cloudwatch
45 import boto
.ec2
.connection
47 exit("Boto not avialable. Try activating your virtualenv OR `pip install boto`")
53 "COUNT" : "SampleCount",
64 """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """
66 self
.alarm_resp
= dict()
67 self
.del_resp
= dict()
69 def config_alarm(self
,cloudwatch_conn
,create_info
):
70 """Configure or Create a new alarm"""
72 """ Alarm Name to ID Mapping """
73 alarm_info
= create_info
['alarm_create_request']
74 alarm_id
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid']
75 if self
.is_present(cloudwatch_conn
,alarm_id
)['status'] == True:
77 log
.debug ("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'")
81 if alarm_info
['statistic'] in STATISTICS
:
82 if alarm_info
['operation'] in OPERATIONS
:
83 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
84 connection
= cloudwatch_conn
,
85 name
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
86 metric
= alarm_info
['metric_name'],
87 namespace
= "AWS/EC2",
88 statistic
= STATISTICS
[alarm_info
['statistic']],
89 comparison
= OPERATIONS
[alarm_info
['operation']],
90 threshold
= alarm_info
['threshold_value'],
92 evaluation_periods
= 1,
93 unit
=alarm_info
['unit'],
94 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
95 dimensions
= {'InstanceId':alarm_info
['resource_uuid']},
98 insufficient_data_actions
= None)
100 """Setting Alarm Actions :
101 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
103 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
105 log
.debug ("Alarm Configured Succesfully")
106 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
107 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
109 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
110 inner_dict
['alarm_uuid'] = str(alarm_id
)
111 inner_dict
['status'] = status
113 self
.alarm_resp
['alarm_create_response'] = inner_dict
116 return self
.alarm_resp
120 log
.error("Operation not supported")
123 log
.error("Statistic not supported")
125 except Exception as e
:
126 log
.error("Alarm Configuration Failed: " + str(e
))
128 #-----------------------------------------------------------------------------------------------------------------------------
129 def update_alarm(self
,cloudwatch_conn
,update_info
):
131 """Update or reconfigure an alarm"""
133 alarm_info
= update_info
['alarm_update_request']
135 """Alarm Name to ID Mapping"""
136 alarm_id
= alarm_info
['alarm_uuid']
137 status
= self
.is_present(cloudwatch_conn
,alarm_id
)
139 """Verifying : Alarm exists already"""
140 if status
['status'] == False:
142 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
146 if alarm_info
['statistic'] in STATISTICS
:
147 if alarm_info
['operation'] in OPERATIONS
:
148 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
149 connection
= cloudwatch_conn
,
150 name
= status
['info'].name
,
151 metric
= alarm_info
['metric_name'],
152 namespace
= "AWS/EC2",
153 statistic
= STATISTICS
[alarm_info
['statistic']],
154 comparison
= OPERATIONS
[alarm_info
['operation']],
155 threshold
= alarm_info
['threshold_value'],
157 evaluation_periods
= 1,
158 unit
=alarm_info
['unit'],
159 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
160 dimensions
= {'InstanceId':str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
161 alarm_actions
= None,
163 insufficient_data_actions
= None)
165 """Setting Alarm Actions :
166 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
168 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
169 log
.debug("Alarm %s Updated ",alarm
.name
)
170 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
171 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
173 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
174 inner_dict
['alarm_uuid'] = str(alarm_id
)
175 inner_dict
['status'] = status
177 self
.alarm_resp
['alarm_update_response'] = inner_dict
178 return self
.alarm_resp
180 log
.error("Operation not supported")
183 log
.error("Statistic not supported")
185 except Exception as e
:
186 log
.error ("Error in Updating Alarm " + str(e
))
188 #-----------------------------------------------------------------------------------------------------------------------------
189 def delete_Alarm(self
,cloudwatch_conn
,del_info_all
):
191 """Deletes an Alarm with specified alarm_id"""
193 del_info
= del_info_all
['alarm_delete_request']
194 status
= self
.is_present(cloudwatch_conn
,del_info
['alarm_uuid'])
196 if status
['status'] == True:
197 del_status
=cloudwatch_conn
.delete_alarms(status
['info'].name
)
198 self
.del_resp
['schema_version'] = str(del_info_all
['schema_version'])
199 self
.del_resp
['schema_type'] = 'delete_alarm_response'
200 inner_dict
['correlation_id'] = str(del_info
['correlation_id'])
201 inner_dict
['alarm_id'] = str(del_info
['alarm_uuid'])
202 inner_dict
['status'] = del_status
203 self
.del_resp
['alarm_deletion_response'] = inner_dict
206 except Exception as e
:
207 log
.error("Alarm Not Deleted: " + str(e
))
208 #-----------------------------------------------------------------------------------------------------------------------------
209 def alarms_list(self
,cloudwatch_conn
,list_info
):
211 """Get a list of alarms that are present on a particular VIM type"""
214 inner_dict
= list_info
['alarm_list_request']
216 alarms
= cloudwatch_conn
.describe_alarms()
219 list_info
['alarm_list_request']['alarm_uuid'] = str(alarm
.description
).split(';')[1]
221 #Severity = alarm_name = resource_uuid = ""
222 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
223 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
225 #alarm_name = resource_uuid = ""
226 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
227 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
229 #severity = resource_uuid = ""
230 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
231 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
233 #severity = alarm_name = ""
234 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
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'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
239 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
242 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]:
243 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
246 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
247 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
250 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]:
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_resp'] = alarm_list
259 except Exception as e
:
260 log
.error("Error in Getting List : %s",str(e
))
261 #-----------------------------------------------------------------------------------------------------------------------------
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
272 if 'ack_details' in ack_info
:
273 ack_info
= ack_info
['ack_details']
274 elif 'alarm_list_request' in ack_info
:
275 ack_info
= ack_info
['alarm_list_request']
277 is_present
= self
.is_present(cloudwatch_conn
,ack_info
['alarm_uuid'])
279 for itr
in range (len(alarms_details
)):
280 if alarms_details
[itr
].name
== is_present
['info'].name
:#name, timestamp, summary
281 if 'created' in alarms_details
[itr
].summary
:
282 alarm_details_dict
['status'] = "New"
283 elif 'updated' in alarms_details
[itr
].summary
:
284 alarm_details_dict
['status'] = "Update"
285 elif 'deleted' in alarms_details
[itr
].summary
:
286 alarm_details_dict
['status'] = "Canceled"
288 status
= alarms_details
[itr
].summary
.split()
289 alarms
= cloudwatch_conn
.describe_alarms()
291 if str(alarm
.description
).split(';')[1] == ack_info
['alarm_uuid']:
292 alarm_details_dict
['alarm_uuid'] = str(ack_info
['alarm_uuid'])
293 alarm_details_dict
['resource_uuid'] = str(alarm
.dimensions
['InstanceId']).split("'")[1]
294 alarm_details_dict
['description'] = str(alarm
.description
).split(';')[1]
295 alarm_details_dict
['severity'] = str(alarm
.description
).split(';')[0]
296 alarm_details_dict
['start_date_time'] = str(alarms_details
[itr
].timestamp
)
297 alarm_details_dict
['vim_type'] = str(ack_info_all
['vim_type'])
299 if 'ack_details' in ack_info_all
:
300 alarm_details_all
['schema_version'] = str(ack_info_all
['schema_version'])
301 alarm_details_all
['schema_type'] = 'notify_alarm'
302 alarm_details_all
['notify_details'] = alarm_details_dict
303 return alarm_details_all
305 elif 'alarm_list_request' in ack_info_all
:
306 return alarm_details_dict
308 except Exception as e
:
309 log
.error("Error getting alarm details: %s",str(e
))
310 #-----------------------------------------------------------------------------------------------------------------------------
311 def is_present(self
,cloudwatch_conn
,alarm_id
):
312 """Finding alarm from already configured alarms"""
315 alarms
= cloudwatch_conn
.describe_alarms()
317 if str(alarm
.description
).split(';')[1] == alarm_id
:
318 alarm_info
['status'] = True
319 alarm_info
['info'] = alarm
321 alarm_info
['status'] = False
323 except Exception as e
:
324 log
.error("Error Finding Alarm",str(e
))
325 #-----------------------------------------------------------------------------------------------------------------------------