From 1e6fa0bfb0c77a1b29e4de6c989a227a11a6b156 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Thu, 22 Mar 2018 16:00:50 +0100 Subject: [PATCH] Add support for rescue mode in enrollment and node configuration workflows Change-Id: Ifed82bb0bc6bdfbfe5c89454187f00f347e5be45 Implements: blueprint ironic-rescue --- .../notes/ironic-rescue-ce08f432ccdcece4.yaml | 8 ++++++++ tripleo_common/actions/baremetal.py | 10 ++++++++++ .../tests/actions/test_baremetal.py | 20 +++++++++++++++++-- tripleo_common/tests/utils/test_nodes.py | 8 +++++++- tripleo_common/utils/nodes.py | 20 ++++++++++++++----- 5 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/ironic-rescue-ce08f432ccdcece4.yaml diff --git a/releasenotes/notes/ironic-rescue-ce08f432ccdcece4.yaml b/releasenotes/notes/ironic-rescue-ce08f432ccdcece4.yaml new file mode 100644 index 000000000..e67a6ea8a --- /dev/null +++ b/releasenotes/notes/ironic-rescue-ce08f432ccdcece4.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Sets ``rescue_kernel`` and ``rescue_ramdisk`` to the same values as + ``deploy_kernel`` and ``deploy_ramdisk`` on node enrollment or + configuration. + - | + Adds support for ``rescue_interface`` when enrolling nodes. diff --git a/tripleo_common/actions/baremetal.py b/tripleo_common/actions/baremetal.py index dc73355ec..f9cac7522 100644 --- a/tripleo_common/actions/baremetal.py +++ b/tripleo_common/actions/baremetal.py @@ -152,6 +152,16 @@ class ConfigureBootAction(base.TripleOAction): 'path': '/driver_info/deploy_kernel', 'value': image_ids['kernel'], }, + { + 'op': 'add', + 'path': '/driver_info/rescue_ramdisk', + 'value': image_ids['ramdisk'], + }, + { + 'op': 'add', + 'path': '/driver_info/rescue_kernel', + 'value': image_ids['kernel'], + }, ]) LOG.debug("Configuring boot option for Node %s", self.node_uuid) except Exception as err: diff --git a/tripleo_common/tests/actions/test_baremetal.py b/tripleo_common/tests/actions/test_baremetal.py index 5f313397d..52c60f94d 100644 --- a/tripleo_common/tests/actions/test_baremetal.py +++ b/tripleo_common/tests/actions/test_baremetal.py @@ -35,6 +35,12 @@ class TestConfigureBootAction(base.TestCase): 'value': 'r_id'}, {'op': 'add', 'path': '/driver_info/deploy_kernel', + 'value': 'k_id'}, + {'op': 'add', + 'path': '/driver_info/rescue_ramdisk', + 'value': 'r_id'}, + {'op': 'add', + 'path': '/driver_info/rescue_kernel', 'value': 'k_id'}] self.ironic = mock.MagicMock() @@ -118,8 +124,18 @@ class TestConfigureBootAction(base.TestCase): self.assertIsNone(result) - self.node_update[1].update({'value': 'test_ramdisk_id'}) - self.node_update[2].update({'value': 'test_kernel_id'}) + self.node_update[1:] = [{'op': 'add', + 'path': '/driver_info/deploy_ramdisk', + 'value': 'test_ramdisk_id'}, + {'op': 'add', + 'path': '/driver_info/deploy_kernel', + 'value': 'test_kernel_id'}, + {'op': 'add', + 'path': '/driver_info/rescue_ramdisk', + 'value': 'test_ramdisk_id'}, + {'op': 'add', + 'path': '/driver_info/rescue_kernel', + 'value': 'test_kernel_id'}] self.ironic.node.update.assert_called_once_with(mock.ANY, self.node_update) diff --git a/tripleo_common/tests/utils/test_nodes.py b/tripleo_common/tests/utils/test_nodes.py index 53b2ee872..9e08e9689 100644 --- a/tripleo_common/tests/utils/test_nodes.py +++ b/tripleo_common/tests/utils/test_nodes.py @@ -334,7 +334,9 @@ class NodesTest(base.TestCase): "ipmi_username": "test", "ipmi_password": "random", "deploy_kernel": "kernel-123", - "deploy_ramdisk": "ramdisk-999"} + "deploy_ramdisk": "ramdisk-999", + "rescue_kernel": "kernel-123", + "rescue_ramdisk": "ramdisk-999"} pxe_node = mock.call(driver="ipmi", name='node1', driver_info=pxe_node_driver_info, @@ -403,6 +405,7 @@ class NodesTest(base.TestCase): 'network_interface': 'neutron', 'power_interface': 'ipmitool', 'raid_interface': 'agent', + 'rescue_interface': 'agent', 'storage_interface': 'cinder', 'vendor_interface': 'ipmitool'} @@ -438,6 +441,7 @@ class NodesTest(base.TestCase): 'network_interface': 'neutron', 'power_interface': 'ipmitool', 'raid_interface': 'agent', + 'rescue_interface': 'agent', 'storage_interface': 'cinder', 'vendor_interface': 'ipmitool'} @@ -492,6 +496,8 @@ class NodesTest(base.TestCase): {'path': '/properties/capabilities', 'value': 'num_nics:6'}, {'path': '/driver_info/deploy_kernel', 'value': 'image-k'}, {'path': '/driver_info/deploy_ramdisk', 'value': 'image-r'}, + {'path': '/driver_info/rescue_kernel', 'value': 'image-k'}, + {'path': '/driver_info/rescue_ramdisk', 'value': 'image-r'}, {'path': '/driver_info/ipmi_username', 'value': 'test'}] for key in update_patch: key['op'] = 'add' diff --git a/tripleo_common/utils/nodes.py b/tripleo_common/utils/nodes.py index 76d4d056c..2ef5b5866 100644 --- a/tripleo_common/utils/nodes.py +++ b/tripleo_common/utils/nodes.py @@ -28,7 +28,8 @@ LOG = logging.getLogger(__name__) _KNOWN_INTERFACE_FIELDS = [ '%s_interface' % field for field in ('boot', 'console', 'deploy', 'inspect', 'management', 'network', - 'power', 'raid', 'storage', 'vendor') + 'power', 'raid', 'rescue', 'storage', + 'vendor') ] CTLPLANE_NETWORK = 'ctlplane' @@ -312,8 +313,10 @@ def register_ironic_node(node, client): if "kernel_id" in node: driver_info["deploy_kernel"] = node["kernel_id"] + driver_info["rescue_kernel"] = node["kernel_id"] if "ramdisk_id" in node: driver_info["deploy_ramdisk"] = node["ramdisk_id"] + driver_info["rescue_ramdisk"] = node["ramdisk_id"] interface_fields = {field: node.pop(field) for field in _KNOWN_INTERFACE_FIELDS @@ -420,8 +423,10 @@ _NON_DRIVER_FIELDS = {'cpu': '/properties/cpus', 'root_device': '/properties/root_device', 'name': '/name', 'resource_class': '/resource_class', - 'kernel_id': '/driver_info/deploy_kernel', - 'ramdisk_id': '/driver_info/deploy_ramdisk', + 'kernel_id': ['/driver_info/deploy_kernel', + '/driver_info/rescue_kernel'], + 'ramdisk_id': ['/driver_info/deploy_ramdisk', + '/driver_info/rescue_ramdisk'], 'capabilities': '/properties/capabilities'} _NON_DRIVER_FIELDS.update({field: '/%s' % field @@ -437,9 +442,14 @@ def _update_or_register_ironic_node(node, node_map, client): node_uuid) patched = {} - for field, path in _NON_DRIVER_FIELDS.items(): + for field, paths in _NON_DRIVER_FIELDS.items(): + if isinstance(paths, six.string_types): + paths = [paths] + if field in node: - patched[path] = node.pop(field) + value = node.pop(field) + for path in paths: + patched[path] = value driver_info = handler.convert(node) for key, value in driver_info.items():