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 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 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 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 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 _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 _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 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 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 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 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 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 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(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 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 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 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."))