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