Use Ansible to Install Software on Junos Devices
Use the Juniper Networks Ansible modules to install software on Junos devices.
Use Ansible to Install Software
Juniper Networks provides an Ansible module that enables you to install or upgrade the software image on a Junos device. Table 1 outlines the module.
Content Set |
Module Name |
---|---|
|
The following sections discuss how to specify the software image location and the general software installation process and options when using the Ansible module to install software packages on Junos devices. They also discuss how to perform more specialized upgrade scenarios such as a VM host upgrade, a unified in-service software upgrade (unified ISSU), or a nonstop software upgrade (NSSU) on devices that support these features.
How to Specify the Software Image Location
When you use the juniper.device.software
module to install
software on Junos devices, you can download the software package to the Ansible
control node, and the module, by default, copies the package to the target
device before performing the installation. For mixed Virtual Chassis
environments, the software packages must reside on the Ansible control node. For
standalone devices or non-mixed Virtual Chassis environments, you can also
instruct the module to install a software image that already resides on the
target Junos device or resides at a URL that is reachable from the target
device.
Table 2 outlines the module arguments that you must set depending on the software
package location. The module must always include either the
local_package
, pkg_set
, or
remote_package
argument. The no_copy
argument defaults to false
, which instructs the module to copy
the software package from the specified location on the Ansible control node to
the target device.
Software Package Location |
|
|
|
---|---|---|---|
Ansible control node |
Omit or set to |
For standalone devices or non-mixed Virtual Chassis environments: Set |
(Optional) File path on the target device to which the software package is copied. The default directory is /var/tmp. If |
For mixed Virtual Chassis environments: Set |
– |
||
Remote Location |
– |
– |
URL from the perspective of the target Junos device from which the software package is installed. |
Target device |
Set to |
– |
File path on the target device where the software package must already reside. The default directory is /var/tmp. |
If the software package resides on the Ansible control node, include the argument that is appropriate for your installation:
-
local_package
—Install software on a standalone Junos device or on members in a non-mixed Virtual Chassis. The argument value is a single string specifying the absolute or relative path to the software image. -
pkg_set
—Install software on the members in a mixed Virtual Chassis. The argument value is a list of strings that specify the absolute or relative file paths of the software images, in no particular order, for the various Virtual Chassis members.
For example:
pkg_set: - 'software/jinstall-qfx-5-13.2X51-D35.3-domestic-signed.tgz' - 'software/jinstall-ex-4300-13.2X51-D35.3-domestic-signed.tgz'
By default, when you include the local_package
or
pkg_set
argument, the module copies any software packages
from the Ansible control node to the /var/tmp directory on
the target Junos device (individual device or Virtual Chassis primary device).
If you want to copy the local_package
image to a different
directory, define the remote_package
argument and specify the
target directory. If the remote_package
argument includes a
filename, the filenames of the local_package
and
remote_package
arguments must be identical, or the module
generates an error.
If the software package already resides on the target Junos device (individual
device or Virtual Chassis primary device), the module must include the
no_copy: true
argument as well the
remote_package
argument, which specifies the file path to
an existing software package on the target device. If
remote_package
does not specify a directory, the default is
/var/tmp.
If the software package resides at a location other than the Ansible control node
or target device, the module must include the remote_package
argument and specify the location of the software package. The value of
remote_package
is a URL from the perspective of the target
Junos device. For information about acceptable URL formats, see Format for Specifying Filenames and URLs in Junos OS CLI
Commands.
Installation Process Overview
To use Ansible to install a software package on a Junos device, execute the
software
module, and
provide any necessary arguments. For example:
--- - name: Perform a Junos OS software upgrade hosts: dc1 connection: local gather_facts: no tasks: - name: Upgrade Junos OS juniper.device.software: local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz" no_copy: false validate: true register: response - name: Print the response ansible.builtin.debug: var: response
When you execute the software
module, it performs the following
operations:
Once the software package is on the target device, whether downloaded there initially or copied over by the module, the module then performs the following operations:
Validates the configuration against the new package when the
validate
argument is set totrue
.Note:By default, the
software
module does not validate the software package or bundle against the existing configuration as a prerequisite to adding the software package. To ensure that the active configuration will work with the new software image, set thevalidate
argument totrue
.Installs the package on each individual Routing Engine, unless
all_re
is set tofalse
.Reboots each upgraded Routing Engine, unless the
reboot
argument is set tofalse
.
The software
module enables you to log the progress of the
installation by including the logfile
module argument. By
default, only messages of severity level WARNING or higher are logged. To log
messages of severity level INFO or higher, which is required to log messages for
the general installation process, execute the playbook with the
-v
or --verbose
command-line option.
How to Specify Timeout Values
The juniper.device.software
module performs operations over a
NETCONF session. The default time for a NETCONF RPC to time out is 30 seconds.
During the installation process, certain operations increase the RPC timeout
interval as follows:
-
Copying and installing the package on the device—1800 seconds (30 minutes)
-
Computing the checksum—300 seconds (5 minutes)
-
Performing a storage cleanup—300 seconds (5 minutes)
In some cases, the installation process, checksum calculation, or storage cleanup
might exceed these time intervals. You can change the timeout value for these
operations by setting the install_timeout
,
checksum_timeout
, and cleanfs_timeout
arguments to the required number of seconds in the module’s argument list. For
example:
- name: Upgrade Junos OS juniper.device.software: local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz" validate: true install_timeout: 2000 checksum_timeout: 420 cleanfs_timeout: 600
How to Specify Installation Options That Do Not Have an Equivalent Module Argument
When you use the juniper.device.software
module to install
software on a device, the module invokes the appropriate RPC for the included
installation arguments. For example, the module invokes the
<request-package-add>
RPC for standard Junos OS
installations, the <request-vmhost-package-add>
RPC for
VM host upgrades, the
<request-package-in-service-upgrade>
RPC for unified
ISSU scenarios, and so on.
The module supports explicit arguments for many of the installation options, for
example, the validate
option. The module also supports the
kwargs
argument, which enables you to include any
additional options that are supported by the RPC but which do not have an
equivalent module argument. The kwargs
argument takes a
dictionary of key/value pairs of additional supported options.
For the current list of options supported by the module, see the API reference documentation for the module. For a list of all available options for a specific RPC, see the documentation for the equivalent command or search for the RPC’s request tag in the Junos XML API Explorer.
You should only include installation options that are supported on the target Junos device for the given RPC.
In the following playbook, the software
module installs a new
software image on the target hosts. The module includes the
kwargs
argument with unlink: true
. This
argument, which removes the software package from the directory after a
successful upgrade, is equivalent to including the
<unlink/>
option in the
<request-package-add>
RPC.
--- - name: Perform a Junos OS software upgrade hosts: router1 connection: local gather_facts: no tasks: - name: Upgrade Junos OS juniper.device.software: local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz" kwargs: unlink: true register: response - name: Print the response ansible.builtin.debug: var: response
How to Perform a VM Host Upgrade
On devices that have Routing Engines with VM host support, Junos OS runs as a
virtual machine (VM) over a Linux-based host (VM host). A VM host upgrade
requires a VM Host installation package
(junos-vmhost-install-x.tgz) and
upgrades the host OS and compatible Junos OS. In the CLI, you perform the
upgrade using the request vmhost software add
operational mode
command, which corresponds to the
<request-vmhost-package-add>
RPC.
The juniper.device.software
module supports the vmhost:
true
argument for performing a VM host upgrade. When the argument
is present, the module performs the installation using the
<request-vmhost-package-add>
RPC.
The following playbook upgrades and reboots the Junos OS and host OS on the specified devices:
--- - name: Upgrade VM Hosts hosts: vm_hosts connection: local gather_facts: no tasks: - name: Perform a VM host upgrade juniper.device.software: local_package: "junos-vmhost-install-qfx-x86-64-18.1R1.9.tgz" vmhost: true register: response - name: Print the response ansible.builtin.debug: var: response
How to Perform a Unified ISSU or NSSU
The juniper.device.software
module supports performing a unified
in-service software upgrade (unified ISSU) or a nonstop software upgrade (NSSU)
on devices that support the feature and meet the necessary requirements. For
more information about the unified ISSU and NSSU features, see the software
documentation for your product.
The unified ISSU feature enables you to upgrade between two different Junos OS
releases with no disruption on the control plane and with minimal disruption of
traffic. To perform a unified in-service software upgrade, the
software
module must include the issu:
true
argument. For example:
--- - name: Perform a Junos OS software upgrade hosts: mx1 connection: local gather_facts: no tasks: - name: Perform a unified ISSU juniper.device.software: local_package: "junos-install-mx-x86-64-17.2R1.13.tgz" issu: true register: response - name: Print the response ansible.builtin.debug: var: response
The NSSU feature enables you to upgrade the Junos OS software running on a switch
or Virtual Chassis with redundant Routing Engines with minimal disruption to
network traffic. To perform a nonstop software upgrade, the
software
module must include the nssu:
true
argument. For example:
--- - name: Perform a Junos OS software upgrade hosts: ex1 connection: local gather_facts: no tasks: - name: Perform an NSSU juniper.device.software: local_package: "jinstall-ex-4300–17.3R1.10-signed.tgz" nssu: true register: response - name: Print the response ansible.builtin.debug: var: response
How to Install Software on an EX Series Virtual Chassis Member
Generally, when you upgrade a non-mixed EX Series Virtual Chassis, you follow the
installation process outlined in Installation Process Overview to upgrade the entire Virtual Chassis. However, there might
be times when you need to install software on specific member switches in the
Virtual Chassis. Starting with Release 1.0.3 of the
juniper.device
collection, you can install a software
package on individual member switches in a non-mixed EX Series Virtual Chassis.
To install software on specific members, include the member_id
argument and define a list of strings that specify the member IDs. The system
installs the software package from the Virtual Chassis primary device onto the
specified members.
The following Ansible playbook upgrades the software on member 0 and member 1 in the EX Series Virtual Chassis:
--- - name: Upgrade specific EX VC members hosts: ex_vc connection: local gather_facts: no vars: OS_version: "23.2R1.13" OS_package: "junos-install-ex-x86-64-23.2R1.13.tgz" pkg_dir: "software" log_dir: /var/log/ tasks: - name: Check NETCONF connectivity ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: 830 timeout: 5 - name: Install package on EX VC members juniper.device.software: version: "{{ OS_version }}" local_package: "{{ pkg_dir }}/{{ OS_package }}" member_id: ["0","1"] logfile: "{{ log_dir }}/software.log"
Example: Use Ansible to Install Software
This example uses the juniper.device.software
module to install a
software image on a Junos device.
Requirements
This example uses the following hardware and software components:
-
Configuration management server running Ansible 2.18 or later with the
juniper.device
collection 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 control node and Junos device
-
Existing Ansible inventory file with required hosts defined
Overview
This example presents an Ansible playbook that uses the
juniper.device.software
module to upgrade Junos OS on the
hosts in the specified inventory group. In this example, the software image
resides on the Ansible control node, and the module copies the image to the
target device before installing it. The module does not explicitly define a
host
argument, so the module operates on the default host,
which is {{ inventory_hostname }}
.
This playbook includes the Check NETCONF connectivity
task,
which utilizes the ansible.builtin.wait_for
module to try to
establish a NETCONF session with the Junos device using the default NETCONF port
830. If the control node fails to establish a NETCONF session with a device
during playbook execution, then it skips the remaining tasks in the play for
that device.
The Install Junos OS package
task executes the
software
module provided that the NETCONF check was
successful. The version
argument defines the desired Junos OS
version as it would be reported by the show version
command on
the Junos device. During playbook execution, the module first checks that the
requested version is not already installed on the device. If the requested
version is different from the currently installed version, the module installs
the requested version.
The local_package
argument defines the path of the Junos OS
software package on the Ansible control node. During the installation, the
module performs a storage cleanup operation on the target device, copies the
software image to the /var/tmp directory on the device,
verifies the file’s checksum, validates the new software against the active
configuration, and then installs the software on each Routing Engine on the
target host. By default, the software
module reboots each
Routing Engine after the installation completes; however, this task explicitly
sets reboot: true
for clarity.
The task stores the module result in the response
variable and
notifies one handler. If the user does not execute the playbook using check
mode, the wait_reboot
handler then tries to establish a session
with the device to verify that the device is back online. The
wait_time
variable defines the length of time that the
control node attempts to reconnect with the device.
This example includes the logfile
parameter to log the progress
of the installation. This is important for debugging purposes should the
installation fail as well as for logging the dates and times of installations on
the devices. The user executing the playbook must have permissions to write to
the specified log file. By default, only messages of severity level WARNING or
higher are logged. In this example, the playbook is executed with the
-v
option to log messages of severity level INFO or higher
to monitor the installation.
Configuration
Creating the Ansible Playbook
To create a playbook that uses the juniper.device.software
module to install a software image on a Junos device:
-
Include the boilerplate for the playbook and this play, which executes the modules locally.
--- - name: Install Junos OS hosts: mx1 connection: local gather_facts: no
-
Define or import any necessary variables, which for this example, includes the desired Junos OS version and the path to the new image, among others.
vars: OS_version: "23.4R1.9" OS_package: "junos-install-mx-x86-64-23.4R1.9.tgz" pkg_dir: "software" log_dir: "{{ playbook_dir }}" netconf_port: 830 wait_time: 3600
-
(Optional) Create a task to verify NETCONF connectivity.
tasks: - name: Check NETCONF connectivity ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: "{{ netconf_port }}" timeout: 5
-
Create the task to install the Junos OS package on the device and notify the handler.
- name: Install Junos OS package juniper.device.software: version: "{{ OS_version }}" local_package: "{{ pkg_dir }}/{{ OS_package }}" reboot: true validate: true logfile: "{{ log_dir }}/software.log" register: response notify: - wait_reboot
-
(Optional) Create a task to print the module response.
- name: Print response ansible.builtin.debug: var: response
-
Create the handler that verifies that the device comes back online after rebooting.
The handler name should be the same as that referenced in the installation task.
handlers: - name: wait_reboot ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: "{{ netconf_port }}" timeout: "{{ wait_time }}" when: not response.check_mode
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: Install Junos OS hosts: mx1 connection: local gather_facts: no vars: OS_version: "23.4R1.9" OS_package: "junos-install-mx-x86-64-23.4R1.9.tgz" pkg_dir: "software" log_dir: "{{ playbook_dir }}" netconf_port: 830 wait_time: 3600 tasks: - name: Check NETCONF connectivity ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: "{{ netconf_port }}" timeout: 5 - name: Install Junos OS package juniper.device.software: version: "{{ OS_version }}" local_package: "{{ pkg_dir }}/{{ OS_package }}" reboot: true validate: true logfile: "{{ log_dir }}/software.log" register: response notify: - wait_reboot - name: Print response ansible.builtin.debug: var: response handlers: - name: wait_reboot ansible.builtin.wait_for: host: "{{ inventory_hostname }}" port: "{{ netconf_port }}" timeout: "{{ wait_time }}" when: not response.check_mode
Execute the Playbook
To execute the playbook:
-
Issue the
ansible-playbook
command on the control node, and provide the playbook path and any desired options.user@ansible-cn:~/ansible$ ansible-playbook -v ansible-pb-junos-install-os.yaml Using /etc/ansible/ansible.cfg as config file PLAY [Install Junos OS] **************************************************** TASK [Check NETCONF connectivity] ****************************************** ok: [mx1a.example.com] => {"changed": false, "elapsed": 0, "match_groupdict": {}, "match_groups": [], "path": null, "port": 830, "search_regex": null, "state": "started"} TASK [Install Junos OS package] ******************************************** changed: [mx1a.example.com] => {"changed": true, "check_mode": false, "msg": "Package /home/user/ansible/software/junos-install-mx-x86-64-23.4R1.9.tgz successfully installed. Response from device is: \nVerified junos-install-mx-x86-64-23.4R1.9 signed by PackageProductionECP256_2023 method ECDSA256+SHA256\n [...output truncated...] NOTICE: 'pending' set will be activated at next reboot... Reboot successfully initiated. Reboot message: Shutdown NOW! [pid 79385]"} TASK [Print response] ****************************************************** ok: [mx1a.example.com] => { "response": { "changed": true, "check_mode": false, "failed": false, "msg": "Package /home/user/ansible/software/junos-install-mx-x86-64-23.4R1.9.tgz successfully installed. Response from device is: \nVerified junos-install-mx-x86-64-23.4R1.9 signed by PackageProductionECP256_2023 method ECDSA256+SHA256\nVerified auto-snapshot signed by PackageProductionECP256_2023 method ECDSA256+SHA256\n [...output truncated...] NOTICE: 'pending' set will be activated at next reboot... Reboot successfully initiated. Reboot message: Shutdown NOW! [pid 79385]" } } RUNNING HANDLER [wait_reboot] ********************************************** ok: [mx1a.example.com] => {"changed": false, "elapsed": 250, "match_groupdict": {}, "match_groups": [], "path": null, "port": 830, "search_regex": null, "state": "started"} PLAY RECAP ***************************************************************** mx1a.example.com : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Verification
Verify the Installation
Purpose
Verify that the software installation was successful.
Action
The playbook output should indicate any failed tasks. However, you can also review the contents of the log file defined in the playbook for details about the installation. Sample log file output is shown here. Some output has been omitted for brevity.
2024-08-23 22:20:49,455 - ncclient.transport.ssh - INFO - Connected (version 2.0, client OpenSSH_7.9) 2024-08-23 22:20:52,950 - ncclient.transport.ssh - INFO - Authentication (publickey) successful! ... 2024-08-23 22:21:00,770 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] computing checksum on local package: /home/user/ansible/software/junos-install-mx-x86-64-23.4R1.9.tgz 2024-08-23 22:21:08,070 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] cleaning filesystem ... ... 2024-08-23 22:21:08,329 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] before copy, computing checksum on remote package: /var/tmp/junos-install-mx-x86-64-23.4R1.9.tgz ... 2024-08-23 22:21:08,491 - paramiko.transport - INFO - Connected (version 2.0, client OpenSSH_7.9) 2024-08-23 22:21:08,958 - paramiko.transport - INFO - Authentication (publickey) successful! 2024-08-23 22:21:16,846 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 363528192 / 3635202890 (10%) 2024-08-23 22:21:24,405 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 727056384 / 3635202890 (20%) 2024-08-23 22:21:31,966 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 1090568192 / 3635202890 (30%) 2024-08-23 22:21:39,652 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 1454096384 / 3635202890 (40%) 2024-08-23 22:21:47,631 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 1817608192 / 3635202890 (50%) 2024-08-23 22:21:55,343 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 2181136384 / 3635202890 (60%) 2024-08-23 22:22:02,878 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 2544648192 / 3635202890 (70%) 2024-08-23 22:22:11,395 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 2908176384 / 3635202890 (80%) 2024-08-23 22:22:19,949 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 3271688192 / 3635202890 (90%) 2024-08-23 22:22:27,522 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] b'junos-install-mx-x86-64-23.4R1.9.tgz': 3635202890 / 3635202890 (100%) 2024-08-23 22:22:27,533 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] after copy, computing checksum on remote package: /var/tmp/junos-install-mx-x86-64-23.4R1.9.tgz ... 2024-08-23 22:22:44,891 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] checksum check passed. 2024-08-23 22:22:44,892 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] validating software against current config, please be patient ... ... 2024-08-23 22:27:52,538 - ncclient.transport.ssh - INFO - [host mx1a.example.com session-id 27526] Received message from host 2024-08-23 22:27:52,542 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] software validate package-result: 0 Output: Verified junos-install-mx-x86-64-23.4R1.9 signed by PackageProductionECP256_2023 method ECDSA256+SHA256 Adding junos-mx-x86-64-23.4R1.9 ... ... Validating against /config/juniper.conf.gz mgd: commit complete Validation succeeded 2024-08-23 22:27:52,542 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] installing software on RE0 ... please be patient ... ... 2024-08-23 22:30:57,510 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] software pkgadd package-result: 0 Output: Verified junos-install-mx-x86-64-23.4R1.9 signed by PackageProductionECP256_2023 method ECDSA256+SHA256 ... NOTICE: 'pending' set will be activated at next reboot... 2024-08-23 22:30:57,510 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] installing software on RE1 ... please be patient ... ... 2024-08-23 22:34:30,228 - jnpr.ansible_module.juniper.device.software - INFO - [mx1a.example.com] software pkgadd package-result: 0 Output: Pushing /var/tmp/junos-install-mx-x86-64-23.4R1.9.tgz to re1:/var/tmp/junos-install-mx-x86-64-23.4R1.9.tgz Verified junos-install-mx-x86-64-23.4R1.9 signed by PackageProductionECP256_2023 method ECDSA256+SHA256 ... NOTICE: 'pending' set will be activated at next reboot... ... 2024-08-23 22:34:30,732 - ncclient.operations.rpc - INFO - [host mx1a.example.com session-id 27526] Requesting 'CloseSession'
Meaning
The log file contents indicate that the image was successfully copied and installed on both Routing Engines on the target device.