Ejemplo n.º 1
0
    def _check_version(self, api_version):
        if api_version == 'latest':
            return LATEST_API_VERSION
        else:
            try:
                versions = tuple(int(i) for i in api_version.split('.'))
            except ValueError:
                versions = ()
            if len(versions) == 1:
                # Default value of magnum_api_version is '1'.
                # If user not specify the value of api version, not passing
                # headers at all.
                magnum_api_version = None
            elif len(versions) == 2:
                magnum_api_version = api_version
                # In the case of '1.0'
                if versions[1] == 0:
                    magnum_api_version = None
            else:
                msg = _("The requested API version %(ver)s is an unexpected "
                        "format. Acceptable formats are 'X', 'X.Y', or the "
                        "literal string '%(latest)s'.") % {
                            'ver': api_version,
                            'latest': 'latest'
                        }
                raise exc.CommandError(msg)

            api_major_version = versions[0]
            return (api_major_version, magnum_api_version)
Ejemplo n.º 2
0
def _config_cluster_kubernetes(cluster,
                               cluster_template,
                               cfg_dir,
                               force=False):
    """Return and write configuration for the given kubernetes cluster."""
    cfg_file = "%s/config" % cfg_dir
    if cluster_template.tls_disabled:
        cfg = ("apiVersion: v1\n"
               "clusters:\n"
               "- cluster:\n"
               "    server: %(api_address)s\n"
               "  name: %(name)s\n"
               "contexts:\n"
               "- context:\n"
               "    cluster: %(name)s\n"
               "    user: %(name)s\n"
               "  name: %(name)s\n"
               "current-context: %(name)s\n"
               "kind: Config\n"
               "preferences: {}\n"
               "users:\n"
               "- name: %(name)s'\n" % {
                   'name': cluster.name,
                   'api_address': cluster.api_address
               })
    else:
        cfg = ("apiVersion: v1\n"
               "clusters:\n"
               "- cluster:\n"
               "    certificate-authority: %(cfg_dir)s/ca.pem\n"
               "    server: %(api_address)s\n"
               "  name: %(name)s\n"
               "contexts:\n"
               "- context:\n"
               "    cluster: %(name)s\n"
               "    user: %(name)s\n"
               "  name: %(name)s\n"
               "current-context: %(name)s\n"
               "kind: Config\n"
               "preferences: {}\n"
               "users:\n"
               "- name: %(name)s\n"
               "  user:\n"
               "    client-certificate: %(cfg_dir)s/cert.pem\n"
               "    client-key: %(cfg_dir)s/key.pem\n" % {
                   'name': cluster.name,
                   'api_address': cluster.api_address,
                   'cfg_dir': cfg_dir
               })

    if os.path.exists(cfg_file) and not force:
        raise exc.CommandError("File %s exists, aborting." % cfg_file)
    else:
        f = open(cfg_file, "w")
        f.write(cfg)
        f.close()
    if 'csh' in os.environ['SHELL']:
        return "setenv KUBECONFIG %s\n" % cfg_file
    else:
        return "export KUBECONFIG=%s\n" % cfg_file
Ejemplo n.º 3
0
def do_cluster_config(cs, args):
    """Configure native client to access cluster.

    You can source the output of this command to get the native client of the
    corresponding COE configured to access the cluster.

    Example: eval $(magnum cluster-config <cluster-name>).
    """
    cluster = cs.clusters.get(args.cluster)
    if cluster.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE'):
        raise exceptions.CommandError("cluster in status %s" % cluster.status)
    cluster_template = cs.cluster_templates.get(cluster.cluster_template_id)
    opts = {
        'cluster_uuid': cluster.uuid,
    }

    if not cluster_template.tls_disabled:
        tls = _generate_csr_and_key()
        tls['ca'] = cs.certificates.get(**opts).pem
        opts['csr'] = tls['csr']
        tls['cert'] = cs.certificates.create(**opts).pem
        for k in ('key', 'cert', 'ca'):
            fname = "%s/%s.pem" % (args.dir, k)
            if os.path.exists(fname) and not args.force:
                raise Exception("File %s exists, aborting." % fname)
            else:
                f = open(fname, "w")
                f.write(tls[k])
                f.close()

    print(
        _config_cluster(cluster,
                        cluster_template,
                        cfg_dir=args.dir,
                        force=args.force))
Ejemplo n.º 4
0
def format_labels(lbls, parse_comma=True):
    '''Reformat labels into dict of format expected by the API.'''

    if not lbls:
        return {}

    if parse_comma:
        # expect multiple invocations of --labels but fall back
        # to either , or ; delimited if only one --labels is specified
        if len(lbls) == 1 and lbls[0].count('=') > 1:
            lbls = lbls[0].replace(';', ',').split(',')

    labels = {}
    for l in lbls:
        try:
            (k, v) = l.split(('='), 1)
        except ValueError:
            raise exc.CommandError(
                _('labels must be a list of KEY=VALUE '
                  'not %s') % l)
        if k not in labels:
            labels[k] = v
        else:
            labels[k] += ",%s" % v

    return labels
Ejemplo n.º 5
0
def do_bay_config(cs, args):
    """Configure native client to access bay.

    You can source the output of this command to get the native client of the
    corresponding COE configured to access the bay.

    Example: eval $(magnum bay-config <bay-name>).

    (Deprecated in favor of cluster-config.)
    """
    args.dir = os.path.abspath(args.dir)
    bay = cs.bays.get(args.bay)
    if bay.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE'):
        raise exceptions.CommandError("Bay in status %s" % bay.status)
    baymodel = cs.baymodels.get(bay.baymodel_id)
    opts = {
        'cluster_uuid': bay.uuid,
    }

    if not baymodel.tls_disabled:
        tls = _generate_csr_and_key()
        tls['ca'] = cs.certificates.get(**opts).pem
        opts['csr'] = tls['csr']
        tls['cert'] = cs.certificates.create(**opts).pem
        for k in ('key', 'cert', 'ca'):
            fname = "%s/%s.pem" % (args.dir, k)
            if os.path.exists(fname) and not args.force:
                raise Exception("File %s exists, aborting." % fname)
            else:
                f = open(fname, "w")
                f.write(tls[k])
                f.close()

    print(_config_bay(bay, baymodel, cfg_dir=args.dir, force=args.force))
Ejemplo n.º 6
0
def _config_bay_kubernetes(bay, baymodel, cfg_dir, force=False):
    """Return and write configuration for the given kubernetes bay."""
    cfg_file = "%s/config" % cfg_dir
    if baymodel.tls_disabled:
        cfg = ("apiVersion: v1\n"
               "bays:\n"
               "- bay:\n"
               "    server: %(api_address)s\n"
               "  name: %(name)s\n"
               "contexts:\n"
               "- context:\n"
               "    bay: %(name)s\n"
               "    user: %(name)s\n"
               "  name: default/%(name)s\n"
               "current-context: default/%(name)s\n"
               "kind: Config\n"
               "preferences: {}\n"
               "users:\n"
               "- name: %(name)s'\n" % {
                   'name': bay.name,
                   'api_address': bay.api_address
               })
    else:
        cfg = ("apiVersion: v1\n"
               "bays:\n"
               "- bay:\n"
               "    certificate-authority: ca.pem\n"
               "    server: %(api_address)s\n"
               "  name: %(name)s\n"
               "contexts:\n"
               "- context:\n"
               "    bay: %(name)s\n"
               "    user: %(name)s\n"
               "  name: default/%(name)s\n"
               "current-context: default/%(name)s\n"
               "kind: Config\n"
               "preferences: {}\n"
               "users:\n"
               "- name: %(name)s\n"
               "  user:\n"
               "    client-certificate: cert.pem\n"
               "    client-key: key.pem\n" % {
                   'name': bay.name,
                   'api_address': bay.api_address
               })

    if os.path.exists(cfg_file) and not force:
        raise exceptions.CommandError("File %s exists, aborting." % cfg_file)
    else:
        f = open(cfg_file, "w")
        f.write(cfg)
        f.close()
    if 'csh' in os.environ['SHELL']:
        return "setenv KUBECONFIG %s\n" % cfg_file
    else:
        return "export KUBECONFIG=%s\n" % cfg_file
Ejemplo n.º 7
0
    def do_help(self, args):
        """Display help about this program or one of its subcommands."""
        # NOTE(jamespage): args.command is not guaranteed with python >= 3.4
        command = getattr(args, 'command', '')

        if command:
            if args.command in self.subcommands:
                self.subcommands[args.command].print_help()
            else:
                raise exc.CommandError("'%s' is not a valid subcommand" %
                                       args.command)
        else:
            self.parser.print_help()
Ejemplo n.º 8
0
def do_cluster_update(cs, args):
    """Update information about the given cluster."""
    if args.rollback and args.magnum_api_version and \
            args.magnum_api_version in ('1.0', '1.1', '1.2'):
        raise exceptions.CommandError("Rollback is not supported in API v%s. "
                                      "Please use API v1.3+." %
                                      args.magnum_api_version)
    patch = magnum_utils.args_array_to_patch(args.op, args.attributes[0])
    cluster = cs.clusters.update(args.cluster, patch, args.rollback)
    if args.magnum_api_version and args.magnum_api_version == '1.1':
        _show_cluster(cluster)
    else:
        print("Request to update cluster %s has been accepted." % args.cluster)
Ejemplo n.º 9
0
    def take_action(self, parsed_args):
        """Configure native client to access cluster.

        You can source the output of this command to get the native client of
        the corresponding COE configured to access the cluster.

        """
        if parsed_args.use_keystone:
            parsed_args.use_certificate = False
        if not parsed_args.use_certificate:
            parsed_args.use_keystone = True

        self.log.debug("take_action(%s)", parsed_args)

        mag_client = self.app.client_manager.container_infra

        parsed_args.dir = os.path.abspath(parsed_args.dir)
        cluster = mag_client.clusters.get(parsed_args.cluster)
        if cluster.status not in ('CREATE_COMPLETE', 'UPDATE_COMPLETE',
                                  'ROLLBACK_COMPLETE'):
            raise exceptions.CommandError("cluster in status %s" %
                                          cluster.status)
        cluster_template = mag_client.cluster_templates.get(
            cluster.cluster_template_id)
        opts = {
            'cluster_uuid': cluster.uuid,
        }

        tls = None
        if not cluster_template.tls_disabled:
            tls = magnum_utils.generate_csr_and_key()
            tls['ca'] = mag_client.certificates.get(**opts).pem
            opts['csr'] = tls['csr']
            tls['cert'] = mag_client.certificates.create(**opts).pem
            if parsed_args.output_certs:
                for k in ('key', 'cert', 'ca'):
                    fname = "%s/%s.pem" % (parsed_args.dir, k)
                    if os.path.exists(fname) and not parsed_args.force:
                        raise Exception("File %s exists, aborting." % fname)
                    else:
                        with open(fname, "w") as f:
                            f.write(tls[k])

        print(
            magnum_utils.config_cluster(cluster,
                                        cluster_template,
                                        parsed_args.dir,
                                        force=parsed_args.force,
                                        certs=tls,
                                        use_keystone=parsed_args.use_keystone))
Ejemplo n.º 10
0
    def _ensure_auth_info(self, args):
        if not cliutils.isunauthenticated(args.func):
            if (not (args.os_token and
                     (args.os_auth_url or args.os_endpoint_override))
                    and not args.os_cloud):

                if not (args.os_username or args.os_user_id):
                    raise exc.CommandError(
                        "You must provide a username via either --os-username "
                        "or via env[OS_USERNAME]")
                if not args.os_password:
                    raise exc.CommandError(
                        "You must provide a password via either "
                        "--os-password, env[OS_PASSWORD], or prompted "
                        "response")
                if (not args.os_project_name and not args.os_project_id):
                    raise exc.CommandError(
                        "You must provide a project name or project id via "
                        "--os-project-name, --os-project-id, "
                        "env[OS_PROJECT_NAME] or env[OS_PROJECT_ID]")
                if not args.os_auth_url:
                    raise exc.CommandError(
                        "You must provide an auth url via either "
                        "--os-auth-url or via env[OS_AUTH_URL]")
Ejemplo n.º 11
0
def args_array_to_patch(op, attributes):
    patch = []
    for attr in attributes:
        # Sanitize
        if not attr.startswith('/'):
            attr = '/' + attr
        if op in ['add', 'replace']:
            path, value = split_and_deserialize(attr)
            patch.append({'op': op, 'path': path, 'value': value})

        elif op == "remove":
            # For remove only the key is needed
            patch.append({'op': op, 'path': attr})
        else:
            raise exc.CommandError(_('Unknown PATCH operation: %s') % op)
    return patch
Ejemplo n.º 12
0
def do_bay_update(cs, args):
    """Update information about the given bay.

    (Deprecated in favor of cluster-update.)
    """
    if args.rollback and args.magnum_api_version and \
            args.magnum_api_version in ('1.0', '1.1', '1.2'):
        raise exceptions.CommandError("Rollback is not supported in API v%s. "
                                      "Please use API v1.3+." %
                                      args.magnum_api_version)
    patch = magnum_utils.args_array_to_patch(args.op, args.attributes[0])
    bay = cs.bays.update(args.bay, patch, args.rollback)
    if args.magnum_api_version and args.magnum_api_version == '1.1':
        _show_bay(bay)
    else:
        print("Request to update bay %s has been accepted." % args.bay)
Ejemplo n.º 13
0
def split_and_deserialize(string):
    """Split and try to JSON deserialize a string.

    Gets a string with the KEY=VALUE format, split it (using '=' as the
    separator) and try to JSON deserialize the VALUE.
    :returns: A tuple of (key, value).
    """
    try:
        key, value = string.split("=", 1)
    except ValueError:
        raise exc.CommandError(_('Attributes must be a list of '
                                 'PATH=VALUE not "%s"') % string)
    try:
        value = json.loads(value)
    except ValueError:
        pass

    return (key, value)
Ejemplo n.º 14
0
    def main(self, argv):

        # NOTE(Christoph Jansen): With Python 3.4 argv somehow becomes a Map.
        #                         This hack fixes it.
        argv = list(argv)

        # Parse args once to find version and debug settings
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)
        self.setup_debugging(options.debug)

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.
        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        # build available subcommands based on version
        (api_major_version, magnum_api_version) = (self._check_version(
            options.magnum_api_version))

        subcommand_parser = (self.get_subcommand_parser(api_major_version))
        self.parser = subcommand_parser

        if options.help or not argv:
            subcommand_parser.print_help()
            return 0

        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help right away.
        # NOTE(jamespage): args.func is not guaranteed with python >= 3.4
        if not hasattr(args, 'func') or args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        if not args.service_type:
            args.service_type = DEFAULT_SERVICE_TYPE

        if args.bypass_url:
            args.os_endpoint_override = args.bypass_url

        args.os_project_id = (args.os_project_id or args.os_tenant_id)
        args.os_project_name = (args.os_project_name or args.os_tenant_name)

        if not cliutils.isunauthenticated(args.func):
            if (not (args.os_token and
                     (args.os_auth_url or args.os_endpoint_override))
                    and not args.os_cloud):

                if not (args.os_username or args.os_user_id):
                    raise exc.CommandError(
                        "You must provide a username via either --os-username "
                        "or via env[OS_USERNAME]")
                if not args.os_password:
                    raise exc.CommandError(
                        "You must provide a password via either "
                        "--os-password, env[OS_PASSWORD], or prompted "
                        "response")
                if (not args.os_project_name and not args.os_project_id):
                    raise exc.CommandError(
                        "You must provide a project name or project id via "
                        "--os-project-name, --os-project-id, "
                        "env[OS_PROJECT_NAME] or env[OS_PROJECT_ID]")
                if not args.os_auth_url:
                    raise exc.CommandError(
                        "You must provide an auth url via either "
                        "--os-auth-url or via env[OS_AUTH_URL]")
        try:
            client = {
                '1': client_v1,
            }[api_major_version]
        except KeyError:
            client = client_v1

        args.os_endpoint_type = (args.os_endpoint_type or args.endpoint_type)
        if args.os_endpoint_type:
            args.os_interface = args.os_endpoint_type

        if args.os_interface.endswith('URL'):
            args.os_interface = args.os_interface[:-3]

        self.cs = client.Client(
            cloud=args.os_cloud,
            user_id=args.os_user_id,
            username=args.os_username,
            password=args.os_password,
            auth_token=args.os_token,
            project_id=args.os_project_id,
            project_name=args.os_project_name,
            user_domain_id=args.os_user_domain_id,
            user_domain_name=args.os_user_domain_name,
            project_domain_id=args.os_project_domain_id,
            project_domain_name=args.os_project_domain_name,
            auth_url=args.os_auth_url,
            service_type=args.service_type,
            region_name=args.os_region_name,
            magnum_url=args.os_endpoint_override,
            interface=args.os_interface,
            insecure=args.insecure,
            api_version=args.magnum_api_version,
        )

        self._check_deprecation(args.func, argv)
        args.func(self.cs, args)
Ejemplo n.º 15
0
def _config_cluster_kubernetes(cluster, cluster_template, cfg_dir,
                               force=False, certs=None, use_keystone=False):
    """Return and write configuration for the given kubernetes cluster."""
    cfg_file = "%s/config" % cfg_dir
    if cluster_template.tls_disabled or certs is None:
        cfg = ("apiVersion: v1\n"
               "clusters:\n"
               "- cluster:\n"
               "    server: %(api_address)s\n"
               "  name: %(name)s\n"
               "contexts:\n"
               "- context:\n"
               "    cluster: %(name)s\n"
               "    user: %(name)s\n"
               "  name: %(name)s\n"
               "current-context: %(name)s\n"
               "kind: Config\n"
               "preferences: {}\n"
               "users:\n"
               "- name: %(name)s'\n"
               % {'name': cluster.name, 'api_address': cluster.api_address})
    else:
        if not use_keystone:
            cfg = ("apiVersion: v1\n"
                   "clusters:\n"
                   "- cluster:\n"
                   "    certificate-authority-data: %(ca)s\n"
                   "    server: %(api_address)s\n"
                   "  name: %(name)s\n"
                   "contexts:\n"
                   "- context:\n"
                   "    cluster: %(name)s\n"
                   "    user: admin\n"
                   "  name: default\n"
                   "current-context: default\n"
                   "kind: Config\n"
                   "preferences: {}\n"
                   "users:\n"
                   "- name: admin\n"
                   "  user:\n"
                   "    client-certificate-data: %(cert)s\n"
                   "    client-key-data: %(key)s\n"
                   % {'name': cluster.name,
                      'api_address': cluster.api_address,
                      'key': base64.encode_as_text(certs['key']),
                      'cert': base64.encode_as_text(certs['cert']),
                      'ca': base64.encode_as_text(certs['ca'])})
        else:
            cfg = ("apiVersion: v1\n"
                   "clusters:\n"
                   "- cluster:\n"
                   "    certificate-authority-data: %(ca)s\n"
                   "    server: %(api_address)s\n"
                   "  name: %(name)s\n"
                   "contexts:\n"
                   "- context:\n"
                   "    cluster: %(name)s\n"
                   "    user: openstackuser\n"
                   "  name: openstackuser@kubernetes\n"
                   "current-context: openstackuser@kubernetes\n"
                   "kind: Config\n"
                   "preferences: {}\n"
                   "users:\n"
                   "- name: openstackuser\n"
                   "  user:\n"
                   "    exec:\n"
                   "      command: /bin/bash\n"
                   "      apiVersion: client.authentication.k8s.io/v1alpha1\n"
                   "      args:\n"
                   "      - -c\n"
                   "      - >\n"
                   "        if [ -z ${OS_TOKEN} ]; then\n"
                   "            echo 'Error: Missing OpenStack credential from environment variable $OS_TOKEN' > /dev/stderr\n"  # noqa
                   "            exit 1\n"
                   "        else\n"
                   "            echo '{ \"apiVersion\": \"client.authentication.k8s.io/v1alpha1\", \"kind\": \"ExecCredential\", \"status\": { \"token\": \"'\"${OS_TOKEN}\"'\"}}'\n"  # noqa
                   "        fi\n"
                   % {'name': cluster.name,
                      'api_address': cluster.api_address,
                      'ca': base64.encode_as_text(certs['ca'])})

    if os.path.exists(cfg_file) and not force:
        raise exc.CommandError("File %s exists, aborting." % cfg_file)
    else:
        f = open(cfg_file, "w")
        f.write(cfg)
        f.close()
    if 'csh' in os.environ['SHELL']:
        return "setenv KUBECONFIG %s\n" % cfg_file
    else:
        return "export KUBECONFIG=%s\n" % cfg_file
Ejemplo n.º 16
0
    def main(self, argv):

        # NOTE(Christoph Jansen): With Python 3.4 argv somehow becomes a Map.
        #                         This hack fixes it.
        argv = list(argv)

        # Parse args once to find version and debug settings
        parser = self.get_base_parser()
        (options, args) = parser.parse_known_args(argv)
        self.setup_debugging(options.debug)

        # NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
        #                thinking usage-list --end is ambiguous; but it
        #                works fine with only --endpoint-type present
        #                Go figure.
        if '--endpoint_type' in argv:
            spot = argv.index('--endpoint_type')
            argv[spot] = '--endpoint-type'

        subcommand_parser = (self.get_subcommand_parser(
            options.magnum_api_version))
        self.parser = subcommand_parser

        if options.help or not argv:
            subcommand_parser.print_help()
            return 0

        args = subcommand_parser.parse_args(argv)

        # Short-circuit and deal with help right away.
        # NOTE(jamespage): args.func is not guaranteed with python >= 3.4
        if not hasattr(args, 'func') or args.func == self.do_help:
            self.do_help(args)
            return 0
        elif args.func == self.do_bash_completion:
            self.do_bash_completion(args)
            return 0

        (os_username, os_tenant_name, os_tenant_id, os_user_domain_id,
         os_user_domain_name, os_project_domain_id, os_project_domain_name,
         os_auth_url, os_auth_system, endpoint_type, service_type, bypass_url,
         insecure) = ((args.os_username, args.os_tenant_name,
                       args.os_tenant_id, args.os_user_domain_id,
                       args.os_user_domain_name, args.os_project_domain_id,
                       args.os_project_domain_name, args.os_auth_url,
                       args.os_auth_system, args.endpoint_type,
                       args.service_type, args.bypass_url, args.insecure))

        if os_auth_system and os_auth_system != "keystone":
            auth_plugin = auth.load_plugin(os_auth_system)
        else:
            auth_plugin = None

        # Fetched and set later as needed
        os_password = None

        if not endpoint_type:
            endpoint_type = DEFAULT_ENDPOINT_TYPE

        if not service_type:
            service_type = DEFAULT_SERVICE_TYPE
# NA - there is only one service this CLI accesses
#            service_type = utils.get_service_type(args.func) or service_type

# FIXME(usrleon): Here should be restrict for project id same as
# for os_username or os_password but for compatibility it is not.
        if not cliutils.isunauthenticated(args.func):
            if auth_plugin:
                auth_plugin.parse_opts(args)

            if not auth_plugin or not auth_plugin.opts:
                if not os_username:
                    raise exc.CommandError("You must provide a username "
                                           "via either --os-username or "
                                           "env[OS_USERNAME]")

            if not os_tenant_name and not os_tenant_id:
                raise exc.CommandError("You must provide a tenant name "
                                       "or tenant id via --os-tenant-name, "
                                       "--os-tenant-id, env[OS_TENANT_NAME] "
                                       "or env[OS_TENANT_ID]")

            if not os_auth_url:
                if os_auth_system and os_auth_system != 'keystone':
                    os_auth_url = auth_plugin.get_auth_url()

            if not os_auth_url:
                raise exc.CommandError("You must provide an auth url "
                                       "via either --os-auth-url or "
                                       "env[OS_AUTH_URL] or specify an "
                                       "auth_system which defines a "
                                       "default url with --os-auth-system "
                                       "or env[OS_AUTH_SYSTEM]")

# NOTE: The Magnum client authenticates when you create it. So instead of
#       creating here and authenticating later, which is what the novaclient
#       does, we just create the client later.

# Now check for the password/token of which pieces of the
# identifying keyring key can come from the underlying client
        if not cliutils.isunauthenticated(args.func):
            # NA - Client can't be used with SecretsHelper
            if (auth_plugin and auth_plugin.opts
                    and "os_password" not in auth_plugin.opts):
                use_pw = False
            else:
                use_pw = True

            if use_pw:
                # Auth using token must have failed or not happened
                # at all, so now switch to password mode and save
                # the token when its gotten... using our keyring
                # saver
                os_password = args.os_password
                if not os_password:
                    raise exc.CommandError(
                        'Expecting a password provided via either '
                        '--os-password, env[OS_PASSWORD], or '
                        'prompted response')

        try:
            client = {
                '1': client_v1,
            }[options.magnum_api_version]
        except KeyError:
            client = client_v1

        self.cs = client.Client(username=os_username,
                                api_key=os_password,
                                project_id=os_tenant_id,
                                project_name=os_tenant_name,
                                user_domain_id=os_user_domain_id,
                                user_domain_name=os_user_domain_name,
                                project_domain_id=os_project_domain_id,
                                project_domain_name=os_project_domain_name,
                                auth_url=os_auth_url,
                                service_type=service_type,
                                region_name=args.os_region_name,
                                magnum_url=bypass_url,
                                endpoint_type=endpoint_type,
                                insecure=insecure)

        args.func(self.cs, args)