From 0fbfa69930c8ff0c06ae53ac8c049eef1e75b50c Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Mon, 8 Nov 2021 22:50:18 +0000 Subject: [PATCH 1/6] Add third party plugin support --- blazarclient/command.py | 69 ++-- blazarclient/v1/client.py | 7 + blazarclient/v1/resources.py | 106 ++++++ blazarclient/v1/shell_commands/leases.py | 7 +- blazarclient/v1/shell_commands/resources.py | 336 ++++++++++++++++++++ setup.cfg | 12 +- 6 files changed, 511 insertions(+), 26 deletions(-) create mode 100644 blazarclient/v1/resources.py create mode 100644 blazarclient/v1/shell_commands/resources.py diff --git a/blazarclient/command.py b/blazarclient/command.py index 50b7e78..ff0291e 100644 --- a/blazarclient/command.py +++ b/blazarclient/command.py @@ -28,6 +28,8 @@ HEX_ELEM + '{4}', HEX_ELEM + '{4}', HEX_ELEM + '{12}']) +import logging +LOG = logging.getLogger(__name__) class OpenStackCommand(command.Command): """Base class for OpenStack commands.""" @@ -88,6 +90,26 @@ def get_client(self): else: return self.app.client + def get_manager_and_args( + self, parsed_args, args, add_to_body=False, blazar_client=None + ): + if not blazar_client: + blazar_client = self.get_client() + if hasattr(parsed_args, "resource") and hasattr(blazar_client, parsed_args.resource): + resource_manager = getattr(blazar_client, parsed_args.resource) + if add_to_body: + args["resource_type"] = self.resource + elif hasattr(parsed_args, "resource"): # If third party resource + resource_manager = blazar_client.resource + if add_to_body: + args["resource_type"] = parsed_args.resource + else: + args.insert(0, parsed_args.resource) + else: # Else, no --resource, normal usage + resource_manager = getattr(blazar_client, self.resource) + return resource_manager, args + + def get_parser(self, prog_name): parser = super(BlazarCommand, self).get_parser(prog_name) return parser @@ -135,7 +157,7 @@ def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) blazar_client = self.get_client() body = self.args2body(parsed_args) - resource_manager = getattr(blazar_client, self.resource) + resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client) data = resource_manager.create(**body) self.format_output_data(data) @@ -178,8 +200,8 @@ def run(self, parsed_args): self.id_pattern) else: res_id = parsed_args.id - resource_manager = getattr(blazar_client, self.resource) - resource_manager.update(res_id, **body) + resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client) + data = resource_manager.update(*args, **body) print('Updated %s: %s' % (self.resource, parsed_args.id), file=self.app.stdout) return @@ -189,7 +211,7 @@ class DeleteCommand(BlazarCommand): """Delete a given resource.""" api = 'reservation' - resource = None + resource = "resource" log = None def get_parser(self, prog_name): @@ -206,16 +228,15 @@ def get_parser(self, prog_name): def run(self, parsed_args): self.log.debug('run(%s)' % parsed_args) blazar_client = self.get_client() - resource_manager = getattr(blazar_client, self.resource) + res_id = parsed_args.id if self.allow_names: res_id = utils.find_resource_id_by_name_or_id(blazar_client, self.resource, parsed_args.id, self.name_key, self.id_pattern) - else: - res_id = parsed_args.id - resource_manager.delete(res_id) + resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client) + data = resource_manager.delete(*args) print('Deleted %s: %s' % (self.resource, parsed_args.id), file=self.app.stdout) return @@ -231,6 +252,8 @@ class ListCommand(BlazarCommand, lister.Lister): list_columns = [] unknown_parts_flag = True + list_fn_name = "list" + def args2body(self, parsed_args): params = {} if parsed_args.sort_by: @@ -249,8 +272,8 @@ def retrieve_list(self, parsed_args): """Retrieve a list of resources from Blazar server.""" blazar_client = self.get_client() body = self.args2body(parsed_args) - resource_manager = getattr(blazar_client, self.resource) - data = resource_manager.list(**body) + resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client) + data = getattr(resource_manager, self.list_fn_name)(**body) return data def setup_columns(self, info, parsed_args): @@ -292,7 +315,7 @@ def retrieve_list(self, parsed_args): """Retrieve a list of resources from Blazar server.""" blazar_client = self.get_client() body = self.args2body(parsed_args) - resource_manager = getattr(blazar_client, self.resource) + resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client) data = resource_manager.list_allocations(**body) return data @@ -317,18 +340,15 @@ def get_parser(self, prog_name): def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) blazar_client = self.get_client() - + res_id = parsed_args.id if self.allow_names: res_id = utils.find_resource_id_by_name_or_id(blazar_client, self.resource, parsed_args.id, self.name_key, self.id_pattern) - else: - res_id = parsed_args.id - - resource_manager = getattr(blazar_client, self.resource) - data = resource_manager.get(res_id) + resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client) + data = resource_manager.get(*args) self.format_output_data(data) return list(zip(*sorted(data.items()))) @@ -339,8 +359,8 @@ class ShowAllocationCommand(ShowCommand, show.ShowOne): def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) blazar_client = self.get_client() - resource_manager = getattr(blazar_client, self.resource) - data = resource_manager.get_allocation(parsed_args.id) + resource_manager, args = self.get_manager_and_args(parsed_args, [parsed_args.id], add_to_body=False, blazar_client=blazar_client) + data = resource_manager.get_allocation(*args) self.format_output_data(data) return list(zip(*sorted(data.items()))) @@ -377,8 +397,8 @@ def run(self, parsed_args): self.id_pattern) else: res_id = parsed_args.id - resource_manager = getattr(blazar_client, self.resource) - resource_manager.reallocate(res_id, body) + resource_manager, args = self.get_manager_and_args(parsed_args, [res_id, body], add_to_body=False, blazar_client=blazar_client) + resource_manager.reallocate(*args) print('Reallocated %s: %s' % (self.resource, parsed_args.id), file=self.app.stdout) return @@ -400,8 +420,9 @@ def get_parser(self, prog_name): def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) blazar_client = self.get_client() - resource_manager = getattr(blazar_client, self.resource) - data = resource_manager.get_capability(parsed_args.capability_name) + resource_manager, args = self.get_manager_and_args(parsed_args, [parsed_args.capability_name], add_to_body=False, blazar_client=blazar_client) + LOG.info(args) + data = resource_manager.get_capability(*args) self.format_output_data(data) return list(zip(*sorted(data.items()))) @@ -415,7 +436,7 @@ def run(self, parsed_args): self.log.debug('run(%s)' % parsed_args) blazar_client = self.get_client() body = self.args2body(parsed_args) - resource_manager = getattr(blazar_client, self.resource) + resource_manager, body = self.get_manager_and_args(parsed_args, body, add_to_body=True, blazar_client=blazar_client) resource_manager.set_capability(**body) print( 'Updated %s extra capability: %s' % ( diff --git a/blazarclient/v1/client.py b/blazarclient/v1/client.py index 0313a19..3ff8d2a 100644 --- a/blazarclient/v1/client.py +++ b/blazarclient/v1/client.py @@ -20,6 +20,7 @@ from blazarclient.v1 import hosts from blazarclient.v1 import leases from blazarclient.v1 import networks +from blazarclient.v1 import resources class Client(object): @@ -76,3 +77,9 @@ def __init__(self, blazar_url=None, auth_token=None, session=None, session=self.session, version=self.version, **kwargs) + self.resource = resources.ResourceClientManager( + blazar_url=self.blazar_url, + auth_token=self.auth_token, + session=self.session, + version=self.version, + **kwargs) diff --git a/blazarclient/v1/resources.py b/blazarclient/v1/resources.py new file mode 100644 index 0000000..29db09c --- /dev/null +++ b/blazarclient/v1/resources.py @@ -0,0 +1,106 @@ +# Copyright (c) 2019 StackHPC Ltd. +# +# 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. + +from blazarclient import base +from blazarclient.i18n import _ + +import logging +LOG = logging.getLogger(__name__) + +class ResourceClientManager(base.BaseClientManager): + def create(self, resource_type, data, **kwargs): + values = {'data': data} + values.update(**kwargs) + resp, body = self.request_manager.post(f'/{resource_type}', body=values) + return body['resource'] + + def get(self, resource_type, resource_id): + resp, body = self.request_manager.get( + f'/{resource_type}/{resource_id}') + return body['resource'] + + def update(self, resource_type, res_id, data, extras): + LOG.info("RESOURCE CLIENT UPDATE") + if not data and not extras: + return _('No information to update passed.') + LOG.info(data) + LOG.info(extras) + body = {"data": data, "extras": extras} + resp, body = self.request_manager.put( + f'/{resource_type}/{res_id}', body=body + ) + return body['resource'] + + def delete(self, resource_type, resource_id): + resp, body = self.request_manager.delete( + f'/{resource_type}/{resource_id}') + + def list(self, resource_type, sort_by=None): + resp, body = self.request_manager.get(f'/{resource_type}') + resources = body['resources'] + if sort_by: + resources = sorted(resources, key=lambda l: l[sort_by]) + return resources + + def get_allocation(self, resource_type, resource_id): + resp, body = self.request_manager.get( + f'/{resource_type}/{resource_id}/allocation') + return body['allocation'] + + def list_allocations(self, resource_type, sort_by=None): + resp, body = self.request_manager.get(f'/{resource_type}/allocations') + allocations = body['allocations'] + if sort_by: + allocations = sorted(allocations, key=lambda l: l[sort_by]) + return allocations + + def reallocate(self, resource_type, resource_id, values): + resp, body = self.request_manager.put( + f'/{resource_type}/{resource_id}/allocation', body=values) + return body['allocation'] + + def list_capabilities(self, resource_type, detail=False, sort_by=None): + url = f'/{resource_type}/properties' + + if detail: + url += '?detail=True' + + resp, body = self.request_manager.get(url) + resource_properties = body['resource_properties'] + + # Values is a reserved word in cliff so need to rename values column. + if detail: + for p in resource_properties: + p['capability_values'] = p['values'] + del p['values'] + + if sort_by: + resource_properties = sorted(resource_properties, + key=lambda l: l[sort_by]) + return resource_properties + + def get_capability(self, resource_type, capability_name): + resource_property = [ + x for x in self.list_capabilities(resource_type, detail=True) + if x['property'] == capability_name] + + return {} if not resource_property else resource_property[0] + + def set_capability(self, resource_type, capability_name, private): + data = {'private': private} + resp, body = self.request_manager.patch( + f'/{resource_type}/properties/{capability_name}', body=data) + + return body['resource_property'] diff --git a/blazarclient/v1/shell_commands/leases.py b/blazarclient/v1/shell_commands/leases.py index 02b13b7..b9074ef 100644 --- a/blazarclient/v1/shell_commands/leases.py +++ b/blazarclient/v1/shell_commands/leases.py @@ -67,7 +67,10 @@ "resource_type": 'device' }, "others": { - ".*": None + "min": "", + "max": "", + "resource_properties": {}, + "resource_type": "", } } @@ -280,6 +283,8 @@ def _parse_params(self, str_params, default, err_msg): prog = re.compile('^(?:(.*),)?(%s)=(.*)$' % "|".join(default.keys())) + self.log.info("%s", str_params) + self.log.info("%s", default) while str_params != "": match = prog.search(str_params) diff --git a/blazarclient/v1/shell_commands/resources.py b/blazarclient/v1/shell_commands/resources.py new file mode 100644 index 0000000..2ad0a6f --- /dev/null +++ b/blazarclient/v1/shell_commands/resources.py @@ -0,0 +1,336 @@ +# Copyright (c) 2019 StackHPC Ltd. +# +# 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. + +import logging + +from oslo_serialization import jsonutils + +from blazarclient import command +from blazarclient import exception + +RESOURCE_ID_PATTERN = '^[0-9]+$' + + +class ListResources(command.ListCommand): + resource = "resource" + log = logging.getLogger(__name__ + '.ListResources') + list_columns = ['id', 'data'] + + def get_parser(self, prog_name): + parser = super(ListResources, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource to list', + ) + parser.add_argument( + '--sort-by', metavar="", + help='column name used to sort result', + default='id' + ) + return parser + + def args2body(self, parsed_args): + params = super(ListResources, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class ShowResource(command.ShowCommand): + resource = "resource" + allow_names = False + json_indent = 4 + log = logging.getLogger(__name__ + '.ShowResource') + + def get_parser(self, prog_name): + parser = super(ShowResource, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(ShowResource, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class CreateResource(command.CreateCommand): + resource = "resource" + json_indent = 4 + log = logging.getLogger(__name__ + '.CreateResource') + + def get_parser(self, prog_name): + parser = super(CreateResource, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + parser.add_argument( + 'data', metavar='DATA', + help='json data for the resource' + ) + return parser + + def args2body(self, parsed_args): + params = super(CreateResource, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + if parsed_args.data: + params['data'] = jsonutils.loads(parsed_args.data) + return params + + +class UpdateResource(command.UpdateCommand): + resource = 'resource' + json_indent = 4 + log = logging.getLogger(__name__ + '.UpdateResource') + + def get_parser(self, prog_name): + parser = super(UpdateResource, self).get_parser(prog_name) + parser.add_argument( + '--extra', metavar='=', + action='append', + dest='extra_capabilities', + default=[], + help='Extra capabilities key/value pairs to update for the resource' + ) + parser.add_argument( + '--data', metavar='', dest='data', default=None, + help='New data JSON object for resource' + ) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = {} + extras = {} + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + params['data'] = parsed_args.data + if parsed_args.extra_capabilities: + for capa in parsed_args.extra_capabilities: + key, _sep, value = capa.partition('=') + # NOTE(sbauza): multiple copies of the same capability will + # result in only the last value to be stored + extras[key] = value + params['extras'] = extras + return params + + +class DeleteResource(command.DeleteCommand): + resource = "resource" + allow_names = False + log = logging.getLogger(__name__ + '.DeleteResource') + + def get_parser(self, prog_name): + parser = super(DeleteResource, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(DeleteResource, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class ShowResourceAllocation(command.ShowAllocationCommand): + resource = 'resource' + json_indent = 4 + log = logging.getLogger(__name__ + '.ShowResourceAllocation') + + def get_parser(self, prog_name): + parser = super(ShowResourceAllocation, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(ShowResourceAllocation, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class ListResourceAllocations(command.ListAllocationCommand): + resource = None + log = logging.getLogger(__name__ + '.ListResourceAllocations') + list_columns = ['resource_id', 'reservations'] + + def get_parser(self, prog_name): + parser = super(ListResourceAllocations, self).get_parser(prog_name) + parser.add_argument( + '--sort-by', metavar="", + help='column name used to sort result', + default='resource_id' + ) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(ListResourceAllocations, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class ReallocateResource(command.ReallocateCommand): + resource = "resource" + json_indent = 4 + log = logging.getLogger(__name__ + '.ReallocateResource') + id_pattern = RESOURCE_ID_PATTERN + + def get_parser(self, prog_name): + parser = super(ReallocateResource, self).get_parser(prog_name) + parser.add_argument( + '--lease-id', + help='Lease ID to reallocate resource from.') + parser.add_argument( + '--reservation-id', + help='Reservation ID to reallocate resource from') + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = {} + + if parsed_args.reservation_id: + params['reservation_id'] = parsed_args.reservation_id + elif parsed_args.lease_id: + params['lease_id'] = parsed_args.lease_id + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + + return params + + +class ShowResourceCapability(command.ShowCapabilityCommand): + resource = 'resource' + json_indent = 4 + log = logging.getLogger(__name__ + '.ShowResourceCapability') + + def get_parser(self, prog_name): + parser = super(ShowResourceCapability, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(ShowResourceCapability, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + + +class ListResourceCapabilities(command.ListCommand): + resource = 'resource' + log = logging.getLogger(__name__ + '.ListResourceCapabilities') + list_columns = ['property', 'private', 'capability_values'] + list_fn_name = "list_capabilities" + + def args2body(self, parsed_args): + params = {'detail': parsed_args.detail} + if parsed_args.sort_by: + if parsed_args.sort_by in self.list_columns: + params['sort_by'] = parsed_args.sort_by + else: + msg = 'Invalid sort option %s' % parsed_args.sort_by + raise exception.BlazarClientException(msg) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + + return params + + def get_parser(self, prog_name): + parser = super(ListResourceCapabilities, self).get_parser(prog_name) + parser.add_argument( + '--detail', + action='store_true', + help='Return capabilities with values and attributes.', + default=False + ) + parser.add_argument( + '--sort-by', metavar="", + help='column name used to sort result', + default='property' + ) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + +class UpdateResourceCapability(command.UpdateCapabilityCommand): + resource = 'resource' + json_indent = 4 + log = logging.getLogger(__name__ + '.UpdateResourceCapability') + name_key = 'capability_name' + + def get_parser(self, prog_name): + parser = super(UpdateResourceCapability, self).get_parser(prog_name) + parser.add_argument( + '--resource', metavar="", + help='resource type to show', + ) + return parser + + def args2body(self, parsed_args): + params = super(UpdateResourceCapability, self).args2body(parsed_args) + if parsed_args.resource: + self.resource = parsed_args.resource + else: + raise exception.BlazarClientException("Resource not specified") + return params + diff --git a/setup.cfg b/setup.cfg index 430270d..63eb363 100644 --- a/setup.cfg +++ b/setup.cfg @@ -79,4 +79,14 @@ openstack.reservation.v1 = reservation_network_set = blazarclient.v1.shell_commands.networks:UpdateNetwork reservation_network_unset = blazarclient.v1.shell_commands.networks:UnsetAttributeNetwork reservation_network_show = blazarclient.v1.shell_commands.networks:ShowNetwork - + reservation_resource_create = blazarclient.v1.shell_commands.resources:CreateResource + reservation_resource_delete = blazarclient.v1.shell_commands.resources:DeleteResource + reservation_resource_list = blazarclient.v1.shell_commands.resources:ListResources + reservation_resource_set = blazarclient.v1.shell_commands.resources:UpdateResource + reservation_resource_show = blazarclient.v1.shell_commands.resources:ShowResource + reservation_resource_allocation_list = blazarclient.v1.shell_commands.resources:ListResourceAllocations + reservation_resource_allocation_show = blazarclient.v1.shell_commands.resources:ShowResourceAllocation + reservation_resource_capability_show = blazarclient.v1.shell_commands.resources:ShowResourceCapability + reservation_resource_capability_list = blazarclient.v1.shell_commands.resources:ListResourceCapabilities + reservation_resource_capability_update = blazarclient.v1.shell_commands.resources:UpdateResourceCapability + reservation_resource_reallocate = blazarclient.v1.shell_commands.resources:ReallocateResource From ca5c7e25f653c8a2e11f95b07211d91685a2e1c5 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Thu, 18 Nov 2021 22:51:42 +0000 Subject: [PATCH 2/6] Add resouces endpoint command --- blazarclient/v1/resources.py | 6 ++++++ blazarclient/v1/shell_commands/resources.py | 16 ++++++++++++++++ setup.cfg | 1 + 3 files changed, 23 insertions(+) diff --git a/blazarclient/v1/resources.py b/blazarclient/v1/resources.py index 29db09c..79a3b8b 100644 --- a/blazarclient/v1/resources.py +++ b/blazarclient/v1/resources.py @@ -20,6 +20,12 @@ LOG = logging.getLogger(__name__) class ResourceClientManager(base.BaseClientManager): + def list_resources(self, sort_by=None): + resp, body = self.request_manager.get('/resources') + if sort_by: + resources = sorted(body, key=lambda l: l[sort_by]) + return body + def create(self, resource_type, data, **kwargs): values = {'data': data} values.update(**kwargs) diff --git a/blazarclient/v1/shell_commands/resources.py b/blazarclient/v1/shell_commands/resources.py index 2ad0a6f..076394d 100644 --- a/blazarclient/v1/shell_commands/resources.py +++ b/blazarclient/v1/shell_commands/resources.py @@ -23,6 +23,21 @@ RESOURCE_ID_PATTERN = '^[0-9]+$' +class ListResourceTypes(command.ListCommand): + resource = "resource" + log = logging.getLogger(__name__ + '.ListResourceTypes') + list_columns = ['name', 'prefix'] + list_fn_name = 'list_resources' + + def get_parser(self, prog_name): + parser = super(ListResourceTypes, self).get_parser(prog_name) + parser.add_argument( + '--sort-by', metavar="", + help='column name used to sort result', + default='name' + ) + return parser + class ListResources(command.ListCommand): resource = "resource" log = logging.getLogger(__name__ + '.ListResources') @@ -219,6 +234,7 @@ class ReallocateResource(command.ReallocateCommand): json_indent = 4 log = logging.getLogger(__name__ + '.ReallocateResource') id_pattern = RESOURCE_ID_PATTERN + allow_names = False def get_parser(self, prog_name): parser = super(ReallocateResource, self).get_parser(prog_name) diff --git a/setup.cfg b/setup.cfg index 63eb363..5b0d474 100644 --- a/setup.cfg +++ b/setup.cfg @@ -90,3 +90,4 @@ openstack.reservation.v1 = reservation_resource_capability_list = blazarclient.v1.shell_commands.resources:ListResourceCapabilities reservation_resource_capability_update = blazarclient.v1.shell_commands.resources:UpdateResourceCapability reservation_resource_reallocate = blazarclient.v1.shell_commands.resources:ReallocateResource + reservation_resources_list=blazarclient.v1.shell_commands.resources:ListResourceTypes From 452f159447c597714ac0cc1f9b9730af6990d749 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Mon, 12 Jun 2023 19:54:37 +0000 Subject: [PATCH 3/6] Fix update method --- blazarclient/utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/blazarclient/utils.py b/blazarclient/utils.py index 57adb46..1ccadcc 100644 --- a/blazarclient/utils.py +++ b/blazarclient/utils.py @@ -120,8 +120,12 @@ def find_resource_id_by_name_or_id(client, resource_type, name_or_id, def _find_resource_id_by_name(client, resource_type, name, name_key): - resource_manager = getattr(client, resource_type) - resources = resource_manager.list() + if hasattr(client, resource_type): + resource_manager = getattr(client, resource_type) + resources = resource_manager.list() + else: # If third party resource + resource_manager = client.resource + resources = resource_manager.list(resource_type) named_resources = [] key = name_key if name_key else 'name' From 17d113dc818ab82608ff5b31985c43160ebd4884 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Thu, 13 Jul 2023 14:40:15 +0000 Subject: [PATCH 4/6] Clean up code --- blazarclient/command.py | 27 ++++++++++++++------------- blazarclient/v1/hosts.py | 2 +- blazarclient/v1/resources.py | 5 +---- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/blazarclient/command.py b/blazarclient/command.py index ff0291e..0218f9c 100644 --- a/blazarclient/command.py +++ b/blazarclient/command.py @@ -95,18 +95,18 @@ def get_manager_and_args( ): if not blazar_client: blazar_client = self.get_client() - if hasattr(parsed_args, "resource") and hasattr(blazar_client, parsed_args.resource): - resource_manager = getattr(blazar_client, parsed_args.resource) - if add_to_body: - args["resource_type"] = self.resource - elif hasattr(parsed_args, "resource"): # If third party resource - resource_manager = blazar_client.resource - if add_to_body: - args["resource_type"] = parsed_args.resource - else: - args.insert(0, parsed_args.resource) + if hasattr(parsed_args, "resource"): # Passed in via --resource flag + if hasattr(blazar_client, parsed_args.resource): # Not built-in type + resource_manager = getattr(blazar_client, parsed_args.resource) + else: # A built-in resource type + resource_manager = blazar_client.resource else: # Else, no --resource, normal usage resource_manager = getattr(blazar_client, self.resource) + # Update resource type depending on calling method + if add_to_body: + args["resource_type"] = parsed_args.resource + else: + args.insert(0, parsed_args.resource) return resource_manager, args @@ -201,7 +201,7 @@ def run(self, parsed_args): else: res_id = parsed_args.id resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client) - data = resource_manager.update(*args, **body) + resource_manager.update(*args, **body) print('Updated %s: %s' % (self.resource, parsed_args.id), file=self.app.stdout) return @@ -228,15 +228,16 @@ def get_parser(self, prog_name): def run(self, parsed_args): self.log.debug('run(%s)' % parsed_args) blazar_client = self.get_client() - res_id = parsed_args.id if self.allow_names: res_id = utils.find_resource_id_by_name_or_id(blazar_client, self.resource, parsed_args.id, self.name_key, self.id_pattern) + else: + res_id = parsed_args.id resource_manager, args = self.get_manager_and_args(parsed_args, [res_id], add_to_body=False, blazar_client=blazar_client) - data = resource_manager.delete(*args) + resource_manager.delete(*args) print('Deleted %s: %s' % (self.resource, parsed_args.id), file=self.app.stdout) return diff --git a/blazarclient/v1/hosts.py b/blazarclient/v1/hosts.py index b403249..72ebad1 100644 --- a/blazarclient/v1/hosts.py +++ b/blazarclient/v1/hosts.py @@ -43,7 +43,7 @@ def update(self, host_id, values): def delete(self, host_id): """Delete host with specified ID.""" - resp, body = self.request_manager.delete('/os-hosts/%s' % host_id) + self.request_manager.delete('/os-hosts/%s' % host_id) def list(self, sort_by=None): """List all hosts.""" diff --git a/blazarclient/v1/resources.py b/blazarclient/v1/resources.py index 79a3b8b..485c391 100644 --- a/blazarclient/v1/resources.py +++ b/blazarclient/v1/resources.py @@ -23,7 +23,7 @@ class ResourceClientManager(base.BaseClientManager): def list_resources(self, sort_by=None): resp, body = self.request_manager.get('/resources') if sort_by: - resources = sorted(body, key=lambda l: l[sort_by]) + body = sorted(body, key=lambda l: l[sort_by]) return body def create(self, resource_type, data, **kwargs): @@ -38,11 +38,8 @@ def get(self, resource_type, resource_id): return body['resource'] def update(self, resource_type, res_id, data, extras): - LOG.info("RESOURCE CLIENT UPDATE") if not data and not extras: return _('No information to update passed.') - LOG.info(data) - LOG.info(extras) body = {"data": data, "extras": extras} resp, body = self.request_manager.put( f'/{resource_type}/{res_id}', body=body From 107dd0d11ebba5ceafa80c20fb7ca9899b2a53f3 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Fri, 14 Jul 2023 17:16:43 +0000 Subject: [PATCH 5/6] Fix resource type parsing --- blazarclient/command.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/blazarclient/command.py b/blazarclient/command.py index 0218f9c..d6b98b2 100644 --- a/blazarclient/command.py +++ b/blazarclient/command.py @@ -95,18 +95,21 @@ def get_manager_and_args( ): if not blazar_client: blazar_client = self.get_client() + if hasattr(parsed_args, "resource"): # Passed in via --resource flag if hasattr(blazar_client, parsed_args.resource): # Not built-in type resource_manager = getattr(blazar_client, parsed_args.resource) + if add_to_body: + args["resource_type"] = parsed_args.resource + else: + args.insert(0, parsed_args.resource) else: # A built-in resource type resource_manager = blazar_client.resource + if add_to_body: + args["resource_type"] = self.resource else: # Else, no --resource, normal usage resource_manager = getattr(blazar_client, self.resource) # Update resource type depending on calling method - if add_to_body: - args["resource_type"] = parsed_args.resource - else: - args.insert(0, parsed_args.resource) return resource_manager, args From bd0d551900dd42adb3738a4cb398e6bf24a34857 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Wed, 26 Jul 2023 17:12:53 +0000 Subject: [PATCH 6/6] Fix args for delete --- blazarclient/command.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/blazarclient/command.py b/blazarclient/command.py index d6b98b2..39d3654 100644 --- a/blazarclient/command.py +++ b/blazarclient/command.py @@ -97,7 +97,7 @@ def get_manager_and_args( blazar_client = self.get_client() if hasattr(parsed_args, "resource"): # Passed in via --resource flag - if hasattr(blazar_client, parsed_args.resource): # Not built-in type + if hasattr(blazar_client, parsed_args.resource): # A built-in type resource_manager = getattr(blazar_client, parsed_args.resource) if add_to_body: args["resource_type"] = parsed_args.resource @@ -107,6 +107,8 @@ def get_manager_and_args( resource_manager = blazar_client.resource if add_to_body: args["resource_type"] = self.resource + else: + args.insert(0, parsed_args.resource) else: # Else, no --resource, normal usage resource_manager = getattr(blazar_client, self.resource) # Update resource type depending on calling method