Merge "Add complex query support for alarms"
This commit is contained in:
72
ceilometerclient/tests/v2/test_query_alarms.py
Normal file
72
ceilometerclient/tests/v2/test_query_alarms.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# Copyright Ericsson AB 2014. All rights reserved
|
||||
#
|
||||
# Author: Balazs Gibizer <balazs.gibizer@ericsson.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.
|
||||
|
||||
from ceilometerclient.tests import utils
|
||||
from ceilometerclient.v2 import query
|
||||
|
||||
|
||||
ALARM = {"alarm_actions": ["http://site:8000/alarm"],
|
||||
"alarm_id": None,
|
||||
"combination_rule": {
|
||||
"alarm_ids": [
|
||||
"739e99cb-c2ec-4718-b900-332502355f38",
|
||||
"153462d0-a9b8-4b5b-8175-9e4b05e9b856"],
|
||||
"operator": "or"},
|
||||
"description": "An alarm",
|
||||
"enabled": True,
|
||||
"insufficient_data_actions": ["http://site:8000/nodata"],
|
||||
"name": "SwiftObjectAlarm",
|
||||
"ok_actions": ["http://site:8000/ok"],
|
||||
"project_id": "c96c887c216949acbdfbd8b494863567",
|
||||
"repeat_actions": False,
|
||||
"state": "ok",
|
||||
"state_timestamp": "2014-02-20T10:37:15.589860",
|
||||
"threshold_rule": None,
|
||||
"timestamp": "2014-02-20T10:37:15.589856",
|
||||
"type": "combination",
|
||||
"user_id": "c96c887c216949acbdfbd8b494863567"}
|
||||
|
||||
QUERY = {"filter": {"and": [{"!=": {"state": "ok"}},
|
||||
{"=": {"type": "combination"}}]},
|
||||
"orderby": [{"state_timestamp": "desc"}],
|
||||
"limit": 10}
|
||||
|
||||
base_url = '/v2/query/alarms'
|
||||
fixtures = {
|
||||
base_url:
|
||||
{
|
||||
'POST': (
|
||||
{},
|
||||
[ALARM],
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class QueryAlarmsManagerTest(utils.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(QueryAlarmsManagerTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fixtures)
|
||||
self.mgr = query.QueryAlarmsManager(self.api)
|
||||
|
||||
def test_query(self):
|
||||
alarms = self.mgr.query(**QUERY)
|
||||
expect = [
|
||||
('POST', '/v2/query/alarms', {}, QUERY),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
self.assertEqual(1, len(alarms))
|
||||
@@ -15,7 +15,7 @@
|
||||
# under the License.
|
||||
|
||||
from ceilometerclient.tests import utils
|
||||
from ceilometerclient.v2 import query_samples
|
||||
from ceilometerclient.v2 import query
|
||||
|
||||
|
||||
SAMPLE = {u'id': u'b55d1526-9929-11e3-a3f6-02163e5df1e6',
|
||||
@@ -54,7 +54,7 @@ class QuerySamplesManagerTest(utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(QuerySamplesManagerTest, self).setUp()
|
||||
self.api = utils.FakeAPI(fixtures)
|
||||
self.mgr = query_samples.QuerySamplesManager(self.api)
|
||||
self.mgr = query.QuerySamplesManager(self.api)
|
||||
|
||||
def test_query(self):
|
||||
samples = self.mgr.query(**QUERY)
|
||||
|
||||
@@ -469,3 +469,70 @@ class ShellQuerySamplesCommandTest(utils.BaseTestCase):
|
||||
+--------------------------------------+----------+-------+--------+---------\
|
||||
-+----------------------------+
|
||||
''', output.getvalue())
|
||||
|
||||
|
||||
class ShellQueryAlarmsCommandTest(utils.BaseTestCase):
|
||||
|
||||
ALARM = [{"alarm_actions": ["http://site:8000/alarm"],
|
||||
"alarm_id": "768ff714-8cfb-4db9-9753-d484cb33a1cc",
|
||||
"combination_rule": {
|
||||
"alarm_ids": [
|
||||
"739e99cb-c2ec-4718-b900-332502355f38",
|
||||
"153462d0-a9b8-4b5b-8175-9e4b05e9b856"],
|
||||
"operator": "or"},
|
||||
"description": "An alarm",
|
||||
"enabled": True,
|
||||
"insufficient_data_actions": ["http://site:8000/nodata"],
|
||||
"name": "SwiftObjectAlarm",
|
||||
"ok_actions": ["http://site:8000/ok"],
|
||||
"project_id": "c96c887c216949acbdfbd8b494863567",
|
||||
"repeat_actions": False,
|
||||
"state": "ok",
|
||||
"state_timestamp": "2014-02-20T10:37:15.589860",
|
||||
"threshold_rule": None,
|
||||
"timestamp": "2014-02-20T10:37:15.589856",
|
||||
"type": "combination",
|
||||
"user_id": "c96c887c216949acbdfbd8b494863567"}]
|
||||
|
||||
QUERY = {"filter": {"and": [{"!=": {"state": "ok"}},
|
||||
{"=": {"type": "combination"}}]},
|
||||
"orderby": [{"state_timestamp": "desc"}],
|
||||
"limit": 10}
|
||||
|
||||
def setUp(self):
|
||||
super(ShellQueryAlarmsCommandTest, self).setUp()
|
||||
self.cc = mock.Mock()
|
||||
self.args = mock.Mock()
|
||||
self.args.filter = self.QUERY["filter"]
|
||||
self.args.orderby = self.QUERY["orderby"]
|
||||
self.args.limit = self.QUERY["limit"]
|
||||
|
||||
def test_query(self):
|
||||
|
||||
ret_alarm = [alarms.Alarm(mock.Mock(), alarm)
|
||||
for alarm in self.ALARM]
|
||||
self.cc.query_alarms.query.return_value = ret_alarm
|
||||
org_stdout = sys.stdout
|
||||
try:
|
||||
sys.stdout = output = six.StringIO()
|
||||
ceilometer_shell.do_query_alarms(self.cc, self.args)
|
||||
finally:
|
||||
sys.stdout = org_stdout
|
||||
|
||||
self.assertEqual('''\
|
||||
+--------------------------------------+------------------+-------+---------\
|
||||
+------------+--------------------------------------------------------------\
|
||||
----------------------------------------+
|
||||
| Alarm ID | Name | State | Enabled \
|
||||
| Continuous | Alarm condition \
|
||||
|
|
||||
+--------------------------------------+------------------+-------+---------\
|
||||
+------------+--------------------------------------------------------------\
|
||||
----------------------------------------+
|
||||
| 768ff714-8cfb-4db9-9753-d484cb33a1cc | SwiftObjectAlarm | ok | True \
|
||||
| False | combinated states (OR) of 739e99cb-c2ec-4718-b900-332502355f3\
|
||||
8, 153462d0-a9b8-4b5b-8175-9e4b05e9b856 |
|
||||
+--------------------------------------+------------------+-------+---------\
|
||||
+------------+--------------------------------------------------------------\
|
||||
----------------------------------------+
|
||||
''', output.getvalue())
|
||||
|
||||
@@ -19,7 +19,7 @@ from ceilometerclient.v2 import alarms
|
||||
from ceilometerclient.v2 import event_types
|
||||
from ceilometerclient.v2 import events
|
||||
from ceilometerclient.v2 import meters
|
||||
from ceilometerclient.v2 import query_samples
|
||||
from ceilometerclient.v2 import query
|
||||
from ceilometerclient.v2 import resources
|
||||
from ceilometerclient.v2 import samples
|
||||
from ceilometerclient.v2 import statistics
|
||||
@@ -50,5 +50,7 @@ class Client(object):
|
||||
self.traits = traits.TraitManager(self.http_client)
|
||||
self.trait_info = trait_descriptions.\
|
||||
TraitDescriptionManager(self.http_client)
|
||||
self.query_samples = query_samples.QuerySamplesManager(
|
||||
self.query_samples = query.QuerySamplesManager(
|
||||
self.http_client)
|
||||
self.query_alarms = query.QueryAlarmsManager(
|
||||
self.http_client)
|
||||
|
||||
@@ -15,15 +15,12 @@
|
||||
# under the License.
|
||||
|
||||
from ceilometerclient.common import base
|
||||
from ceilometerclient.v2 import alarms
|
||||
from ceilometerclient.v2 import samples
|
||||
|
||||
|
||||
class QuerySamplesManager(base.Manager):
|
||||
resource_class = samples.Sample
|
||||
|
||||
@staticmethod
|
||||
def _path():
|
||||
return '/v2/query/samples'
|
||||
class QueryManager(base.Manager):
|
||||
path_suffix = None
|
||||
|
||||
def query(self, filter, orderby, limit):
|
||||
query = {}
|
||||
@@ -34,7 +31,7 @@ class QuerySamplesManager(base.Manager):
|
||||
if limit:
|
||||
query["limit"] = limit
|
||||
|
||||
url = self._path()
|
||||
url = '/v2/query%s' % self.path_suffix
|
||||
resp, body = self.api.json_request('POST',
|
||||
url,
|
||||
body=query)
|
||||
@@ -42,3 +39,13 @@ class QuerySamplesManager(base.Manager):
|
||||
return [self.resource_class(self, b) for b in body]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
class QuerySamplesManager(QueryManager):
|
||||
resource_class = samples.Sample
|
||||
path_suffix = '/samples'
|
||||
|
||||
|
||||
class QueryAlarmsManager(QueryManager):
|
||||
resource_class = alarms.Alarm
|
||||
path_suffix = '/alarms'
|
||||
@@ -671,3 +671,31 @@ def do_query_samples(cc, args):
|
||||
'volume', 'unit', 'timestamp']
|
||||
utils.print_list(samples, fields, field_labels,
|
||||
sortby=None)
|
||||
|
||||
|
||||
@utils.arg('-f', '--filter', metavar='<FILTER>',
|
||||
help=('{complex_op: [{simple_op: {field_name: value}}]} '
|
||||
'The complex_op is one of: ' + str(COMPLEX_OPERATORS) + ', '
|
||||
'simple_op is one of: ' + str(SIMPLE_OPERATORS) + '.'))
|
||||
@utils.arg('-o', '--orderby', metavar='<ORDERBY>',
|
||||
help=('[{field_name: direction}, {field_name: direction}] '
|
||||
'The direction is one of: ' + str(ORDER_DIRECTIONS) + '.'))
|
||||
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
||||
help='Maximum number of alarms to return.')
|
||||
def do_query_alarms(cc, args):
|
||||
'''Query Alarms.'''
|
||||
fields = {'filter': args.filter,
|
||||
'orderby': args.orderby,
|
||||
'limit': args.limit}
|
||||
try:
|
||||
alarms = cc.query_alarms.query(**fields)
|
||||
except exc.HTTPNotFound:
|
||||
raise exc.CommandError('Alarms not found')
|
||||
else:
|
||||
field_labels = ['Alarm ID', 'Name', 'State', 'Enabled', 'Continuous',
|
||||
'Alarm condition']
|
||||
fields = ['alarm_id', 'name', 'state', 'enabled', 'repeat_actions',
|
||||
'rule']
|
||||
utils.print_list(alarms, fields, field_labels,
|
||||
formatters={'rule': alarm_rule_formatter},
|
||||
sortby=None)
|
||||
|
||||
Reference in New Issue
Block a user