Ansible cisco.iosxr.iosxr_config: Idempotent IOS XR Changes - 夜莺博客

Ansible cisco.iosxr.iosxr_config: Idempotent IOS XR Changes

IOS XR's two-stage commit model is friendlier to automation than most network operating systems, but it also means a careless playbook can commit half a router's configuration and leave an open session behind. The cisco.iosxr.iosxr_config module exists to make that model safe: it reads the running configuration, computes a diff against your intended lines, commits only when something actually changed, and can label the commit so the change is traceable in the configuration history. This article covers the parameters that matter in production and the playbook patterns that keep IOS XR automation idempotent.

What the module actually does

  1. Connects to the device over network_cli.
  2. Retrieves the running configuration (unless you supply your own baseline).
  3. Compares it with the lines you provide, treating them as a configuration section, not as commands to replay.
  4. Enters configuration mode, applies only the missing lines, and commits.
  5. Returns a diff you can log or gate on.

Step 3 is the important one. Because IOS XR configuration is a hierarchical block syntax, the module needs your lines formatted close to how they appear in the running configuration. If it cannot match them, it re-applies them on every run and you lose idempotency.

A minimal, safe playbook

- name: Configure IOS XR interfaces idempotently
  hosts: iosxr_routers
  gather_facts: false
  tasks:
    - name: Set top-level hostname
      cisco.iosxr.iosxr_config:
        lines:
          - hostname {{ inventory_hostname }}
        comment: "ansible: hostname standardisation"

    - name: Configure a routed interface
      cisco.iosxr.iosxr_config:
        lines:
          - description ANSIBLE-MANAGED-UPLINK
          - mtu 9216
          - ipv4 address 192.0.2.1 255.255.255.252
        parents:
          - interface HundredGigE0/0/0/1
        comment: "ansible: uplink standard"
        label: ansible-uplink
      register: cfg

    - name: Fail the play if the device would drift
      ansible.builtin.assert:
        that:
          - not cfg.changed
        fail_msg: "Configuration drift detected on {{ inventory_hostname }}"

The parents list is what makes the lines land in the right stanza — without it the module applies them at global configuration level and the change is meaningless. The assertion turns the playbook into a drift detector when run with --check semantics on a schedule.

Parameters worth knowing

Parameter Why you would use it
parents Anchors the lines inside a stanza such as an interface or router process
before / after Ordered commands pushed around the change — useful for prerequisites and validation
comment Recorded with the commit; appears in commit history
label Named commit label, alphabetically starting, max 30 characters, for rollback targeting
exclusive Locks out other users from committing until the session ends — prevents a race with a human operator
running_config Supply a baseline instead of fetching it every task, which cuts round trips on slow links
match Controls how strictly lines are compared; none forces a push, strict enforces exact presence
backup / backup_options Writes the pre-change configuration to the control node

Enabling backup: yes on every task is the cheapest insurance in network automation: you get a timestamped copy of the configuration as it was before the change, stored next to the playbook run.

Two-stage commit and rollback

IOS XR keeps a configuration history, and commit labels make it navigable. After a labelled playbook run you can inspect and revert with plain CLI:

RP/0/RP0/CPU0:router# show configuration commit list
RP/0/RP0/CPU0:router# show configuration commit changes label ansible-uplink
RP/0/RP0/CPU0:router# configure
RP/0/RP0/CPU0:router(config)# rollback configuration to label ansible-uplink
RP/0/RP0/CPU0:router(config)# commit

Pair that with a change ticket reference in the label value and you have an audit trail that survives the automation tool being unavailable.

Patterns that prevent outages

  • Never run a full-config replace from a playbook without an out-of-band recovery path. If the playbook breaks management reachability you lose the device and the tool in one step.
  • Stage, then commit — use --check --diff in a dry run first and review the diff artifact in CI.
  • Serial execution for control-plane changes — routing protocol or ACL changes should not hit every router simultaneously.
  • Guard management interfaces — assert reachability after each task, or use wait_for on the management address.
  • Pin the collection version — module behaviour and returned keys change between collection releases, which silently breaks conditional logic.

Verification checklist

ansible-playbook iosxr.yml --check --diff
ansible-playbook iosxr.yml | tee run.log
grep -c '"changed": true' run.log

A second consecutive run should report zero changes. If it does not, your lines are not matching the running configuration format — inspect the returned diff, match the device's own line formatting exactly, and re-run.

Inventory and connection details

Most IOS XR automation failures happen before the module runs: the connection is wrong, the inventory variables are missing, or the privilege escalation is not configured. A minimal working inventory for network_cli looks like this:

# inventory.ini
[iosxr_routers]
rtr-core-01 ansible_host=10.10.20.11
rtr-core-02 ansible_host=10.10.20.12

[iosxr_routers:vars]
ansible_network_os=cisco.iosxr.iosxr
ansible_connection=network_cli
ansible_user=automation
ansible_password={{ vault_iosxr_password }}
ansible_become=yes
ansible_become_method=enable
ansible_command_timeout=120

Notes that save hours later:

  • ansible_command_timeout needs raising on IOS XR because configuration commands can take noticeably longer than on IOS, especially with large ACLs or under load. The default is too short for many real changes.
  • Credentials belong in a vault, not in the inventory file. A committed password is an incident waiting for a repository leak.
  • network_cli requires a persistent connection; run with ANSIBLE_PERSISTENT_COMMAND_TIMEOUT aligned to your device timeouts.
  • Keep the automation user's task permissions narrower than a human administrator's. The playbook should not be able to reload a router.

Integrating into a CI pipeline

Once the playbook is idempotent, it fits a standard review-based workflow:

  1. Lint and syntax checkansible-lint plus a YAML parse of the inventory and variables.
  2. Diff stage — run with --check --diff against a lab device or a container-based virtual router, and publish the diff as a build artifact.
  3. Approval — a human reviews the diff. Because the diff is produced by the same module that will apply the change, review is meaningful rather than aspirational.
  4. Apply in batches — serial execution with a limited batch size for anything touching routing or ACLs.
  5. Verify — a post-change assertion task that fails the pipeline if the intended state is missing.
  6. Archive — store the pre-change configuration backup alongside the pipeline run record, so the recovery point is always findable.

The value of the pipeline is not speed; it is that every change has a reviewable diff, an automated verification step and a stored rollback point. Those three properties are what make routine automation safe enough to run on demand.

When not to automate

Some changes still deserve a human hand on the CLI: first-time bring-up of a new chassis, fabric or hardware replacement, and any change whose failure would break the management path. The module is not inherently unsafe — but during bring-up you are discovering the device, and the discovery process is faster to reason about interactively. Automate the steady state, explore interactively.

Related automation articles

For backup and facts collection patterns see Ansible network modules for IOS configuration, facts and backup, and for inventory and playbook scaffolding see Ansible network automation inventory and playbook examples. Lab environments for testing playbooks are covered in Containerlab multi-vendor network labs.

原文链接:https://docs.ansible.com/projects/ansible/9/collections/cisco/iosxr/iosxr_config_module.html