Opt-in device actions
Use this guide to authorize and inspect a one-shot device mutation. It is for operators responsible for IOS-XE maintenance, with namespace-scoped write permissions and a tested device recovery path. A completed action records what was invoked and its outcome; reboot or factory-reset acceptance still requires independent convergence checks.
For a complete operating-system change, follow the IOS-XE upgrade and downgrade runbook. The software API details below supplement that procedure. For read-only requests, use Device diagnostics.
Prerequisites
- A working IOS-XE
CiscoDevice, per-device worker, current mutation CRDs and secure gNOI connection. The request and target device must share a namespace. - A maintenance window, out-of-band recovery access and authorization for the specific action. Validate the workflow on a non-production device first.
aggregator.enabled=false: neither mutation controller runs in aggregator mode. DirectIOSXEOperationalActionrequests also require the standalone topology; the chart rejectsgnoi.enableWriteClass=truewhentopology.enabled=true. Managed topology admits campaign-owned software upgrade leaves through its separate maintenance protocol.
RBAC and runtime gates
Both mutation APIs are Beta (v1alpha1) and disabled by default. Keep diagnostic
permissions separate from permissions to create iosxeoperationalactions or
iosxesoftwareupgrades in the ops.cisco.vk API group.
Creating an action grants broad device authority
Kubernetes RBAC cannot distinguish spec.action.kind. Permission to create
IOSXEOperationalAction includes reboot, file mutation and factory-reset
requests. When a signer is configured, it also includes
ProvisionCertificate and therefore PKI replacement authority. Namespace
RBAC is not an action-kind allowlist; restrict the principals that receive
it and any additional admission controls before enabling the gate.
For an existing standalone installation, review these settings in your Helm values, preserving the rest of the installation's configuration:
aggregator:
enabled: false
topology:
enabled: false
gnoi:
disabled: false
enableWriteClass: true
enableSoftwareUpgrade: false
Apply them through the installation-maintenance procedure,
using the same release, namespace and immutable chart version. Do not disable
managed topology merely to copy this example. The write-class runtime flag is
--enable-write-class-gnoi; its environment equivalent is
CISCO_VK_ENABLE_WRITE_CLASS_GNOI=1.
Software maintenance has a separate gnoi.enableSoftwareUpgrade gate
(--enable-iosxesoftwareupgrade or
CISCO_VK_ENABLE_IOSXE_SOFTWARE_UPGRADE=1). Follow the OS runbook to enable only
the gate that task needs. Chart-level gates affect the applicable workers in
the release; they do not authorize individual operators or operations.
Enabling either mutation gate makes IOS-XE worker Deployments use Recreate
to prevent overlapping generations from sharing one at-most-once mutation
identity. Allow for a brief management interruption. Disabling both gates (or
all gNOI) does not immediately guarantee RollingUpdate: old mutation workers
and signer cleanup must settle, and managed topology or mounted device trust
can independently require Recreate.
Run an action
IOSXEOperationalAction supports Reboot, CancelReboot, KillProcess,
FilePut, FileRemove, FactoryReset and ProvisionCertificate. Each request
has one deviceRef, spec.confirm equal to that device name, and exactly the
argument block matching spec.action.kind. The spec is immutable after create.
This example requests an immediate cold reboot of default/cat9k-smoke. Only
create it after completing the prerequisites and enabling the write-class gate.
Save it as reload-cat9k-smoke.yaml, replacing both device references and the
namespace with the authorized target:
apiVersion: ops.cisco.vk/v1alpha1
kind: IOSXEOperationalAction
metadata:
name: reload-cat9k-smoke
namespace: default
spec:
deviceRef:
name: cat9k-smoke
confirm: cat9k-smoke
action:
kind: Reboot
reboot:
method: COLD
delaySeconds: 0
message: "maintenance reload"
kubectl create -f reload-cat9k-smoke.yaml
kubectl -n default get iosxeoperationalaction reload-cat9k-smoke -w
Stop the watch at a terminal phase, then inspect the status and the device. Do not create another action simply because the worker restarted or the device became temporarily unreachable.
For ProvisionCertificate, the provisionCertificate block must contain the
configured certificateID and publicMaterialSHA256: lowercase SHA-256 of
the exact tls.crt bytes followed by the exact ca.crt bytes. Stale IDs or
digests are rejected before connecting. This action is the only path that
installs the configured gNOI identity; GNOIOSVerify remains read-only. Use the
certificate provisioning workflow
for signer setup and cleanup. Treat factory reset as the last capability to
exercise in a rollout; RBAC alone cannot selectively disable that action kind.
Invocation and recovery
An action is validated in Pending and recorded as Running before the
RPC. A Running action is never dispatched again. Terminal phases are
Succeeded, Failed and Rejected; normal events describe running/successful
requests, and warning events describe rejection, failure or pending deletion.
After a controller restart, CVK waits for the original five-minute RPC window
and a short persistence grace. Without a durably recorded result, the action
fails with ActionOutcomeUnknown and its Lease stays quarantined until expiry.
Inspect the device before creating a replacement request.
For certificate provisioning, CertificateInstallIndeterminate means the
create-only result remained unknown after bounded certificate and OS.Verify
checks over fresh connections. Use GNOICertGet and inspect device PKI state;
never blindly retry the same certificate ID.
IOSXEOperationalAction — example output
kubectl -n default get iosxeoperationalaction reload-cat9k-smoke -o yaml
kubectl -n default describe iosxeoperationalaction reload-cat9k-smoke
An accepted reboot can have the following abbreviated status:
status:
phase: Succeeded
invocationID: "a3f2e1d0-8c7b-4a5f-9e6d-1b2c3d4e5f60"
conditions:
- type: Ready
status: "True"
reason: AcceptedPendingConvergence
For Reboot and FactoryReset, this means the device accepted the RPC.
It does not establish recovery or convergence, and the mutation Lease
remains quarantined until expiry. Verify reachability and resulting device
state independently before declaring maintenance complete.
Shared device-mutation Lease
Actions and software upgrades share a platform-neutral
device-disruptive-mutation Lease for each namespaced device. Its safety TTL is
26 hours in this release. Definitive outcomes release the Lease; every invoked
action failure, accepted reboot/factory reset, and uncertain upgrade outcome
retains it until expiry. Delayed reboots add their accepted delay to the hold.
CancelReboot bypasses coordination and never releases another holder's Lease.
An in-flight action retains its finalizer through the bounded RPC and
persistence window. If its outcome remains unknown, CVK records
ActionOutcomeUnknown, allows deletion to complete and retains quarantine.
Deleting a software-upgrade CR does not cancel device work or clear a required
quarantine. Disabling a gate also does not discard an existing quarantine.
The fence identifies a device by namespace and CiscoDevice name, not its IP.
Register a physical device once and coordinate ownership across clusters.
Manual CLI and external automation remain outside this fence. See
gNOI mutation coordination
for the maintenance taint, app-hosting/configuration-write guard and managed
campaign behavior.
Software upgrade API details
Use the OS upgrade and downgrade runbook for the
complete procedure, credentials, recovery prerequisites and verification.
This reference retains the source-selection, strategy and compatibility
contracts needed to interpret IOSXESoftwareUpgrade objects.
Image sources
Select exactly one source in spec.imageSource:
| Source | Behavior and constraint |
|---|---|
url with sha256 |
Fetch and verify the content, then stream it through gNOI OS.Install. |
configMapRef |
Stream binaryData["image"] through OS.Install; the roughly 900 KiB ConfigMap limit makes this a testing-only source. |
preinstalled: {} |
Activate an exact native-inventory version without transfer or registration. |
deviceFile with path and sha256 |
Verify through gNOI File.Get, register through IOS-XE RESTCONF install, then activate through gNOI. |
Deprecated localPath, optionally localPathSHA256 |
Inventory-only compatibility form; never registers a file. |
Device-file registration has no CLI fallback. Ambiguous or non-activatable
inventory fails closed. URL credentials must not appear as URL user information.
For FTP/SCP/SFTP, an optional same-namespace urlSecretRef must have label
cisco.vk/purpose=software-image-source and keys allowedScheme, allowedHost
and allowedPort matching the canonical endpoint before credentials are
loaded. See the Secret and transfer contract.
Strategies, preparation and rollback
| Strategy | Current behavior |
|---|---|
Reload (default) |
Activates the selected image and reloads the device. |
ISSU |
Rejected during preflight until CVK can verify IOS-XE selected the ISSU path. |
NoReboot |
Requests activation without immediate reload; if the old version remains running, ends as StagedForNextBoot and needs a separately authorized reboot. It is not a hitless-upgrade guarantee. |
PrepareOnly |
Accepts URL, ConfigMap or deviceFile sources, never calls OS.Activate, verifies the old version remains running, and ends as Prepared with an immutable content-addressed receipt. |
A retained preparation receipt blocks both direct upgrades for the same device
and a competing managed campaign for the same Device UID. For managed
activation, the completed rollout needs append-only spec.activationApproval,
the exact frozen plan and receipt set, a bounded UTC window and the distinct
activate permission. CVK creates a new preinstalled activation leaf and
reservation, then revalidates inventory, trust, source, policy, identity, health
and workload safety before claiming activation. The prepared leaf remains audit
evidence; deleting it is never an authorization workflow. Follow
separate preparation and activation
for that approval procedure.
When OS.Verify requires individual-supervisor handling, CVK installs active
then standby, activates standby then active, rejects NoReboot, and uses one
shared install deadline.
With rollbackOnFailure: true, a different running version after activation
can enter RollingBack only if the previous version was captured and the
backend proves it remains activatable. RolledBack requires OS.Verify to
confirm that version. Automatic rollback is rejected for individual-supervisor
handling because a safe, separately verified sequence for both supervisors is
not yet established.
Staging, activation and rollback intent is persisted before its RPC and is not replayed after an ambiguous result. Inspect the device when an outcome remains unknown; submitting a replacement is a new maintenance decision.
IOSXESoftwareUpgrade — example output
For an upgrade created through the OS runbook, substitute its actual namespace and name:
kubectl -n edge get iosxesoftwareupgrade cat9000-1-to-17-18-03 -w
kubectl -n edge describe iosxesoftwareupgrade cat9000-1-to-17-18-03
A successful transfer/reload can progress through Pending → Resolving →
Transferring → Activating → AwaitingReachability → Verifying
→ Succeeded. A deviceFile source uses Staging and Validating before
activation. Inspect the pinned source digest, staging operation ID, inventory,
conditions and events; terminal preparation or staging is not proof that the
target version is running.
Migrating existing mutation objects
The current at-most-once reconciler adopts an unmarked legacy upgrade only in
Pending or Resolving. A later unmarked phase may already have submitted a
mutation, so it ends with LegacyStateOutcomeUnknown and a quarantined Lease.
Inspect device state before replacing it.
Older manifests may retain resumePolicy and maxRetries; stored status may
retain retryCount or phase Cancelled. Admission preserves the historical
Retry and 3 defaults for controller rollback compatibility, but the current
reconciler ignores those retry fields. An unknown non-empty execution-model
marker is preserved as newer-controller state: CVK holds the Lease and issues
no RPC rather than rewriting or replaying the operation.
During this migration, either mutation controller reads both mutation CRDs before claiming a Lease, including when the other controller is disabled. It chooses a deterministic legacy quarantine holder and fails closed on API or RBAC errors. Released invoked actions retain a bounded 26-hour safety window plus any accepted reboot delay, independent of future drivers' normal Lease settings.