Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions components/ironic/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ conf:
default_deploy_interface: direct
enabled_bios_interfaces: no-bios,redfish,idrac-redfish,ilo
enabled_boot_interfaces: http-ipxe,ipxe,redfish-virtual-media,redfish-https,idrac-redfish-virtual-media,ilo-virtual-media,ilo-uefi-https,ilo-ipxe
enabled_deploy_interfaces: direct,ramdisk
enabled_deploy_interfaces: direct,ramdisk,noop
enabled_firmware_interfaces: redfish,no-firmware
enabled_hardware_types: redfish,idrac,ilo5,ilo
enabled_hardware_types: redfish,idrac,ilo5,ilo,netdev
enabled_inspect_interfaces: redfish,agent,idrac-redfish,ilo
enabled_management_interfaces: ipmitool,redfish,idrac-redfish,ilo,ilo5
enabled_network_interfaces: noop,neutron
Expand Down
18 changes: 18 additions & 0 deletions docs/design-guide/ironic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ironic

## Custom Hardware Types

UnderStack ships additional Ironic hardware types via the `ironic-understack`
Python package, registered as `ironic.hardware.types` entry points.

### netdev

The `netdev` hardware type is a stub type for network devices (switches,
routers) that Ironic tracks solely for Neutron physical port binding. It uses
noop or no-* interfaces for everything except `network`, which is set to
`neutron`. This means nodes of this type go through no deployment, inspection,
BIOS, RAID, rescue, or firmware lifecycle — Ironic only manages their port
bindings.

To use it, add `netdev` to `enabled_hardware_types` in `ironic.conf` and
ensure `noop` deploy and `neutron` network interfaces are also enabled.
1 change: 1 addition & 0 deletions properdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ nav:
- design-guide/device-types.md
- design-guide/hardware-traits.md
- design-guide/flavors.md
- design-guide/ironic.md
- design-guide/neutron-networking.md
- design-guide/neutron-understack-config-sample.md
- design-guide/argo-workflows.md
Expand Down
57 changes: 57 additions & 0 deletions python/ironic-understack/ironic_understack/netdev_hardware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from ironic.drivers import generic
from ironic.drivers.modules import noop
from ironic.drivers.modules.network import neutron
from ironic.drivers.modules.storage import noop as noop_storage


class NetdevHardware(generic.ManualManagementHardware):
"""Hardware type for network devices.

Intended for nodes that represent network infrastructure (e.g. switches,
routers). Deploy is intentionally a no-op; Neutron is the only supported
network interface. All other interfaces use the no-* noop variants.

Boot, power, and management are inherited from ManualManagementHardware
(NoopManagement / FakePower / iPXE+PXE boot) because Ironic has no
NoBoot or NoPower equivalents.
"""

@property
def supported_bios_interfaces(self):
return [noop.NoBIOS]

@property
def supported_console_interfaces(self):
return [noop.NoConsole]

@property
def supported_deploy_interfaces(self):
return [noop.NoDeploy]

@property
def supported_firmware_interfaces(self):
return [noop.NoFirmware]

@property
def supported_inspect_interfaces(self):
return [noop.NoInspect]

@property
def supported_network_interfaces(self):
return [neutron.NeutronNetwork]

@property
def supported_raid_interfaces(self):
return [noop.NoRAID]

@property
def supported_rescue_interfaces(self):
return [noop.NoRescue]

@property
def supported_storage_interfaces(self):
return [noop_storage.NoopStorage]

@property
def supported_vendor_interfaces(self):
return [noop.NoVendor]
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from ironic.drivers.modules import noop
from ironic.drivers.modules.storage import noop as noop_storage

from ironic_understack.netdev_hardware import NetdevHardware


def _interface_names(ifaces):
return [cls.__name__ for cls in ifaces]


def test_netdev_deploy():
hw = NetdevHardware()
assert _interface_names(hw.supported_deploy_interfaces) == ["NoDeploy"]


def test_netdev_bios():
hw = NetdevHardware()
assert _interface_names(hw.supported_bios_interfaces) == ["NoBIOS"]


def test_netdev_network():
hw = NetdevHardware()
assert _interface_names(hw.supported_network_interfaces) == ["NeutronNetwork"]


def test_netdev_noop_interfaces():
hw = NetdevHardware()
assert hw.supported_console_interfaces == [noop.NoConsole]
assert hw.supported_firmware_interfaces == [noop.NoFirmware]
assert hw.supported_inspect_interfaces == [noop.NoInspect]
assert hw.supported_raid_interfaces == [noop.NoRAID]
assert hw.supported_rescue_interfaces == [noop.NoRescue]
assert hw.supported_storage_interfaces == [noop_storage.NoopStorage]
assert hw.supported_vendor_interfaces == [noop.NoVendor]
5 changes: 4 additions & 1 deletion python/ironic-understack/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ requires-python = "~=3.12.0"
readme = "README.md"
license = "MIT"
dependencies = [
"ironic>=32.0,<36",
"ironic>=35.0,<36",
"pyyaml~=6.0",
]

Expand All @@ -26,6 +26,9 @@ port-bios-name = "ironic_understack.port_bios_name_hook:PortBiosNameHook"
node-name-check = "ironic_understack.inspect_hook_node_name_check:InspectHookNodeNameCheck"
chassis_model = "ironic_understack.inspect_hook_chassis_model:InspectHookChassisModel"

[project.entry-points."ironic.hardware.types"]
netdev = "ironic_understack.netdev_hardware:NetdevHardware"

[project.entry-points."ironic.hardware.interfaces.inspect"]
redfish-understack = "ironic_understack.redfish_inspect_understack:UnderstackRedfishInspect"
idrac-redfish-understack = "ironic_understack.redfish_inspect_understack:UnderstackDracRedfishInspect"
Expand Down
41 changes: 20 additions & 21 deletions python/ironic-understack/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading