Introduce safer access to resource meters

Storing of meters in the wrapper object attributes is bad. It
can lead to name conflicts, which can theoretically result
in weird bugs.

Change-Id: I7b1a248be52721b0401fba7bf976b9c4e63f71ba
Implements: blueprint ceilometer-api-enhancements
This commit is contained in:
Ladislav Smola
2014-06-05 10:51:42 +02:00
parent c28c221f77
commit 8f2ebe66d6
3 changed files with 33 additions and 16 deletions

View File

@@ -127,6 +127,9 @@ class Resource(base.APIResourceWrapper):
self.user_id,
self.resource_id)
# Meters with statistics data
self._meters = {}
# TODO(lsmola) make parallel obtaining of tenant and user
# make the threading here, thread join into resource_list
if ceilometer_usage and self.project_id:
@@ -169,6 +172,16 @@ class Resource(base.APIResourceWrapper):
def query(self):
return self._query
@property
def meters(self):
return self._meters
def get_meter(self, meter_name):
return self._meters.get(meter_name, None)
def set_meter(self, meter_name, value):
self._meters[meter_name] = value
class ResourceAggregate(Resource):
"""Represents aggregate of more resources together.
@@ -195,6 +208,9 @@ class ResourceAggregate(Resource):
self.user_id = None
self.resource_id = None
# Meters with statistics data
self._meters = {}
if query:
self._query = query
else:
@@ -563,13 +579,14 @@ class CeilometerUsage(object):
if statistics:
if stats_attr:
# I want to load only a specific attribute
setattr(resource, meter,
getattr(statistics[0], stats_attr, None))
resource.set_meter(
meter,
getattr(statistics[0], stats_attr, None))
else:
# I want a dictionary of all statistics
setattr(resource, meter, statistics)
resource.set_meter(meter, statistics)
else:
setattr(resource, meter, None)
resource.set_meter(meter, None)
return resource

View File

@@ -51,11 +51,11 @@ class SamplesView(generic.TemplateView):
"""Construct datapoint series for a meter from resource aggregates."""
series = []
for resource in aggregates:
if getattr(resource, meter_name):
if resource.get_meter(meter_name):
point = {'unit': unit,
'name': getattr(resource, resource_name),
'data': []}
for statistic in getattr(resource, meter_name):
for statistic in resource.get_meter(meter_name):
date = statistic.duration_end[:19]
value = float(getattr(statistic, stats_name))
point['data'].append({'x': date, 'y': value})
@@ -334,7 +334,7 @@ def load_report_data(request):
meter.name,
3600 * 24)
for re in res:
values = getattr(re, meter.name.replace(".", "_"))
values = re.get_meter(meter.name.replace(".", "_"))
if values:
for value in values:
row = {"name": 'none',

View File

@@ -161,8 +161,7 @@ class CeilometerApiTests(test.APITestCase):
"get_tenant")})
def test_global_data_get(self):
class TempUsage(api.base.APIResourceWrapper):
_attrs = ["id", "tenant", "user", "resource", "fake_meter_1",
"fake_meter_2"]
_attrs = ["id", "tenant", "user", "resource", "get_meter"]
meters = ["fake_meter_1",
"fake_meter_2"]
@@ -207,9 +206,9 @@ class CeilometerApiTests(test.APITestCase):
self.assertEqual(first.user.name, 'user')
self.assertEqual(first.tenant.name, 'test_tenant')
self.assertEqual(first.resource, 'fake_resource_id')
self.assertEqual(first.fake_meter_1, 9)
self.assertEqual(first.fake_meter_2, 9)
self.assertEqual(first.get_meter('fake_meter_1'), 9)
self.assertEqual(first.get_meter('fake_meter_2'), 9)
self.assertEqual(len(first.meters), 2)
# check that only one resource is returned
self.assertEqual(len(data), 1)
@@ -262,8 +261,7 @@ class CeilometerApiTests(test.APITestCase):
"get_tenant")})
def test_global_data_get_all_statistic_data(self):
class TempUsage(api.base.APIResourceWrapper):
_attrs = ["id", "tenant", "user", "resource", "fake_meter_1",
"fake_meter_2"]
_attrs = ["id", "tenant", "user", "resource", "get_meter", ]
meters = ["fake_meter_1",
"fake_meter_2"]
@@ -308,7 +306,9 @@ class CeilometerApiTests(test.APITestCase):
statistic_obj = api.ceilometer.Statistic(statistics[0])
# check that it returns whole statistic object
self.assertEqual(vars(first.fake_meter_1[0]), vars(statistic_obj))
self.assertEqual(vars(first.fake_meter_2[0]), vars(statistic_obj))
self.assertEqual(vars(first.get_meter('fake_meter_1')[0]),
vars(statistic_obj))
self.assertEqual(vars(first.get_meter('fake_meter_2')[0]),
vars(statistic_obj))
self.assertEqual(len(data), len(resources))