diff --git a/api-ref/source/v1/hosts.inc b/api-ref/source/v1/hosts.inc index 50f43a8a..02862a3e 100644 --- a/api-ref/source/v1/hosts.inc +++ b/api-ref/source/v1/hosts.inc @@ -243,3 +243,79 @@ Response -------- No body content is returned on a successful DELETE. + +==================== +Resource Allocations +==================== + +List Allocations +================ + +.. rest_method:: GET v1/os-hosts/allocations + +List allocations of all hosts. + +**Response codes** + +Normal response code: 200 + +Error response codes: Bad Request(400), Unauthorized(401), Forbidden(403), +Internal Server Error(500) + +Request +------- + +No body content, path, nor query option. + +Response +-------- + +.. rest_parameters:: parameters.yaml + + - allocations: allocations + - resource_id: host_id + - reservations: reservation_allocation + - reservation.id: reservation_id + - reservation.lease_id: lease_id + +**Example of List Allocations Response** + +.. literalinclude:: ../../../doc/api_samples/hosts/allocation-list-resp.json + :language: javascript + +Get Allocation +============== + +.. rest_method:: GET v1/os-hosts/{host_id}/allocation + +Get allocation of a host. + +**Response codes** + +Normal response code: 200 + +Error response codes: Bad Request(400), Unauthorized(401), Forbidden(403), +Internal Server Error(500) + +Request +------- + +.. rest_parameters:: parameters.yaml + + - host_id: host_id_path + +Response +-------- + +.. rest_parameters:: parameters.yaml + + - allocation: allocation + - resource_id: host_id + - reservations: reservation_allocation + - reservation.id: reservation_id + - reservation.lease_id: lease_id + +**Example of Get Allocation Response** + +.. literalinclude:: ../../../doc/api_samples/hosts/allocation-get-resp.json + :language: javascript diff --git a/api-ref/source/v1/parameters.yaml b/api-ref/source/v1/parameters.yaml index d09ed376..8592a981 100644 --- a/api-ref/source/v1/parameters.yaml +++ b/api-ref/source/v1/parameters.yaml @@ -13,6 +13,19 @@ lease_id_path: type: string # variables in body +allocation: + description: | + An ``allocation`` object. This object describes a mapping + between resource_id and reservations. + in: body + required: true + type: array +allocations: + description: | + A list of ``allocation`` objects. + in: body + required: true + type: array created_at: description: | The date and time when the object was created. @@ -300,6 +313,13 @@ reservation_aggregate_id: in: body required: true type: integer +reservation_allocation: + description: | + A list of ``reservation allocation`` objects. The object consists of + reservation id and its lease_id. + in: body + required: true + type: array reservation_amount: description: | The amount of instances to reserve. diff --git a/blazar/api/v1/oshosts/service.py b/blazar/api/v1/oshosts/service.py index 8a177203..565a5034 100644 --- a/blazar/api/v1/oshosts/service.py +++ b/blazar/api/v1/oshosts/service.py @@ -66,3 +66,23 @@ class API(object): :type host_id: str """ self.manager_rpcapi.delete_computehost(host_id) + + @policy.authorize('oshosts', 'get_allocations') + def list_allocations(self, query): + """List all allocations on all computehosts. + + :param query: parameters to query allocations + :type query: dict + """ + return self.manager_rpcapi.list_allocations(query) + + @policy.authorize('oshosts', 'get_allocations') + def get_allocations(self, host_id, query): + """List all allocations on a specified computehost. + + :param host_id: ID of the computehost in Blazar DB. + :type host_id: str + :param query: parameters to query allocations + :type query: dict + """ + return self.manager_rpcapi.get_allocations(host_id, query) diff --git a/blazar/api/v1/oshosts/v1_0.py b/blazar/api/v1/oshosts/v1_0.py index d15a3242..07e6d0e4 100644 --- a/blazar/api/v1/oshosts/v1_0.py +++ b/blazar/api/v1/oshosts/v1_0.py @@ -61,3 +61,16 @@ def computehosts_delete(host_id): """Delete specified computehost.""" _api.delete_computehost(host_id) return api_utils.render() + + +@rest.get('/allocations', query=True) +def allocations_list(query): + """List all allocations on all computehosts.""" + return api_utils.render(allocations=_api.list_allocations(query)) + + +@rest.get('//allocation', query=True) +@validation.check_exists(_api.get_computehost, host_id='host_id') +def allocations_get(host_id, query): + """List all allocations on a specific host.""" + return api_utils.render(allocation=_api.get_allocations(host_id, query)) diff --git a/blazar/manager/oshosts/rpcapi.py b/blazar/manager/oshosts/rpcapi.py index 23863913..6aad773c 100644 --- a/blazar/manager/oshosts/rpcapi.py +++ b/blazar/manager/oshosts/rpcapi.py @@ -55,3 +55,12 @@ class ManagerRPCAPI(service.RPCClient): """Delete specified computehost.""" return self.call('physical:host:delete_computehost', host_id=host_id) + + def list_allocations(self, query): + """List all allocations on all computehosts.""" + return self.call('physical:host:list_allocations', query=query) + + def get_allocations(self, host_id, query): + """List all allocations on a specified computehost.""" + return self.call('physical:host:get_allocations', + host_id=host_id, query=query) diff --git a/blazar/policies/oshosts.py b/blazar/policies/oshosts.py index 04c4873c..68a9143e 100644 --- a/blazar/policies/oshosts.py +++ b/blazar/policies/oshosts.py @@ -64,6 +64,21 @@ oshosts_policies = [ 'method': 'DELETE' } ] + ), + policy.DocumentedRuleDefault( + name=POLICY_ROOT % 'get_allocations', + check_str=base.RULE_ADMIN, + description='Policy rule for List/Get Host(s) Allocations API.', + operations=[ + { + 'path': '/{api_version}/os-hosts/allocations', + 'method': 'GET' + }, + { + 'path': '/{api_version}/os-hosts/{host_id}/allocation', + 'method': 'GET' + } + ] ) ] diff --git a/blazar/tests/api/v1/oshosts/test_v1_0.py b/blazar/tests/api/v1/oshosts/test_v1_0.py index ff16a3ba..869d5624 100644 --- a/blazar/tests/api/v1/oshosts/test_v1_0.py +++ b/blazar/tests/api/v1/oshosts/test_v1_0.py @@ -36,7 +36,8 @@ class RESTApiTestCase(tests.TestCase): 'update_computehost') self.delete_computehost = self.patch(self.s_api.API, 'delete_computehost') - + self.list_allocations = self.patch(self.s_api.API, 'list_allocations') + self.get_allocations = self.patch(self.s_api.API, 'get_allocations') self.fake_id = '1' def test_computehost_list(self): @@ -59,3 +60,12 @@ class RESTApiTestCase(tests.TestCase): def test_computehosts_delete(self): self.api.computehosts_delete(host_id=self.fake_id) self.render.assert_called_once_with() + + def test_allocation_list(self): + self.api.allocations_list(query={}) + self.render.assert_called_once_with( + allocations=self.list_allocations()) + + def test_allocation_get(self): + self.api.allocations_get(host_id=self.fake_id, query={}) + self.render.assert_called_once_with(allocation=self.get_allocations()) diff --git a/doc/api_samples/hosts/allocation-get-resp.json b/doc/api_samples/hosts/allocation-get-resp.json new file mode 100644 index 00000000..08cedb2a --- /dev/null +++ b/doc/api_samples/hosts/allocation-get-resp.json @@ -0,0 +1,15 @@ +{ + "allocation": { + "resource_id": "1", + "reservations": [ + { + "id": "3504fbac-fdb2-458e-a43f-34d27fbd0b86", + "lease_id": "0ec2bed6-75f9-4959-8198-9d9717dde4cb" + }, + { + "id": "4f4743a2-d8c7-44c2-ba39-300eb7659bb9", + "lease_id": "6050288d-5535-4e3c-93d5-083184b86c61" + } + ] + } +} diff --git a/doc/api_samples/hosts/allocation-list-resp.json b/doc/api_samples/hosts/allocation-list-resp.json new file mode 100644 index 00000000..b98393f6 --- /dev/null +++ b/doc/api_samples/hosts/allocation-list-resp.json @@ -0,0 +1,26 @@ +{ + "allocations": [ + { + "resource_id": "1", + "reservations": [ + { + "id": "3504fbac-fdb2-458e-a43f-34d27fbd0b86", + "lease_id": "0ec2bed6-75f9-4959-8198-9d9717dde4cb" + }, + { + "id": "4f4743a2-d8c7-44c2-ba39-300eb7659bb9", + "lease_id": "6050288d-5535-4e3c-93d5-083184b86c61" + } + ] + }, + { + "resource_id": "2", + "reservations": [ + { + "id": "b2475424-6872-43ec-857d-f4b50b403e97", + "lease_id": "e92b9d47-9078-47ec-a35c-27e67f7b8429" + } + ] + } + ] +}