diff --git a/iotronicclient/v1/client.py b/iotronicclient/v1/client.py index b420052..3f6e9ce 100644 --- a/iotronicclient/v1/client.py +++ b/iotronicclient/v1/client.py @@ -20,6 +20,7 @@ from iotronicclient.common.i18n import _ from iotronicclient import exc from iotronicclient.v1 import board from iotronicclient.v1 import exposed_service +from iotronicclient.v1 import fleet from iotronicclient.v1 import plugin from iotronicclient.v1 import plugin_injection from iotronicclient.v1 import port @@ -71,3 +72,4 @@ class Client(object): self.http_client) self.portonboard = port.PortOnBoardManager( self.http_client) + self.fleet = fleet.FleetManager(self.http_client) diff --git a/iotronicclient/v1/fleet.py b/iotronicclient/v1/fleet.py new file mode 100644 index 0000000..f1909a9 --- /dev/null +++ b/iotronicclient/v1/fleet.py @@ -0,0 +1,97 @@ +# 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 iotronicclient.common import base +from iotronicclient.common.i18n import _ +from iotronicclient.common import utils +from iotronicclient import exc + +LOG = logging.getLogger(__name__) +_DEFAULT_POLL_INTERVAL = 2 + + +class Fleet(base.Resource): + def __repr__(self): + return "" % self._info + + +class FleetManager(base.CreateManager): + resource_class = Fleet + _creation_attributes = ['name', 'description', 'extra'] + + _resource_name = 'fleets' + + def list(self, marker=None, limit=None, + detail=False, sort_key=None, sort_dir=None, fields=None): + """Retrieve a list of fleets. + + :param marker: Optional, the UUID of a fleet, eg the last + fleet from a previous result set. Return + the next result set. + :param limit: The maximum number of results to return per + request, if: + + 1) limit > 0, the maximum number of fleets to return. + 2) limit == 0, return the entire list of fleets. + 3) limit param is NOT specified (None), the number of items + returned respect the maximum imposed by the Iotronic API + (see Iotronic's api.max_limit option). + + :param detail: Optional, boolean whether to return detailed information + about fleets. + + :param sort_key: Optional, field used for sorting. + + :param sort_dir: Optional, direction of sorting, either 'asc' (the + default) or 'desc'. + + :param fields: Optional, a list with a specified set of fields + of the resource to be returned. Can not be used + when 'detail' is set. + + :returns: A list of fleets. + + """ + if limit is not None: + limit = int(limit) + + if detail and fields: + raise exc.InvalidAttribute(_("Can't fetch a subset of fields " + "with 'detail' set")) + + filters = utils.common_filters(marker, limit, sort_key, sort_dir, + fields) + path = '' + + if detail: + path += 'detail' + + if filters: + path += '?' + '&'.join(filters) + + if limit is None: + return self._list(self._path(path), "fleets") + else: + return self._list_pagination(self._path(path), "fleets", + limit=limit) + + def get(self, fleet_id, fields=None): + return self._get(resource_id=fleet_id, fields=fields) + + def delete(self, fleet_id): + return self._delete(resource_id=fleet_id) + + def update(self, fleet_id, patch, http_method='PATCH'): + return self._update(resource_id=fleet_id, patch=patch, + method=http_method) diff --git a/iotronicclient/v1/fleet_shell.py b/iotronicclient/v1/fleet_shell.py new file mode 100644 index 0000000..7143a92 --- /dev/null +++ b/iotronicclient/v1/fleet_shell.py @@ -0,0 +1,184 @@ +# 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 iotronicclient.common.apiclient import exceptions +from iotronicclient.common import cliutils +from iotronicclient.common.i18n import _ +from iotronicclient.common import utils +from iotronicclient.v1 import resource_fields as res_fields + + +def _print_fleet_show(fleet, fields=None, json=False): + if fields is None: + fields = res_fields.FLEET_DETAILED_RESOURCE.fields + + data = dict( + [(f, getattr(fleet, f, '')) for f in fields]) + cliutils.print_dict(data, wrap=72, json_flag=json) + + +@cliutils.arg( + 'fleet', + metavar='', + help="Name or UUID of the fleet ") +@cliutils.arg( + '--fields', + nargs='+', + dest='fields', + metavar='', + action='append', + default=[], + help="One or more fleet fields. Only these fields will be fetched from " + "the server.") +def do_fleet_show(cc, args): + """Show detailed information about a fleet.""" + fields = args.fields[0] if args.fields else None + utils.check_empty_arg(args.fleet, '') + utils.check_for_invalid_fields( + fields, res_fields.FLEET_DETAILED_RESOURCE.fields) + fleet = cc.fleet.get(args.fleet, fields=fields) + _print_fleet_show(fleet, fields=fields, json=args.json) + + +@cliutils.arg( + '--limit', + metavar='', + type=int, + help='Maximum number of fleets to return per request, ' + '0 for no limit. Default is the maximum number used ' + 'by the Iotronic API Fleet.') +@cliutils.arg( + '--marker', + metavar='', + help='Fleet UUID (for example, of the last fleet in the list from ' + 'a previous request). Returns the list of fleets after this UUID.') +@cliutils.arg( + '--sort-key', + metavar='', + help='Fleet field that will be used for sorting.') +@cliutils.arg( + '--sort-dir', + metavar='', + choices=['asc', 'desc'], + help='Sort direction: "asc" (the default) or "desc".') +@cliutils.arg( + '--detail', + dest='detail', + action='store_true', + default=False, + help="Show detailed information about the fleets.") +@cliutils.arg( + '--fields', + nargs='+', + dest='fields', + metavar='', + action='append', + default=[], + help="One or more fleet fields. Only these fields will be fetched from " + "the server. Can not be used when '--detail' is specified.") +def do_fleet_list(cc, args): + """List the fleets which are registered with the Iotronic fleet.""" + params = {} + + if args.detail: + fields = res_fields.FLEET_DETAILED_RESOURCE.fields + field_labels = res_fields.FLEET_DETAILED_RESOURCE.labels + elif args.fields: + utils.check_for_invalid_fields( + args.fields[0], res_fields.FLEET_DETAILED_RESOURCE.fields) + resource = res_fields.Resource(args.fields[0]) + fields = resource.fields + field_labels = resource.labels + else: + fields = res_fields.FLEET_RESOURCE.fields + field_labels = res_fields.FLEET_RESOURCE.labels + + sort_fields = res_fields.FLEET_DETAILED_RESOURCE.sort_fields + sort_field_labels = res_fields.FLEET_DETAILED_RESOURCE.sort_labels + + params.update(utils.common_params_for_list(args, + sort_fields, + sort_field_labels)) + + fleets = cc.fleet.list(**params) + cliutils.print_list(fleets, fields, + field_labels=field_labels, + sortby_index=None, + json_flag=args.json) + + +@cliutils.arg( + 'name', + metavar='', + help="Name or UUID of the fleet ") +@cliutils.arg( + '--description', + dest='description', + default="", + help="Description of the fleet") +def do_fleet_create(cc, args): + """Register a new fleet with the Iotronic fleet.""" + + field_list = ['name', 'description', 'extra'] + + fields = dict((k, v) for (k, v) in vars(args).items() + if k in field_list and not (v is None)) + + fields = utils.args_array_to_dict(fields, 'extra') + + fleet = cc.fleet.create(**fields) + + data = dict([(f, getattr(fleet, f, '')) for f in + res_fields.FLEET_DETAILED_RESOURCE.fields]) + + cliutils.print_dict(data, wrap=72, json_flag=args.json) + + +@cliutils.arg('fleet', + metavar='', + nargs='+', + help="Name or UUID of the fleet.") +def do_fleet_delete(cc, args): + """Unregister fleet(s) from the Iotronic fleet. + + Returns errors for any fleets that could not be unregistered. + """ + + failures = [] + for n in args.fleet: + try: + cc.fleet.delete(n) + print(_('Deleted fleet %s') % n) + except exceptions.ClientException as e: + failures.append( + _("Failed to delete fleet %(fleet)s: %(error)s") + % {'fleet': n, 'error': e}) + if failures: + raise exceptions.ClientException("\n".join(failures)) + + +@cliutils.arg('fleet', metavar='', + help="Name or UUID of the fleet.") +@cliutils.arg( + 'attributes', + metavar='', + nargs='+', + action='append', + default=[], + help="Values to be changed.") +def do_fleet_update(cc, args): + """Update information about a registered fleet.""" + + patch = {k: v for k, v in (x.split('=') for x in args.attributes[0])} + + fleet = cc.fleet.update(args.fleet, patch) + _print_fleet_show(fleet, json=args.json) diff --git a/iotronicclient/v1/resource_fields.py b/iotronicclient/v1/resource_fields.py index 83182dc..dcbcc29 100644 --- a/iotronicclient/v1/resource_fields.py +++ b/iotronicclient/v1/resource_fields.py @@ -61,7 +61,8 @@ class Resource(object): 'MAC_add': 'Mac Address', 'VIF_name': 'VIF', 'network': 'Network', - 'ip': 'ip' + 'ip': 'ip', + 'description': 'Description', # # 'address': 'Address', @@ -70,7 +71,6 @@ class Resource(object): # 'chassis_uuid': 'Chassis UUID', # 'clean_step': 'Clean Step', # 'console_enabled': 'Console Enabled', - # 'description': 'Description', # 'http_methods': 'Supported HTTP methods', # 'inspection_finished_at': 'Inspection Finished At', # 'inspection_started_at': 'Inspection Started At', @@ -257,6 +257,8 @@ EXPOSED_SERVICE_RESOURCE = Resource( 'updated_at', ]) +# Port + PORT_RESOURCE = Resource( ['uuid', 'MAC_add', @@ -266,7 +268,6 @@ PORT_RESOURCE = Resource( 'ip' ] ) -# Service PORT_DETAILED_RESOURCE = Resource( ['uuid', @@ -282,3 +283,25 @@ PORT_DETAILED_RESOURCE = Resource( sort_excluded=[ 'extra', ]) + +# Fleet + +FLEET_DETAILED_RESOURCE = Resource( + ['uuid', + 'name', + 'project', + 'description', + 'extra', + 'created_at', + 'updated_at', + ], + sort_excluded=[ + 'extra', + ]) + +FLEET_RESOURCE = Resource( + ['uuid', + 'name', + 'project', + 'description' + ]) diff --git a/iotronicclient/v1/shell.py b/iotronicclient/v1/shell.py index 58c3aa3..b0fbac0 100644 --- a/iotronicclient/v1/shell.py +++ b/iotronicclient/v1/shell.py @@ -14,6 +14,7 @@ from iotronicclient.common import utils from iotronicclient.v1 import board_shell from iotronicclient.v1 import exposed_service_shell +from iotronicclient.v1 import fleet_shell from iotronicclient.v1 import plugin_injection_shell from iotronicclient.v1 import plugin_shell from iotronicclient.v1 import port_shell @@ -26,6 +27,7 @@ COMMAND_MODULES = [ service_shell, exposed_service_shell, port_shell, + fleet_shell, ]