11from typing import ClassVar
22
3- from ironic .common import exception
43from ironic .drivers .modules .inspector .hooks import base
54from oslo_log import log as logging
65
1413class PortBiosNameHook (base .InspectionHook ):
1514 """Set bios_name, pxe_enabled, local_link_connection and physical_network.
1615
17- Populates extra.bios_name and port name from inspection inventory, then
18- determines PXE-enabled ports from node.extra["enrolled_pxe_ports"]
19- (populated during enrolment). If that data is unavailable, all
20- NIC.Integrated.* and NIC.Slot.* ports are treated as PXE-enabled.
16+ Runs after the "ports" hook has created a baremetal port for each NIC in the
17+ box.
2118
22- PXE ports get pxe_enabled=True plus placeholder physical_network and
23- local_link_connection values that neutron requires.
19+ We set the `name` and `extra.bios_name` for each port using the BIOS names
20+ in the inventory data that was collected by redfish inspection.
21+
22+ If this node has no PXE ports at all, then we assume that this box has just
23+ been enrolled and has not yet undergone a successful agent inspection.
24+ Agent inspection will be the next step, and therefore we need to set up the
25+ bare minimum that is required by Ironic/Neutron to prepare to boot the IPA
26+ image.
27+
28+ Even though PXE is not in use, the provisioning network is still required,
29+ because that is how the agent communicates with Ironic. Neutron wants to
30+ make a port in the provisioning network, and it will error out unless it can
31+ find a suitable baremetal port.
32+
33+ We choose one arbitrary baremetal port and we populate its attributes with
34+ dummy data to enable Ironic/Neutron to do an IPA boot:
35+
36+ - pxe_enabled=True
37+ - physical_network="enrol" (placeholder value)
38+ - local_link_connection set to dummy data as placeholder
39+
40+ Note that this only works because neutron is not completely controlling the
41+ DHCP server, so it doesn't matter if we choose the wrong port. If this
42+ situation changes then we would need to configure all possible NICs with
43+ placeholder data, which would result in a configuration for every single
44+ NIC.
2445 """
2546
2647 dependencies : ClassVar [list [str ]] = ["ports" ]
@@ -36,8 +57,9 @@ def __call__(self, task, inventory, plugin_data):
3657 }
3758
3859 ports = list (ironic_ports_for_node (task .context , task .node .id ))
39- initial_enroll = _is_initial_enroll (ports )
40- pxe_nics = _enrolled_pxe_nics (task ) if initial_enroll else []
60+ if not ports :
61+ LOG .error ("No baremetal ports in Ironic for node %s" , task .node .uuid )
62+ return
4163
4264 for baremetal_port in ports :
4365 mac = baremetal_port .address .upper ()
@@ -46,68 +68,23 @@ def __call__(self, task, inventory, plugin_data):
4668 _set_port_extra (baremetal_port , mac , bios_name )
4769 _set_port_name (baremetal_port , mac , bios_name , task .node .name )
4870
49- if initial_enroll :
50- is_pxe = bios_name is not None and any (
51- pxe_nic .startswith (bios_name ) or bios_name .startswith (pxe_nic )
52- for pxe_nic in pxe_nics
53- )
54- _set_port_pxe_enabled (baremetal_port , mac , bios_name , is_pxe )
55- else :
56- is_pxe = baremetal_port .pxe_enabled
57-
58- if initial_enroll and is_pxe :
59- _set_port_physical_network (baremetal_port , mac )
60- _set_port_local_link_connection (baremetal_port , mac )
61-
62- _assert_has_pxe_port (task , ports )
71+ if not any (port .pxe_enabled for port in ports ):
72+ _set_port_pxe_placeholder (ports [0 ])
6373
6474
65- def _enrolled_pxe_nics (task ) -> list [str ]:
66- """Read enrolled PXE NIC names from node.extra, or use broad prefixes."""
67- enrolled_pxe_nics = task .node .extra .get ("enrolled_pxe_ports" )
68- if enrolled_pxe_nics :
69- LOG .info (
70- "Set node %s pxe flag on interfaces from extra.enrolled_pxe_ports %s" ,
71- task .node .uuid ,
72- enrolled_pxe_nics ,
73- )
74- return enrolled_pxe_nics
75- else :
76- LOG .warning (
77- "Node %s extra.enrolled_pxe_ports is missing, "
78- "setting pxe flag on all interfaces starting %s." ,
79- task .node .uuid ,
80- PXE_BIOS_NAME_PREFIXES ,
81- )
82- return PXE_BIOS_NAME_PREFIXES
83-
84-
85- def _is_initial_enroll (ports ) -> bool :
86- return all (
87- not port .physical_network or "enrol" in port .physical_network for port in ports
75+ def _set_port_pxe_placeholder (baremetal_port ):
76+ LOG .info (
77+ "Populating port %s with placeholder PXE data to support enrol." ,
78+ baremetal_port .address ,
8879 )
89-
90-
91- def _set_port_pxe_enabled (baremetal_port , mac , bios_name , is_pxe ):
92- if baremetal_port .pxe_enabled != is_pxe :
93- LOG .info (
94- "Port %s (%s) pxe_enabled %s -> %s" ,
95- mac ,
96- bios_name ,
97- baremetal_port .pxe_enabled ,
98- is_pxe ,
99- )
100- baremetal_port .pxe_enabled = is_pxe
101- baremetal_port .save ()
102-
103-
104- def _assert_has_pxe_port (task , ports ):
105- if any (port .pxe_enabled for port in ports ):
106- return
107-
108- msg = f"No PXE-enabled ports found for node { task .node .uuid } "
109- LOG .error (msg )
110- raise exception .InvalidNodeInventory (node = task .node .uuid , reason = msg )
80+ baremetal_port .pxe_enabled = True
81+ baremetal_port .physical_network = "enrol"
82+ baremetal_port .local_link_connection = {
83+ "port_id" : "None" ,
84+ "switch_id" : "00:00:00:00:00:00" ,
85+ "switch_info" : "None" ,
86+ }
87+ baremetal_port .save ()
11188
11289
11390def _set_port_extra (baremetal_port , mac , required_bios_name ):
@@ -140,25 +117,3 @@ def _set_port_name(baremetal_port, mac, required_bios_name, node_name):
140117 )
141118 baremetal_port .name = required_port_name
142119 baremetal_port .save ()
143-
144-
145- def _set_port_physical_network (baremetal_port , mac ):
146- if not baremetal_port .physical_network :
147- LOG .info ("Port %s changing physical_network from None to 'enrol'" , mac )
148- baremetal_port .physical_network = "enrol"
149- baremetal_port .save ()
150-
151-
152- def _set_port_local_link_connection (baremetal_port , mac ):
153- if not baremetal_port .local_link_connection :
154- baremetal_port .local_link_connection = {
155- "port_id" : "None" ,
156- "switch_id" : "00:00:00:00:00:00" ,
157- "switch_info" : "None" ,
158- }
159- LOG .info (
160- "Port %s changing local_link_connection from None to %s" ,
161- mac ,
162- baremetal_port .local_link_connection ,
163- )
164- baremetal_port .save ()
0 commit comments