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()'")
80 if alarm_info
['statistic'] in STATISTICS
:
81 if alarm_info
['operation'] in OPERATIONS
:
82 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
83 connection
= cloudwatch_conn
,
84 name
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
85 metric
= alarm_info
['metric_name'],
86 namespace
= "AWS/EC2",
87 statistic
= STATISTICS
[alarm_info
['statistic']],
88 comparison
= OPERATIONS
[alarm_info
['operation']],
89 threshold
= alarm_info
['threshold_value'],
91 evaluation_periods
= 1,
92 unit
=alarm_info
['unit'],
93 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
94 dimensions
= {'InstanceId':alarm_info
['resource_uuid']},
97 insufficient_data_actions
= None)
99 """Setting Alarm Actions :
100 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
102 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
104 log
.debug ("Alarm Configured Succesfully")
105 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
106 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
108 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
109 inner_dict
['alarm_uuid'] = str(alarm_id
)
110 inner_dict
['status'] = status
112 self
.alarm_resp
['alarm_create_response'] = inner_dict
115 return self
.alarm_resp
119 log
.error("Operation not supported")
122 log
.error("Statistic not supported")
124 except Exception as e
:
125 log
.error("Alarm Configuration Failed: " + str(e
))
127 #-----------------------------------------------------------------------------------------------------------------------------
128 def update_alarm(self
,cloudwatch_conn
,update_info
):
130 """Update or reconfigure an alarm"""
132 alarm_info
= update_info
['alarm_update_request']
134 """Alarm Name to ID Mapping"""
135 alarm_id
= alarm_info
['alarm_uuid']
136 status
= self
.is_present(cloudwatch_conn
,alarm_id
)
138 """Verifying : Alarm exists already"""
139 if status
['status'] == False:
141 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
145 if alarm_info
['statistic'] in STATISTICS
:
146 if alarm_info
['operation'] in OPERATIONS
:
147 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
148 connection
= cloudwatch_conn
,
149 name
= status
['info'].name
,
150 metric
= alarm_info
['metric_name'],
151 namespace
= "AWS/EC2",
152 statistic
= STATISTICS
[alarm_info
['statistic']],
153 comparison
= OPERATIONS
[alarm_info
['operation']],
154 threshold
= alarm_info
['threshold_value'],
156 evaluation_periods
= 1,
157 unit
=alarm_info
['unit'],
158 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
159 dimensions
= {'InstanceId':str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
160 alarm_actions
= None,
162 insufficient_data_actions
= None)
164 """Setting Alarm Actions :
165 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
167 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
168 log
.debug("Alarm %s Updated ",alarm
.name
)
169 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
170 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
172 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
173 inner_dict
['alarm_uuid'] = str(alarm_id
)
174 inner_dict
['status'] = status
176 self
.alarm_resp
['alarm_update_response'] = inner_dict
177 return self
.alarm_resp
179 log
.error("Operation not supported")
182 log
.error("Statistic not supported")
184 except Exception as e
:
185 log
.error ("Error in Updating Alarm " + str(e
))
187 #-----------------------------------------------------------------------------------------------------------------------------
188 def delete_Alarm(self
,cloudwatch_conn
,del_info_all
):
190 """Deletes an Alarm with specified alarm_id"""
192 del_info
= del_info_all
['alarm_delete_request']
193 status
= self
.is_present(cloudwatch_conn
,del_info
['alarm_uuid'])
195 if status
['status'] == True:
196 del_status
=cloudwatch_conn
.delete_alarms(status
['info'].name
)
197 self
.del_resp
['schema_version'] = str(del_info_all
['schema_version'])
198 self
.del_resp
['schema_type'] = 'delete_alarm_response'
199 inner_dict
['correlation_id'] = str(del_info
['correlation_id'])
200 inner_dict
['alarm_id'] = str(del_info
['alarm_uuid'])
201 inner_dict
['status'] = del_status
202 self
.del_resp
['alarm_deletion_response'] = inner_dict
205 except Exception as e
:
206 log
.error("Alarm Not Deleted: " + str(e
))
207 #-----------------------------------------------------------------------------------------------------------------------------
208 def alarms_list(self
,cloudwatch_conn
,list_info
):
210 """Get a list of alarms that are present on a particular VIM type"""
213 inner_dict
= list_info
['alarm_list_request']
215 alarms
= cloudwatch_conn
.describe_alarms()
218 list_info
['alarm_list_request']['alarm_uuid'] = str(alarm
.description
).split(';')[1]
220 #Severity = alarm_name = resource_uuid = ""
221 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
222 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
224 #alarm_name = resource_uuid = ""
225 if inner_dict
['severity'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] == "" and inner_dict
['resource_uuid'] == "":
226 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
228 #severity = resource_uuid = ""
229 if inner_dict
['severity'] == "" 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
))
232 #severity = alarm_name = ""
233 if inner_dict
['severity'] == "" 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'] == str(alarm
.description
).split(';')[0] and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == "":
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'] == "" and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
242 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
245 if inner_dict
['severity'] == "" and inner_dict
['alarm_name'] in alarm
.name
and inner_dict
['resource_uuid'] == str(alarm
.dimensions
['InstanceId']).split("'")[1]:
246 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
249 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]:
250 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
253 alarm_info
['schema_version'] = str(list_info
['schema_version'])
254 alarm_info
['schema_type'] = 'list_alarm_response'
255 alarm_info
['list_alarm_resp'] = alarm_list
258 except Exception as e
:
259 log
.error("Error in Getting List : %s",str(e
))
260 #-----------------------------------------------------------------------------------------------------------------------------
261 def alarm_details(self
,cloudwatch_conn
,ack_info
):
263 """Get an individual alarm details specified by alarm_name"""
265 alarms_details
=cloudwatch_conn
.describe_alarm_history()
266 alarm_details_all
= dict()
267 alarm_details_dict
= dict()
268 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
))
309 #-----------------------------------------------------------------------------------------------------------------------------
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
))
324 #-----------------------------------------------------------------------------------------------------------------------------