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:
parent
a30af5bc6c
commit
d62fbc9b49
@ -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',
|
||||
|
0
ceilometer/alarm/storage/__init__.py
Normal file
0
ceilometer/alarm/storage/__init__.py
Normal file
122
ceilometer/alarm/storage/models.py
Normal file
122
ceilometer/alarm/storage/models.py
Normal 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)
|
@ -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)
|
||||
|
@ -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."""
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"}}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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])
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user