Source code for ironic.command.manage

#    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.

"""
Management and discoverability utility for ironic deployments.
"""

from importlib import metadata
import sys

from oslo_config import cfg

from ironic.common.i18n import _
from ironic.common import service
from ironic.conf import CONF
from ironic.drivers import base as driver_base

HARDWARE_TYPES_GROUP = 'ironic.hardware.types'
INTERFACES_GROUP_TEMPLATE = 'ironic.hardware.interfaces.%s'


def _print_entry_point_group(group, config_option, title):
    """Print all entry points registered under an entry point group.

    :param group: name of the entry point group, e.g.
        "ironic.hardware.types".
    :param config_option: name of the [DEFAULT] configuration option the
        entry point names are valid values for.
    :param title: human-readable name for the group of entry points.
    """
    print('%s (for [DEFAULT]%s):' % (title, config_option))

    entry_points = sorted(metadata.entry_points(group=group),
                          key=lambda ep: ep.name)
    if not entry_points:
        print(_('  (no entry points found)'))
        return

    name_width = max(len(ep.name) for ep in entry_points)
    for ep in entry_points:
        try:
            plugin = ep.load()
        except Exception as exc:
            detail = _('(failed to load: %s)') % exc
        else:
            dist = getattr(ep, 'dist', None)
            detail = ep.value
            if dist is not None:
                detail += ' (%s)' % dist.name
            if not getattr(plugin, 'supported', True):
                detail += _(' (deprecated/unsupported)')
        print('  %s  %s' % (ep.name.ljust(name_width), detail))


def _print_interfaces(interface_types):
    """Print the entry points for the requested interface types.

    :param interface_types: list of interface types to display.
    """
    for index, iface_type in enumerate(interface_types):
        if index:
            print()
        _print_entry_point_group(
            INTERFACES_GROUP_TEMPLATE % iface_type,
            'enabled_%s_interfaces' % iface_type,
            '%s interfaces' % iface_type.capitalize())


def _select_interface_types(requested):
    """Validate the requested interface types.

    :param requested: list of interface types requested by the user. An
        empty list requests all interface types.
    :returns: the list of interface types to display.
    """
    unknown = set(requested) - driver_base.ALL_INTERFACES
    if unknown:
        sys.stderr.write(
            _('Unknown interface type(s): %s\n')
            % ', '.join(sorted(unknown)))
        sys.exit(2)
    if not requested:
        return sorted(driver_base.ALL_INTERFACES)
    # Preserve the requested order while removing duplicates.
    return list(dict.fromkeys(requested))


[docs] class DriverCommands(object):
[docs] def hardware_types(self): _print_entry_point_group(HARDWARE_TYPES_GROUP, 'enabled_hardware_types', 'Hardware types')
[docs] def interfaces(self): _print_interfaces( _select_interface_types(CONF.command.interface_types))
[docs] def add_command_parsers(subparsers): driver_commands = DriverCommands() parser = subparsers.add_parser( 'drivers', help=_('Discover the driver entry points installed on this ' 'system.')) drivers_subparsers = parser.add_subparsers( title='Driver commands', dest='drivers_command') drivers_subparsers.required = True parser = drivers_subparsers.add_parser( 'hardware-types', help=_('List the hardware types installed on this system, i.e. ' 'the valid values for the [DEFAULT]enabled_hardware_types ' 'configuration option.')) parser.set_defaults(func=driver_commands.hardware_types) parser = drivers_subparsers.add_parser( 'interfaces', help=_('List the hardware interfaces installed on this system, ' 'i.e. the valid values for the ' '[DEFAULT]enabled_<interface type>_interfaces ' 'configuration options. Optionally, pass one or more ' 'interface types (e.g. "deploy") to only list those ' 'types.')) parser.add_argument( 'interface_types', nargs='*', metavar='<interface type>', help=_('Interface types to list, one of: %s. If not specified, ' 'all interface types are listed.') % ', '.join(sorted(driver_base.ALL_INTERFACES))) parser.set_defaults(func=driver_commands.interfaces)
[docs] def main(): command_opt = cfg.SubCommandOpt('command', title='Command', help=_('Available commands'), handler=add_command_parsers) CONF.register_cli_opt(command_opt) service.prepare_command(sys.argv) CONF.command.func()
if __name__ == '__main__': sys.exit(main())