From 0796d18f1efa5c03a3cc81b83b61b8886ecd2bc2 Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Thu, 27 Sep 2012 15:17:35 -0400 Subject: [PATCH] Add volume/sum API endpoint for resource meters Provide an API for querying the total volume from a meter for a given resource. Change-Id: I5ee28fc2db7fd05f8259a4727c32a3c45507c855 --- ceilometer/api/v1.py | 31 +++++++ tests/api/v1/test_sum_resource_volume.py | 101 +++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 tests/api/v1/test_sum_resource_volume.py diff --git a/ceilometer/api/v1.py b/ceilometer/api/v1.py index b4560c1ed..933089d91 100644 --- a/ceilometer/api/v1.py +++ b/ceilometer/api/v1.py @@ -443,3 +443,34 @@ def compute_max_resource_volume(resource, meter): value = results[0].get('value') # there should only be one! return flask.jsonify(volume=value) + + +@blueprint.route('/resources//meters//volume/sum') +def compute_resource_volume_sum(resource, meter): + """Return the total volume for a meter. + + :param resource: The ID of the resource. + :param meter: The name of the meter. + :param start_timestamp: ISO-formatted string of the + earliest time to include in the calculation. + :param end_timestamp: ISO-formatted string of the + latest time to include in the calculation. + :param search_offset: Number of minutes before and + after start and end timestamps to query. + """ + q_ts = _get_query_timestamps(flask.request.args) + + # Query the database for the max volume + f = storage.EventFilter(meter=meter, + resource=resource, + start=q_ts['query_start'], + end=q_ts['query_end'], + ) + # TODO(sberler): do we want to return an error if the resource + # does not exist? + results = list(flask.request.storage_conn.get_volume_sum(f)) + value = None + if results: + value = results[0].get('value') # there should only be one! + + return flask.jsonify(volume=value) diff --git a/tests/api/v1/test_sum_resource_volume.py b/tests/api/v1/test_sum_resource_volume.py new file mode 100644 index 000000000..3ccaee850 --- /dev/null +++ b/tests/api/v1/test_sum_resource_volume.py @@ -0,0 +1,101 @@ +# -*- encoding: utf-8 -*- +# +# Copyright © 2012 New Dream Network, LLC (DreamHost) +# +# Author: Doug Hellmann +# +# 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. +"""Test getting the total resource volume. +""" + +import datetime +import logging + +from ming import mim +from nose.plugins import skip + +from ceilometer import counter +from ceilometer import meter + +from ceilometer.tests import api as tests_api + + +class TestSumResourceVolume(tests_api.TestBase): + + def setUp(self): + super(TestSumResourceVolume, self).setUp() + + # NOTE(dhellmann): mim requires spidermonkey to implement the + # map-reduce functions, so if we can't import it then just + # skip these tests unless we aren't using mim. + try: + import spidermonkey + except: + if isinstance(self.conn.conn, mim.Connection): + raise skip.SkipTest('requires spidermonkey') + + self.counters = [] + for i in range(3): + c = counter.Counter( + 'source1', + 'volume_size', + 'absolute', + 5 + i, + 'user-id', + 'project1', + 'resource-id', + timestamp=datetime.datetime(2012, 9, 25, 10 + i, 30 + i), + duration=0, + resource_metadata={'display_name': 'test-volume', + 'tag': 'self.counter', + } + ) + self.counters.append(c) + msg = meter.meter_message_from_counter(c) + self.conn.record_metering_data(msg) + + def test_no_time_bounds(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum') + expected = {'volume': 5 + 6 + 7} + assert data == expected + + def test_start_timestamp(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum', + start_timestamp='2012-09-25T11:30:00') + expected = {'volume': 6 + 7} + assert data == expected + + def test_start_timestamp_after(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum', + start_timestamp='2012-09-25T12:34:00') + expected = {'volume': None} + assert data == expected + + def test_end_timestamp(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum', + end_timestamp='2012-09-25T11:30:00') + expected = {'volume': 5} + assert data == expected + + def test_end_timestamp_before(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum', + end_timestamp='2012-09-25T09:54:00') + expected = {'volume': None} + assert data == expected + + def test_start_end_timestamp(self): + data = self.get('/resources/resource-id/meters/volume_size/volume/sum', + start_timestamp='2012-09-25T11:30:00', + end_timestamp='2012-09-25T11:32:00') + expected = {'volume': 6} + assert data == expected