Files
monasca-api/monasca_api/tests/test_ad_repository.py
liyingjun f379d71fcb Use oslo.db for sqla driver
Use create_engine in oslo.db instead of the sqlalchemy one to get
the optimization benefit from oslo.db.

Breaking change would be replacing database.url with
database.connection therefore database.url will be still
supported until Pike is released. database.url
has been marked as deprecated option.

Change-Id: Id3cdafa791a7d2558a5b065022a9afc6ff31e004
Closes-bug: #1640419
2017-03-08 10:08:42 +01:00

844 lines
40 KiB
Python

# Copyright 2015 Cray
# Copyright 2016 FUJITSU LIMITED
# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import fixtures
from oslo_config import cfg
from oslo_config import fixture as fixture_config
from oslo_db.sqlalchemy.engines import create_engine
from sqlalchemy import delete, MetaData, insert, bindparam, select, func
import testtools
from monasca_api.common.repositories import exceptions
from monasca_api.common.repositories.model import sub_alarm_definition
from monasca_api.common.repositories.sqla import models
from monasca_api.expression_parser import alarm_expr_parser
CONF = cfg.CONF
ALARM_DEF_123_FIELDS = {'actions_enabled': False,
'alarm_actions': u'29387234,77778687',
'description': None,
'expression': u'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': u'123',
'match_by': u'flavor_id,image_id',
'name': u'90% CPU',
'ok_actions': None,
'severity': u'LOW',
'undetermined_actions': None}
TENANT_ID = 'bob'
class TestAlarmDefinitionRepoDB(testtools.TestCase, fixtures.TestWithFixtures):
@classmethod
def setUpClass(cls):
engine = create_engine('sqlite://')
qry = open('monasca_api/tests/sqlite_alarm.sql', 'r').read()
sconn = engine.raw_connection()
c = sconn.cursor()
c.executescript(qry)
sconn.commit()
c.close()
cls.engine = engine
def _fake_engine_from_config(*args, **kw):
return cls.engine
cls.fixture = fixtures.MonkeyPatch(
'sqlalchemy.create_engine', _fake_engine_from_config)
cls.fixture.setUp()
metadata = MetaData()
cls.aa = models.create_aa_model(metadata)
cls._delete_aa_query = delete(cls.aa)
cls._insert_aa_query = (insert(cls.aa)
.values(
alarm_definition_id=bindparam('alarm_definition_id'),
alarm_state=bindparam('alarm_state'),
action_id=bindparam('action_id')))
cls.ad = models.create_ad_model(metadata)
cls._delete_ad_query = delete(cls.ad)
cls._insert_ad_query = (insert(cls.ad)
.values(
id=bindparam('id'),
tenant_id=bindparam('tenant_id'),
name=bindparam('name'),
severity=bindparam('severity'),
expression=bindparam('expression'),
match_by=bindparam('match_by'),
actions_enabled=bindparam('actions_enabled'),
created_at=bindparam('created_at'),
updated_at=bindparam('updated_at'),
deleted_at=bindparam('deleted_at')))
cls.sad = models.create_sad_model(metadata)
cls._delete_sad_query = delete(cls.sad)
cls._insert_sad_query = (insert(cls.sad)
.values(
id=bindparam('id'),
alarm_definition_id=bindparam('alarm_definition_id'),
function=bindparam('function'),
metric_name=bindparam('metric_name'),
operator=bindparam('operator'),
threshold=bindparam('threshold'),
period=bindparam('period'),
periods=bindparam('periods'),
is_deterministic=bindparam('is_deterministic'),
created_at=bindparam('created_at'),
updated_at=bindparam('updated_at')))
cls.sadd = models.create_sadd_model(metadata)
cls._delete_sadd_query = delete(cls.sadd)
cls._insert_sadd_query = (insert(cls.sadd)
.values(
sub_alarm_definition_id=bindparam('sub_alarm_definition_id'),
dimension_name=bindparam('dimension_name'),
value=bindparam('value')))
cls.nm = models.create_nm_model(metadata)
cls._delete_nm_query = delete(cls.nm)
cls._insert_nm_query = (insert(cls.nm)
.values(
id=bindparam('id'),
tenant_id=bindparam('tenant_id'),
name=bindparam('name'),
type=bindparam('type'),
address=bindparam('address'),
created_at=bindparam('created_at'),
updated_at=bindparam('updated_at')))
@classmethod
def tearDownClass(cls):
cls.fixture.cleanUp()
def setUp(self):
super(TestAlarmDefinitionRepoDB, self).setUp()
self._fixture_config = self.useFixture(
fixture_config.Config(cfg.CONF))
self._fixture_config.config(connection='sqlite://',
group='database')
from monasca_api.common.repositories.sqla import alarm_definitions_repository as adr
self.repo = adr.AlarmDefinitionsRepository()
self.default_ads = [{'id': '123',
'tenant_id': 'bob',
'name': '90% CPU',
'severity': 'LOW',
'expression': 'AVG(hpcs.compute{flavor_id=777,'
' image_id=888, metric_name=cpu, device=1}) > 10',
'match_by': 'flavor_id,image_id',
'actions_enabled': False,
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now(),
'deleted_at': None},
{'id': '234',
'tenant_id': 'bob',
'name': '50% CPU',
'severity': 'LOW',
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20'
' and AVG(hpcs.compute) < 100',
'match_by': 'flavor_id,image_id',
'actions_enabled': False,
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now(),
'deleted_at': None}]
self.default_sads = [{'id': '111',
'alarm_definition_id': '123',
'function': 'AVG',
'metric_name': 'hpcs.compute',
'operator': 'GT',
'threshold': 10,
'period': 60,
'periods': 1,
'is_deterministic': False,
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()},
{'id': '222',
'alarm_definition_id': '234',
'function': 'AVG',
'metric_name': 'hpcs.compute',
'operator': 'GT',
'threshold': 20,
'period': 60,
'periods': 1,
'is_deterministic': False,
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()},
{'id': '223',
'alarm_definition_id': '234',
'function': 'AVG',
'metric_name': 'hpcs.compute',
'operator': 'LT',
'threshold': 100,
'period': 60,
'periods': 1,
'is_deterministic': False,
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()},
]
self.default_sadds = [{'sub_alarm_definition_id': '111',
'dimension_name': 'flavor_id',
'value': '777'},
{'sub_alarm_definition_id': '111',
'dimension_name': 'image_id',
'value': '888'},
{'sub_alarm_definition_id': '111',
'dimension_name': 'metric_name',
'value': 'cpu'},
{'sub_alarm_definition_id': '111',
'dimension_name': 'device',
'value': '1'},
{'sub_alarm_definition_id': '222',
'dimension_name': 'flavor_id',
'value': '777'},
{'sub_alarm_definition_id': '222',
'dimension_name': 'image_id',
'value': '888'},
{'sub_alarm_definition_id': '222',
'dimension_name': 'metric_name',
'value': 'mem'}]
self.default_nms = [{'id': '29387234',
'tenant_id': 'alarm-test',
'name': 'MyEmail',
'type': 'EMAIL',
'address': 'a@b',
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()},
{'id': '77778687',
'tenant_id': 'alarm-test',
'name': 'OtherEmail',
'type': 'EMAIL',
'address': 'a@b',
'created_at': datetime.datetime.now(),
'updated_at': datetime.datetime.now()}]
self.default_aas = [{'alarm_definition_id': '123',
'alarm_state': 'ALARM',
'action_id': '29387234'},
{'alarm_definition_id': '123',
'alarm_state': 'ALARM',
'action_id': '77778687'},
{'alarm_definition_id': '234',
'alarm_state': 'ALARM',
'action_id': '29387234'},
{'alarm_definition_id': '234',
'alarm_state': 'ALARM',
'action_id': '77778687'}]
with self.engine.begin() as conn:
conn.execute(self._delete_ad_query)
conn.execute(self._insert_ad_query, self.default_ads)
conn.execute(self._delete_sad_query)
conn.execute(self._insert_sad_query, self.default_sads)
conn.execute(self._delete_sadd_query)
conn.execute(self._insert_sadd_query, self.default_sadds)
conn.execute(self._delete_nm_query)
conn.execute(self._insert_nm_query, self.default_nms)
conn.execute(self._delete_aa_query)
conn.execute(self._insert_aa_query, self.default_aas)
def test_should_create(self):
expression = ('AVG(hpcs.compute{flavor_id=777, image_id=888,'
' metric_name=cpu}) > 10')
description = ''
match_by = ['flavor_id', 'image_id']
sub_expr_list = (alarm_expr_parser.AlarmExprParser(expression).sub_expr_list)
alarm_actions = ['29387234', '77778687']
alarmA_id = self.repo.create_alarm_definition('555',
'90% CPU',
expression,
sub_expr_list,
description,
'LOW',
match_by,
alarm_actions,
None,
None)
alarmB = self.repo.get_alarm_definition('555', alarmA_id)
self.assertEqual(alarmA_id, alarmB['id'])
query_sad = (select([self.sad.c.id])
.select_from(self.sad)
.where(self.sad.c.alarm_definition_id == alarmA_id))
query_sadd = (select([func.count()])
.select_from(self.sadd)
.where(self.sadd.c.sub_alarm_definition_id == bindparam('id')))
with self.engine.connect() as conn:
count_sad = conn.execute(query_sad).fetchall()
self.assertEqual(len(count_sad), 1)
count_sadd = conn.execute(query_sadd, id=count_sad[0][0]).fetchone()
self.assertEqual(count_sadd[0], 3)
def test_should_update(self):
expression = ''.join(['AVG(hpcs.compute{flavor_id=777, image_id=888,',
' metric_name=mem}) > 20 and',
' AVG(hpcs.compute) < 100'])
description = ''
match_by = ['flavor_id', 'image_id']
sub_expr_list = (alarm_expr_parser.AlarmExprParser(expression).sub_expr_list)
alarm_actions = ['29387234', '77778687']
self.repo.update_or_patch_alarm_definition('bob', '234',
'90% CPU', expression,
sub_expr_list, False,
description, alarm_actions,
None, None,
match_by, 'LOW')
alarm = self.repo.get_alarm_definition('bob', '234')
expected = {'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': '',
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 and'
' AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}
self.assertEqual(alarm, expected)
sub_alarms = self.repo.get_sub_alarm_definitions('234')
expected = [{'alarm_definition_id': '234',
'dimensions': 'flavor_id=777,image_id=888,'
'metric_name=mem',
'function': 'AVG',
'id': '222',
'metric_name': 'hpcs.compute',
'operator': 'GT',
'period': 60,
'periods': 1,
'is_deterministic': False,
'threshold': 20.0},
{'alarm_definition_id': '234',
'dimensions': None,
'function': 'AVG',
'id': '223',
'metric_name': 'hpcs.compute',
'operator': 'LT',
'period': 60,
'periods': 1,
'is_deterministic': False,
'threshold': 100.0}]
self.assertEqual(len(sub_alarms), len(expected))
for s, e in zip(sub_alarms, expected):
e['created_at'] = s['created_at']
e['updated_at'] = s['updated_at']
self.assertEqual(sub_alarms, expected)
am = self.repo.get_alarm_metrics('bob', '234')
self.assertEqual(am, [])
sub_alarms = self.repo.get_sub_alarms('bob', '234')
self.assertEqual(sub_alarms, [])
ads = self.repo.get_alarm_definitions('bob', '90% CPU', {'image_id': '888'}, None, None, 0, 100)
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None},
{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': '',
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 and'
' AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
self.assertEqual(ads, expected)
ads = self.repo.get_alarm_definitions('bob', '90% CPU', {'image_id': '888'}, 'LOW', None, 0, 100)
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None},
{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': '',
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 and'
' AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
self.assertEqual(ads, expected)
ads = self.repo.get_alarm_definitions('bob', '90% CPU', {'image_id': '888'}, 'CRITICAL', None, 0, 100)
expected = []
self.assertEqual(ads, expected)
self.repo.update_or_patch_alarm_definition('bob', '234',
'90% CPU', None,
sub_expr_list, False,
description, alarm_actions,
None, None,
match_by, 'LOW')
self.repo.update_or_patch_alarm_definition('bob', '234',
None, None,
None, True,
None, None,
None, None,
None, None,
True)
self.repo.update_or_patch_alarm_definition('bob', '234',
None, None,
None, None,
None, None,
None, None,
None, None,
True)
self.repo.update_or_patch_alarm_definition('bob', '234',
None, None,
None, None,
None, [],
[], [],
None, None,
True)
self.repo.update_or_patch_alarm_definition('bob', '234',
None, None,
None, False,
None, None,
None, None,
match_by, None,
False)
self.assertRaises(exceptions.InvalidUpdateException,
self.repo.update_or_patch_alarm_definition,
'bob', '234',
None, None,
None, False,
None, None,
None, None,
None, None,
False)
self.assertRaises(exceptions.InvalidUpdateException,
self.repo.update_or_patch_alarm_definition,
'bob', '234',
'90% CPU', None,
sub_expr_list, False,
description, alarm_actions,
None, None,
'update_match_by', 'LOW')
self.repo.delete_alarm_definition('bob', '234')
self.assertRaises(exceptions.DoesNotExistException,
self.repo.get_alarm_definition, 'bob', '234')
def test_should_find_by_id(self):
alarmDef1 = self.repo.get_alarm_definition('bob', '123')
expected = {'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}
self.assertEqual(alarmDef1, expected)
with self.engine.begin() as conn:
conn.execute(self._delete_aa_query)
alarmDef2 = self.repo.get_alarm_definition('bob', '123')
expected['alarm_actions'] = None
self.assertEqual(alarmDef2, expected)
def test_shoud_find_sub_alarm_metric_definitions(self):
sub_alarms = self.repo.get_sub_alarm_definitions('123')
expected = [{'alarm_definition_id': '123',
'dimensions': 'flavor_id=777,image_id=888,'
'metric_name=cpu,device=1',
'function': 'AVG',
'id': '111',
'metric_name': 'hpcs.compute',
'operator': 'GT',
'period': 60,
'periods': 1,
'is_deterministic': False,
'threshold': 10.0}]
self.assertEqual(len(sub_alarms), len(expected))
for s, e in zip(sub_alarms, expected):
e['created_at'] = s['created_at']
e['updated_at'] = s['updated_at']
self.assertEqual(sub_alarms, expected)
sub_alarms = self.repo.get_sub_alarm_definitions('234')
expected = [{'alarm_definition_id': '234',
'dimensions': 'flavor_id=777,image_id=888,metric_name=mem',
'function': 'AVG',
'id': '222',
'metric_name': 'hpcs.compute',
'operator': 'GT',
'period': 60,
'periods': 1,
'is_deterministic': False,
'threshold': 20.0},
{'alarm_definition_id': '234',
'dimensions': None,
'function': 'AVG',
'id': '223',
'metric_name': 'hpcs.compute',
'operator': 'LT',
'period': 60,
'periods': 1,
'is_deterministic': False,
'threshold': 100.0}]
self.assertEqual(len(sub_alarms), len(expected))
for s, e in zip(sub_alarms, expected):
e['created_at'] = s['created_at']
e['updated_at'] = s['updated_at']
self.assertEqual(sub_alarms, expected)
sub_alarms = self.repo.get_sub_alarm_definitions('asdfasdf')
self.assertEqual(sub_alarms, [])
def test_exists(self):
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
name='90% CPU')
expected = {'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}
self.assertEqual(alarmDef1, [expected])
alarmDef2 = self.repo.get_alarm_definitions(tenant_id='bob',
name='999% CPU')
self.assertEqual(alarmDef2, [])
def test_should_find(self):
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
limit=1)
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None},
{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 and '
'AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '50% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
self.assertEqual(alarmDef1, expected)
with self.engine.begin() as conn:
conn.execute(self._delete_aa_query)
alarmDef2 = self.repo.get_alarm_definitions(tenant_id='bob',
limit=1)
expected[0]['alarm_actions'] = None
expected[1]['alarm_actions'] = None
self.assertEqual(alarmDef2, expected)
alarmDef3 = self.repo.get_alarm_definitions(tenant_id='bill',
limit=1)
self.assertEqual(alarmDef3, [])
alarmDef3 = self.repo.get_alarm_definitions(tenant_id='bill',
offset='10',
limit=1)
self.assertEqual(alarmDef3, [])
def test_should_find_by_dimension(self):
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777,'
' image_id=888, metric_name=mem}) > 20 '
'and AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '50% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
dimensions = {'image_id': '888', 'metric_name': 'mem'}
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
dimensions=dimensions,
limit=1)
self.assertEqual(alarmDef1, expected)
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None},
{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 and '
'AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '50% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
dimensions = {'image_id': '888'}
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
dimensions=dimensions,
limit=1)
self.assertEqual(alarmDef1, expected)
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=cpu, device=1}) > 10',
'id': '123',
'match_by': 'flavor_id,image_id',
'name': '90% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
dimensions = {'device': '1'}
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
dimensions=dimensions,
limit=1)
self.assertEqual(alarmDef1, expected)
dimensions = {'Not real': 'AA'}
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
dimensions=dimensions,
limit=1)
self.assertEqual(alarmDef1, [])
def test_should_delete_by_id(self):
self.repo.delete_alarm_definition('bob', '123')
from monasca_api.common.repositories import exceptions
self.assertRaises(exceptions.DoesNotExistException,
self.repo.get_alarm_definition,
'bob',
'123')
expected = [{'actions_enabled': False,
'alarm_actions': '29387234,77778687',
'description': None,
'expression': 'AVG(hpcs.compute{flavor_id=777, '
'image_id=888, metric_name=mem}) > 20 '
'and AVG(hpcs.compute) < 100',
'id': '234',
'match_by': 'flavor_id,image_id',
'name': '50% CPU',
'ok_actions': None,
'severity': 'LOW',
'undetermined_actions': None}]
alarmDef1 = self.repo.get_alarm_definitions(tenant_id='bob',
limit=1)
self.assertEqual(alarmDef1, expected)
def test_should_patch_name(self):
self.run_patch_test(name=u'90% CPU New')
def test_should_patch_description(self):
self.run_patch_test(description=u'New Description')
def test_should_patch_severity(self):
self.run_patch_test(severity=u'CRITICAL')
def test_should_patch_actions_enabled(self):
self.run_patch_test(actions_enabled=False)
def test_should_patch_ok_actions(self):
self.run_patch_test(ok_actions=[u'29387234'])
def test_should_patch_alarm_actions(self):
self.run_patch_test(alarm_actions=[u'29387234'])
def test_should_patch_undetermined_actions(self):
self.run_patch_test(undetermined_actions=[u'29387234', u'77778687'])
def test_should_patch_match_by(self):
# match_by can't change, so make sure old value works
self.run_patch_test(match_by=[u'flavor_id', u'image_id'])
def test_should_patch_expression_no_change(self):
# match_by can't change, so make sure old value works
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'])
def test_should_patch_expression_threshold_change(self):
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'].replace(' 10', ' 20'))
def test_should_patch_expression_function_change(self):
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'].replace('AVG', 'MAX'))
def test_should_patch_expression_operation_change(self):
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'].replace('>', '<'))
def test_should_patch_expression_period_change(self):
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'].replace(')', ', 120)'))
def test_should_patch_expression_periods_change(self):
self.run_patch_test(expression=ALARM_DEF_123_FIELDS['expression'].replace(' 10', ' 10 times 2'))
def test_patch_fails_change_match_by(self):
self.assertRaises(exceptions.InvalidUpdateException, self.run_patch_test, match_by=u'device')
def test_patch_fails_change_metric_name(self):
self.assertRaises(exceptions.InvalidUpdateException, self.run_patch_test,
expression=ALARM_DEF_123_FIELDS['expression'].replace('hpcs.compute',
'new_metric_name'))
def test_patch_fails_change_metric_dimensions(self):
self.assertRaises(exceptions.InvalidUpdateException, self.run_patch_test,
expression=ALARM_DEF_123_FIELDS['expression'].replace('image_id=888',
'image_id=42'))
def test_patch_fails_change_num_sub_expressions(self):
self.assertRaises(exceptions.InvalidUpdateException, self.run_patch_test,
expression=ALARM_DEF_123_FIELDS['expression']
.replace(' 10', ' 10 and MAX(cpu.idle_perc) < 10'))
def run_patch_test(self, name=None, expression=None, description=None, actions_enabled=None,
alarm_actions=None, ok_actions=None, undetermined_actions=None,
match_by=None, severity=None):
if expression:
sub_expr_list = (alarm_expr_parser.AlarmExprParser(expression).sub_expr_list)
else:
sub_expr_list = None
updates = self.repo.update_or_patch_alarm_definition(TENANT_ID, '123',
name, expression,
sub_expr_list, actions_enabled,
description, alarm_actions,
ok_actions, undetermined_actions,
match_by, severity,
patch=True)
alarm_def_row = (ALARM_DEF_123_FIELDS['id'],
name if name else ALARM_DEF_123_FIELDS['name'],
description if description else ALARM_DEF_123_FIELDS['description'],
expression if expression else ALARM_DEF_123_FIELDS['expression'],
ALARM_DEF_123_FIELDS['match_by'], # match-by can't change
severity if severity else ALARM_DEF_123_FIELDS['severity'],
actions_enabled if actions_enabled else ALARM_DEF_123_FIELDS['actions_enabled'],
u','.join(alarm_actions) if alarm_actions else ALARM_DEF_123_FIELDS['alarm_actions'],
u','.join(ok_actions) if ok_actions else ALARM_DEF_123_FIELDS['ok_actions'],
(u','.join(undetermined_actions) if undetermined_actions else
ALARM_DEF_123_FIELDS['undetermined_actions']))
sad = self.default_sads[0]
if expression and ALARM_DEF_123_FIELDS['expression'] != expression:
sub_expr = sub_expr_list[0]
sub_alarm_def = sub_alarm_definition.SubAlarmDefinition(
row={'id': '',
'alarm_definition_id': sad['alarm_definition_id'],
'function': sub_expr.normalized_func,
'metric_name': sub_expr.metric_name,
'dimensions': u'device=1,image_id=888,flavor_id=777,metric_name=cpu',
'operator': sub_expr.normalized_operator,
'threshold': sub_expr.threshold,
'period': sub_expr.period,
'is_deterministic': sub_expr.deterministic,
'periods': sub_expr.periods})
expected_sub_alarm_maps = {'changed': {u'111': sub_alarm_def}, 'new': {}, 'old': {}, 'unchanged': {}}
else:
sub_alarm_def = sub_alarm_definition.SubAlarmDefinition(
row={'id': sad['id'],
'alarm_definition_id': sad['alarm_definition_id'],
'function': sad['function'],
'metric_name': sad['metric_name'],
'dimensions': u'device=1,image_id=888,flavor_id=777,metric_name=cpu',
'operator': sad['operator'],
'threshold': sad['threshold'],
'period': sad['period'],
'is_deterministic': sad['is_deterministic'],
'periods': sad['periods']})
expected_sub_alarm_maps = {'changed': {}, 'new': {}, 'old': {}, 'unchanged': {u'111': sub_alarm_def}}
self.assertEqual((alarm_def_row, expected_sub_alarm_maps), updates)