Operation Rules
User-defined operation rules configure power control and firmware operations. Each rule specifies a sequence of steps that determine component ordering, parallelism, verification, and retry behavior.
Concepts
Rules and Operations
Each rule is bound to a single operation (e.g., power_on, power_off).
When an operation is triggered, Flow resolves the applicable rule for the target
rack and executes it.
Steps and Stages
A rule contains steps. Each step targets one component type and belongs to a numbered stage. Execution proceeds stage by stage in ascending order. Within a stage, all steps run in parallel.
Action Sequences
Each step defines optional pre_operation and post_operation lists and one required main_operation action:
pre_operation— runs before the main operation (e.g., Sleep to settle)main_operation— the primary work (PowerControl, FirmwareControl, or a verification action when used as the entire step’s purpose)post_operation— runs after the main operation (e.g., verify status)
All three phases execute inside a single child workflow per component-type step. The step supplies activity timeout and retry defaults; Flow derives a separate child-workflow execution budget.
Rule Schema
Top-level fields
Rules are submitted as JSON via the --rule-file flag or embedded in a YAML
batch file.
Step fields
The validator accepts all six component types. The service only registers component managers for Compute, NVSwitch, and PowerShelf; accepting a rule does not establish runtime support for ToRSwitch, UMS, or CDU. Execution also requires the selected manager to support each action.
Retry policy fields
Duration format
All duration fields accept Go duration strings: "5s", "30s", "2m",
"1m30s", "10m", "1h".
Actions Reference
The user-rule validator rejects BringUpControl, WaitBringUp, and InjectExpectation. Their presence in internal workflows does not make them accepted user-rule actions. The public operation-rule API exposes power-control and firmware-control operation types.
PowerControl
Executes a power operation (on/off/restart) for the component.
When used from the power workflow, the operation is inherited from the task
context — no parameters required. When used cross-workflow (e.g., firmware
power recycle, bring-up), specify operation explicitly:
FirmwareControl
Starts a firmware update and polls for completion (async start + poll pattern).
Calls FirmwareControl to initiate, then repeatedly calls
GetFirmwareStatus until all components complete or the poll timeout
expires.
VerifyPowerStatus
Polls the component until its power status matches expected_status. Typically
used in post_operation to confirm the result of PowerControl.
When used as main_operation, the step performs only verification (no power
command is sent). This is the pattern for forceful operation final-verification
stages.
VerifyReachability
Polls until all components of the specified types in the rack become reachable over the network. Used after powering on a powershelf to confirm downstream components have booted, or before bring-up to wait for all PMCs.
By default, a component type is considered reachable when the GetPowerStatus
API call succeeds. With require_all: true, every individual component within
the type must respond (i.e., the returned status map must contain all target
component IDs).
Sleep
Pauses execution for a fixed duration. Implemented as a durable workflow timer (survives worker restarts). Useful for hardware settle time.
GetPowerStatus
Queries the current power status of components and returns a status map.
DecommissionControl
Requests decommissioning of the target components. It has no required parameters. The executor uses a five-minute activity timeout and one attempt, overriding the step’s activity timeout and retry settings. Completion of this action confirms the request, not that decommissioning has finished.
WaitDecommissioned
Polls decommission status until every target reports Decommissioned or
Decommissioning/Decommissioned. Use it after DecommissionControl to wait
for completion.
Use positive durations. Ready, Maintenance(...), and other
Decommissioning/ states continue polling. Missing or empty status results,
unexpected states, five minutes of consecutive status-call failures, or the
action deadline cause failure. Both decommission actions require the selected
component manager’s decommission capabilities; schema validation alone does
not check those capabilities.
Examples
Graceful power on
Powers components in dependency order (powershelf → nvswitch → compute) and verifies status at each stage before proceeding.
Graceful power off
Reverse dependency order (compute → nvswitch → powershelf). A Sleep in the
powershelf pre_operation allows downstream components to finish shutting down
before cutting power.
Forceful power on
Skips per-stage verification for maximum speed. All power commands are issued first; a dedicated final stage (4) verifies all component types simultaneously.
Execution behavior
Flow selects an explicit rule_id first, then a rack-specific rule association, then a global default for the operation, and finally a built-in fallback. An explicit rule that cannot be loaded returns an error instead of falling back. The selected rule is embedded in workflow input before execution starts.
Stages run in order. A failed stage stops the task; earlier stages are not rolled back. Steps for component types absent from the rack are skipped. Activity retries can repeat external calls. The child-workflow execution timeout includes the configured retry budget, declared pre/post action timeouts, and a scheduling buffer; it is not equal to the step timeout.
When retry is omitted, activities default to three attempts, but the child
workflow budget counts only one attempt. With no step timeout or pre/post
action timeouts, the child budget is 32 minutes, while each activity attempt
can take 20 minutes. The child deadline can therefore stop execution before
all three attempts finish.
For Temporal workflow and activity details, see Operation Rule Execution.
CLI Usage
The examples use a local development Flow service and run from rest-api/flow/. Configure the client connection and authentication for other environments before running mutating commands. --dry-run validates a batch without contacting the server.
Batch lookup matches operation type and operation code, not the rule name. --overwrite deletes the matching rule before creating its replacement; it is not an atomic update and can remove rack associations. Use it only after reviewing affected rules and bindings.
Creating with --is-default fails if a default already exists for that operation. To change the default, create a non-default rule and use set-default. Replace <rule-id> and <rack-id> below with existing UUIDs. Save the Graceful power on JSON example as my-rule.json for the single-rule command.
Create a single rule
Load rules from a YAML batch file
Manage rules
A batch must contain every required operation for each included operation type. The small YAML below illustrates structure only; use the complete reference file for batch loading. Single-rule flags (--name, --rule-file, --operation-type, --operation, --is-default) cannot be combined with --from-yaml. --dry-run and --overwrite are batch options.
YAML batch file format
Reference YAML
The loadable rule examples are the canonical batch file. The CLI examples above assume the working directory is rest-api/flow/ in a repository checkout.