A standalone CLI for ironic

This changes adds a new command ``baremetal`` that works mostly like
the OSC ``openstack baremetal`` command but does not require OSC and
defaults to no-auth. No changes in existing commands are required,
the existing OSC plugins are pulled in.

Change-Id: Id4895ec37bfb58eb635e5c8519f96f1bdc30c925
This commit is contained in:
Dmitry Tantsur 2020-04-03 11:52:02 +02:00
parent 9be0a750a9
commit f7662b01c2
9 changed files with 235 additions and 6 deletions

View File

@ -4,4 +4,5 @@ python-ironicclient User Documentation
.. toctree:: .. toctree::
standalone
osc_plugin_cli osc_plugin_cli

View File

@ -30,6 +30,16 @@ package must be installed. There are two ways to do this:
$ pip install python-openstackclient $ pip install python-openstackclient
This CLI is provided by python-openstackclient and osc-lib projects:
* https://opendev.org/openstack/python-openstackclient
* https://opendev.org/openstack/osc-lib
.. _osc-auth:
Authentication
--------------
To use the CLI, you must provide your OpenStack username, password, To use the CLI, you must provide your OpenStack username, password,
project, and auth endpoint. You can use configuration options project, and auth endpoint. You can use configuration options
``--os-username``, ``--os-password``, ``--os-project-id`` ``--os-username``, ``--os-password``, ``--os-project-id``
@ -44,11 +54,6 @@ or set the corresponding environment variables::
$ export OS_IDENTITY_API_VERSION=3 $ export OS_IDENTITY_API_VERSION=3
$ export OS_AUTH_URL=http://auth.example.com:5000/identity $ export OS_AUTH_URL=http://auth.example.com:5000/identity
This CLI is provided by python-openstackclient and osc-lib projects:
* https://opendev.org/openstack/python-openstackclient
* https://opendev.org/openstack/osc-lib
Getting help Getting help
============ ============
@ -91,6 +96,7 @@ The baremetal API version can be specified via:
$ openstack baremetal port group list --os-baremetal-api-version 1.25 $ openstack baremetal port group list --os-baremetal-api-version 1.25
Command Reference Command Reference
================= =================
.. toctree:: .. toctree::

View File

@ -0,0 +1,69 @@
=====================================================
``baremetal`` Standalone Command-Line Interface (CLI)
=====================================================
.. program:: baremetal
.. highlight:: bash
Synopsis
========
:program:`baremetal [options]` <command> [command-options]
:program:`baremetal help` <command>
Description
===========
The standalone ``baremetal`` tool allows interacting with the Bare Metal
service without installing the OpenStack Client tool as in
:doc:`osc_plugin_cli`.
The standalone tool is mostly identical to its OSC counterpart, with two
exceptions:
#. No need to prefix commands with ``openstack``.
#. No authentication is assumed by default.
Check the :doc:`OSC CLI reference </cli/osc/v1/index>` for a list of available
commands.
Standalone usage
----------------
To use the CLI with a standalone bare metal service, you need to provide an
endpoint to connect to. It can be done in three ways:
#. Provide an explicit ``--os-endpoint`` argument, e.g.:
.. code-block:: bash
$ baremetal --os-endpoint https://ironic.host:6385 node list
#. Set the corresponding environment variable, e.g.:
.. code-block:: bash
$ export OS_ENDPOINT=https://ironic.host:6385
$ baremetal node list
#. Populate a clouds.yaml_ file, setting ``baremetal_endpoint_override``, e.g.:
.. code-block:: bash
$ cat ~/.config/openstack/clouds.yaml
clouds:
ironic:
auth_type: none
baremetal_endpoint_override: http://127.0.0.1:6385
$ export OS_CLOUD=ironic
$ baremetal node list
.. _clouds.yaml: https://docs.openstack.org/openstacksdk/latest/user/guides/connect_from_config.html
Usage with OpenStack
--------------------
The standalone CLI can also be used with the Bare Metal service installed as
part of OpenStack. See :ref:`osc-auth` for information on the required input.

134
ironicclient/shell.py Normal file
View File

@ -0,0 +1,134 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import collections
import logging
import sys
from cliff import app
from cliff import commandmanager
from openstack import config as os_config
from osc_lib import utils
import pbr.version
from ironicclient.common import http
from ironicclient.common.i18n import _
from ironicclient import exc
from ironicclient.v1 import client
_DEFAULTS = {
'auth_type': 'none',
}
_TYPE = 'baremetal'
_DESCRIPTION = 'Bare Metal service (ironic) client'
_NAMESPACE = 'openstack.baremetal.v1'
LOG = logging.getLogger(__name__)
ClientManager = collections.namedtuple('ClientManager', ['baremetal'])
class CommandManager(commandmanager.CommandManager):
def load_commands(self, namespace):
super(CommandManager, self).load_commands(namespace)
# Stip the 'baremetal' prefix used in OSC
prefix = 'baremetal '
prefix_len = len(prefix)
self.commands = dict(
(cmd[prefix_len:] if cmd.startswith(prefix) else cmd, ep)
for (cmd, ep) in self.commands.items()
)
class App(app.App):
def __init__(self):
version_info = pbr.version.VersionInfo('python-ironicclient')
mgr = CommandManager(_NAMESPACE)
self.config = os_config.OpenStackConfig(override_defaults=_DEFAULTS)
super(App, self).__init__(description=_DESCRIPTION,
version=str(version_info),
command_manager=mgr)
def build_option_parser(self, description, version, argparse_kwargs=None):
parser = super(App, self).build_option_parser(
description, version, argparse_kwargs=argparse_kwargs)
self.config.register_argparse_arguments(parser, sys.argv[1:])
parser.add_argument(
'--os-baremetal-api-version',
metavar='<baremetal-api-version>',
default=utils.env('OS_BAREMETAL_API_VERSION'),
help='Bare metal API version, default="latest" (the maximum '
'version supported by both the client and the server). '
'(Env: OS_BAREMETAL_API_VERSION)',
)
parser.add_argument(
'--max-retries',
metavar='<max-retries-number>',
default=http.DEFAULT_MAX_RETRIES,
type=int,
help='Maximum number of retries on connection problems and '
'resource state conflicts'
)
parser.add_argument(
'--retry-interval',
metavar='<retry-interval-seconds>',
default=http.DEFAULT_RETRY_INTERVAL,
type=int,
help='Interval in seconds between two retries'
)
return parser
def initialize_app(self, argv):
super(App, self).initialize_app(argv)
self.cloud_region = self.config.get_one(argparse=self.options)
api_version = self.options.os_baremetal_api_version
allow_api_version_downgrade = False
if not api_version:
api_version = self.cloud_region.get_default_microversion(_TYPE)
if not api_version:
api_version = http.LATEST_VERSION
allow_api_version_downgrade = True
LOG.debug('Using API version %s, downgrade %s', api_version,
'allowed' if allow_api_version_downgrade else 'disallowed')
# NOTE(dtantsur): endpoint_override is required to respect settings in
# clouds.yaml, such as baremetal_endpoint_override.
endpoint_override = self.cloud_region.get_endpoint(_TYPE)
try:
self.client = client.Client(
os_ironic_api_version=api_version,
allow_api_version_downgrade=allow_api_version_downgrade,
session=self.cloud_region.get_session(),
region_name=self.cloud_region.get_region_name(_TYPE),
endpoint_override=endpoint_override,
max_retries=self.options.max_retries,
retry_interval=self.options.retry_interval,
)
except exc.EndpointNotFound as e:
# Re-raise with a more obvious message.
msg = _("%(err)s.\n* Use --os-endpoint for standalone ironic.\n"
"* Use --os-auth-url and credentials for authentication.\n"
"* Use --os-cloud to load configuration from clouds.yaml\n"
"* See `%(cmd)s --help` for more details")
raise exc.EndpointNotFound(msg % {'err': e, 'cmd': sys.argv[0]})
# Compatibility with OSC
self.client_manager = ClientManager(self.client)
def main(argv=sys.argv[1:]):
return App().run(argv)

View File

@ -42,7 +42,7 @@ munch==2.1.0
netaddr==0.7.18 netaddr==0.7.18
netifaces==0.10.4 netifaces==0.10.4
openstackdocstheme==1.20.0 openstackdocstheme==1.20.0
openstacksdk==0.11.2 openstacksdk==0.18.0
os-client-config==1.28.0 os-client-config==1.28.0
os-service-types==1.2.0 os-service-types==1.2.0
os-testr==1.0.0 os-testr==1.0.0

View File

@ -0,0 +1,11 @@
---
prelude: |
This release includes a new standalone CLI tool ``baremetal`` that is
mostly identical to the existing OSC plugin, but
* Does not require commands to be prefixed with ``openstack``.
* Does not require ``python-openstackclient`` to be installed.
* Defaults to no authentication.
features:
- |
Adds a new ``baremetal`` CLI tool, mostly targeted at standalone users.

View File

@ -3,9 +3,11 @@
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0
appdirs>=1.3.0 # MIT License appdirs>=1.3.0 # MIT License
cliff!=2.9.0,>=2.8.0 # Apache-2.0
dogpile.cache>=0.6.2 # BSD dogpile.cache>=0.6.2 # BSD
jsonschema>=2.6.0 # MIT jsonschema>=2.6.0 # MIT
keystoneauth1>=3.4.0 # Apache-2.0 keystoneauth1>=3.4.0 # Apache-2.0
openstacksdk>=0.18.0 # Apache-2.0
osc-lib>=1.10.0 # Apache-2.0 osc-lib>=1.10.0 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0 oslo.config>=5.2.0 # Apache-2.0
oslo.i18n>=3.15.3 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0
@ -13,3 +15,4 @@ oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
PyYAML>=3.12 # MIT PyYAML>=3.12 # MIT
requests>=2.14.2 # Apache-2.0 requests>=2.14.2 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0

View File

@ -20,6 +20,9 @@ classifier =
packages = ironicclient packages = ironicclient
[entry_points] [entry_points]
console_scripts =
baremetal = ironicclient.shell:main
openstack.cli.extension = openstack.cli.extension =
baremetal = ironicclient.osc.plugin baremetal = ironicclient.osc.plugin

View File

@ -14,3 +14,5 @@ tempest>=17.1.0 # Apache-2.0
stestr>=1.0.0 # Apache-2.0 stestr>=1.0.0 # Apache-2.0
ddt>=1.0.1 # MIT ddt>=1.0.1 # MIT
python-openstackclient>=3.12.0 # Apache-2.0 python-openstackclient>=3.12.0 # Apache-2.0
# Required for syntax highlighting check
Pygments>=2.2.0 # BSD