Separate alarm storage models from other models

This change isolate storage models used for alarm into a separate file.

This a preparation work to have all alarms related storage API inside
the alarm namespace and then be able to have a different database for
alarming and metering.

Partial implements blueprint dedicated-alarm-database

Change-Id: Iab6b70c6a48301164016823bd0f8e9781ca21abd
This commit is contained in:
Mehdi Abaakouk 2014-06-10 17:04:12 +02:00
parent a30af5bc6c
commit d62fbc9b49
18 changed files with 433 additions and 404 deletions

View File

@ -18,11 +18,11 @@
from oslo.config import cfg from oslo.config import cfg
import six import six
from ceilometer.alarm.storage import models
from ceilometer import messaging from ceilometer import messaging
from ceilometer.openstack.common import context from ceilometer.openstack.common import context
from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log from ceilometer.openstack.common import log
from ceilometer.storage import models
OPTS = [ OPTS = [
cfg.StrOpt('notifier_rpc_topic', cfg.StrOpt('notifier_rpc_topic',

View File

View File

@ -0,0 +1,122 @@
#
# Copyright 2013 New Dream Network, LLC (DreamHost)
#
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
#
# 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)

View File

@ -44,6 +44,7 @@ import wsme
from wsme import types as wtypes from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan import wsmeext.pecan as wsme_pecan
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.api import acl from ceilometer.api import acl
from ceilometer import messaging from ceilometer import messaging
from ceilometer.openstack.common import context 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): def _record_change(self, data, now, on_behalf_of=None, type=None):
if not cfg.CONF.alarm.record_history: if not cfg.CONF.alarm.record_history:
return return
type = type or storage.models.AlarmChange.RULE_CHANGE type = type or alarm_models.AlarmChange.RULE_CHANGE
scrubbed_data = utils.stringify_timestamps(data) scrubbed_data = utils.stringify_timestamps(data)
detail = json.dumps(scrubbed_data) detail = json.dumps(scrubbed_data)
user_id = pecan.request.headers.get('X-User-Id') 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 ' raise ClientSideError(_('Cannot specify alarm %s itself in '
'combination rule') % self._id) 'combination rule') % self._id)
old_alarm = Alarm.from_db_model(alarm_in).as_dict(storage.models.Alarm) old_alarm = Alarm.from_db_model(alarm_in).as_dict(alarm_models.Alarm)
updated_alarm = data.as_dict(storage.models.Alarm) updated_alarm = data.as_dict(alarm_models.Alarm)
try: try:
alarm_in = storage.models.Alarm(**updated_alarm) alarm_in = alarm_models.Alarm(**updated_alarm)
except Exception: except Exception:
LOG.exception(_("Error while putting alarm: %s") % updated_alarm) LOG.exception(_("Error while putting alarm: %s") % updated_alarm)
raise ClientSideError(_("Alarm incorrect")) raise ClientSideError(_("Alarm incorrect"))
@ -1990,10 +1991,10 @@ class AlarmController(rest.RestController):
# ensure alarm exists before deleting # ensure alarm exists before deleting
alarm = self._alarm() alarm = self._alarm()
self.conn.delete_alarm(alarm.alarm_id) 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, self._record_change(change,
timeutils.utcnow(), timeutils.utcnow(),
type=storage.models.AlarmChange.DELETION) type=alarm_models.AlarmChange.DELETION)
# TODO(eglynn): add pagination marker to signature once overall # TODO(eglynn): add pagination marker to signature once overall
# API support for pagination is finalized # API support for pagination is finalized
@ -2033,7 +2034,7 @@ class AlarmController(rest.RestController):
alarm = self.conn.update_alarm(alarm) alarm = self.conn.update_alarm(alarm)
change = {'state': alarm.state} change = {'state': alarm.state}
self._record_change(change, now, on_behalf_of=alarm.project_id, 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 return alarm.state
@wsme_pecan.wsexpose(state_kind_enum) @wsme_pecan.wsexpose(state_kind_enum)
@ -2055,7 +2056,7 @@ class AlarmsController(rest.RestController):
def _record_creation(self, conn, data, alarm_id, now): def _record_creation(self, conn, data, alarm_id, now):
if not cfg.CONF.alarm.record_history: if not cfg.CONF.alarm.record_history:
return return
type = storage.models.AlarmChange.CREATION type = alarm_models.AlarmChange.CREATION
scrubbed_data = utils.stringify_timestamps(data) scrubbed_data = utils.stringify_timestamps(data)
detail = json.dumps(scrubbed_data) detail = json.dumps(scrubbed_data)
user_id = pecan.request.headers.get('X-User-Id') user_id = pecan.request.headers.get('X-User-Id')
@ -2109,7 +2110,7 @@ class AlarmsController(rest.RestController):
data.timestamp = now data.timestamp = now
data.state_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. # make sure alarms are unique by name per project.
alarms = list(conn.get_alarms(name=data.name, alarms = list(conn.get_alarms(name=data.name,
@ -2120,7 +2121,7 @@ class AlarmsController(rest.RestController):
status_code=409) status_code=409)
try: try:
alarm_in = storage.models.Alarm(**change) alarm_in = alarm_models.Alarm(**change)
except Exception: except Exception:
LOG.exception(_("Error while posting alarm: %s") % change) LOG.exception(_("Error while posting alarm: %s") % change)
raise ClientSideError(_("Alarm incorrect")) raise ClientSideError(_("Alarm incorrect"))
@ -2412,7 +2413,7 @@ class QueryAlarmHistoryController(rest.RestController):
:param body: Query rules for the alarm history to be returned. :param body: Query rules for the alarm history to be returned.
""" """
query = ValidatedComplexQuery(body, query = ValidatedComplexQuery(body,
storage.models.AlarmChange) alarm_models.AlarmChange)
query.validate(visibility_field="on_behalf_of") query.validate(visibility_field="on_behalf_of")
conn = pecan.request.storage_conn conn = pecan.request.storage_conn
return [AlarmChange.from_db_model(s) return [AlarmChange.from_db_model(s)
@ -2433,7 +2434,7 @@ class QueryAlarmsController(rest.RestController):
:param body: Query rules for the alarms to be returned. :param body: Query rules for the alarms to be returned.
""" """
query = ValidatedComplexQuery(body, query = ValidatedComplexQuery(body,
storage.models.Alarm) alarm_models.Alarm)
query.validate(visibility_field="project_id") query.validate(visibility_field="project_id")
conn = pecan.request.storage_conn conn = pecan.request.storage_conn
return [Alarm.from_db_model(s) return [Alarm.from_db_model(s)

View File

@ -18,6 +18,7 @@
""" """
import datetime import datetime
import inspect
import math import math
from six import moves from six import moves
@ -102,6 +103,35 @@ class Pagination(object):
self.sort_dirs = sort_dirs or [] 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): class Connection(object):
"""Base class for storage system connections.""" """Base class for storage system connections."""

View File

@ -31,6 +31,7 @@ import time
import bson.json_util import bson.json_util
import happybase import happybase
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log from ceilometer.openstack.common import log
from ceilometer.openstack.common import network_utils from ceilometer.openstack.common import network_utils
@ -263,7 +264,7 @@ class Connection(base.Connection):
alarm_table = conn.table(self.ALARM_TABLE) alarm_table = conn.table(self.ALARM_TABLE)
alarm_table.put(_id, alarm_to_store) alarm_table.put(_id, alarm_to_store)
stored_alarm = deserialize_entry(alarm_table.row(_id))[0] stored_alarm = deserialize_entry(alarm_table.row(_id))[0]
return models.Alarm(**stored_alarm) return alarm_models.Alarm(**stored_alarm)
create_alarm = update_alarm create_alarm = update_alarm
@ -288,7 +289,7 @@ class Connection(base.Connection):
gen = alarm_table.scan(filter=q) gen = alarm_table.scan(filter=q)
for ignored, data in gen: for ignored, data in gen:
stored_alarm = deserialize_entry(data)[0] 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, def get_alarm_changes(self, alarm_id, on_behalf_of,
user=None, project=None, type=None, user=None, project=None, type=None,
@ -307,7 +308,7 @@ class Connection(base.Connection):
row_stop=end_row) row_stop=end_row)
for ignored, data in gen: for ignored, data in gen:
stored_entry = deserialize_entry(data)[0] stored_entry = deserialize_entry(data)[0]
yield models.AlarmChange(**stored_entry) yield alarm_models.AlarmChange(**stored_entry)
def record_alarm_change(self, alarm_change): def record_alarm_change(self, alarm_change):
"""Record alarm change event. """Record alarm change event.

View File

@ -32,6 +32,7 @@ from sqlalchemy import not_
from sqlalchemy import or_ from sqlalchemy import or_
from sqlalchemy.orm import aliased 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 import exception as dbexc
from ceilometer.openstack.common.db.sqlalchemy import migration from ceilometer.openstack.common.db.sqlalchemy import migration
import ceilometer.openstack.common.db.sqlalchemy.session as sqlalchemy_session import ceilometer.openstack.common.db.sqlalchemy.session as sqlalchemy_session
@ -664,7 +665,7 @@ class Connection(base.Connection):
@staticmethod @staticmethod
def _row_to_alarm_model(row): def _row_to_alarm_model(row):
return api_models.Alarm(alarm_id=row.alarm_id, return alarm_api_models.Alarm(alarm_id=row.alarm_id,
enabled=row.enabled, enabled=row.enabled,
type=row.type, type=row.type,
name=row.name, name=row.name,
@ -762,7 +763,7 @@ class Connection(base.Connection):
@staticmethod @staticmethod
def _row_to_alarm_change_model(row): def _row_to_alarm_change_model(row):
return api_models.AlarmChange(event_id=row.event_id, return alarm_api_models.AlarmChange(event_id=row.event_id,
alarm_id=row.alarm_id, alarm_id=row.alarm_id,
type=row.type, type=row.type,
detail=row.detail, detail=row.detail,

View File

@ -16,41 +16,12 @@
# under the License. # under the License.
"""Model classes for use in the storage API. """Model classes for use in the storage API.
""" """
import inspect
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.storage import base
class Model(object): class Event(base.Model):
"""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):
"""A raw event from the source system. Events have Traits. """A raw event from the source system. Events have Traits.
Metrics will be derived from one or more Events. Metrics will be derived from one or more Events.
@ -70,7 +41,7 @@ class Event(Model):
:param generated: UTC time for when the event occurred. :param generated: UTC time for when the event occurred.
:param traits: list of Traits on this Event. :param traits: list of Traits on this Event.
""" """
Model.__init__(self, message_id=message_id, event_type=event_type, base.Model.__init__(self, message_id=message_id, event_type=event_type,
generated=generated, traits=traits) generated=generated, traits=traits)
def append_trait(self, trait_model): def append_trait(self, trait_model):
@ -85,7 +56,7 @@ class Event(Model):
" ".join(trait_list)) " ".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 """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). record of basic data types (int, date, float, etc).
""" """
@ -107,7 +78,7 @@ class Trait(Model):
def __init__(self, name, dtype, value): def __init__(self, name, dtype, value):
if not dtype: if not dtype:
dtype = Trait.NONE_TYPE 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): def __repr__(self):
return "<Trait: %s %d %s>" % (self.name, self.dtype, self.value) return "<Trait: %s %d %s>" % (self.name, self.dtype, self.value)
@ -138,7 +109,7 @@ class Trait(Model):
return str(value) return str(value)
class Resource(Model): class Resource(base.Model):
"""Something for which sample data has been collected. """Something for which sample data has been collected.
""" """
@ -156,7 +127,7 @@ class Resource(Model):
:param user_id: UUID of user owning the resource :param user_id: UUID of user owning the resource
:param metadata: most current metadata for the resource (a dict) :param metadata: most current metadata for the resource (a dict)
""" """
Model.__init__(self, base.Model.__init__(self,
resource_id=resource_id, resource_id=resource_id,
first_sample_timestamp=first_sample_timestamp, first_sample_timestamp=first_sample_timestamp,
last_sample_timestamp=last_sample_timestamp, last_sample_timestamp=last_sample_timestamp,
@ -167,7 +138,7 @@ class Resource(Model):
) )
class Meter(Model): class Meter(base.Model):
"""Definition of a meter for which sample data has been collected. """Definition of a meter for which sample data has been collected.
""" """
@ -183,7 +154,7 @@ class Meter(Model):
:param source: the identifier for the user/project id definition :param source: the identifier for the user/project id definition
:param user_id: UUID of user owning the resource :param user_id: UUID of user owning the resource
""" """
Model.__init__(self, base.Model.__init__(self,
name=name, name=name,
type=type, type=type,
unit=unit, unit=unit,
@ -194,7 +165,7 @@ class Meter(Model):
) )
class Sample(Model): class Sample(base.Model):
"""One collected data point. """One collected data point.
""" """
def __init__(self, def __init__(self,
@ -223,7 +194,7 @@ class Sample(Model):
:param message_signature: a hash created from the rest of the :param message_signature: a hash created from the rest of the
message data message data
""" """
Model.__init__(self, base.Model.__init__(self,
source=source, source=source,
counter_name=counter_name, counter_name=counter_name,
counter_type=counter_type, counter_type=counter_type,
@ -239,7 +210,7 @@ class Sample(Model):
recorded_at=recorded_at) recorded_at=recorded_at)
class Statistics(Model): class Statistics(base.Model):
"""Computed statistics based on a set of sample data. """Computed statistics based on a set of sample data.
""" """
def __init__(self, unit, def __init__(self, unit,
@ -264,112 +235,10 @@ class Statistics(Model):
count: The number of samples found count: The number of samples found
aggregate: name-value pairs for selectable aggregates aggregate: name-value pairs for selectable aggregates
""" """
Model.__init__(self, unit=unit, base.Model.__init__(self, unit=unit,
period=period, period_start=period_start, period=period, period_start=period_start,
period_end=period_end, duration=duration, period_end=period_end, duration=duration,
duration_start=duration_start, duration_start=duration_start,
duration_end=duration_end, duration_end=duration_end,
groupby=groupby, groupby=groupby,
**data) **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)

View File

@ -24,6 +24,7 @@ from oslo.config import cfg
import pymongo import pymongo
import weakref import weakref
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.openstack.common.gettextutils import _ from ceilometer.openstack.common.gettextutils import _
from ceilometer.openstack.common import log from ceilometer.openstack.common import log
from ceilometer.openstack.common import network_utils from ceilometer.openstack.common import network_utils
@ -240,7 +241,7 @@ class Connection(base.Connection):
del stored_alarm['_id'] del stored_alarm['_id']
self._ensure_encapsulated_rule_format(stored_alarm) self._ensure_encapsulated_rule_format(stored_alarm)
self._ensure_time_constraints(stored_alarm) self._ensure_time_constraints(stored_alarm)
return models.Alarm(**stored_alarm) return alarm_models.Alarm(**stored_alarm)
create_alarm = update_alarm create_alarm = update_alarm
@ -357,7 +358,8 @@ class Connection(base.Connection):
def query_alarms(self, filter_expr=None, orderby=None, limit=None): def query_alarms(self, filter_expr=None, orderby=None, limit=None):
"""Return an iterable of model.Alarm objects. """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): def query_alarm_history(self, filter_expr=None, orderby=None, limit=None):
"""Return an iterable of model.AlarmChange objects. """Return an iterable of model.AlarmChange objects.
@ -365,7 +367,7 @@ class Connection(base.Connection):
return self._retrieve_data(filter_expr, return self._retrieve_data(filter_expr,
orderby, orderby,
limit, limit,
models.AlarmChange) alarm_models.AlarmChange)
def _retrieve_data(self, filter_expr, orderby, limit, model): def _retrieve_data(self, filter_expr, orderby, limit, model):
if limit == 0: if limit == 0:
@ -379,8 +381,8 @@ class Connection(base.Connection):
query_filter = transformer.transform_filter(filter_expr) query_filter = transformer.transform_filter(filter_expr)
retrieve = {models.Meter: self._retrieve_samples, retrieve = {models.Meter: self._retrieve_samples,
models.Alarm: self._retrieve_alarms, alarm_models.Alarm: self._retrieve_alarms,
models.AlarmChange: self._retrieve_alarm_changes} alarm_models.AlarmChange: self._retrieve_alarm_changes}
return retrieve[model](query_filter, orderby_filter, limit) return retrieve[model](query_filter, orderby_filter, limit)
def _retrieve_samples(self, query, orderby, limit): def _retrieve_samples(self, query, orderby, limit):
@ -417,7 +419,7 @@ class Connection(base.Connection):
del a['_id'] del a['_id']
self._ensure_encapsulated_rule_format(a) self._ensure_encapsulated_rule_format(a)
self._ensure_time_constraints(a) self._ensure_time_constraints(a)
yield models.Alarm(**a) yield alarm_models.Alarm(**a)
def _retrieve_alarm_changes(self, query_filter, orderby, limit): def _retrieve_alarm_changes(self, query_filter, orderby, limit):
if limit is not None: if limit is not None:
@ -432,7 +434,7 @@ class Connection(base.Connection):
ah = {} ah = {}
ah.update(alarm_history) ah.update(alarm_history)
del ah['_id'] del ah['_id']
yield models.AlarmChange(**ah) yield alarm_models.AlarmChange(**ah)
@classmethod @classmethod
def _ensure_encapsulated_rule_format(cls, alarm): def _ensure_encapsulated_rule_format(cls, alarm):

View File

@ -22,8 +22,8 @@ import pytz
import uuid import uuid
from ceilometer.alarm.evaluator import combination from ceilometer.alarm.evaluator import combination
from ceilometer.alarm.storage import models
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.storage import models
from ceilometer.tests.alarm.evaluator import base from ceilometer.tests.alarm.evaluator import base
from ceilometerclient import exc from ceilometerclient import exc
from ceilometerclient.v2 import alarms from ceilometerclient.v2 import alarms

View File

@ -24,8 +24,8 @@ import uuid
from six import moves from six import moves
from ceilometer.alarm.evaluator import threshold from ceilometer.alarm.evaluator import threshold
from ceilometer.alarm.storage import models
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.storage import models
from ceilometer.tests.alarm.evaluator import base from ceilometer.tests.alarm.evaluator import base
from ceilometerclient import exc from ceilometerclient import exc
from ceilometerclient.v2 import statistics from ceilometerclient.v2 import statistics

View File

@ -25,9 +25,9 @@ import mock
from six import moves from six import moves
from ceilometer.alarm.partition import coordination from ceilometer.alarm.partition import coordination
from ceilometer.alarm.storage import models
from ceilometer.openstack.common.fixture import config from ceilometer.openstack.common.fixture import config
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.storage import models
from ceilometer.tests import base as tests_base from ceilometer.tests import base as tests_base

View File

@ -21,11 +21,11 @@ from ceilometerclient.v2 import alarms
import eventlet import eventlet
from ceilometer.alarm import rpc as rpc_alarm from ceilometer.alarm import rpc as rpc_alarm
from ceilometer.alarm.storage import models
from ceilometer import messaging from ceilometer import messaging
from ceilometer.openstack.common.fixture import config from ceilometer.openstack.common.fixture import config
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.storage import models from ceilometer.tests import base as tests_base
from ceilometer.tests import base
class FakeNotifier(object): class FakeNotifier(object):
@ -44,7 +44,7 @@ class FakeNotifier(object):
self.rpc.stop() self.rpc.stop()
class TestRPCAlarmNotifier(base.BaseTestCase): class TestRPCAlarmNotifier(tests_base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestRPCAlarmNotifier, self).setUp() super(TestRPCAlarmNotifier, self).setUp()
self.CONF = self.useFixture(config.Config()).conf self.CONF = self.useFixture(config.Config()).conf
@ -165,7 +165,7 @@ class FakeCoordinator(object):
self.rpc.stop() self.rpc.stop()
class TestRPCAlarmPartitionCoordination(base.BaseTestCase): class TestRPCAlarmPartitionCoordination(tests_base.BaseTestCase):
def setUp(self): def setUp(self):
super(TestRPCAlarmPartitionCoordination, self).setUp() super(TestRPCAlarmPartitionCoordination, self).setUp()
self.CONF = self.useFixture(config.Config()).conf self.CONF = self.useFixture(config.Config()).conf

View File

@ -28,8 +28,8 @@ import mock
import oslo.messaging.conffixture import oslo.messaging.conffixture
from six import moves from six import moves
from ceilometer.alarm.storage import models
from ceilometer import messaging from ceilometer import messaging
from ceilometer.storage import models
from ceilometer.tests.api.v2 import FunctionalTest from ceilometer.tests.api.v2 import FunctionalTest
from ceilometer.tests import db as tests_db from ceilometer.tests import db as tests_db

View File

@ -22,9 +22,10 @@ import jsonschema
import mock import mock
import wsme import wsme
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.api.controllers import v2 as api from ceilometer.api.controllers import v2 as api
from ceilometer.openstack.common import test from ceilometer.openstack.common import test
from ceilometer import storage as storage from ceilometer import storage
class FakeComplexQuery(api.ValidatedComplexQuery): class FakeComplexQuery(api.ValidatedComplexQuery):
@ -51,9 +52,9 @@ class TestComplexQuery(test.BaseTestCase):
self.query = FakeComplexQuery(storage.models.Sample, self.query = FakeComplexQuery(storage.models.Sample,
sample_name_mapping, sample_name_mapping,
True) True)
self.query_alarm = FakeComplexQuery(storage.models.Alarm) self.query_alarm = FakeComplexQuery(alarm_models.Alarm)
self.query_alarmchange = FakeComplexQuery( self.query_alarmchange = FakeComplexQuery(
storage.models.AlarmChange) alarm_models.AlarmChange)
def test_replace_isotime_utc(self): def test_replace_isotime_utc(self):
filter_expr = {"=": {"timestamp": "2013-12-05T19:38:29Z"}} filter_expr = {"=": {"timestamp": "2013-12-05T19:38:29Z"}}

View File

@ -21,10 +21,10 @@
import datetime import datetime
import logging import logging
from ceilometer.alarm.storage import models
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.publisher import utils from ceilometer.publisher import utils
from ceilometer import sample from ceilometer import sample
from ceilometer.storage import models
from ceilometer.tests.api import v2 as tests_api from ceilometer.tests.api import v2 as tests_api
from ceilometer.tests import db as tests_db from ceilometer.tests import db as tests_db

View File

@ -17,13 +17,15 @@
import datetime import datetime
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.openstack.common import test from ceilometer.openstack.common import test
from ceilometer.storage import base
from ceilometer.storage import models from ceilometer.storage import models
class FakeModel(models.Model): class FakeModel(base.Model):
def __init__(self, arg1, arg2): 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): class ModelTest(test.BaseTestCase):
@ -76,7 +78,7 @@ class ModelTest(test.BaseTestCase):
"time_constraints"] "time_constraints"]
self.assertEqual(set(alarm_fields), 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): def test_get_field_names_of_alarmchange(self):
alarmchange_fields = ["event_id", "alarm_id", "type", "detail", alarmchange_fields = ["event_id", "alarm_id", "type", "detail",
@ -84,7 +86,7 @@ class ModelTest(test.BaseTestCase):
"timestamp"] "timestamp"]
self.assertEqual(set(alarmchange_fields), self.assertEqual(set(alarmchange_fields),
set(models.AlarmChange.get_field_names())) set(alarm_models.AlarmChange.get_field_names()))
class TestTraitModel(test.BaseTestCase): class TestTraitModel(test.BaseTestCase):

View File

@ -23,6 +23,7 @@ import datetime
import mock import mock
from ceilometer.alarm.storage import models as alarm_models
from ceilometer.openstack.common import timeutils from ceilometer.openstack.common import timeutils
from ceilometer.publisher import utils from ceilometer.publisher import utils
from ceilometer import sample from ceilometer import sample
@ -655,7 +656,7 @@ class RawSampleTest(DBTestBase,
if isinstance(self.conn, mongodb.Connection): if isinstance(self.conn, mongodb.Connection):
return return
alarm = models.Alarm(alarm_id='r3d', alarm = alarm_models.Alarm(alarm_id='r3d',
enabled=True, enabled=True,
type='threshold', type='threshold',
name='red-alert', name='red-alert',
@ -2302,7 +2303,7 @@ class CounterDataTypeTest(DBTestBase,
class AlarmTestBase(DBTestBase): class AlarmTestBase(DBTestBase):
def add_some_alarms(self): def add_some_alarms(self):
alarms = [models.Alarm(alarm_id='r3d', alarms = [alarm_models.Alarm(alarm_id='r3d',
enabled=True, enabled=True,
type='threshold', type='threshold',
name='red-alert', name='red-alert',
@ -2330,7 +2331,7 @@ class AlarmTestBase(DBTestBase):
'value': 'value', 'value': 'value',
'type': 'string'}]), 'type': 'string'}]),
), ),
models.Alarm(alarm_id='0r4ng3', alarm_models.Alarm(alarm_id='0r4ng3',
enabled=True, enabled=True,
type='threshold', type='threshold',
name='orange-alert', name='orange-alert',
@ -2356,7 +2357,7 @@ class AlarmTestBase(DBTestBase):
'value': 'value2', 'value': 'value2',
'type': 'string'}]), 'type': 'string'}]),
), ),
models.Alarm(alarm_id='y3ll0w', alarm_models.Alarm(alarm_id='y3ll0w',
enabled=False, enabled=False,
type='threshold', type='threshold',
name='yellow-alert', name='yellow-alert',
@ -2427,7 +2428,7 @@ class AlarmTest(AlarmTestBase,
self.add_some_alarms() self.add_some_alarms()
orange = list(self.conn.get_alarms(name='orange-alert'))[0] orange = list(self.conn.get_alarms(name='orange-alert'))[0]
orange.enabled = False orange.enabled = False
orange.state = models.Alarm.ALARM_INSUFFICIENT_DATA orange.state = alarm_models.Alarm.ALARM_INSUFFICIENT_DATA
query = [{'field': 'metadata.group', query = [{'field': 'metadata.group',
'op': 'eq', 'op': 'eq',
'value': 'test.updated', 'value': 'test.updated',
@ -2436,12 +2437,13 @@ class AlarmTest(AlarmTestBase,
orange.rule['meter_name'] = 'new_meter_name' orange.rule['meter_name'] = 'new_meter_name'
updated = self.conn.update_alarm(orange) updated = self.conn.update_alarm(orange)
self.assertEqual(updated.enabled, False) 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['query'], query)
self.assertEqual(updated.rule['meter_name'], 'new_meter_name') self.assertEqual(updated.rule['meter_name'], 'new_meter_name')
def test_update_llu(self): def test_update_llu(self):
llu = models.Alarm(alarm_id='llu', llu = alarm_models.Alarm(alarm_id='llu',
enabled=True, enabled=True,
type='threshold', type='threshold',
name='llu', name='llu',
@ -2465,7 +2467,7 @@ class AlarmTest(AlarmTestBase,
query=[]) query=[])
) )
updated = self.conn.update_alarm(llu) updated = self.conn.update_alarm(llu)
updated.state = models.Alarm.ALARM_OK updated.state = alarm_models.Alarm.ALARM_OK
updated.description = ':)' updated.description = ':)'
self.conn.update_alarm(updated) self.conn.update_alarm(updated)
@ -2595,7 +2597,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
alarm_change = dict(event_id= alarm_change = dict(event_id=
"16fd2706-8baf-433b-82eb-8c7fada847c%s" % i, "16fd2706-8baf-433b-82eb-8c7fada847c%s" % i,
alarm_id=alarm.alarm_id, alarm_id=alarm.alarm_id,
type=models.AlarmChange.CREATION, type=alarm_models.AlarmChange.CREATION,
detail="detail %s" % alarm.name, detail="detail %s" % alarm.name,
user_id=alarm.user_id, user_id=alarm.user_id,
project_id=alarm.project_id, project_id=alarm.project_id,
@ -2608,7 +2610,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
alarm_change2 = dict(event_id= alarm_change2 = dict(event_id=
"16fd2706-8baf-433b-82eb-8c7fada847d%s" % i, "16fd2706-8baf-433b-82eb-8c7fada847d%s" % i,
alarm_id=alarm.alarm_id, alarm_id=alarm.alarm_id,
type=models.AlarmChange.RULE_CHANGE, type=alarm_models.AlarmChange.RULE_CHANGE,
detail="detail %s" % i, detail="detail %s" % i,
user_id=alarm.user_id, user_id=alarm.user_id,
project_id=alarm.project_id, project_id=alarm.project_id,
@ -2618,18 +2620,16 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
30 + i)) 30 + i))
self.conn.record_alarm_change(alarm_change=alarm_change2) self.conn.record_alarm_change(alarm_change=alarm_change2)
alarm_change3 = dict(event_id= alarm_change3 = dict(
"16fd2706-8baf-433b-82eb-8c7fada847e%s" event_id="16fd2706-8baf-433b-82eb-8c7fada847e%s" % i,
% i,
alarm_id=alarm.alarm_id, alarm_id=alarm.alarm_id,
type=models.AlarmChange.STATE_TRANSITION, type=alarm_models.AlarmChange.STATE_TRANSITION,
detail="detail %s" % (i + 1), detail="detail %s" % (i + 1),
user_id=alarm.user_id, user_id=alarm.user_id,
project_id=alarm.project_id, project_id=alarm.project_id,
on_behalf_of=alarm.project_id, on_behalf_of=alarm.project_id,
timestamp=datetime.datetime(2012, 9, 26, timestamp=datetime.datetime(2012, 9, 26, 10 + i, 30 + i)
10 + i, )
30 + i))
if alarm.name == "red-alert": if alarm.name == "red-alert":
alarm_change3['on_behalf_of'] = 'and-da-girls' alarm_change3['on_behalf_of'] = 'and-da-girls'
@ -2641,7 +2641,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
"16fd2706-8baf-433b-82eb-8c7fada847f%s" "16fd2706-8baf-433b-82eb-8c7fada847f%s"
% i, % i,
alarm_id=alarm.alarm_id, alarm_id=alarm.alarm_id,
type=models.AlarmChange.DELETION, type=alarm_models.AlarmChange.DELETION,
detail="detail %s" % (i + 2), detail="detail %s" % (i + 2),
user_id=alarm.user_id, user_id=alarm.user_id,
project_id=alarm.project_id, project_id=alarm.project_id,
@ -2669,8 +2669,8 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
self.conn.query_alarm_history(filter_expr=self.filter_expr, self.conn.query_alarm_history(filter_expr=self.filter_expr,
orderby=[{"timestamp": orderby=[{"timestamp":
"asc"}])) "asc"}]))
self.assertEqual([models.AlarmChange.RULE_CHANGE, self.assertEqual([alarm_models.AlarmChange.RULE_CHANGE,
models.AlarmChange.STATE_TRANSITION], alarm_models.AlarmChange.STATE_TRANSITION],
[h.type for h in history]) [h.type for h in history])
def test_alarm_history_with_filter_and_orderby_and_limit(self): def test_alarm_history_with_filter_and_orderby_and_limit(self):
@ -2679,7 +2679,7 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
orderby=[{"timestamp": orderby=[{"timestamp":
"asc"}], "asc"}],
limit=1)) 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): def test_alarm_history_with_on_behalf_of_filter(self):
filter_expr = {"=": {"on_behalf_of": "and-da-girls"}} filter_expr = {"=": {"on_behalf_of": "and-da-girls"}}
@ -2694,10 +2694,10 @@ class ComplexAlarmHistoryQueryTest(AlarmTestBase,
orderby=[{"timestamp": orderby=[{"timestamp":
"asc"}])) "asc"}]))
self.assertEqual(4, len(history)) self.assertEqual(4, len(history))
self.assertEqual([models.AlarmChange.CREATION, self.assertEqual([alarm_models.AlarmChange.CREATION,
models.AlarmChange.RULE_CHANGE, alarm_models.AlarmChange.RULE_CHANGE,
models.AlarmChange.STATE_TRANSITION, alarm_models.AlarmChange.STATE_TRANSITION,
models.AlarmChange.DELETION], alarm_models.AlarmChange.DELETION],
[h.type for h in history]) [h.type for h in history])