Runbooks with Multiple Traits¶
This spec introduces a traits field on runbooks and removes the
constraint that a runbook’s name must be a valid trait string.
A new description field is also added, consistent with other
Ironic objects.
Problem description¶
When runbooks were originally introduced (API v1.92), the runbook
name served a dual purpose:
A human-readable identifier for the runbook.
A gate – to execute a runbook on a node, the node must carry a trait whose value equals the runbook name.
This coupling creates several problems:
Runbook names are forced to follow the trait naming convention (
CUSTOM_[A-Z0-9_]+or anos-traitsstandard trait). Human readable names like"wipe-disks-for-decommission"or"firmware-upgrade-gen10"are not permitted.Each node that could use the runbook would have to have the trait added to it which means more data pushed to placement and more data in the scheduling filter which we have seen a lot of traits causing performance impacts.
A single runbook can only be “approved” for use via one trait name. Operators that want the same runbook to be available across different hardware families—each identified by a different trait—must either duplicate the runbook or add a single shared trait to all nodes, which undermines the per-hardware-family approval intent.
There is no
descriptionfield on the Runbook object, making runbooks harder to document and discover compared with other Ironic objects (nodes, ports, etc.) which all carry adescription.
Proposed change¶
Runbooks will be associated with multiple traits, and inversely multiple runbooks may be associated with a single trait. This improves operator workflows and reduces the number of traits that need to be assigned to a node, which alleviates the scheduling performance impact seen when nodes carry a large number of traits in placement.
Add a ``traits`` field to runbooks. A runbook’s
traitsis a set of trait strings (same format as node traits). Traits must begin withCUSTOM_followed by uppercase letters, digits, or underscores. When a user requests execution of a runbook, the system checks that the target node carries at least one trait that appears in the runbook’straitsset. Any non-empty intersection is sufficient.Remove the trait-name constraint from runbook names. From the API microversion introduced by this spec onwards, a runbook
namemay be any valid logical name string (the same format accepted for node names), not just a trait-formatted string. Names remain unique and are still used to look up runbooks by name.Add a ``description`` field to runbooks. The field accepts a nullable string up to 255 characters, consistent with other Ironic objects.
Automatic migration. During the database migration, each existing runbook’s current
namevalue is inserted as the sole entry in that runbook’s newtraitsset. This preserves the existing behaviour so that no operator action is required on upgrade.New trait-management API endpoints (
/v1/runbooks/{ident}/traits). Following the same design as node traits, operators can list, set, add, and remove individual traits on a runbook. This reuses the existing runbook ownership model: project-scoped managers that are already trusted to operate the hardware and update their runbooks are likewise trusted to manage the runbook’s approval traits.
Alternatives¶
Keep name-as-trait, add an optional ``traits`` list. Rejected because it leaves the confusing dual-role of
name, makes the migration path awkward, and does not cleanly fix the naming restriction.Use a separate field ``allowed_node_traits``. Rejected in favour of re-using the well-established
traitsconcept and endpoint pattern already present for nodes.
Data model impact¶
A new
runbook_traitstable is created:runbook_traits ( runbook_id INTEGER NOT NULL REFERENCES runbooks(id), trait VARCHAR(255) NOT NULL, version VARCHAR(15), created_at DATETIME, updated_at DATETIME, PRIMARY KEY (runbook_id, trait), )
A
descriptioncolumn (VARCHAR(255), nullable) is added to therunbookstable.The unique constraint on
runbooks.nameis retained; names remain unique identifiers.Migration: for every existing row in
runbooks, a row is inserted intorunbook_traitswith the samerunbook_idand withtraitset to the oldnamevalue (which was previously required to be a valid trait string).
State Machine Impact¶
No impact.
REST API impact¶
The API microversion introduced by this spec introduces the following changes.
All existing endpoints in /v1/runbooks are modified:
On GET (list and single-item), the response now includes:
traits: a list of trait strings (e.g.["CUSTOM_FOO", "CUSTOM_BAR"]).description: a nullable string.
On POST (create), the request body may include:
traits: optional list of trait strings. If omitted, defaults to an empty list. A runbook created without any traits is valid but will not be eligible to run on any node until traits are later assigned through the dedicated trait endpoints. The name is no longer required to be a valid trait string.description: optional nullable string (max 255 chars).
The
namefield now accepts any valid logical name (letters, digits, hyphens, dots, underscores; 1–255 characters).On PATCH (update), the
namefield may now be patched to any valid logical name. Thedescriptionfield may also be patched. (Direct patching oftraitsvia the runbook PATCH endpoint is not supported; use the dedicated trait endpoints instead.)
New sub-resource endpoints:
GET /v1/runbooks/{runbook_ident}/traitsList the traits associated with the runbook.
Response body:
{"traits": ["CUSTOM_FOO", "CUSTOM_BAR"]}
PUT /v1/runbooks/{runbook_ident}/traitsReplace all traits for a runbook.
Request body:
{"traits": ["CUSTOM_FOO"]}
PUT /v1/runbooks/{runbook_ident}/traits/{trait}Add a single trait to the runbook (idempotent).
No request body.
DELETE /v1/runbooks/{runbook_ident}/traits/{trait}Remove a single trait from the runbook.
All trait management endpoints require appropriate policy authorisation
(baremetal:runbook:update). This is intentional: deployments that
delegate runbook updates to project-scoped managers are treating those
managers as the operators for that hardware, so the same role that can
maintain the runbook may also maintain its trait gate.
Client (CLI) impact¶
“openstack baremetal” CLI¶
python-ironicclient/ theopenstack baremetalplugin will need updates to exposetraitsin the CLI output forbaremetal runbook create,show, andlist.New
baremetal runbook add trait/remove trait/set traitscommands should be added, matching the existingbaremetal node *traitcommands.
“openstacksdk”¶
None.
RPC API impact¶
None.
Driver API impact¶
None.
Nova driver impact¶
None.
Ramdisk impact¶
None.
Security impact¶
None beyond what was already documented in the original runbooks spec. The trait-intersection check maintains the same operator-controlled gate within the existing runbook RBAC model: before a runbook can run on a node, a manager that is already authorised to operate that hardware must explicitly add a matching trait to the node or to the runbook.
Other end user impact¶
Consumers of the existing baremetal.runbook.* notifications will
see traits and description added to the payload.
Scalability impact¶
The runbook_traits table is expected to be small (at most ~50
rows per runbook, matching the node-traits limit).
Performance Impact¶
Minimal. Trait lookups are indexed on runbook_id.
Other deployer impact¶
On upgrade, the database migration automatically populates
runbook_traitsfrom existing runbook names. No manual operator action is required.Operators may subsequently rename runbooks (to non-trait-format names) and add multiple traits per runbook.
Developer impact¶
None beyond the normal versioned-object and API-microversion conventions.
Implementation¶
Assignee(s)¶
Primary assignee: Doug Goldstein <cardoe@cardoe.com>
- Other contributors:
None
Work Items¶
Database model: add
descriptiontoRunbook; addRunbookTraitmodel.Database API: add CRUD methods for runbook traits.
Alembic migration: create
runbook_traits; adddescriptioncolumn; migrate names to traits.Versioned object: bump
Runbookto v1.2 addingdescriptionandtraitsfields; addRunbookTraitandRunbookTraitListobjects.API controller:
Relax
namevalidation from the new microversion onwards.Include
descriptionandtraitsin responses from the new microversion onwards.Implement
RunbookTraitsController.Keep pre-updated-microversion create/update flows synchronized by mirroring the legacy
namefield intorunbook_traits.
Update node provision API to check runbook traits instead of name.
Update conductor manager automated-cleaning validation to check runbook traits instead of name.
Update API documentation and release notes.
Dependencies¶
None.
Testing¶
Unit tests for all new DB methods, object methods, and API endpoints.
Tempest API tests for the new
/traitssub-resource.Migration unit test verifying that existing runbook names are correctly migrated to the new
traitstable.
Upgrades and Backwards Compatibility¶
When the API version is below the microversion introduced by this spec,
existing behaviour is unchanged:
a runbook’s name is still validated as a trait string, the traits
and description fields are not returned, and the
/v1/runbooks/{ident}/traits sub-resource is not accessible.
To preserve the legacy execution semantics after compatibility checks
move to runbook.traits, pre-updated-microversion runbook create requests
also add the submitted name into runbook_traits. Likewise,
pre-updated-microversion name updates keep runbook_traits synchronized
with the submitted
legacy name so that old clients continue to observe name-based
behaviour.
Documentation Impact¶
doc/source/admin/runbooks.rst– update to describe the new trait-set model.API reference (
api-ref/source/baremetal-api-v1-runbooks.inc) – document new fields and endpoints.Web API version history.