summaryrefslogtreecommitdiff
path: root/ironic/drivers
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2021-01-26 12:25:26 +0000
committerGerrit Code Review <review@openstack.org>2021-01-26 12:25:26 +0000
commit2a7871d060ecaef8b0bba48a5481a3a1bb24669f (patch)
tree12182858d4d64f4b5404a5bbd17b1e87b633e271 /ironic/drivers
parent8612c06d4ad5f9a6d6c442c67a959348cec756e2 (diff)
parentb6f4587f0bdfc2f4b5736db1c9f89639ef2e09a7 (diff)
downloadironic-2a7871d060ecaef8b0bba48a5481a3a1bb24669f.tar.gz
Merge "Common framework for configuring secure boot"
Diffstat (limited to 'ironic/drivers')
-rw-r--r--ironic/drivers/base.py34
-rw-r--r--ironic/drivers/modules/boot_mode_utils.py52
-rw-r--r--ironic/drivers/modules/pxe_base.py3
3 files changed, 89 insertions, 0 deletions
diff --git a/ironic/drivers/base.py b/ironic/drivers/base.py
index baf5a5579..7d137f9c4 100644
--- a/ironic/drivers/base.py
+++ b/ironic/drivers/base.py
@@ -972,6 +972,40 @@ class ManagementInterface(BaseInterface):
raise exception.UnsupportedDriverExtension(
driver=task.node.driver, extension='get_boot_mode')
+ def get_secure_boot_state(self, task):
+ """Get the current secure boot state for the node.
+
+ NOTE: Not all drivers support this method. Older hardware
+ may not implement that.
+
+ :param task: A task from TaskManager.
+ :raises: MissingParameterValue if a required parameter is missing
+ :raises: DriverOperationError or its derivative in case
+ of driver runtime error.
+ :raises: UnsupportedDriverExtension if secure boot is
+ not supported by the driver or the hardware
+ :returns: Boolean
+ """
+ raise exception.UnsupportedDriverExtension(
+ driver=task.node.driver, extension='get_secure_boot_state')
+
+ def set_secure_boot_state(self, task, state):
+ """Set the current secure boot state for the node.
+
+ NOTE: Not all drivers support this method. Older hardware
+ may not implement that.
+
+ :param task: A task from TaskManager.
+ :param state: A new state as a boolean.
+ :raises: MissingParameterValue if a required parameter is missing
+ :raises: DriverOperationError or its derivative in case
+ of driver runtime error.
+ :raises: UnsupportedDriverExtension if secure boot is
+ not supported by the driver or the hardware
+ """
+ raise exception.UnsupportedDriverExtension(
+ driver=task.node.driver, extension='set_secure_boot_state')
+
@abc.abstractmethod
def get_sensors_data(self, task):
"""Get sensors data method.
diff --git a/ironic/drivers/modules/boot_mode_utils.py b/ironic/drivers/modules/boot_mode_utils.py
index eea09d1c0..6eebe50aa 100644
--- a/ironic/drivers/modules/boot_mode_utils.py
+++ b/ironic/drivers/modules/boot_mode_utils.py
@@ -14,11 +14,13 @@
# under the License.
from oslo_log import log as logging
+from oslo_utils import excutils
from ironic.common import boot_modes
from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import utils as common_utils
+from ironic.conductor import task_manager
from ironic.conductor import utils as manager_utils
from ironic.conf import CONF
from ironic.drivers import utils as driver_utils
@@ -296,3 +298,53 @@ def get_boot_mode(node):
'bios': boot_modes.LEGACY_BIOS,
'uefi': boot_modes.UEFI})
return CONF.deploy.default_boot_mode
+
+
+@task_manager.require_exclusive_lock
+def configure_secure_boot_if_needed(task):
+ """Configures secure boot if it has been requested for the node."""
+ if not is_secure_boot_requested(task.node):
+ return
+
+ try:
+ task.driver.management.set_secure_boot_state(task, True)
+ except exception.UnsupportedDriverExtension:
+ # TODO(dtantsur): make a failure in Xena
+ LOG.warning('Secure boot was requested for node %(node)s but its '
+ 'management interface %(driver)s does not support it. '
+ 'This warning will become an error in a future release.',
+ {'node': task.node.uuid,
+ 'driver': task.node.management_interface})
+ except Exception as exc:
+ with excutils.save_and_reraise_exception():
+ LOG.error('Failed to configure secure boot for node %(node)s: '
+ '%(error)s',
+ {'node': task.node.uuid, 'error': exc},
+ exc_info=not isinstance(exc, exception.IronicException))
+ else:
+ LOG.info('Secure boot has been enabled for node %s', task.node.uuid)
+
+
+@task_manager.require_exclusive_lock
+def deconfigure_secure_boot_if_needed(task):
+ """Deconfigures secure boot if it has been requested for the node."""
+ if not is_secure_boot_requested(task.node):
+ return
+
+ try:
+ task.driver.management.set_secure_boot_state(task, False)
+ except exception.UnsupportedDriverExtension:
+ # NOTE(dtantsur): don't make it a hard failure to allow tearing down
+ # misconfigured nodes.
+ LOG.debug('Secure boot was requested for node %(node)s but its '
+ 'management interface %(driver)s does not support it.',
+ {'node': task.node.uuid,
+ 'driver': task.node.management_interface})
+ except Exception as exc:
+ with excutils.save_and_reraise_exception():
+ LOG.error('Failed to deconfigure secure boot for node %(node)s: '
+ '%(error)s',
+ {'node': task.node.uuid, 'error': exc},
+ exc_info=not isinstance(exc, exception.IronicException))
+ else:
+ LOG.info('Secure boot has been disabled for node %s', task.node.uuid)
diff --git a/ironic/drivers/modules/pxe_base.py b/ironic/drivers/modules/pxe_base.py
index 5d9ac49ba..0944e7d4e 100644
--- a/ironic/drivers/modules/pxe_base.py
+++ b/ironic/drivers/modules/pxe_base.py
@@ -133,6 +133,8 @@ class PXEBaseMixin(object):
pxe_utils.clean_up_pxe_env(task, images_info,
ipxe_enabled=self.ipxe_enabled)
+ boot_mode_utils.deconfigure_secure_boot_if_needed(task)
+
@METRICS.timer('PXEBaseMixin.prepare_ramdisk')
def prepare_ramdisk(self, task, ramdisk_params):
"""Prepares the boot of Ironic ramdisk using PXE.
@@ -240,6 +242,7 @@ class PXEBaseMixin(object):
:returns: None
"""
boot_mode_utils.sync_boot_mode(task)
+ boot_mode_utils.configure_secure_boot_if_needed(task)
node = task.node
boot_option = deploy_utils.get_boot_option(node)