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
1 change: 1 addition & 0 deletions .github/workflows/containers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
- dnsmasq
- ironic-nautobot-client
- understack-tests
- shell-operator-ironic
uses: ./.github/workflows/build-container-reuse.yaml
secrets: inherit
with:
Expand Down
2 changes: 2 additions & 0 deletions components/ironic/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ resources:
# working due to the way the chart hardcodes the config-file parameter which then
# takes precedence over the directory
- configmap-ironic-bin.yaml
- ./runbook-crd
- ./runbook-operator
103 changes: 103 additions & 0 deletions components/ironic/runbook-crd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Ironic Runbook Kubernetes CRD

Kubernetes Custom Resource Definition (CRD) for managing Ironic baremetal runbooks. Runbooks define automated sequences of operations (cleaning, configuration, firmware updates) to be executed on baremetal nodes.

## What is a Runbook?

A Runbook is a collection of ordered steps that define automated operations on baremetal nodes in Ironic. Runbooks enable:

- **Automated Cleaning**: Prepare nodes for reuse (disk wiping, BIOS config, firmware updates)
- **Declarative Workflows**: Define repeatable, version-controlled sequences
- **Trait-Based Matching**: Runbooks match to nodes when the runbook name matches a node trait

## Quick Start

### Installation

```bash
# Install the CRD
kubectl apply -f bases/baremetal.ironicproject.org_runbooks.yaml
```

### Create Your First Runbook

```bash
# Apply a minimal example
kubectl apply -f samples/runbook_v1alpha1_minimal.yaml

# Verify it was created
kubectl get runbooks
kubectl describe runbook minimal-runbook
```

### View Available Samples

```bash
# List all sample runbooks
ls samples/

# Apply a specific sample
kubectl apply -f samples/runbook_bios_config.yaml
```

## Field Requirements

### ✅ Required Fields

| Field | Type | Description |
|-------|------|-------------|
| `spec.runbookName` | string | Runbook name matching CUSTOM_* pattern |
| `spec.steps` | array | Ordered list of steps (minimum 1) |
| `steps[].interface` | enum | Hardware interface (bios, raid, deploy, etc.) |
| `steps[].step` | string | Step name (non-empty) |
| `steps[].order` | integer | Execution order (>= 0, unique) |

### ❌ Optional Fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `spec.disableRamdisk` | boolean | `false` | Skip ramdisk booting |
| `spec.public` | boolean | `false` | Public accessibility |
| `spec.owner` | string | `null` | Project/tenant owner |
| `spec.extra` | object | `{}` | Additional metadata |
| `steps[].args` | object | `{}` | Step-specific arguments |

## Minimal Example

```yaml
apiVersion: baremetal.ironicproject.org/v1alpha1
kind: IronicRunbook
metadata:
name: minimal-runbook
namespace: default
spec:
runbookName: CUSTOM_MINIMAL
steps:
- interface: deploy
step: erase_devices
order: 1
```

## Sample Runbooks

| Sample | Use Case | Description |
|--------|----------|-------------|
| `runbook_v1alpha1_minimal.yaml` | Learning | Minimal example with required fields only |
| `runbook_v1alpha1_complete.yaml` | Reference | Complete example with all fields |
| `runbook_bios_config.yaml` | Compute Nodes | BIOS configuration for virtualization |
| `runbook_raid_config.yaml` | Storage Nodes | RAID setup (OS + data volumes) |
| `runbook_firmware_update.yaml` | Maintenance | Firmware updates (BIOS, BMC, NIC) |
| `runbook_disk_cleaning.yaml` | Node Reuse | Secure disk erasure |
| `runbook_gpu_node_setup.yaml` | ML/AI | GPU node configuration |

## Support

- **Ironic Documentation**: https://docs.openstack.org/ironic/latest/
- **Kubernetes CRDs**: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/

---

**Version**: v1alpha1
**API Group**: baremetal.ironicproject.org
**Kind**: IronicRunbook
**Short Name**: rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: ironicrunbooks.baremetal.ironicproject.org
annotations:
controller-gen.kubebuilder.io/version: v0.13.0
spec:
group: baremetal.ironicproject.org
names:
kind: IronicRunbook
listKind: IronicRunbookList
plural: ironicrunbooks
singular: ironicrunbook
shortNames:
- rb
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
description: IronicRunbook represents a collection of ordered steps that define automated operations on baremetal nodes
type: object
required:
- spec
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: IronicRunbookSpec defines the desired state of IronicRunbook
type: object
required:
- runbookName
- steps
properties:
runbookName:
description: 'RunbookName is the unique name of the runbook (REQUIRED). Must match trait naming convention, typically CUSTOM_*. This name is used to match runbooks to nodes via traits.'
type: string
pattern: '^CUSTOM_[A-Z0-9_]+$'
minLength: 1
maxLength: 255
steps:
description: 'Steps is an ordered list of operations to execute (REQUIRED). Minimum 1 step required.'
type: array
minItems: 1
items:
description: RunbookStep defines a single step in the runbook
type: object
required:
- interface
- step
- order
properties:
interface:
description: 'Interface specifies which hardware interface handles this step (REQUIRED). Must be one of the valid Ironic cleaning interfaces.'
type: string
enum:
- bios
- raid
- deploy
- management
- power
- storage
- vendor
- rescue
- console
- boot
- inspect
- network
- firmware
step:
description: 'Step is the name of the step to execute (REQUIRED). Must be a valid step name for the specified interface.'
type: string
minLength: 1
maxLength: 255
order:
description: 'Order defines the execution sequence (REQUIRED). Must be >= 0 and unique within the runbook. Lower numbers execute first.'
type: integer
minimum: 0
args:
description: 'Args contains step-specific arguments (OPTIONAL). Structure depends on the interface and step. Default: {}'
type: object
x-kubernetes-preserve-unknown-fields: true
disableRamdisk:
description: 'DisableRamdisk skips booting the ramdisk for cleaning operations (OPTIONAL). Use when steps can run without IPA (Ironic Python Agent). Default: false'
type: boolean
default: false
public:
description: 'Public makes the runbook accessible to all projects/tenants (OPTIONAL). Cannot be true if owner is set. Default: false'
type: boolean
default: false
owner:
description: 'Owner identifies the project/tenant that owns this runbook (OPTIONAL). Cannot be set if public is true. Default: null'
type: string
nullable: true
maxLength: 255
extra:
description: 'Extra contains additional metadata (OPTIONAL). Use for descriptions, versions, maintainer info, etc. Default: {}'
type: object
x-kubernetes-preserve-unknown-fields: true
status:
description: RunbookStatus defines the observed state of Runbook
type: object
properties:
ironicUUID:
description: IronicUUID is the UUID of this runbook in the Ironic API
type: string
syncStatus:
description: SyncStatus indicates the synchronization state with Ironic
type: string
enum:
- Synced
- Pending
- Failed
- Unknown
lastSyncTime:
description: LastSyncTime is the timestamp of the last successful sync with Ironic
type: string
format: date-time
observedGeneration:
description: ObservedGeneration reflects the generation of the most recently observed Runbook
type: integer
format: int64
conditions:
description: Conditions represent the latest available observations of the runbook's state
type: array
items:
description: Condition contains details for one aspect of the current state of this API Resource
type: object
required:
- type
- status
- lastTransitionTime
properties:
type:
description: Type of condition (e.g., Ready, Validated, Synced)
type: string
status:
description: Status of the condition (True, False, Unknown)
type: string
enum:
- "True"
- "False"
- Unknown
lastTransitionTime:
description: LastTransitionTime is the last time the condition transitioned from one status to another
type: string
format: date-time
reason:
description: Reason contains a programmatic identifier indicating the reason for the condition's last transition
type: string
message:
description: Message is a human readable message indicating details about the transition
type: string
subresources:
status: {}
additionalPrinterColumns:
- name: Runbook Name
type: string
description: The runbook name used for trait matching
jsonPath: .spec.runbookName
- name: Steps
type: integer
description: Number of steps in the runbook
jsonPath: .spec.steps[*]
- name: Public
type: boolean
description: Whether the runbook is public
jsonPath: .spec.public
- name: Sync Status
type: string
description: Synchronization status with Ironic
jsonPath: .status.syncStatus
- name: Age
type: date
jsonPath: .metadata.creationTimestamp
9 changes: 9 additions & 0 deletions components/ironic/runbook-crd/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

# Namespace for runbook resources
namespace: openstack

# Create namespace if it doesn't exist
resources:
- bases/baremetal.ironicproject.org_runbooks.yaml
60 changes: 60 additions & 0 deletions components/ironic/runbook-crd/samples/runbook_bios_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# BIOS Configuration Runbook
#
# This runbook configures BIOS settings for compute nodes.
# Common use case: Enabling virtualization features for hypervisor nodes.
#
# Matches nodes with trait: CUSTOM_COMPUTE_BIOS

apiVersion: baremetal.ironicproject.org/v1alpha1
kind: IronicRunbook
metadata:
name: compute-bios-config
namespace: baremetal-system
labels:
use-case: bios-configuration
hardware-type: compute
spec:
runbookName: CUSTOM_COMPUTE_BIOS

steps:
- interface: bios
step: apply_configuration
order: 1
args:
settings:
# Enable logical processors (hyperthreading)
- name: LogicalProc
value: Enabled

# Enable virtualization technology
- name: VirtualizationTechnology
value: Enabled

# Enable Intel VT-d (IOMMU)
- name: VtForDirectIo
value: Enabled

# Enable SR-IOV support
- name: SRIOV
value: Enabled

# Set boot mode to UEFI
- name: BootMode
value: Uefi

# Enable secure boot
- name: SecureBoot
value: Enabled

extra:
description: "BIOS configuration for compute nodes with virtualization support"
version: "1.0.0"
use_case: "Hypervisor node preparation"
hardware_compatibility:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

post initial or pre, we will want to add the Dell R7515 and R7615 to the compatibility list for this item, assuming they're able to participate without issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was only included in this repo as an example IronicRunbook manifest. I expect any actual runbooks that will be deployed will be done in the overlay repo, and be crafted for specific sites/environments.

- "Dell PowerEdge R740"
- "Dell PowerEdge R640"
- "HPE ProLiant DL380 Gen10"
notes: |
This runbook enables common virtualization features required for
running KVM/QEMU workloads. Adjust settings based on your specific
hardware and requirements.
Loading
Loading