Merge "Add complex query support for alarms"

This commit is contained in:
Jenkins
2014-03-25 23:07:36 +00:00
committed by Gerrit Code Review
6 changed files with 187 additions and 11 deletions

View 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))

View File

@@ -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)

View File

@@ -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())

View File

@@ -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)

View File

@@ -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'

View File

@@ -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)