add mandatory limit value to meter list
unrestricted listing of meters can require significant memory. this patch implements mandatory limit on meter-list Change-Id: I8b38136c2493e75fbc7d9aef75aa055463a26319 Implements: blueprint mandatory-limit
This commit is contained in:
parent
1852eaf48e
commit
f3c01e7528
@ -476,8 +476,8 @@ class MetersController(rest.RestController):
|
||||
def _lookup(self, meter_name, *remainder):
|
||||
return MeterController(meter_name), remainder
|
||||
|
||||
@wsme_pecan.wsexpose([Meter], [base.Query])
|
||||
def get_all(self, q=None):
|
||||
@wsme_pecan.wsexpose([Meter], [base.Query], int)
|
||||
def get_all(self, q=None, limit=None):
|
||||
"""Return all known meters, based on the data recorded so far.
|
||||
|
||||
:param q: Filter rules for the meters to be returned.
|
||||
@ -488,7 +488,9 @@ class MetersController(rest.RestController):
|
||||
q = q or []
|
||||
|
||||
# Timestamp field is not supported for Meter queries
|
||||
limit = v2_utils.enforce_limit(limit)
|
||||
kwargs = v2_utils.query_to_kwargs(
|
||||
q, pecan.request.storage_conn.get_meters, allow_timestamps=False)
|
||||
return [Meter.from_db_model(m)
|
||||
for m in pecan.request.storage_conn.get_meters(**kwargs)]
|
||||
for m in pecan.request.storage_conn.get_meters(limit=limit,
|
||||
**kwargs)]
|
||||
|
@ -242,7 +242,7 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
metadata=md)
|
||||
|
||||
def get_meters(self, user=None, project=None, resource=None, source=None,
|
||||
metaquery=None):
|
||||
metaquery=None, limit=None):
|
||||
"""Return an iterable of models.Meter instances
|
||||
|
||||
:param user: Optional ID for user that owns the resource.
|
||||
@ -250,7 +250,10 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
:param resource: Optional resource filter.
|
||||
:param source: Optional source filter.
|
||||
:param metaquery: Optional dict with metadata to match on.
|
||||
:param limit: Maximum number of results to return.
|
||||
"""
|
||||
if limit == 0:
|
||||
return
|
||||
|
||||
metaquery = metaquery or {}
|
||||
|
||||
@ -271,6 +274,8 @@ class Connection(hbase_base.Connection, base.Connection):
|
||||
flatten_result, s, meters, md = hbase_utils.deserialize_entry(
|
||||
data)
|
||||
for m in meters:
|
||||
if limit and len(result) >= limit:
|
||||
return
|
||||
_m_rts, m_source, name, m_type, unit = m[0]
|
||||
meter_dict = {'name': name,
|
||||
'type': m_type,
|
||||
|
@ -464,7 +464,7 @@ class Connection(base.Connection):
|
||||
)
|
||||
|
||||
def get_meters(self, user=None, project=None, resource=None, source=None,
|
||||
metaquery=None):
|
||||
metaquery=None, limit=None):
|
||||
"""Return an iterable of api_models.Meter instances
|
||||
|
||||
:param user: Optional ID for user that owns the resource.
|
||||
@ -472,7 +472,10 @@ class Connection(base.Connection):
|
||||
:param resource: Optional ID of the resource.
|
||||
:param source: Optional source filter.
|
||||
:param metaquery: Optional dict with metadata to match on.
|
||||
:param limit: Maximum number of results to return.
|
||||
"""
|
||||
if limit == 0:
|
||||
return
|
||||
s_filter = storage.SampleFilter(user=user,
|
||||
project=project,
|
||||
source=source,
|
||||
@ -505,6 +508,7 @@ class Connection(base.Connection):
|
||||
query_sample = make_query_from_filter(session, query_sample, s_filter,
|
||||
require_meter=False)
|
||||
|
||||
query_sample = query_sample.limit(limit) if limit else query_sample
|
||||
for row in query_sample.all():
|
||||
yield api_models.Meter(
|
||||
name=row.name,
|
||||
|
@ -50,7 +50,7 @@ class Connection(base.Connection):
|
||||
)
|
||||
|
||||
def get_meters(self, user=None, project=None, resource=None, source=None,
|
||||
metaquery=None):
|
||||
metaquery=None, limit=None):
|
||||
"""Return an iterable of models.Meter instances
|
||||
|
||||
:param user: Optional ID for user that owns the resource.
|
||||
@ -58,7 +58,10 @@ class Connection(base.Connection):
|
||||
:param resource: Optional resource filter.
|
||||
:param source: Optional source filter.
|
||||
:param metaquery: Optional dict with metadata to match on.
|
||||
:param limit: Maximum number of results to return.
|
||||
"""
|
||||
if limit == 0:
|
||||
return
|
||||
|
||||
metaquery = pymongo_utils.improve_keys(metaquery, metaquery=True) or {}
|
||||
|
||||
@ -73,8 +76,13 @@ class Connection(base.Connection):
|
||||
q['source'] = source
|
||||
q.update(metaquery)
|
||||
|
||||
count = 0
|
||||
for r in self.db.resource.find(q):
|
||||
for r_meter in r['meter']:
|
||||
if limit and count >= limit:
|
||||
return
|
||||
else:
|
||||
count += 1
|
||||
yield models.Meter(
|
||||
name=r_meter['counter_name'],
|
||||
type=r_meter['counter_type'],
|
||||
|
@ -66,10 +66,11 @@ class TestListMetersRestriction(v2.FunctionalTest,
|
||||
|
||||
def setUp(self):
|
||||
super(TestListMetersRestriction, self).setUp()
|
||||
self.CONF.set_override('default_api_return_limit', 10, group='api')
|
||||
for i in range(20):
|
||||
self.CONF.set_override('default_api_return_limit', 3, group='api')
|
||||
for x in range(5):
|
||||
for i in range(5):
|
||||
s = sample.Sample(
|
||||
'volume.size',
|
||||
'volume.size%s' % x,
|
||||
'gauge',
|
||||
'GiB',
|
||||
5 + i,
|
||||
@ -89,21 +90,38 @@ class TestListMetersRestriction(v2.FunctionalTest,
|
||||
self.conn.record_metering_data(msg)
|
||||
|
||||
def test_meter_limit(self):
|
||||
data = self.get_json('/meters/volume.size?limit=1')
|
||||
data = self.get_json('/meters?limit=1')
|
||||
self.assertEqual(1, len(data))
|
||||
|
||||
def test_meter_limit_negative(self):
|
||||
self.assertRaises(webtest.app.AppError,
|
||||
self.get_json,
|
||||
'/meters/volume.size?limit=-2')
|
||||
'/meters?limit=-2')
|
||||
|
||||
def test_meter_limit_bigger(self):
|
||||
data = self.get_json('/meters/volume.size?limit=42')
|
||||
self.assertEqual(20, len(data))
|
||||
data = self.get_json('/meters?limit=42')
|
||||
self.assertEqual(5, len(data))
|
||||
|
||||
def test_meter_default_limit(self):
|
||||
data = self.get_json('/meters/volume.size')
|
||||
self.assertEqual(10, len(data))
|
||||
data = self.get_json('/meters')
|
||||
self.assertEqual(3, len(data))
|
||||
|
||||
def test_old_sample_limit(self):
|
||||
data = self.get_json('/meters/volume.size0?limit=1')
|
||||
self.assertEqual(1, len(data))
|
||||
|
||||
def test_old_sample_limit_negative(self):
|
||||
self.assertRaises(webtest.app.AppError,
|
||||
self.get_json,
|
||||
'/meters/volume.size0?limit=-2')
|
||||
|
||||
def test_old_sample_limit_bigger(self):
|
||||
data = self.get_json('/meters/volume.size0?limit=42')
|
||||
self.assertEqual(5, len(data))
|
||||
|
||||
def test_old_sample_default_limit(self):
|
||||
data = self.get_json('/meters/volume.size0')
|
||||
self.assertEqual(3, len(data))
|
||||
|
||||
def test_sample_limit(self):
|
||||
data = self.get_json('/samples?limit=1')
|
||||
@ -116,11 +134,11 @@ class TestListMetersRestriction(v2.FunctionalTest,
|
||||
|
||||
def test_sample_limit_bigger(self):
|
||||
data = self.get_json('/samples?limit=42')
|
||||
self.assertEqual(20, len(data))
|
||||
self.assertEqual(25, len(data))
|
||||
|
||||
def test_sample_default_limit(self):
|
||||
data = self.get_json('/samples')
|
||||
self.assertEqual(10, len(data))
|
||||
self.assertEqual(3, len(data))
|
||||
|
||||
|
||||
class TestListMeters(v2.FunctionalTest,
|
||||
|
Loading…
Reference in New Issue
Block a user