From 58701fe014bf118ee0bbed5272c1a08e3f594ae0 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 3 Nov 2017 14:27:36 +0100 Subject: [PATCH] Support more hardware types and deprecate enabled_drivers Ironic is going to deprecate classic drivers in Queens and remove them in Rocky. This change enables hardware types ilo and idrac that correspond to already enabled classic drivers pxe_ilo and pxe_drac. It also adds support for other common hardware types, but does not enable them by default. The enabled_drivers option is deprecated. Partial-Bug: #1690185 Change-Id: Ib505f3512627c49d17d6adcdc2622bdfe580a84f --- .../puppet-stack-config.yaml.template | 3 + instack_undercloud/tests/test_undercloud.py | 63 ++++++++-- instack_undercloud/undercloud.py | 115 +++++++++++++----- .../switch-to-hw-types-b3abf03ef9b7973b.yaml | 23 ++++ undercloud.conf.sample | 17 ++- 5 files changed, 176 insertions(+), 45 deletions(-) create mode 100644 releasenotes/notes/switch-to-hw-types-b3abf03ef9b7973b.yaml diff --git a/elements/puppet-stack-config/puppet-stack-config.yaml.template b/elements/puppet-stack-config/puppet-stack-config.yaml.template index ea8d3fbdd..b41302c9f 100644 --- a/elements/puppet-stack-config/puppet-stack-config.yaml.template +++ b/elements/puppet-stack-config/puppet-stack-config.yaml.template @@ -513,10 +513,13 @@ ironic::conductor::default_boot_option: 'local' ironic::conductor::enabled_drivers: {{ENABLED_DRIVERS}} ironic::conductor::enabled_hardware_types: {{ENABLED_HARDWARE_TYPES}} ironic::drivers::interfaces::default_inspect_interface: inspector +ironic::drivers::interfaces::enabled_boot_interfaces: {{ENABLED_BOOT_INTERFACES}} ironic::drivers::interfaces::enabled_console_interfaces: ['no-console', 'ipmitool-socat'] ironic::drivers::interfaces::enabled_inspect_interfaces: ['no-inspect', 'inspector'] ironic::drivers::interfaces::enabled_management_interfaces: {{ENABLED_MANAGEMENT_INTERFACES}} ironic::drivers::interfaces::enabled_power_interfaces: {{ENABLED_POWER_INTERFACES}} +ironic::drivers::interfaces::enabled_raid_interfaces: {{ENABLED_RAID_INTERFACES}} +ironic::drivers::interfaces::enabled_vendor_interfaces: {{ENABLED_VENDOR_INTERFACES}} ironic::keystone::auth::tenant: 'service' ironic::keystone::auth::public_url: {{UNDERCLOUD_ENDPOINT_IRONIC_PUBLIC}} ironic::keystone::auth::internal_url: {{UNDERCLOUD_ENDPOINT_IRONIC_INTERNAL}} diff --git a/instack_undercloud/tests/test_undercloud.py b/instack_undercloud/tests/test_undercloud.py index 27ca58056..991d8d7e0 100644 --- a/instack_undercloud/tests/test_undercloud.py +++ b/instack_undercloud/tests/test_undercloud.py @@ -482,19 +482,70 @@ class TestGenerateEnvironment(BaseTestCase): drivers = json.loads(env['ENABLED_DRIVERS']) self.assertEqual(sorted(drivers), ['pxe_drac', 'pxe_ilo', 'pxe_ipmitool']) + hw_types = json.loads(env['ENABLED_HARDWARE_TYPES']) + self.assertEqual(sorted(hw_types), ['idrac', 'ilo', 'ipmi', 'redfish']) + self.assertEqual( + sorted(json.loads(env['ENABLED_BOOT_INTERFACES'])), + ['ilo-pxe', 'pxe']) + self.assertEqual( + sorted(json.loads(env['ENABLED_POWER_INTERFACES'])), + ['fake', 'idrac', 'ilo', 'ipmitool', 'redfish']) + self.assertEqual( + sorted(json.loads(env['ENABLED_MANAGEMENT_INTERFACES'])), + ['fake', 'idrac', 'ilo', 'ipmitool', 'redfish']) + self.assertEqual( + sorted(json.loads(env['ENABLED_RAID_INTERFACES'])), + ['idrac', 'no-raid']) + self.assertEqual( + sorted(json.loads(env['ENABLED_VENDOR_INTERFACES'])), + ['idrac', 'ipmitool', 'no-vendor']) self.assertEqual(env['INSPECTION_NODE_NOT_FOUND_HOOK'], '') + def test_all_hardware_types(self): + conf = config_fixture.Config() + self.useFixture(conf) + conf.config(enabled_hardware_types=['ipmi', 'redfish', 'ilo', + 'idrac', 'irmc', 'snmp', + 'cisco-ucs-managed', + 'cisco-ucs-standalone']) + env = undercloud._generate_environment('.') + # The list is generated from a set, so we can't rely on ordering. + # Instead make sure that it looks like a valid list by parsing it. + hw_types = json.loads(env['ENABLED_HARDWARE_TYPES']) + self.assertEqual(sorted(hw_types), ['cisco-ucs-managed', + 'cisco-ucs-standalone', + 'idrac', 'ilo', 'ipmi', 'irmc', + 'redfish', 'snmp']) + self.assertEqual( + sorted(json.loads(env['ENABLED_BOOT_INTERFACES'])), + ['ilo-pxe', 'irmc-pxe', 'pxe']) + self.assertEqual( + sorted(json.loads(env['ENABLED_POWER_INTERFACES'])), + ['cimc', 'fake', 'idrac', 'ilo', 'ipmitool', 'irmc', + 'redfish', 'snmp', 'ucsm']) + self.assertEqual( + sorted(json.loads(env['ENABLED_MANAGEMENT_INTERFACES'])), + ['cimc', 'fake', 'idrac', 'ilo', 'ipmitool', 'irmc', + 'redfish', 'ucsm']) + self.assertEqual( + sorted(json.loads(env['ENABLED_RAID_INTERFACES'])), + ['idrac', 'no-raid']) + self.assertEqual( + sorted(json.loads(env['ENABLED_VENDOR_INTERFACES'])), + ['idrac', 'ipmitool', 'no-vendor']) + def test_enabled_discovery(self): conf = config_fixture.Config() self.useFixture(conf) conf.config(enable_node_discovery=True, - discovery_default_driver='foobar') + discovery_default_driver='pxe_foobar') env = undercloud._generate_environment('.') # The list is generated from a set, so we can't rely on ordering. # Instead make sure that it looks like a valid list by parsing it. drivers = json.loads(env['ENABLED_DRIVERS']) - # Discovery requires enabling the default driver - self.assertEqual(sorted(drivers), ['foobar', 'pxe_drac', 'pxe_ilo', + # Discovery requires enabling the default driver. The pxe_ prefix + # designates a classic driver. + self.assertEqual(sorted(drivers), ['pxe_drac', 'pxe_foobar', 'pxe_ilo', 'pxe_ipmitool']) self.assertEqual(env['INSPECTION_NODE_NOT_FOUND_HOOK'], 'enroll') @@ -503,17 +554,15 @@ class TestGenerateEnvironment(BaseTestCase): self.useFixture(conf) conf.config(enable_node_discovery=True, discovery_default_driver='foobar', - enabled_hardware_types=['ipmi', 'foobar']) + enabled_hardware_types=['ipmi', 'something']) env = undercloud._generate_environment('.') # The list is generated from a set, so we can't rely on ordering. # Instead make sure that it looks like a valid list by parsing it. drivers = json.loads(env['ENABLED_DRIVERS']) hw_types = json.loads(env['ENABLED_HARDWARE_TYPES']) - # The driver is already in hardware types, so we don't try adding it to - # the driver list. self.assertEqual(sorted(drivers), ['pxe_drac', 'pxe_ilo', 'pxe_ipmitool']) - self.assertEqual(sorted(hw_types), ['foobar', 'ipmi']) + self.assertEqual(sorted(hw_types), ['foobar', 'ipmi', 'something']) def test_docker_registry_mirror(self): conf = config_fixture.Config() diff --git a/instack_undercloud/undercloud.py b/instack_undercloud/undercloud.py index 8586c6020..5acc310f1 100644 --- a/instack_undercloud/undercloud.py +++ b/instack_undercloud/undercloud.py @@ -289,10 +289,11 @@ _opts = [ 'information for newly enrolled nodes.') ), cfg.StrOpt('discovery_default_driver', - default='pxe_ipmitool', - help=('The default driver to use for newly discovered nodes ' - '(requires enable_node_discovery set to True). This ' - 'driver is automatically added to enabled_drivers.') + default='ipmi', + help=('The default driver or hardware type to use for newly ' + 'discovered nodes (requires enable_node_discovery set to ' + 'True). It is automatically added to enabled_drivers ' + 'or enabled_hardware_types accordingly.') ), cfg.BoolOpt('undercloud_debug', default=True, @@ -360,9 +361,12 @@ _opts = [ 'between deployments and after the introspection.')), cfg.ListOpt('enabled_drivers', default=['pxe_ipmitool', 'pxe_drac', 'pxe_ilo'], - help=('List of enabled bare metal drivers.')), + help=('List of enabled bare metal drivers.'), + deprecated_for_removal=True, + deprecated_reason=('Please switch to hardware types and ' + 'the enabled_hardware_types option.')), cfg.ListOpt('enabled_hardware_types', - default=['ipmi', 'redfish'], + default=['ipmi', 'redfish', 'ilo', 'idrac'], help=('List of enabled bare metal hardware types (next ' 'generation drivers).')), cfg.StrOpt('docker_registry_mirror', @@ -1056,7 +1060,8 @@ class InstackEnvironment(dict): 'INSPECTION_NODE_NOT_FOUND_HOOK', 'TRIPLEO_INSTALL_USER', 'TRIPLEO_UNDERCLOUD_CONF_FILE', 'TRIPLEO_UNDERCLOUD_PASSWORD_FILE', - 'ENABLED_POWER_INTERFACES', + 'ENABLED_BOOT_INTERFACES', 'ENABLED_POWER_INTERFACES', + 'ENABLED_RAID_INTERFACES', 'ENABLED_VENDOR_INTERFACES', 'ENABLED_MANAGEMENT_INTERFACES', 'SYSCTL_SETTINGS', 'LOCAL_IP_WRAPPED'} """The variables we calculate in _generate_environment call.""" @@ -1091,6 +1096,76 @@ def _generate_sysctl_settings(): return json.dumps(sysctl_settings) +def _is_classic_driver(name): + """Poor man's way to detect if something is a driver or a hardware type. + + To be removed when we remove support for classic drivers. + """ + return (name == 'fake' or + name.startswith('fake_') or + name.startswith('pxe_') or + name.startswith('agent_') or + name.startswith('iscsi_')) + + +def _process_drivers_and_hardware_types(instack_env): + """Populate the environment with ironic driver information.""" + # Ensure correct rendering of the list and uniqueness of the items + enabled_drivers = set(CONF.enabled_drivers) + enabled_hardware_types = set(CONF.enabled_hardware_types) + if CONF.enable_node_discovery: + if _is_classic_driver(CONF.discovery_default_driver): + if CONF.discovery_default_driver not in enabled_drivers: + enabled_drivers.add(CONF.discovery_default_driver) + else: + if CONF.discovery_default_driver not in enabled_hardware_types: + enabled_hardware_types.add(CONF.discovery_default_driver) + instack_env['INSPECTION_NODE_NOT_FOUND_HOOK'] = 'enroll' + else: + instack_env['INSPECTION_NODE_NOT_FOUND_HOOK'] = '' + + # In most cases power and management interfaces are called the same, so we + # use one variable for them. + mgmt_interfaces = {'fake', 'ipmitool'} + # TODO(dtantsur): can we somehow avoid hardcoding hardware types here? + for hw_type in ('redfish', 'idrac', 'ilo', 'irmc'): + if hw_type in enabled_hardware_types: + mgmt_interfaces.add(hw_type) + for (hw_type, iface) in [('cisco-ucs-managed', 'ucsm'), + ('cisco-ucs-standalone', 'cimc')]: + if hw_type in enabled_hardware_types: + mgmt_interfaces.add(iface) + + # Two hardware types use non-default boot interfaces. + boot_interfaces = {'pxe'} + for hw_type in ('ilo', 'irmc'): + if hw_type in enabled_hardware_types: + boot_interfaces.add('%s-pxe' % hw_type) + + raid_interfaces = {'no-raid'} + if 'idrac' in enabled_hardware_types: + raid_interfaces.add('idrac') + + vendor_interfaces = {'no-vendor'} + for (hw_type, iface) in [('ipmi', 'ipmitool'), + ('idrac', 'idrac')]: + if hw_type in enabled_hardware_types: + vendor_interfaces.add(iface) + + instack_env['ENABLED_DRIVERS'] = _make_list(enabled_drivers) + instack_env['ENABLED_HARDWARE_TYPES'] = _make_list(enabled_hardware_types) + + instack_env['ENABLED_BOOT_INTERFACES'] = _make_list(boot_interfaces) + instack_env['ENABLED_MANAGEMENT_INTERFACES'] = _make_list(mgmt_interfaces) + instack_env['ENABLED_RAID_INTERFACES'] = _make_list(raid_interfaces) + instack_env['ENABLED_VENDOR_INTERFACES'] = _make_list(vendor_interfaces) + + # The snmp hardware type uses fake management and snmp power + if 'snmp' in enabled_hardware_types: + mgmt_interfaces.add('snmp') + instack_env['ENABLED_POWER_INTERFACES'] = _make_list(mgmt_interfaces) + + def _generate_environment(instack_root): """Generate an environment dict for instack @@ -1172,31 +1247,7 @@ def _generate_environment(instack_root): instack_env['INSPECTION_KERNEL_ARGS'] = ' '.join(inspection_kernel_args) - # Ensure correct rendering of the list and uniqueness of the items - enabled_drivers = set(CONF.enabled_drivers) - enabled_hardware_types = set(CONF.enabled_hardware_types) - if CONF.enable_node_discovery: - if (CONF.discovery_default_driver not in (enabled_drivers | - enabled_hardware_types)): - enabled_drivers.add(CONF.discovery_default_driver) - instack_env['INSPECTION_NODE_NOT_FOUND_HOOK'] = 'enroll' - else: - instack_env['INSPECTION_NODE_NOT_FOUND_HOOK'] = '' - - # In most cases power and management interfaces are called the same, so we - # use one variable for them. - enabled_interfaces = set() - if 'ipmi' in enabled_hardware_types: - enabled_interfaces.add('ipmitool') - if 'redfish' in enabled_hardware_types: - enabled_interfaces.add('redfish') - - instack_env['ENABLED_DRIVERS'] = _make_list(enabled_drivers) - instack_env['ENABLED_HARDWARE_TYPES'] = _make_list(enabled_hardware_types) - - enabled_interfaces = _make_list(enabled_interfaces) - instack_env['ENABLED_POWER_INTERFACES'] = enabled_interfaces - instack_env['ENABLED_MANAGEMENT_INTERFACES'] = enabled_interfaces + _process_drivers_and_hardware_types(instack_env) instack_env['SYSCTL_SETTINGS'] = _generate_sysctl_settings() diff --git a/releasenotes/notes/switch-to-hw-types-b3abf03ef9b7973b.yaml b/releasenotes/notes/switch-to-hw-types-b3abf03ef9b7973b.yaml new file mode 100644 index 000000000..66626cd90 --- /dev/null +++ b/releasenotes/notes/switch-to-hw-types-b3abf03ef9b7973b.yaml @@ -0,0 +1,23 @@ +--- +features: + - | + The hardware types ``ilo`` and ``idrac`` are now enabled by default. + - | + Added support for the following hardware types: ``cisco-ucs-managed``, + ``cisco-ucs-standalone``, ``idrac``, ``ilo``, ``irmc``, ``snmp``. +deprecations: + - | + The ``enabled_drivers`` option is deprecated, please use + ``enabled_hardware_types``. Make sure to switch your nodes to hardware + types before disabling drivers. +upgrade: + - | + Classic drivers are going to be deprecated soon, it is recommended to + switch all overcloud nodes to matching hardware types. See the `hardware + types migration documentation + `_ + for the detailed procedure. + - | + As part of migration to hardware types, the default value of the + ``discovery_default_driver`` option was changed from ``pxe_ipmitool`` + to ``ipmi``. diff --git a/undercloud.conf.sample b/undercloud.conf.sample index ff0e3ff22..1cd2c881d 100644 --- a/undercloud.conf.sample +++ b/undercloud.conf.sample @@ -141,10 +141,11 @@ # for newly enrolled nodes. (boolean value) #enable_node_discovery = false -# The default driver to use for newly discovered nodes (requires -# enable_node_discovery set to True). This driver is automatically -# added to enabled_drivers. (string value) -#discovery_default_driver = pxe_ipmitool +# The default driver or hardware type to use for newly discovered +# nodes (requires enable_node_discovery set to True). It is +# automatically added to enabled_drivers or enabled_hardware_types +# accordingly. (string value) +#discovery_default_driver = ipmi # Whether to enable the debug log level for Undercloud OpenStack # services. (boolean value) @@ -199,12 +200,16 @@ # deployments and after the introspection. (boolean value) #clean_nodes = false -# List of enabled bare metal drivers. (list value) +# DEPRECATED: List of enabled bare metal drivers. (list value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Please switch to hardware types and the +# enabled_hardware_types option. #enabled_drivers = pxe_ipmitool,pxe_drac,pxe_ilo # List of enabled bare metal hardware types (next generation drivers). # (list value) -#enabled_hardware_types = ipmi,redfish +#enabled_hardware_types = ipmi,redfish,ilo,idrac # An optional docker 'registry-mirror' that will beconfigured in # /etc/docker/daemon.json. (string value)