diff --git a/ironic/common/pxe_utils.py b/ironic/common/pxe_utils.py index fc4fb97447..3f8eca953e 100644 --- a/ironic/common/pxe_utils.py +++ b/ironic/common/pxe_utils.py @@ -115,6 +115,8 @@ def _link_mac_pxe_configs(task, ipxe_enabled=False): pxe_config_file_path = get_pxe_config_file_path( task.node.uuid, ipxe_enabled=ipxe_enabled) for port in task.ports: + if not CONF.neutron.add_all_ports and not port.pxe_enabled: + continue client_id = port.extra.get('client-id') # Syslinux, ipxe, depending on settings. create_link(_get_pxe_mac_path(port.address, client_id=client_id, diff --git a/ironic/tests/unit/common/test_pxe_utils.py b/ironic/tests/unit/common/test_pxe_utils.py index ca19d621b6..27d08ecf55 100644 --- a/ironic/tests/unit/common/test_pxe_utils.py +++ b/ironic/tests/unit/common/test_pxe_utils.py @@ -517,6 +517,53 @@ class TestPXEUtils(db_base.DbTestCase): unlink_mock.assert_has_calls(unlink_calls) create_link_mock.assert_has_calls(create_link_calls) + @mock.patch('ironic.common.utils.create_link_without_raise', autospec=True) + def test_link_mac_pxe_configs_with_pxe_disabled(self, create_link_mock): + port_1 = object_utils.create_test_port( + self.context, node_id=self.node.id, pxe_enabled=True, + address='11:22:33:44:55:66', uuid=uuidutils.generate_uuid()) + port_2 = object_utils.create_test_port( + self.context, node_id=self.node.id, pxe_enabled=False, + address='11:22:33:44:55:67', uuid=uuidutils.generate_uuid()) + + with task_manager.acquire(self.context, self.node.uuid) as task: + task.ports = [port_1, port_2] + + # Test with add_all_ports set to False (default) + pxe_utils._link_mac_pxe_configs(task) + + # Verify that no links were created for pxe disabled ports + self.assertNotIn(mock.call( + u'../%s/config' % self.node.uuid, + '/tftpboot/pxelinux.cfg/01-11-22-33-44-55-67'), + create_link_mock.mock_calls) + self.assertNotIn(mock.call( + u'%s/config' % self.node.uuid, + '/tftpboot/grub.cfg-01-11-22-33-44-55-67'), + create_link_mock.mock_calls) + self.assertNotIn(mock.call( + u'%s/config' % self.node.uuid, + '/tftpboot/11:22:33:44:55:67.conf'), + create_link_mock.mock_calls) + + # Test with add_all_ports set to True + self.config(add_all_ports=True, group='neutron') + pxe_utils._link_mac_pxe_configs(task) + + # Verify that links were created for all ports + self.assertIn(mock.call( + u'../%s/config' % self.node.uuid, + '/tftpboot/pxelinux.cfg/01-11-22-33-44-55-67'), + create_link_mock.mock_calls) + self.assertIn(mock.call( + u'%s/config' % self.node.uuid, + '/tftpboot/grub.cfg-01-11-22-33-44-55-67'), + create_link_mock.mock_calls) + self.assertIn(mock.call( + u'%s/config' % self.node.uuid, + '/tftpboot/11:22:33:44:55:67.conf'), + create_link_mock.mock_calls) + @mock.patch('ironic.common.utils.create_link_without_raise', autospec=True) @mock.patch('ironic_lib.utils.unlink_without_raise', autospec=True) @mock.patch('ironic.common.dhcp_factory.DHCPFactory.provider', diff --git a/releasenotes/notes/restrict-pxe-link-files-to-only-pxe-enabled-ports-d2ca5386bdd04bef.yaml b/releasenotes/notes/restrict-pxe-link-files-to-only-pxe-enabled-ports-d2ca5386bdd04bef.yaml new file mode 100644 index 0000000000..1444c7cf84 --- /dev/null +++ b/releasenotes/notes/restrict-pxe-link-files-to-only-pxe-enabled-ports-d2ca5386bdd04bef.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + During node deployment, unless explicitly configured otherwise, + Ironic now only creates PXE link files for ports with pxe_enabled=True, + preventing unintended booting from disabled ports.