OLD | NEW |
1 # Copyright (c) 2010 Reza Lotun http://reza.lotun.name | 1 # Copyright (c) 2010 Reza Lotun http://reza.lotun.name |
2 # | 2 # |
3 # Permission is hereby granted, free of charge, to any person obtaining a | 3 # Permission is hereby granted, free of charge, to any person obtaining a |
4 # copy of this software and associated documentation files (the | 4 # copy of this software and associated documentation files (the |
5 # "Software"), to deal in the Software without restriction, including | 5 # "Software"), to deal in the Software without restriction, including |
6 # without limitation the rights to use, copy, modify, merge, publish, dis- | 6 # without limitation the rights to use, copy, modify, merge, publish, dis- |
7 # tribute, sublicense, and/or sell copies of the Software, and to permit | 7 # tribute, sublicense, and/or sell copies of the Software, and to permit |
8 # persons to whom the Software is furnished to do so, subject to the fol- | 8 # persons to whom the Software is furnished to do so, subject to the fol- |
9 # lowing conditions: | 9 # lowing conditions: |
10 # | 10 # |
11 # The above copyright notice and this permission notice shall be included | 11 # The above copyright notice and this permission notice shall be included |
12 # in all copies or substantial portions of the Software. | 12 # in all copies or substantial portions of the Software. |
13 # | 13 # |
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 # IN THE SOFTWARE. | 20 # IN THE SOFTWARE. |
21 # | 21 # |
22 | 22 |
23 from datetime import datetime | 23 from datetime import datetime |
24 import json | 24 from boto.resultset import ResultSet |
25 | 25 from boto.ec2.cloudwatch.listelement import ListElement |
| 26 try: |
| 27 import simplejson as json |
| 28 except ImportError: |
| 29 import json |
26 | 30 |
27 class MetricAlarm(object): | 31 class MetricAlarm(object): |
28 | 32 |
29 OK = 'OK' | 33 OK = 'OK' |
30 ALARM = 'ALARM' | 34 ALARM = 'ALARM' |
31 INSUFFICIENT_DATA = 'INSUFFICIENT_DATA' | 35 INSUFFICIENT_DATA = 'INSUFFICIENT_DATA' |
32 | 36 |
33 _cmp_map = { | 37 _cmp_map = { |
34 '>=' : 'GreaterThanOrEqualToThreshold', | 38 '>=' : 'GreaterThanOrEqualToThreshold', |
35 '>' : 'GreaterThanThreshold', | 39 '>' : 'GreaterThanThreshold', |
36 '<' : 'LessThanThreshold', | 40 '<' : 'LessThanThreshold', |
37 '<=' : 'LessThanOrEqualToThreshold', | 41 '<=' : 'LessThanOrEqualToThreshold', |
38 } | 42 } |
39 _rev_cmp_map = dict((v, k) for (k, v) in _cmp_map.iteritems()) | 43 _rev_cmp_map = dict((v, k) for (k, v) in _cmp_map.iteritems()) |
40 | 44 |
41 def __init__(self, connection=None, name=None, metric=None, | 45 def __init__(self, connection=None, name=None, metric=None, |
42 namespace=None, statistic=None, comparison=None, threshold=None
, | 46 namespace=None, statistic=None, comparison=None, |
43 period=None, evaluation_periods=None): | 47 threshold=None, period=None, evaluation_periods=None, |
| 48 unit=None, description='', dimensions=None, |
| 49 alarm_actions=None, insufficient_data_actions=None, |
| 50 ok_actions=None): |
44 """ | 51 """ |
45 Creates a new Alarm. | 52 Creates a new Alarm. |
46 | 53 |
47 :type name: str | 54 :type name: str |
48 :param name: Name of alarm. | 55 :param name: Name of alarm. |
49 | 56 |
50 :type metric: str | 57 :type metric: str |
51 :param metric: Name of alarm's associated metric. | 58 :param metric: Name of alarm's associated metric. |
52 | 59 |
53 :type namespace: str | 60 :type namespace: str |
54 :param namespace: The namespace for the alarm's metric. | 61 :param namespace: The namespace for the alarm's metric. |
55 | 62 |
56 :type statistic: str | 63 :type statistic: str |
57 :param statistic: The statistic to apply to the alarm's associated metri
c. Can | 64 :param statistic: The statistic to apply to the alarm's associated |
58 be one of 'SampleCount', 'Average', 'Sum', 'Minimum',
'Maximum' | 65 metric. |
| 66 Valid values: SampleCount|Average|Sum|Minimum|Maximum |
59 | 67 |
60 :type comparison: str | 68 :type comparison: str |
61 :param comparison: Comparison used to compare statistic with threshold.
Can be | 69 :param comparison: Comparison used to compare statistic with threshold. |
62 one of '>=', '>', '<', '<=' | 70 Valid values: >= | > | < | <= |
63 | 71 |
64 :type threshold: float | 72 :type threshold: float |
65 :param threshold: The value against which the specified statistic is com
pared. | 73 :param threshold: The value against which the specified statistic |
| 74 is compared. |
66 | 75 |
67 :type period: int | 76 :type period: int |
68 :param period: The period in seconds over which teh specified statistic
is applied. | 77 :param period: The period in seconds over which teh specified |
| 78 statistic is applied. |
69 | 79 |
70 :type evaluation_periods: int | 80 :type evaluation_periods: int |
71 :param evaluation_period: The number of periods over which data is compa
red to | 81 :param evaluation_period: The number of periods over which data is |
72 the specified threshold | 82 compared to the specified threshold. |
| 83 |
| 84 :type unit: str |
| 85 :param unit: Allowed Values are: |
| 86 Seconds|Microseconds|Milliseconds, |
| 87 Bytes|Kilobytes|Megabytes|Gigabytes|Terabytes, |
| 88 Bits|Kilobits|Megabits|Gigabits|Terabits, |
| 89 Percent|Count| |
| 90 Bytes/Second|Kilobytes/Second|Megabytes/Second| |
| 91 Gigabytes/Second|Terabytes/Second, |
| 92 Bits/Second|Kilobits/Second|Megabits/Second, |
| 93 Gigabits/Second|Terabits/Second|Count/Second|None |
| 94 |
| 95 :type description: str |
| 96 :param description: Description of MetricAlarm |
| 97 |
| 98 :type dimensions: list of dicts |
| 99 :param description: Dimensions of alarm, such as: |
| 100 [{'InstanceId':['i-0123456,i-0123457']}] |
| 101 |
| 102 :type alarm_actions: list of strs |
| 103 :param alarm_actions: A list of the ARNs of the actions to take in |
| 104 ALARM state |
| 105 |
| 106 :type insufficient_data_actions: list of strs |
| 107 :param insufficient_data_actions: A list of the ARNs of the actions to |
| 108 take in INSUFFICIENT_DATA state |
| 109 |
| 110 :type ok_actions: list of strs |
| 111 :param ok_actions: A list of the ARNs of the actions to take in OK state |
73 """ | 112 """ |
74 self.name = name | 113 self.name = name |
75 self.connection = connection | 114 self.connection = connection |
76 self.metric = metric | 115 self.metric = metric |
77 self.namespace = namespace | 116 self.namespace = namespace |
78 self.statistic = statistic | 117 self.statistic = statistic |
79 self.threshold = float(threshold) if threshold is not None else None | 118 if threshold is not None: |
| 119 self.threshold = float(threshold) |
| 120 else: |
| 121 self.threshold = None |
80 self.comparison = self._cmp_map.get(comparison) | 122 self.comparison = self._cmp_map.get(comparison) |
81 self.period = int(period) if period is not None else None | 123 if period is not None: |
82 self.evaluation_periods = int(evaluation_periods) if evaluation_periods
is not None else None | 124 self.period = int(period) |
| 125 else: |
| 126 self.period = None |
| 127 if evaluation_periods is not None: |
| 128 self.evaluation_periods = int(evaluation_periods) |
| 129 else: |
| 130 self.evaluation_periods = None |
83 self.actions_enabled = None | 131 self.actions_enabled = None |
84 self.alarm_actions = [] | |
85 self.alarm_arn = None | 132 self.alarm_arn = None |
86 self.last_updated = None | 133 self.last_updated = None |
87 self.description = '' | 134 self.description = description |
88 self.dimensions = [] | 135 self.dimensions = dimensions |
89 self.insufficient_data_actions = [] | |
90 self.ok_actions = [] | |
91 self.state_reason = None | 136 self.state_reason = None |
92 self.state_value = None | 137 self.state_value = None |
93 self.unit = None | 138 self.unit = unit |
| 139 self.alarm_actions = alarm_actions |
| 140 self.insufficient_data_actions = insufficient_data_actions |
| 141 self.ok_actions = ok_actions |
94 | 142 |
95 def __repr__(self): | 143 def __repr__(self): |
96 return 'MetricAlarm:%s[%s(%s) %s %s]' % (self.name, self.metric, self.st
atistic, self.comparison, self.threshold) | 144 return 'MetricAlarm:%s[%s(%s) %s %s]' % (self.name, self.metric, |
| 145 self.statistic, |
| 146 self.comparison, |
| 147 self.threshold) |
97 | 148 |
98 def startElement(self, name, attrs, connection): | 149 def startElement(self, name, attrs, connection): |
99 return | 150 if name == 'AlarmActions': |
| 151 self.alarm_actions = ListElement() |
| 152 return self.alarm_actions |
| 153 elif name == 'InsufficientDataActions': |
| 154 self.insufficient_data_actions = ListElement() |
| 155 return self.insufficient_data_actions |
| 156 elif name == 'OKActions': |
| 157 self.ok_actions = ListElement() |
| 158 return self.ok_actions |
| 159 else: |
| 160 pass |
100 | 161 |
101 def endElement(self, name, value, connection): | 162 def endElement(self, name, value, connection): |
102 if name == 'ActionsEnabled': | 163 if name == 'ActionsEnabled': |
103 self.actions_enabled = value | 164 self.actions_enabled = value |
104 elif name == 'AlarmArn': | 165 elif name == 'AlarmArn': |
105 self.alarm_arn = value | 166 self.alarm_arn = value |
106 elif name == 'AlarmConfigurationUpdatedTimestamp': | 167 elif name == 'AlarmConfigurationUpdatedTimestamp': |
107 self.last_updated = value | 168 self.last_updated = value |
108 elif name == 'AlarmDescription': | 169 elif name == 'AlarmDescription': |
109 self.description = value | 170 self.description = value |
110 elif name == 'AlarmName': | 171 elif name == 'AlarmName': |
111 self.name = value | 172 self.name = value |
112 elif name == 'ComparisonOperator': | 173 elif name == 'ComparisonOperator': |
113 setattr(self, 'comparison', self._rev_cmp_map[value]) | 174 setattr(self, 'comparison', self._rev_cmp_map[value]) |
114 elif name == 'EvaluationPeriods': | 175 elif name == 'EvaluationPeriods': |
115 self.evaluation_periods = int(value) | 176 self.evaluation_periods = int(value) |
116 elif name == 'MetricName': | 177 elif name == 'MetricName': |
117 self.metric = value | 178 self.metric = value |
118 elif name == 'Namespace': | 179 elif name == 'Namespace': |
119 self.namespace = value | 180 self.namespace = value |
120 elif name == 'Period': | 181 elif name == 'Period': |
121 self.period = int(value) | 182 self.period = int(value) |
122 elif name == 'StateReason': | 183 elif name == 'StateReason': |
123 self.state_reason = value | 184 self.state_reason = value |
124 elif name == 'StateValue': | 185 elif name == 'StateValue': |
125 self.state_value = None | 186 self.state_value = value |
126 elif name == 'Statistic': | 187 elif name == 'Statistic': |
127 self.statistic = value | 188 self.statistic = value |
128 elif name == 'Threshold': | 189 elif name == 'Threshold': |
129 self.threshold = float(value) | 190 self.threshold = float(value) |
130 elif name == 'Unit': | 191 elif name == 'Unit': |
131 self.unit = value | 192 self.unit = value |
132 else: | 193 else: |
133 setattr(self, name, value) | 194 setattr(self, name, value) |
134 | 195 |
135 def set_state(self, value, reason, data=None): | 196 def set_state(self, value, reason, data=None): |
(...skipping 12 matching lines...) Expand all Loading... |
148 | 209 |
149 def update(self): | 210 def update(self): |
150 return self.connection.update_alarm(self) | 211 return self.connection.update_alarm(self) |
151 | 212 |
152 def enable_actions(self): | 213 def enable_actions(self): |
153 return self.connection.enable_alarm_actions([self.name]) | 214 return self.connection.enable_alarm_actions([self.name]) |
154 | 215 |
155 def disable_actions(self): | 216 def disable_actions(self): |
156 return self.connection.disable_alarm_actions([self.name]) | 217 return self.connection.disable_alarm_actions([self.name]) |
157 | 218 |
158 def describe_history(self, start_date=None, end_date=None, max_records=None,
history_item_type=None, next_token=None): | 219 def describe_history(self, start_date=None, end_date=None, max_records=None, |
159 return self.connection.describe_alarm_history(self.name, start_date, end
_date, | 220 history_item_type=None, next_token=None): |
160 max_records, history_item_
type, next_token) | 221 return self.connection.describe_alarm_history(self.name, start_date, |
| 222 end_date, max_records, |
| 223 history_item_type, |
| 224 next_token) |
| 225 |
| 226 def add_alarm_action(self, action_arn=None): |
| 227 """ |
| 228 Adds an alarm action, represented as an SNS topic, to this alarm. |
| 229 What do do when alarm is triggered. |
| 230 |
| 231 :type action_arn: str |
| 232 :param action_arn: SNS topics to which notification should be |
| 233 sent if the alarm goes to state ALARM. |
| 234 """ |
| 235 if not action_arn: |
| 236 return # Raise exception instead? |
| 237 self.actions_enabled = 'true' |
| 238 self.alarm_actions.append(action_arn) |
| 239 |
| 240 def add_insufficient_data_action(self, action_arn=None): |
| 241 """ |
| 242 Adds an insufficient_data action, represented as an SNS topic, to |
| 243 this alarm. What to do when the insufficient_data state is reached. |
| 244 |
| 245 :type action_arn: str |
| 246 :param action_arn: SNS topics to which notification should be |
| 247 sent if the alarm goes to state INSUFFICIENT_DATA. |
| 248 """ |
| 249 if not action_arn: |
| 250 return |
| 251 self.actions_enabled = 'true' |
| 252 self.insufficient_data_actions.append(action_arn) |
| 253 |
| 254 def add_ok_action(self, action_arn=None): |
| 255 """ |
| 256 Adds an ok action, represented as an SNS topic, to this alarm. What |
| 257 to do when the ok state is reached. |
| 258 |
| 259 :type action_arn: str |
| 260 :param action_arn: SNS topics to which notification should be |
| 261 sent if the alarm goes to state INSUFFICIENT_DATA. |
| 262 """ |
| 263 if not action_arn: |
| 264 return |
| 265 self.actions_enabled = 'true' |
| 266 self.ok_actions.append(action_arn) |
| 267 |
| 268 def delete(self): |
| 269 self.connection.delete_alarms([self]) |
161 | 270 |
162 class AlarmHistoryItem(object): | 271 class AlarmHistoryItem(object): |
163 def __init__(self, connection=None): | 272 def __init__(self, connection=None): |
164 self.connection = connection | 273 self.connection = connection |
165 | 274 |
166 def __repr__(self): | 275 def __repr__(self): |
167 return 'AlarmHistory:%s[%s at %s]' % (self.name, self.summary, self.time
stamp) | 276 return 'AlarmHistory:%s[%s at %s]' % (self.name, self.summary, self.time
stamp) |
168 | 277 |
169 def startElement(self, name, attrs, connection): | 278 def startElement(self, name, attrs, connection): |
170 pass | 279 pass |
171 | 280 |
172 def endElement(self, name, value, connection): | 281 def endElement(self, name, value, connection): |
173 if name == 'AlarmName': | 282 if name == 'AlarmName': |
174 self.name = value | 283 self.name = value |
175 elif name == 'HistoryData': | 284 elif name == 'HistoryData': |
176 self.data = json.loads(value) | 285 self.data = json.loads(value) |
177 elif name == 'HistoryItemType': | 286 elif name == 'HistoryItemType': |
178 self.tem_type = value | 287 self.tem_type = value |
179 elif name == 'HistorySummary': | 288 elif name == 'HistorySummary': |
180 self.summary = value | 289 self.summary = value |
181 elif name == 'Timestamp': | 290 elif name == 'Timestamp': |
182 self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') | 291 self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ') |
183 | 292 |
OLD | NEW |