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
|
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',
|
||||||
|
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
|
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)
|
||||||
|
@ -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."""
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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"}}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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])
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user