diff --git a/ceilometer/api/v1.py b/ceilometer/api/v1.py index 9dcc4f94d..f0b57b445 100644 --- a/ceilometer/api/v1.py +++ b/ceilometer/api/v1.py @@ -18,6 +18,55 @@ """Blueprint for version 1 of API. """ +# [ ] / -- information about this version of the API +# +# [ ] /extensions -- list of available extensions +# [ ] /extensions/ -- details about a specific extension +# +# [ ] /sources -- list of known sources (where do we get this?) +# [ ] /sources/components -- list of components which provide metering +# data (where do we get this)? +# +# [x] /projects//resources -- list of resource ids +# [x] /resources -- list of resource ids +# [x] /sources//resources -- list of resource ids +# [x] /users//resources -- list of resource ids +# +# [x] /users -- list of user ids +# [x] /sources//users -- list of user ids +# +# [x] /projects -- list of project ids +# [x] /sources//projects -- list of project ids +# +# [ ] /resources/ -- metadata +# +# [ ] /projects//meters -- list of meters reporting for parent obj +# [ ] /resources//meters -- list of meters reporting for parent obj +# [ ] /sources//meters -- list of meters reporting for parent obj +# [ ] /users//meters -- list of meters reporting for parent obj +# +# [x] /projects//meters/ -- events +# [x] /resources//meters/ -- events +# [x] /sources//meters/ -- events +# [x] /users//meters/ -- events +# +# [ ] /projects//meters//duration -- total time for selected +# meter +# [ ] /resources//meters//duration -- total time for selected +# meter +# [ ] /sources//meters//duration -- total time for selected +# meter +# [ ] /users//meters//duration -- total time for selected meter +# +# [ ] /projects//meters//volume -- total or max volume for +# selected meter +# [ ] /resources//meters//volume -- total or max volume for +# selected meter +# [ ] /sources//meters//volume -- total or max volume for +# selected meter +# [ ] /users//meters//volume -- total or max volume for selected +# meter + import flask from ceilometer.openstack.common import log @@ -33,14 +82,8 @@ blueprint = flask.Blueprint('v1', __name__) ## APIs for working with resources. -@blueprint.route('/resources', defaults={'source': None}) -@blueprint.route('/sources//resources') -@blueprint.route('/users//resources') -@blueprint.route('/projects//resources') -@blueprint.route('/sources//users//resources') -@blueprint.route('/sources//projects//resources') -def list_resources(source=None, user=None, project=None): - """Return a list of resource names. +def _list_resources(source=None, user=None, project=None): + """Return a list of resource identifiers. """ resources = flask.request.storage_conn.get_resources( source=source, @@ -50,58 +93,103 @@ def list_resources(source=None, user=None, project=None): return flask.jsonify(resources=list(resources)) +@blueprint.route('/projects//resources') +def list_resources_by_project(project): + """Return a list of resources owned by the project. + + :param project: The ID of the owning project. + """ + return _list_resources(project=project) + + +@blueprint.route('/resources') +def list_all_resources(): + """Return a list of all known resources. + """ + return _list_resources() + + +@blueprint.route('/sources//resources') +def list_resources_by_source(source): + """Return a list of resources for which a source is reporting + data. + + :param source: The ID of the reporting source. + """ + return _list_resources(source=source) + + +@blueprint.route('/users//resources') +def list_resources_by_user(user): + """Return a list of resources owned by the user. + + :param user: The ID of the owning user. + """ + return _list_resources(user=user) + + ## APIs for working with users. -@blueprint.route('/users', defaults={'source': None}) -@blueprint.route('/sources//users') -def list_users(source): +def _list_users(source=None): """Return a list of user names. """ users = flask.request.storage_conn.get_users(source=source) return flask.jsonify(users=list(users)) +@blueprint.route('/users') +def list_all_users(): + """Return a list of all known user names. + """ + return _list_users() + + +@blueprint.route('/sources//users') +def list_users_by_source(source): + """Return a list of the users for which the source is reporting + data. + + :param source: The ID of the source. + """ + return _list_users(source=source) + + ## APIs for working with projects. -@blueprint.route('/projects', defaults={'source': None}) -@blueprint.route('/sources//projects') -def list_projects(source): +def _list_projects(source=None): """Return a list of project names. """ projects = flask.request.storage_conn.get_projects(source=source) return flask.jsonify(projects=list(projects)) +@blueprint.route('/projects') +def list_all_projects(): + """Return a list of all known project names. + """ + return _list_projects() + + +@blueprint.route('/sources//projects') +def list_projects_by_source(source): + """Return a list project names for which the source is reporting + data. + + :param source: The ID of the source. + """ + return _list_projects(source=source) + + ## APIs for working with events. -@blueprint.route('/projects/') -@blueprint.route('/projects//meters/') -@blueprint.route('/projects//resources/') -@blueprint.route('/projects//resources//meters/') -@blueprint.route('/sources//projects/') -@blueprint.route('/sources//projects//meters/') -@blueprint.route('/sources//projects//resources/') -@blueprint.route( - '/sources//projects//resources//meters/' - ) -@blueprint.route('/users/') -@blueprint.route('/users//meters/') -@blueprint.route('/users//resources/') -@blueprint.route('/users//resources//meters/') -@blueprint.route('/sources//users/') -@blueprint.route('/sources//users//meters/') -@blueprint.route('/sources//users//resources/') -@blueprint.route( - '/sources//users//resources//meters/' - ) -def list_events(user=None, - meter=None, +def _list_events(project=None, resource=None, source=None, - project=None, + user=None, + meter=None, ): """Return a list of raw metering events. """ @@ -113,3 +201,51 @@ def list_events(user=None, ) events = flask.request.storage_conn.get_raw_events(f) return flask.jsonify(events=list(events)) + + +@blueprint.route('/projects//meters/') +def list_events_by_project(project, meter): + """Return a list of raw metering events for the project. + + :param project: The ID of the project. + :param meter: The name of the meter. + """ + return _list_events(project=project, + meter=meter, + ) + + +@blueprint.route('/resources//meters/') +def list_events_by_resource(resource, meter): + """Return a list of raw metering events for the resource. + + :param resource: The ID of the resource. + :param meter: The name of the meter. + """ + return _list_events(resource=resource, + meter=meter, + ) + + +@blueprint.route('/sources//meters/') +def list_events_by_source(source, meter): + """Return a list of raw metering events for the source. + + :param source: The ID of the reporting source. + :param meter: The name of the meter. + """ + return _list_events(source=source, + meter=meter, + ) + + +@blueprint.route('/users//meters/') +def list_events_by_user(user, meter): + """Return a list of raw metering events for the user. + + :param user: The ID of the user. + :param meter: The name of the meter. + """ + return _list_events(user=user, + meter=meter, + ) diff --git a/tests/api/v1/test_list_events.py b/tests/api/v1/test_list_events.py index e3dd68699..01529b3ac 100644 --- a/tests/api/v1/test_list_events.py +++ b/tests/api/v1/test_list_events.py @@ -55,7 +55,7 @@ class TestListEvents(tests_api.TestBase): 'instance', 'cumulative', 1, - 'user-id', + 'user-id2', 'project2', 'resource-id-alternate', timestamp=datetime.datetime(2012, 7, 2, 10, 41), @@ -67,52 +67,38 @@ class TestListEvents(tests_api.TestBase): msg2 = meter.meter_message_from_counter(self.counter2) self.conn.record_metering_data(msg2) - def test_empty(self): - data = self.get('/users/no-such-user') + def test_all(self): + data = self.get('/resources') + self.assertEquals(2, len(data['resources'])) + + def test_empty_project(self): + data = self.get('/projects/no-such-project/meters/instance') self.assertEquals({'events': []}, data) - def test_with_user(self): - data = self.get('/users/user-id') - self.assertEquals(2, len(data['events'])) - - def test_with_user_and_meters(self): - data = self.get('/users/user-id/meters/instance') - self.assertEquals(2, len(data['events'])) - - def test_with_user_and_meters_invalid(self): - data = self.get('/users/user-id/meters/no-such-meter') - self.assertEquals(0, len(data['events'])) - - def test_with_source_and_user(self): - data = self.get('/sources/source1/users/user-id') - ids = [r['resource_id'] for r in data['events']] - self.assertEquals(['resource-id'], ids) - - def test_with_resource(self): - data = self.get('/users/user-id/resources/resource-id') - ids = [r['resource_id'] for r in data['events']] - self.assertEquals(['resource-id'], ids) - - - def test_with_project(self): - data = self.get('/projects/project1') - self.assertEquals(1, len(data['events'])) - - def test_with_project_and_meters(self): + def test_by_project(self): data = self.get('/projects/project1/meters/instance') self.assertEquals(1, len(data['events'])) - def test_with_project_and_meters_invalid(self): - data = self.get('/projects/project2/meters/no-such-meter') - self.assertEquals(0, len(data['events'])) + def test_empty_resource(self): + data = self.get('/resources/no-such-resource/meters/instance') + self.assertEquals({'events': []}, data) - def test_with_source_and_project(self): - data = self.get('/sources/source1/projects/project1') - ids = [r['resource_id'] for r in data['events']] - self.assertEquals(['resource-id'], ids) + def test_by_resource(self): + data = self.get('/resources/resource-id/meters/instance') + self.assertEquals(1, len(data['events'])) - def test_with_resource(self): - data = self.get('/projects/project1/resources/resource-id') - ids = [r['resource_id'] for r in data['events']] - self.assertEquals(['resource-id'], ids) + def test_empty_source(self): + data = self.get('/sources/no-such-source/meters/instance') + self.assertEquals({'events': []}, data) + def test_by_source(self): + data = self.get('/sources/source1/meters/instance') + self.assertEquals(1, len(data['events'])) + + def test_empty_user(self): + data = self.get('/users/no-such-user/meters/instance') + self.assertEquals({'events': []}, data) + + def test_by_user(self): + data = self.get('/users/user-id/meters/instance') + self.assertEquals(1, len(data['events']))