Skip to content

NETCONF Transaction¤

Use netconf_transaction to apply configuration to selected devices with locking, validation, commit, and failure recovery according to each device's NETCONF capabilities. Confirmed commit provides automatic rollback if the final confirmation does not arrive before the device's timer expires.

Use Cases¤

  • Parallel rollouts: update routing policies across several routers while datastore locks prevent overlapping configuration edits on each device.
  • Recover from failed changes: stage configuration in candidate, validate it before activation, and discard pending changes if editing, validation, or commit fails.
  • Commit-confirmed changes beyond the CLI: use NETCONF candidate and confirmed-commit capabilities on devices whose ordinary CLI workflow does not use commits, such as Cisco IOS XE and NX-OS devices.

How It Works¤

The workflow uses the candidate and confirmed-commit capabilities defined in RFC 6241. Support depends on the platform, software release, and enabled NETCONF features; see the IOS XE NETCONF guide and NX-OS NETCONF guide.

For each selected device:

  1. Lock the target datastore: candidate when available, otherwise running, unless explicitly selected.
  2. Discard existing uncommitted changes when using candidate.
  3. Apply the configuration to the target datastore.
  4. Validate the configuration when enabled and supported.
  5. Commit candidate changes. When confirmed commit is enabled and supported, start the rollback timer, wait commit_final_delay, and send the final confirmation.
  6. Unlock the datastore and return the transaction results.

If editing, validation, or commit fails, attempt to discard pending candidate changes and release the lock. If a confirmed commit is not confirmed before its timer expires, the device rolls back the change.

flowchart TD A[Selected devices run in parallel] --> B[Lock datastore on each device] B --> C{Candidate datastore?} C -->|Yes| D[Discard existing candidate changes] C -->|No| E[Edit running configuration] D --> F[Edit candidate configuration] F --> G[Validate if enabled and supported] E --> G G --> H{Using candidate?} H -->|No| U[Unlock datastore] H -->|Yes| I{Confirmed commit enabled and supported?} I -->|No| J[Commit] I -->|Yes| K[Confirmed commit starts rollback timer] K --> L[Wait commit_final_delay] L --> M[Send final confirmation] M --> U J --> U U --> N[Device transaction complete] F -.->|Edit fails| X[Attempt to discard pending candidate changes] G -.->|Validation fails| X J -.->|Commit fails| X K -.->|Commit fails| X M -.->|Confirmation fails| X E -.->|Edit fails| Y[Report failure and attempt to unlock] X --> Y K -.->|Timer expires without confirmation| R[Device rolls back confirmed commit]

Failure recovery applies to each device independently. Discarding candidate changes does not undo running edits or changes already committed.

How To Enable candidate datastore on Cisco IOS XE¤

On IOS XE devices, enable the candidate datastore in global configuration mode:

Device(config)# netconf-yang feature candidate-datastore

This also enables NETCONF confirmed commit support. Changing this setting restarts NETCONF/RESTCONF services and disconnects active sessions; see the IOS XE candidate configuration guide.

Output¤

Results contain an ordered list of step dictionaries under each host's transaction key. Steps can include discard_changes, edit_config, validate, commit_confirmed, commit, and error, depending on the backend, capabilities, and outcome. Lock and unlock replies are not included in the step list. Failed RPCs and connection errors mark host results as failed. add_details=True includes task metadata; to_dict=False returns serialized records.

Examples¤

nf# nornir netconf transaction config nf://netconf/interface.xml plugin scrapli FL ceos-leaf-1
from norfab.core.nfapi import NorFab

with NorFab(inventory="inventory.yaml") as nf:
    client = nf.make_client()
    result = client.run_job(
        "nornir", "netconf_transaction",
        kwargs={
            "config": "nf://netconf/interface.xml",
            "job_data": {"description": "Lab uplink"},
            "plugin": "ncclient",
            "FL": ["ceos-leaf-1"],
        },
    )
    print(result)

Notes¤

  • Set up device access using the NETCONF connection inventory.
  • Supply XML inside a <config> wrapper, either inline or in a template file. Use host and job_data in templates for device-specific values.
  • By default, changes use candidate when available, otherwise running. Existing uncommitted candidate changes are discarded before applying yours.
  • Confirmed commits are automatically confirmed after commit_final_delay (default: 1 second), without checking connectivity or service health.

Task Command Shell Reference¤

nf#man tree nornir.netconf.transaction

R - required field, M - supports multiline input, D - dynamic key

root
└── nornir:    Nornir service
    └── netconf:    Manage devices using NETCONF
        └── transaction:    Apply configuration using a NETCONF transaction
            ├── timeout:    Job timeout
            ├── workers:    Filter workers to target, default 'all'
            ├── verbose-result:    Control output details, default 'False'
            ├── nowait:    Do not wait for job to complete, default 'False'
            ├── FO:    Filter hosts using a Nornir-Salt Filter Object
            ├── FB:    Filter hosts by name using glob patterns
            ├── FH:    Filter hosts by hostname
            ├── FC:    Filter hosts by name containment pattern
            ├── FR:    Filter hosts by name using regular expressions
            ├── FG:    Filter hosts by group
            ├── FP:    Filter hosts by hostname using IP prefix
            ├── FL:    Filter hosts by names list
            ├── FM:    Filter hosts by platform
            ├── FX:    Exclude hosts by name
            ├── FN:    Negate the host filter match
            ├── on-failed:    Run task on hosts currently marked as failed by Nornir, default 'False'
            ├── to-dict:    Return task results as a dictionary keyed by host, default 'True'
            ├── add-details:    Add Nornir task execution details to results, default 'False'
            ├── progress:    Emit progress events during task execution, default 'True'
            ├── num-workers:    RetryRunner number of threads for task execution
            ├── num-connectors:    RetryRunner number of threads for device connections
            ├── connect-retry:    RetryRunner number of connection attempts
            ├── task-retry:    RetryRunner number of attempts to run each task
            ├── reconnect-on-fail:    RetryRunner reconnects to a host after task failure
            ├── connect-check:    RetryRunner tests TCP connectivity before opening connection
            ├── connect-timeout:    RetryRunner TCP connection check timeout in seconds
            ├── creds-retry:    RetryRunner connection credentials and parameters to retry
            ├── tf:    File group name to save task results on the worker
            ├── tf-skip-failed:    Skip failed task results when saving to file
            ├── diff:    File group name to diff task results against
            ├── diff-last:    Previous saved file version to diff against
            ├── plugin:    NETCONF backend, default 'NetconfPlugin.ncclient'
            ├── config (R):    XML config wrapper or NorFab template URL
            ├── target:    Datastore to edit; omit for backend automatic selection
            ├── job-data:    Template data or YAML file URL
            ├── validate:    Validate when supported by the device, default 'True'
            ├── confirmed:    Use confirmed commit when supported, default 'True'
            ├── confirm-delay:    Confirmed commit timeout in seconds, default '60'
            ├── commit-final-delay:    Delay before final commit in seconds, default '1'
            ├── edit-rpc:    ncclient configuration edit RPC; unused by Scrapli, default 'edit_config'
            ├── edit-arg:    ncclient edit RPC arguments; unused by Scrapli, default '{}'
            └── commit-arg:    ncclient first commit arguments; unused by Scrapli, default '{}'
nf#

The command inherits common host filters, job options, and serialization options. Transaction arguments use hyphenated names such as job-data, confirm-delay, commit-final-delay, edit-rpc, edit-arg, and commit-arg.

Python API Reference¤

Apply configuration using Nornir-Salt's NETCONF transaction call.

Parameters:

Name Type Description Default
job Job

NorFab job metadata.

required
config str

XML including the config wrapper or a NorFab template URL. Rendered per host with host, job_data, norfab and netbox context.

required
target str

Datastore to edit. Omit to let the backend choose candidate when supported, otherwise running.

None
plugin str

Backend name: ncclient (default) or scrapli.

'ncclient'
job_data Any

Template context data or URL to a YAML data file.

None
validate bool

Request validation when supported. Defaults to true.

True
confirmed bool

Request confirmed commit when supported. Defaults to true.

True
confirm_delay int

Confirmed commit rollback timeout in seconds. Defaults to 60.

60
commit_final_delay int

Seconds before automatic final confirmation. Defaults to 1.

1
edit_rpc str

ncclient edit RPC name. Defaults to edit_config; ignored by Scrapli.

'edit_config'
edit_arg dict[str, Any]

Additional ncclient edit RPC arguments; ignored by Scrapli. The backend supplies config and target.

None
commit_arg dict[str, Any]

Additional ncclient first commit arguments; ignored by Scrapli.

None
**kwargs Any

Common host filters, processors, retries and serialization options, plus additional Nornir-Salt backend arguments.

{}

Returns:

Name Type Description
Result Result

Per-host transaction step lists under the transaction key, or serialized records with to_dict=False. Nornir-Salt owns locking, candidate discard, editing, validation, commit and failure cleanup. Existing candidate changes are discarded. Running edits cannot be rolled back by discarding candidate changes. Transactions are per host, and retries may repeat them. RPC failures mark hosts failed; unmatched hosts return status no_match.

Raises:

Type Description
FileNotFoundError

If a referenced template cannot be fetched.

Source code in norfab\workers\nornir_worker\netconf_task.py
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
@Task(
    fastapi={"methods": ["POST"]},
    input=NetconfTransactionInput,
    output=NetconfResult,
    mcp={
        "annotations": {
            "title": "NETCONF Transaction",
            "readOnlyHint": False,
            "destructiveHint": True,
            "idempotentHint": False,
            "openWorldHint": True,
        }
    },
)
def netconf_transaction(
    self,
    job: Job,
    config: str,
    target: str = None,
    plugin: str = "ncclient",
    job_data: Any = None,
    validate: bool = True,
    confirmed: bool = True,
    confirm_delay: int = 60,
    commit_final_delay: int = 1,
    edit_rpc: str = "edit_config",
    edit_arg: dict[str, Any] = None,
    commit_arg: dict[str, Any] = None,
    **kwargs: Any,
) -> Result:
    """Apply configuration using Nornir-Salt's NETCONF transaction call.

    Args:
        job: NorFab job metadata.
        config: XML including the config wrapper or a NorFab template URL.
            Rendered per host with host, job_data, norfab and netbox context.
        target: Datastore to edit. Omit to let the backend choose candidate
            when supported, otherwise running.
        plugin: Backend name: ncclient (default) or scrapli.
        job_data: Template context data or URL to a YAML data file.
        validate: Request validation when supported. Defaults to true.
        confirmed: Request confirmed commit when supported. Defaults to true.
        confirm_delay: Confirmed commit rollback timeout in seconds. Defaults to 60.
        commit_final_delay: Seconds before automatic final confirmation. Defaults to 1.
        edit_rpc: ncclient edit RPC name. Defaults to edit_config; ignored by Scrapli.
        edit_arg: Additional ncclient edit RPC arguments; ignored by Scrapli.
            The backend supplies config and target.
        commit_arg: Additional ncclient first commit arguments; ignored by Scrapli.
        **kwargs: Common host filters, processors, retries and serialization
            options, plus additional Nornir-Salt backend arguments.

    Returns:
        Result: Per-host transaction step lists under the transaction key,
            or serialized records with to_dict=False. Nornir-Salt owns locking,
            candidate discard, editing, validation, commit and failure cleanup.
            Existing candidate changes are discarded. Running edits cannot be
            rolled back by discarding candidate changes. Transactions are per
            host, and retries may repeat them. RPC failures mark hosts failed;
            unmatched hosts return status no_match.

    Raises:
        FileNotFoundError: If a referenced template cannot be fetched.
    """
    if target is not None:
        kwargs["target"] = target
    return self._run_netconf(
        job,
        call="transaction",
        plugin=plugin,
        render={"config": config},
        job_data=job_data,
        validate=validate,
        confirmed=confirmed,
        confirm_delay=confirm_delay,
        commit_final_delay=commit_final_delay,
        edit_rpc=edit_rpc,
        edit_arg=edit_arg if edit_arg is not None else {},
        commit_arg=commit_arg if commit_arg is not None else {},
        **kwargs,
    )