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
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',

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
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)

View File

@ -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."""

View File

@ -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.

View File

@ -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

View File

@ -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 "<Trait: %s %d %s>" % (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)

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"}}

View File

@ -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

View File

@ -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):

View File

@ -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])