Skip to content

Commit 2632f1b

Browse files
feat(ironic): Adds ironic runbook for performing BMC maintenances.
1 parent cf1f2e8 commit 2632f1b

6 files changed

Lines changed: 97 additions & 1 deletion

File tree

components/ironic/runbook-crd/README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,52 @@ spec:
9090
| `runbook_disk_cleaning.yaml` | Node Reuse | Secure disk erasure |
9191
| `runbook_gpu_node_setup.yaml` | ML/AI | GPU node configuration |
9292

93+
## Running a Runbook
94+
95+
Once the operator syncs the CRD into Ironic, you execute a runbook by
96+
transitioning a node into the `clean` provisioning state with the runbook
97+
specified. The node must be in `manageable` state before you can trigger
98+
cleaning.
99+
100+
### OpenStack CLI
101+
102+
```bash
103+
# Run a runbook by name
104+
openstack baremetal node clean <node-uuid> --runbook CUSTOM_BMC_MAINTENANCE
105+
106+
# Check node state while cleaning runs
107+
openstack baremetal node show <node-uuid> -f value -c provision_state
108+
```
109+
110+
### Python SDK
111+
112+
```python
113+
from understack_workflows.ironic_node import transition
114+
115+
# node must already be in manageable state
116+
transition(
117+
node,
118+
"clean",
119+
expected_state="manageable",
120+
runbook=runbook_uuid,
121+
)
122+
```
123+
124+
The `transition` helper calls `set_node_provision_state` and waits for the
125+
node to return to `manageable` once all steps complete.
126+
127+
### Trait-Based Automatic Execution
128+
129+
Runbooks can also be triggered automatically by matching node traits. Add the
130+
runbook name as a trait on the node:
131+
132+
```bash
133+
openstack baremetal node add trait <node-uuid> CUSTOM_BMC_MAINTENANCE
134+
```
135+
136+
Workflow code (e.g. `apply_firmware_updates` in `ironic_node.py`) can then
137+
discover matching traits and execute the corresponding runbooks in order.
138+
93139
## Support
94140

95141
- **Ironic Documentation**: https://docs.openstack.org/ironic/latest/

components/ironic/runbook-crd/kustomization.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ namespace: openstack
77
# Create namespace if it doesn't exist
88
resources:
99
- bases/baremetal.ironicproject.org_runbooks.yaml
10+
- runbooks/runbook_bmc_maintenance.yaml
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: baremetal.ironicproject.org/v1alpha1
2+
kind: IronicRunbook
3+
metadata:
4+
name: bmc-maintenance
5+
namespace: openstack
6+
spec:
7+
runbookName: CUSTOM_BMC_MAINTENANCE
8+
9+
steps:
10+
- interface: management
11+
step: clear_job_queue
12+
order: 1
13+
14+
- interface: management
15+
step: set_bmc_clock
16+
order: 2

components/ironic/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ conf:
103103
keep_ports: "present"
104104
redfish:
105105
# Redfish inspection hooks run after inspecting out-of-band using the BMC:
106-
inspection_hooks: "validate-interfaces,ports,port-bios-name,architecture,pci-devices,resource-class"
106+
inspection_hooks: "validate-interfaces,ports,port-bios-name,architecture,pci-devices,resource-class,bmc-maintenance"
107107
# To avoid SSL issues due to the system clock differing, have the conductor
108108
# set the system clock to its time whenever we go to boot the machine into
109109
# IPA
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from ironic import objects
2+
from ironic.drivers.modules.inspector.hooks import base
3+
from oslo_log import log as logging
4+
5+
LOG = logging.getLogger(__name__)
6+
7+
BMC_MAINTENANCE_TRAIT = "CUSTOM_BMC_MAINTENANCE"
8+
9+
10+
class InspectHookBmcMaintenance(base.InspectionHook):
11+
"""Ensure all nodes have the CUSTOM_BMC_MAINTENANCE trait.
12+
13+
This trait authorizes the BMC maintenance runbook to be executed on the
14+
node. The runbook clears the BMC job queue and synchronizes the BMC clock.
15+
"""
16+
17+
def __call__(self, task, inventory, _plugin_data):
18+
node = task.node
19+
existing_traits = set(node.traits.get_trait_names())
20+
21+
if BMC_MAINTENANCE_TRAIT in existing_traits:
22+
LOG.debug("Node %s already has trait %s", node.uuid, BMC_MAINTENANCE_TRAIT)
23+
return
24+
25+
required_traits = existing_traits | {BMC_MAINTENANCE_TRAIT}
26+
LOG.info(
27+
"Adding trait %s to node %s",
28+
BMC_MAINTENANCE_TRAIT,
29+
node.uuid,
30+
)
31+
objects.TraitList.create(task.context, task.node.id, required_traits)
32+
node.save()

python/ironic-understack/pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ update-baremetal-port = "ironic_understack.inspect_hook_update_baremetal_ports:I
2525
port-bios-name = "ironic_understack.port_bios_name_hook:PortBiosNameHook"
2626
node-name-check = "ironic_understack.inspect_hook_node_name_check:InspectHookNodeNameCheck"
2727
chassis_model = "ironic_understack.inspect_hook_chassis_model:InspectHookChassisModel"
28+
bmc-maintenance = "ironic_understack.inspect_hook_bmc_maintenance:InspectHookBmcMaintenance"
2829

2930
[project.entry-points."ironic.hardware.interfaces.inspect"]
3031
redfish-understack = "ironic_understack.redfish_inspect_understack:UnderstackRedfishInspect"

0 commit comments

Comments
 (0)