Skip to content

Configuration management

The driver implements the full NAPALM candidate-config workflow: load a change, inspect the diff, commit it, and roll back if needed.

device.load_merge_candidate(config='set / system information location "lab"')
print(device.compare_config())   # what would change
device.commit_config()           # apply it
device.rollback()                # restore the pre-commit state

How it works under the hood

The JSON-RPC interface has no persistent candidate datastore across requests — a set request against the candidate datastore is transactional and commits on success. The NAPALM candidate workflow is therefore emulated client-side:

sequenceDiagram
    participant A as Automation
    participant D as Driver (client-side candidate)
    participant N as SR Linux

    A->>D: load_merge_candidate(config)
    D->>N: validate
    N-->>D: OK
    A->>D: compare_config()
    D->>N: diff
    N-->>D: diff text
    A->>D: commit_config()
    D->>N: generate-checkpoint (rollback anchor)
    D->>N: set (one transactional request)
    A->>D: rollback()
    D->>N: load checkpoint + commit

What this means for each method:

  • load_merge_candidate() / load_replace_candidate() store the intended change in the driver and (for JSON configs) validate it on the device via the JSON-RPC validate method — nothing is applied yet.
  • compare_config() uses the JSON-RPC diff method (JSON configs) or a throwaway named candidate on the device (CLI configs).
  • commit_config() first creates a named checkpoint (NAPALM-<session>-<n>, unique per driver instance) as the rollback anchor, then applies everything in one transactional request.
  • discard_config() only clears the client-side state; it never touches the device.
  • rollback() restores the checkpoint created by the last commit_config().

Checkpoints snapshot everything

Checkpoints contain the entire configuration tree. rollback() restores the device to the state at the last commit_config() — any change made by anyone after that checkpoint is reverted too.

No locking

Because the candidate is client-side, no lock is held on the device. Concurrent clients are not blocked — and not protected — against each other.

Accepted config formats

load_merge_candidate() and load_replace_candidate() take a filename or a config string in any of three formats; the driver detects the format automatically.

=== "Native SR Linux JSON"

A JSON document as found in the running config. A merge is interpreted as `update /`, a replace as `replace /`.

```python
device.load_merge_candidate(config="""
{
  "system": {
    "information": {"location": "lab"}
  }
}
""")
```

=== "gNMI-style envelope"

A JSON object with `updates`, `replaces` and/or `deletes` lists, each entry carrying a `path` and (except deletes) a `value`. This gives you path-level control in a single candidate.

```python
device.load_merge_candidate(config="""
{
  "updates": [
    {"path": "/system/information", "value": {"location": "lab"}}
  ],
  "deletes": [
    {"path": "/system/banner"}
  ]
}
""")
```

`load_replace_candidate()` accepts only `replaces` in this format.

=== "SR Linux CLI"

Plain CLI commands, one per line — anything that is not valid JSON is treated as CLI.

```python
device.load_merge_candidate(config="""
set / system information location "lab"
set / system banner login-banner "managed by NAPALM"
""")
```

JSON candidates are validated on the device at load time, so a malformed change fails in load_*_candidate() rather than in commit_config(). CLI candidates are validated when they are diffed or committed.

Committing

device.commit_config(message="change ticket #1234")
  • The message is recorded as the checkpoint comment (and the commit comment for CLI candidates).
  • With the commit_save optional argument, commits use commit save / save startup, so the change also persists into the startup configuration.
  • commit_config(revert_in=...) starts a confirmed commit with an automatic revert timer.
  • Loading a second candidate while one is pending raises an error — commit_config() or discard_config() first.