def updateAlarms(self, alarms): # Set up our alarms... for name, atts in alarms.items(): # We don't pass in the alarm_actions attributes into the constructor try: alarm_actions = [ self.actions[a] for a in atts.pop('alarm', []) ] insufficient_data_actions = [ self.actions[a] for a in atts.pop('insufficient_data', []) ] ok_actions = [self.actions[a] for a in atts.pop('ok', [])] except KeyError as e: raise EmitterException('Unknown action %s' % repr(e)) # Set some defaults: atts['statistic'] = atts.get('statistic', 'Average') atts['period'] = atts.get('period', 60) atts['evaluation_periods'] = atts.get('evaluation_periods', 1) # For each of the dimensions... try: atts['dimensions']['InstanceId'] = self.dims['InstanceId'] atts['namespace'] = self.namespace except KeyError: pass a = MetricAlarm(name=self.dims['InstanceId'] + "-" + name, **atts) a.alarm_actions = alarm_actions a.insufficient_data_actions = ListElement( insufficient_data_actions) a.ok_actions = ListElement(ok_actions) self.conn.update_alarm(a)
def updateAlarms(self, alarms): # Set up our alarms... for name, atts in alarms.items(): # We don't pass in the alarm_actions attributes into the constructor try: alarm_actions = [self.actions[a] for a in atts.pop("alarm", [])] insufficient_data_actions = [self.actions[a] for a in atts.pop("insufficient_data", [])] ok_actions = [self.actions[a] for a in atts.pop("ok", [])] except KeyError as e: raise EmitterException("Unknown action %s" % repr(e)) # Set some defaults: atts["statistic"] = atts.get("statistic", "Average") atts["period"] = atts.get("period", 60) atts["evaluation_periods"] = atts.get("evaluation_periods", 1) # For each of the dimensions... try: atts["dimensions"]["InstanceId"] = self.dims["InstanceId"] atts["namespace"] = self.namespace except KeyError: pass a = MetricAlarm(name=self.dims["InstanceId"] + "-" + name, **atts) a.alarm_actions = alarm_actions a.insufficient_data_actions = ListElement(insufficient_data_actions) a.ok_actions = ListElement(ok_actions) self.conn.update_alarm(a)
def updateAlarms(self, alarms): # Set up our alarms... for name, atts in alarms.items(): # We don't pass in the alarm_actions attributes into the constructor try: alarm_actions = [self.actions[a] for a in atts.pop('alarm', [])] insufficient_data_actions = [self.actions[a] for a in atts.pop('insufficient_data', [])] ok_actions = [self.actions[a] for a in atts.pop('ok', [])] except KeyError as e: raise EmitterException('Unknown action %s' % repr(e)) # Set some defaults: atts['statistic'] = atts.get('statistic', 'Average') atts['period'] = atts.get('period', 60) atts['evaluation_periods'] = atts.get('evaluation_periods', 1) # For each of the dimensions... try: atts['dimensions']['InstanceId'] = self.dims['InstanceId'] atts['namespace'] = self.namespace except KeyError: pass a = MetricAlarm(name=name, **atts) a.alarm_actions = alarm_actions a.insufficient_data_actions = ListElement(insufficient_data_actions) a.ok_actions = ListElement(ok_actions) self.conn.update_alarm(a)
def test_put_alarm_with_long_period(self): alarm_name = self.generate_random_name("TestAlarm_") metric_name = self.generate_random_name("TestMetric_") kw = dict(name=alarm_name, metric=metric_name, namespace=self.namespace, threshold=50.0, comparison=">", unit="Percent") # period: a day + one second, evaluation_periods: 1 time long_period_kw = kw.copy() long_period_kw.update(period=60 * 60 * 24 + 1, evaluation_periods=1) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, MetricAlarm(**long_period_kw)) # period: a minutes, evaluation_periods: 24 * 60 + 1 times long_evaluation_period_kw = kw.copy() long_evaluation_period_kw.update(period=60, evaluation_periods=24 * 60 + 1) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, MetricAlarm(**long_evaluation_period_kw)) # period: an hour, evaluation_periods: 25 times (over a day) long_evaluation_kw = kw.copy() long_evaluation_kw.update(period=60 * 60, evaluation_periods=25) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, MetricAlarm(**long_evaluation_kw))
def create_alarm(self, name, comparison, threshold, period, evaluation_periods, statistic, enabled=True, description=None, dimensions=None, alarm_actions=None, ok_actions=None, insufficient_data_actions=None, unit=None): """ Creates or updates an alarm and associates it with this metric. Optionally, this operation can associate one or more Amazon Simple Notification Service resources with the alarm. When this operation creates an alarm, the alarm state is immediately set to INSUFFICIENT_DATA. The alarm is evaluated and its StateValue is set appropriately. Any actions associated with the StateValue is then executed. When updating an existing alarm, its StateValue is left unchanged. :type alarm: boto.ec2.cloudwatch.alarm.MetricAlarm :param alarm: MetricAlarm object. """ if not dimensions: dimensions = self.dimensions alarm = MetricAlarm(self.connection, name, self.name, self.namespace, statistic, comparison, threshold, period, evaluation_periods, unit, description, dimensions, alarm_actions, insufficient_data_actions, ok_actions) if self.connection.put_metric_alarm(alarm): return alarm
def test_describe_alarms_for_metric(self): prefix = "AlarmsToBeDescribed" alarmnames = [self.generate_random_name(prefix) for i in range(10)] for alarmname in alarmnames: alarm = MetricAlarm(name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) self.synaps.describe_alarms_for_metric(namespace=self.namespace, metric_name=self.metric_name, dimensions=self.dimensions) self.synaps.delete_alarms(alarmnames)
def set_alarm(alarmName, metricName, thresholdValue, unit, thresholds, operator): print "put-metric-alarm(alarm-name="+alarmName+ \ ",alarm-description="+metricName+\ ",metric-name="+metricName+\ ",namespace="+config.SERVER_NAME+\ ",statistic=Average"+\ ",period=120"+\ "threshold="+thresholdValue+\ "comparison-operator="+operator+\ ",evaluation-periods=1"+\ ",alarm-actions="+sns_arn+\ ",unit="+unit if not options.debug: cwc.put_metric_alarm( MetricAlarm(name=alarmName, description=metricName, alarm_actions=sns_arn, metric=metricName, namespace=config.SERVER_NAME, statistic="Average", period=120, unit=unit, evaluation_periods=1, threshold=thresholdValue, comparison=operator))
def test_delete_alarm(): conn = boto.connect_cloudwatch() alarm = MetricAlarm( name='tester', comparison='>=', threshold=2.0, period=60, evaluation_periods=5, statistic='Average', description='A test', dimensions={'InstanceId': ['i-0123456,i-0123457']}, alarm_actions=['arn:alarm'], ok_actions=['arn:ok'], insufficient_data_actions=['arn:insufficient'], unit='Seconds', ) conn.create_alarm(alarm) alarms = conn.describe_alarms() alarms.should.have.length_of(1) alarms[0].delete() alarms = conn.describe_alarms() alarms.should.have.length_of(0)
def test_delete_ten_alarms(self): # put 10 alarms and delete all of them alarmnames = [ self.generate_random_name("AlarmsToBeDeleted") for i in range(10) ] for name in alarmnames: alarm = MetricAlarm(name=name, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) time.sleep(ASYNC_WAIT) for alarm in alarmnames: self.synaps.delete_alarms(alarms=[alarm]) time.sleep(ASYNC_WAIT) alarms = self.synaps.describe_alarms() for a in alarms: self.assertFalse(a.name in alarmnames)
def test_set_alarm_state(self): alarmname = self.generate_random_name("TEST_ALARM_") alarm = MetricAlarm(name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0, period=60, evaluation_periods=1, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) time.sleep(ASYNC_WAIT) self.synaps.set_alarm_state(alarmname, state_reason="Manual input", state_value="ALARM") time.sleep(ASYNC_WAIT) self.synaps.delete_alarms(alarms=[alarmname])
def test_create_alarm(): conn = boto.connect_cloudwatch() alarm = MetricAlarm( name='tester', comparison='>=', threshold=2.0, period=60, evaluation_periods=5, statistic='Average', description='A test', dimensions={'InstanceId': ['i-0123456,i-0123457']}, alarm_actions=['arn:alarm'], ok_actions=['arn:ok'], insufficient_data_actions=['arn:insufficient'], unit='Seconds', ) conn.create_alarm(alarm) alarms = conn.describe_alarms() alarms.should.have.length_of(1) alarm = alarms[0] alarm.name.should.equal('tester') alarm.comparison.should.equal('>=') alarm.threshold.should.equal(2.0) alarm.period.should.equal(60) alarm.evaluation_periods.should.equal(5) alarm.statistic.should.equal('Average') alarm.description.should.equal('A test') dict(alarm.dimensions).should.equal( {'InstanceId': ['i-0123456,i-0123457']}) list(alarm.alarm_actions).should.equal(['arn:alarm']) list(alarm.ok_actions).should.equal(['arn:ok']) list(alarm.insufficient_data_actions).should.equal(['arn:insufficient']) alarm.unit.should.equal('Seconds')
def create_alarm_obj(self, task, domain): alarm = MetricAlarm( name=self.alarm_name(task), alarm_actions=self.sns_topic_arns, namespace='AWS/SWF', period=self.period, evaluation_periods=self.evaluation_periods, statistic='Sum', **self.alarm_params(task, domain)) return alarm
def test_put_alarm(self): alarmname = self.generate_random_name("AlarmToBeDeleted") alarm_actions = ['+82 1012345678', '*****@*****.**'] ok_actions = [ '+82 1012345678', '+82 1012345678', '*****@*****.**' ] insufficient_data_actions = [ '+82 1087654322', '*****@*****.**', '*****@*****.**' ] alarm = MetricAlarm( name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison=">", threshold=50.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=alarm_actions, insufficient_data_actions=insufficient_data_actions, ok_actions=ok_actions) self.synaps.put_metric_alarm(alarm) n = 20 minute = datetime.timedelta(seconds=60) start = datetime.datetime.utcnow() - n * minute for i in range(n): ret = self.synaps.put_metric_data( namespace=self.namespace, name=self.metric_name, value=i * 5.0, unit="Percent", dimensions=self.dimensions, timestamp=start + i * minute, ) time.sleep(ASYNC_WAIT) alarms = self.synaps.describe_alarms(alarm_names=[alarmname]) for a in alarms: self.assertSetEqual(set(ok_actions), set(a.ok_actions)) self.assertSetEqual(set(alarm_actions), set(a.alarm_actions)) self.assertSetEqual(set(insufficient_data_actions), set(a.insufficient_data_actions)) last_updated = datetime.datetime.strptime(a.last_updated, "%Y-%m-%dT%H:%M:%S.%fZ") self.assertTrue(datetime.datetime.utcnow() - last_updated < datetime.timedelta(seconds=60)) self.synaps.delete_alarms([alarmname])
def monitor_instance(self, instid, cputhres=None, period=None): ''' Adds an instance to CloudWatch, generating cpuhigh and cpulow alarms. ''' conn = self.init() # default threshold if cputhres is None: cputhres = os.environ['KAS_ALARM_CPUTHRES'] if period is None: period = os.environ['KAS_WATCH_PERIOD'] cpulow = float(cputhres.split(':')[0]) cpuhigh = float(cputhres.split(':')[1]) #create a metric for cpu high for this instance alarm = MetricAlarm(name=self.alarm_name('cpuhigh', instid), metric='CPUUtilization', statistic='Average', namespace="AWS/EC2", dimensions={'InstanceId': [instid]}, comparison='>=', threshold=cpuhigh, evaluation_periods=1, description='Automatic metric', alarm_actions=os.environ['KAS_SNS_TOPIC_ARN'], ok_actions=os.environ['KAS_SNS_TOPIC_ARN'], period=int(period)) conn.put_metric_alarm(alarm) # create a metric for cpu high for this instance alarm = MetricAlarm(name=self.alarm_name('cpulow', instid), metric='CPUUtilization', statistic='Average', namespace="AWS/EC2", dimensions={'InstanceId': [instid]}, comparison='>=', threshold=cpulow, evaluation_periods=1, description='Automatic metric', alarm_actions=os.environ['KAS_SNS_TOPIC_ARN'], ok_actions=os.environ['KAS_SNS_TOPIC_ARN'], period=int(period)) conn.put_metric_alarm(alarm)
def setUpCloudWatch(self, instance_ids, env="stg"): alarm = MetricAlarm(name="servergmsextender_CloudWatchAlarm" + env, namespace="AWS/EC2", metric="CPUUtilization", comparison=">=", threshold="90", evaluation_periods=1, statistic="Average", period=300, dimensions={'InstanceId': instance_ids}, alarm_actions=['arn:alarm'], ok_actions=['arn:ok']) watch_conn = boto.connect_cloudwatch() watch_conn.put_metric_alarm(alarm)
def create_alarm(self, name, comparison, threshold, period, evaluation_periods, statistic, enabled=True, description=None, dimensions=None, alarm_actions=None, ok_actions=None, insufficient_data_actions=None, unit=None): if not dimensions: dimensions = self.dimensions alarm = MetricAlarm(self.connection, name, self.name, self.namespace, statistic, comparison, threshold, period, evaluation_periods, unit, description, dimensions, alarm_actions, insufficient_data_actions, ok_actions) if self.connection.put_metric_alarm(alarm): return alarm
def setUpCloudWatchWithWrongConfig(self, instance_ids, env="stg"): alarm = MetricAlarm( name = "servergmsextender_CloudWatchAlarm" + env, namespace = "AWS/EC2", metric = "CPUUtilization", comparison = "GreaterThanThreshold", # wrong configuration that would generate error. threshold = "90", evaluation_periods = 1, statistic = "Average", period = 300, dimensions = {'InstanceId': instance_ids}, alarm_actions=['arn:alarm'], ok_actions=['arn:ok'] ) watch_conn = boto.connect_cloudwatch() watch_conn.put_metric_alarm(alarm)
def alarm_fixture(name="tester", action=None): action = action or ['arn:alarm'] return MetricAlarm( name=name, comparison='>=', threshold=2.0, period=60, evaluation_periods=5, statistic='Average', description='A test', dimensions={'InstanceId': ['i-0123456,i-0123457']}, alarm_actions=action, ok_actions=['arn:ok'], insufficient_data_actions=['arn:insufficient'], unit='Seconds', )
def test_put_alarm_with_invalid_unit(self): # test check Parameters... alarm = MetricAlarm(name="CPU_Alarm", metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison=">", threshold=50.0, period=300, evaluation_periods=2, unit="It will occur an error", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, alarm)
def alarm_fixture(name="tester", action=None): action = action or ["arn:alarm"] return MetricAlarm( name=name, namespace="{0}_namespace".format(name), metric="{0}_metric".format(name), comparison=">=", threshold=2.0, period=60, evaluation_periods=5, statistic="Average", description="A test", dimensions={"InstanceId": ["i-0123456,i-0123457"]}, alarm_actions=action, ok_actions=["arn:ok"], insufficient_data_actions=["arn:insufficient"], unit="Seconds", )
def test_enable_alarm_actions(self): alarmnames = [ self.generate_random_name("TEST_ALARM_") for i in range(10) ] metric_name = self.generate_random_name("TEST_METRIC") for alarmname in alarmnames: alarm = MetricAlarm(name=alarmname, metric=metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0 * i, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) time.sleep(ASYNC_WAIT) self.synaps.enable_alarm_actions(alarmnames) time.sleep(ASYNC_WAIT) alarms = self.synaps.describe_alarms(alarm_names=alarmnames) for a in alarms: self.assertTrue(a.actions_enabled, 'true') self.synaps.disable_alarm_actions(alarmnames) time.sleep(ASYNC_WAIT) alarms = self.synaps.describe_alarms(alarm_names=alarmnames) for a in alarms: self.assertEqual(a.actions_enabled, 'false') for alarm in alarmnames: self.synaps.delete_alarms(alarms=[alarm]) time.sleep(ASYNC_WAIT) alarms = self.synaps.describe_alarms(alarm_names=alarmnames) for a in alarms: self.assertFalse(a.name in alarmnames)
def test_put_metric_alarm_with_bad_statistic(self): # test check Parameters... alarmname = self.generate_random_name("BadAlarm") alarm = MetricAlarm(name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="It will occur an error", comparison=">", threshold=50.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, alarm)
def test_put_alarm_with_utf8_name(self): prefix = u"TEST_\uc54c\ub78c_02" alarm_names = map(self.generate_random_name, [prefix]) for alarmname in alarm_names: alarm = MetricAlarm(name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.assertRaises(BotoServerError, self.synaps.put_metric_alarm, alarm)
def monitor_loadbalancer(self, name, reqthres=None): conn = self.init() # default threshold if reqthres is None: reqthres = 1.0 # create a metric for request count this instance alarm = MetricAlarm(name=self.alarm_name('reqcount', name), metric='Latency', statistic='Average', dimensions={'LoadBalancerName': [name]}, namespace="AWS/EC2", comparison='>=', threshold=reqthres, unit='Count', evaluation_periods=1, description='Automatic metric', alarm_actions=os.environ['KAS_SNS_TOPIC_ARN'], ok_actions=os.environ['KAS_SNS_TOPIC_ARN'], period=300) conn.put_metric_alarm(alarm)
def test_describe_alarms_with_max_records(self): # put 10 alarms prefix = "AlarmsToBeDescribed" alarmnames = [self.generate_random_name(prefix) for i in range(10)] metric_name = self.generate_random_name("metricname-") for alarmname in alarmnames: alarm = MetricAlarm(name=alarmname, metric=metric_name, namespace=self.namespace, statistic="Average", comparison="<", threshold=2.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) alarms = self.synaps.describe_alarms(max_records=3) self.assertEqual(len(alarms), 3) alarms = self.synaps.describe_alarms(max_records=9, alarm_name_prefix=prefix) self.assertTrue(len(alarms) <= 9) for a in alarms: self.assertTrue(a.name.startswith(prefix)) alarms = self.synaps.describe_alarms(alarm_names=alarmnames) for a in alarms: self.assertTrue(a.name in alarmnames) self.synaps.delete_alarms(alarms=alarmnames)
def test_alarm_actions(self): # delete Alarm try: self.synaps.delete_alarms(alarms=['AlarmActionTest']) time.sleep(ASYNC_WAIT) except BotoServerError: pass # add Alarm alarm_actions = ['+82 1093145616', '*****@*****.**'] ok_actions = [ '+82 1012345678', '+82 1093145616', '*****@*****.**' ] insufficient_data_actions = [ '+82 1093145616', '*****@*****.**', '*****@*****.**' ] alarm = MetricAlarm( name="AlarmActionTest", metric=self.metric_name, namespace=self.namespace, statistic="Sum", comparison=">", threshold=50.0, period=300, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=alarm_actions, insufficient_data_actions=insufficient_data_actions, ok_actions=ok_actions) self.synaps.put_metric_alarm(alarm) time.sleep(ASYNC_WAIT) # get MetricStatistics n = 10 minute = datetime.timedelta(seconds=60) end_time = datetime.datetime.utcnow() start_time = end_time - n * minute stats = self.synaps.get_metric_statistics(period=60, start_time=start_time, end_time=end_time, metric_name=self.metric_name, namespace=self.namespace, statistics=["Sum"], dimensions=self.dimensions, unit="Percent") for s in stats: self.synaps.put_metric_data(namespace=self.namespace, name=self.metric_name, value=-s["Sum"], timestamp=s['Timestamp'], unit=s["Unit"], dimensions=self.dimensions) for i in range(n): self.synaps.put_metric_data(namespace=self.namespace, name=self.metric_name, value=i * 10, unit="Percent", dimensions=self.dimensions, timestamp=start_time + i * minute) time.sleep(ASYNC_WAIT) # delete alarm self.synaps.delete_alarms(alarms=['AlarmActionTest']) time.sleep(ASYNC_WAIT)
def test_put_alarm_with_period(self): alarmname = self.generate_random_name("Test_Alarm_Period") alarm = MetricAlarm(name=alarmname, metric=self.metric_name, namespace=self.namespace, statistic="Average", comparison=">", threshold=50.0, period=6000, evaluation_periods=2, unit="Percent", description=None, dimensions=self.dimensions, alarm_actions=None, insufficient_data_actions=None, ok_actions=None) self.synaps.put_metric_alarm(alarm) td = timedelta(days=20, seconds=1) ret1 = self.synaps.put_metric_data( namespace=self.namespace, name=self.metric_name, value=10, unit="Percent", dimensions=self.dimensions, timestamp=datetime.datetime.utcnow() - td) td2 = timedelta(seconds=7200) ret2 = self.synaps.put_metric_data( namespace=self.namespace, name=self.metric_name, value=20, unit="Percent", dimensions=self.dimensions, timestamp=datetime.datetime.utcnow() - td2) self.assertTrue(ret2) td3 = timedelta(seconds=5400) ret3 = self.synaps.put_metric_data( namespace=self.namespace, name=self.metric_name, value=30, unit="Percent", dimensions=self.dimensions, timestamp=datetime.datetime.utcnow() - td3) self.assertTrue(ret3) self.synaps.delete_alarms(alarms=[alarmname]) td4 = timedelta(seconds=2000) ret4 = self.synaps.put_metric_data( namespace=self.namespace, name=self.metric_name, value=40, unit="Percent", dimensions=self.dimensions, timestamp=datetime.datetime.utcnow() - td4) self.assertTrue(ret4)
def test_eval_alarm(self): """ Test Scenario for following sequence. 1. Put metric alarm (period 60, evaluation_periods 1) 2. Put metric data which is over the threshold so that the alarm state would be 'ALARM' 3. Wait 2 minutes so that alarm state could be 'INSUFFICIENT_DATA' 4. Put metric data which is under the threshold so that the alarm state would be 'OK' 5. Wait 3 minutes so that alarm state could be 'INSUFFICIENT_DATA' 6. Describe alarm history and check if it has been changed as we are expected """ def get_state_update_value(h): oldstate = h.data['oldState']['stateValue'] newstate = h.data['newState']['stateValue'] querydate = h.data['newState']['stateReasonData']['queryDate'] querydate = utils.parse_strtime(querydate) return oldstate, newstate, querydate test_uuid = str(uuid.uuid4()) alarmname = "TestEvalAlarm_" + test_uuid metricname = "TestEvalMetric_" + test_uuid namespace = self.namespace unit = "Percent" dimensions = {"test_id":test_uuid} threshold = 2.0 # create metric alarm alarm = MetricAlarm(name=alarmname, metric=metricname, namespace=namespace, statistic="Average", comparison=">", threshold=threshold, period=60, evaluation_periods=1, unit=unit, dimensions=dimensions) self.synaps.put_metric_alarm(alarm) # due to put_metric_alarm is asynchronous time.sleep(ASYNC_WAIT) alarm_time = datetime.datetime.utcnow().replace(second=0, microsecond=0) self.synaps.put_metric_data(namespace=namespace, name=metricname, value=threshold + 1, timestamp=alarm_time, unit=unit, dimensions=dimensions) time.sleep(60 * 5) ok_time = datetime.datetime.utcnow().replace(second=0, microsecond=0) self.synaps.put_metric_data(namespace=namespace, name=metricname, value=threshold - 2, timestamp=ok_time, unit=unit, dimensions=dimensions) time.sleep(60 * 5) histories = self.synaps.describe_alarm_history(alarm_name=alarmname, history_item_type="StateUpdate") histories.sort(cmp=lambda a, b: cmp(a.timestamp, b.timestamp)) result = map(get_state_update_value, histories) expected = (('INSUFFICIENT_DATA', 'ALARM', alarm_time), ('ALARM', 'INSUFFICIENT_DATA', None), ('INSUFFICIENT_DATA', 'OK', ok_time), ('OK', 'INSUFFICIENT_DATA', None)) failmsg = "expected: %s real: %s" % (expected, result) self.assertEqual(len(result), len(expected), msg=failmsg) for ((r_new, r_old, r_time), (e_new, e_old, e_time)) in zip(result, expected): self.assertEqual(r_new, e_new, msg=failmsg) self.assertEqual(r_old, e_old, msg=failmsg) if e_time: self.assertTrue((r_time - e_time) < timedelta(seconds=300), msg=failmsg) self.synaps.delete_alarms(alarms=[alarmname])