Add client support for updating alarms.
Change-Id: I2a368f536ec440387d32a8076a86d143b94d7c90
This commit is contained in:
@@ -72,7 +72,7 @@ class Manager(object):
|
||||
resp, body = self.api.json_request('PUT', url, body=body)
|
||||
# PUT requests may not return a body
|
||||
if body:
|
||||
return self.resource_class(self, body[response_key])
|
||||
return self.resource_class(self, body)
|
||||
|
||||
|
||||
class Resource(object):
|
||||
|
||||
@@ -20,6 +20,22 @@ from ceilometerclient.common import base
|
||||
from ceilometerclient.v2 import options
|
||||
|
||||
|
||||
UPDATABLE_ATTRIBUTES = [
|
||||
'description',
|
||||
'period',
|
||||
'evaluation_periods',
|
||||
'state',
|
||||
'enabled',
|
||||
'counter_name',
|
||||
'statistic',
|
||||
'comparison_operator',
|
||||
'threshold',
|
||||
'alarm_actions',
|
||||
'ok_actions',
|
||||
'insufficient_data_actions',
|
||||
]
|
||||
|
||||
|
||||
class Alarm(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Alarm %s>" % self._info
|
||||
@@ -41,5 +57,13 @@ class AlarmManager(base.Manager):
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def update(self, alarm_id, **kwargs):
|
||||
existing = self.get(alarm_id)
|
||||
updated = existing.to_dict()
|
||||
for (key, value) in kwargs.items():
|
||||
if key in updated and key in UPDATABLE_ATTRIBUTES:
|
||||
updated[key] = value
|
||||
return self._update(self._path(alarm_id), updated)
|
||||
|
||||
def delete(self, alarm_id):
|
||||
return self._delete(self._path(alarm_id))
|
||||
|
||||
@@ -21,6 +21,11 @@ from ceilometerclient import exc
|
||||
from ceilometerclient.v2 import options
|
||||
|
||||
|
||||
ALARM_STATES = ['ok', 'alarm', 'insufficient_data']
|
||||
ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt']
|
||||
STATISTICS = ['max', 'min', 'avg', 'sum', 'count']
|
||||
|
||||
|
||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||
help='key[op]value; list.')
|
||||
@utils.arg('-m', '--meter', metavar='<NAME>',
|
||||
@@ -98,6 +103,15 @@ def do_alarm_list(cc, args={}):
|
||||
sortby=0)
|
||||
|
||||
|
||||
def _display_alarm(alarm):
|
||||
fields = ['name', 'description', 'counter_name', 'period',
|
||||
'evaluation_periods', 'threshold', 'comparison_operator',
|
||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
||||
'alarm_actions', 'ok_actions', 'insufficient_data_actions']
|
||||
data = dict([(f, getattr(alarm, f, '')) for f in fields])
|
||||
utils.print_dict(data, wrap=72)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>',
|
||||
help='ID of the alarm to show.')
|
||||
def do_alarm_show(cc, args={}):
|
||||
@@ -105,16 +119,51 @@ def do_alarm_show(cc, args={}):
|
||||
if args.alarm_id is None:
|
||||
raise exc.CommandError('Alarm ID not provided (-a <alarm id>)')
|
||||
try:
|
||||
resource = cc.alarms.get(args.alarm_id)
|
||||
alarm = cc.alarms.get(args.alarm_id)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
else:
|
||||
fields = ['name', 'description', 'counter_name', 'period',
|
||||
'evaluation_periods', 'threshold', 'comparison_operator',
|
||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
||||
'alarm_actions', 'ok_actions', 'insufficient_data_actions']
|
||||
data = dict([(f, getattr(resource, f, '')) for f in fields])
|
||||
utils.print_dict(data, wrap=72)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>',
|
||||
help='ID of the alarm to update.')
|
||||
@utils.arg('--description', metavar='<DESCRIPTION>',
|
||||
help='Free text description of the alarm')
|
||||
@utils.arg('--period', type=int, metavar='<PERIOD>',
|
||||
help='Length of each period (seconds) to evaluate over')
|
||||
@utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
|
||||
help='Number of periods to evaluate over')
|
||||
@utils.arg('--state', metavar='<STATE>',
|
||||
help='State of the alarm, one of: ' + str(ALARM_STATES))
|
||||
@utils.arg('--enabled', type=utils.string_to_bool, metavar='{True|False}',
|
||||
help='True if alarm evaluation/actioning is enabled')
|
||||
@utils.arg('--counter-name', metavar='<METRIC>',
|
||||
help='Metric to evaluate against')
|
||||
@utils.arg('--statistic', metavar='<STATISTIC>',
|
||||
help='Statistic to evaluate, one of: ' + str(STATISTICS))
|
||||
@utils.arg('--comparison-operator', metavar='<OPERATOR>',
|
||||
help='Operator to compare with, one of: ' + str(ALARM_OPERATORS))
|
||||
@utils.arg('--threshold', type=float, metavar='<THRESHOLD>',
|
||||
help='Threshold to evaluate against')
|
||||
@utils.arg('--alarm-action', dest='alarm_actions',
|
||||
metavar='<Webhook URL>', action='append', default=None,
|
||||
help=('URL to invoke when state transitions to alarm. '
|
||||
'May be used multiple times.'))
|
||||
@utils.arg('--ok-action', dest='ok_actions',
|
||||
metavar='<Webhook URL>', action='append', default=None,
|
||||
help=('URL to invoke when state transitions to OK. '
|
||||
'May be used multiple times.'))
|
||||
@utils.arg('--insufficient-data-action', dest='insufficient_data_actions',
|
||||
metavar='<Webhook URL>', action='append', default=None,
|
||||
help=('URL to invoke when state transitions to unkown. '
|
||||
'May be used multiple times.'))
|
||||
def do_alarm_update(cc, args={}):
|
||||
'''Update an existing alarm.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields.pop('alarm_id')
|
||||
alarm = cc.alarms.update(args.alarm_id, **fields)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>',
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import unittest
|
||||
|
||||
import ceilometerclient.v2.alarms
|
||||
@@ -41,6 +42,11 @@ AN_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'],
|
||||
u'state_timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'comparison_operator': 'gt',
|
||||
u'name': 'SwiftObjectAlarm'}
|
||||
DELTA_ALARM = {u'alarm_actions': ['url1', 'url2'],
|
||||
u'comparison_operator': u'lt',
|
||||
u'threshold': 42.1}
|
||||
UPDATED_ALARM = copy.deepcopy(AN_ALARM)
|
||||
UPDATED_ALARM.update(DELTA_ALARM)
|
||||
|
||||
fixtures = {
|
||||
'/v2/alarms':
|
||||
@@ -56,6 +62,10 @@ fixtures = {
|
||||
{},
|
||||
AN_ALARM,
|
||||
),
|
||||
'PUT': (
|
||||
{},
|
||||
UPDATED_ALARM,
|
||||
),
|
||||
},
|
||||
'/v2/alarms?q.op=&q.op=&q.value=project-id&q.value=SwiftObjectAlarm'
|
||||
'&q.field=project_id&q.field=name':
|
||||
@@ -116,6 +126,18 @@ class AlarmManagerTest(unittest.TestCase):
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
|
||||
def test_update(self):
|
||||
alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_ALARM)
|
||||
expect = [
|
||||
('GET', '/v2/alarms/alarm-id', {}, None),
|
||||
('PUT', '/v2/alarms/alarm-id', {}, UPDATED_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
for (key, value) in DELTA_ALARM.iteritems():
|
||||
self.assertEqual(getattr(alarm, key), value)
|
||||
|
||||
def test_delete(self):
|
||||
deleted = self.mgr.delete(alarm_id='victim-id')
|
||||
expect = [
|
||||
|
||||
Reference in New Issue
Block a user