diff --git a/ironic_inspector/plugins/standard.py b/ironic_inspector/plugins/standard.py index 47078da69..6c22fdee2 100644 --- a/ironic_inspector/plugins/standard.py +++ b/ironic_inspector/plugins/standard.py @@ -37,6 +37,21 @@ class RootDiskSelectionHook(base.ProcessingHook): might not be updated. """ + def _get_skip_list_from_node(self, node, block_devices): + skip_list_hints = node.node().properties.get("skip_block_devices", []) + if not skip_list_hints: + return + skip_list = set() + for hint in skip_list_hints: + found_devs = il_utils.find_devices_by_hints(block_devices, hint) + excluded_devs = {dev['name'] for dev in found_devs} + skipped_devices = excluded_devs.difference(skip_list) + skip_list = skip_list.union(excluded_devs) + if skipped_devices: + LOG.warning("Using hint %(hint)s skipping devices: %(devs)s", + {'hint': hint, 'devs': ','.join(skipped_devices)}) + return skip_list + def _process_root_device_hints(self, introspection_data, node_info, inventory): """Detect root disk from root device hints and IPA inventory.""" @@ -46,6 +61,11 @@ class RootDiskSelectionHook(base.ProcessingHook): node_info=node_info, data=introspection_data) return + skip_list = self._get_skip_list_from_node(node_info, + inventory['disks']) + if skip_list: + inventory['disks'] = [d for d in inventory['disks'] + if d['name'] not in skip_list] try: device = il_utils.match_root_device_hints(inventory['disks'], hints) diff --git a/ironic_inspector/test/unit/test_plugins_standard.py b/ironic_inspector/test/unit/test_plugins_standard.py index 3aac1166c..3f3139a70 100644 --- a/ironic_inspector/test/unit/test_plugins_standard.py +++ b/ironic_inspector/test/unit/test_plugins_standard.py @@ -364,6 +364,7 @@ class TestRootDiskSelection(test_base.NodeTest): {'model': 'Model 4', 'size': 4 * units.Gi, 'name': '/dev/sdd'}, {'model': 'Too Small', 'size': 1 * units.Gi, 'name': '/dev/sde'}, {'model': 'Floppy', 'size': 0, 'name': '/dev/sdf'}, + {'model': 'Model 3', 'size': 20 * units.Gi, 'name': '/dev/sdg'}, ] self.matched = self.inventory['disks'][2].copy() self.node_info = mock.Mock(spec=node_cache.NodeInfo, @@ -416,6 +417,29 @@ class TestRootDiskSelection(test_base.NodeTest): self.assertNotIn('local_gb', self.data) self.assertFalse(self.node_info.update_properties.called) + def test_one_that_matches_on_skip_list(self): + self.node.properties['root_device'] = {'size': 10} + self.node.properties['skip_block_devices'] = [{'size': 10}] + + self.assertRaisesRegex(utils.Error, + 'No disks satisfied root device hints', + self.hook.before_update, + self.data, self.node_info) + + self.assertNotIn('local_gb', self.data) + self.assertFalse(self.node_info.update_properties.called) + + def test_first_match_on_skip_list_use_second(self): + self.node.properties['root_device'] = {'model': 'Model 3'} + self.node.properties['skip_block_devices'] = [{'size': 10}] + + second = self.inventory['disks'][6].copy() + self.hook.before_update(self.data, self.node_info) + + self.assertEqual(second, self.data['root_disk']) + self.assertEqual(19, self.data['local_gb']) + self.node_info.update_properties.assert_called_once_with(local_gb='19') + def test_one_matches(self): self.node.properties['root_device'] = {'size': 10} diff --git a/releasenotes/notes/introduce_skip_list_to_inspector-825cab226dd212f4.yaml b/releasenotes/notes/introduce_skip_list_to_inspector-825cab226dd212f4.yaml new file mode 100644 index 000000000..b3d684da6 --- /dev/null +++ b/releasenotes/notes/introduce_skip_list_to_inspector-825cab226dd212f4.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Follow the same process for determining root device as Ironic Python Agent + which has been changed to accommodate for the feature enabling users to + specify a list of devices that should be skipped during cleaning/deployment + The field ``skip_block_devices`` is one of the properties of a node