|
| 1 | +from ironic.drivers.modules.inspector.hooks import base |
| 2 | +from oslo_log import log as logging |
| 3 | + |
| 4 | +from ironic_understack.ironic_wrapper import ironic_ports_for_node |
| 5 | + |
| 6 | +LOG = logging.getLogger(__name__) |
| 7 | + |
| 8 | + |
| 9 | +class PortBiosNameHook(base.InspectionHook): |
| 10 | + """Set port.extra.bios_name and pxe_enabled fields from redfish data.""" |
| 11 | + |
| 12 | + # "ports" creates baremetal ports for each physical NIC, be sure to run this |
| 13 | + # first because we will only be updating ports that already exist: |
| 14 | + dependencies = ["ports"] |
| 15 | + |
| 16 | + def __call__(self, task, inventory, plugin_data): |
| 17 | + """Populate the baremetal_port.extra.bios_name attribute.""" |
| 18 | + LOG.debug(f"{__class__} called with {task=!r} {inventory=!r} {plugin_data=!r}") |
| 19 | + |
| 20 | + inspected_interfaces = inventory.get("interfaces") |
| 21 | + if not inspected_interfaces: |
| 22 | + LOG.error("No interfaces in inventory for node %s", task.node.uuid) |
| 23 | + return |
| 24 | + |
| 25 | + interface_names = { |
| 26 | + i["mac_address"].upper(): i["name"] for i in inspected_interfaces |
| 27 | + } |
| 28 | + |
| 29 | + pxe_interface = _pxe_interface_name(inspected_interfaces) |
| 30 | + |
| 31 | + for baremetal_port in ironic_ports_for_node(task.context, task.node.id): |
| 32 | + mac = baremetal_port.address.upper() |
| 33 | + required_bios_name = interface_names.get(mac) |
| 34 | + extra = baremetal_port.extra |
| 35 | + current_bios_name = extra.get("bios_name") |
| 36 | + |
| 37 | + if current_bios_name != required_bios_name: |
| 38 | + LOG.info( |
| 39 | + "Port %(mac)s updating bios_name from %(old)s to %(new)s", |
| 40 | + {"mac": mac, "old": current_bios_name, "new": required_bios_name}, |
| 41 | + ) |
| 42 | + |
| 43 | + if required_bios_name: |
| 44 | + extra["bios_name"] = required_bios_name |
| 45 | + else: |
| 46 | + extra.pop("bios_name", None) |
| 47 | + |
| 48 | + baremetal_port.extra = extra |
| 49 | + baremetal_port.save() |
| 50 | + |
| 51 | + required_pxe = required_bios_name == pxe_interface |
| 52 | + if baremetal_port.pxe_enabled != required_pxe: |
| 53 | + LOG.info("Port %s changed pxe_enabled to %s", mac, required_pxe) |
| 54 | + baremetal_port.pxe_enabled = required_pxe |
| 55 | + baremetal_port.save() |
| 56 | + |
| 57 | + |
| 58 | +def _pxe_interface_name(inspected_interfaces: list[dict]) -> str: |
| 59 | + """Use a heuristic to determine our default interface for PXE.""" |
| 60 | + names = sorted(i["name"] for i in inspected_interfaces) |
| 61 | + for prefix in ["NIC.Integrated", "NIC.Slot"]: |
| 62 | + for name in names: |
| 63 | + if name.startswith(prefix): |
| 64 | + return name |
0 commit comments