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`")
50 """Alarms Functionality Handler -- Carries out alarming requests and responses via BOTO.Cloudwatch """
52 self
.alarm_resp
= dict()
53 self
.del_resp
= dict()
55 def config_alarm(self
,cloudwatch_conn
,create_info
):
56 """Configure or Create a new alarm"""
58 """ Alarm Name to ID Mapping """
59 alarm_info
= create_info
['alarm_create_request']
60 alarm_id
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid']
61 if self
.is_present(cloudwatch_conn
,alarm_id
)['status'] == True:
63 log
.debug ("Alarm already exists, Try updating the alarm using 'update_alarm_configuration()'")
66 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
67 connection
= cloudwatch_conn
,
68 name
= alarm_info
['alarm_name'] + "_" + alarm_info
['resource_uuid'],
69 metric
= alarm_info
['metric_name'],
70 namespace
= "AWS/EC2",
71 statistic
= alarm_info
['statistic'],
72 comparison
= alarm_info
['operation'],
73 threshold
= alarm_info
['threshold_value'],
75 evaluation_periods
= 1,
76 unit
=alarm_info
['unit'],
77 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
78 dimensions
= {'InstanceId':alarm_info
['resource_uuid']},
81 insufficient_data_actions
= None)
83 """Setting Alarm Actions :
84 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
86 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
88 log
.debug ("Alarm Configured Succesfully")
89 self
.alarm_resp
['schema_version'] = str(create_info
['schema_version'])
90 self
.alarm_resp
['schema_type'] = 'create_alarm_response'
92 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
93 inner_dict
['alarm_uuid'] = str(alarm_id
)
94 inner_dict
['status'] = status
96 self
.alarm_resp
['alarm_create_response'] = inner_dict
98 return self
.alarm_resp
102 except Exception as e
:
103 log
.error("Alarm Configuration Failed: " + str(e
))
105 #-----------------------------------------------------------------------------------------------------------------------------
106 def update_alarm(self
,cloudwatch_conn
,update_info
):
108 """Update or reconfigure an alarm"""
110 alarm_info
= update_info
['alarm_update_request']
112 """Alarm Name to ID Mapping"""
113 alarm_id
= alarm_info
['alarm_uuid']
114 status
= self
.is_present(cloudwatch_conn
,alarm_id
)
116 """Verifying : Alarm exists already"""
117 if status
['status'] == False:
119 log
.debug("Alarm not found, Try creating the alarm using 'configure_alarm()'")
123 alarm
= boto
.ec2
.cloudwatch
.alarm
.MetricAlarm(
124 connection
= cloudwatch_conn
,
125 name
= status
['info'].name
,
126 metric
= alarm_info
['metric_name'],
127 namespace
= "AWS/EC2",
128 statistic
= alarm_info
['statistic'],
129 comparison
= alarm_info
['operation'],
130 threshold
= alarm_info
['threshold_value'],
132 evaluation_periods
= 1,
133 unit
=alarm_info
['unit'],
134 description
= alarm_info
['severity'] + ";" + alarm_id
+ ";" + alarm_info
['description'],
135 dimensions
= {'InstanceId':str(status
['info'].dimensions
['InstanceId']).split("'")[1]},
136 alarm_actions
= None,
138 insufficient_data_actions
= None)
140 """Setting Alarm Actions :
141 alarm_actions = ['arn:aws:swf:us-west-2:465479087178:action/actions/AWS_EC2.InstanceId.Stop/1.0']"""
143 status
=cloudwatch_conn
.put_metric_alarm(alarm
)
144 log
.debug("Alarm %s Updated ",alarm
.name
)
145 self
.alarm_resp
['schema_version'] = str(update_info
['schema_version'])
146 self
.alarm_resp
['schema_type'] = 'update_alarm_response'
148 inner_dict
['correlation_id'] = str(alarm_info
['correlation_id'])
149 inner_dict
['alarm_uuid'] = str(alarm_id
)
150 inner_dict
['status'] = status
152 self
.alarm_resp
['alarm_update_response'] = inner_dict
153 return self
.alarm_resp
154 except Exception as e
:
155 log
.error ("Error in Updating Alarm " + str(e
))
157 #-----------------------------------------------------------------------------------------------------------------------------
158 def delete_Alarm(self
,cloudwatch_conn
,del_info_all
):
160 """Deletes an Alarm with specified alarm_id"""
162 del_info
= del_info_all
['alarm_delete_request']
163 status
= self
.is_present(cloudwatch_conn
,del_info
['alarm_uuid'])
165 if status
['status'] == True:
166 del_status
=cloudwatch_conn
.delete_alarms(status
['info'].name
)
167 self
.del_resp
['schema_version'] = str(del_info_all
['schema_version'])
168 self
.del_resp
['schema_type'] = 'delete_alarm_response'
169 inner_dict
['correlation_id'] = str(del_info
['correlation_id'])
170 inner_dict
['alarm_id'] = str(del_info
['alarm_uuid'])
171 inner_dict
['status'] = del_status
172 self
.del_resp
['alarm_deletion_response'] = inner_dict
175 except Exception as e
:
176 log
.error("Alarm Not Deleted: " + str(e
))
177 #-----------------------------------------------------------------------------------------------------------------------------
178 def alarms_list(self
,cloudwatch_conn
,list_info
):
180 """Get a list of alarms that are present on a particular VIM type"""
184 alarms
= cloudwatch_conn
.describe_alarms()
187 list_info
['alarm_list_request']['alarm_uuid'] = str(alarm
.description
).split(';')[1]
188 alarm_list
.insert(itr
,self
.alarm_details(cloudwatch_conn
,list_info
))
191 alarm_info
['schema_version'] = str(list_info
['schema_version'])
192 alarm_info
['schema_type'] = 'list_alarm_response'
193 alarm_info
['list_alarm_resp'] = json
.dumps(alarm_list
)
196 except Exception as e
:
197 log
.error("Error in Getting List : %s",str(e
))
198 #-----------------------------------------------------------------------------------------------------------------------------
199 def alarm_details(self
,cloudwatch_conn
,ack_info
):
201 """Get an individual alarm details specified by alarm_name"""
203 alarms_details
=cloudwatch_conn
.describe_alarm_history()
204 alarm_details_all
= dict()
205 alarm_details_dict
= dict()
206 ack_info_all
= ack_info
209 if 'ack_details' in ack_info
:
210 ack_info
= ack_info
['ack_details']
211 elif 'alarm_list_request' in ack_info
:
212 ack_info
= ack_info
['alarm_list_request']
214 is_present
= self
.is_present(cloudwatch_conn
,ack_info
['alarm_uuid'])
216 for itr
in range (len(alarms_details
)):
217 if alarms_details
[itr
].name
== is_present
['info'].name
:#name, timestamp, summary
218 if 'created' in alarms_details
[itr
].summary
:
219 alarm_details_dict
['status'] = "New"
220 elif 'updated' in alarms_details
[itr
].summary
:
221 alarm_details_dict
['status'] = "Update"
222 elif 'deleted' in alarms_details
[itr
].summary
:
223 alarm_details_dict
['status'] = "Canceled"
225 status
= alarms_details
[itr
].summary
.split()
226 alarms
= cloudwatch_conn
.describe_alarms()
228 if str(alarm
.description
).split(';')[1] == ack_info
['alarm_uuid']:
229 alarm_details_dict
['alarm_uuid'] = str(ack_info
['alarm_uuid'])
230 alarm_details_dict
['resource_uuid'] = str(alarm
.dimensions
['InstanceId']).split("'")[1]
231 alarm_details_dict
['description'] = str(alarm
.description
).split(';')[1]
232 alarm_details_dict
['severity'] = str(alarm
.description
).split(';')[0]
233 alarm_details_dict
['start_date_time'] = str(alarms_details
[itr
].timestamp
)
234 alarm_details_dict
['vim_type'] = str(ack_info_all
['vim_type'])
236 if 'ack_details' in ack_info_all
:
237 alarm_details_all
['schema_version'] = str(ack_info_all
['schema_version'])
238 alarm_details_all
['schema_type'] = 'notify_alarm'
239 alarm_details_all
['notify_details'] = alarm_details_dict
240 return alarm_details_all
242 elif 'alarm_list_request' in ack_info_all
:
243 return alarm_details_dict
245 except Exception as e
:
246 log
.error("Error getting alarm details: %s",str(e
))
247 #-----------------------------------------------------------------------------------------------------------------------------
248 def is_present(self
,cloudwatch_conn
,alarm_id
):
249 """Finding alarm from already configured alarms"""
252 alarms
= cloudwatch_conn
.describe_alarms()
254 if str(alarm
.description
).split(';')[1] == alarm_id
:
255 alarm_info
['status'] = True
256 alarm_info
['info'] = alarm
258 alarm_info
['status'] = False
260 except Exception as e
:
261 log
.error("Error Finding Alarm",str(e
))
262 #-----------------------------------------------------------------------------------------------------------------------------