Merge "Expose alarm severity in Alarm Model"
This commit is contained in:
commit
2b55867308
@ -23,13 +23,14 @@ class AlarmNotifier(object):
|
||||
"""Base class for alarm notifier plugins."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def notify(self, action, alarm_id, alarm_name, previous, current,
|
||||
reason, reason_data):
|
||||
def notify(self, action, alarm_id, alarm_name, severity, previous,
|
||||
current, reason, reason_data):
|
||||
"""Notify that an alarm has been triggered.
|
||||
|
||||
:param action: The action that is being attended, as a parsed URL.
|
||||
:param alarm_id: The triggered alarm.
|
||||
:param alarm_name: The name of triggered alarm.
|
||||
:param severity: The level of triggered alarm
|
||||
:param previous: The previous state of the alarm.
|
||||
:param current: The current state of the alarm.
|
||||
:param reason: The reason the alarm changed its state.
|
||||
|
@ -25,11 +25,15 @@ class LogAlarmNotifier(notifier.AlarmNotifier):
|
||||
"Log alarm notifier."""
|
||||
|
||||
@staticmethod
|
||||
def notify(action, alarm_id, alarm_name, previous, current, reason,
|
||||
reason_data):
|
||||
def notify(action, alarm_id, alarm_name, severity, previous, current,
|
||||
reason, reason_data):
|
||||
LOG.info(_(
|
||||
"Notifying alarm %(alarm_name)s %(alarm_id)s from %(previous)s "
|
||||
"to %(current)s with action %(action)s because "
|
||||
"%(reason)s.") % ({'alarm_name': alarm_name, 'alarm_id': alarm_id,
|
||||
'previous': previous, 'current': current,
|
||||
'action': action, 'reason': reason}))
|
||||
"Notifying alarm %(alarm_name)s %(alarm_id)s of %(severity)s "
|
||||
"priority from %(previous)s to %(current)s with action %(action)s"
|
||||
" because %(reason)s.") % ({'alarm_name': alarm_name,
|
||||
'alarm_id': alarm_id,
|
||||
'severity': severity,
|
||||
'previous': previous,
|
||||
'current': current,
|
||||
'action': action,
|
||||
'reason': reason}))
|
||||
|
@ -55,8 +55,8 @@ class RestAlarmNotifier(notifier.AlarmNotifier):
|
||||
"""Rest alarm notifier."""
|
||||
|
||||
@staticmethod
|
||||
def notify(action, alarm_id, alarm_name, previous, current, reason,
|
||||
reason_data, headers=None):
|
||||
def notify(action, alarm_id, alarm_name, severity, previous,
|
||||
current, reason, reason_data, headers=None):
|
||||
headers = headers or {}
|
||||
if not headers.get('x-openstack-request-id'):
|
||||
headers['x-openstack-request-id'] = context.generate_request_id()
|
||||
@ -66,12 +66,13 @@ class RestAlarmNotifier(notifier.AlarmNotifier):
|
||||
"%(previous)s to %(current)s with action %(action)s because "
|
||||
"%(reason)s. request-id: %(request_id)s ") %
|
||||
({'alarm_name': alarm_name, 'alarm_id': alarm_id,
|
||||
'previous': previous, 'current': current,
|
||||
'action': action, 'reason': reason,
|
||||
'severity': severity, 'previous': previous,
|
||||
'current': current, 'action': action, 'reason': reason,
|
||||
'request_id': headers['x-openstack-request-id']}))
|
||||
body = {'alarm_name': alarm_name, 'alarm_id': alarm_id,
|
||||
'previous': previous, 'current': current,
|
||||
'reason': reason, 'reason_data': reason_data}
|
||||
'severity': severity, 'previous': previous,
|
||||
'current': current, 'reason': reason,
|
||||
'reason_data': reason_data}
|
||||
headers['content-type'] = 'application/json'
|
||||
kwargs = {'data': jsonutils.dumps(body),
|
||||
'headers': headers}
|
||||
|
@ -23,11 +23,12 @@ class TestAlarmNotifier(notifier.AlarmNotifier):
|
||||
def __init__(self):
|
||||
self.notifications = []
|
||||
|
||||
def notify(self, action, alarm_id, alarm_name, previous, current,
|
||||
reason, reason_data):
|
||||
def notify(self, action, alarm_id, alarm_name, severity,
|
||||
previous, current, reason, reason_data):
|
||||
self.notifications.append((action,
|
||||
alarm_id,
|
||||
alarm_name,
|
||||
severity,
|
||||
previous,
|
||||
current,
|
||||
reason,
|
||||
|
@ -36,7 +36,7 @@ class TrustRestAlarmNotifier(rest.RestAlarmNotifier):
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def notify(action, alarm_id, alarm_name, previous, current,
|
||||
def notify(action, alarm_id, alarm_name, severity, previous, current,
|
||||
reason, reason_data):
|
||||
trust_id = action.username
|
||||
|
||||
@ -62,5 +62,5 @@ class TrustRestAlarmNotifier(rest.RestAlarmNotifier):
|
||||
|
||||
headers = {'X-Auth-Token': client.auth_token}
|
||||
rest.RestAlarmNotifier.notify(
|
||||
action, alarm_id, alarm_name, previous, current, reason,
|
||||
action, alarm_id, alarm_name, severity, previous, current, reason,
|
||||
reason_data, headers)
|
||||
|
@ -65,6 +65,7 @@ class RPCAlarmNotifier(object):
|
||||
'actions': actions,
|
||||
'alarm_id': alarm.alarm_id,
|
||||
'alarm_name': alarm.name,
|
||||
'severity': alarm.severity,
|
||||
'previous': previous,
|
||||
'current': alarm.state,
|
||||
'reason': six.text_type(reason),
|
||||
|
@ -243,8 +243,8 @@ class AlarmNotifierService(os_service.Service):
|
||||
self.rpc_server.stop()
|
||||
super(AlarmNotifierService, self).stop()
|
||||
|
||||
def _handle_action(self, action, alarm_id, alarm_name, previous,
|
||||
current, reason, reason_data):
|
||||
def _handle_action(self, action, alarm_id, alarm_name, severity,
|
||||
previous, current, reason, reason_data):
|
||||
try:
|
||||
action = netutils.urlsplit(action)
|
||||
except Exception:
|
||||
@ -266,8 +266,8 @@ class AlarmNotifierService(os_service.Service):
|
||||
try:
|
||||
LOG.debug(_("Notifying alarm %(id)s with action %(act)s") % (
|
||||
{'id': alarm_id, 'act': action}))
|
||||
notifier.notify(action, alarm_id, alarm_name, previous,
|
||||
current, reason, reason_data)
|
||||
notifier.notify(action, alarm_id, alarm_name, severity,
|
||||
previous, current, reason, reason_data)
|
||||
except Exception:
|
||||
LOG.exception(_("Unable to notify alarm %s"), alarm_id)
|
||||
return
|
||||
@ -282,6 +282,7 @@ class AlarmNotifierService(os_service.Service):
|
||||
extensions automatically
|
||||
- alarm_id, the ID of the alarm that has been triggered
|
||||
- alarm_name, the name of the alarm that has been triggered
|
||||
- severity, the level of the alarm that has been triggered
|
||||
- previous, the previous state of the alarm
|
||||
- current, the new state the alarm has transitioned to
|
||||
- reason, the reason the alarm changed its state
|
||||
@ -296,6 +297,7 @@ class AlarmNotifierService(os_service.Service):
|
||||
self._handle_action(action,
|
||||
data.get('alarm_id'),
|
||||
data.get('alarm_name'),
|
||||
data.get('severity'),
|
||||
data.get('previous'),
|
||||
data.get('current'),
|
||||
data.get('reason'),
|
||||
|
@ -42,7 +42,7 @@ class Connection(object):
|
||||
@staticmethod
|
||||
def get_alarms(name=None, user=None, state=None, meter=None,
|
||||
project=None, enabled=None, alarm_id=None, pagination=None,
|
||||
alarm_type=None):
|
||||
alarm_type=None, severity=None):
|
||||
"""Yields a lists of alarms that match filters.
|
||||
|
||||
:param name: Optional name for alarm.
|
||||
@ -54,6 +54,7 @@ class Connection(object):
|
||||
:param alarm_id: Optional alarm_id to return one alarm.
|
||||
:param pagination: Optional pagination query.
|
||||
:param alarm_type: Optional alarm type.
|
||||
:parmr severity: Optional alarm severity
|
||||
"""
|
||||
raise ceilometer.NotImplementedError('Alarms not implemented')
|
||||
|
||||
@ -78,8 +79,9 @@ class Connection(object):
|
||||
@staticmethod
|
||||
def get_alarm_changes(alarm_id, on_behalf_of,
|
||||
user=None, project=None, alarm_type=None,
|
||||
start_timestamp=None, start_timestamp_op=None,
|
||||
end_timestamp=None, end_timestamp_op=None):
|
||||
severity=None, start_timestamp=None,
|
||||
start_timestamp_op=None, end_timestamp=None,
|
||||
end_timestamp_op=None):
|
||||
"""Yields list of AlarmChanges describing alarm history
|
||||
|
||||
Changes are always sorted in reverse order of occurrence, given
|
||||
@ -98,6 +100,7 @@ class Connection(object):
|
||||
:param user: Optional ID of user to return changes for
|
||||
:param project: Optional ID of project to return changes for
|
||||
:param alarm_type: Optional change type
|
||||
:param severity: Optional change severity
|
||||
:param start_timestamp: Optional modified timestamp start range
|
||||
:param start_timestamp_op: Optional timestamp start range operation
|
||||
:param end_timestamp: Optional modified timestamp end range
|
||||
|
@ -120,7 +120,7 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
|
||||
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
||||
project=None, enabled=None, alarm_id=None, pagination=None,
|
||||
alarm_type=None):
|
||||
alarm_type=None, severity=None):
|
||||
|
||||
if pagination:
|
||||
raise ceilometer.NotImplementedError('Pagination not implemented')
|
||||
@ -131,7 +131,7 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
q = hbase_utils.make_query(alarm_id=alarm_id, name=name,
|
||||
enabled=enabled, user_id=user,
|
||||
project_id=project, state=state,
|
||||
type=alarm_type)
|
||||
type=alarm_type, severity=severity)
|
||||
|
||||
with self.conn_pool.connection() as conn:
|
||||
alarm_table = conn.table(self.ALARM_TABLE)
|
||||
@ -146,11 +146,13 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
|
||||
def get_alarm_changes(self, alarm_id, on_behalf_of,
|
||||
user=None, project=None, alarm_type=None,
|
||||
start_timestamp=None, start_timestamp_op=None,
|
||||
end_timestamp=None, end_timestamp_op=None):
|
||||
severity=None, start_timestamp=None,
|
||||
start_timestamp_op=None, end_timestamp=None,
|
||||
end_timestamp_op=None):
|
||||
q = hbase_utils.make_query(alarm_id=alarm_id,
|
||||
on_behalf_of=on_behalf_of, type=alarm_type,
|
||||
user_id=user, project_id=project)
|
||||
user_id=user, project_id=project,
|
||||
severity=severity)
|
||||
start_row, end_row = hbase_utils.make_timestamp_query(
|
||||
hbase_utils.make_general_rowkey_scan,
|
||||
start=start_timestamp, start_op=start_timestamp_op,
|
||||
|
@ -32,7 +32,7 @@ class Connection(base.Connection):
|
||||
|
||||
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
||||
project=None, enabled=None, alarm_id=None, pagination=None,
|
||||
alarm_type=None):
|
||||
alarm_type=None, severity=None):
|
||||
"""Yields a lists of alarms that match filters."""
|
||||
return []
|
||||
|
||||
|
@ -132,14 +132,15 @@ class Connection(base.Connection):
|
||||
row.insufficient_data_actions),
|
||||
rule=row.rule,
|
||||
time_constraints=row.time_constraints,
|
||||
repeat_actions=row.repeat_actions)
|
||||
repeat_actions=row.repeat_actions,
|
||||
severity=row.severity)
|
||||
|
||||
def _retrieve_alarms(self, query):
|
||||
return (self._row_to_alarm_model(x) for x in query.all())
|
||||
|
||||
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
||||
project=None, enabled=None, alarm_id=None, pagination=None,
|
||||
alarm_type=None):
|
||||
alarm_type=None, severity=None):
|
||||
"""Yields a lists of alarms that match filters.
|
||||
|
||||
:param name: Optional name for alarm.
|
||||
@ -151,6 +152,7 @@ class Connection(base.Connection):
|
||||
:param alarm_id: Optional alarm_id to return one alarm.
|
||||
:param pagination: Optional pagination query.
|
||||
:param alarm_type: Optional alarm type.
|
||||
:param severity: Optional alarm severity
|
||||
"""
|
||||
|
||||
if pagination:
|
||||
@ -172,6 +174,8 @@ class Connection(base.Connection):
|
||||
query = query.filter(models.Alarm.state == state)
|
||||
if alarm_type is not None:
|
||||
query = query.filter(models.Alarm.type == alarm_type)
|
||||
if severity is not None:
|
||||
query = query.filter(models.Alarm.severity == severity)
|
||||
|
||||
query = query.order_by(desc(models.Alarm.timestamp))
|
||||
alarms = self._retrieve_alarms(query)
|
||||
@ -246,8 +250,9 @@ class Connection(base.Connection):
|
||||
|
||||
def get_alarm_changes(self, alarm_id, on_behalf_of,
|
||||
user=None, project=None, alarm_type=None,
|
||||
start_timestamp=None, start_timestamp_op=None,
|
||||
end_timestamp=None, end_timestamp_op=None):
|
||||
severity=None, start_timestamp=None,
|
||||
start_timestamp_op=None, end_timestamp=None,
|
||||
end_timestamp_op=None):
|
||||
"""Yields list of AlarmChanges describing alarm history
|
||||
|
||||
Changes are always sorted in reverse order of occurrence, given
|
||||
@ -266,6 +271,7 @@ class Connection(base.Connection):
|
||||
:param user: Optional ID of user to return changes for
|
||||
:param project: Optional ID of project to return changes for
|
||||
:param alarm_type: Optional change type
|
||||
:param severity: Optional alarm severity
|
||||
:param start_timestamp: Optional modified timestamp start range
|
||||
:param start_timestamp_op: Optional timestamp start range operation
|
||||
:param end_timestamp: Optional modified timestamp end range
|
||||
@ -284,6 +290,8 @@ class Connection(base.Connection):
|
||||
query = query.filter(models.AlarmChange.project_id == project)
|
||||
if alarm_type is not None:
|
||||
query = query.filter(models.AlarmChange.type == alarm_type)
|
||||
if severity is not None:
|
||||
query = query.filter(models.AlarmChange.severity == severity)
|
||||
if start_timestamp:
|
||||
if start_timestamp_op == 'gt':
|
||||
query = query.filter(
|
||||
|
@ -32,6 +32,10 @@ class Alarm(base.Model):
|
||||
ALARM_ALARM: 'alarm_actions',
|
||||
}
|
||||
|
||||
ALARM_LEVEL_LOW = 'low'
|
||||
ALARM_LEVEL_MODERATE = 'moderate'
|
||||
ALARM_LEVEL_CRITICAL = 'critical'
|
||||
|
||||
"""
|
||||
An alarm to monitor.
|
||||
|
||||
@ -56,16 +60,16 @@ class Alarm(base.Model):
|
||||
entering the insufficient data state
|
||||
:param repeat_actions: Is the actions should be triggered on each
|
||||
alarm evaluation.
|
||||
:param severity: Alarm level (low/moderate/critical)
|
||||
"""
|
||||
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):
|
||||
repeat_actions, rule, time_constraints, severity=None):
|
||||
if not isinstance(timestamp, datetime.datetime):
|
||||
raise TypeError(_("timestamp should be datetime object"))
|
||||
if not isinstance(state_timestamp, datetime.datetime):
|
||||
raise TypeError(_("state_timestamp should be datetime object"))
|
||||
|
||||
base.Model.__init__(
|
||||
self,
|
||||
alarm_id=alarm_id,
|
||||
@ -83,7 +87,8 @@ class Alarm(base.Model):
|
||||
insufficient_data_actions=insufficient_data_actions,
|
||||
repeat_actions=repeat_actions,
|
||||
rule=rule,
|
||||
time_constraints=time_constraints)
|
||||
time_constraints=time_constraints,
|
||||
severity=severity)
|
||||
|
||||
|
||||
class AlarmChange(base.Model):
|
||||
@ -92,6 +97,7 @@ class AlarmChange(base.Model):
|
||||
:param event_id: UUID of the change event
|
||||
:param alarm_id: UUID of the alarm
|
||||
:param type: The type of change
|
||||
:param severity: The severity of alarm
|
||||
: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
|
||||
@ -113,6 +119,7 @@ class AlarmChange(base.Model):
|
||||
user_id,
|
||||
project_id,
|
||||
on_behalf_of,
|
||||
severity=None,
|
||||
timestamp=None
|
||||
):
|
||||
base.Model.__init__(
|
||||
@ -120,6 +127,7 @@ class AlarmChange(base.Model):
|
||||
event_id=event_id,
|
||||
alarm_id=alarm_id,
|
||||
type=type,
|
||||
severity=severity,
|
||||
detail=detail,
|
||||
user_id=user_id,
|
||||
project_id=project_id,
|
||||
|
@ -81,7 +81,7 @@ class Connection(base.Connection):
|
||||
|
||||
def get_alarms(self, name=None, user=None, state=None, meter=None,
|
||||
project=None, enabled=None, alarm_id=None, pagination=None,
|
||||
alarm_type=None):
|
||||
alarm_type=None, severity=None):
|
||||
"""Yields a lists of alarms that match filters.
|
||||
|
||||
:param name: Optional name for alarm.
|
||||
@ -93,6 +93,7 @@ class Connection(base.Connection):
|
||||
:param alarm_id: Optional alarm_id to return one alarm.
|
||||
:param pagination: Optional pagination query.
|
||||
:param alarm_type: Optional alarm type.
|
||||
:param severity: Optional alarm severity.
|
||||
"""
|
||||
if pagination:
|
||||
raise ceilometer.NotImplementedError('Pagination not implemented')
|
||||
@ -114,6 +115,8 @@ class Connection(base.Connection):
|
||||
q['rule.meter_name'] = meter
|
||||
if alarm_type is not None:
|
||||
q['type'] = alarm_type
|
||||
if severity is not None:
|
||||
q['severity'] = severity
|
||||
|
||||
return self._retrieve_alarms(q,
|
||||
[("timestamp",
|
||||
@ -122,8 +125,9 @@ class Connection(base.Connection):
|
||||
|
||||
def get_alarm_changes(self, alarm_id, on_behalf_of,
|
||||
user=None, project=None, alarm_type=None,
|
||||
start_timestamp=None, start_timestamp_op=None,
|
||||
end_timestamp=None, end_timestamp_op=None):
|
||||
severity=None, start_timestamp=None,
|
||||
start_timestamp_op=None, end_timestamp=None,
|
||||
end_timestamp_op=None):
|
||||
"""Yields list of AlarmChanges describing alarm history
|
||||
|
||||
Changes are always sorted in reverse order of occurrence, given
|
||||
@ -142,6 +146,7 @@ class Connection(base.Connection):
|
||||
:param user: Optional ID of user to return changes for
|
||||
:param project: Optional ID of project to return changes for
|
||||
:param alarm_type: Optional change type
|
||||
:param severity: Optional change severity
|
||||
:param start_timestamp: Optional modified timestamp start range
|
||||
:param start_timestamp_op: Optional timestamp start range operation
|
||||
:param end_timestamp: Optional modified timestamp end range
|
||||
@ -156,6 +161,8 @@ class Connection(base.Connection):
|
||||
q['project_id'] = project
|
||||
if alarm_type is not None:
|
||||
q['type'] = alarm_type
|
||||
if severity is not None:
|
||||
q['severity'] = severity
|
||||
if start_timestamp or end_timestamp:
|
||||
ts_range = pymongo_utils.make_timestamp_range(start_timestamp,
|
||||
end_timestamp,
|
||||
|
@ -86,6 +86,8 @@ state_kind = ["ok", "alarm", "insufficient data"]
|
||||
state_kind_enum = wtypes.Enum(str, *state_kind)
|
||||
operation_kind = ('lt', 'le', 'eq', 'ne', 'ge', 'gt')
|
||||
operation_kind_enum = wtypes.Enum(str, *operation_kind)
|
||||
severity_kind = ["low", "moderate", "critical"]
|
||||
severity_kind_enum = wtypes.Enum(str, *severity_kind)
|
||||
|
||||
|
||||
class ClientSideError(wsme.exc.ClientSideError):
|
||||
@ -1832,6 +1834,10 @@ class Alarm(_Base):
|
||||
state_timestamp = datetime.datetime
|
||||
"The date of the last alarm state changed"
|
||||
|
||||
severity = AdvEnum('severity', str, *severity_kind,
|
||||
default='low')
|
||||
"The severity of the alarm"
|
||||
|
||||
def __init__(self, rule=None, time_constraints=None, **kwargs):
|
||||
super(Alarm, self).__init__(**kwargs)
|
||||
|
||||
@ -1920,6 +1926,7 @@ class Alarm(_Base):
|
||||
enabled=True,
|
||||
timestamp=datetime.datetime.utcnow(),
|
||||
state="ok",
|
||||
severity="moderate",
|
||||
state_timestamp=datetime.datetime.utcnow(),
|
||||
ok_actions=["http://site:8000/ok"],
|
||||
alarm_actions=["http://site:8000/alarm"],
|
||||
@ -2051,6 +2058,7 @@ class AlarmController(rest.RestController):
|
||||
now = timeutils.utcnow()
|
||||
|
||||
data.alarm_id = self._id
|
||||
|
||||
user, project = rbac.get_limited_to(pecan.request.headers)
|
||||
if user:
|
||||
data.user_id = user
|
||||
@ -2065,7 +2073,7 @@ class AlarmController(rest.RestController):
|
||||
data.state_timestamp = now
|
||||
else:
|
||||
data.state_timestamp = alarm_in.state_timestamp
|
||||
|
||||
alarm_in.severity = data.severity
|
||||
# make sure alarms are unique by name per project.
|
||||
if alarm_in.name != data.name:
|
||||
alarms = list(self.conn.get_alarms(name=data.name,
|
||||
|
@ -0,0 +1,31 @@
|
||||
#
|
||||
# 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.
|
||||
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Table
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData(bind=migrate_engine)
|
||||
alarm = Table('alarm', meta, autoload=True)
|
||||
severity = Column('severity', String(50))
|
||||
alarm.create_column(severity)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData(bind=migrate_engine)
|
||||
alarm = Table('alarm', meta, autoload=True)
|
||||
severity = Column('severity', String(50))
|
||||
alarm.drop_column(severity)
|
@ -259,6 +259,7 @@ class Alarm(Base):
|
||||
enabled = Column(Boolean)
|
||||
name = Column(Text)
|
||||
type = Column(String(50))
|
||||
severity = Column(String(50))
|
||||
description = Column(Text)
|
||||
timestamp = Column(PreciseTimestamp, default=lambda: timeutils.utcnow())
|
||||
|
||||
|
@ -58,7 +58,8 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
'9cfc3e51-2ff1-4b1d-ac01-c1bd4c6d0d1e',
|
||||
'1d441595-d069-4e05-95ab-8693ba6a8302'],
|
||||
operator='or',
|
||||
)),
|
||||
),
|
||||
severity='critical'),
|
||||
models.Alarm(name='and-alarm',
|
||||
description='the and alarm',
|
||||
type='combination',
|
||||
@ -79,7 +80,8 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
'b82734f4-9d06-48f3-8a86-fa59a0c99dc8',
|
||||
'15a700e5-2fe8-4b3d-8c55-9e92831f6a2b'],
|
||||
operator='and',
|
||||
))
|
||||
),
|
||||
severity='critical')
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
|
@ -63,7 +63,8 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
'value': 'cpu_util'},
|
||||
{'field': 'resource_id',
|
||||
'op': 'eq',
|
||||
'value': 'my_instance'}])
|
||||
'value': 'my_instance'}]),
|
||||
severity='critical'
|
||||
),
|
||||
models.Alarm(name='group_running_idle',
|
||||
description='group_running_idle',
|
||||
@ -92,7 +93,8 @@ class TestEvaluate(base.TestEvaluatorBase):
|
||||
'value': 'cpu_util'},
|
||||
{'field': 'metadata.user_metadata.AS',
|
||||
'op': 'eq',
|
||||
'value': 'my_group'}])
|
||||
'value': 'my_group'}]),
|
||||
severity='critical'
|
||||
),
|
||||
]
|
||||
|
||||
|
@ -121,6 +121,7 @@ class TestCoordinate(tests_base.BaseTestCase):
|
||||
alarm_actions=[],
|
||||
insufficient_data_actions=[],
|
||||
alarm_id=uuid,
|
||||
severity='critical',
|
||||
time_constraints=[],
|
||||
rule=dict(
|
||||
statistic='avg',
|
||||
|
@ -28,11 +28,12 @@ from ceilometer.tests import base as tests_base
|
||||
|
||||
DATA_JSON = jsonutils.loads(
|
||||
'{"current": "ALARM", "alarm_id": "foobar", "alarm_name": "testalarm",'
|
||||
' "reason": "what ?", "reason_data": {"test": "test"},'
|
||||
' "previous": "OK"}'
|
||||
' "severity": "critical", "reason": "what ?",'
|
||||
' "reason_data": {"test": "test"}, "previous": "OK"}'
|
||||
)
|
||||
NOTIFICATION = dict(alarm_id='foobar',
|
||||
alarm_name='testalarm',
|
||||
severity='critical',
|
||||
condition=dict(threshold=42),
|
||||
reason='what ?',
|
||||
reason_data={'test': 'test'},
|
||||
@ -64,6 +65,7 @@ class TestAlarmNotifier(tests_base.BaseTestCase):
|
||||
'actions': ['test://'],
|
||||
'alarm_id': 'foobar',
|
||||
'alarm_name': 'testalarm',
|
||||
'severity': 'critical',
|
||||
'previous': 'OK',
|
||||
'current': 'ALARM',
|
||||
'reason': 'Everything is on fire',
|
||||
@ -75,6 +77,7 @@ class TestAlarmNotifier(tests_base.BaseTestCase):
|
||||
self.assertEqual((urlparse.urlsplit(data['actions'][0]),
|
||||
data['alarm_id'],
|
||||
data['alarm_name'],
|
||||
data['severity'],
|
||||
data['previous'],
|
||||
data['current'],
|
||||
data['reason'],
|
||||
|
@ -67,6 +67,7 @@ class TestRPCAlarmNotifier(tests_base.BaseTestCase):
|
||||
'project_id': 'snafu',
|
||||
'period': 60,
|
||||
'alarm_id': str(uuid.uuid4()),
|
||||
'severity': 'critical',
|
||||
'matching_metadata':{'resource_id':
|
||||
'my_instance'}
|
||||
}),
|
||||
@ -83,6 +84,7 @@ class TestRPCAlarmNotifier(tests_base.BaseTestCase):
|
||||
'project_id': 'snafu',
|
||||
'period': 300,
|
||||
'alarm_id': str(uuid.uuid4()),
|
||||
'severity': 'critical',
|
||||
'matching_metadata':{'metadata.user_metadata.AS':
|
||||
'my_group'}
|
||||
}),
|
||||
@ -109,6 +111,8 @@ class TestRPCAlarmNotifier(tests_base.BaseTestCase):
|
||||
self.notifier_server.notified[i]["alarm_id"])
|
||||
self.assertEqual(self.alarms[i].name,
|
||||
self.notifier_server.notified[i]["alarm_name"])
|
||||
self.assertEqual(self.alarms[i].severity,
|
||||
self.notifier_server.notified[i]["severity"])
|
||||
self.assertEqual(actions,
|
||||
self.notifier_server.notified[i]["actions"])
|
||||
self.assertEqual(previous[i],
|
||||
|
@ -52,6 +52,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
alarm_id='a',
|
||||
description='a',
|
||||
state='insufficient data',
|
||||
severity='critical',
|
||||
state_timestamp=constants.MIN_DATETIME,
|
||||
timestamp=constants.MIN_DATETIME,
|
||||
ok_actions=[],
|
||||
@ -72,7 +73,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
query=[{'field': 'project_id',
|
||||
'op': 'eq', 'value':
|
||||
self.auth_headers['X-Project-Id']}
|
||||
])
|
||||
]),
|
||||
),
|
||||
models.Alarm(name='name2',
|
||||
type='threshold',
|
||||
@ -80,6 +81,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
alarm_id='b',
|
||||
description='b',
|
||||
state='insufficient data',
|
||||
severity='critical',
|
||||
state_timestamp=constants.MIN_DATETIME,
|
||||
timestamp=constants.MIN_DATETIME,
|
||||
ok_actions=[],
|
||||
@ -98,7 +100,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
query=[{'field': 'project_id',
|
||||
'op': 'eq', 'value':
|
||||
self.auth_headers['X-Project-Id']}
|
||||
])
|
||||
]),
|
||||
),
|
||||
models.Alarm(name='name3',
|
||||
type='threshold',
|
||||
@ -106,6 +108,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
alarm_id='c',
|
||||
description='c',
|
||||
state='insufficient data',
|
||||
severity='moderate',
|
||||
state_timestamp=constants.MIN_DATETIME,
|
||||
timestamp=constants.MIN_DATETIME,
|
||||
ok_actions=[],
|
||||
@ -124,7 +127,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
query=[{'field': 'project_id',
|
||||
'op': 'eq', 'value':
|
||||
self.auth_headers['X-Project-Id']}
|
||||
])
|
||||
]),
|
||||
),
|
||||
models.Alarm(name='name4',
|
||||
type='combination',
|
||||
@ -132,6 +135,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
alarm_id='d',
|
||||
description='d',
|
||||
state='insufficient data',
|
||||
severity='low',
|
||||
state_timestamp=constants.MIN_DATETIME,
|
||||
timestamp=constants.MIN_DATETIME,
|
||||
ok_actions=[],
|
||||
@ -142,7 +146,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
project_id=self.auth_headers['X-Project-Id'],
|
||||
time_constraints=[],
|
||||
rule=dict(alarm_ids=['a', 'b'],
|
||||
operator='or')
|
||||
operator='or'),
|
||||
)]:
|
||||
self.alarm_conn.update_alarm(alarm)
|
||||
|
||||
@ -218,7 +222,8 @@ class TestAlarms(v2.FunctionalTest,
|
||||
user_id=self.auth_headers['X-User-Id'],
|
||||
project_id=self.auth_headers['X-Project-Id'],
|
||||
time_constraints=[],
|
||||
rule=dict(alarm_ids=['a', 'b'], operator='or'))
|
||||
rule=dict(alarm_ids=['a', 'b'], operator='or'),
|
||||
severity='critical')
|
||||
self.alarm_conn.update_alarm(alarm)
|
||||
resp = self.get_json('/alarms',
|
||||
q=[{'field': 'state',
|
||||
@ -277,7 +282,8 @@ class TestAlarms(v2.FunctionalTest,
|
||||
user_id=self.auth_headers['X-User-Id'],
|
||||
project_id=self.auth_headers['X-Project-Id'],
|
||||
time_constraints=[],
|
||||
rule=dict(alarm_ids=['a', 'b'], operator='or'))
|
||||
rule=dict(alarm_ids=['a', 'b'], operator='or'),
|
||||
severity='critical')
|
||||
self.alarm_conn.update_alarm(alarm)
|
||||
|
||||
alarms = self.get_json('/alarms',
|
||||
@ -566,6 +572,27 @@ class TestAlarms(v2.FunctionalTest,
|
||||
alarms = list(self.alarm_conn.get_alarms())
|
||||
self.assertEqual(4, len(alarms))
|
||||
|
||||
def test_post_invalid_alarm_input_severity(self):
|
||||
json = {
|
||||
'name': 'alarm1',
|
||||
'state': 'ok',
|
||||
'severity': 'bad_value',
|
||||
'type': 'threshold',
|
||||
'threshold_rule': {
|
||||
'meter_name': 'ameter',
|
||||
'comparison_operator': 'gt',
|
||||
'threshold': 50.0
|
||||
}
|
||||
}
|
||||
resp = self.post_json('/alarms', params=json, expect_errors=True,
|
||||
status=400, headers=self.auth_headers)
|
||||
expected_err_msg = ("Invalid input for field/attribute severity."
|
||||
" Value: 'bad_value'.")
|
||||
self.assertIn(expected_err_msg,
|
||||
resp.json['error_message']['faultstring'])
|
||||
alarms = list(self.alarm_conn.get_alarms())
|
||||
self.assertEqual(4, len(alarms))
|
||||
|
||||
def test_post_invalid_alarm_input_comparison_operator(self):
|
||||
json = {
|
||||
'name': 'alarm2',
|
||||
@ -924,6 +951,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'added_alarm',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'low',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -971,6 +999,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'added_alarm',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'low',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -1539,6 +1568,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'name_put',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'critical',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -1581,6 +1611,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'name_put',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'critical',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -1630,6 +1661,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'name1',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'critical',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -1666,6 +1698,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'name1',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'critical',
|
||||
'ok_actions': ['http://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -1704,6 +1737,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
'name': 'name1',
|
||||
'state': 'ok',
|
||||
'type': 'threshold',
|
||||
'severity': 'critical',
|
||||
'ok_actions': ['spam://something/ok'],
|
||||
'alarm_actions': ['http://something/alarm'],
|
||||
'insufficient_data_actions': ['http://something/no'],
|
||||
@ -2154,10 +2188,11 @@ class TestAlarms(v2.FunctionalTest,
|
||||
query = dict(field='alarm_id', op='eq', value='b')
|
||||
resp = self._get_alarm_history(alarm, query=query,
|
||||
expect_errors=True, status=400)
|
||||
self.assertEqual('Unknown argument: "alarm_id": unrecognized'
|
||||
self.assertEqual(u'Unknown argument: "alarm_id": unrecognized'
|
||||
" field in query: [<Query u'alarm_id' eq"
|
||||
" u'b' Unset>], valid keys: ['project', "
|
||||
"'search_offset', 'timestamp', 'type', 'user']",
|
||||
"'search_offset', 'severity', 'timestamp',"
|
||||
" 'type', 'user']",
|
||||
resp.json['error_message']['faultstring'])
|
||||
|
||||
def test_get_alarm_history_constrained_by_not_supported_rule(self):
|
||||
@ -2165,10 +2200,11 @@ class TestAlarms(v2.FunctionalTest,
|
||||
query = dict(field='abcd', op='eq', value='abcd')
|
||||
resp = self._get_alarm_history(alarm, query=query,
|
||||
expect_errors=True, status=400)
|
||||
self.assertEqual('Unknown argument: "abcd": unrecognized'
|
||||
self.assertEqual(u'Unknown argument: "abcd": unrecognized'
|
||||
" field in query: [<Query u'abcd' eq"
|
||||
" u'abcd' Unset>], valid keys: ['project', "
|
||||
"'search_offset', 'timestamp', 'type', 'user']",
|
||||
"'search_offset', 'severity', 'timestamp',"
|
||||
" 'type', 'user']",
|
||||
resp.json['error_message']['faultstring'])
|
||||
|
||||
def test_get_nonexistent_alarm_history(self):
|
||||
@ -2182,6 +2218,7 @@ class TestAlarms(v2.FunctionalTest,
|
||||
json = {
|
||||
'name': 'sent_notification',
|
||||
'type': 'threshold',
|
||||
'severity': 'low',
|
||||
'threshold_rule': {
|
||||
'meter_name': 'ameter',
|
||||
'comparison_operator': 'gt',
|
||||
|
@ -351,7 +351,8 @@ class TestQueryAlarmsController(tests_api.FunctionalTest,
|
||||
'project_id',
|
||||
'op': 'eq',
|
||||
'value':
|
||||
project_id}]))
|
||||
project_id}]),
|
||||
severity='critical')
|
||||
self.alarm_conn.update_alarm(alarm)
|
||||
|
||||
def test_query_all(self):
|
||||
|
@ -345,7 +345,7 @@ class TestQueryToKwArgs(tests_base.BaseTestCase):
|
||||
api._query_to_kwargs, q,
|
||||
alarm_storage_base.Connection.get_alarm_changes)
|
||||
valid_keys = ['alarm_id', 'on_behalf_of', 'project', 'search_offset',
|
||||
'timestamp', 'type', 'user']
|
||||
'severity', 'timestamp', 'type', 'user']
|
||||
msg = ("unrecognized field in query: %s, "
|
||||
"valid keys: %s") % (q, valid_keys)
|
||||
expected_exc = wsme.exc.UnknownArgument('abc', msg)
|
||||
@ -402,7 +402,7 @@ class TestQueryToKwArgs(tests_base.BaseTestCase):
|
||||
wsme.exc.UnknownArgument,
|
||||
api._query_to_kwargs, q, alarm_storage_base.Connection.get_alarms)
|
||||
valid_keys = ['alarm_id', 'enabled', 'meter', 'name', 'pagination',
|
||||
'project', 'state', 'type', 'user']
|
||||
'project', 'severity', 'state', 'type', 'user']
|
||||
msg = ("unrecognized field in query: %s, "
|
||||
"valid keys: %s") % (q, valid_keys)
|
||||
expected_exc = wsme.exc.UnknownArgument('abc', msg)
|
||||
|
@ -75,15 +75,15 @@ class ModelTest(testbase.BaseTestCase):
|
||||
"timestamp", "user_id", "project_id", "state",
|
||||
"state_timestamp", "ok_actions", "alarm_actions",
|
||||
"insufficient_data_actions", "repeat_actions", "rule",
|
||||
"time_constraints"]
|
||||
"severity", "time_constraints"]
|
||||
|
||||
self.assertEqual(set(alarm_fields),
|
||||
set(alarm_models.Alarm.get_field_names()))
|
||||
|
||||
def test_get_field_names_of_alarmchange(self):
|
||||
alarmchange_fields = ["event_id", "alarm_id", "type", "detail",
|
||||
"user_id", "project_id", "on_behalf_of",
|
||||
"timestamp"]
|
||||
"user_id", "project_id", "severity",
|
||||
"on_behalf_of", "timestamp"]
|
||||
|
||||
self.assertEqual(set(alarmchange_fields),
|
||||
set(alarm_models.AlarmChange.get_field_names()))
|
||||
|
Loading…
Reference in New Issue
Block a user