diff --git a/ceilometer/alarm/rpc.py b/ceilometer/alarm/rpc.py index 78271e56..2f876b0c 100644 --- a/ceilometer/alarm/rpc.py +++ b/ceilometer/alarm/rpc.py @@ -18,11 +18,11 @@ from oslo.config import cfg import six +from ceilometer.alarm.storage import models from ceilometer import messaging from ceilometer.openstack.common import context from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common import log -from ceilometer.storage import models OPTS = [ cfg.StrOpt('notifier_rpc_topic', diff --git a/ceilometer/alarm/storage/__init__.py b/ceilometer/alarm/storage/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ceilometer/alarm/storage/models.py b/ceilometer/alarm/storage/models.py new file mode 100644 index 00000000..de701846 --- /dev/null +++ b/ceilometer/alarm/storage/models.py @@ -0,0 +1,122 @@ +# +# Copyright 2013 New Dream Network, LLC (DreamHost) +# +# Author: Doug Hellmann +# +# 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. +"""Model classes for use in the storage API. +""" + +from ceilometer.storage import base + + +class Alarm(base.Model): + ALARM_INSUFFICIENT_DATA = 'insufficient data' + ALARM_OK = 'ok' + ALARM_ALARM = 'alarm' + + ALARM_ACTIONS_MAP = { + ALARM_INSUFFICIENT_DATA: 'insufficient_data_actions', + ALARM_OK: 'ok_actions', + ALARM_ALARM: 'alarm_actions', + } + + """ + An alarm to monitor. + + :param alarm_id: UUID of the alarm + :param type: type of the alarm + :param name: The Alarm name + :param description: User friendly description of the alarm + :param enabled: Is the alarm enabled + :param state: Alarm state (ok/alarm/insufficient data) + :param rule: A rule that defines when the alarm fires + :param user_id: the owner/creator of the alarm + :param project_id: the project_id of the creator + :param evaluation_periods: the number of periods + :param period: the time period in seconds + :param time_constraints: the list of the alarm's time constraints, if any + :param timestamp: the timestamp when the alarm was last updated + :param state_timestamp: the timestamp of the last state change + :param ok_actions: the list of webhooks to call when entering the ok state + :param alarm_actions: the list of webhooks to call when entering the + alarm state + :param insufficient_data_actions: the list of webhooks to call when + entering the insufficient data state + :param repeat_actions: Is the actions should be triggered on each + alarm evaluation. + """ + def __init__(self, alarm_id, type, enabled, name, description, + timestamp, user_id, project_id, state, state_timestamp, + ok_actions, alarm_actions, insufficient_data_actions, + repeat_actions, rule, time_constraints): + base.Model.__init__( + self, + alarm_id=alarm_id, + type=type, + enabled=enabled, + name=name, + description=description, + timestamp=timestamp, + user_id=user_id, + project_id=project_id, + state=state, + state_timestamp=state_timestamp, + ok_actions=ok_actions, + alarm_actions=alarm_actions, + insufficient_data_actions= + insufficient_data_actions, + repeat_actions=repeat_actions, + rule=rule, + time_constraints=time_constraints) + + +class AlarmChange(base.Model): + """Record of an alarm change. + + :param event_id: UUID of the change event + :param alarm_id: UUID of the alarm + :param type: The type of change + :param detail: JSON fragment describing change + :param user_id: the user ID of the initiating identity + :param project_id: the project ID of the initiating identity + :param on_behalf_of: the tenant on behalf of which the change + is being made + :param timestamp: the timestamp of the change + """ + + CREATION = 'creation' + RULE_CHANGE = 'rule change' + STATE_TRANSITION = 'state transition' + DELETION = 'deletion' + + def __init__(self, + event_id, + alarm_id, + type, + detail, + user_id, + project_id, + on_behalf_of, + timestamp=None + ): + base.Model.__init__( + self, + event_id=event_id, + alarm_id=alarm_id, + type=type, + detail=detail, + user_id=user_id, + project_id=project_id, + on_behalf_of=on_behalf_of, + timestamp=timestamp) diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index 962ff6e9..dae14b8d 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -44,6 +44,7 @@ import wsme from wsme import types as wtypes import wsmeext.pecan as wsme_pecan +from ceilometer.alarm.storage import models as alarm_models from ceilometer.api import acl from ceilometer import messaging from ceilometer.openstack.common import context @@ -1894,7 +1895,7 @@ class AlarmController(rest.RestController): def _record_change(self, data, now, on_behalf_of=None, type=None): if not cfg.CONF.alarm.record_history: return - type = type or storage.models.AlarmChange.RULE_CHANGE + type = type or alarm_models.AlarmChange.RULE_CHANGE scrubbed_data = utils.stringify_timestamps(data) detail = json.dumps(scrubbed_data) user_id = pecan.request.headers.get('X-User-Id') @@ -1967,10 +1968,10 @@ class AlarmController(rest.RestController): raise ClientSideError(_('Cannot specify alarm %s itself in ' 'combination rule') % self._id) - old_alarm = Alarm.from_db_model(alarm_in).as_dict(storage.models.Alarm) - updated_alarm = data.as_dict(storage.models.Alarm) + old_alarm = Alarm.from_db_model(alarm_in).as_dict(alarm_models.Alarm) + updated_alarm = data.as_dict(alarm_models.Alarm) try: - alarm_in = storage.models.Alarm(**updated_alarm) + alarm_in = alarm_models.Alarm(**updated_alarm) except Exception: LOG.exception(_("Error while putting alarm: %s") % updated_alarm) raise ClientSideError(_("Alarm incorrect")) @@ -1990,10 +1991,10 @@ class AlarmController(rest.RestController): # ensure alarm exists before deleting alarm = self._alarm() self.conn.delete_alarm(alarm.alarm_id) - change = Alarm.from_db_model(alarm).as_dict(storage.models.Alarm) + change = Alarm.from_db_model(alarm).as_dict(alarm_models.Alarm) self._record_change(change, timeutils.utcnow(), - type=storage.models.AlarmChange.DELETION) + type=alarm_models.AlarmChange.DELETION) # TODO(eglynn): add pagination marker to signature once overall # API support for pagination is finalized @@ -2033,7 +2034,7 @@ class AlarmController(rest.RestController): alarm = self.conn.update_alarm(alarm) change = {'state': alarm.state} self._record_change(change, now, on_behalf_of=alarm.project_id, - type=storage.models.AlarmChange.STATE_TRANSITION) + type=alarm_models.AlarmChange.STATE_TRANSITION) return alarm.state @wsme_pecan.wsexpose(state_kind_enum) @@ -2055,7 +2056,7 @@ class AlarmsController(rest.RestController): def _record_creation(self, conn, data, alarm_id, now): if not cfg.CONF.alarm.record_history: return - type = storage.models.AlarmChange.CREATION + type = alarm_models.AlarmChange.CREATION scrubbed_data = utils.stringify_timestamps(data) detail = json.dumps(scrubbed_data) user_id = pecan.request.headers.get('X-User-Id') @@ -2109,7 +2110,7 @@ class AlarmsController(rest.RestController): data.timestamp = now data.state_timestamp = now - change = data.as_dict(storage.models.Alarm) + change = data.as_dict(alarm_models.Alarm) # make sure alarms are unique by name per project. alarms = list(conn.get_alarms(name=data.name, @@ -2120,7 +2121,7 @@ class AlarmsController(rest.RestController): status_code=409) try: - alarm_in = storage.models.Alarm(**change) + alarm_in = alarm_models.Alarm(**change) except Exception: LOG.exception(_("Error while posting alarm: %s") % change) raise ClientSideError(_("Alarm incorrect")) @@ -2412,7 +2413,7 @@ class QueryAlarmHistoryController(rest.RestController): :param body: Query rules for the alarm history to be returned. """ query = ValidatedComplexQuery(body, - storage.models.AlarmChange) + alarm_models.AlarmChange) query.validate(visibility_field="on_behalf_of") conn = pecan.request.storage_conn return [AlarmChange.from_db_model(s) @@ -2433,7 +2434,7 @@ class QueryAlarmsController(rest.RestController): :param body: Query rules for the alarms to be returned. """ query = ValidatedComplexQuery(body, - storage.models.Alarm) + alarm_models.Alarm) query.validate(visibility_field="project_id") conn = pecan.request.storage_conn return [Alarm.from_db_model(s) diff --git a/ceilometer/storage/base.py b/ceilometer/storage/base.py index 4e79d6b7..0f11aa2f 100644 --- a/ceilometer/storage/base.py +++ b/ceilometer/storage/base.py @@ -18,6 +18,7 @@ """ import datetime +import inspect import math from six import moves @@ -102,6 +103,35 @@ class Pagination(object): self.sort_dirs = sort_dirs or [] +class Model(object): + """Base class for storage API models. + """ + + def __init__(self, **kwds): + self.fields = list(kwds) + for k, v in kwds.iteritems(): + setattr(self, k, v) + + def as_dict(self): + d = {} + for f in self.fields: + v = getattr(self, f) + if isinstance(v, Model): + v = v.as_dict() + elif isinstance(v, list) and v and isinstance(v[0], Model): + v = [sub.as_dict() for sub in v] + d[f] = v + return d + + def __eq__(self, other): + return self.as_dict() == other.as_dict() + + @classmethod + def get_field_names(cls): + fields = inspect.getargspec(cls.__init__)[0] + return set(fields) - set(["self"]) + + class Connection(object): """Base class for storage system connections.""" diff --git a/ceilometer/storage/impl_hbase.py b/ceilometer/storage/impl_hbase.py index b856a2bd..717916a6 100644 --- a/ceilometer/storage/impl_hbase.py +++ b/ceilometer/storage/impl_hbase.py @@ -31,6 +31,7 @@ import time import bson.json_util import happybase +from ceilometer.alarm.storage import models as alarm_models from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common import log from ceilometer.openstack.common import network_utils @@ -263,7 +264,7 @@ class Connection(base.Connection): alarm_table = conn.table(self.ALARM_TABLE) alarm_table.put(_id, alarm_to_store) stored_alarm = deserialize_entry(alarm_table.row(_id))[0] - return models.Alarm(**stored_alarm) + return alarm_models.Alarm(**stored_alarm) create_alarm = update_alarm @@ -288,7 +289,7 @@ class Connection(base.Connection): gen = alarm_table.scan(filter=q) for ignored, data in gen: stored_alarm = deserialize_entry(data)[0] - yield models.Alarm(**stored_alarm) + yield alarm_models.Alarm(**stored_alarm) def get_alarm_changes(self, alarm_id, on_behalf_of, user=None, project=None, type=None, @@ -307,7 +308,7 @@ class Connection(base.Connection): row_stop=end_row) for ignored, data in gen: stored_entry = deserialize_entry(data)[0] - yield models.AlarmChange(**stored_entry) + yield alarm_models.AlarmChange(**stored_entry) def record_alarm_change(self, alarm_change): """Record alarm change event. diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py index 3cce1ec6..2f4a0892 100644 --- a/ceilometer/storage/impl_sqlalchemy.py +++ b/ceilometer/storage/impl_sqlalchemy.py @@ -32,6 +32,7 @@ from sqlalchemy import not_ from sqlalchemy import or_ from sqlalchemy.orm import aliased +from ceilometer.alarm.storage import models as alarm_api_models from ceilometer.openstack.common.db import exception as dbexc from ceilometer.openstack.common.db.sqlalchemy import migration import ceilometer.openstack.common.db.sqlalchemy.session as sqlalchemy_session @@ -664,23 +665,23 @@ class Connection(base.Connection): @staticmethod def _row_to_alarm_model(row): - return api_models.Alarm(alarm_id=row.alarm_id, - enabled=row.enabled, - type=row.type, - name=row.name, - description=row.description, - timestamp=row.timestamp, - user_id=row.user_id, - project_id=row.project_id, - state=row.state, - state_timestamp=row.state_timestamp, - ok_actions=row.ok_actions, - alarm_actions=row.alarm_actions, - insufficient_data_actions= - row.insufficient_data_actions, - rule=row.rule, - time_constraints=row.time_constraints, - repeat_actions=row.repeat_actions) + return alarm_api_models.Alarm(alarm_id=row.alarm_id, + enabled=row.enabled, + type=row.type, + name=row.name, + description=row.description, + timestamp=row.timestamp, + user_id=row.user_id, + project_id=row.project_id, + state=row.state, + state_timestamp=row.state_timestamp, + ok_actions=row.ok_actions, + alarm_actions=row.alarm_actions, + insufficient_data_actions= + row.insufficient_data_actions, + rule=row.rule, + time_constraints=row.time_constraints, + repeat_actions=row.repeat_actions) def _retrieve_alarms(self, query): return (self._row_to_alarm_model(x) for x in query.all()) @@ -762,14 +763,14 @@ class Connection(base.Connection): @staticmethod def _row_to_alarm_change_model(row): - return api_models.AlarmChange(event_id=row.event_id, - alarm_id=row.alarm_id, - type=row.type, - detail=row.detail, - user_id=row.user_id, - project_id=row.project_id, - on_behalf_of=row.on_behalf_of, - timestamp=row.timestamp) + return alarm_api_models.AlarmChange(event_id=row.event_id, + alarm_id=row.alarm_id, + type=row.type, + detail=row.detail, + user_id=row.user_id, + project_id=row.project_id, + on_behalf_of=row.on_behalf_of, + timestamp=row.timestamp) def query_alarms(self, filter_expr=None, orderby=None, limit=None): """Yields a lists of alarms that match filter diff --git a/ceilometer/storage/models.py b/ceilometer/storage/models.py index 99d3c373..f61b83f7 100644 --- a/ceilometer/storage/models.py +++ b/ceilometer/storage/models.py @@ -16,41 +16,12 @@ # under the License. """Model classes for use in the storage API. """ -import inspect from ceilometer.openstack.common import timeutils +from ceilometer.storage import base -class Model(object): - """Base class for storage API models. - """ - - def __init__(self, **kwds): - self.fields = list(kwds) - for k, v in kwds.iteritems(): - setattr(self, k, v) - - def as_dict(self): - d = {} - for f in self.fields: - v = getattr(self, f) - if isinstance(v, Model): - v = v.as_dict() - elif isinstance(v, list) and v and isinstance(v[0], Model): - v = [sub.as_dict() for sub in v] - d[f] = v - return d - - def __eq__(self, other): - return self.as_dict() == other.as_dict() - - @classmethod - def get_field_names(cls): - fields = inspect.getargspec(cls.__init__)[0] - return set(fields) - set(["self"]) - - -class Event(Model): +class Event(base.Model): """A raw event from the source system. Events have Traits. Metrics will be derived from one or more Events. @@ -70,8 +41,8 @@ class Event(Model): :param generated: UTC time for when the event occurred. :param traits: list of Traits on this Event. """ - Model.__init__(self, message_id=message_id, event_type=event_type, - generated=generated, traits=traits) + base.Model.__init__(self, message_id=message_id, event_type=event_type, + generated=generated, traits=traits) def append_trait(self, trait_model): self.traits.append(trait_model) @@ -85,7 +56,7 @@ class Event(Model): " ".join(trait_list)) -class Trait(Model): +class Trait(base.Model): """A Trait is a key/value pair of data on an Event. The value is variant record of basic data types (int, date, float, etc). """ @@ -107,7 +78,7 @@ class Trait(Model): def __init__(self, name, dtype, value): if not dtype: dtype = Trait.NONE_TYPE - Model.__init__(self, name=name, dtype=dtype, value=value) + base.Model.__init__(self, name=name, dtype=dtype, value=value) def __repr__(self): return "" % (self.name, self.dtype, self.value) @@ -138,7 +109,7 @@ class Trait(Model): return str(value) -class Resource(Model): +class Resource(base.Model): """Something for which sample data has been collected. """ @@ -156,18 +127,18 @@ class Resource(Model): :param user_id: UUID of user owning the resource :param metadata: most current metadata for the resource (a dict) """ - Model.__init__(self, - resource_id=resource_id, - first_sample_timestamp=first_sample_timestamp, - last_sample_timestamp=last_sample_timestamp, - project_id=project_id, - source=source, - user_id=user_id, - metadata=metadata, - ) + base.Model.__init__(self, + resource_id=resource_id, + first_sample_timestamp=first_sample_timestamp, + last_sample_timestamp=last_sample_timestamp, + project_id=project_id, + source=source, + user_id=user_id, + metadata=metadata, + ) -class Meter(Model): +class Meter(base.Model): """Definition of a meter for which sample data has been collected. """ @@ -183,18 +154,18 @@ class Meter(Model): :param source: the identifier for the user/project id definition :param user_id: UUID of user owning the resource """ - Model.__init__(self, - name=name, - type=type, - unit=unit, - resource_id=resource_id, - project_id=project_id, - source=source, - user_id=user_id, - ) + base.Model.__init__(self, + name=name, + type=type, + unit=unit, + resource_id=resource_id, + project_id=project_id, + source=source, + user_id=user_id, + ) -class Sample(Model): +class Sample(base.Model): """One collected data point. """ def __init__(self, @@ -221,25 +192,25 @@ class Sample(Model): :param message_id: a message identifier :param recorded_at: sample record timestamp :param message_signature: a hash created from the rest of the - message data + message data """ - Model.__init__(self, - source=source, - counter_name=counter_name, - counter_type=counter_type, - counter_unit=counter_unit, - counter_volume=counter_volume, - user_id=user_id, - project_id=project_id, - resource_id=resource_id, - timestamp=timestamp, - resource_metadata=resource_metadata, - message_id=message_id, - message_signature=message_signature, - recorded_at=recorded_at) + base.Model.__init__(self, + source=source, + counter_name=counter_name, + counter_type=counter_type, + counter_unit=counter_unit, + counter_volume=counter_volume, + user_id=user_id, + project_id=project_id, + resource_id=resource_id, + timestamp=timestamp, + resource_metadata=resource_metadata, + message_id=message_id, + message_signature=message_signature, + recorded_at=recorded_at) -class Statistics(Model): +class Statistics(base.Model): """Computed statistics based on a set of sample data. """ def __init__(self, unit, @@ -264,112 +235,10 @@ class Statistics(Model): count: The number of samples found aggregate: name-value pairs for selectable aggregates """ - Model.__init__(self, unit=unit, - period=period, period_start=period_start, - period_end=period_end, duration=duration, - duration_start=duration_start, - duration_end=duration_end, - groupby=groupby, - **data) - - -class Alarm(Model): - ALARM_INSUFFICIENT_DATA = 'insufficient data' - ALARM_OK = 'ok' - ALARM_ALARM = 'alarm' - - ALARM_ACTIONS_MAP = { - ALARM_INSUFFICIENT_DATA: 'insufficient_data_actions', - ALARM_OK: 'ok_actions', - ALARM_ALARM: 'alarm_actions', - } - - """ - An alarm to monitor. - - :param alarm_id: UUID of the alarm - :param type: type of the alarm - :param name: The Alarm name - :param description: User friendly description of the alarm - :param enabled: Is the alarm enabled - :param state: Alarm state (ok/alarm/insufficient data) - :param rule: A rule that defines when the alarm fires - :param user_id: the owner/creator of the alarm - :param project_id: the project_id of the creator - :param evaluation_periods: the number of periods - :param period: the time period in seconds - :param time_constraints: the list of the alarm's time constraints, if any - :param timestamp: the timestamp when the alarm was last updated - :param state_timestamp: the timestamp of the last state change - :param ok_actions: the list of webhooks to call when entering the ok state - :param alarm_actions: the list of webhooks to call when entering the - alarm state - :param insufficient_data_actions: the list of webhooks to call when - entering the insufficient data state - :param repeat_actions: Is the actions should be triggered on each - alarm evaluation. - """ - def __init__(self, alarm_id, type, enabled, name, description, - timestamp, user_id, project_id, state, state_timestamp, - ok_actions, alarm_actions, insufficient_data_actions, - repeat_actions, rule, time_constraints): - Model.__init__( - self, - alarm_id=alarm_id, - type=type, - enabled=enabled, - name=name, - description=description, - timestamp=timestamp, - user_id=user_id, - project_id=project_id, - state=state, - state_timestamp=state_timestamp, - ok_actions=ok_actions, - alarm_actions=alarm_actions, - insufficient_data_actions= - insufficient_data_actions, - repeat_actions=repeat_actions, - rule=rule, - time_constraints=time_constraints) - - -class AlarmChange(Model): - """Record of an alarm change. - - :param event_id: UUID of the change event - :param alarm_id: UUID of the alarm - :param type: The type of change - :param detail: JSON fragment describing change - :param user_id: the user ID of the initiating identity - :param project_id: the project ID of the initiating identity - :param on_behalf_of: the tenant on behalf of which the change - is being made - :param timestamp: the timestamp of the change - """ - - CREATION = 'creation' - RULE_CHANGE = 'rule change' - STATE_TRANSITION = 'state transition' - DELETION = 'deletion' - - def __init__(self, - event_id, - alarm_id, - type, - detail, - user_id, - project_id, - on_behalf_of, - timestamp=None - ): - Model.__init__( - self, - event_id=event_id, - alarm_id=alarm_id, - type=type, - detail=detail, - user_id=user_id, - project_id=project_id, - on_behalf_of=on_behalf_of, - timestamp=timestamp) + base.Model.__init__(self, unit=unit, + period=period, period_start=period_start, + period_end=period_end, duration=duration, + duration_start=duration_start, + duration_end=duration_end, + groupby=groupby, + **data) diff --git a/ceilometer/storage/pymongo_base.py b/ceilometer/storage/pymongo_base.py index 3ae08c0a..e1b579bb 100644 --- a/ceilometer/storage/pymongo_base.py +++ b/ceilometer/storage/pymongo_base.py @@ -24,6 +24,7 @@ from oslo.config import cfg import pymongo import weakref +from ceilometer.alarm.storage import models as alarm_models from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common import log from ceilometer.openstack.common import network_utils @@ -240,7 +241,7 @@ class Connection(base.Connection): del stored_alarm['_id'] self._ensure_encapsulated_rule_format(stored_alarm) self._ensure_time_constraints(stored_alarm) - return models.Alarm(**stored_alarm) + return alarm_models.Alarm(**stored_alarm) create_alarm = update_alarm @@ -357,7 +358,8 @@ class Connection(base.Connection): def query_alarms(self, filter_expr=None, orderby=None, limit=None): """Return an iterable of model.Alarm objects. """ - return self._retrieve_data(filter_expr, orderby, limit, models.Alarm) + return self._retrieve_data(filter_expr, orderby, limit, + alarm_models.Alarm) def query_alarm_history(self, filter_expr=None, orderby=None, limit=None): """Return an iterable of model.AlarmChange objects. @@ -365,7 +367,7 @@ class Connection(base.Connection): return self._retrieve_data(filter_expr, orderby, limit, - models.AlarmChange) + alarm_models.AlarmChange) def _retrieve_data(self, filter_expr, orderby, limit, model): if limit == 0: @@ -379,8 +381,8 @@ class Connection(base.Connection): query_filter = transformer.transform_filter(filter_expr) retrieve = {models.Meter: self._retrieve_samples, - models.Alarm: self._retrieve_alarms, - models.AlarmChange: self._retrieve_alarm_changes} + alarm_models.Alarm: self._retrieve_alarms, + alarm_models.AlarmChange: self._retrieve_alarm_changes} return retrieve[model](query_filter, orderby_filter, limit) def _retrieve_samples(self, query, orderby, limit): @@ -417,7 +419,7 @@ class Connection(base.Connection): del a['_id'] self._ensure_encapsulated_rule_format(a) self._ensure_time_constraints(a) - yield models.Alarm(**a) + yield alarm_models.Alarm(**a) def _retrieve_alarm_changes(self, query_filter, orderby, limit): if limit is not None: @@ -432,7 +434,7 @@ class Connection(base.Connection): ah = {} ah.update(alarm_history) del ah['_id'] - yield models.AlarmChange(**ah) + yield alarm_models.AlarmChange(**ah) @classmethod def _ensure_encapsulated_rule_format(cls, alarm): diff --git a/ceilometer/tests/alarm/evaluator/test_combination.py b/ceilometer/tests/alarm/evaluator/test_combination.py index 1189f5a2..cc36d34a 100644 --- a/ceilometer/tests/alarm/evaluator/test_combination.py +++ b/ceilometer/tests/alarm/evaluator/test_combination.py @@ -22,8 +22,8 @@ import pytz import uuid from ceilometer.alarm.evaluator import combination +from ceilometer.alarm.storage import models from ceilometer.openstack.common import timeutils -from ceilometer.storage import models from ceilometer.tests.alarm.evaluator import base from ceilometerclient import exc from ceilometerclient.v2 import alarms diff --git a/ceilometer/tests/alarm/evaluator/test_threshold.py b/ceilometer/tests/alarm/evaluator/test_threshold.py index 6b8efd14..66d27898 100644 --- a/ceilometer/tests/alarm/evaluator/test_threshold.py +++ b/ceilometer/tests/alarm/evaluator/test_threshold.py @@ -24,8 +24,8 @@ import uuid from six import moves from ceilometer.alarm.evaluator import threshold +from ceilometer.alarm.storage import models from ceilometer.openstack.common import timeutils -from ceilometer.storage import models from ceilometer.tests.alarm.evaluator import base from ceilometerclient import exc from ceilometerclient.v2 import statistics diff --git a/ceilometer/tests/alarm/partition/test_coordination.py b/ceilometer/tests/alarm/partition/test_coordination.py index b396c66e..c56ccb37 100644 --- a/ceilometer/tests/alarm/partition/test_coordination.py +++ b/ceilometer/tests/alarm/partition/test_coordination.py @@ -25,9 +25,9 @@ import mock from six import moves from ceilometer.alarm.partition import coordination +from ceilometer.alarm.storage import models from ceilometer.openstack.common.fixture import config from ceilometer.openstack.common import timeutils -from ceilometer.storage import models from ceilometer.tests import base as tests_base diff --git a/ceilometer/tests/alarm/test_rpc.py b/ceilometer/tests/alarm/test_rpc.py index 3e6bd9d8..c46d3bc1 100644 --- a/ceilometer/tests/alarm/test_rpc.py +++ b/ceilometer/tests/alarm/test_rpc.py @@ -21,11 +21,11 @@ from ceilometerclient.v2 import alarms import eventlet from ceilometer.alarm import rpc as rpc_alarm +from ceilometer.alarm.storage import models from ceilometer import messaging from ceilometer.openstack.common.fixture import config from ceilometer.openstack.common import timeutils -from ceilometer.storage import models -from ceilometer.tests import base +from ceilometer.tests import base as tests_base class FakeNotifier(object): @@ -44,7 +44,7 @@ class FakeNotifier(object): self.rpc.stop() -class TestRPCAlarmNotifier(base.BaseTestCase): +class TestRPCAlarmNotifier(tests_base.BaseTestCase): def setUp(self): super(TestRPCAlarmNotifier, self).setUp() self.CONF = self.useFixture(config.Config()).conf @@ -165,7 +165,7 @@ class FakeCoordinator(object): self.rpc.stop() -class TestRPCAlarmPartitionCoordination(base.BaseTestCase): +class TestRPCAlarmPartitionCoordination(tests_base.BaseTestCase): def setUp(self): super(TestRPCAlarmPartitionCoordination, self).setUp() self.CONF = self.useFixture(config.Config()).conf diff --git a/ceilometer/tests/api/v2/test_alarm_scenarios.py b/ceilometer/tests/api/v2/test_alarm_scenarios.py index 35eadce8..2134bc35 100644 --- a/ceilometer/tests/api/v2/test_alarm_scenarios.py +++ b/ceilometer/tests/api/v2/test_alarm_scenarios.py @@ -28,8 +28,8 @@ import mock import oslo.messaging.conffixture from six import moves +from ceilometer.alarm.storage import models from ceilometer import messaging -from ceilometer.storage import models from ceilometer.tests.api.v2 import FunctionalTest from ceilometer.tests import db as tests_db diff --git a/ceilometer/tests/api/v2/test_complex_query.py b/ceilometer/tests/api/v2/test_complex_query.py index b11e41b4..d7d2af6f 100644 --- a/ceilometer/tests/api/v2/test_complex_query.py +++ b/ceilometer/tests/api/v2/test_complex_query.py @@ -22,9 +22,10 @@ import jsonschema import mock import wsme +from ceilometer.alarm.storage import models as alarm_models from ceilometer.api.controllers import v2 as api from ceilometer.openstack.common import test -from ceilometer import storage as storage +from ceilometer import storage class FakeComplexQuery(api.ValidatedComplexQuery): @@ -51,9 +52,9 @@ class TestComplexQuery(test.BaseTestCase): self.query = FakeComplexQuery(storage.models.Sample, sample_name_mapping, True) - self.query_alarm = FakeComplexQuery(storage.models.Alarm) + self.query_alarm = FakeComplexQuery(alarm_models.Alarm) self.query_alarmchange = FakeComplexQuery( - storage.models.AlarmChange) + alarm_models.AlarmChange) def test_replace_isotime_utc(self): filter_expr = {"=": {"timestamp": "2013-12-05T19:38:29Z"}} diff --git a/ceilometer/tests/api/v2/test_complex_query_scenarios.py b/ceilometer/tests/api/v2/test_complex_query_scenarios.py index 0a46343c..2fdc441b 100644 --- a/ceilometer/tests/api/v2/test_complex_query_scenarios.py +++ b/ceilometer/tests/api/v2/test_complex_query_scenarios.py @@ -21,10 +21,10 @@ import datetime import logging +from ceilometer.alarm.storage import models from ceilometer.openstack.common import timeutils from ceilometer.publisher import utils from ceilometer import sample -from ceilometer.storage import models from ceilometer.tests.api import v2 as tests_api from ceilometer.tests import db as tests_db diff --git a/ceilometer/tests/storage/test_models.py b/ceilometer/tests/storage/test_models.py index be20c734..4f9b46a0 100644 --- a/ceilometer/tests/storage/test_models.py +++ b/ceilometer/tests/storage/test_models.py @@ -17,13 +17,15 @@ import datetime +from ceilometer.alarm.storage import models as alarm_models from ceilometer.openstack.common import test +from ceilometer.storage import base from ceilometer.storage import models -class FakeModel(models.Model): +class FakeModel(base.Model): def __init__(self, arg1, arg2): - models.Model.__init__(self, arg1=arg1, arg2=arg2) + base.Model.__init__(self, arg1=arg1, arg2=arg2) class ModelTest(test.BaseTestCase): @@ -76,7 +78,7 @@ class ModelTest(test.BaseTestCase): "time_constraints"] self.assertEqual(set(alarm_fields), - set(models.Alarm.get_field_names())) + set(alarm_models.Alarm.get_field_names())) def test_get_field_names_of_alarmchange(self): alarmchange_fields = ["event_id", "alarm_id", "type", "detail", @@ -84,7 +86,7 @@ class ModelTest(test.BaseTestCase): "timestamp"] self.assertEqual(set(alarmchange_fields), - set(models.AlarmChange.get_field_names())) + set(alarm_models.AlarmChange.get_field_names())) class TestTraitModel(test.BaseTestCase): diff --git a/ceilometer/tests/storage/test_storage_scenarios.py b/ceilometer/tests/storage/test_storage_scenarios.py index 3cbe322a..31dad331 100644 --- a/ceilometer/tests/storage/test_storage_scenarios.py +++ b/ceilometer/tests/storage/test_storage_scenarios.py @@ -23,6 +23,7 @@ import datetime import mock +from ceilometer.alarm.storage import models as alarm_models from ceilometer.openstack.common import timeutils from ceilometer.publisher import utils from ceilometer import sample @@ -655,32 +656,32 @@ class RawSampleTest(DBTestBase, if isinstance(self.conn, mongodb.Connection): return - alarm = models.Alarm(alarm_id='r3d', - enabled=True, - type='threshold', - name='red-alert', - description='my red-alert', - timestamp=None, - user_id='user-id', - project_id='project-id', - state="insufficient data", - state_timestamp=None, - ok_actions=[], - alarm_actions=['http://nowhere/alarms'], - insufficient_data_actions=[], - repeat_actions=False, - time_constraints=[], - rule=dict(comparison_operator='eq', - threshold=36, - statistic='count', - evaluation_periods=1, - period=60, - meter_name='test.one', - query=[{'field': 'key', - 'op': 'eq', - 'value': 'value', - 'type': 'string'}]), - ) + alarm = alarm_models.Alarm(alarm_id='r3d', + enabled=True, + type='threshold', + name='red-alert', + description='my red-alert', + timestamp=None, + user_id='user-id', + project_id='project-id', + state="insufficient data", + state_timestamp=None, + ok_actions=[], + alarm_actions=['http://nowhere/alarms'], + insufficient_data_actions=[], + repeat_actions=False, + time_constraints=[], + rule=dict(comparison_operator='eq', + threshold=36, + statistic='count', + evaluation_periods=1, + period=60, + meter_name='test.one', + query=[{'field': 'key', + 'op': 'eq', + 'value': 'value', + 'type': 'string'}]), + ) self.conn.create_alarm(alarm) self.mock_utcnow.return_value = datetime.datetime(2012, 7, 2, 10, 45) @@ -2302,91 +2303,91 @@ class CounterDataTypeTest(DBTestBase, class AlarmTestBase(DBTestBase): def add_some_alarms(self): - alarms = [models.Alarm(alarm_id='r3d', - enabled=True, - type='threshold', - name='red-alert', - description='my red-alert', - timestamp=None, - user_id='me', - project_id='and-da-boys', - state="insufficient data", - state_timestamp=None, - ok_actions=[], - alarm_actions=['http://nowhere/alarms'], - insufficient_data_actions=[], - repeat_actions=False, - time_constraints=[dict(name='testcons', - start='0 11 * * *', - duration=300)], - rule=dict(comparison_operator='eq', - threshold=36, - statistic='count', - evaluation_periods=1, - period=60, - meter_name='test.one', - query=[{'field': 'key', - 'op': 'eq', - 'value': 'value', - 'type': 'string'}]), - ), - models.Alarm(alarm_id='0r4ng3', - enabled=True, - type='threshold', - name='orange-alert', - description='a orange', - timestamp=None, - user_id='me', - project_id='and-da-boys', - state="insufficient data", - state_timestamp=None, - ok_actions=[], - alarm_actions=['http://nowhere/alarms'], - insufficient_data_actions=[], - repeat_actions=False, - time_constraints=[], - rule=dict(comparison_operator='gt', - threshold=75, - statistic='avg', - evaluation_periods=1, - period=60, - meter_name='test.fourty', - query=[{'field': 'key2', - 'op': 'eq', - 'value': 'value2', - 'type': 'string'}]), - ), - models.Alarm(alarm_id='y3ll0w', - enabled=False, - type='threshold', - name='yellow-alert', - description='yellow', - timestamp=None, - user_id='me', - project_id='and-da-boys', - state="insufficient data", - state_timestamp=None, - ok_actions=[], - alarm_actions=['http://nowhere/alarms'], - insufficient_data_actions=[], - repeat_actions=False, - time_constraints=[], - rule=dict(comparison_operator='lt', - threshold=10, - statistic='min', - evaluation_periods=1, - period=60, - meter_name='test.five', - query=[{'field': 'key2', - 'op': 'eq', - 'value': 'value2', - 'type': 'string'}, - {'field': - 'user_metadata.key3', - 'op': 'eq', - 'value': 'value3', - 'type': 'string'}]), - )] + alarms = [alarm_models.Alarm(alarm_id='r3d', + enabled=True, + type='threshold', + name='red-alert', + description='my red-alert', + timestamp=None, + user_id='me', + project_id='and-da-boys', + state="insufficient data", + state_timestamp=None, + ok_actions=[], + alarm_actions=['http://nowhere/alarms'], + insufficient_data_actions=[], + repeat_actions=False, + time_constraints=[dict(name='testcons', + start='0 11 * * *', + duration=300)], + rule=dict(comparison_operator='eq', + threshold=36, + statistic='count', + evaluation_periods=1, + period=60, + meter_name='test.one', + query=[{'field': 'key', + 'op': 'eq', + 'value': 'value', + 'type': 'string'}]), + ), + alarm_models.Alarm(alarm_id='0r4ng3', + enabled=True, + type='threshold', + name='orange-alert', + description='a orange', + timestamp=None, + user_id='me', + project_id='and-da-boys', + state="insufficient data", + state_timestamp=None, + ok_actions=[], + alarm_actions=['http://nowhere/alarms'], + insufficient_data_actions=[], + repeat_actions=False, + time_constraints=[], + rule=dict(comparison_operator='gt', + threshold=75, + statistic='avg', + evaluation_periods=1, + period=60, + meter_name='test.fourty', + query=[{'field': 'key2', + 'op': 'eq', + 'value': 'value2', + 'type': 'string'}]), + ), + alarm_models.Alarm(alarm_id='y3ll0w', + enabled=False, + type='threshold', + name='yellow-alert', + description='yellow', + timestamp=None, + user_id='me', + project_id='and-da-boys', + state="insufficient data", + state_timestamp=None, + ok_actions=[], + alarm_actions=['http://nowhere/alarms'], + insufficient_data_actions=[], + repeat_actions=False, + time_constraints=[], + rule=dict(comparison_operator='lt', + threshold=10, + statistic='min', + evaluation_periods=1, + period=60, + meter_name='test.five', + query=[{'field': 'key2', + 'op': 'eq', + 'value': 'value2', + 'type': 'string'}, + {'field': + 'user_metadata.key3', + 'op': 'eq', + 'value': 'value3', + 'type': 'string'}]), + )] for a in alarms: self.conn.create_alarm(a) @@ -2427,7 +2428,7 @@ class AlarmTest(AlarmTestBase, self.add_some_alarms() orange = list(self.conn.get_alarms(name='orange-alert'))[0] orange.enabled = False - orange.state = models.Alarm.ALARM_INSUFFICIENT_DATA + orange.state = alarm_models.Alarm.ALARM_INSUFFICIENT_DATA query = [{'field': 'metadata.group', 'op': 'eq', 'value': 'test.updated', @@ -2436,36 +2437,37 @@ class AlarmTest(AlarmTestBase, orange.rule['meter_name'] = 'new_meter_name' updated = self.conn.update_alarm(orange) self.assertEqual(updated.enabled, False) - self.assertEqual(updated.state, models.Alarm.ALARM_INSUFFICIENT_DATA) + self.assertEqual(updated.state, + alarm_models.Alarm.ALARM_INSUFFICIENT_DATA) self.assertEqual(updated.rule['query'], query) self.assertEqual(updated.rule['meter_name'], 'new_meter_name') def test_update_llu(self): - llu = models.Alarm(alarm_id='llu', - enabled=True, - type='threshold', - name='llu', - description='llu', - timestamp=None, - user_id='bla', - project_id='ffo', - state="insufficient data", - state_timestamp=None, - ok_actions=[], - alarm_actions=[], - insufficient_data_actions=[], - repeat_actions=False, - time_constraints=[], - rule=dict(comparison_operator='lt', - threshold=34, - statistic='max', - evaluation_periods=1, - period=60, - meter_name='llt', - query=[]) - ) + llu = alarm_models.Alarm(alarm_id='llu', + enabled=True, + type='threshold', + name='llu', + description='llu', + timestamp=None, + user_id='bla', + project_id='ffo', + state="insufficient data", + state_timestamp=None, + ok_actions=[], + alarm_actions=[], + insufficient_data_actions=[], + repeat_actions=False, + time_constraints=[], + rule=dict(comparison_operator='lt', + threshold=34, + statistic='max', + evaluation_periods=1, + period=60, + meter_name='llt', + query=[]) + ) updated = self.conn.update_alarm(llu) - updated.state = models.Alarm.ALARM_OK + updated.state = alarm_models.Alarm.ALARM_OK updated.description = ':)' self.conn.update_alarm(updated) @@ -2595,7 +2597,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, alarm_change = dict(event_id= "16fd2706-8baf-433b-82eb-8c7fada847c%s" % i, alarm_id=alarm.alarm_id, - type=models.AlarmChange.CREATION, + type=alarm_models.AlarmChange.CREATION, detail="detail %s" % alarm.name, user_id=alarm.user_id, project_id=alarm.project_id, @@ -2608,7 +2610,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, alarm_change2 = dict(event_id= "16fd2706-8baf-433b-82eb-8c7fada847d%s" % i, alarm_id=alarm.alarm_id, - type=models.AlarmChange.RULE_CHANGE, + type=alarm_models.AlarmChange.RULE_CHANGE, detail="detail %s" % i, user_id=alarm.user_id, project_id=alarm.project_id, @@ -2618,18 +2620,16 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, 30 + i)) self.conn.record_alarm_change(alarm_change=alarm_change2) - alarm_change3 = dict(event_id= - "16fd2706-8baf-433b-82eb-8c7fada847e%s" - % i, - alarm_id=alarm.alarm_id, - type=models.AlarmChange.STATE_TRANSITION, - detail="detail %s" % (i + 1), - user_id=alarm.user_id, - project_id=alarm.project_id, - on_behalf_of=alarm.project_id, - timestamp=datetime.datetime(2012, 9, 26, - 10 + i, - 30 + i)) + alarm_change3 = dict( + event_id="16fd2706-8baf-433b-82eb-8c7fada847e%s" % i, + alarm_id=alarm.alarm_id, + type=alarm_models.AlarmChange.STATE_TRANSITION, + detail="detail %s" % (i + 1), + user_id=alarm.user_id, + project_id=alarm.project_id, + on_behalf_of=alarm.project_id, + timestamp=datetime.datetime(2012, 9, 26, 10 + i, 30 + i) + ) if alarm.name == "red-alert": alarm_change3['on_behalf_of'] = 'and-da-girls' @@ -2641,7 +2641,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, "16fd2706-8baf-433b-82eb-8c7fada847f%s" % i, alarm_id=alarm.alarm_id, - type=models.AlarmChange.DELETION, + type=alarm_models.AlarmChange.DELETION, detail="detail %s" % (i + 2), user_id=alarm.user_id, project_id=alarm.project_id, @@ -2669,8 +2669,8 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, self.conn.query_alarm_history(filter_expr=self.filter_expr, orderby=[{"timestamp": "asc"}])) - self.assertEqual([models.AlarmChange.RULE_CHANGE, - models.AlarmChange.STATE_TRANSITION], + self.assertEqual([alarm_models.AlarmChange.RULE_CHANGE, + alarm_models.AlarmChange.STATE_TRANSITION], [h.type for h in history]) def test_alarm_history_with_filter_and_orderby_and_limit(self): @@ -2679,7 +2679,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, orderby=[{"timestamp": "asc"}], limit=1)) - self.assertEqual(models.AlarmChange.RULE_CHANGE, history[0].type) + self.assertEqual(alarm_models.AlarmChange.RULE_CHANGE, history[0].type) def test_alarm_history_with_on_behalf_of_filter(self): filter_expr = {"=": {"on_behalf_of": "and-da-girls"}} @@ -2694,10 +2694,10 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase, orderby=[{"timestamp": "asc"}])) self.assertEqual(4, len(history)) - self.assertEqual([models.AlarmChange.CREATION, - models.AlarmChange.RULE_CHANGE, - models.AlarmChange.STATE_TRANSITION, - models.AlarmChange.DELETION], + self.assertEqual([alarm_models.AlarmChange.CREATION, + alarm_models.AlarmChange.RULE_CHANGE, + alarm_models.AlarmChange.STATE_TRANSITION, + alarm_models.AlarmChange.DELETION], [h.type for h in history])