# Copyright (c) 2013 Mirantis Inc. # # 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 __future__ import print_function import logging import six from cliff import command from cliff.formatters import table from cliff import lister from cliff import show from climateclient import utils class OpenStackCommand(command.Command): """Base class for OpenStack commands.""" api = None def run(self, parsed_args): if not self.api: return else: return super(OpenStackCommand, self).run(parsed_args) def get_data(self, parsed_args): pass def take_action(self, parsed_args): return self.get_data(parsed_args) class TableFormatter(table.TableFormatter): """This class is used to keep consistency with prettytable 0.6.""" def emit_list(self, column_names, data, stdout, parsed_args): if column_names: super(TableFormatter, self).emit_list(column_names, data, stdout, parsed_args) else: stdout.write('\n') class ClimateCommand(OpenStackCommand): """Base Climate CLI command.""" api = 'reservation' log = logging.getLogger(__name__ + '.ClimateCommand') values_specs = [] json_indent = None resource = None def __init__(self, app, app_args): super(ClimateCommand, self).__init__(app, app_args) # NOTE(dbelova): This is no longer supported in cliff version 1.5.2 # the same moment occurred in Neutron: # see https://bugs.launchpad.net/python-neutronclient/+bug/1265926 # if hasattr(self, 'formatters'): # self.formatters['table'] = TableFormatter() def get_client(self): return self.app.client def get_parser(self, prog_name): parser = super(ClimateCommand, self).get_parser(prog_name) return parser def format_output_data(self, data): for k, v in six.iteritems(data): if isinstance(v, list): value = '\n'.join(utils.dumps( i, indent=self.json_indent) if isinstance(i, dict) else str(i) for i in v) data[k] = value elif isinstance(v, dict): value = utils.dumps(v, indent=self.json_indent) data[k] = value elif v is None: data[k] = '' def add_known_arguments(self, parser): pass def args2body(self, parsed_args): return {} class CreateCommand(ClimateCommand, show.ShowOne): """Create resource with passed args.""" api = 'reservation' resource = None log = None def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) climate_client = self.get_client() body = self.args2body(parsed_args) resource_manager = getattr(climate_client, self.resource) data = resource_manager.create(**body) self.format_output_data(data) if data: print(self.app.stdout, 'Created a new %s:' % self.resource) else: data = {'': ''} return zip(*sorted(six.iteritems(data))) class UpdateCommand(ClimateCommand): """Update resource's information.""" api = 'reservation' resource = None log = None def get_parser(self, prog_name): parser = super(UpdateCommand, self).get_parser(prog_name) parser.add_argument( 'id', metavar=self.resource.upper(), help='ID or name of %s to update' % self.resource ) self.add_known_arguments(parser) return parser def run(self, parsed_args): self.log.debug('run(%s)' % parsed_args) climate_client = self.get_client() body = self.args2body(parsed_args) res_id = utils.find_resource_id_by_name_or_id(climate_client, self.resource, parsed_args.id) resource_manager = getattr(climate_client, self.resource) resource_manager.update(res_id, **body) print(self.app.stdout, 'Updated %s: %s' % (self.resource, parsed_args.id)) return class DeleteCommand(ClimateCommand): """Delete a given resource.""" api = 'reservation' resource = None log = None allow_names = True def get_parser(self, prog_name): parser = super(DeleteCommand, self).get_parser(prog_name) if self.allow_names: help_str = 'ID or name of %s to delete' else: help_str = 'ID of %s to delete' parser.add_argument( 'id', metavar=self.resource.upper(), help=help_str % self.resource) return parser def run(self, parsed_args): self.log.debug('run(%s)' % parsed_args) climate_client = self.get_client() resource_manager = getattr(climate_client, self.resource) if self.allow_names: res_id = utils.find_resource_id_by_name_or_id(climate_client, self.resource, parsed_args.id) else: res_id = parsed_args.id resource_manager.delete(res_id) print(self.app.stdout, 'Deleted %s: %s' % (self.resource, parsed_args.id)) return class ListCommand(ClimateCommand, lister.Lister): """List resources that belong to a given tenant.""" api = 'reservation' resource = None log = None _formatters = {} list_columns = [] unknown_parts_flag = True def get_parser(self, prog_name): parser = super(ListCommand, self).get_parser(prog_name) return parser def retrieve_list(self, parsed_args): """Retrieve a list of resources from Climate server""" climate_client = self.get_client() resource_manager = getattr(climate_client, self.resource) data = resource_manager.list() return data def setup_columns(self, info, parsed_args): columns = len(info) > 0 and sorted(info[0].keys()) or [] if not columns: parsed_args.columns = [] elif parsed_args.columns: columns = [col for col in parsed_args.columns if col in columns] elif self.list_columns: columns = [col for col in self.list_columns if col in columns] return ( columns, (utils.get_item_properties(s, columns, formatters=self._formatters) for s in info) ) def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) data = self.retrieve_list(parsed_args) return self.setup_columns(data, parsed_args) class ShowCommand(ClimateCommand, show.ShowOne): """Show information of a given resource.""" api = 'reservation' resource = None log = None allow_names = True def get_parser(self, prog_name): parser = super(ShowCommand, self).get_parser(prog_name) if self.allow_names: help_str = 'ID or name of %s to look up' else: help_str = 'ID of %s to look up' parser.add_argument('id', metavar=self.resource.upper(), help=help_str % self.resource) return parser def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) climate_client = self.get_client() if self.allow_names: res_id = utils.find_resource_id_by_name_or_id(climate_client, self.resource, parsed_args.id) else: res_id = parsed_args.id resource_manager = getattr(climate_client, self.resource) data = resource_manager.get(res_id) self.format_output_data(data) return zip(*sorted(six.iteritems(data)))