From 797544316ebd07d2ce674ed9aa4f8f98fe7d894d Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Thu, 19 Jan 2017 16:35:49 +0100 Subject: [PATCH] Add hardware type for IPMI using ipmitool Created a new Python module ironic.drivers.ipmi to contain all supported IPMI-related drivers (both new and old). Backward compatible aliases are left at old locations. Change-Id: I526b8505d08b25b668af76d3fcd8f2feab31e420 Partial-Bug: #1524745 --- devstack/lib/ironic | 4 +- etc/ironic/ironic.conf.sample | 13 +- ironic/conf/default.py | 13 +- ironic/drivers/agent.py | 45 +----- ironic/drivers/ipmi.py | 131 ++++++++++++++++++ ironic/drivers/pxe.py | 43 +----- ironic/tests/unit/drivers/test_agent.py | 51 ------- ironic/tests/unit/drivers/test_ipmi.py | 112 +++++++++++++++ ironic/tests/unit/drivers/test_pxe.py | 24 ---- .../ipmi-hardware-type-c536fbeeae610147.yaml | 8 ++ setup.cfg | 13 +- 11 files changed, 282 insertions(+), 175 deletions(-) create mode 100644 ironic/drivers/ipmi.py delete mode 100644 ironic/tests/unit/drivers/test_agent.py create mode 100644 ironic/tests/unit/drivers/test_ipmi.py create mode 100644 releasenotes/notes/ipmi-hardware-type-c536fbeeae610147.yaml diff --git a/devstack/lib/ironic b/devstack/lib/ironic index 4eb61d7d34..e6f9fda8f8 100644 --- a/devstack/lib/ironic +++ b/devstack/lib/ironic @@ -138,9 +138,9 @@ if [[ -n "$BUILD_TIMEOUT" ]]; then fi # driver / hardware type options -# TODO(jroll) add enabled/default interfaces here IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ipmitool,agent_ipmitool} -IRONIC_ENABLED_HARDWARE_TYPES=${IRONIC_ENABLED_HARDWARE_TYPES:-manual-management} +# TODO(jroll) add enabled/default interfaces here +IRONIC_ENABLED_HARDWARE_TYPES=${IRONIC_ENABLED_HARDWARE_TYPES:-ipmi} # If IRONIC_VM_ENGING is explictly set to "auto" or "kvm", # devstack will attempt to use hardware virtualization diff --git a/etc/ironic/ironic.conf.sample b/etc/ironic/ironic.conf.sample index 7eb874da85..dc4a7d7bf2 100644 --- a/etc/ironic/ironic.conf.sample +++ b/etc/ironic/ironic.conf.sample @@ -33,13 +33,12 @@ # Specify the list of hardware types to load during service # initialization. Missing hardware types, or hardware types # which fail to initialize, will prevent the conductor service -# from starting. No hardware types are enabled by default now, -# but in the future this option will default to a recommended -# set of production-oriented hardware types. A complete list -# of hardware types present on your system may be found by +# from starting. This option defaults to a recommended set of +# production-oriented hardware types. A complete list of +# hardware types present on your system may be found by # enumerating the "ironic.hardware.types" entrypoint. (list # value) -#enabled_hardware_types = +#enabled_hardware_types = ipmi # Specify the list of boot interfaces to load during service # initialization. Missing boot interfaces, or boot interfaces @@ -131,7 +130,7 @@ # setting this value, please make sure that every enabled # hardware type will have the same set of enabled management # interfaces on every ironic-conductor service. (list value) -#enabled_management_interfaces = +#enabled_management_interfaces = ipmitool # Default management interface to be used for nodes that do # not have management_interface field set. A complete list of @@ -171,7 +170,7 @@ # this value, please make sure that every enabled hardware # type will have the same set of enabled power interfaces on # every ironic-conductor service. (list value) -#enabled_power_interfaces = +#enabled_power_interfaces = ipmitool # Default power interface to be used for nodes that do not # have power_interface field set. A complete list of power diff --git a/ironic/conf/default.py b/ironic/conf/default.py index 65225f1dc9..fcd6ce1477 100644 --- a/ironic/conf/default.py +++ b/ironic/conf/default.py @@ -79,14 +79,13 @@ driver_opts = [ 'entrypoint. An example may be found in the ' 'developer documentation online.')), cfg.ListOpt('enabled_hardware_types', - default=[], + default=['ipmi'], help=_('Specify the list of hardware types to load during ' 'service initialization. Missing hardware types, or ' 'hardware types which fail to initialize, will prevent ' - 'the conductor service from starting. No hardware ' - 'types are enabled by default now, but in the future ' - 'this option will default to a recommended set of ' - 'production-oriented hardware types. ' + 'the conductor service from starting. This option ' + 'defaults to a recommended set of production-oriented ' + 'hardware types. ' 'A complete list of hardware types present on your ' 'system may be found by enumerating the ' '"ironic.hardware.types" entrypoint.')), @@ -111,7 +110,7 @@ driver_opts = [ cfg.StrOpt('default_inspect_interface', help=_DEFAULT_IFACE_HELP.format('inspect')), cfg.ListOpt('enabled_management_interfaces', - default=[], + default=['ipmitool'], help=_ENABLED_IFACE_HELP.format('management')), cfg.StrOpt('default_management_interface', help=_DEFAULT_IFACE_HELP.format('management')), @@ -121,7 +120,7 @@ driver_opts = [ cfg.StrOpt('default_network_interface', help=_DEFAULT_IFACE_HELP.format('network')), cfg.ListOpt('enabled_power_interfaces', - default=[], + default=['ipmitool'], help=_ENABLED_IFACE_HELP.format('power')), cfg.StrOpt('default_power_interface', help=_DEFAULT_IFACE_HELP.format('power')), diff --git a/ironic/drivers/agent.py b/ironic/drivers/agent.py index f1f9402236..44065a9710 100644 --- a/ironic/drivers/agent.py +++ b/ironic/drivers/agent.py @@ -17,12 +17,12 @@ from oslo_utils import importutils from ironic.common import exception from ironic.common.i18n import _ from ironic.drivers import base +from ironic.drivers import ipmi from ironic.drivers.modules import agent from ironic.drivers.modules.cimc import management as cimc_mgmt from ironic.drivers.modules.cimc import power as cimc_power from ironic.drivers.modules import inspector from ironic.drivers.modules import ipminative -from ironic.drivers.modules import ipmitool from ironic.drivers.modules import pxe from ironic.drivers.modules import ssh from ironic.drivers.modules.ucs import management as ucs_mgmt @@ -30,46 +30,9 @@ from ironic.drivers.modules.ucs import power as ucs_power from ironic.drivers.modules import virtualbox -class AgentAndIPMIToolDriver(base.BaseDriver): - """Agent + IPMITool driver. - - This driver implements the `core` functionality, combining - :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and - reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for - image deployment). - Implementations are in those respective classes; this class is merely the - glue between them. - """ - - def __init__(self): - self.power = ipmitool.IPMIPower() - self.boot = pxe.PXEBoot() - self.deploy = agent.AgentDeploy() - self.management = ipmitool.IPMIManagement() - self.console = ipmitool.IPMIShellinaboxConsole() - self.vendor = ipmitool.VendorPassthru() - self.raid = agent.AgentRAID() - self.inspect = inspector.Inspector.create_if_enabled( - 'AgentAndIPMIToolDriver') - - -class AgentAndIPMIToolAndSocatDriver(AgentAndIPMIToolDriver): - """Agent + IPMITool + socat driver. - - This driver implements the `core` functionality, combining - :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and - reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for - image deployment) and with - :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`. - This driver uses the socat console interface instead of the shellinabox - one. - Implementations are in those respective classes; this class is merely the - glue between them. - """ - - def __init__(self): - AgentAndIPMIToolDriver.__init__(self) - self.console = ipmitool.IPMISocatConsole() +# For backward compatibility +AgentAndIPMIToolDriver = ipmi.AgentAndIPMIToolDriver +AgentAndIPMIToolAndSocatDriver = ipmi.AgentAndIPMIToolAndSocatDriver class AgentAndIPMINativeDriver(base.BaseDriver): diff --git a/ironic/drivers/ipmi.py b/ironic/drivers/ipmi.py new file mode 100644 index 0000000000..6e95462f7e --- /dev/null +++ b/ironic/drivers/ipmi.py @@ -0,0 +1,131 @@ +# 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. + +""" +Hardware types and classic drivers for IPMI (using ipmitool). +""" + +from ironic.drivers import base +from ironic.drivers import generic +from ironic.drivers.modules import agent +from ironic.drivers.modules import inspector +from ironic.drivers.modules import ipmitool +from ironic.drivers.modules import iscsi_deploy +from ironic.drivers.modules import noop +from ironic.drivers.modules import pxe + + +class IPMIHardware(generic.GenericHardware): + """IPMI hardware type. + + Uses ``ipmitool`` to implement power and management. + Provides serial console implementations via ``shellinabox`` or ``socat``. + """ + + @property + def supported_console_interfaces(self): + """List of supported console interfaces.""" + return [ipmitool.IPMISocatConsole, ipmitool.IPMIShellinaboxConsole, + noop.NoConsole] + + @property + def supported_management_interfaces(self): + """List of supported management interfaces.""" + return [ipmitool.IPMIManagement] + + @property + def supported_power_interfaces(self): + """List of supported power interfaces.""" + return [ipmitool.IPMIPower] + + +class PXEAndIPMIToolDriver(base.BaseDriver): + """PXE + IPMITool driver. + + This driver implements the `core` functionality, combining + :class:`ironic.drivers.modules.ipmitool.IPMIPower` for power on/off + and reboot with + :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` for + image deployment. Implementations are in those respective + classes; this class is merely the glue between them. + """ + def __init__(self): + self.power = ipmitool.IPMIPower() + self.console = ipmitool.IPMIShellinaboxConsole() + self.boot = pxe.PXEBoot() + self.deploy = iscsi_deploy.ISCSIDeploy() + self.management = ipmitool.IPMIManagement() + self.inspect = inspector.Inspector.create_if_enabled( + 'PXEAndIPMIToolDriver') + self.vendor = ipmitool.VendorPassthru() + self.raid = agent.AgentRAID() + + +class PXEAndIPMIToolAndSocatDriver(PXEAndIPMIToolDriver): + """PXE + IPMITool + socat driver. + + This driver implements the `core` functionality, combining + :class:`ironic.drivers.modules.ipmitool.IPMIPower` for power on/off + and reboot with + :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` (for + image deployment) and with + :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`. + This driver uses the socat console interface instead of the shellinabox + one. + Implementations are in those respective + classes; this class is merely the glue between them. + """ + def __init__(self): + PXEAndIPMIToolDriver.__init__(self) + self.console = ipmitool.IPMISocatConsole() + + +class AgentAndIPMIToolDriver(base.BaseDriver): + """Agent + IPMITool driver. + + This driver implements the `core` functionality, combining + :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and + reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for + image deployment). + Implementations are in those respective classes; this class is merely the + glue between them. + """ + + def __init__(self): + self.power = ipmitool.IPMIPower() + self.boot = pxe.PXEBoot() + self.deploy = agent.AgentDeploy() + self.management = ipmitool.IPMIManagement() + self.console = ipmitool.IPMIShellinaboxConsole() + self.vendor = ipmitool.VendorPassthru() + self.raid = agent.AgentRAID() + self.inspect = inspector.Inspector.create_if_enabled( + 'AgentAndIPMIToolDriver') + + +class AgentAndIPMIToolAndSocatDriver(AgentAndIPMIToolDriver): + """Agent + IPMITool + socat driver. + + This driver implements the `core` functionality, combining + :class:`ironic.drivers.modules.ipmitool.IPMIPower` (for power on/off and + reboot) with :class:`ironic.drivers.modules.agent.AgentDeploy` (for + image deployment) and with + :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`. + This driver uses the socat console interface instead of the shellinabox + one. + Implementations are in those respective classes; this class is merely the + glue between them. + """ + + def __init__(self): + AgentAndIPMIToolDriver.__init__(self) + self.console = ipmitool.IPMISocatConsole() diff --git a/ironic/drivers/pxe.py b/ironic/drivers/pxe.py index 440c9bd5be..8f890f9740 100644 --- a/ironic/drivers/pxe.py +++ b/ironic/drivers/pxe.py @@ -22,6 +22,7 @@ from oslo_utils import importutils from ironic.common import exception from ironic.common.i18n import _ from ironic.drivers import base +from ironic.drivers import ipmi from ironic.drivers.modules import agent from ironic.drivers.modules.cimc import management as cimc_mgmt from ironic.drivers.modules.cimc import power as cimc_power @@ -49,45 +50,9 @@ from ironic.drivers.modules.ucs import power as ucs_power from ironic.drivers.modules import virtualbox -class PXEAndIPMIToolDriver(base.BaseDriver): - """PXE + IPMITool driver. - - This driver implements the `core` functionality, combining - :class:`ironic.drivers.modules.ipmi.IPMI` for power on/off - and reboot with - :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` for - image deployment. Implementations are in those respective - classes; this class is merely the glue between them. - """ - def __init__(self): - self.power = ipmitool.IPMIPower() - self.console = ipmitool.IPMIShellinaboxConsole() - self.boot = pxe.PXEBoot() - self.deploy = iscsi_deploy.ISCSIDeploy() - self.management = ipmitool.IPMIManagement() - self.inspect = inspector.Inspector.create_if_enabled( - 'PXEAndIPMIToolDriver') - self.vendor = ipmitool.VendorPassthru() - self.raid = agent.AgentRAID() - - -class PXEAndIPMIToolAndSocatDriver(PXEAndIPMIToolDriver): - """PXE + IPMITool + socat driver. - - This driver implements the `core` functionality, combining - :class:`ironic.drivers.modules.ipmi.IPMI` for power on/off - and reboot with - :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` (for - image deployment) and with - :class:`ironic.drivers.modules.ipmitool.IPMISocatConsole`. - This driver uses the socat console interface instead of the shellinabox - one. - Implementations are in those respective - classes; this class is merely the glue between them. - """ - def __init__(self): - PXEAndIPMIToolDriver.__init__(self) - self.console = ipmitool.IPMISocatConsole() +# For backward compatibility +PXEAndIPMIToolDriver = ipmi.PXEAndIPMIToolDriver +PXEAndIPMIToolAndSocatDriver = ipmi.PXEAndIPMIToolAndSocatDriver class PXEAndSSHDriver(base.BaseDriver): diff --git a/ironic/tests/unit/drivers/test_agent.py b/ironic/tests/unit/drivers/test_agent.py deleted file mode 100644 index 13b7579835..0000000000 --- a/ironic/tests/unit/drivers/test_agent.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2015 Rackspace, Inc. -# -# 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. - -""" -Test class for Agent Deploy Driver -""" - -from ironic.drivers import agent -from ironic.drivers.modules import agent as agent_module -from ironic.drivers.modules import ipmitool -from ironic.drivers.modules import pxe -from ironic.tests import base - - -class AgentAndIPMIToolDriverTestCase(base.TestCase): - - def test___init__(self): - driver = agent.AgentAndIPMIToolDriver() - - self.assertIsInstance(driver.power, ipmitool.IPMIPower) - self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole) - self.assertIsInstance(driver.boot, pxe.PXEBoot) - self.assertIsInstance(driver.deploy, agent_module.AgentDeploy) - self.assertIsInstance(driver.management, ipmitool.IPMIManagement) - self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) - self.assertIsInstance(driver.raid, agent_module.AgentRAID) - - -class AgentAndIPMIToolAndSocatDriverTestCase(base.TestCase): - - def test___init__(self): - driver = agent.AgentAndIPMIToolAndSocatDriver() - - self.assertIsInstance(driver.power, ipmitool.IPMIPower) - self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole) - self.assertIsInstance(driver.boot, pxe.PXEBoot) - self.assertIsInstance(driver.deploy, agent_module.AgentDeploy) - self.assertIsInstance(driver.management, ipmitool.IPMIManagement) - self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) - self.assertIsInstance(driver.raid, agent_module.AgentRAID) diff --git a/ironic/tests/unit/drivers/test_ipmi.py b/ironic/tests/unit/drivers/test_ipmi.py new file mode 100644 index 0000000000..c12e6dda6c --- /dev/null +++ b/ironic/tests/unit/drivers/test_ipmi.py @@ -0,0 +1,112 @@ +# 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 testtools + +from ironic.conductor import task_manager +from ironic.drivers import ipmi +from ironic.drivers.modules import agent +from ironic.drivers.modules import ipmitool +from ironic.drivers.modules import iscsi_deploy +from ironic.drivers.modules import noop +from ironic.drivers.modules import pxe +from ironic.tests.unit.db import base as db_base +from ironic.tests.unit.objects import utils as obj_utils + + +class IPMIHardwareTestCase(db_base.DbTestCase): + + def setUp(self): + super(IPMIHardwareTestCase, self).setUp() + self.config(enabled_hardware_types=['ipmi'], + enabled_power_interfaces=['ipmitool'], + enabled_management_interfaces=['ipmitool'], + enabled_raid_interfaces=['no-raid', 'agent'], + enabled_console_interfaces=['no-console']) + + def test_default_interfaces(self): + node = obj_utils.create_test_node(self.context, driver='ipmi') + with task_manager.acquire(self.context, node.id) as task: + self.assertIsInstance(task.driver.management, + ipmitool.IPMIManagement) + self.assertIsInstance(task.driver.power, ipmitool.IPMIPower) + self.assertIsInstance(task.driver.boot, pxe.PXEBoot) + self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.console, noop.NoConsole) + self.assertIsInstance(task.driver.raid, noop.NoRAID) + + def test_override_with_shellinabox(self): + self.config(enabled_console_interfaces=['ipmitool-shellinabox', + 'ipmitool-socat']) + node = obj_utils.create_test_node( + self.context, driver='ipmi', + deploy_interface='direct', + raid_interface='agent', + console_interface='ipmitool-shellinabox') + with task_manager.acquire(self.context, node.id) as task: + self.assertIsInstance(task.driver.management, + ipmitool.IPMIManagement) + self.assertIsInstance(task.driver.power, ipmitool.IPMIPower) + self.assertIsInstance(task.driver.boot, pxe.PXEBoot) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) + self.assertIsInstance(task.driver.console, + ipmitool.IPMIShellinaboxConsole) + self.assertIsInstance(task.driver.raid, agent.AgentRAID) + + +class IPMIClassicDriversTestCase(testtools.TestCase): + + def test_pxe_ipmitool_driver(self): + driver = ipmi.PXEAndIPMIToolDriver() + + self.assertIsInstance(driver.power, ipmitool.IPMIPower) + self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole) + self.assertIsInstance(driver.boot, pxe.PXEBoot) + self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(driver.management, ipmitool.IPMIManagement) + self.assertIsNone(driver.inspect) + self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) + self.assertIsInstance(driver.raid, agent.AgentRAID) + + def test_pxe_ipmitool_socat_driver(self): + driver = ipmi.PXEAndIPMIToolAndSocatDriver() + + self.assertIsInstance(driver.power, ipmitool.IPMIPower) + self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole) + self.assertIsInstance(driver.boot, pxe.PXEBoot) + self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(driver.management, ipmitool.IPMIManagement) + self.assertIsNone(driver.inspect) + self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) + self.assertIsInstance(driver.raid, agent.AgentRAID) + + def test_agent_ipmitool_driver(self): + driver = ipmi.AgentAndIPMIToolDriver() + + self.assertIsInstance(driver.power, ipmitool.IPMIPower) + self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole) + self.assertIsInstance(driver.boot, pxe.PXEBoot) + self.assertIsInstance(driver.deploy, agent.AgentDeploy) + self.assertIsInstance(driver.management, ipmitool.IPMIManagement) + self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) + self.assertIsInstance(driver.raid, agent.AgentRAID) + + def test_agent_ipmitool_socat_driver(self): + driver = ipmi.AgentAndIPMIToolAndSocatDriver() + + self.assertIsInstance(driver.power, ipmitool.IPMIPower) + self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole) + self.assertIsInstance(driver.boot, pxe.PXEBoot) + self.assertIsInstance(driver.deploy, agent.AgentDeploy) + self.assertIsInstance(driver.management, ipmitool.IPMIManagement) + self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) + self.assertIsInstance(driver.raid, agent.AgentRAID) diff --git a/ironic/tests/unit/drivers/test_pxe.py b/ironic/tests/unit/drivers/test_pxe.py index f3f6fcba5b..c6799c9610 100644 --- a/ironic/tests/unit/drivers/test_pxe.py +++ b/ironic/tests/unit/drivers/test_pxe.py @@ -47,30 +47,6 @@ from ironic.drivers import pxe class PXEDriversTestCase(testtools.TestCase): - def test_pxe_ipmitool_driver(self): - driver = pxe.PXEAndIPMIToolDriver() - - self.assertIsInstance(driver.power, ipmitool.IPMIPower) - self.assertIsInstance(driver.console, ipmitool.IPMIShellinaboxConsole) - self.assertIsInstance(driver.boot, pxe_module.PXEBoot) - self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy) - self.assertIsInstance(driver.management, ipmitool.IPMIManagement) - self.assertIsNone(driver.inspect) - self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) - self.assertIsInstance(driver.raid, agent.AgentRAID) - - def test_pxe_ipmitool_socat_driver(self): - driver = pxe.PXEAndIPMIToolAndSocatDriver() - - self.assertIsInstance(driver.power, ipmitool.IPMIPower) - self.assertIsInstance(driver.console, ipmitool.IPMISocatConsole) - self.assertIsInstance(driver.boot, pxe_module.PXEBoot) - self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy) - self.assertIsInstance(driver.management, ipmitool.IPMIManagement) - self.assertIsNone(driver.inspect) - self.assertIsInstance(driver.vendor, ipmitool.VendorPassthru) - self.assertIsInstance(driver.raid, agent.AgentRAID) - def test_pxe_ssh_driver(self): driver = pxe.PXEAndSSHDriver() diff --git a/releasenotes/notes/ipmi-hardware-type-c536fbeeae610147.yaml b/releasenotes/notes/ipmi-hardware-type-c536fbeeae610147.yaml new file mode 100644 index 0000000000..73457e7d98 --- /dev/null +++ b/releasenotes/notes/ipmi-hardware-type-c536fbeeae610147.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Introduces new hardware type ``ipmi`` for IPMI-compatible hardware. + This type is enabled by default. Uses ``ipmitool`` utility under the hood, + similar to existing classic drivers ``pxe_ipmitool`` and + ``agent_ipmitool``. Supports both types of serial console: via + ``shellinabox`` and via ``socat``, both are disabled by default. diff --git a/setup.cfg b/setup.cfg index 3b09425709..03b2802751 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,8 +43,8 @@ ironic.dhcp = ironic.drivers = agent_ilo = ironic.drivers.ilo:IloVirtualMediaAgentDriver - agent_ipmitool = ironic.drivers.agent:AgentAndIPMIToolDriver - agent_ipmitool_socat = ironic.drivers.agent:AgentAndIPMIToolAndSocatDriver + agent_ipmitool = ironic.drivers.ipmi:AgentAndIPMIToolDriver + agent_ipmitool_socat = ironic.drivers.ipmi:AgentAndIPMIToolAndSocatDriver agent_irmc = ironic.drivers.irmc:IRMCVirtualMediaAgentDriver agent_pxe_oneview = ironic.drivers.oneview:AgentPXEOneViewDriver agent_pyghmi = ironic.drivers.agent:AgentAndIPMINativeDriver @@ -73,8 +73,8 @@ ironic.drivers = iscsi_ilo = ironic.drivers.ilo:IloVirtualMediaIscsiDriver iscsi_irmc = ironic.drivers.irmc:IRMCVirtualMediaIscsiDriver iscsi_pxe_oneview = ironic.drivers.oneview:ISCSIPXEOneViewDriver - pxe_ipmitool = ironic.drivers.pxe:PXEAndIPMIToolDriver - pxe_ipmitool_socat = ironic.drivers.pxe:PXEAndIPMIToolAndSocatDriver + pxe_ipmitool = ironic.drivers.ipmi:PXEAndIPMIToolDriver + pxe_ipmitool_socat = ironic.drivers.ipmi:PXEAndIPMIToolAndSocatDriver pxe_ipminative = ironic.drivers.pxe:PXEAndIPMINativeDriver pxe_ssh = ironic.drivers.pxe:PXEAndSSHDriver pxe_vbox = ironic.drivers.pxe:PXEAndVirtualBoxDriver @@ -95,6 +95,8 @@ ironic.hardware.interfaces.boot = ironic.hardware.interfaces.console = fake = ironic.drivers.modules.fake:FakeConsole + ipmitool-shellinabox = ironic.drivers.modules.ipmitool:IPMIShellinaboxConsole + ipmitool-socat = ironic.drivers.modules.ipmitool:IPMISocatConsole no-console = ironic.drivers.modules.noop:NoConsole ironic.hardware.interfaces.deploy = @@ -109,6 +111,7 @@ ironic.hardware.interfaces.inspect = ironic.hardware.interfaces.management = fake = ironic.drivers.modules.fake:FakeManagement + ipmitool = ironic.drivers.modules.ipmitool:IPMIManagement ironic.hardware.interfaces.network = flat = ironic.drivers.modules.network.flat:FlatNetwork @@ -117,6 +120,7 @@ ironic.hardware.interfaces.network = ironic.hardware.interfaces.power = fake = ironic.drivers.modules.fake:FakePower + ipmitool = ironic.drivers.modules.ipmitool:IPMIPower ironic.hardware.interfaces.raid = agent = ironic.drivers.modules.agent:AgentRAID @@ -137,6 +141,7 @@ ironic.hardware.interfaces.vendor = ironic.hardware.types = fake-hardware = ironic.drivers.fake_hardware:FakeHardware manual-management = ironic.drivers.generic:ManualManagementHardware + ipmi = ironic.drivers.ipmi:IPMIHardware ironic.database.migration_backend = sqlalchemy = ironic.db.sqlalchemy.migration