diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index 584dad7c6..747daa0b7 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -34,6 +34,7 @@ import ast import datetime import inspect +import uuid import pecan from pecan import rest @@ -1016,9 +1017,9 @@ class AlarmsController(rest.RestController): """Create a new alarm.""" conn = pecan.request.storage_conn + data.alarm_id = str(uuid.uuid4()) data.user_id = pecan.request.headers.get('X-User-Id') data.project_id = pecan.request.headers.get('X-Project-Id') - data.alarm_id = wsme.Unset data.state_timestamp = wsme.Unset data.timestamp = timeutils.utcnow() @@ -1039,7 +1040,7 @@ class AlarmsController(rest.RestController): pecan.response.translatable_error = error raise wsme.exc.ClientSideError(error) - alarm = conn.update_alarm(alarm_in) + alarm = conn.create_alarm(alarm_in) return Alarm.from_db_model(alarm) @wsme_pecan.wsexpose([Alarm], [Query]) diff --git a/ceilometer/storage/base.py b/ceilometer/storage/base.py index 1bda217b1..e6f24c0c8 100644 --- a/ceilometer/storage/base.py +++ b/ceilometer/storage/base.py @@ -188,6 +188,13 @@ class Connection(object): """Yields a lists of alarms that match filters """ + @abc.abstractmethod + def create_alarm(self, alarm): + """Create an alarm. Returns the alarm as created. + + :param alarm: The alarm to create. + """ + @abc.abstractmethod def update_alarm(self, alarm): """update alarm diff --git a/ceilometer/storage/impl_db2.py b/ceilometer/storage/impl_db2.py index e472d8619..d7462ada0 100644 --- a/ceilometer/storage/impl_db2.py +++ b/ceilometer/storage/impl_db2.py @@ -22,7 +22,6 @@ """ import copy -import uuid import weakref import bson.code @@ -595,9 +594,6 @@ class Connection(base.Connection): def update_alarm(self, alarm): """update alarm """ - if alarm.alarm_id is None: - # This is an insert, generate an id - alarm.alarm_id = str(uuid.uuid1()) data = alarm.as_dict() data['matching_metadata'] = \ self._encode_matching_metadata(data['matching_metadata']) @@ -613,6 +609,8 @@ class Connection(base.Connection): self._decode_matching_metadata(stored_alarm['matching_metadata']) return models.Alarm(**stored_alarm) + create_alarm = update_alarm + def delete_alarm(self, alarm_id): """Delete an alarm """ diff --git a/ceilometer/storage/impl_hbase.py b/ceilometer/storage/impl_hbase.py index d04fbd594..e69a1f128 100644 --- a/ceilometer/storage/impl_hbase.py +++ b/ceilometer/storage/impl_hbase.py @@ -599,6 +599,11 @@ class Connection(base.Connection): """ raise NotImplementedError('Alarms not implemented') + def create_alarm(self, alarm): + """update alarm + """ + raise NotImplementedError('Alarms not implemented') + def update_alarm(self, alarm): """update alarm """ diff --git a/ceilometer/storage/impl_log.py b/ceilometer/storage/impl_log.py index 6aa7aabc1..2ae0553b9 100644 --- a/ceilometer/storage/impl_log.py +++ b/ceilometer/storage/impl_log.py @@ -161,6 +161,11 @@ class Connection(base.Connection): """ return [] + def create_alarm(self, alarm): + """Create alarm. + """ + return alarm + def update_alarm(self, alarm): """update alarm """ diff --git a/ceilometer/storage/impl_mongodb.py b/ceilometer/storage/impl_mongodb.py index 442f25fa3..53119dd51 100644 --- a/ceilometer/storage/impl_mongodb.py +++ b/ceilometer/storage/impl_mongodb.py @@ -23,7 +23,6 @@ import calendar import copy import operator -import uuid import weakref import bson.code @@ -844,9 +843,6 @@ class Connection(base.Connection): def update_alarm(self, alarm): """update alarm """ - if alarm.alarm_id is None: - # This is an insert, generate an id - alarm.alarm_id = str(uuid.uuid1()) data = alarm.as_dict() data['matching_metadata'] = \ self._encode_matching_metadata(data['matching_metadata']) @@ -862,6 +858,8 @@ class Connection(base.Connection): self._decode_matching_metadata(stored_alarm['matching_metadata']) return models.Alarm(**stored_alarm) + create_alarm = update_alarm + def delete_alarm(self, alarm_id): """Delete a alarm """ diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py index cb79a9b43..526f29e8d 100644 --- a/ceilometer/storage/impl_sqlalchemy.py +++ b/ceilometer/storage/impl_sqlalchemy.py @@ -22,7 +22,6 @@ from __future__ import absolute_import import datetime import operator import os -import uuid from sqlalchemy import func from sqlalchemy import desc from sqlalchemy.orm import aliased @@ -571,13 +570,6 @@ class Connection(base.Connection): matching_metadata=row.matching_metadata, repeat_actions=row.repeat_actions) - @staticmethod - def _alarm_model_to_row(alarm, row=None): - if row is None: - row = Alarm(id=str(uuid.uuid1())) - row.update(alarm.as_dict()) - return row - def get_alarms(self, name=None, user=None, project=None, enabled=True, alarm_id=None, limit=None, marker_pairs=None, @@ -614,24 +606,33 @@ class Connection(base.Connection): return (self._row_to_alarm_model(x) for x in query.all()) + def create_alarm(self, alarm): + """Create an alarm. + + :param alarm: The alarm to create. + """ + session = sqlalchemy_session.get_session() + with session.begin(): + session.merge(User(id=alarm.user_id)) + session.merge(Project(id=alarm.project_id)) + alarm_row = Alarm(id=alarm.alarm_id) + alarm_row.update(alarm.as_dict()) + session.add(alarm_row) + session.flush() + + return self._row_to_alarm_model(alarm_row) + def update_alarm(self, alarm): - """update alarm + """Update an alarm. :param alarm: the new Alarm to update """ session = sqlalchemy_session.get_session() with session.begin(): - if alarm.alarm_id: - alarm_row = session.merge(Alarm(id=alarm.alarm_id)) - self._alarm_model_to_row(alarm, alarm_row) - else: - session.merge(User(id=alarm.user_id)) - session.merge(Project(id=alarm.project_id)) - - alarm_row = self._alarm_model_to_row(alarm) - session.add(alarm_row) - + alarm_row = session.merge(Alarm(id=alarm.alarm_id)) + alarm_row.update(alarm.as_dict()) session.flush() + return self._row_to_alarm_model(alarm_row) @staticmethod diff --git a/ceilometer/storage/models.py b/ceilometer/storage/models.py index 8d6cebd4d..c1a19879b 100644 --- a/ceilometer/storage/models.py +++ b/ceilometer/storage/models.py @@ -277,12 +277,11 @@ class Alarm(Model): :param repeat_actions: Is the actions should be triggered on each alarm evaluation. """ - def __init__(self, name, counter_name, + def __init__(self, alarm_id, name, counter_name, comparison_operator, threshold, statistic, user_id, project_id, evaluation_periods=1, period=60, - alarm_id=None, enabled=True, description='', timestamp=None, diff --git a/tests/api/v2/test_alarm_scenarios.py b/tests/api/v2/test_alarm_scenarios.py index e62167534..1a6597658 100644 --- a/tests/api/v2/test_alarm_scenarios.py +++ b/tests/api/v2/test_alarm_scenarios.py @@ -50,6 +50,7 @@ class TestAlarms(FunctionalTest, self.auth_headers = {'X-User-Id': str(uuid.uuid1()), 'X-Project-Id': str(uuid.uuid1())} for alarm in [Alarm(name='name1', + alarm_id='a', counter_name='meter.test', comparison_operator='gt', threshold=2.0, statistic='avg', @@ -57,12 +58,14 @@ class TestAlarms(FunctionalTest, user_id=self.auth_headers['X-User-Id'], project_id=self.auth_headers['X-Project-Id']), Alarm(name='name2', + alarm_id='b', counter_name='meter.mine', comparison_operator='gt', threshold=2.0, statistic='avg', user_id=self.auth_headers['X-User-Id'], project_id=self.auth_headers['X-Project-Id']), Alarm(name='name3', + alarm_id='c', counter_name='meter.test', comparison_operator='gt', threshold=2.0, statistic='avg', diff --git a/tests/storage/test_impl_mongodb.py b/tests/storage/test_impl_mongodb.py index 2ba5a3420..b4e083c1a 100644 --- a/tests/storage/test_impl_mongodb.py +++ b/tests/storage/test_impl_mongodb.py @@ -194,7 +194,7 @@ class CompatibilityTest(test_storage_scenarios.DBTestBase, # Create the old format alarm with a dict instead of a # array for matching_metadata - alarm = models.Alarm('old-alert', + alarm = models.Alarm('0ld-4l3rt', 'old-alert', 'test.one', 'eq', 36, 'count', 'me', 'and-da-boys', evaluation_periods=1, diff --git a/tests/storage/test_storage_scenarios.py b/tests/storage/test_storage_scenarios.py index a3d13185a..a48be4ba3 100644 --- a/tests/storage/test_storage_scenarios.py +++ b/tests/storage/test_storage_scenarios.py @@ -1495,20 +1495,20 @@ class CounterDataTypeTest(DBTestBase, class AlarmTestBase(DBTestBase): def add_some_alarms(self): - alarms = [models.Alarm('red-alert', + alarms = [models.Alarm('r3d', 'red-alert', 'test.one', 'eq', 36, 'count', 'me', 'and-da-boys', evaluation_periods=1, period=60, alarm_actions=['http://nowhere/alarms'], matching_metadata={'key': 'value'}), - models.Alarm('orange-alert', + models.Alarm('0r4ng3', 'orange-alert', 'test.fourty', 'gt', 75, 'avg', 'me', 'and-da-boys', period=60, alarm_actions=['http://nowhere/alarms'], matching_metadata={'key2': 'value2'}), - models.Alarm('yellow-alert', + models.Alarm('y3ll0w', 'yellow-alert', 'test.five', 'lt', 10, 'min', 'me', 'and-da-boys', alarm_actions=['http://nowhere/alarms'], @@ -1516,7 +1516,7 @@ class AlarmTestBase(DBTestBase): {'key2': 'value2', 'user_metadata.key3': 'value3'})] for a in alarms: - self.conn.update_alarm(a) + self.conn.create_alarm(a) class AlarmTest(AlarmTestBase, @@ -1561,7 +1561,7 @@ class AlarmTest(AlarmTestBase, {'new': 'value', 'user_metadata.new2': 'value4'}) def test_update_llu(self): - llu = models.Alarm('llu', + llu = models.Alarm('llu', 'llu', 'counter_name', 'lt', 34, 'max', 'bla', 'ffo') updated = self.conn.update_alarm(llu)