ON THIS PAGE
Use the juniper.device.config Ansible Module to Manage the Junos OS
Configuration
You can use the juniper.device.config Ansible module to manage the
configuration on devices running Junos OS and devices running Junos OS Evolved.
Juniper Networks provides Ansible modules that enable you to configure Junos devices.
Table 1 outlines the available modules. If you are already using a given set of modules from
the juniper.device collection, use the module for that set.
|
Collection |
Module Set |
Module Name |
|---|---|---|
|
|
||
|
|
juniper.device.junos_config |
The following sections discuss how to use the juniper.device.config
module to modify and commit the configuration on Junos devices. For information about
the juniper.device.junos_config module, see Use the juniper.device.junos_config Ansible Module to Configure Junos Devices.
Module Overview
The juniper.device.config module enables you to perform the
following operations on Junos devices:
-
Load configuration data
-
Commit the configuration
-
Roll back the configuration
-
Load the rescue configuration
The basic process for making configuration changes is to lock the configuration, load the configuration changes, commit the configuration to make it active, and then unlock the configuration. The user account that is used to make configuration changes must have permissions to change the relevant portions of the configuration on each device. To modify the configuration, the module’s argument list must include one of the following parameters:
-
load—Load new configuration data. -
rollback—Revert to the rescue configuration or a previously committed configuration.
By default, the juniper.device.config module makes changes to
the candidate configuration database using configure exclusive
mode, which automatically locks and unlocks the candidate global configuration.
You can also specify a different configuration mode. For example, you can make
changes to a private copy of the candidate configuration or to the ephemeral
configuration database. For more information about specifying the configuration
mode, see How to Specify the Configuration Mode.
When loading new configuration data, in addition to specifying the configuration mode, you can also specify the load operation and the source and format of the changes.
-
Load operation—The load operation determines how the configuration data is loaded into the selected configuration database. You can select from many of the same load operations that are available in the Junos OS CLI. For more information, see How to Specify the Load Action.
-
Format—You can configure Junos devices using one of the standard, supported formats. You can provide configuration data or Jinja2 templates as text, Junos XML elements, Junos OS
setcommands, or JSON. For information about specifying the format of the configuration data, see How to Specify the Format of the Configuration Data to Load. -
Configuration data source—You can load configuration data from a list of strings, a file on the local Ansible control node, a Jinja2 template, or a URL reachable from the client device. For more information about specifying the source of the configuration data, see the following sections:
The juniper.device.config module also enables you to load and
commit the rescue configuration or roll the configuration back to a previously
committed configuration. To load the rescue configuration or a previously
committed configuration, you must include the rollback module
argument. For more information, see the following sections:
After modifying the configuration, you must commit the configuration to make it
the active configuration on the device. By default, the
juniper.device.config module commits the changes to the
configuration. To alter this behavior or supply additional commit options, see
How to Commit the Configuration.
By default, when the juniper.device.config module includes the
load or rollback arguments, the module's
response automatically returns the configuration changes in diff or patch
format. The module returns the differences in the diff and
diff_lines fields. To prevent the module from calculating
and returning the differences, set the diff module argument to
false.
How to Specify the Configuration Mode
You can specify the configuration mode to use when modifying the device
configuration. To specify the configuration mode in your task, include the
module's config_mode parameter. Supported configuration modes
include:
-
batch -
dynamic -
ephemeral -
exclusive -
private
By default, the juniper.device.config module makes changes to
the candidate configuration database using configure exclusive
mode. Configure exclusive mode locks the candidate global configuration (also
known as the shared configuration database) for as long as the module
requires to make the requested configuration changes. Locking the database
prevents other users from modifying or committing changes to the database at the
same time.
The following examples show how to configure a private copy of the candidate configuration and how to configure the ephemeral database.
Example: config_mode: "private"
The following playbook uses private configuration mode to
modify a private copy of the candidate configuration:
---
- name: Configure Device
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Configure op script
juniper.device.config:
config_mode: private
load: set
lines:
- "set system scripts op file bgp.slax"
register: response
- name: Print the config changes
ansible.builtin.debug:
var: response.diff_linesuser@ansible-cn:~/ansible$ ansible-playbook configure-script.yaml
PLAY [Configure Device] *******************************************************
TASK [Configure op script] ****************************************************
changed: [dc1a.example.net]
TASK [Print the config changes] ***********************************************
ok: [dc1a.example.net] => {
"response.diff_lines": [
"",
"[edit system scripts op]",
"+ file bgp.slax;"
]
}
PLAY RECAP ********************************************************************
dc1a.example.net : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Configure the Ephemeral Database
You can use the juniper.device.config module to update the
ephemeral configuration database on devices that support this
database. The ephemeral database is an alternate configuration database that
provides a fast programmatic interface for performing configuration updates
on Junos devices.
To open and configure the default instance of the ephemeral configuration
database, include the config_mode: ephemeral argument. For
example:
---
- name: Configure ephemeral database
hosts: dc1a
connection: local
gather_facts: no
tasks:
- name: Configure the default ephemeral database
juniper.device.config:
config_mode: ephemeral
load: set
lines:
- "set protocols mpls label-switched-path to-hastings to 192.0.2.1"To open and configure an existing user-defined instance of the ephemeral
configuration database, include the config_mode: ephemeral
argument, and set the ephemeral_instance argument to the
name of the instance.
tasks:
- name: Configure a user-defined ephemeral instance
juniper.device.config:
config_mode: ephemeral
ephemeral_instance: eph1
load: set
lines:
- "set protocols mpls label-switched-path to-hastings to 192.0.2.2"How to Specify the Load Action
The juniper.device.config module supports loading configuration
changes using many of the same load operations supported in the Junos OS CLI.
You specify the load operation by setting the module's load
argument to the value of the corresponding load operation. Table 2 summarizes the argument values for the different load operations.
|
Load Operation |
|
Description |
|---|---|---|
|
|
|
Merge the loaded configuration with the existing configuration. |
|
|
|
Replace the entire configuration with the loaded configuration. All system processes parse the configuration. |
|
|
|
Load configuration data from a patch file. |
|
|
|
Merge the loaded configuration with the existing
configuration, but replace statements in the existing
configuration with statements in the loaded configuration
that specify the |
|
|
|
Load configuration data that is in |
|
|
|
Load a complete configuration and compare it against the existing configuration. Replace only those parts of the candidate configuration that have changed. During the commit operation, only affected system processes parse the new configuration. |
How to Specify the Format of the Configuration Data to Load
The juniper.device.config module enables you to configure Junos
devices using one of the standard supported formats. You can provide
configuration data as strings or files. Files can contain either configuration
data or Jinja2 templates. When providing configuration data within a string,
file, or Jinja2 template, supported formats for the data include text, Junos XML
elements, Junos OS set commands, and JSON.
The juniper.device.config module attempts to auto-detect the
format of configuration data that you supply as strings within the
lines argument. However, you can explicitly specify the
format for strings by including the format argument. When you
provide configuration data in a file or Jinja2 template, you must specify the
format of the data. Add the appropriate extension to the file or include the
format argument.
Table 3 summarizes the supported formats for the configuration data and the
corresponding value for the file extension and format
parameter. If you include the format argument, it overrides
both the auto-detect format for strings and the format indicated by a file
extension.
|
Configuration Data Format |
File Extension |
|
|---|---|---|
|
CLI configuration statements (text) |
.conf |
|
|
JavaScript Object Notation (JSON) |
.json |
|
|
Junos OS |
.set |
|
|
Junos XML elements |
.xml |
|
When you set the module’s load argument to
override or update, you cannot use the
Junos OS set command format.
How to Load Configuration Data as Strings
The juniper.device.config module enables you to load
configuration data from a list of strings. To load configuration data as
strings, include the appropriate load argument and the
lines argument. The lines argument takes a
list of strings containing the configuration data to load.
The module attempts to auto-detect the format of the lines
configuration data. However, you can explicitly specify the format by including
the format argument. For information about specifying the
format, see How to Specify the Format of the Configuration Data to Load. If you
include the format argument, it overrides the auto-detected
format.
The following playbook configures and commits two op scripts. In this case, the
load argument has the value 'set' because
the configuration data in lines uses Junos OS
set statement format.
---
- name: Load and commit configuration
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load configuration data using strings and commit
juniper.device.config:
load: set
lines:
- "set system scripts op file bgp.slax"
- "set system scripts op file bgp-neighbor.slax"
register: response
- name: Print the response
ansible.builtin.debug:
var: responseThe following playbook configures the same statements using
lines with configuration data in text format. In this case,
the example uses load: "merge".
---
- name: Load and commit configuration
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load configuration data using strings and commit
juniper.device.config:
load: merge
lines:
- |
system {
scripts {
op {
file bgp.slax;
file bgp-neighbor.slax;
}
}
}
register: response
- name: "Print the response"
ansible.builtin.debug:
var: responseHow to Load Configuration Data from a Local or Remote File
The juniper.device.config module enables you to load
configuration data from a file. The file can reside in one of the following
locations:
-
Ansible control node
-
Client device
-
FTP or HTTP URL that is reachable from the client device
When you load configuration data from a file, you must indicate the location of
the file and the format of the configuration data in the file. Supported
configuration data formats include text, Junos XML elements, Junos OS
set commands, and JSON. For information about loading files
containing Jinja2 templates, see How to Load Configuration Data Using a Jinja2 Template.
To specify the format, include the module's format parameter or
add the appropriate extension to the configuration data file. If you specify the
format parameter, it overrides the format indicated by the
file extension. For information about specifying the format, see How to Specify the Format of the Configuration Data to Load. When the configuration
data uses Junos XML format, you must enclose the data in the top-level
<configuration> tag.
You do not need to enclose configuration data that is formatted as text,
Junos OS set commands, or JSON in
<configuration-text>,
<configuration-set>, or
<configuration-json> tags as is required when
configuring the device directly within a NETCONF session.
Table 4 outlines the module parameters that you can include to specify the location of the file.
|
Module Parameter |
Description |
|---|---|
|
|
|
|
|
|
To load configuration data from a local file on the Ansible control node, set the
src argument to the absolute or relative path of the file
containing the configuration data. For example:
---
- name: Load and commit configuration
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load configuration from a local file and commit
juniper.device.config:
load: merge
src: "build_conf/{{ inventory_hostname }}/junos.conf"
register: response
- name: Print the response
ansible.builtin.debug:
var: responseTo load configuration data from a file on the Junos device or from an FTP or HTTP
URL, use the url parameter. Specify the path or URL of the file
to load. For example:
---
- name: Load and commit configuration
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load configuration from a remote file and commit
juniper.device.config:
load: merge
url: "/var/tmp/junos.conf"
register: response
- name: Print the response
ansible.builtin.debug:
var: responseThe value for url can be an absolute or relative local file
path, an FTP location, or an HTTP URL.
-
The file path for a local file on the target device has one of the following forms:
-
/path/filename—File on a mounted file system, either on the local flash disk or on hard disk.
-
a:filename or a:path/filename—File on the local drive. The default path is / (the root-level directory). The removable media can be in MS-DOS or UNIX (UFS) format.
-
-
The file path for a file on an FTP server has the following form:
ftp://username:password@hostname/path/filename -
The file path for a file on an HTTP server has the following form:
http://username:password@hostname/path/filename
In each case, the default value for the path variable is the home directory for the user. To specify an absolute path, the application starts the path with the characters %2F; for example, ftp://username:password@hostname/%2Fpath/filename.
How to Load Configuration Data Using a Jinja2 Template
The juniper.device.config module enables you to render
configuration data from a Jinja2 template file on the Ansible control node and
load and commit the configuration on a Junos device. Jinja is a template engine
for Python that enables you to generate documents from predefined templates. The
templates, which are text files in the desired language, provide flexibility
through the use of expressions and variables. You can create Junos OS
configuration data using Jinja2 templates in one of the supported configuration
formats, which includes ASCII text, Junos XML elements, Junos OS
set commands, and JSON. The Ansible module uses the Jinja2
template and a supplied dictionary of variables to render the configuration
data.
To load and commit configuration data using a Jinja2 template, include the
template and vars parameters in the
module’s argument list.
-
template—Path of the Jinja2 template file -
vars—Dictionary of keys and values that are required to render the Jinja2 template
You must also include the format parameter when the template’s
file extension does not indicate the format of the data. For information about
specifying the format, see How to Specify the Format of the Configuration Data to Load.
For example, the interfaces-mpls.j2 file contains the following Jinja2 template:
interfaces {
{% for item in interfaces %}
{{ item }} {
description "{{ description }}";
unit 0 {
family {{ family }};
}
} {% endfor %}
}
protocols {
mpls {
{% for item in interfaces %}
interface {{ item }};
{% endfor %}
}
rsvp {
{% for item in interfaces %}
interface {{ item }};
{% endfor %}
}
}
To use the juniper.device.config module to load the Jinja2
template, set the template argument to the path of the template
file. Define the variables required by the template in the vars
dictionary.
The following playbook uses the Jinja2 template and the vars
dictionary to render the configuration data. The format
parameter indicates the format of the configuration data in the template file.
The playbook loads and commits the configuration on the target host.
---
- name: Load and commit configuration
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load a configuration from a Jinja2 template and commit
juniper.device.config:
load: merge
template: "build_conf/templates/interfaces-mpls.j2"
format: text
vars:
interfaces: ["ge-1/0/1", "ge-1/0/2", "ge-1/0/3"]
description: "MPLS interface"
family: "mpls"
register: response
- name: Print the response
ansible.builtin.debug:
var: response
The module generates the following configuration data. The module loads the data into the candidate configuration on the device and commits it.
interfaces {
ge-1/0/1 {
description "MPLS interface";
unit 0 {
family mpls;
}
}
ge-1/0/2 {
description "MPLS interface";
unit 0 {
family mpls;
}
}
ge-1/0/3 {
description "MPLS interface";
unit 0 {
family mpls;
}
}
}
protocols {
mpls {
interface ge-1/0/1;
interface ge-1/0/2;
interface ge-1/0/3;
}
rsvp {
interface ge-1/0/1;
interface ge-1/0/2;
interface ge-1/0/3;
}
}
How to Load the Rescue Configuration
A rescue configuration enables you to define a known working configuration or a configuration with a known state that you can restore at any time. You use the rescue configuration when you need to revert to a known configuration or as a last resort if the device configuration and the backup configuration files become damaged beyond repair. When you create a rescue configuration, the device saves the most recently committed configuration as the rescue configuration.
The juniper.device.config module enables you to revert to an
existing rescue configuration on Junos devices. To load and commit the rescue
configuration on a device, include the module’s
rollback: rescue argument. For example:
---
- name: Revert to rescue configuration
hosts: dc1a
connection: local
gather_facts: no
tasks:
- name: Load and commit rescue configuration
juniper.device.config:
rollback: rescue
register: response
- name: Print response
ansible.builtin.debug:
var: responseHow to Roll Back the Configuration
Junos devices store a copy of the most recently committed configuration and up to 49 previous configurations, depending on the platform. You can roll back to any of the stored configurations. This feature is useful when configuration changes cause undesirable results and you want to revert to a known working configuration. Rolling back the configuration is similar to the process for making configuration changes on the device. However, instead of loading configuration data, you perform a rollback, which replaces the entire candidate configuration with a previously committed configuration.
The juniper.device.config module enables you to roll back to a
previously committed configuration on Junos devices. To roll back the
configuration and commit it, include the module’s rollback
argument, and specify the ID of the rollback configuration. Valid ID values are
0 (zero, for the most recently committed configuration) through one less than
the number of stored previous configurations (maximum is 49).
The following playbook first prompts for the rollback ID of the configuration to restore. The first task rolls back the configuration to the requested version and commits it. The second task prints the configuration differences to standard output.
---
- name: Roll back the configuration
hosts: dc1a
connection: local
gather_facts: no
vars_prompt:
- name: "ROLLBACK"
prompt: "Rollback ID of the configuration to restore"
private: no
tasks:
- name: Roll back the configuration and commit
juniper.device.config:
rollback: "{{ ROLLBACK }}"
register: response
- name: Print the configuration changes
ansible.builtin.debug:
var: response.diff_lines
user@ansible-cn:~/ansible$ ansible-playbook configuration-rollback.yaml
Rollback ID of the configuration to restore: 1
PLAY [Roll back the configuration] ********************************************
TASK [Roll back the configuration and commit] *********************************
changed: [dc1a.example.net]
TASK [Print the configuration changes] ***************************************
ok: [dc1a.example.net] => {
"response.diff_lines": [
"",
"[edit interfaces]",
"- ge-0/0/0 {",
"- unit 0 {",
"- family mpls;",
"- }",
"- }"
]
}
PLAY RECAP ********************************************************************
dc1a.example.net : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0How to Commit the Configuration
By default, when you use the juniper.device.config module to
modify the configuration, the module automatically performs a commit check and
commits the changes. To prevent the module from performing a commit check or
from committing the changes, set the check or
commit argument to false,
respectively.
You can also customize the commit operation with many of the same options that are available in the Junos OS CLI. Table 5 outlines the module arguments that you can use to specify different commit options.
|
Module Argument |
Description |
Default value for |
|---|---|---|
|
|
Perform a commit check or confirm a previous confirmed commit operation. |
|
|
|
Wait the specified number of seconds between the commit check and the commit operation. |
– |
|
|
Log a comment for that commit operation in the system log file and in the device’s commit history. |
– |
|
|
Commit the configuration changes or confirm a previous confirmed commit operation. |
|
|
|
Commit the configuration even if the candidate configuration has no changes. |
|
|
|
Synchronize and commit the configuration on all Routing Engines, even if the other Routing Engine has open configuration sessions or uncommitted configuration changes. |
|
|
|
Synchronize and commit the configuration on all Routing Engines. |
|
|
|
Require that a commit operation be confirmed within a specified amount of time after the initial commit. If you do not confirm the commit in the specified time, roll back to the previously committed configuration. Confirm the commit using either the
|
– |
|
|
Wait for completion of the operation using the specified value as the timeout. |
30 seconds |
Commit Comment
When you commit the configuration, you can include a brief comment to describe
the purpose of the committed changes. To log a comment describing the changes,
include the comment: "comment string"
argument with the message string.
Commit Check
By default, the juniper.device.config module executes both a
commit check and a commit operation. The check_commit_wait
argument defines the number of seconds to wait between the commit check and
commit operations. Include this argument when you need to provide sufficient
time for the device to complete the commit check operation and release the
configuration lock before initiating the commit operation. If the device
initiates the commit operation before the commit check operation releases its
lock on the configuration, the commit operation fails and the module issues a
CommitError.
Commit Empty Changes
By default, if the candidate configuration and the committed configuration have
no differences, the module does not commit the changes. To force a commit
operation even when no differences are present, include the
commit_empty_changes: true argument.
Commit Synchronize
If the device has dual Routing Engines, you can synchronize and commit the
configuration on both Routing Engines by including the
commit_sync: true argument. To force the
commit synchronize operation to succeed even if the other
Routing Engine has open configuration sessions or uncommitted configuration
changes, use the commit_force_sync: true argument. When you
include the commit_force_sync: true option, the device
terminates any configuration sessions on the other Routing Engine before
synchronizing and committing the configuration.
Commit Confirm
To require that a commit operation be confirmed within a specified amount of time
after the initial commit, include the
confirmed: minutes argument. If you
do not confirm the commit within the given time limit, the configuration
automatically rolls back to the previously committed configuration. The allowed
range is 1 through 65,535 minutes. The confirmed commit operation is useful for
verifying that a configuration change works correctly and does not prevent
management access to the device. If the change prevents access or causes other
errors, the automatic rollback to the previous configuration enables access to
the device after the rollback deadline passes. To confirm the commit operation,
invoke the juniper.device.config module with the
check: true or commit: true argument.
In the following playbook, the first task modifies the configuration, waits 10
seconds between the commit check and the commit operation, and requires that the
commit operation be confirmed within 5 minutes. It also logs a comment for the
commit. The second task issues a commit check operation to
confirm the commit. In a real-world scenario, you might perform validation tasks
after the initial commit and only execute the commit confirmation if the tasks
pass certain validation criteria.
---
- name: Load configuration and confirm within 5 minutes
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Load configuration. Wait 10 seconds between check and commit. Confirm within 5 min.
juniper.device.config:
load: merge
format: text
src: "build_conf/{{ inventory_hostname }}/junos.conf"
check_commit_wait: 10
confirmed: 5
comment: "updated using Ansible"
register: response
- name: Print the response
ansible.builtin.debug:
var: response
- name: Confirm the commit with a commit check
juniper.device.config:
check: true
diff: false
commit: false
register: response
- name: Print the response
ansible.builtin.debug:
var: responseHow to Ignore Warnings When Configuring Devices
The juniper.device.config module enables you to modify and
commit the configuration on Junos devices. In some cases, the RPC reply might
contain <rpc-error> elements with a severity level of
warning or higher that cause the module to raise an RpcError
exception. An RpcError exception can cause the load or commit
operation to fail.
In certain cases, it might be necessary or desirable to suppress the
RpcError exceptions that are raised in response to warnings
for load and commit operations. You can instruct the
juniper.device.config module to suppress
RpcError exceptions that are raised for warnings by
including the ignore_warning parameter in the module’s argument
list. The ignore_warning argument takes a Boolean, a string, or
a list of strings.
To instruct the module to ignore all warnings for load and commit operations
performed by the module, include the ignore_warning: true
argument. The following example ignores all warnings for load and commit
operations.
---
- name: Configure Device
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Configure op script
juniper.device.config:
config_mode: private
load: set
lines:
- "set system scripts op file bgp.slax"
ignore_warning: true
register: response
- name: Print the response
ansible.builtin.debug:
var: responseIf you include ignore_warning: true and all of the
<rpc-error> elements have a severity level of
warning, the application ignores all warnings and does not raise an
RpcError exception. However, any
<rpc-error> elements with higher severity levels will
still raise exceptions.
To instruct the module to ignore specific warnings, set the
ignore_warning argument to a string or a list of strings
containing the warnings to ignore. The following example ignores two specific
warnings:
---
- name: Configure Device
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Configure Junos device and ignore warnings
juniper.device.config:
config_mode: private
load: merge
src: "build_conf/{{ inventory_hostname }}/junos.conf"
ignore_warning:
- "Advertisement-interval is less than four times"
- "Chassis configuration for network services has been changed."
register: response
- name: Print the response
ansible.builtin.debug:
var: responseThe module suppresses RpcError exceptions if all of the
<rpc-error> elements have a severity level of warning
and each warning in the response matches one or more of the specified strings.
Example: Use Ansible to Configure Junos Devices
The juniper.device.config module enables you to manage the
configuration on Junos devices. This example uses the config module to
make configuration changes on a Junos device through NETCONF over SSH.
Requirements
This example uses the following hardware and software components:
-
Configuration management server running Ansible 2.17 or later with the
juniper.devicecollection installed -
Junos device with NETCONF enabled and a user account configured with appropriate permissions
-
SSH public/private key pair configured for the appropriate user on the Ansible controller and the Junos device
-
Existing Ansible inventory file with required hosts defined
Overview
This example presents an Ansible playbook that uses the
juniper.device.config module to enable a new op script in the
configuration of the target Junos devices. The configuration data file,
junos-config.conf, contains the relevant configuration data
formatted as text.
The playbook includes the Check NETCONF connectivity task, which
utilizes the ansible.builtin.wait_for Ansible module to try to
establish a NETCONF session with the target device using the NETCONF default port
(830). If the control node fails to establish a NETCONF session with a target device
during playbook execution, then it skips the remaining tasks in the play for that
device.
The playbook uses the juniper.device.file_copy module to copy the
new op script from the Ansible control node to the Junos device. The module
arguments specify the directory and filename of the script on the local device and
the destination directory on the remote device.
The task to configure the device executes the juniper.device.config
module provided that the NETCONF check was successful. The load:
"merge" argument loads the new configuration data into the candidate
configuration using a load merge operation. By default, the
config module commits configuration data on a device for
load and rollback operations. The module
arguments include the comment argument, which records a commit
comment in the device’s system log file and commit history.
Configuration
Create the Configuration Data File
Step-by-Step Procedure
To create the configuration data file that is used by the module:
Create a new file with the appropriate extension based on the format of the configuration data, which in this example is text.
Include the desired configuration changes in the file.
user@ansible-cn:~/ansible$ cat build_conf/dc1a.example.net/junos-config.conf system { scripts { op { file bgp.slax; } } }
Create the Ansible Playbook
Step-by-Step Procedure
To create a playbook that uses the config module to make
configuration changes on a Junos device:
Include the playbook boilerplate, which executes the modules locally.
--- - name: Load and commit configuration data on a Junos device hosts: dc1 connection: local gather_facts: no
(Optional) Create a task to verify NETCONF connectivity.
tasks: - name: Check NETCONF connectivity ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: 830 timeout: 5Create a task to copy the new op script to the device.
- name: Copy the op script to the device juniper.device.file_copy: action: put file: bgp.slax local_dir: scripts remote_dir: /var/db/scripts/opCreate the task to load the configuration onto the device and commit it.
- name: Merge configuration data from a file and commit juniper.device.config: load: "merge" src: "build_conf/{{ inventory_hostname }}/junos-config.conf" comment: "Configuring op script with Ansible" register: response(Optional) Create a task to print the response, which includes the configuration changes in diff format.
- name: Print the response ansible.builtin.debug: var: response
Results
On the Ansible control node, review the completed playbook. If the playbook does not display the intended code, repeat the instructions in this example to correct the playbook.
---
- name: Load and commit configuration data on a Junos device
hosts: dc1
connection: local
gather_facts: no
tasks:
- name: Check NETCONF connectivity
ansible.builtin.wait_for:
host: "{{ inventory_hostname }}"
port: 830
timeout: 5
- name: Copy the op script to the device
juniper.device.file_copy:
action: put
file: bgp.slax
local_dir: scripts
remote_dir: /var/db/scripts/op
- name: Merge configuration data from a file and commit
juniper.device.config:
load: "merge"
src: "build_conf/{{ inventory_hostname }}/junos-config.conf"
comment: "Configuring op script with Ansible"
register: response
- name: Print the response
ansible.builtin.debug:
var: responseExecute the Playbook
To execute the playbook:
-
Issue the
ansible-playbookcommand on the control node, and provide the playbook path and any desired options.user@ansible-cn:~/ansible$ ansible-playbook ansible-pb-junos-config.yaml PLAY [Load and commit configuration data on a Junos device] *************** TASK [Check NETCONF connectivity] ***************************************** ok: [dc1a.example.net] TASK [Copy the op script to the device] *********************************** changed: [dc1a.example.net] TASK [Merge configuration data from a file and commit] ******************** changed: [dc1a.example.net] TASK [Print the response] ************************************************* ok: [dc1a.example.net] => { "response": { "changed": true, "diff": { "prepared": "\n[edit system scripts op]\n+ file bgp.slax;\n" }, "diff_lines": [ "", "[edit system scripts op]", "+ file bgp.slax;" ], "failed": false, "file": "build_conf/dc1a.example.net/junos-config.conf", "msg": "Configuration has been: opened, loaded, checked, diffed, committed, closed." } } PLAY RECAP **************************************************************** dc1a.example.net : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Verification
Verify the Configuration
Purpose
Verify that the configuration was correctly updated on the Junos device.
Action
Review the Ansible playbook output to see whether the configuration task succeeded or failed. You can also log in to the Junos device and view the configuration, commit history, and log files to verify the configuration and commit, for example:
user@dc1a> show configuration system scripts
op {
file bgp.slax;
}user@dc1a> show system commit
0 2020-12-17 15:33:50 PST by user via netconf
Configuring op script with Ansible
user@dc1a> show log messages Dec 17 15:33:39 dc1a mgd[33444]: UI_COMMIT: User 'user' requested 'commit' operation (comment: Configuring op script with Ansible) Dec 17 15:33:57 dc1a mgd[33444]: UI_COMMIT_COMPLETED: commit complete
Troubleshoot Playbook Errors
- Troubleshoot Timeout Errors
- Troubleshoot Configuration Lock Errors
- Troubleshoot Configuration Change Errors
Troubleshoot Timeout Errors
Problem
The playbook generates a TimeoutExpiredError error message
and fails to update the device configuration.
ncclient.operations.errors.TimeoutExpiredError: ncclient timed out while waiting for an rpc reply
The default time for a NETCONF RPC to time out is 30 seconds. Large configuration changes might exceed this value causing the operation to time out before the configuration can be uploaded and committed.
Solution
To accommodate configuration changes that might require a commit time that is
longer than the default RPC timeout interval, set the module’s
timeout argument to an appropriate value and re-run the
playbook.
Troubleshoot Configuration Lock Errors
Problem
The playbook generates a LockError error message indicating
that the configuration cannot be locked. For example:
FAILED! => {"changed": false, "msg": "Unable to open the configuration in exclusive mode: LockError(severity: error, bad_element: None, message: configuration database modified)"}
or
FAILED! => {"changed": false, "msg": "Unable to open the configuration in exclusive mode: LockError(severity: error, bad_element: lock-configuration, message: permission denied)"}
A configuration lock error can occur for the following reasons:
-
Another user has an exclusive lock on the configuration.
-
Another user made changes to the configuration database but has not yet committed the changes.
-
The user executing the Ansible module does not have permissions to configure the device.
Solution
The LockError message string usually indicates the root
cause of the issue. If another user has an exclusive lock on the
configuration or has modified the configuration, wait until the lock is
released or the changes are committed, and execute the playbook again. If
the cause of the issue is that the user does not have permissions to
configure the device, either execute the playbook with a user who has the
necessary permissions, or if appropriate, configure the Junos device to give
the current user the necessary permissions to make the changes.
Troubleshoot Configuration Change Errors
Problem
The playbook generates a ConfigLoadError error message
indicating that the configuration cannot be modified, because permission is
denied.
FAILED! => {"changed": false, "msg": "Failure loading the configuraton: ConfigLoadError(severity: error, bad_element: scripts, message: error: permission denied)"}
This error message is generated when the user executing the Ansible module has permission to alter the configuration but does not have permission to alter the requested section of the configuration.
Solution
Either execute the playbook with a user who has the necessary permissions, or if appropriate, configure the Junos device to give the current user the necessary permissions to make the changes.