Deploying Device Configurations

netlab Ansible playbooks deploy configurations through device-specific task lists and templates. When adding a new device type, you’ll have to create either a generic deploy configuration task list and a bunch of configuration templates or a task list for every module supported by the device (plus the initial configuration templates).

You can also mix and match the two approaches. For example, you could have a generic deploy configuration task list but use a separate list of tasks for the initial configuration.

Configuration Deployment Search Paths

Before starting the configuration deployment process, netlab initial Ansible playbook tries to find an Ansible task list that can be used to check the readiness of a lab device. If that task list is found, it’s executed before the initial device configuration deployment starts. You can use that task list to check the device’s SSH server (Arista cEOS) or interface initialization state (Cisco Nexus OS). netlab initial uses these default parameters to find the device readiness task list (more details):




Directory search path for device readiness task list


Filename search pattern for device readiness task list

The netlab initial Ansible playbook tries to find device-specific task lists or templates using netlab_device_type or ansible_network_os (when netlab_device_type is missing) Ansible variable, including a combination with netlab_provider (for provider-specific configuration). These variables are usually defined as device group variables in system settings.

Directory- and file search paths are defined in these default parameters (more details):




Directory search path for configuration templates


Filename search patterns for configuration templates

After finding the Jinja2 template, the initial configuration deployment playbook tries to find the device/module-specific Ansible task list to deploy the configuration (config_module is set to initial when deploying the initial device configuration). The task list search process uses these default parameters (more details):




Directory search paths for configuration deployment task lists


Filename search patterns for module configuration deployment task lists

Finding Custom Configuration Templates

The following paths are searched when looking for custom configuration templates specified in the config list or through a plugin (more details):




Directory search paths for custom configuration templates


Filename search patterns for custom configuration templates

The custom configuration could be deployed via a dedicated task list or a generic configuration deployment task list. These parameters are used to find the custom configuration deployment task (more details):




Directory search paths for custom configuration deployment tasks


Filename search patterns for custom configuration deployment tasks


Generic configuration deployment task lists
(used to deploy custom configuration)

If the deployment playbook cannot find a dedicated deployment tasklist, it uses the default tasklist that depends on the device type and virtualization provider.

Ansible Variables

The following Ansible variables are set before a device-specific task list is executed:

  • config_template – configuration template name (warning: the presence of configuration template might not be checked)

  • netsim_action – action currently being executed (initial, module name, or custom configuration name)

  • config_module – the name of the currently-deployed module (present only in the module configuration deployment phase of netlab initial)

  • custom_config – the name of the currently-deployed custom configuration (present only in the custom configuration deployment phase of netlab initial)

Sample Configuration Deployment Task Lists

Most network devices need a minimal configuration deployment task list, for example (Cisco IOS):

- cisco.ios.ios_config:
    src: "{{ config_template }}"

Some deployment task lists are a bit more complex. For example, Cumulus VX/FRR configuration deployment could use bash or vtysh:

- template:
    src: "{{ config_template }}"
    dest: /tmp/
- set_fact: deployed_config={{ lookup('template',config_template) }}
- command: bash /tmp/
  when: not ansible_check_mode and ("#!/bin/bash" in deployed_config)
- command: vtysh -f /tmp/
  when: not ansible_check_mode and not ("#!/bin/bash" in deployed_config)

Mikrotik RouterOS deployment copies a configuration file to the device with scp and executes an import command on the device:

- local_action:
    module: tempfile
    state: file
    suffix: temp
    prefix: ansible.{{ inventory_hostname }}.
  register: tempfile_1

- local_action:
    module: template
    src: "{{ config_template }}"
    dest: "{{ tempfile_1.path }}"

- local_action:
    module: command
    cmd: "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {{ lookup('env', 'HOME') }}/.vagrant.d/insecure_private_key {{ tempfile_1.path }} vagrant@{{ ansible_host }}:config.rsc"

- routeros_command:
    commands: /import config.rsc

- local_action:
    module: file
    path: "{{ tempfile_1.path }}"
    state: absent
  when: tempfile_1.path is defined

You’ll find even more complex examples in deploy-config/srlinux.yml and deploy-config/sros.yml

Mixing Task Lists and Configuration Templates

Nexus OS configurations usually use configuration templates. deploy-config/nxos.yml task list is as trivial as the Cisco IOS one:

- cisco.nxos.nxos_config:
    src: "{{ config_template }}"

Unfortunately, the Nexus 9300v linecards become active almost a minute after completing the device boot. We could check whether the Ethernet interfaces are present every time a configuration template is deployed on Nexus 9300v; a more streamlined approach uses a separate task list for initial device configuration in nxos/initial.yml[1]:

- name: Wait for Eth1/1 to appear
    - show interface brief
    - result[0] contains Eth1
    interval: 5
    retries: 20

- cisco.nxos.nxos_config:
    src: "{{ config_template }}"

Changing and Troubleshooting Search Paths

The directory and filename search paths used by the netlab initial and netlab config commands are defined in the paths dictionary within the system defaults. You can change these parameters or prepend/append another list to them:

  • To change a search path list, set the corresponding defaults.paths variable in lab topology or user defaults.

  • To prepend a list of path components to a search path list, set the defaults.paths.prepend.path_name list.

  • To append a list of path components to a search path list, set the defaults.paths.append.path_name list.

For example, to append the ~/templates directory to the custom configuration template search list, set the defaults.paths.append.custom.dirs parameter to [ ~/templates ].


netlab does not report errors in ‌defaults settings. Make sure you’re using the expected attribute paths and list (not string) values.

You can inspect the default value of any search path with the netlab show defaults paths.path_name command. For example, to inspect the directory search path used for custom configuration templates, use the netlab show defaults paths.custom.dirs command:

$ netlab show defaults paths.custom.dirs

netlab default settings within the paths.custom.dirs subtree

- 'topology:'
- .
- ~/.netlab
- package:extra

The filename search patterns can use Jinja2 expressions that rely on Ansible variables set during the configuration deployment process. Directory search patterns can use these prefixes:




networklab package (system file)


Directory containing the current lab topology

The directory search patterns are evaluated during the data transformation process, and the absolute paths are stored in the Ansible inventory (in the all group) and the netlab.snapshot.yml file. You can use the netlab inspect defaults.paths command to display the transformed values (netlab inspect command is available after starting the lab or executing the netlab create command).

For example, the default custom configuration template directory search path (defaults.paths.custom.dirs) contains these entries:

custom:                         # Custom configuration templates
  dirs:                         # ... search directories
  - "topology:"
  - "."
  - "~/.netlab"
  - "package:extra"

The evaluated search path that is stored in netlab.snapshot.yml might contain these values (the topology directory is equal to the current directory, netlab is executed from local Git directory):

$ netlab inspect defaults.paths.custom.dirs
- /home/user/BGP/session/2-asoverride
- /home/user/.netlab
- /home/user/net101/tools/netsim/extra

You can also display the evaluated absolute paths without creating a lab topology. Use the evaluate-paths option of the netlab show defaults command:

$ netlab show defaults paths.custom.dirs --evaluate-paths

netlab default settings within the paths.custom.dirs subtree

- /home/user/net101/tools/netsim/cli
- /home/user
- /home/user/.netlab
- /home/pipi/net101/tools/netsim/extra


The lab topology is the first entry in the custom template search path. The empty topology file used by the ‌netlab show defaults resides in the package:cli directory, resulting in the first entry in the evaluated paths display.