diff --git a/aodh/api/controllers/v2/alarm_rules/gnocchi.py b/aodh/api/controllers/v2/alarm_rules/gnocchi.py index 37af41fbc..47d2428be 100644 --- a/aodh/api/controllers/v2/alarm_rules/gnocchi.py +++ b/aodh/api/controllers/v2/alarm_rules/gnocchi.py @@ -200,10 +200,15 @@ class AggregationMetricByResourcesLookupRule(AlarmGnocchiThresholdRule): 'interface': conf.service_credentials.interface, 'region_name': conf.service_credentials.region_name}) try: - gnocchi_client.metric.aggregation( - metrics=rule.metric, - query=query, - aggregation=rule.aggregation_method, + gnocchi_client.aggregates.fetch( + operations=[ + 'aggregate', rule.aggregation_method, + [ + 'metric', rule.metric, + rule.aggregation_method.lstrip('rate:') + ] + ], + search=query, needed_overlap=0, start="-1 day", stop="now", diff --git a/aodh/evaluator/gnocchi.py b/aodh/evaluator/gnocchi.py index 29fd5493d..802e8a3b7 100644 --- a/aodh/evaluator/gnocchi.py +++ b/aodh/evaluator/gnocchi.py @@ -47,6 +47,12 @@ class GnocchiBase(threshold.ThresholdEvaluator): # but not a stddev-of-stddevs). # TODO(sileht): support alarm['exclude_outliers'] LOG.debug('sanitize stats %s', statistics) + # NOTE(jamespage) + # Dynamic Aggregates are returned in a dict struct so + # check for this first. + if isinstance(statistics, dict): + # Pop array of measures from aggregated subdict + statistics = statistics['measures']['aggregated'] statistics = [stats[VALUE] for stats in statistics if stats[GRANULARITY] == rule['granularity']] if not statistics: @@ -93,6 +99,16 @@ class GnocchiResourceThresholdEvaluator(GnocchiBase): class GnocchiAggregationMetricsThresholdEvaluator(GnocchiBase): def _statistics(self, rule, start, end): try: + _operations = [ + 'aggregate', rule['aggregation_method'] + ] + for metric in rule['metrics']: + _operations.append( + [ + 'metric', metric, + rule['aggregation_method'].lstrip('rate:') + ] + ) # FIXME(sileht): In case of a heat autoscaling stack decide to # delete an instance, the gnocchi metrics associated to this # instance will be no more updated and when the alarm will ask @@ -101,11 +117,10 @@ class GnocchiAggregationMetricsThresholdEvaluator(GnocchiBase): # So temporary set 'needed_overlap' to 0 to disable the # gnocchi checks about missing points. For more detail see: # https://bugs.launchpad.net/gnocchi/+bug/1479429 - return self._gnocchi_client.metric.aggregation( - metrics=rule['metrics'], + return self._gnocchi_client.aggregates.fetch( + operations=_operations, granularity=rule['granularity'], start=start, stop=end, - aggregation=rule['aggregation_method'], needed_overlap=0) except exceptions.MetricNotFound: raise threshold.InsufficientDataError( @@ -128,24 +143,28 @@ class GnocchiAggregationMetricsThresholdEvaluator(GnocchiBase): class GnocchiAggregationResourcesThresholdEvaluator(GnocchiBase): def _statistics(self, rule, start, end): - # FIXME(sileht): In case of a heat autoscaling stack decide to - # delete an instance, the gnocchi metrics associated to this - # instance will be no more updated and when the alarm will ask - # for the aggregation, gnocchi will raise a 'No overlap' - # exception. - # So temporary set 'needed_overlap' to 0 to disable the - # gnocchi checks about missing points. For more detail see: - # https://bugs.launchpad.net/gnocchi/+bug/1479429 try: - return self._gnocchi_client.metric.aggregation( - metrics=rule['metric'], + # FIXME(sileht): In case of a heat autoscaling stack decide to + # delete an instance, the gnocchi metrics associated to this + # instance will be no more updated and when the alarm will ask + # for the aggregation, gnocchi will raise a 'No overlap' + # exception. + # So temporary set 'needed_overlap' to 0 to disable the + # gnocchi checks about missing points. For more detail see: + # https://bugs.launchpad.net/gnocchi/+bug/1479429 + return self._gnocchi_client.aggregates.fetch( + operations=[ + 'aggregate', rule['aggregation_method'], + [ + 'metric', rule['metric'], + rule['aggregation_method'].lstrip('rate:') + ] + ], granularity=rule['granularity'], - query=json.loads(rule['query']), + search=json.loads(rule['query']), resource_type=rule["resource_type"], start=start, stop=end, - aggregation=rule['aggregation_method'], - needed_overlap=0, - ) + needed_overlap=0) except exceptions.MetricNotFound: raise threshold.InsufficientDataError( 'metric %s does not exists' % rule['metric'], []) diff --git a/aodh/tests/functional/api/v2/test_alarm_scenarios.py b/aodh/tests/functional/api/v2/test_alarm_scenarios.py index 3d2e55de3..78e11153f 100644 --- a/aodh/tests/functional/api/v2/test_alarm_scenarios.py +++ b/aodh/tests/functional/api/v2/test_alarm_scenarios.py @@ -2503,14 +2503,16 @@ class TestAlarmsRuleGnocchi(TestAlarmsBase): self.post_json('/alarms', params=json, headers=self.auth_headers) self.assertEqual([mock.call( - aggregation='count', - metrics='ameter', + operations=[ + 'aggregate', 'count', + ['metric', 'ameter', 'count'] + ], needed_overlap=0, start="-1 day", stop="now", - query=expected_query, + search=expected_query, resource_type="instance")], - c.metric.aggregation.mock_calls), + c.aggregates.fetch.mock_calls), alarms = list(self.alarm_conn.get_alarms(enabled=False)) self.assertEqual(1, len(alarms)) diff --git a/aodh/tests/unit/evaluator/test_composite.py b/aodh/tests/unit/evaluator/test_composite.py index db9d254cf..54030c6c6 100644 --- a/aodh/tests/unit/evaluator/test_composite.py +++ b/aodh/tests/unit/evaluator/test_composite.py @@ -35,8 +35,16 @@ class BaseCompositeEvaluate(base.TestEvaluatorBase): super(BaseCompositeEvaluate, self).setUp() @staticmethod - def _get_gnocchi_stats(granularity, values): + def _get_gnocchi_stats(granularity, values, aggregated=False): now = timeutils.utcnow_ts() + if aggregated: + return { + 'measures': { + 'aggregated': + [[str(now - len(values) * granularity), + granularity, value] for value in values] + } + } return [[str(now - len(values) * granularity), granularity, value] for value in values] @@ -236,7 +244,7 @@ class CompositeTest(BaseCompositeEvaluate): def test_simple_insufficient(self): self._set_all_alarms('ok') - self.client.metric.aggregation.return_value = [] + self.client.aggregates.fetch.return_value = [] self.client.metric.get_measures.return_value = [] self._evaluate_all_alarms() self._assert_all_alarms('insufficient data') @@ -287,26 +295,36 @@ class CompositeTest(BaseCompositeEvaluate): # self.sub_rule4: ok # self.sub_rule5: ok # self.sub_rule6: alarm - maxs = self._get_gnocchi_stats(60, [self.sub_rule2['threshold'] + v - for v in range(1, 5)]) - avgs1 = self._get_gnocchi_stats(60, [self.sub_rule3['threshold'] + v - for v in range(1, 4)]) - avgs2 = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] - v - for v in range(1, 6)]) - - gavgs1 = self._get_gnocchi_stats(60, [self.sub_rule4['threshold'] - - v for v in range(1, 6)]) - gmaxs = self._get_gnocchi_stats(300, [self.sub_rule5['threshold'] + v - for v in range(1, 5)]) - gavgs2 = self._get_gnocchi_stats(50, [self.sub_rule6['threshold'] + v - for v in range(1, 7)]) + maxs = self._get_gnocchi_stats( + 60, [self.sub_rule2['threshold'] + v + for v in range(1, 5)], + aggregated=True) + avgs1 = self._get_gnocchi_stats( + 60, [self.sub_rule3['threshold'] + v + for v in range(1, 4)]) + avgs2 = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] - v + for v in range(1, 6)], + aggregated=True) + gavgs1 = self._get_gnocchi_stats( + 60, [self.sub_rule4['threshold'] + - v for v in range(1, 6)], + aggregated=True) + gmaxs = self._get_gnocchi_stats( + 300, [self.sub_rule5['threshold'] + v + for v in range(1, 5)], + aggregated=True) + gavgs2 = self._get_gnocchi_stats( + 50, [self.sub_rule6['threshold'] + v + for v in range(1, 7)], + aggregated=True) self.client.metric.get_measures.side_effect = [gavgs1] - self.client.metric.aggregation.side_effect = [maxs, avgs1, avgs2, - gmaxs, gavgs2] + self.client.aggregates.fetch.side_effect = [maxs, avgs1, avgs2, + gmaxs, gavgs2] self.evaluator.evaluate(alarm) self.assertEqual(1, self.client.metric.get_measures.call_count) - self.assertEqual(5, self.client.metric.aggregation.call_count) + self.assertEqual(5, self.client.aggregates.fetch.call_count) self.assertEqual('alarm', alarm.state) expected = mock.call( alarm, 'ok', @@ -320,12 +338,14 @@ class CompositeTest(BaseCompositeEvaluate): def test_alarm_with_short_circuit_logic(self): alarm = self.alarms[1] # self.sub_rule1: alarm - avgs = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] + v - for v in range(1, 6)]) - self.client.metric.aggregation.side_effect = [avgs] + avgs = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] + v + for v in range(1, 6)], + aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs] self.evaluator.evaluate(alarm) self.assertEqual('alarm', alarm.state) - self.assertEqual(1, self.client.metric.aggregation.call_count) + self.assertEqual(1, self.client.aggregates.fetch.call_count) expected = mock.call(self.alarms[1], 'insufficient data', *self._reason( 'alarm', @@ -336,12 +356,14 @@ class CompositeTest(BaseCompositeEvaluate): def test_ok_with_short_circuit_logic(self): alarm = self.alarms[2] # self.sub_rule1: ok - avgs = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] - v - for v in range(1, 6)]) - self.client.metric.aggregation.side_effect = [avgs] + avgs = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] - v + for v in range(1, 6)], + aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs] self.evaluator.evaluate(alarm) self.assertEqual('ok', alarm.state) - self.assertEqual(1, self.client.metric.aggregation.call_count) + self.assertEqual(1, self.client.aggregates.fetch.call_count) expected = mock.call(self.alarms[2], 'insufficient data', *self._reason( 'ok', @@ -351,13 +373,19 @@ class CompositeTest(BaseCompositeEvaluate): def test_unknown_state_with_sub_rules_trending_state(self): alarm = self.alarms[0] - maxs = self._get_gnocchi_stats(60, [self.sub_rule2['threshold'] + v - for v in range(-1, 4)]) - avgs = self._get_gnocchi_stats(60, [self.sub_rule3['threshold'] + v - for v in range(-1, 3)]) - avgs2 = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] - v - for v in range(1, 6)]) - self.client.metric.aggregation.side_effect = [avgs2, maxs, avgs] + maxs = self._get_gnocchi_stats( + 60, [self.sub_rule2['threshold'] + v + for v in range(-1, 4)], + aggregated=True) + avgs = self._get_gnocchi_stats( + 60, [self.sub_rule3['threshold'] + v + for v in range(-1, 3)], + aggregated=True) + avgs2 = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] - v + for v in range(1, 6)], + aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs2, maxs, avgs] self.evaluator.evaluate(alarm) self.assertEqual('alarm', alarm.state) @@ -374,13 +402,19 @@ class CompositeTest(BaseCompositeEvaluate): alarm.repeat_actions = True alarm.state = 'ok' - maxs = self._get_gnocchi_stats(60, [self.sub_rule2['threshold'] + v - for v in range(-1, 4)]) - avgs = self._get_gnocchi_stats(60, [self.sub_rule3['threshold'] + v - for v in range(-1, 3)]) - avgs2 = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] - v - for v in range(1, 6)]) - self.client.metric.aggregation.side_effect = [avgs2, maxs, avgs] + maxs = self._get_gnocchi_stats( + 60, [self.sub_rule2['threshold'] + v + for v in range(-1, 4)], + aggregated=True) + avgs = self._get_gnocchi_stats( + 60, [self.sub_rule3['threshold'] + v + for v in range(-1, 3)], + aggregated=True) + avgs2 = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] - v + for v in range(1, 6)], + aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs2, maxs, avgs] self.evaluator.evaluate(alarm) self.assertEqual('ok', alarm.state) @@ -396,13 +430,19 @@ class CompositeTest(BaseCompositeEvaluate): def test_known_state_with_sub_rules_trending_state_and_not_repeat(self): alarm = self.alarms[2] alarm.state = 'ok' - maxs = self._get_gnocchi_stats(60, [self.sub_rule2['threshold'] + v - for v in range(-1, 4)]) - avgs = self._get_gnocchi_stats(60, [self.sub_rule3['threshold'] + v - for v in range(-1, 3)]) - avgs2 = self._get_gnocchi_stats(60, [self.sub_rule1['threshold'] - v - for v in range(1, 6)]) - self.client.metric.aggregation.side_effect = [avgs2, maxs, avgs] + maxs = self._get_gnocchi_stats( + 60, [self.sub_rule2['threshold'] + v + for v in range(-1, 4)], + aggregated=True) + avgs = self._get_gnocchi_stats( + 60, [self.sub_rule3['threshold'] + v + for v in range(-1, 3)], + aggregated=True) + avgs2 = self._get_gnocchi_stats( + 60, [self.sub_rule1['threshold'] - v + for v in range(1, 6)], + aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs2, maxs, avgs] self.evaluator.evaluate(alarm) self.assertEqual('ok', alarm.state) self.assertEqual([], self.notifier.notify.mock_calls) diff --git a/aodh/tests/unit/evaluator/test_gnocchi.py b/aodh/tests/unit/evaluator/test_gnocchi.py index 4ac894db1..f6aa127e6 100644 --- a/aodh/tests/unit/evaluator/test_gnocchi.py +++ b/aodh/tests/unit/evaluator/test_gnocchi.py @@ -109,9 +109,9 @@ class TestGnocchiEvaluatorBase(base.TestEvaluatorBase): comparison_operator='gt', threshold=80.0, evaluation_periods=6, - aggregation_method='mean', + aggregation_method='rate:mean', granularity=50, - metric='cpu_util', + metric='cpu', resource_type='instance', query='{"=": {"server_group": ' '"my_autoscaling_group"}}') @@ -121,8 +121,16 @@ class TestGnocchiEvaluatorBase(base.TestEvaluatorBase): super(TestGnocchiEvaluatorBase, self).setUp() @staticmethod - def _get_stats(granularity, values): + def _get_stats(granularity, values, aggregated=False): now = timeutils.utcnow_ts() + if aggregated: + return { + 'measures': { + 'aggregated': + [[str(now - len(values) * granularity), + granularity, value] for value in values] + } + } return [[str(now - len(values) * granularity), granularity, value] for value in values] @@ -431,13 +439,17 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): self.alarms = self.prepared_alarms[1:2] def test_retry_transient_api_failure(self): - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] + v - for v in range(4)]) - self.client.metric.aggregation.side_effect = [Exception('boom'), maxs] + maxs = self._get_stats( + 300, + [self.alarms[0].rule['threshold'] + v + for v in range(4)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [Exception('boom'), maxs] self._test_retry_transient() def test_simple_insufficient(self): - self.client.metric.aggregation.return_value = [] + self.client.aggregates.fetch.return_value = [] self._test_simple_insufficient() @mock.patch.object(timeutils, 'utcnow') @@ -445,26 +457,33 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): utcnow.return_value = datetime.datetime(2015, 1, 26, 12, 57, 0, 0) self._set_all_alarms('ok') - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] - v - for v in range(4)]) - self.client.metric.aggregation.side_effect = [maxs] + maxs = self._get_stats( + 300, + [self.alarms[0].rule['threshold'] - v + for v in range(4)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() start_alarm = "2015-01-26T12:32:00" end = "2015-01-26T12:57:00" self.assertEqual( - [mock.call.aggregation(aggregation='max', - metrics=[ - '0bb1604d-1193-4c0a-b4b8-74b170e35e83', - '9ddc209f-42f8-41e1-b8f1-8804f59c4053'], - granularity=300, - needed_overlap=0, - start=start_alarm, stop=end)], - self.client.metric.mock_calls) + [mock.call.fetch( + operations=[ + 'aggregate', 'max', + ['metric', '0bb1604d-1193-4c0a-b4b8-74b170e35e83', 'max'], # noqa + ['metric', '9ddc209f-42f8-41e1-b8f1-8804f59c4053', 'max'], # noqa + ], + granularity=300, + needed_overlap=0, + start=start_alarm, stop=end)], + self.client.aggregates.mock_calls) self._assert_all_alarms('alarm') expected = [mock.call(alarm) for alarm in self.alarms] update_calls = self.storage_conn.update_alarm.call_args_list self.assertEqual(expected, update_calls) + maxs = maxs['measures']['aggregated'] reason = ('Transition to alarm due to 4 samples outside ' 'threshold, most recent: %s' % maxs[-1][2]) @@ -475,13 +494,14 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): def test_simple_alarm_clear(self): self._set_all_alarms('alarm') maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] + v - for v in range(1, 5)]) - self.client.metric.aggregation.side_effect = [maxs] + for v in range(1, 5)], aggregated=True) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() self._assert_all_alarms('ok') expected = [mock.call(alarm) for alarm in self.alarms] update_calls = self.storage_conn.update_alarm.call_args_list self.assertEqual(expected, update_calls) + maxs = maxs['measures']['aggregated'] reason = ('Transition to ok due to 4 samples inside ' 'threshold, most recent: %s' % maxs[-1][2]) reason_data = self._reason_data('inside', 4, maxs[-1][2]) @@ -491,9 +511,13 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): def test_equivocal_from_known_state_ok(self): self._set_all_alarms('ok') - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] - v - for v in range(-1, 3)]) - self.client.metric.aggregation.side_effect = [maxs] + maxs = self._get_stats( + 300, + [self.alarms[0].rule['threshold'] - v + for v in range(-1, 3)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() self._assert_all_alarms('ok') self.assertEqual( @@ -505,18 +529,26 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): self._set_all_alarms('ok') # NOTE(sileht): we add one useless point (81.0) that will break # the test if the evaluator doesn't remove it. - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] - v - for v in range(-1, 5)]) - self.client.metric.aggregation.side_effect = [maxs] + maxs = self._get_stats( + 300, + [self.alarms[0].rule['threshold'] - v + for v in range(-1, 5)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() self._assert_all_alarms('alarm') def test_equivocal_from_known_state_and_repeat_actions(self): self._set_all_alarms('ok') self.alarms[0].repeat_actions = True - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] - v - for v in range(-1, 3)]) - self.client.metric.aggregation.side_effect = [maxs] + maxs = self._get_stats( + 300, + [self.alarms[0].rule['threshold'] - v + for v in range(-1, 3)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() self._assert_all_alarms('ok') self.assertEqual([], self.storage_conn.update_alarm.call_args_list) @@ -530,9 +562,12 @@ class TestGnocchiAggregationMetricsThresholdEvaluate(TestGnocchiEvaluatorBase): self._set_all_alarms('alarm') self.alarms[0].repeat_actions = True - maxs = self._get_stats(300, [self.alarms[0].rule['threshold'] - v - for v in range(4)]) - self.client.metric.aggregation.side_effect = [maxs] + maxs = self._get_stats( + 300, [self.alarms[0].rule['threshold'] - v + for v in range(4)], + aggregated=True + ) + self.client.aggregates.fetch.side_effect = [maxs] self._evaluate_all_alarms() self._assert_all_alarms('alarm') self.assertEqual([], self.storage_conn.update_alarm.call_args_list) @@ -553,13 +588,13 @@ class TestGnocchiAggregationResourcesThresholdEvaluate( def test_retry_transient_api_failure(self): avgs2 = self._get_stats(50, [self.alarms[0].rule['threshold'] - v - for v in range(6)]) - self.client.metric.aggregation.side_effect = [ + for v in range(6)], aggregated=True) + self.client.aggregates.fetch.side_effect = [ exceptions.ClientException(500, "error"), avgs2] self._test_retry_transient() def test_simple_insufficient(self): - self.client.metric.aggregation.return_value = [] + self.client.aggregates.fetch.return_value = [] self._test_simple_insufficient() @mock.patch.object(timeutils, 'utcnow') @@ -567,25 +602,30 @@ class TestGnocchiAggregationResourcesThresholdEvaluate( utcnow.return_value = datetime.datetime(2015, 1, 26, 12, 57, 0, 0) self._set_all_alarms('ok') avgs = self._get_stats(50, [self.alarms[0].rule['threshold'] + v - for v in range(1, 7)]) + for v in range(1, 7)], aggregated=True) - self.client.metric.aggregation.side_effect = [avgs] + self.client.aggregates.fetch.side_effect = [avgs] self._evaluate_all_alarms() start_alarm = "2015-01-26T12:51:10" end = "2015-01-26T12:57:00" self.assertEqual( - [mock.call.aggregation(aggregation='mean', metrics='cpu_util', - granularity=50, - needed_overlap=0, - query={"=": {"server_group": - "my_autoscaling_group"}}, - resource_type='instance', - start=start_alarm, stop=end)], - self.client.metric.mock_calls) + [mock.call.fetch( + operations=[ + 'aggregate', 'rate:mean', + ['metric', 'cpu', 'mean'], + ], + granularity=50, + search={"=": {"server_group": + "my_autoscaling_group"}}, + resource_type='instance', + start=start_alarm, stop=end, + needed_overlap=0)], + self.client.aggregates.mock_calls) self._assert_all_alarms('alarm') expected = [mock.call(alarm) for alarm in self.alarms] update_calls = self.storage_conn.update_alarm.call_args_list self.assertEqual(expected, update_calls) + avgs = avgs['measures']['aggregated'] reason = ('Transition to alarm due to 6 samples outside ' 'threshold, most recent: %s' % avgs[-1][2]) reason_data = self._reason_data('outside', 6, avgs[-1][2]) @@ -595,13 +635,14 @@ class TestGnocchiAggregationResourcesThresholdEvaluate( def test_simple_alarm_clear(self): self._set_all_alarms('alarm') avgs = self._get_stats(50, [self.alarms[0].rule['threshold'] - v - for v in range(6)]) - self.client.metric.aggregation.side_effect = [avgs] + for v in range(6)], aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs] self._evaluate_all_alarms() self._assert_all_alarms('ok') expected = [mock.call(alarm) for alarm in self.alarms] update_calls = self.storage_conn.update_alarm.call_args_list self.assertEqual(expected, update_calls) + avgs = avgs['measures']['aggregated'] reason = ('Transition to ok due to 6 samples inside ' 'threshold, most recent: %s' % avgs[-1][2]) reason_data = self._reason_data('inside', 6, avgs[-1][2]) @@ -611,8 +652,8 @@ class TestGnocchiAggregationResourcesThresholdEvaluate( def test_equivocal_from_known_state_ok(self): self._set_all_alarms('ok') avgs = self._get_stats(50, [self.alarms[0].rule['threshold'] + v - for v in range(6)]) - self.client.metric.aggregation.side_effect = [avgs] + for v in range(6)], aggregated=True) + self.client.aggregates.fetch.side_effect = [avgs] self._evaluate_all_alarms() self._assert_all_alarms('ok') self.assertEqual(