summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-08-07 18:11:49 +0000
committerGerrit Code Review <review@openstack.org>2018-08-07 18:11:49 +0000
commit257fcf9f9819aa4dee6359630194066f16bee6fb (patch)
tree81874e785de100c50fc55ecbd84246c98b624493
parent1364df4361e0746aef89ea1224f45d61f8cb9990 (diff)
parentd42bd9a77ba46240853769f08a5f25bcfdddda79 (diff)
downloadironic-257fcf9f9819aa4dee6359630194066f16bee6fb.tar.gz
Merge "Add "noop" management and use it in the "ipmi" hardware type"
-rw-r--r--devstack/lib/ironic2
-rw-r--r--doc/source/admin/drivers/ipmitool.rst43
-rw-r--r--ironic/drivers/ipmi.py3
-rw-r--r--ironic/drivers/modules/noop_mgmt.py58
-rw-r--r--ironic/tests/unit/drivers/modules/test_noop_mgmt.py37
-rw-r--r--ironic/tests/unit/drivers/test_ipmi.py12
-rw-r--r--releasenotes/notes/ipmi-noop-mgmt-8fad89dc2b4665b8.yaml7
-rw-r--r--setup.cfg1
8 files changed, 160 insertions, 3 deletions
diff --git a/devstack/lib/ironic b/devstack/lib/ironic
index 41a2658bc..877e17174 100644
--- a/devstack/lib/ironic
+++ b/devstack/lib/ironic
@@ -167,7 +167,7 @@ IRONIC_ENABLED_BOOT_INTERFACES=${IRONIC_ENABLED_BOOT_INTERFACES:-"fake,pxe"}
IRONIC_ENABLED_CONSOLE_INTERFACES=${IRONIC_ENABLED_CONSOLE_INTERFACES:-"fake,no-console"}
IRONIC_ENABLED_DEPLOY_INTERFACES=${IRONIC_ENABLED_DEPLOY_INTERFACES:-"fake,iscsi,direct"}
IRONIC_ENABLED_INSPECT_INTERFACES=${IRONIC_ENABLED_INSPECT_INTERFACES:-"fake,no-inspect"}
-IRONIC_ENABLED_MANAGEMENT_INTERFACES=${IRONIC_ENABLED_MANAGEMENT_INTERFACES:-"fake,ipmitool"}
+IRONIC_ENABLED_MANAGEMENT_INTERFACES=${IRONIC_ENABLED_MANAGEMENT_INTERFACES:-"fake,ipmitool,noop"}
IRONIC_ENABLED_NETWORK_INTERFACES=${IRONIC_ENABLED_NETWORK_INTERFACES:-"flat,noop"}
IRONIC_ENABLED_POWER_INTERFACES=${IRONIC_ENABLED_POWER_INTERFACES:-"fake,ipmitool"}
IRONIC_ENABLED_RAID_INTERFACES=${IRONIC_ENABLED_RAID_INTERFACES:-"fake,agent,no-raid"}
diff --git a/doc/source/admin/drivers/ipmitool.rst b/doc/source/admin/drivers/ipmitool.rst
index 160f742f9..b6d64f17d 100644
--- a/doc/source/admin/drivers/ipmitool.rst
+++ b/doc/source/admin/drivers/ipmitool.rst
@@ -30,6 +30,21 @@ Please see :doc:`/install/configure-ipmi` for the required dependencies.
[DEFAULT]
enabled_hardware_types = ipmi
+ enabled_management_interfaces = ipmitool,noop
+ enabled_power_interfaces = ipmitool
+
+ Optionally, enable the :doc:`vendor passthru interface
+ </contributor/vendor-passthru>` and either or both :doc:`console interfaces
+ </admin/console>`:
+
+ .. code-block:: ini
+
+ [DEFAULT]
+ enabled_hardware_types = ipmi
+ enabled_console_interfaces = ipmitool-socat,ipmitool-shellinabox,no-console
+ enabled_management_interfaces = ipmitool,noop
+ enabled_power_interfaces = ipmitool
+ enabled_vendor_interfaces = ipmitool,no-vendor
#. Restart the Ironic conductor service.
@@ -153,6 +168,34 @@ protocol version::
Version *1.5* of the IPMI protocol does not support encryption.
Therefore, it is highly recommended that version 2.0 is used.
+Static boot order configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some hardware is known to misbehave when changing the boot device through the
+IPMI protocol. To work around it you can use the ``noop`` management interface
+implementation with the ``ipmi`` hardware type. In this case the Bare Metal
+service will not change the boot device for you, leaving the pre-configured
+boot order.
+
+For example, in case of the :ref:`pxe-boot`:
+
+#. Via any available means configure the boot order on the node as follows:
+
+ #. Boot from PXE/iPXE on the provisioning NIC.
+
+ .. warning::
+ If it is not possible to limit network boot to only provisioning NIC,
+ make sure that no other DHCP/PXE servers are accessible by the node.
+
+ #. Boot from hard drive.
+
+#. Make sure the ``noop`` management interface is enabled, see example in
+ `Enabling the IPMI hardware type`_.
+
+#. Change the node to use the ``noop`` management interface::
+
+ openstack baremetal node set <NODE> --management-interface noop
+
.. TODO(lucasagomes): Write about privilege level
.. TODO(lucasagomes): Write about force boot device
diff --git a/ironic/drivers/ipmi.py b/ironic/drivers/ipmi.py
index 96a091b41..3810c894f 100644
--- a/ironic/drivers/ipmi.py
+++ b/ironic/drivers/ipmi.py
@@ -17,6 +17,7 @@ Hardware type for IPMI (using ipmitool).
from ironic.drivers import generic
from ironic.drivers.modules import ipmitool
from ironic.drivers.modules import noop
+from ironic.drivers.modules import noop_mgmt
class IPMIHardware(generic.GenericHardware):
@@ -35,7 +36,7 @@ class IPMIHardware(generic.GenericHardware):
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
- return [ipmitool.IPMIManagement]
+ return [ipmitool.IPMIManagement, noop_mgmt.NoopManagement]
@property
def supported_power_interfaces(self):
diff --git a/ironic/drivers/modules/noop_mgmt.py b/ironic/drivers/modules/noop_mgmt.py
new file mode 100644
index 000000000..0efc089e9
--- /dev/null
+++ b/ironic/drivers/modules/noop_mgmt.py
@@ -0,0 +1,58 @@
+# 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.
+
+"""No-op management interface implementation."""
+
+from oslo_log import log
+
+from ironic.common import boot_devices
+from ironic.common import exception
+from ironic.common.i18n import _
+from ironic.drivers import base
+
+
+LOG = log.getLogger(__name__)
+
+
+class NoopManagement(base.ManagementInterface):
+ """No-op management interface implementation.
+
+ Using this implementation requires the boot order to be preconfigured
+ to first try PXE booting, then fall back to hard drives.
+ """
+
+ def get_properties(self):
+ return {}
+
+ def validate(self, task):
+ pass
+
+ def get_supported_boot_devices(self, task):
+ return [boot_devices.PXE, boot_devices.DISK]
+
+ def set_boot_device(self, task, device, persistent=False):
+ supported = self.get_supported_boot_devices(task)
+ if device not in supported:
+ raise exception.InvalidParameterValue(
+ _("Invalid boot device %(dev)s specified, supported are "
+ "%(supported)s.") % {'dev': device,
+ 'supported': ', '.join(supported)})
+ LOG.debug('Setting boot device to %(target)s requested for node '
+ '%(node)s with noop management. Assuming the correct '
+ 'boot order is already configured',
+ {'target': device, 'node': task.node.uuid})
+
+ def get_boot_device(self, task):
+ return {'boot_device': boot_devices.PXE, 'persistent': True}
+
+ def get_sensors_data(self, task):
+ raise NotImplementedError()
diff --git a/ironic/tests/unit/drivers/modules/test_noop_mgmt.py b/ironic/tests/unit/drivers/modules/test_noop_mgmt.py
new file mode 100644
index 000000000..c34b05fe3
--- /dev/null
+++ b/ironic/tests/unit/drivers/modules/test_noop_mgmt.py
@@ -0,0 +1,37 @@
+# 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 mock
+
+from ironic.common import boot_devices
+from ironic.common import exception
+from ironic.drivers.modules import noop_mgmt
+from ironic.tests import base
+
+
+class TestNoopManagement(base.TestCase):
+ iface = noop_mgmt.NoopManagement()
+
+ def test_dummy_methods(self):
+ self.assertEqual({}, self.iface.get_properties())
+ self.assertIsNone(self.iface.validate("task"))
+ self.assertEqual([boot_devices.PXE, boot_devices.DISK],
+ self.iface.get_supported_boot_devices("task"))
+ self.assertEqual({'boot_device': boot_devices.PXE,
+ 'persistent': True},
+ self.iface.get_boot_device("task"))
+
+ def test_set_boot_device(self):
+ self.iface.set_boot_device(mock.Mock(), boot_devices.DISK)
+ self.assertRaises(exception.InvalidParameterValue,
+ self.iface.set_boot_device, mock.Mock(),
+ boot_devices.CDROM)
diff --git a/ironic/tests/unit/drivers/test_ipmi.py b/ironic/tests/unit/drivers/test_ipmi.py
index d302d60ec..c3e822c52 100644
--- a/ironic/tests/unit/drivers/test_ipmi.py
+++ b/ironic/tests/unit/drivers/test_ipmi.py
@@ -15,6 +15,7 @@ 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 noop_mgmt
from ironic.drivers.modules import pxe
from ironic.drivers.modules.storage import cinder
from ironic.drivers.modules.storage import noop as noop_storage
@@ -28,7 +29,7 @@ class IPMIHardwareTestCase(db_base.DbTestCase):
super(IPMIHardwareTestCase, self).setUp()
self.config(enabled_hardware_types=['ipmi'],
enabled_power_interfaces=['ipmitool'],
- enabled_management_interfaces=['ipmitool'],
+ enabled_management_interfaces=['ipmitool', 'noop'],
enabled_raid_interfaces=['no-raid', 'agent'],
enabled_console_interfaces=['no-console'],
enabled_vendor_interfaces=['ipmitool', 'no-vendor'])
@@ -99,3 +100,12 @@ class IPMIHardwareTestCase(db_base.DbTestCase):
rescue_interface='agent')
with task_manager.acquire(self.context, node.id) as task:
self._validate_interfaces(task, rescue=agent.AgentRescue)
+
+ def test_override_with_noop_mgmt(self):
+ self.config(enabled_management_interfaces=['ipmitool', 'noop'])
+ node = obj_utils.create_test_node(
+ self.context, driver='ipmi',
+ management_interface='noop')
+ with task_manager.acquire(self.context, node.id) as task:
+ self._validate_interfaces(task,
+ management=noop_mgmt.NoopManagement)
diff --git a/releasenotes/notes/ipmi-noop-mgmt-8fad89dc2b4665b8.yaml b/releasenotes/notes/ipmi-noop-mgmt-8fad89dc2b4665b8.yaml
new file mode 100644
index 000000000..a2215b9e5
--- /dev/null
+++ b/releasenotes/notes/ipmi-noop-mgmt-8fad89dc2b4665b8.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ Adds support for the new ``noop`` interface to the ``ipmi`` hardware type.
+ This interface targets hardware that does not correctly change boot mode
+ via the IPMI protocol. Using it requires pre-configuring the boot order
+ on a node to try PXE, then fall back to local booting.
diff --git a/setup.cfg b/setup.cfg
index 0a1df11ea..eb4cfb2e8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -98,6 +98,7 @@ ironic.hardware.interfaces.management =
ilo = ironic.drivers.modules.ilo.management:IloManagement
ipmitool = ironic.drivers.modules.ipmitool:IPMIManagement
irmc = ironic.drivers.modules.irmc.management:IRMCManagement
+ noop = ironic.drivers.modules.noop_mgmt:NoopManagement
oneview = ironic.drivers.modules.oneview.management:OneViewManagement
redfish = ironic.drivers.modules.redfish.management:RedfishManagement
ucsm = ironic.drivers.modules.ucs.management:UcsManagement