Merge tag '1.0.5' into debian/unstable
python-ceilometerclient 1.0.5
This commit is contained in:
@@ -29,6 +29,7 @@ def _get_ksclient(**kwargs):
|
||||
tenant_id=kwargs.get('tenant_id'),
|
||||
tenant_name=kwargs.get('tenant_name'),
|
||||
auth_url=kwargs.get('auth_url'),
|
||||
region_name=kwargs.get('region_name'),
|
||||
insecure=kwargs.get('insecure'))
|
||||
|
||||
|
||||
@@ -68,6 +69,7 @@ def get_client(api_version, **kwargs):
|
||||
'tenant_id': kwargs.get('os_tenant_id'),
|
||||
'tenant_name': kwargs.get('os_tenant_name'),
|
||||
'auth_url': kwargs.get('os_auth_url'),
|
||||
'region_name': kwargs.get('os_region_name'),
|
||||
'service_type': kwargs.get('os_service_type'),
|
||||
'endpoint_type': kwargs.get('os_endpoint_type'),
|
||||
'insecure': kwargs.get('insecure'),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@@ -140,6 +140,17 @@ def args_array_to_dict(kwargs, key_to_convert):
|
||||
return kwargs
|
||||
|
||||
|
||||
def key_with_slash_to_nested_dict(kwargs):
|
||||
nested_kwargs = {}
|
||||
for k in kwargs.keys():
|
||||
keys = k.split('/', 1)
|
||||
if len(keys) == 2:
|
||||
nested_kwargs.setdefault(keys[0], {})[keys[1]] = kwargs[k]
|
||||
del kwargs[k]
|
||||
kwargs.update(nested_kwargs)
|
||||
return kwargs
|
||||
|
||||
|
||||
def exit(msg=''):
|
||||
if msg:
|
||||
print >> sys.stderr, msg
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2013 OpenStack LLC.
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@@ -57,3 +57,20 @@ class UtilsTest(test_utils.BaseTestCase):
|
||||
'matching_metadata': {'metadata.key': 'metadata_value'},
|
||||
'other': 'value'
|
||||
})
|
||||
|
||||
def test_key_with_slash_to_nested_dict(self):
|
||||
my_args = {
|
||||
'combination_rule/alarm_ids': ['id1', 'id2'],
|
||||
'combination_rule/operator': 'and',
|
||||
'threshold_rule/threshold': 400,
|
||||
'threshold_rule/statictic': 'avg',
|
||||
'threshold_rule/comparison_operator': 'or',
|
||||
}
|
||||
nested_dict = utils.key_with_slash_to_nested_dict(my_args)
|
||||
self.assertEqual(nested_dict, {
|
||||
'combination_rule': {'alarm_ids': ['id1', 'id2'],
|
||||
'operator': 'and'},
|
||||
'threshold_rule': {'threshold': 400,
|
||||
'statictic': 'avg',
|
||||
'comparison_operator': 'or'},
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -22,36 +22,91 @@ import testtools
|
||||
from ceilometerclient.tests import utils
|
||||
import ceilometerclient.v2.alarms
|
||||
|
||||
|
||||
AN_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'],
|
||||
u'ok_actions': [u'http://site:8000/ok'],
|
||||
u'description': u'An alarm',
|
||||
u'matching_metadata': {u'key_name': u'key_value'},
|
||||
u'evaluation_periods': 2,
|
||||
u'type': u'threshold',
|
||||
u'threshold_rule': {
|
||||
u'meter_name': u'storage.objects',
|
||||
u'query': [{u'field': u'key_name',
|
||||
u'op': u'eq',
|
||||
u'value': u'key_value'}],
|
||||
u'evaluation_periods': 2,
|
||||
u'period': 240.0,
|
||||
u'statistic': u'avg',
|
||||
u'threshold': 200.0,
|
||||
u'comparison_operator': 'gt',
|
||||
},
|
||||
u'timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'enabled': True,
|
||||
u'counter_name': u'storage.objects',
|
||||
u'period': 240.0,
|
||||
u'alarm_id': u'alarm-id',
|
||||
u'state': u'ok',
|
||||
u'insufficient_data_actions': [u'http://site:8000/nodata'],
|
||||
u'statistic': u'avg',
|
||||
u'threshold': 200.0,
|
||||
u'user_id': u'user-id',
|
||||
u'project_id': u'project-id',
|
||||
u'state_timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'comparison_operator': 'gt',
|
||||
u'repeat_actions': False,
|
||||
u'name': 'SwiftObjectAlarm'}
|
||||
CREATE_ALARM = copy.deepcopy(AN_ALARM)
|
||||
del CREATE_ALARM['timestamp']
|
||||
del CREATE_ALARM['state_timestamp']
|
||||
del CREATE_ALARM['alarm_id']
|
||||
DELTA_ALARM = {u'alarm_actions': ['url1', 'url2'],
|
||||
u'comparison_operator': u'lt',
|
||||
u'threshold': 42.1}
|
||||
DELTA_ALARM = {u'alarm_actions': ['url1', 'url2']}
|
||||
DELTA_ALARM_RULE = {u'comparison_operator': u'lt',
|
||||
u'threshold': 42.1,
|
||||
u'meter_name': u'foobar',
|
||||
u'query': [{u'field': u'key_name',
|
||||
u'op': u'eq',
|
||||
u'value': u'key_value'}]}
|
||||
UPDATED_ALARM = copy.deepcopy(AN_ALARM)
|
||||
UPDATED_ALARM.update(DELTA_ALARM)
|
||||
UPDATED_ALARM['threshold_rule'].update(DELTA_ALARM_RULE)
|
||||
UPDATE_ALARM = copy.deepcopy(UPDATED_ALARM)
|
||||
del UPDATE_ALARM['user_id']
|
||||
del UPDATE_ALARM['project_id']
|
||||
del UPDATE_ALARM['name']
|
||||
del UPDATE_ALARM['alarm_id']
|
||||
del UPDATE_ALARM['timestamp']
|
||||
del UPDATE_ALARM['state_timestamp']
|
||||
|
||||
AN_LEGACY_ALARM = {u'alarm_actions': [u'http://site:8000/alarm'],
|
||||
u'ok_actions': [u'http://site:8000/ok'],
|
||||
u'description': u'An alarm',
|
||||
u'matching_metadata': {u'key_name': u'key_value'},
|
||||
u'evaluation_periods': 2,
|
||||
u'timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'enabled': True,
|
||||
u'meter_name': u'storage.objects',
|
||||
u'period': 240.0,
|
||||
u'alarm_id': u'alarm-id',
|
||||
u'state': u'ok',
|
||||
u'insufficient_data_actions': [u'http://site:8000/nodata'],
|
||||
u'statistic': u'avg',
|
||||
u'threshold': 200.0,
|
||||
u'user_id': u'user-id',
|
||||
u'project_id': u'project-id',
|
||||
u'state_timestamp': u'2013-05-09T13:41:23.085000',
|
||||
u'comparison_operator': 'gt',
|
||||
u'repeat_actions': False,
|
||||
u'name': 'SwiftObjectAlarm'}
|
||||
CREATE_LEGACY_ALARM = copy.deepcopy(AN_LEGACY_ALARM)
|
||||
del CREATE_LEGACY_ALARM['timestamp']
|
||||
del CREATE_LEGACY_ALARM['state_timestamp']
|
||||
del CREATE_LEGACY_ALARM['alarm_id']
|
||||
DELTA_LEGACY_ALARM = {u'alarm_actions': ['url1', 'url2'],
|
||||
u'comparison_operator': u'lt',
|
||||
u'meter_name': u'foobar',
|
||||
u'threshold': 42.1}
|
||||
UPDATED_LEGACY_ALARM = copy.deepcopy(AN_LEGACY_ALARM)
|
||||
UPDATED_LEGACY_ALARM.update(DELTA_LEGACY_ALARM)
|
||||
UPDATE_LEGACY_ALARM = copy.deepcopy(UPDATED_LEGACY_ALARM)
|
||||
del UPDATE_LEGACY_ALARM['user_id']
|
||||
del UPDATE_LEGACY_ALARM['project_id']
|
||||
del UPDATE_LEGACY_ALARM['name']
|
||||
del UPDATE_LEGACY_ALARM['alarm_id']
|
||||
del UPDATE_LEGACY_ALARM['timestamp']
|
||||
del UPDATE_LEGACY_ALARM['state_timestamp']
|
||||
|
||||
|
||||
fixtures = {
|
||||
'/v2/alarms':
|
||||
@@ -76,6 +131,18 @@ fixtures = {
|
||||
UPDATED_ALARM,
|
||||
),
|
||||
},
|
||||
'/v2/alarms/alarm-id/state':
|
||||
{
|
||||
'PUT': (
|
||||
{},
|
||||
'alarm'
|
||||
),
|
||||
'GET': (
|
||||
{},
|
||||
'alarm'
|
||||
),
|
||||
|
||||
},
|
||||
'/v2/alarms?q.op=&q.op=&q.value=project-id&q.value=SwiftObjectAlarm'
|
||||
'&q.field=project_id&q.field=name':
|
||||
{
|
||||
@@ -135,6 +202,7 @@ class AlarmManagerTest(testtools.TestCase):
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
self.assertEqual(alarm.rule, alarm.threshold_rule)
|
||||
|
||||
def test_create(self):
|
||||
alarm = self.mgr.create(**CREATE_ALARM)
|
||||
@@ -145,16 +213,32 @@ class AlarmManagerTest(testtools.TestCase):
|
||||
self.assertTrue(alarm)
|
||||
|
||||
def test_update(self):
|
||||
alarm = self.mgr.update(alarm_id='alarm-id', **DELTA_ALARM)
|
||||
alarm = self.mgr.update(alarm_id='alarm-id', **UPDATE_ALARM)
|
||||
expect = [
|
||||
('PUT', '/v2/alarms/alarm-id', {}, DELTA_ALARM),
|
||||
('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
for (key, value) in DELTA_ALARM.iteritems():
|
||||
for (key, value) in UPDATED_ALARM.iteritems():
|
||||
self.assertEqual(getattr(alarm, key), value)
|
||||
|
||||
def test_set_state(self):
|
||||
state = self.mgr.set_state(alarm_id='alarm-id', state='alarm')
|
||||
expect = [
|
||||
('PUT', '/v2/alarms/alarm-id/state', {}, 'alarm'),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertEqual(state, 'alarm')
|
||||
|
||||
def test_get_state(self):
|
||||
state = self.mgr.get_state(alarm_id='alarm-id')
|
||||
expect = [
|
||||
('GET', '/v2/alarms/alarm-id/state', {}, None),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertEqual(state, 'alarm')
|
||||
|
||||
def test_delete(self):
|
||||
deleted = self.mgr.delete(alarm_id='victim-id')
|
||||
expect = [
|
||||
@@ -162,3 +246,57 @@ class AlarmManagerTest(testtools.TestCase):
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(deleted is None)
|
||||
|
||||
|
||||
class AlarmLegacyManagerTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AlarmLegacyManagerTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fixtures)
|
||||
self.mgr = ceilometerclient.v2.alarms.AlarmManager(self.api)
|
||||
|
||||
def test_create(self):
|
||||
alarm = self.mgr.create(**CREATE_LEGACY_ALARM)
|
||||
expect = [
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
|
||||
def test_create_counter_name(self):
|
||||
create = {}
|
||||
create.update(CREATE_LEGACY_ALARM)
|
||||
create['counter_name'] = CREATE_LEGACY_ALARM['meter_name']
|
||||
del create['meter_name']
|
||||
alarm = self.mgr.create(**create)
|
||||
expect = [
|
||||
('POST', '/v2/alarms', {}, CREATE_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
|
||||
def test_update(self):
|
||||
alarm = self.mgr.update(alarm_id='alarm-id', **UPDATE_LEGACY_ALARM)
|
||||
expect = [
|
||||
('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
for (key, value) in UPDATED_ALARM.iteritems():
|
||||
self.assertEqual(getattr(alarm, key), value)
|
||||
|
||||
def test_update_counter_name(self):
|
||||
updated = {}
|
||||
updated.update(UPDATE_LEGACY_ALARM)
|
||||
updated['counter_name'] = UPDATED_LEGACY_ALARM['meter_name']
|
||||
del updated['meter_name']
|
||||
alarm = self.mgr.update(alarm_id='alarm-id', **updated)
|
||||
expect = [
|
||||
('PUT', '/v2/alarms/alarm-id', {}, UPDATE_ALARM),
|
||||
]
|
||||
self.assertEqual(self.api.calls, expect)
|
||||
self.assertTrue(alarm)
|
||||
self.assertEqual(alarm.alarm_id, 'alarm-id')
|
||||
for (key, value) in UPDATED_ALARM.iteritems():
|
||||
self.assertEqual(getattr(alarm, key), value)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -16,33 +16,39 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import warnings
|
||||
|
||||
from ceilometerclient.common import base
|
||||
from ceilometerclient.v2 import options
|
||||
|
||||
|
||||
UPDATABLE_ATTRIBUTES = [
|
||||
'name',
|
||||
'description',
|
||||
'period',
|
||||
'evaluation_periods',
|
||||
'type',
|
||||
'state',
|
||||
'enabled',
|
||||
'counter_name',
|
||||
'statistic',
|
||||
'comparison_operator',
|
||||
'threshold',
|
||||
'alarm_actions',
|
||||
'ok_actions',
|
||||
'insufficient_data_actions',
|
||||
'repeat_actions',
|
||||
'matching_metadata',
|
||||
'threshold_rule',
|
||||
'combination_rule',
|
||||
]
|
||||
CREATION_ATTRIBUTES = UPDATABLE_ATTRIBUTES + ['name', 'project_id', 'user_id']
|
||||
CREATION_ATTRIBUTES = UPDATABLE_ATTRIBUTES + ['project_id', 'user_id']
|
||||
|
||||
|
||||
class Alarm(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Alarm %s>" % self._info
|
||||
|
||||
def __getattr__(self, k):
|
||||
# Alias to have the Alarm client object
|
||||
# that look like the Alarm storage object
|
||||
if k == 'rule':
|
||||
k = '%s_rule' % self.type
|
||||
return super(Alarm, self).__getattr__(k)
|
||||
|
||||
|
||||
class AlarmManager(base.Manager):
|
||||
resource_class = Alarm
|
||||
@@ -60,15 +66,66 @@ class AlarmManager(base.Manager):
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _compat_legacy_alarm_kwargs(cls, kwargs):
|
||||
cls._compat_counter_rename_kwargs(kwargs)
|
||||
cls._compat_alarm_before_rule_type_kwargs(kwargs)
|
||||
|
||||
@staticmethod
|
||||
def _compat_counter_rename_kwargs(kwargs):
|
||||
# NOTE(jd) Compatibility with Havana-2 API
|
||||
if 'counter_name' in kwargs:
|
||||
warnings.warn("counter_name has been renamed to meter_name",
|
||||
DeprecationWarning)
|
||||
kwargs['meter_name'] = kwargs['counter_name']
|
||||
|
||||
@staticmethod
|
||||
def _compat_alarm_before_rule_type_kwargs(kwargs):
|
||||
# NOTE(sileht) Compatibility with Havana-3 API
|
||||
if kwargs.get('type'):
|
||||
return
|
||||
warnings.warn("alarm without type set is deprecated",
|
||||
DeprecationWarning)
|
||||
|
||||
kwargs['type'] = 'threshold'
|
||||
kwargs['threshold_rule'] = {}
|
||||
for field in ['period', 'evaluation_periods', 'threshold',
|
||||
'statistic', 'comparison_operator', 'meter_name']:
|
||||
if field in kwargs:
|
||||
kwargs['threshold_rule'][field] = kwargs[field]
|
||||
del kwargs[field]
|
||||
|
||||
query = []
|
||||
if 'matching_metadata' in kwargs:
|
||||
for key in kwargs['matching_metadata']:
|
||||
query.append({'field': key,
|
||||
'op': 'eq',
|
||||
'value': kwargs['matching_metadata'][key]})
|
||||
del kwargs['matching_metadata']
|
||||
kwargs['threshold_rule']['query'] = query
|
||||
|
||||
def create(self, **kwargs):
|
||||
self._compat_legacy_alarm_kwargs(kwargs)
|
||||
new = dict((key, value) for (key, value) in kwargs.items()
|
||||
if key in CREATION_ATTRIBUTES)
|
||||
return self._create(self._path(), new)
|
||||
|
||||
def update(self, alarm_id, **kwargs):
|
||||
self._compat_legacy_alarm_kwargs(kwargs)
|
||||
updated = dict((key, value) for (key, value) in kwargs.items()
|
||||
if key in UPDATABLE_ATTRIBUTES)
|
||||
return self._update(self._path(alarm_id), updated)
|
||||
|
||||
def delete(self, alarm_id):
|
||||
return self._delete(self._path(alarm_id))
|
||||
|
||||
def set_state(self, alarm_id, state):
|
||||
resp, body = self.api.json_request('PUT',
|
||||
"%s/state" % self._path(alarm_id),
|
||||
body=state)
|
||||
return body
|
||||
|
||||
def get_state(self, alarm_id):
|
||||
resp, body = self.api.json_request('GET',
|
||||
"%s/state" % self._path(alarm_id))
|
||||
return body
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import functools
|
||||
import json
|
||||
|
||||
from ceilometerclient.common import utils
|
||||
@@ -25,6 +26,7 @@ from ceilometerclient.v2 import options
|
||||
|
||||
ALARM_STATES = ['ok', 'alarm', 'insufficient_data']
|
||||
ALARM_OPERATORS = ['lt', 'le', 'eq', 'ne', 'ge', 'gt']
|
||||
ALARM_COMBINATION_OPERATORS = ['and', 'or']
|
||||
STATISTICS = ['max', 'min', 'avg', 'sum', 'count']
|
||||
|
||||
|
||||
@@ -79,10 +81,10 @@ def do_sample_list(cc, args):
|
||||
|
||||
|
||||
@utils.arg('--project-id', metavar='<PROJECT_ID>',
|
||||
help='Tenant to associate with alarm '
|
||||
help='Tenant to associate with sample '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('--user-id', metavar='<USER_ID>',
|
||||
help='User to associate with alarm '
|
||||
help='User to associate with sample '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('-r', '--resource-id', metavar='<RESOURCE_ID>',
|
||||
help='ID of the resource.')
|
||||
@@ -133,22 +135,19 @@ def do_alarm_list(cc, args={}):
|
||||
alarms = cc.alarms.list(q=options.cli_to_array(args.query))
|
||||
# omit action initially to keep output width sane
|
||||
# (can switch over to vertical formatting when available from CLIFF)
|
||||
field_labels = ['Name', 'Description', 'Metric', 'Period', 'Count',
|
||||
'Threshold', 'Comparison', 'State', 'Enabled', 'Alarm ID',
|
||||
'User ID', 'Project ID']
|
||||
fields = ['name', 'description', 'counter_name', 'period',
|
||||
'evaluation_periods', 'threshold', 'comparison_operator',
|
||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id']
|
||||
field_labels = ['Name', 'Description', 'State', 'Enabled', 'Continuous',
|
||||
'Alarm ID', 'User ID', 'Project ID']
|
||||
fields = ['name', 'description', 'state', 'enabled', 'repeat_actions',
|
||||
'alarm_id', 'user_id', 'project_id']
|
||||
utils.print_list(alarms, fields, field_labels,
|
||||
sortby=0)
|
||||
|
||||
|
||||
def _display_alarm(alarm):
|
||||
fields = ['name', 'description', 'counter_name', 'period',
|
||||
'evaluation_periods', 'threshold', 'comparison_operator',
|
||||
fields = ['name', 'description', 'type', 'rule',
|
||||
'state', 'enabled', 'alarm_id', 'user_id', 'project_id',
|
||||
'alarm_actions', 'ok_actions', 'insufficient_data_actions',
|
||||
'repeat_actions', 'matching_metadata']
|
||||
'repeat_actions']
|
||||
data = dict([(f, getattr(alarm, f, '')) for f in fields])
|
||||
utils.print_dict(data, wrap=72)
|
||||
|
||||
@@ -167,111 +166,218 @@ def do_alarm_show(cc, args={}):
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('--name', metavar='<NAME>',
|
||||
help='Name of the alarm (must be unique per tenant)')
|
||||
@utils.arg('--project-id', metavar='<PROJECT_ID>',
|
||||
help='Tenant to associate with alarm '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('--user-id', metavar='<USER_ID>',
|
||||
help='User to associate with alarm '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('--description', metavar='<DESCRIPTION>',
|
||||
help='Free text description of the alarm')
|
||||
def common_alarm_arguments(func):
|
||||
@utils.arg('--name', metavar='<NAME>', required=True,
|
||||
help='Name of the alarm (must be unique per tenant)')
|
||||
@utils.arg('--project-id', metavar='<PROJECT_ID>',
|
||||
help='Tenant to associate with alarm '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('--user-id', metavar='<USER_ID>',
|
||||
help='User to associate with alarm '
|
||||
'(only settable by admin users)')
|
||||
@utils.arg('--description', metavar='<DESCRIPTION>',
|
||||
help='Free text description of the alarm')
|
||||
@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('--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.'))
|
||||
@utils.arg('--repeat-actions', dest='repeat_actions',
|
||||
metavar='{True|False}', type=utils.string_to_bool,
|
||||
default=False,
|
||||
help=('True if actions should be repeatedly notified '
|
||||
'while alarm remains in target state'))
|
||||
@functools.wraps(func)
|
||||
def _wrapper(*args, **kwargs):
|
||||
return func(*args, **kwargs)
|
||||
return _wrapper
|
||||
|
||||
|
||||
@common_alarm_arguments
|
||||
@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>',
|
||||
@utils.arg('--meter-name', metavar='<METRIC>', required=True,
|
||||
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>',
|
||||
@utils.arg('--threshold', type=float, metavar='<THRESHOLD>', required=True,
|
||||
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.'))
|
||||
@utils.arg('--repeat-actions', dest='repeat_actions', metavar='{True|False}',
|
||||
type=utils.string_to_bool, default=False,
|
||||
help=('True if actions should be repeatedly notified '
|
||||
'while alarm remains in target state'))
|
||||
@utils.arg('--matching-metadata', dest='matching_metadata',
|
||||
metavar='<Matching Metadata>', action='append', default=None,
|
||||
help=('A meter should match this resource metadata (key=value) '
|
||||
'additionally to the counter_name'))
|
||||
'additionally to the meter_name'))
|
||||
def do_alarm_create(cc, args={}):
|
||||
'''Create a new alarm.'''
|
||||
'''Create a new alarm (Deprecated).'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_dict(fields, "matching_metadata")
|
||||
alarm = cc.alarms.create(**fields)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>',
|
||||
@common_alarm_arguments
|
||||
@utils.arg('--meter-name', metavar='<METRIC>', required=True,
|
||||
dest='threshold_rule/meter_name',
|
||||
help='Metric to evaluate against')
|
||||
@utils.arg('--period', type=int, metavar='<PERIOD>',
|
||||
dest='threshold_rule/period',
|
||||
help='Length of each period (seconds) to evaluate over')
|
||||
@utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
|
||||
dest='threshold_rule/evaluation_periods',
|
||||
help='Number of periods to evaluate over')
|
||||
@utils.arg('--statistic', metavar='<STATISTIC>',
|
||||
dest='threshold_rule/statistic',
|
||||
help='Statistic to evaluate, one of: ' + str(STATISTICS))
|
||||
@utils.arg('--comparison-operator', metavar='<OPERATOR>',
|
||||
dest='threshold_rule/comparison_operator',
|
||||
help='Operator to compare with, one of: ' + str(ALARM_OPERATORS))
|
||||
@utils.arg('--threshold', type=float, metavar='<THRESHOLD>', required=True,
|
||||
dest='threshold_rule/threshold',
|
||||
help='Threshold to evaluate against')
|
||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||
dest='threshold_rule/query',
|
||||
help='The query to find the data for computing statistics '
|
||||
'(key[op]value; list.)')
|
||||
def do_alarm_threshold_create(cc, args={}):
|
||||
'''Create a new alarm based on computed statistics.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields['type'] = 'threshold'
|
||||
if 'query' in fields['threshold_rule']:
|
||||
fields['threshold_rule']['query'] = options.cli_to_array(
|
||||
fields['threshold_rule']['query'])
|
||||
alarm = cc.alarms.create(**fields)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@common_alarm_arguments
|
||||
@utils.arg('--alarm_ids', action='append', metavar='<ALARM IDS>',
|
||||
required=True, dest='combination_rule/alarm_ids',
|
||||
help='List of alarm id')
|
||||
@utils.arg('--operator', metavar='<OPERATOR>',
|
||||
dest='combination_rule/operator',
|
||||
help='Operator to compare with, one of: ' + str(
|
||||
ALARM_COMBINATION_OPERATORS))
|
||||
def do_alarm_combination_create(cc, args={}):
|
||||
'''Create a new alarm based on state of other alarms.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields['type'] = 'combination'
|
||||
alarm = cc.alarms.create(**fields)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@utils.arg('--description', metavar='<DESCRIPTION>',
|
||||
help='Free text description of the alarm')
|
||||
@common_alarm_arguments
|
||||
@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>',
|
||||
@utils.arg('--meter-name', metavar='<METRIC>', required=True,
|
||||
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>',
|
||||
@utils.arg('--threshold', type=float, metavar='<THRESHOLD>', required=True,
|
||||
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.'))
|
||||
@utils.arg('--repeat-actions', dest='repeat_actions',
|
||||
metavar='{True|False}', type=utils.string_to_bool,
|
||||
help=('True if actions should be repeatedly notified '
|
||||
'while alarm remains in target state'))
|
||||
@utils.arg('--matching-metadata', dest='matching_metadata',
|
||||
metavar='<Matching Metadata>', action='append', default=None,
|
||||
help=('A meter should match this resource metadata (key=value) '
|
||||
'additionally to the counter_name'))
|
||||
'additionally to the meter_name'))
|
||||
def do_alarm_update(cc, args={}):
|
||||
'''Update an existing alarm.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.args_array_to_dict(fields, "matching_metadata")
|
||||
fields.pop('alarm_id')
|
||||
alarm = cc.alarms.update(args.alarm_id, **fields)
|
||||
try:
|
||||
alarm = cc.alarms.update(args.alarm_id, **fields)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>',
|
||||
help='ID of the alarm to show.')
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@common_alarm_arguments
|
||||
@utils.arg('--meter-name', metavar='<METRIC>',
|
||||
dest='threshold_rule/meter_name', required=True,
|
||||
help='Metric to evaluate against')
|
||||
@utils.arg('--period', type=int, metavar='<PERIOD>',
|
||||
dest='threshold_rule/period',
|
||||
help='Length of each period (seconds) to evaluate over')
|
||||
@utils.arg('--evaluation-periods', type=int, metavar='<COUNT>',
|
||||
dest='threshold_rule/evaluation_periods',
|
||||
help='Number of periods to evaluate over')
|
||||
@utils.arg('--statistic', metavar='<STATISTIC>',
|
||||
dest='threshold_rule/statistic',
|
||||
help='Statistic to evaluate, one of: ' + str(STATISTICS))
|
||||
@utils.arg('--comparison-operator', metavar='<OPERATOR>',
|
||||
dest='threshold_rule/comparison_operator',
|
||||
help='Operator to compare with, one of: ' + str(ALARM_OPERATORS))
|
||||
@utils.arg('--threshold', type=float, metavar='<THRESHOLD>', required=True,
|
||||
dest='threshold_rule/threshold',
|
||||
help='Threshold to evaluate against')
|
||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||
dest='threshold_rule/query',
|
||||
help='The query to find the data for computing statistics '
|
||||
'(key[op]value; list.)')
|
||||
def do_alarm_threshold_update(cc, args={}):
|
||||
'''Update an existing alarm based on computed statistics.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields.pop('alarm_id')
|
||||
fields['type'] = 'threshold'
|
||||
if 'query' in fields['threshold_rule']:
|
||||
fields['threshold_rule']['query'] = options.cli_to_array(
|
||||
fields['threshold_rule']['query'])
|
||||
try:
|
||||
alarm = cc.alarms.update(args.alarm_id, **fields)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to update.')
|
||||
@common_alarm_arguments
|
||||
@utils.arg('--alarm_ids', action='append', metavar='<ALARM IDS>',
|
||||
dest='combination_rule/alarm_ids', required=True,
|
||||
help='List of alarm id')
|
||||
@utils.arg('---operator', metavar='<OPERATOR>',
|
||||
dest='combination_rule/operator',
|
||||
help='Operator to compare with, one of: ' + str(
|
||||
ALARM_COMBINATION_OPERATORS))
|
||||
def do_alarm_combination_update(cc, args={}):
|
||||
'''Update an existing alarm based on state of other alarms.'''
|
||||
fields = dict(filter(lambda x: not (x[1] is None), vars(args).items()))
|
||||
fields = utils.key_with_slash_to_nested_dict(fields)
|
||||
fields.pop('alarm_id')
|
||||
fields['type'] = 'combination'
|
||||
try:
|
||||
alarm = cc.alarms.update(args.alarm_id, **fields)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
_display_alarm(alarm)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm to delete.')
|
||||
def do_alarm_delete(cc, args={}):
|
||||
'''Delete an alarm.'''
|
||||
if args.alarm_id is None:
|
||||
@@ -282,6 +388,32 @@ def do_alarm_delete(cc, args={}):
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm state to set.')
|
||||
@utils.arg('--state', metavar='<STATE>', required=True,
|
||||
help='State of the alarm, one of: ' + str(ALARM_STATES))
|
||||
def do_alarm_set_state(cc, args={}):
|
||||
'''Set the state of an alarm.'''
|
||||
try:
|
||||
cc.alarms.set_state(args.alarm_id, args.state)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
state = cc.alarms.get_state(args.alarm_id)
|
||||
utils.print_dict({'state': state}, wrap=72)
|
||||
|
||||
|
||||
@utils.arg('-a', '--alarm_id', metavar='<ALARM_ID>', required=True,
|
||||
help='ID of the alarm state to show.')
|
||||
def do_alarm_get_state(cc, args={}):
|
||||
'''Get the state of an alarm.'''
|
||||
try:
|
||||
cc.alarms.set_state(args.alarm_id, args.state)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarm not found: %s' % args.alarm_id)
|
||||
state = cc.alarms.get_state(args.alarm_id)
|
||||
utils.print_dict({'state': state}, wrap=72)
|
||||
|
||||
|
||||
@utils.arg('-q', '--query', metavar='<QUERY>',
|
||||
help='key[op]value; list.')
|
||||
def do_resource_list(cc, args={}):
|
||||
|
||||
@@ -26,7 +26,7 @@ source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
copyright = u'OpenStack LLC'
|
||||
copyright = u'OpenStack Foundation'
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
@@ -56,7 +56,7 @@ latex_documents = [
|
||||
'index',
|
||||
'%s.tex' % project,
|
||||
u'%s Documentation' % project,
|
||||
u'OpenStack LLC',
|
||||
u'OpenStack Foundation',
|
||||
'manual'
|
||||
),
|
||||
]
|
||||
|
||||
@@ -3,4 +3,4 @@ argparse
|
||||
httplib2
|
||||
iso8601>=0.1.4
|
||||
PrettyTable>=0.6,<0.8
|
||||
python-keystoneclient>=0.3.0
|
||||
python-keystoneclient>=0.3.2
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Install bounded pep8/pyflakes first, then let flake8 install
|
||||
pep8==1.4.5
|
||||
pyflakes==0.7.2
|
||||
pyflakes>=0.7.2,<0.7.4
|
||||
flake8==2.0
|
||||
hacking>=0.5.6,<0.7
|
||||
hacking>=0.5.6,<0.8
|
||||
coverage>=3.6
|
||||
discover
|
||||
fixtures>=0.3.12
|
||||
fixtures>=0.3.14
|
||||
mox>=0.5.3
|
||||
python-subunit
|
||||
sphinx>=1.1.2
|
||||
|
||||
Reference in New Issue
Block a user