def run(self, parsed_args): self.log.debug('run(%s)', parsed_args) vnfsvc_client = self.get_client() vnfsvc_client.format = parsed_args.request_format _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) if self.resource in body: body[self.resource].update(_extra_values) else: body[self.resource] = _extra_values if not body[self.resource]: raise exceptions.CommandError( _("Must specify new values to update %s") % self.cmd_resource) if self.allow_names: _id = find_resourceid_by_name_or_id( vnfsvc_client, self.resource, parsed_args.id, cmd_resource=self.cmd_resource) else: _id = find_resourceid_by_id( vnfsvc_client, self.resource, parsed_args.id, self.cmd_resource, self.parent_id) obj_updater = getattr(vnfsvc_client, "update_%s" % self.cmd_resource) if self.parent_id: obj_updater(_id, self.parent_id, body) else: obj_updater(_id, body) print((_('Updated %(resource)s: %(id)s') % {'id': parsed_args.id, 'resource': self.resource}), file=self.app.stdout) return
def run_subcommand(self, argv): subcommand = self.command_manager.find_command(argv) cmd_factory, cmd_name, sub_argv = subcommand cmd = cmd_factory(self, self.options) err = None result = 1 try: self.prepare_to_run_command(cmd) full_name = (cmd_name if self.interactive_mode else ' '.join( [self.NAME, cmd_name])) cmd_parser = cmd.get_parser(full_name) return run_command(cmd, cmd_parser, sub_argv) except Exception as err: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err)) else: self.log.error(unicode(err)) try: self.clean_up(cmd, result, err) except Exception as err2: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err2)) else: self.log.error(_('Could not clean up: %s'), unicode(err2)) if self.options.verbose_level >= self.DEBUG_LEVEL: raise else: try: self.clean_up(cmd, result, None) except Exception as err3: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err3)) else: self.log.error(_('Could not clean up: %s'), unicode(err3)) return result
def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) vnfsvc_client = self.get_client() vnfsvc_client.format = parsed_args.request_format _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) body[self.resource].update(_extra_values) obj_creator = getattr(vnfsvc_client, "create_%s" % self.cmd_resource) if self.parent_id: data = obj_creator(self.parent_id, body) else: data = obj_creator(body) self.format_output_data(data) info = self.resource in data and data[self.resource] or None if info: if self.resource == 'monitor': print(_('Network Service %s status:') % self.resource, file=self.app.stdout) else: print(_('Created a new %s:') % self.resource, file=self.app.stdout) else: info = {'': ''} return zip(*sorted(six.iteritems(info)))
def args2body(self, parsed_args): body = { self.resource: { 'nsd_id': parsed_args.nsd_id, 'vdus': dict(), 'files': dict() } } if parsed_args.vdus: try: for key_value in parsed_args.vdus: kwargs = key_value.split(',') except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['vdus'] = kwargs if parsed_args.files: try: for key_value in parsed_args.files: kwargs = key_value.split(',') except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['files'] = kwargs vnfsvcV20.update_dict(parsed_args, body[self.resource], ['tenant-id']) return body
def check_non_negative_int(value): try: value = int(value) except ValueError: raise argparse.ArgumentTypeError(_("invalid int value: %r") % value) if value < 0: raise argparse.ArgumentTypeError(_("input value %d is negative") % value) return value
def check_non_negative_int(value): try: value = int(value) except ValueError: raise argparse.ArgumentTypeError(_("invalid int value: %r") % value) if value < 0: raise argparse.ArgumentTypeError( _("input value %d is negative") % value) return value
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 build_option_parser(self, description, version): """Return an argparse option parser for this application. Subclasses may override this method to extend the parser with more global options. :param description: full description of the application :paramtype description: str :param version: version number for the application :paramtype version: str """ parser = argparse.ArgumentParser( description=description, add_help=False, ) parser.add_argument( '--version', action='version', version=version_info, ) parser.add_argument( '-v', '--verbose', '--debug', action='count', dest='verbose_level', default=self.DEFAULT_VERBOSE_LEVEL, help=_('Increase verbosity of output and show tracebacks on' ' errors. You can repeat this option.')) parser.add_argument( '-q', '--quiet', action='store_const', dest='verbose_level', const=0, help=_('Suppress output except warnings and errors.')) parser.add_argument('-h', '--help', action=HelpAction, nargs=0, default=self, help=_("Show this help message and exit.")) parser.add_argument( '-r', '--retries', metavar="NUM", type=check_non_negative_int, default=0, help=_("How many times the request to the vnfsvc server should " "be retried if it fails.")) # FIXME(bklei): this method should come from python-keystoneclient self._append_global_identity_args(parser) return parser
def get_parser(self, prog_name): parser = super(ShowCommand, self).get_parser(prog_name) add_show_list_common_argument(parser) 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 build_option_parser(self, description, version): """Return an argparse option parser for this application. Subclasses may override this method to extend the parser with more global options. :param description: full description of the application :paramtype description: str :param version: version number for the application :paramtype version: str """ parser = argparse.ArgumentParser( description=description, add_help=False, ) parser.add_argument( '--version', action='version', version=version_info,) parser.add_argument( '-v', '--verbose', '--debug', action='count', dest='verbose_level', default=self.DEFAULT_VERBOSE_LEVEL, help=_('Increase verbosity of output and show tracebacks on' ' errors. You can repeat this option.')) parser.add_argument( '-q', '--quiet', action='store_const', dest='verbose_level', const=0, help=_('Suppress output except warnings and errors.')) parser.add_argument( '-h', '--help', action=HelpAction, nargs=0, default=self, help=_("Show this help message and exit.")) parser.add_argument( '-r', '--retries', metavar="NUM", type=check_non_negative_int, default=0, help=_("How many times the request to the vnfsvc server should " "be retried if it fails.")) # FIXME(bklei): this method should come from python-keystoneclient self._append_global_identity_args(parser) return parser
def _from_xml(self, datastring): if datastring is None: return None plurals = set(self.metadata.get('plurals', {})) try: node = etree.fromstring(datastring) root_tag = self._get_key(node.tag) links = self._get_links(root_tag, node) result = self._from_xml_node(node, plurals) # There is no case where root_tag = constants.VIRTUAL_ROOT_KEY # and links is not None because of the way data are serialized if root_tag == constants.VIRTUAL_ROOT_KEY: return result return dict({root_tag: result}, **links) except Exception as e: parseError = False # Python2.7 if (hasattr(etree, 'ParseError') and isinstance(e, getattr(etree, 'ParseError'))): parseError = True # Python2.6 elif isinstance(e, expat.ExpatError): parseError = True if parseError: msg = _("Cannot understand XML") raise exception.MalformedResponseBody(reason=msg) else: raise
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 add_pagination_argument(parser): parser.add_argument( '-P', '--page-size', dest='page_size', metavar='SIZE', type=int, help=_("Specify retrieve unit of each request, then split one request " "to several requests."), default=None)
def make_client(instance): """Returns an vnfsvc client. """ vnfsvc_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS, ) instance.initialize() url = instance._url url = url.rstrip("/") if '1.0' == instance._api_version[API_NAME]: client = vnfsvc_client(username=instance._username, tenant_name=instance._tenant_name, password=instance._password, region_name=instance._region_name, auth_url=instance._auth_url, endpoint_url=url, token=instance._token, auth_strategy=instance._auth_strategy, insecure=instance._insecure, ca_cert=instance._ca_cert, retries=instance._retries, raise_errors=instance._raise_errors, session=instance._session, auth=instance._auth) return client else: raise exceptions.UnsupportedVersion(_("API version %s is not " "supported") % instance._api_version[API_NAME])
def bool_from_string(subject, strict=False, default=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else returns the value specified by 'default'. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = six.text_type(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join("'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % { 'val': subject, 'acceptable': acceptable } raise ValueError(msg) else: return default
def _find_resourceid_by_name(client, resource, name, project_id=None, cmd_resource=None, parent_id=None): if not cmd_resource: cmd_resource = resource cmd_resource_plural = _get_resource_plural(cmd_resource, client) resource_plural = _get_resource_plural(resource, client) obj_lister = getattr(client, "list_%s" % cmd_resource_plural) params = {'name': name, 'fields': 'id'} if project_id: params['tenant_id'] = project_id if parent_id: data = obj_lister(parent_id, **params) else: data = obj_lister(**params) collection = resource_plural info = data[collection] if len(info) > 1: raise exceptions.VNFSvcClientNoUniqueMatch(resource=resource, name=name) elif len(info) == 0: not_found_message = (_("Unable to find %(resource)s with name " "'%(name)s'") % {'resource': resource, 'name': name}) # 404 is used to simulate server side behavior raise exceptions.VNFSvcClientException( message=not_found_message, status_code=404) else: return info[0]['id']
def find_resourceid_by_id(client, resource, resource_id, cmd_resource=None, parent_id=None): if not cmd_resource: cmd_resource = resource cmd_resource_plural = _get_resource_plural(cmd_resource, client) resource_plural = _get_resource_plural(resource, client) obj_lister = getattr(client, "list_%s" % cmd_resource_plural) # perform search by id only if we are passing a valid UUID match = re.match(UUID_PATTERN, resource_id) collection = resource_plural if match: if parent_id: data = obj_lister(parent_id, id=resource_id, fields='id') else: data = obj_lister(id=resource_id, fields='id') if data and data[collection]: return data[collection][0]['id'] not_found_message = (_("Unable to find %(resource)s with id " "'%(id)s'") % { 'resource': resource, 'id': resource_id }) # 404 is used to simulate server side behavior raise exceptions.VNFSvcClientException(message=not_found_message, status_code=404)
def bool_from_string(subject, strict=False, default=False): """Interpret a string as a boolean. A case-insensitive match is performed such that strings matching 't', 'true', 'on', 'y', 'yes', or '1' are considered True and, when `strict=False`, anything else returns the value specified by 'default'. Useful for JSON-decoded stuff and config file parsing. If `strict=True`, unrecognized values, including None, will raise a ValueError which is useful when parsing values passed in from an API call. Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'. """ if not isinstance(subject, six.string_types): subject = six.text_type(subject) lowered = subject.strip().lower() if lowered in TRUE_STRINGS: return True elif lowered in FALSE_STRINGS: return False elif strict: acceptable = ', '.join( "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS)) msg = _("Unrecognized value '%(val)s', acceptable values are:" " %(acceptable)s") % {'val': subject, 'acceptable': acceptable} raise ValueError(msg) else: return default
def run(self, parsed_args): self.log.debug('run(%s)', parsed_args) vnfsvc_client = self.get_client() vnfsvc_client.format = parsed_args.request_format obj_deleter = getattr(vnfsvc_client, "delete_%s" % self.cmd_resource) if self.allow_names: params = {'cmd_resource': self.cmd_resource, 'parent_id': self.parent_id} _id = find_resourceid_by_name_or_id(vnfsvc_client, self.resource, parsed_args.id, **params) else: _id = parsed_args.id if self.parent_id: obj_deleter(_id, self.parent_id) else: obj_deleter(_id) print((_('Deleted %(resource)s: %(id)s') % {'id': parsed_args.id, 'resource': self.resource}), file=self.app.stdout) return
def make_client(instance): """Returns an vnfsvc client. """ vnfsvc_client = utils.get_client_class( API_NAME, instance._api_version[API_NAME], API_VERSIONS, ) instance.initialize() url = instance._url url = url.rstrip("/") if '1.0' == instance._api_version[API_NAME]: client = vnfsvc_client(username=instance._username, tenant_name=instance._tenant_name, password=instance._password, region_name=instance._region_name, auth_url=instance._auth_url, endpoint_url=url, token=instance._token, auth_strategy=instance._auth_strategy, insecure=instance._insecure, ca_cert=instance._ca_cert, retries=instance._retries, raise_errors=instance._raise_errors, session=instance._session, auth=instance._auth) return client else: raise exceptions.UnsupportedVersion( _("API version %s is not " "supported") % instance._api_version[API_NAME])
def add_vdu_specification_for_driver(parser): parser.add_argument( '-VDU', '--vdu-details', help=_('Display Driver details information for specific VDU.'), required=False, default=None, )
def authenticate(self): if self.auth_strategy == 'keystone': self._authenticate_keystone() elif self.auth_strategy == 'noauth': self._authenticate_noauth() else: err_msg = _('Unknown auth strategy: %s') % self.auth_strategy raise exceptions.Unauthorized(message=err_msg)
def _authenticate_noauth(self): if not self.endpoint_url: message = _( 'For "noauth" authentication strategy, the endpoint ' "must be specified either in the constructor or " "using --os-url" ) raise exceptions.Unauthorized(message=message)
def authenticate(self): if self.auth_strategy == "keystone": self._authenticate_keystone() elif self.auth_strategy == "noauth": self._authenticate_noauth() else: err_msg = _("Unknown auth strategy: %s") % self.auth_strategy raise exceptions.Unauthorized(message=err_msg)
def string_to_bytes(text, unit_system='IEC', return_int=False): """Converts a string into an float representation of bytes. The units supported for IEC :: Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it) KB, KiB, MB, MiB, GB, GiB, TB, TiB The units supported for SI :: kb(it), Mb(it), Gb(it), Tb(it) kB, MB, GB, TB Note that the SI unit system does not support capital letter 'K' :param text: String input for bytes size conversion. :param unit_system: Unit system for byte size conversion. :param return_int: If True, returns integer representation of text in bytes. (default: decimal) :returns: Numerical representation of text in bytes. :raises ValueError: If text has an invalid value. """ try: base, reg_ex = UNIT_SYSTEM_INFO[unit_system] except KeyError: msg = _('Invalid unit system: "%s"') % unit_system raise ValueError(msg) match = reg_ex.match(text) if match: magnitude = float(match.group(1)) unit_prefix = match.group(2) if match.group(3) in ['b', 'bit']: magnitude /= 8 else: msg = _('Invalid string format: %s') % text raise ValueError(msg) if not unit_prefix: res = magnitude else: res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix]) if return_int: return int(math.ceil(res)) return res
def get_parser(self, prog_name): parser = super(CreateCommand, self).get_parser(prog_name) parser.add_argument( '--tenant-id', metavar='TENANT_ID', help=_('The owner tenant ID.'), ) parser.add_argument( '--tenant_id', help=argparse.SUPPRESS) self.add_known_arguments(parser) return parser
def add_sorting_argument(parser): parser.add_argument( '--sort-key', dest='sort_key', metavar='FIELD', action='append', help=_("Sorts the list by the specified fields in the specified " "directions. You can repeat this option, but you must " "specify an equal number of sort_dir and sort_key values. " "Extra sort_dir options are ignored. Missing sort_dir options " "use the default asc value."), default=[]) parser.add_argument( '--sort-dir', dest='sort_dir', metavar='{asc,desc}', help=_("Sorts the list in the specified direction. You can repeat " "this option."), action='append', default=[], choices=['asc', 'desc'])
def get_parser(self, prog_name): parser = super(ShowCommand, self).get_parser(prog_name) add_show_list_common_argument(parser) # like localhost:9010/service_drivers/<id>?vdu=<vdu-name> # currently this function is a placebo for the above server request as it # requires client to embed the vdu field into the url. # # However, now the same functionality of filtering the vdu parameters is done # client side with everytime request to the server going as # localhost:9010/service_drivers/<id> if prog_name.split(' ')[-1] == "service-driver-show": add_vdu_specification_for_driver(parser) 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_parser(self, prog_name): parser = super(VNFSvcCommand, self).get_parser(prog_name) parser.add_argument( '--request-format', help=_('The XML or JSON request format.'), default='json', choices=['json', 'xml', ], ) parser.add_argument( '--request_format', choices=['json', 'xml', ], help=argparse.SUPPRESS) return parser
def add_show_list_common_argument(parser): parser.add_argument( '-D', '--show-details', help=_('Show detailed information.'), action='store_true', default=False, ) parser.add_argument( '--show_details', action='store_true', help=argparse.SUPPRESS) parser.add_argument( '--fields', help=argparse.SUPPRESS, action='append', default=[]) parser.add_argument( '-F', '--field', dest='fields', metavar='FIELD', help=_('Specify the field(s) to be returned by server. You can ' 'repeat this option.'), action='append', default=[])
def args2body(self, parsed_args): body = { self.resource: { 'name': parsed_args.name, 'quality_of_service' : parsed_args.qos, 'attributes': dict() } } if parsed_args.networks: try: kwargs = dict(key_value.split('=', 1) for key_value in parsed_args.networks) except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['attributes']['networks'] = kwargs if parsed_args.router: body[self.resource]['attributes']['router'] = parsed_args.router if parsed_args.subnets: try: kwargs = dict(key_value.split('=', 1) for key_value in parsed_args.subnets) except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['attributes']['subnets'] = kwargs vnfsvcV20.update_dict(parsed_args, body[self.resource], ['tenant_id']) return body
def args2body(self, parsed_args): body = { self.resource: { 'name': parsed_args.name, 'quality_of_service': parsed_args.qos, 'attributes': dict() } } if parsed_args.networks: try: kwargs = dict( key_value.split('=', 1) for key_value in parsed_args.networks) except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['attributes']['networks'] = kwargs if parsed_args.router: body[self.resource]['attributes']['router'] = parsed_args.router if parsed_args.subnets: try: kwargs = dict( key_value.split('=', 1) for key_value in parsed_args.subnets) except ValueError: msg = (_('invalid argument for --kwargs %s') % parsed_args.kwargs) raise exceptions.vnfsvcCLIError(msg) if kwargs: body[self.resource]['attributes']['subnets'] = kwargs vnfsvcV20.update_dict(parsed_args, body[self.resource], ['tenant_id']) return body
def run_subcommand(self, argv): subcommand = self.command_manager.find_command(argv) cmd_factory, cmd_name, sub_argv = subcommand cmd = cmd_factory(self, self.options) err = None result = 1 try: self.prepare_to_run_command(cmd) full_name = (cmd_name if self.interactive_mode else ' '.join([self.NAME, cmd_name]) ) cmd_parser = cmd.get_parser(full_name) return run_command(cmd, cmd_parser, sub_argv) except Exception as err: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err)) else: self.log.error(unicode(err)) try: self.clean_up(cmd, result, err) except Exception as err2: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err2)) else: self.log.error(_('Could not clean up: %s'), unicode(err2)) if self.options.verbose_level >= self.DEBUG_LEVEL: raise else: try: self.clean_up(cmd, result, None) except Exception as err3: if self.options.verbose_level >= self.DEBUG_LEVEL: self.log.exception(unicode(err3)) else: self.log.error(_('Could not clean up: %s'), unicode(err3)) return result
def __call__(self, parser, namespace, values, option_string=None): outputs = [] max_len = 0 app = self.default parser.print_help(app.stdout) app.stdout.write(_('\nCommands for API v%s:\n') % app.api_version) command_manager = app.command_manager for name, ep in sorted(command_manager): factory = ep.load() cmd = factory(self, None) one_liner = cmd.get_description().split('\n')[0] outputs.append((name, one_liner)) max_len = max(len(name), max_len) for (name, one_liner) in outputs: app.stdout.write(' %s %s\n' % (name.ljust(max_len), one_liner)) sys.exit(0)
def _process_previous_argument(current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs): if current_arg is not None: if _value_number == 0 and (current_type_str or _list_flag): # This kind of argument should have value raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) if _value_number > 1 or _list_flag or current_type_str == 'list': current_arg.update({'nargs': '+'}) elif _value_number == 0: if _clear_flag: # if we have action=clear, we use argument's default # value None for argument _values_specs.pop() else: # We assume non value argument as bool one current_arg.update({'action': 'store_true'})
def get_data(self, parsed_args): self.log.debug('get_data(%s)' % parsed_args) vnfsvc_client = self.get_client() vnfsvc_client.format = parsed_args.request_format _extra_values = parse_args_to_dict(self.values_specs) _merge_args(self, parsed_args, _extra_values, self.values_specs) body = self.args2body(parsed_args) body[self.resource].update(_extra_values) obj_creator = getattr(vnfsvc_client, "create_%s" % self.cmd_resource) if self.parent_id: data = obj_creator(self.parent_id, body) else: data = obj_creator(body) self.format_output_data(data) info = self.resource in data and data[self.resource] or None if info: print(_('Created a new %s:') % self.resource, file=self.app.stdout) else: info = {'': ''} return zip(*sorted(six.iteritems(info)))
def find_resourceid_by_id(client, resource, resource_id, cmd_resource=None, parent_id=None): if not cmd_resource: cmd_resource = resource cmd_resource_plural = _get_resource_plural(cmd_resource, client) resource_plural = _get_resource_plural(resource, client) obj_lister = getattr(client, "list_%s" % cmd_resource_plural) # perform search by id only if we are passing a valid UUID match = re.match(UUID_PATTERN, resource_id) collection = resource_plural if match: if parent_id: data = obj_lister(parent_id, id=resource_id, fields='id') else: data = obj_lister(id=resource_id, fields='id') if data and data[collection]: return data[collection][0]['id'] not_found_message = (_("Unable to find %(resource)s with id " "'%(id)s'") % {'resource': resource, 'id': resource_id}) # 404 is used to simulate server side behavior raise exceptions.VNFSvcClientException( message=not_found_message, status_code=404)
def _discover_auth_versions(self, session, auth_url): # discover the API versions the server is supporting base on the # given URL try: ks_discover = discover.Discover(session=session, auth_url=auth_url) return (ks_discover.url_for('2.0'), ks_discover.url_for('3.0')) except ks_exc.ClientException: # Identity service may not support discover API version. # Lets try to figure out the API version from the original URL. url_parts = urlparse.urlparse(auth_url) (scheme, netloc, path, params, query, fragment) = url_parts path = path.lower() if path.startswith('/v3'): return (None, auth_url) elif path.startswith('/v2'): return (auth_url, None) else: # not enough information to determine the auth version msg = _('Unable to determine the Keystone version ' 'to authenticate with using the given ' 'auth_url. Identity service may not support API ' 'version discovery. Please provide a versioned ' 'auth_url instead.') raise exc.CommandError(msg)
def _from_json(self, datastring): try: return jsonutils.loads(datastring) except ValueError: msg = _("Cannot understand JSON") raise exception.MalformedResponseBody(reason=msg)
def parse_args_to_dict(values_specs): '''It is used to analyze the extra command options to command. Besides known options and arguments, our commands also support user to put more options to the end of command line. For example, list_nets -- --tag x y --key1 value1, where '-- --tag x y --key1 value1' is extra options to our list_nets. This feature can support V2.0 API's fields selection and filters. For example, to list vnfservices which has name 'test4', we can have list_nets -- --name=test4. value spec is: --key type=int|bool|... value. Type is one of Python built-in types. By default, type is string. The key without value is a bool option. Key with two values will be a list option. ''' # values_specs for example: '-- --tag x y --key1 type=int value1' # -- is a pseudo argument values_specs_copy = values_specs[:] if values_specs_copy and values_specs_copy[0] == '--': del values_specs_copy[0] # converted ArgumentParser arguments for each of the options _options = {} # the argument part for current option in _options current_arg = None # the string after remove meta info in values_specs # for example, '--tag x y --key1 value1' _values_specs = [] # record the count of values for an option # for example: for '--tag x y', it is 2, while for '--key1 value1', it is 1 _value_number = 0 # list=true _list_flag = False # action=clear _clear_flag = False # the current item in values_specs current_item = None # the str after 'type=' current_type_str = None for _item in values_specs_copy: if _item.startswith('--'): # Deal with previous argument if any _process_previous_argument( current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs) # Init variables for current argument current_item = _item _list_flag = False _clear_flag = False current_type_str = None if "=" in _item: _value_number = 1 _item = _item.split('=')[0] else: _value_number = 0 if _item in _options: raise exceptions.CommandError( _("Duplicated options %s") % ' '.join(values_specs)) else: _options.update({_item: {}}) current_arg = _options[_item] _item = current_item elif _item.startswith('type='): if current_arg is None: raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) if 'type' not in current_arg: current_type_str = _item.split('=', 2)[1] current_arg.update({'type': eval(current_type_str)}) if current_type_str == 'bool': current_arg.update({'type': utils.str2bool}) elif current_type_str == 'dict': current_arg.update({'type': utils.str2dict}) continue elif _item == 'list=true': _list_flag = True continue elif _item == 'action=clear': _clear_flag = True continue if not _item.startswith('--'): # All others are value items # Make sure '--' occurs first and allow minus value if (not current_item or '=' in current_item or _item.startswith('-') and not is_number(_item)): raise exceptions.CommandError( _("Invalid values_specs %s") % ' '.join(values_specs)) _value_number += 1 _values_specs.append(_item) # Deal with last one argument _process_previous_argument( current_arg, _value_number, current_type_str, _list_flag, _values_specs, _clear_flag, values_specs) # populate the parser with arguments _parser = argparse.ArgumentParser(add_help=False) for opt, optspec in six.iteritems(_options): _parser.add_argument(opt, **optspec) _args = _parser.parse_args(_values_specs) result_dict = {} for opt in six.iterkeys(_options): _opt = opt.split('--', 2)[1] _opt = _opt.replace('-', '_') _value = getattr(_args, _opt) result_dict.update({_opt: _value}) return result_dict
def _append_global_identity_args(self, parser): # FIXME(bklei): these are global identity (Keystone) arguments which # should be consistent and shared by all service clients. Therefore, # they should be provided by python-keystoneclient. We will need to # refactor this code once this functionality is available in # python-keystoneclient. # # Note: At that time we'll need to decide if we can just abandon # the deprecated args (--service-type and --endpoint-type). parser.add_argument( '--os-service-type', metavar='<os-service-type>', default=env('OS_NETWORK_SERVICE_TYPE', default='network'), help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or network.')) parser.add_argument( '--os-endpoint-type', metavar='<os-endpoint-type>', default=env('OS_ENDPOINT_TYPE', default='publicURL'), help=_('Defaults to env[OS_ENDPOINT_TYPE] or publicURL.')) # FIXME(bklei): --service-type is deprecated but kept in for # backward compatibility. parser.add_argument('--service-type', metavar='<service-type>', default=env('OS_NETWORK_SERVICE_TYPE', default='network'), help=_('DEPRECATED! Use --os-service-type.')) # FIXME(bklei): --endpoint-type is deprecated but kept in for # backward compatibility. parser.add_argument('--endpoint-type', metavar='<endpoint-type>', default=env('OS_ENDPOINT_TYPE', default='publicURL'), help=_('DEPRECATED! Use --os-endpoint-type.')) parser.add_argument('--os-auth-strategy', metavar='<auth-strategy>', default=env('OS_AUTH_STRATEGY', default='keystone'), help=_('DEPRECATED! Only keystone is supported.')) parser.add_argument('--os_auth_strategy', help=argparse.SUPPRESS) parser.add_argument( '--os-auth-url', metavar='<auth-url>', default=env('OS_AUTH_URL'), help=_('Authentication URL, defaults to env[OS_AUTH_URL].')) parser.add_argument('--os_auth_url', help=argparse.SUPPRESS) project_name_group = parser.add_mutually_exclusive_group() project_name_group.add_argument( '--os-tenant-name', metavar='<auth-tenant-name>', default=env('OS_TENANT_NAME'), help=_('Authentication tenant name, defaults to ' 'env[OS_TENANT_NAME].')) project_name_group.add_argument( '--os-project-name', metavar='<auth-project-name>', default=utils.env('OS_PROJECT_NAME'), help='Another way to specify tenant name. ' 'This option is mutually exclusive with ' ' --os-tenant-name. ' 'Defaults to env[OS_PROJECT_NAME].') parser.add_argument('--os_tenant_name', help=argparse.SUPPRESS) project_id_group = parser.add_mutually_exclusive_group() project_id_group.add_argument( '--os-tenant-id', metavar='<auth-tenant-id>', default=env('OS_TENANT_ID'), help=_('Authentication tenant ID, defaults to ' 'env[OS_TENANT_ID].')) project_id_group.add_argument('--os-project-id', metavar='<auth-project-id>', default=utils.env('OS_PROJECT_ID'), help='Another way to specify tenant ID. ' 'This option is mutually exclusive with ' ' --os-tenant-id. ' 'Defaults to env[OS_PROJECT_ID].') parser.add_argument( '--os-username', metavar='<auth-username>', default=utils.env('OS_USERNAME'), help=_('Authentication username, defaults to env[OS_USERNAME].')) parser.add_argument('--os_username', help=argparse.SUPPRESS) parser.add_argument('--os-user-id', metavar='<auth-user-id>', default=env('OS_USER_ID'), help=_('Authentication user ID (Env: OS_USER_ID)')) parser.add_argument('--os_user_id', help=argparse.SUPPRESS) parser.add_argument('--os-user-domain-id', metavar='<auth-user-domain-id>', default=utils.env('OS_USER_DOMAIN_ID'), help='OpenStack user domain ID. ' 'Defaults to env[OS_USER_DOMAIN_ID].') parser.add_argument('--os_user_domain_id', help=argparse.SUPPRESS) parser.add_argument('--os-user-domain-name', metavar='<auth-user-domain-name>', default=utils.env('OS_USER_DOMAIN_NAME'), help='OpenStack user domain name. ' 'Defaults to env[OS_USER_DOMAIN_NAME].') parser.add_argument('--os_user_domain_name', help=argparse.SUPPRESS) parser.add_argument('--os_project_id', help=argparse.SUPPRESS) parser.add_argument('--os_project_name', help=argparse.SUPPRESS) parser.add_argument('--os-project-domain-id', metavar='<auth-project-domain-id>', default=utils.env('OS_PROJECT_DOMAIN_ID'), help='Defaults to env[OS_PROJECT_DOMAIN_ID].') parser.add_argument('--os-project-domain-name', metavar='<auth-project-domain-name>', default=utils.env('OS_PROJECT_DOMAIN_NAME'), help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') parser.add_argument('--os-cert', metavar='<certificate>', default=utils.env('OS_CERT'), help=_("Path of certificate file to use in SSL " "connection. This file can optionally be " "prepended with the private key. Defaults " "to env[OS_CERT]")) parser.add_argument('--os-cacert', metavar='<ca-certificate>', default=env('OS_CACERT', default=None), help=_( "Specify a CA bundle file to use in " "verifying a TLS (https) server certificate. " "Defaults to env[OS_CACERT]")) parser.add_argument('--os-key', metavar='<key>', default=utils.env('OS_KEY'), help=_( "Path of client key to use in SSL " "connection. This option is not necessary " "if your key is prepended to your certificate " "file. Defaults to env[OS_KEY]")) parser.add_argument( '--os-password', metavar='<auth-password>', default=utils.env('OS_PASSWORD'), help=_('Authentication password, defaults to env[OS_PASSWORD].')) parser.add_argument('--os_password', help=argparse.SUPPRESS) parser.add_argument('--os-region-name', metavar='<auth-region-name>', default=env('OS_REGION_NAME'), help=_('Authentication region name, defaults to ' 'env[OS_REGION_NAME].')) parser.add_argument('--os_region_name', help=argparse.SUPPRESS) parser.add_argument( '--os-token', metavar='<token>', default=env('OS_TOKEN'), help=_('Authentication token, defaults to env[OS_TOKEN].')) parser.add_argument('--os_token', help=argparse.SUPPRESS) parser.add_argument( '--http-timeout', metavar='<seconds>', default=env('OS_NETWORK_TIMEOUT', default=None), type=float, help=_('Timeout in seconds to wait for an HTTP response. Defaults ' 'to env[OS_NETWORK_TIMEOUT] or None if not specified.')) parser.add_argument('--os-url', metavar='<url>', default=env('OS_URL'), help=_('Defaults to env[OS_URL].')) parser.add_argument('--os_url', help=argparse.SUPPRESS) parser.add_argument( '--insecure', action='store_true', default=env('VNFSVCCLIENT_INSECURE', default=False), help=_("Explicitly allow vnfsvcclient to perform \"insecure\" " "SSL (https) requests. The server's certificate will " "not be verified against any certificate authorities. " "This option should be used with caution."))
def authenticate_user(self): """Make sure the user has provided all of the authentication info we need. """ if self.options.os_auth_strategy == 'keystone': if self.options.os_token or self.options.os_url: # Token flow auth takes priority if not self.options.os_token: raise exc.CommandError( _("You must provide a token via" " either --os-token or env[OS_TOKEN]")) if not self.options.os_url: raise exc.CommandError( _("You must provide a service URL via" " either --os-url or env[OS_URL]")) else: # Validate password flow auth project_info = (self.options.os_tenant_name or self.options.os_tenant_id or (self.options.os_project_name and (self.options.project_domain_name or self.options.project_domain_id)) or self.options.os_project_id) if (not self.options.os_username and not self.options.os_user_id): raise exc.CommandError( _("You must provide a username or user ID via" " --os-username, env[OS_USERNAME] or" " --os-user_id, env[OS_USER_ID]")) if not self.options.os_password: raise exc.CommandError( _("You must provide a password via" " either --os-password or env[OS_PASSWORD]")) if (not project_info): # tenent is deprecated in Keystone v3. Use the latest # terminology instead. raise exc.CommandError( _("You must provide a project_id or project_name (" "with project_domain_name or project_domain_id) " "via " " --os-project-id (env[OS_PROJECT_ID])" " --os-project-name (env[OS_PROJECT_NAME])," " --os-project-domain-id " "(env[OS_PROJECT_DOMAIN_ID])" " --os-project-domain-name " "(env[OS_PROJECT_DOMAIN_NAME])")) if not self.options.os_auth_url: raise exc.CommandError( _("You must provide an auth url via" " either --os-auth-url or via env[OS_AUTH_URL]")) else: # not keystone if not self.options.os_url: raise exc.CommandError( _("You must provide a service URL via" " either --os-url or env[OS_URL]")) auth_session = self._get_keystone_session() self.client_manager = clientmanager.ClientManager( token=self.options.os_token, url=self.options.os_url, auth_url=self.options.os_auth_url, tenant_name=self.options.os_tenant_name, tenant_id=self.options.os_tenant_id, username=self.options.os_username, user_id=self.options.os_user_id, password=self.options.os_password, region_name=self.options.os_region_name, api_version=self.api_version, auth_strategy=self.options.os_auth_strategy, # FIXME (bklei) honor deprecated service_type and # endpoint type until they are removed service_type=self.options.os_service_type or self.options.service_type, endpoint_type=self.options.os_endpoint_type or self.endpoint_type, insecure=self.options.insecure, ca_cert=self.options.os_cacert, timeout=self.options.http_timeout, retries=self.options.retries, raise_errors=False, session=auth_session, auth=auth_session.auth, log_credentials=True) return
def _append_global_identity_args(self, parser): # FIXME(bklei): these are global identity (Keystone) arguments which # should be consistent and shared by all service clients. Therefore, # they should be provided by python-keystoneclient. We will need to # refactor this code once this functionality is available in # python-keystoneclient. # # Note: At that time we'll need to decide if we can just abandon # the deprecated args (--service-type and --endpoint-type). parser.add_argument( '--os-service-type', metavar='<os-service-type>', default=env('OS_NETWORK_SERVICE_TYPE', default='network'), help=_('Defaults to env[OS_NETWORK_SERVICE_TYPE] or network.')) parser.add_argument( '--os-endpoint-type', metavar='<os-endpoint-type>', default=env('OS_ENDPOINT_TYPE', default='publicURL'), help=_('Defaults to env[OS_ENDPOINT_TYPE] or publicURL.')) # FIXME(bklei): --service-type is deprecated but kept in for # backward compatibility. parser.add_argument( '--service-type', metavar='<service-type>', default=env('OS_NETWORK_SERVICE_TYPE', default='network'), help=_('DEPRECATED! Use --os-service-type.')) # FIXME(bklei): --endpoint-type is deprecated but kept in for # backward compatibility. parser.add_argument( '--endpoint-type', metavar='<endpoint-type>', default=env('OS_ENDPOINT_TYPE', default='publicURL'), help=_('DEPRECATED! Use --os-endpoint-type.')) parser.add_argument( '--os-auth-strategy', metavar='<auth-strategy>', default=env('OS_AUTH_STRATEGY', default='keystone'), help=_('DEPRECATED! Only keystone is supported.')) parser.add_argument( '--os_auth_strategy', help=argparse.SUPPRESS) parser.add_argument( '--os-auth-url', metavar='<auth-url>', default=env('OS_AUTH_URL'), help=_('Authentication URL, defaults to env[OS_AUTH_URL].')) parser.add_argument( '--os_auth_url', help=argparse.SUPPRESS) project_name_group = parser.add_mutually_exclusive_group() project_name_group.add_argument( '--os-tenant-name', metavar='<auth-tenant-name>', default=env('OS_TENANT_NAME'), help=_('Authentication tenant name, defaults to ' 'env[OS_TENANT_NAME].')) project_name_group.add_argument( '--os-project-name', metavar='<auth-project-name>', default=utils.env('OS_PROJECT_NAME'), help='Another way to specify tenant name. ' 'This option is mutually exclusive with ' ' --os-tenant-name. ' 'Defaults to env[OS_PROJECT_NAME].') parser.add_argument( '--os_tenant_name', help=argparse.SUPPRESS) project_id_group = parser.add_mutually_exclusive_group() project_id_group.add_argument( '--os-tenant-id', metavar='<auth-tenant-id>', default=env('OS_TENANT_ID'), help=_('Authentication tenant ID, defaults to ' 'env[OS_TENANT_ID].')) project_id_group.add_argument( '--os-project-id', metavar='<auth-project-id>', default=utils.env('OS_PROJECT_ID'), help='Another way to specify tenant ID. ' 'This option is mutually exclusive with ' ' --os-tenant-id. ' 'Defaults to env[OS_PROJECT_ID].') parser.add_argument( '--os-username', metavar='<auth-username>', default=utils.env('OS_USERNAME'), help=_('Authentication username, defaults to env[OS_USERNAME].')) parser.add_argument( '--os_username', help=argparse.SUPPRESS) parser.add_argument( '--os-user-id', metavar='<auth-user-id>', default=env('OS_USER_ID'), help=_('Authentication user ID (Env: OS_USER_ID)')) parser.add_argument( '--os_user_id', help=argparse.SUPPRESS) parser.add_argument( '--os-user-domain-id', metavar='<auth-user-domain-id>', default=utils.env('OS_USER_DOMAIN_ID'), help='OpenStack user domain ID. ' 'Defaults to env[OS_USER_DOMAIN_ID].') parser.add_argument( '--os_user_domain_id', help=argparse.SUPPRESS) parser.add_argument( '--os-user-domain-name', metavar='<auth-user-domain-name>', default=utils.env('OS_USER_DOMAIN_NAME'), help='OpenStack user domain name. ' 'Defaults to env[OS_USER_DOMAIN_NAME].') parser.add_argument( '--os_user_domain_name', help=argparse.SUPPRESS) parser.add_argument( '--os_project_id', help=argparse.SUPPRESS) parser.add_argument( '--os_project_name', help=argparse.SUPPRESS) parser.add_argument( '--os-project-domain-id', metavar='<auth-project-domain-id>', default=utils.env('OS_PROJECT_DOMAIN_ID'), help='Defaults to env[OS_PROJECT_DOMAIN_ID].') parser.add_argument( '--os-project-domain-name', metavar='<auth-project-domain-name>', default=utils.env('OS_PROJECT_DOMAIN_NAME'), help='Defaults to env[OS_PROJECT_DOMAIN_NAME].') parser.add_argument( '--os-cert', metavar='<certificate>', default=utils.env('OS_CERT'), help=_("Path of certificate file to use in SSL " "connection. This file can optionally be " "prepended with the private key. Defaults " "to env[OS_CERT]")) parser.add_argument( '--os-cacert', metavar='<ca-certificate>', default=env('OS_CACERT', default=None), help=_("Specify a CA bundle file to use in " "verifying a TLS (https) server certificate. " "Defaults to env[OS_CACERT]")) parser.add_argument( '--os-key', metavar='<key>', default=utils.env('OS_KEY'), help=_("Path of client key to use in SSL " "connection. This option is not necessary " "if your key is prepended to your certificate " "file. Defaults to env[OS_KEY]")) parser.add_argument( '--os-password', metavar='<auth-password>', default=utils.env('OS_PASSWORD'), help=_('Authentication password, defaults to env[OS_PASSWORD].')) parser.add_argument( '--os_password', help=argparse.SUPPRESS) parser.add_argument( '--os-region-name', metavar='<auth-region-name>', default=env('OS_REGION_NAME'), help=_('Authentication region name, defaults to ' 'env[OS_REGION_NAME].')) parser.add_argument( '--os_region_name', help=argparse.SUPPRESS) parser.add_argument( '--os-token', metavar='<token>', default=env('OS_TOKEN'), help=_('Authentication token, defaults to env[OS_TOKEN].')) parser.add_argument( '--os_token', help=argparse.SUPPRESS) parser.add_argument( '--http-timeout', metavar='<seconds>', default=env('OS_NETWORK_TIMEOUT', default=None), type=float, help=_('Timeout in seconds to wait for an HTTP response. Defaults ' 'to env[OS_NETWORK_TIMEOUT] or None if not specified.')) parser.add_argument( '--os-url', metavar='<url>', default=env('OS_URL'), help=_('Defaults to env[OS_URL].')) parser.add_argument( '--os_url', help=argparse.SUPPRESS) parser.add_argument( '--insecure', action='store_true', default=env('VNFSVCCLIENT_INSECURE', default=False), help=_("Explicitly allow vnfsvcclient to perform \"insecure\" " "SSL (https) requests. The server's certificate will " "not be verified against any certificate authorities. " "This option should be used with caution."))