0% found this document useful (0 votes)
96 views

Junos Ansible PDF

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
96 views

Junos Ansible PDF

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 192

®

Junos OS

Ansible for Junos OS Developer Guide

Published
2019-12-16
ii

Juniper Networks, Inc.


1133 Innovation Way
Sunnyvale, California 94089
USA
408-745-2000
www.juniper.net

Juniper Networks, the Juniper Networks logo, Juniper, and Junos are registered trademarks of Juniper Networks, Inc. in
the United States and other countries. All other trademarks, service marks, registered marks, or registered service marks
are the property of their respective owners.

Juniper Networks assumes no responsibility for any inaccuracies in this document. Juniper Networks reserves the right
to change, modify, transfer, or otherwise revise this publication without notice.

®
Junos OS Ansible for Junos OS Developer Guide
Copyright © 2019 Juniper Networks, Inc. All rights reserved.

The information in this document is current as of the date on the title page.

YEAR 2000 NOTICE

Juniper Networks hardware and software products are Year 2000 compliant. Junos OS has no known time-related
limitations through the year 2038. However, the NTP application is known to have some difficulty in the year 2036.

END USER LICENSE AGREEMENT

The Juniper Networks product that is the subject of this technical documentation consists of (or is intended for use with)
Juniper Networks software. Use of such software is subject to the terms and conditions of the End User License Agreement
(“EULA”) posted at https://support.juniper.net/support/eula/. By downloading, installing or using such software, you
agree to the terms and conditions of that EULA.
iii

Table of Contents
About the Documentation | ix

Documentation and Release Notes | ix

Documentation Conventions | ix

Documentation Feedback | xii

Requesting Technical Support | xii

Self-Help Online Tools and Resources | xiii

Creating a Service Request with JTAC | xiii

1 Disclaimer
Ansible for Junos OS Disclaimer | 17

2 Ansible Overview
Understanding Ansible for Junos OS | 21

Ansible for Junos OS Overview | 21

Benefits of Ansible and Ansible for Junos OS | 22

Additional Resources | 22

Understanding the Ansible for Junos OS Modules | 23

Ansible for Junos OS Modules Overview | 23

Ansible Core Modules for Junos OS | 25

Ansible Galaxy Modules for Junos OS | 26

Understanding the Ansible Inventory File When Managing Devices Running


Junos OS | 28

Creating and Executing Ansible Playbooks to Manage Devices Running Junos OS | 30

Creating a Playbook | 31

Executing a Playbook | 34
iv

3 Installing Ansible for Junos OS


Ansible for Junos OS Server Requirements | 37

Installing Ansible, the Juniper.junos Role, and Dependencies | 37

Using the Ansible for Junos OS Docker Image | 38

Setting up Ansible for Junos OS Managed Nodes | 39

Configuring Telnet Service on Devices Running Junos OS | 40

Enabling NETCONF on Devices Running Junos OS | 41

Satisfying Requirements for SSHv2 Connections | 41

4 Using Ansible to Connect to Devices Running Junos OS


Connecting to Devices Running Junos OS Using Ansible | 45

Connection Methods Overview | 45

Connecting to a Device Using NETCONF over SSH | 46

Connecting to a Device Using Telnet | 47

Connecting to a Device Using a Serial Console Connection | 48

Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50

Defining Connection and Authentication Options | 51

Understanding the Default Values for the Ansible Galaxy Modules for Junos OS | 52

Authenticating the User Using SSH Keys | 54

Authenticating the User Using a Playbook or Command-Line Password Prompt | 57

Authenticating the User Using an Ansible Vault-Encrypted File | 59

5 Using Ansible to Manage Device Operations


Using Ansible to Retrieve Facts from Devices Running Junos OS | 65

Using Ansible to Execute Commands and RPCs on Devices Running Junos OS | 67

Executing Commands with the juniper_junos_command Module | 68

Executing RPCs with the juniper_junos_rpc Module | 69

Understanding the Module Response | 71

Specifying the Format for the Command or RPC Output | 72


v

Saving the Command or RPC Output to a File | 73

Using Ansible with Junos PyEZ Tables to Retrieve Operational Information from Devices
Running Junos OS | 76

Understanding the juniper_junos_table Module and Junos PyEZ Tables | 77

Using the juniper_junos_table Module with Junos PyEZ Tables | 77

Specifying RPC Arguments | 80

Using Ansible to Install Software on Devices Running Junos OS | 82

Using Ansible to Install Software | 82

Specifying the Software Image Location | 83

Installation Process Overview | 84

Specifying Installation Options That Do Not Have an Equivalent Module Argument | 86

Performing ISSU or NSSU | 87

Example: Using Ansible to Install Software | 88

Using Ansible to Halt, Reboot, or Shut Down Devices Running Junos OS | 97

Using Ansible to Halt, Reboot, or Shut Down Devices | 98

Example: Using Ansible to Reboot Devices | 101

Using Ansible to Restore a Device Running Junos OS to the Factory-Default


Configuration Settings | 107

Using Ansible to Restore the Factory-Default Configuration Settings | 108

Example: Using Ansible to Restore the Factory-Default Configuration Settings | 109

Using Junos Snapshot Administrator in Python (JSNAPy) in Ansible Playbooks | 116

juniper_junos_jsnapy Module Overview | 117

Taking and Comparing Snapshots | 120

Performing Snapcheck Operations | 123

Understanding the juniper_junos_jsnapy Module Output | 124

Enabling the jsnapy Callback Plugin | 126

Example: Using the juniper_junos_jsnapy Module to Perform a JSNAPy Snapcheck


Operation | 127

6 Using Ansible to Manage the Configuration


Using Ansible to Retrieve or Compare Junos OS Configurations | 149

Specifying the Source of the Configuration Data to Return | 150

Specifying the Format of the Configuration Data to Return | 150


vi

Specifying the Scope of the Configuration Data to Return | 151

Specifying Options That Do Not Have an Equivalent Module Argument | 153

Saving Retrieved Configuration Data To a File | 154

Comparing the Active Configuration to a Previous Configuration | 155

Using Ansible to Configure Devices Running Junos OS | 158

juniper_junos_config Module Overview | 159

Specifying the Configuration Mode | 160

Specifying the Load Action | 162

Specifying the Format of the Configuration Data to Load | 162

Loading Configuration Data as Strings | 163

Loading Configuration Data from a Local or Remote File | 165

Loading Configuration Data Using a Jinja2 Template | 167

Loading the Rescue Configuration | 170

Rolling Back the Configuration | 171

Committing the Configuration | 172

Ignoring Warnings When Configuring Devices | 175

Example: Using Ansible to Configure Devices | 176

7 Troubleshooting Ansible for Junos OS


Troubleshooting Junos Pyez (junos-eznc) Install Errors for Ansible Modules | 187

Troubleshooting Ansible Role and Module Errors When Managing Devices Running
Junos OS | 188

Troubleshooting Ansible Connection Errors When Managing Devices Running


Junos OS | 190

Troubleshooting Failed or Invalid Connection Errors | 190

Troubleshooting Unknown Host Errors | 191

Troubleshooting Refused Connection Errors | 192

Troubleshooting Ansible Authentication Errors When Managing Devices Running


Junos OS | 193

Troubleshooting Ansible Errors When Configuring Devices Running Junos OS | 194

Troubleshooting Configuration Timeout Errors | 195

Troubleshooting Configuration Lock Errors | 195

Troubleshooting Configuration Change Errors | 196


vii

Troubleshooting Commit Errors | 197


ix

About the Documentation

IN THIS SECTION

Documentation and Release Notes | ix

Documentation Conventions | ix

Documentation Feedback | xii

Requesting Technical Support | xii

Use this guide to automate the provisioning and management of devices running Junos OS with Ansible
software.

Documentation and Release Notes

®
To obtain the most current version of all Juniper Networks technical documentation, see the product
documentation page on the Juniper Networks website at https://www.juniper.net/documentation/.

If the information in the latest release notes differs from the information in the documentation, follow the
product Release Notes.

Juniper Networks Books publishes books by Juniper Networks engineers and subject matter experts.
These books go beyond the technical documentation to explore the nuances of network architecture,
deployment, and administration. The current list can be viewed at https://www.juniper.net/books.

Documentation Conventions

Table 1 on page x defines notice icons used in this guide.


x

Table 1: Notice Icons

Icon Meaning Description

Informational note Indicates important features or instructions.

Caution Indicates a situation that might result in loss of data or hardware


damage.

Warning Alerts you to the risk of personal injury or death.

Laser warning Alerts you to the risk of personal injury from a laser.

Tip Indicates helpful information.

Best practice Alerts you to a recommended use or implementation.

Table 2 on page x defines the text and syntax conventions used in this guide.

Table 2: Text and Syntax Conventions

Convention Description Examples

Bold text like this Represents text that you type. To enter configuration mode, type
the configure command:

user@host> configure

Fixed-width text like this Represents output that appears on user@host> show chassis alarms
the terminal screen.
No alarms currently active

Italic text like this • Introduces or emphasizes important • A policy term is a named structure
new terms. that defines match conditions and
• Identifies guide names. actions.

• Identifies RFC and Internet draft • Junos OS CLI User Guide


titles. • RFC 1997, BGP Communities
Attribute
xi

Table 2: Text and Syntax Conventions (continued)

Convention Description Examples

Italic text like this Represents variables (options for Configure the machine’s domain
which you substitute a value) in name:
commands or configuration
[edit]
statements.
root@# set system domain-name
domain-name

Text like this Represents names of configuration • To configure a stub area, include
statements, commands, files, and the stub statement at the [edit
directories; configuration hierarchy protocols ospf area area-id]
levels; or labels on routing platform hierarchy level.
components. • The console port is labeled
CONSOLE.

< > (angle brackets) Encloses optional keywords or stub <default-metric metric>;
variables.

| (pipe symbol) Indicates a choice between the broadcast | multicast


mutually exclusive keywords or
(string1 | string2 | string3)
variables on either side of the symbol.
The set of choices is often enclosed
in parentheses for clarity.

# (pound sign) Indicates a comment specified on the rsvp { # Required for dynamic MPLS
same line as the configuration only
statement to which it applies.

[ ] (square brackets) Encloses a variable for which you can community name members [
substitute one or more values. community-ids ]

Indention and braces ( { } ) Identifies a level in the configuration [edit]


hierarchy. routing-options {
static {
; (semicolon) Identifies a leaf statement at a route default {
configuration hierarchy level. nexthop address;
retain;
}
}
}

GUI Conventions
xii

Table 2: Text and Syntax Conventions (continued)

Convention Description Examples

Bold text like this Represents graphical user interface • In the Logical Interfaces box, select
(GUI) items you click or select. All Interfaces.
• To cancel the configuration, click
Cancel.

> (bold right angle bracket) Separates levels in a hierarchy of In the configuration editor hierarchy,
menu selections. select Protocols>Ospf.

Documentation Feedback

We encourage you to provide feedback so that we can improve our documentation. You can use either
of the following methods:

• Online feedback system—Click TechLibrary Feedback, on the lower right of any page on the Juniper
Networks TechLibrary site, and do one of the following:

• Click the thumbs-up icon if the information on the page was helpful to you.

• Click the thumbs-down icon if the information on the page was not helpful to you or if you have
suggestions for improvement, and use the pop-up form to provide feedback.

• E-mail—Send your comments to [email protected]. Include the document or topic name,


URL or page number, and software version (if applicable).

Requesting Technical Support

Technical product support is available through the Juniper Networks Technical Assistance Center (JTAC).
If you are a customer with an active Juniper Care or Partner Support Services support contract, or are
xiii

covered under warranty, and need post-sales technical support, you can access our tools and resources
online or open a case with JTAC.

• JTAC policies—For a complete understanding of our JTAC procedures and policies, review the JTAC User
Guide located at https://www.juniper.net/us/en/local/pdf/resource-guides/7100059-en.pdf.

• Product warranties—For product warranty information, visit https://www.juniper.net/support/warranty/.

• JTAC hours of operation—The JTAC centers have resources available 24 hours a day, 7 days a week,
365 days a year.

Self-Help Online Tools and Resources

For quick and easy problem resolution, Juniper Networks has designed an online self-service portal called
the Customer Support Center (CSC) that provides you with the following features:

• Find CSC offerings: https://www.juniper.net/customers/support/

• Search for known bugs: https://prsearch.juniper.net/

• Find product documentation: https://www.juniper.net/documentation/

• Find solutions and answer questions using our Knowledge Base: https://kb.juniper.net/

• Download the latest versions of software and review release notes:


https://www.juniper.net/customers/csc/software/

• Search technical bulletins for relevant hardware and software notifications:


https://kb.juniper.net/InfoCenter/

• Join and participate in the Juniper Networks Community Forum:


https://www.juniper.net/company/communities/

• Create a service request online: https://myjuniper.juniper.net

To verify service entitlement by product serial number, use our Serial Number Entitlement (SNE) Tool:
https://entitlementsearch.juniper.net/entitlementsearch/

Creating a Service Request with JTAC

You can create a service request with JTAC on the Web or by telephone.

• Visit https://myjuniper.juniper.net.

• Call 1-888-314-JTAC (1-888-314-5822 toll-free in the USA, Canada, and Mexico).

For international or direct-dial options in countries without toll-free numbers, see


https://support.juniper.net/support/requesting-support/.
1 CHAPTER

Disclaimer

Ansible for Junos OS Disclaimer | 17


17

Ansible for Junos OS Disclaimer

Use of the Ansible for Junos OS software implies acceptance of the terms of this disclaimer, in addition
to any other licenses and terms required by Juniper Networks.

Juniper Networks is willing to make the Ansible for Junos OS software available to you only upon the
condition that you accept all of the terms contained in this disclaimer. Please read the terms and conditions
of this disclaimer carefully.

The Ansible for Junos OS software is provided as is. Juniper Networks makes no warranties of any kind
whatsoever with respect to this software. All express or implied conditions, representations and warranties,
including any warranty of non-infringement or warranty of merchantability or fitness for a particular
purpose, are hereby disclaimed and excluded to the extent allowed by applicable law.

In no event will Juniper Networks be liable for any direct or indirect damages, including but not limited to
lost revenue, profit or data, or for direct, special, indirect, consequential, incidental or punitive damages
however caused and regardless of the theory of liability arising out of the use of or inability to use the
software, even if Juniper Networks has been advised of the possibility of such damages.
2 CHAPTER

Ansible Overview

Understanding Ansible for Junos OS | 21

Understanding the Ansible for Junos OS Modules | 23

Understanding the Ansible Inventory File When Managing Devices Running


Junos OS | 28

Creating and Executing Ansible Playbooks to Manage Devices Running Junos OS | 30


21

Understanding Ansible for Junos OS

IN THIS SECTION

Ansible for Junos OS Overview | 21

Benefits of Ansible and Ansible for Junos OS | 22

Additional Resources | 22

Ansible for Junos OS Overview

Ansible is an IT automation framework that is used for infrastructure configuration management. Ansible
supports automating the network infrastructure in addition to the compute and cloud infrastructure. The
Juniper Networks Ansible for Junos OS library enables you to use Ansible to accelerate the deployment
and more easily manage and configure devices running Junos OS in your network. You can use Ansible to
perform specific operational and configuration tasks on devices running Junos OS, including retrieving
information, managing the configuration, installing and upgrading Junos OS, and resetting, rebooting, or
shutting down managed devices.

Ansible comes in several varieties. You can use the following to manage devices running Junos OS:

• Ansible Core—Free, open-source, base version of Ansible

• Red Hat Ansible Tower—Commercial application that is a superset of Ansible Core with additional
features such as a visual dashboard, role-based access control, job scheduling, and graphical inventory
management

• AWX—Open-source upstream project for Ansible Tower

Ansible uses a client-server architecture. You install the Ansible software on the control machine, or server,
which is a Linux or BSD host that manages one or more nodes. Ansible uses an agentless architecture and
thus does not require installing any Ansible-specific software on the managed nodes. Although Ansible
typically requires Python on the managed nodes, it is not required when managing devices running Junos OS.
Instead, Ansible for Junos OS requires all tasks to run locally on the Ansible server and uses NETCONF
and the Junos XML API to interface with managed devices running Junos OS.

Ansible modules model specific resources on managed nodes and ensure that the resource is in a specific
state. Ansible typically uses a push model in which the server sends state information to the managed
nodes on demand. The managed node executes the job and returns the result to the server. In general,
Ansible modules are idempotent such that executing the same playbook or operation multiple times yields
the same result, because the modules only apply a change if it’s required.
22

Ansible is written in Python, but it uses simple YAML syntax to express automation jobs. Thus, Ansible
users can get started quickly, because they do not require extensive knowledge of Python to use Ansible.
Ansible also leverages the Jinja2 templating language to enable dynamic expressions and access to variables.

Benefits of Ansible and Ansible for Junos OS

• Use a simple, easy-to-learn syntax

• Reduce the time to deploy new network devices and applications

• Increase operational efficiency by automating tasks and reducing the manual configuration and
management of devices

• Provide an efficient and scalable solution for managing large numbers of devices

• Improve change management processes

• Minimize risk and errors through standardization

Additional Resources

This documentation assumes that the reader is familiar with the Ansible framework. For more information
about Ansible, including supported operating systems and installation instructions, see the Ansible website
at https://www.ansible.com.

For more information about the Ansible for Junos OS library and related resources, see:

• Ansible for Junos OS GitHub repository at https://github.com/Juniper/ansible-junos-stdlib/

• Ansible for Junos OS module overview: “Understanding the Ansible for Junos OS Modules” on page 23

• Documentation for the Ansible core modules for Junos OS at


https://docs.ansible.com/ansible/list_of_network_modules.html#junos

• Documentation for the Ansible Galaxy modules for Junos OS at


https://junos-ansible-modules.readthedocs.org/

• Juniper.junos role on the Ansible Galaxy website at https://galaxy.ansible.com/Juniper/junos/

• Ansible for Junos OS and Junos PyEZ Google Groups forum at


https://groups.google.com/group/junos-python-ez

RELATED DOCUMENTATION
23

Understanding the Ansible for Junos OS Modules | 23


Ansible for Junos OS Server Requirements | 37
Setting up Ansible for Junos OS Managed Nodes | 39
Creating and Executing Ansible Playbooks to Manage Devices Running Junos OS | 30

Understanding the Ansible for Junos OS Modules

IN THIS SECTION

Ansible for Junos OS Modules Overview | 23

Ansible Core Modules for Junos OS | 25

Ansible Galaxy Modules for Junos OS | 26

Ansible for Junos OS Modules Overview

Ansible is an IT automation framework that is used for infrastructure configuration management. An Ansible
module models a specific resource on a managed node and ensures that the resource is in a specific state.
You can execute individual modules on remote hosts to perform ad-hoc tasks, or you can execute modules
through playbooks.

Ansible and Juniper Networks provide collections of Ansible modules that you can use to perform
operational and configuration tasks on devices running Junos OS. Starting in Ansible Release 2.1, Ansible
natively includes a number of core modules that can be used to manage devices running Junos OS. In
addition, Juniper Networks provides a collection of modules in the Juniper.junos role, which is hosted on
the Ansible Galaxy website . Both the Ansible core modules and Ansible Galaxy modules for Junos OS can
coexist on the same platform. For brevity, references to Ansible for Junos OS modules include both the
Ansible core and Ansible Galaxy modules for Junos OS.

Typically, the control machine sends a module to a managed node, where it is executed and then removed.
In this scenario, the managed nodes must have the ability to execute the Ansible modules. Generally,
Python is required on the managed nodes, because most Ansible modules are written in Python.
24

Ansible for Junos OS modules do not require Python on the managed nodes. In contrast to the typical
operation, you execute Ansible for Junos OS modules locally on the Ansible server, and the modules use
NETCONF and the Junos XML API to interface with managed nodes. This method of execution enables
you to use Ansible to manage any supported device running Junos OS. Figure 1 on page 24 illustrates the
communication between the Ansible control machine and a managed device running Junos OS.

Figure 1: Ansible Communication with Devices Running Junos OS

Ansible Control Machine

Ansible Orchestration Engine

Playbooks Python

Module
Modules Execute Results
Repository

Inventory

RPC
RPCs
Responses
NETCONF NETCONF

g200220
Managed Node Running Junos OS

To run Ansible modules locally on the control machine, include --connection=local when executing individual
modules, or include connection: local in your Ansible playbook. If a playbook uses the Juniper.junos
modules, the playbook must also include the Juniper.junos role.

For example, the following command executes the junos_facts Ansible core module to retrieve device
facts from hosts in inventory group dc1.

user@host$ ansible --connection=local -i hosts.ini dc1 -m junos_facts

The following sample playbook executes the juniper_junos_facts module, which is part of the Juniper.junos
role, to retrieve the device facts and save them to a file.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
25

tasks:
- name: Retrieve facts from device running Junos OS
juniper_junos_facts:
host: "{{ inventory_hostname }}"
savedir: "{{ playbook_dir }}"
- name: Print version
debug:
var: junos.version

You can execute Ansible for Junos OS modules using any user account that has access to the managed
device running Junos OS. When you execute Ansible modules, Junos OS user account access privileges
are enforced, and the class configured for the Junos OS user account determines the permissions. Thus,
if a user executes a module that loads configuration changes onto a device, the user must have permissions
to change the relevant portions of the configuration.

Ansible Core Modules for Junos OS

Starting in Ansible Release 2.1, the Ansible core modules for Junos OS are available as part of the Ansible
software. Table 3 on page 25 summarizes the core modules. For the most current list, documentation, and
usage examples for the Ansible core modules for Junos OS, see
https://docs.ansible.com/ansible/latest/list_of_network_modules.html#junos.

Table 3: Ansible Core Modules for Junos OS

Module Description

junos_banner Manage multiline banners on devices running Junos OS.

junos_command Execute commands on devices running Junos OS.

junos_config Manage configurations on devices running Junos OS.

junos_facts Retrieve device-specific information from the remote host.

junos_interface Configure physical interface properties on devices running Junos OS.

junos_l3_interface Configure logical interfaces on devices running Junos OS.

junos_linkagg Manage link aggregation groups (LAGs) on devices running Junos OS.

junos_lldp Configure Link Layer Discovery Protocol (LLDP) settings.


26

Table 3: Ansible Core Modules for Junos OS (continued)

Module Description

junos_lldp_interface Enable or disable the Link Layer Discovery Protocol (LLDP) on interfaces.

junos_logging Configure system logging on devices running Junos OS.

junos_netconf Configure the NETCONF service on devices running Junos OS.

junos_package Install a Junos OS software package on a device.

junos_rpc Execute Junos OS RPCs.

junos_static_route Manage static routes on devices running Junos OS.

junos_system Manage system attributes such as hostname, domain name, and DNS name
servers on devices running Junos OS.

junos_user Manage Junos OS user accounts.

junos_vlan Manage VLANs on devices running Junos OS.

junos_vrf Manage virtual routing and forwarding (VRF) instances, also known as a Layer
3 VPN routing instances, on devices running Junos OS.

Ansible Galaxy Modules for Junos OS


Juniper Networks provides the Juniper.junos Ansible role, which is hosted on the Ansible Galaxy website
and includes Ansible modules that enable you to manage devices running Junos OS. To use the Ansible
Galaxy modules in the Juniper.junos role, you must install the role on the Ansible control machine. For
example:

[user@ansible-cm]$ sudo ansible-galaxy install Juniper.junos

Starting in Ansible for Junos OS Release 2.0.0, the Juniper.junos role includes an enhanced set of modules.
Each new module replaces the functionality of one or more existing modules. The enhanced modules also
support a common set of connection and authentication parameters, aliases that enable you to specify
the same connection and authentication-related options as the core modules, and the ability to specify
the parameters inside a provider dictionary.
27

Table 4 on page 27 summarizes the Ansible Galaxy modules in the Juniper.junos role, and notes which
modules replace existing modules in Release 2.0.0. For the most current list, documentation, and usage
examples for the Ansible Galaxy modules for Junos OS, see
https://junos-ansible-modules.readthedocs.io/en/latest/.

NOTE: The Juniper.junos modules introduced in Release 2.0.0 of Ansible for Junos OS require
Junos PyEZ Release 2.1.7 or later on the Ansible control machine.

Table 4: Ansible Galaxy Modules in the Juniper.junos Role

Deprecated Modules as
Module Name Description of Release 2.0.0

juniper_junos_command Execute CLI commands on the device running Junos OS junos_cli


and save the output locally.

juniper_junos_config Manage the configuration of devices running Junos OS. junos_commit

junos_get_config

junos_install_config

junos_rollback

juniper_junos_facts Retrieve device-specific information from the remote junos_get_facts


host, including the Junos OS version, serial number, and
hardware model number.

juniper_junos_jsnapy Execute Junos Snapshot Administrator in Python junos_jsnapy


(JSNAPy) tests from Ansible.

juniper_junos_ping Execute the ping command on devices running Junos junos_ping


OS.

juniper_junos_pmtud Perform path MTU discovery on devices running Junos junos_pmtud


OS.

juniper_junos_rpc Execute Junos OS RPCs. junos_rpc

juniper_junos_software Install a Junos OS software package and reboot a device junos_install_os


running Junos OS.
28

Table 4: Ansible Galaxy Modules in the Juniper.junos Role (continued)

Deprecated Modules as
Module Name Description of Release 2.0.0

juniper_junos_system Perform system operations on devices running Junos junos_shutdown


OS, including resetting, rebooting, or shutting down the
junos_zeroize
device.

juniper_junos_srx_cluster Create an SRX Series chassis cluster for cluster-capable junos_srx_cluster


SRX Series Services Gateways running Junos OS.

juniper_junos_table Use Junos PyEZ operational Tables and Views to retrieve junos_get_table
operational information from devices running Junos OS.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the Juniper.junos role includes an
enhanced set of modules.

RELATED DOCUMENTATION

Understanding Ansible for Junos OS | 21


Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50
Connecting to Devices Running Junos OS Using Ansible | 45

Understanding the Ansible Inventory File When


Managing Devices Running Junos OS

The Ansible inventory file defines the hosts and groups of hosts upon which commands, modules, and
tasks in a playbook operate. The file can be in one of many formats depending on your Ansible environment
and plugins. The default location for the inventory file is /etc/ansible/hosts. If necessary, you can also
create project-specific inventory files in alternate locations.

The inventory file can list individual hosts or user-defined groups of hosts. This enables you to define
groups of devices running Junos OS with similar roles upon which to perform the same operational and
29

configuration tasks. For example, if you are managing one or more data centers, you can create Ansible
groups for those switches that require the same set of operations, such as upgrading Junos OS and rebooting
the device.

In order to manage devices running Junos OS using Ansible, you must have a Junos OS login account with
appropriate access privileges on each device where Ansible modules are executed. You must ensure that
usernames and passwords or access keys exist for each host in the file.

The following INI-formatted sample inventory file defines an individual host, host1, and two groups of
hosts, routers and switches:.

host1.example.net

[routers]
router1.example.net
router2.example.net

[switches]
switch1.example.net
switch2.example.net

For more information about the Ansible inventory file, see the official Ansible documentation at
https://docs.ansible.com/intro_inventory.html .

RELATED DOCUMENTATION

Understanding Ansible for Junos OS | 21


Understanding the Ansible for Junos OS Modules | 23
Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50
Creating and Executing Ansible Playbooks to Manage Devices Running Junos OS | 30
Troubleshooting Ansible Connection Errors When Managing Devices Running Junos OS | 190
30

Creating and Executing Ansible Playbooks to Manage


Devices Running Junos OS

IN THIS SECTION

Creating a Playbook | 31

Executing a Playbook | 34

Juniper Networks provides support for using Ansible to manage devices running Junos OS. The Ansible
core and Ansible Galaxy modules for Junos OS provide simple yet powerful methods to perform operational
and configuration tasks on devices running Junos OS. This topic outlines how to create a simple playbook
to execute Ansible for Junos OS modules.

You create Ansible playbooks to handle more complex management tasks. Playbooks consist of one or
more plays, or groups of tasks, that operate on a set of defined hosts. Ansible hosts that are referenced
in the playbook must be defined in the Ansible inventory file, which by default resides at /etc/ansible/hosts.
Each play must specify the hosts on which the tasks operate, the list of tasks to execute on each host, and
any required variables or module parameters. Because devices running Junos OS do not require Python,
you must run modules locally on the control machine by including connection: local in the playbook play.
You can avoid gathering unnecessary facts about the server by also including gather_facts: no.

Starting in Ansible Release 2.1, Ansible natively includes a number of core modules for devices running
Junos OS. In addition, Juniper Networks provides a collection of modules in the Juniper.junos role, which
is hosted on the Ansible Galaxy website. The Ansible core modules are available when you install Ansible.
To use the Ansible Galaxy modules in the Juniper.junos role in your playbook, you must install the role on
the Ansible server and include the role in the playbook.

When you execute Ansible for Junos OS modules using a NETCONF session over SSH, you must have
NETCONF enabled on the devices running Junos OS. We recommend that you create a simple task in the
playbook that explicitly tests whether NETCONF is enabled on each device before executing other tasks.
If this task fails for any host, by default, Ansible does not execute the remaining tasks for this host. Without
this test, you might get a generic connection error during playbook execution that does not indicate whether
this or another issue is the cause of any failures.

Playbooks are expressed in YAML. Because YAML is white-space sensitive and indentation is significant,
you should always use spaces rather than tabs when creating playbooks. In YAML, items preceded by a
hyphen (-) are considered list items, and the key: value notation represents a hash. For detailed information
31

about creating Ansible playbooks, refer to the official Ansible documentation at


https://docs.ansible.com/playbooks.html .

The following sections outline the steps for creating and running a simple playbook that executes Ansible
for Junos OS modules:

Creating a Playbook

To create a simple playbook to perform tasks on devices running Junos OS:

1. In your favorite editor, create a new file with a descriptive playbook name that uses the .yaml file
extension.

2. Enter the required opening line for the playbook, and provide a descriptive name for the play.

---
- name: Get Device Facts

3. Define a colon-delimited list of the hosts or groups of hosts on which the modules will operate, or
specify all to indicate all hosts in the inventory file.

Note that any hosts or groups referenced in the playbook must be defined in the Ansible inventory
file.

---
- name: Get Device Facts
hosts: dc1

4. Include the Juniper.junos role to use the Juniper.junos Ansible Galaxy modules for Junos OS.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
32

5. Because there is no requirement for Python on the devices running Junos OS, include connection: local
to execute the plays locally on the Ansible control machine where Python is installed.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local

6. (Optional) Because Ansible executes plays locally on the control machine, avoid gathering unnecessary
facts about the server by including gather_facts: no.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

7. Define a tasks section, and include one or more tasks with each task as a list item.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:

8. (Optional) As an additional check, create a task to verify NETCONF connectivity for each device running
Junos OS.

---
- name: Get Device Facts
hosts: dc1
roles:
33

- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: 830
timeout: 5

9. Create tasks that use the Ansible core or Ansible Galaxy modules for Junos OS, and provide any
necessary connection or authentication parameters, for example:

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: 830
timeout: 5

- name: Retrieving information from devices running Junos OS


juniper_junos_facts:
host: "{{ inventory_hostname }}"

- name: Print version


debug:
var: junos.version
34

Executing a Playbook

To execute the playbook:

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

user@ansible-cm:~$ ansible-playbook playbook.yaml

PLAY [Get Device Facts] ***************************************************

TASK [Checking NETCONF connectivity] **************************************


ok: [dc1a.example.net]

TASK [Retrieving information from devices running Junos OS] ***************


ok: [dc1a.example.net]

TASK [Print version] ******************************************************


ok: [dc1a.example.net] => {
"junos.version": "14.1R1.10"
}

PLAY RECAP ****************************************************************


dc1a.example.net : ok=3 changed=0 unreachable=0 failed=0

RELATED DOCUMENTATION

Understanding Ansible for Junos OS | 21


Understanding the Ansible for Junos OS Modules | 23
Understanding the Ansible Inventory File When Managing Devices Running Junos OS | 28
Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50
3 CHAPTER

Installing Ansible for Junos OS

Ansible for Junos OS Server Requirements | 37

Setting up Ansible for Junos OS Managed Nodes | 39


37

Ansible for Junos OS Server Requirements

Juniper Networks provides support for using Ansible to manage devices running Junos OS. Starting in
Ansible Release 2.1, Ansible natively includes a number of core modules that can be used to manage
devices running Junos OS. In addition, Juniper Networks provides the Juniper.junos Ansible role, which is
hosted on the Ansible Galaxy website and includes additional modules for Junos OS.

You install Ansible on a control machine with a UNIX-like operating system. When you install Ansible, the
Ansible core modules for Junos OS are included in the software. To use the Ansible Galaxy modules, you
must install the Juniper.junos role on the Ansible server.

To manually install Ansible, the Juniper.junos role, and any dependencies, see the following section:

• Installing Ansible, the Juniper.junos Role, and Dependencies on page 37

Juniper Networks also provides a Docker image that enables you to run Ansible for Junos OS as a Docker
container. The Docker container is a lightweight, self-contained system that bundles Ansible, the
Juniper.junos role, and all dependencies into a single portable container. The Docker image enables you
to quickly run Ansible in interactive mode or as an executable package on any platform that supports
Docker.

To use the Ansible for Junos OS Docker image, see the following section:

• Using the Ansible for Junos OS Docker Image on page 38

Installing Ansible, the Juniper.junos Role, and Dependencies

Before you install the Juniper.junos Ansible role and begin using Ansible for Junos OS, ensure that the
Ansible control machine has the following software installed:

• Python 2.7

• Ansible 2.1 or later release

• Junos PyEZ (junos-eznc) Release 2.1.7 or later

For installation instructions and current information about Junos PyEZ, see:

• Junos PyEZ documentation

• Junos PyEZ GitHub repository


38

After you install the Ansible for Junos OS dependencies on the Ansible server, you can install the
Juniper.junos Ansible role from the Ansible Galaxy website.

• To install the Juniper.junos role on the Ansible server, issue the ansible-galaxy install command and
specify the Juniper.junos role.

[user@ansible-cm]$ sudo ansible-galaxy install Juniper.junos

- downloading role 'junos', owned by Juniper


- downloading role from
https://github.com/Juniper/ansible-junos-stdlib/archive/2.0.0.tar.gz
- extracting Juniper.junos to /etc/ansible/roles/Juniper.junos
- Juniper.junos (2.0.0) was installed successfully

To use the juniper_junos_jsnapy module, install Junos Snapsnot Administrator in Python (JSNAPy) Release
1.1.0 or later on the Ansible control machine. For installation instructions and current information about
JSNAPy, see:

• JSNAPy GitHub repository

• Junos Snapshot Administrator in Python Documentation

Using the Ansible for Junos OS Docker Image

Docker is a software container platform that is used to package and run an application and its dependencies
in an isolated container. Juniper Networks provides Ansible for Junos OS Docker images, which are
automatically built for every release of Ansible for Junos OS. The Docker image includes Python 2.7,
Ansible, Junos PyEZ, the Juniper.junos Ansible role, and Junos Snapshot Administrator in Python along
with any required dependencies. You can run the container in interactive mode or use the container as an
executable to run your playbooks.

To use the Ansible for Junos OS Docker image on your Ansible control machine:

1. Install Docker.

See the Docker website at https://www.docker.com for instructions on installing and configuring
Docker on your specific operating system.

2. Download the juniper/pyez-ansible Docker image from Docker Hub.

• To download the latest image, issue the following command:

user@host:~$ docker pull juniper/pyez-ansible


39

NOTE: The latest Ansible for Junos OS Docker image is built using the most recently
committed code in the Juniper/ansible-junos-stdlib GitHub source repository, which
is under active development and might not be stable.

• To download a specific image, append the appropriate release tag to the image name, for example,
2.0.0.

user@host:~$ docker pull juniper/pyez-ansible:tag

3. Run the container.

For instructions on running the container, see the official usage examples at
https://github.com/Juniper/ansible-junos-stdlib/blob/master/README.md#docker.

RELATED DOCUMENTATION

Setting up Ansible for Junos OS Managed Nodes | 39


Understanding Ansible for Junos OS | 21
Understanding the Ansible for Junos OS Modules | 23

Setting up Ansible for Junos OS Managed Nodes

Juniper Networks provides support for using Ansible to manage devices running Junos OS. You do not
need to install any client software on the remote nodes in order to use Ansible to manage the devices.
Also, Python is not required on the managed devices running Junos OS, because the Ansible for Junos OS
modules are executed locally on the Ansible control machine and use NETCONF and the Junos XML API
to perform the corresponding operational and configuration tasks.

You can execute Ansible for Junos OS modules using any user account that has access to the managed
device running Junos OS. When you execute Ansible modules, Junos OS user account access privileges
are enforced. The class configured for the Junos OS user account determines the permissions. Thus, if a
user executes a module that loads configuration changes onto a device, the user must have permissions
to change the relevant portions of the configuration. For information about configuring user accounts on
devices running Junos OS, see the User Access and Authentication User Guide.

The Ansible core and Ansible Galaxy modules for Junos OS enable you to connect to a device running
Junos OS using NETCONF over SSH. In addition, the Ansible Galaxy modules also enable you to telnet to
40

the device’s management interface or to a console server that is directly connected to the device’s CONSOLE
port. To use Ansible to telnet to the device’s management interface, you must configure the Telnet service
on the managed device. To manage devices through a NETCONF session over SSH, you must enable the
NETCONF service over SSH on the managed device and ensure that the device meets requirements for
SSHv2 connections.

The following sections outline the requirements and required configuration on devices running Junos OS
when using Ansible for Junos OS to access the device using the different connection protocols:

1. Configuring Telnet Service on Devices Running Junos OS | 40


2. Enabling NETCONF on Devices Running Junos OS | 41
3. Satisfying Requirements for SSHv2 Connections | 41

Configuring Telnet Service on Devices Running Junos OS

Juniper.junos Ansible modules can connect to a device running Junos OS using telnet. To telnet to a device
running Junos OS, you must configure the Telnet service on the device. Configuring Telnet service for a
device enables unencrypted, remote access to the device.

To enable Telnet service:

1. Configure the service.

[edit system services]


user@host# set telnet

2. (Optional) Configure the connection limit, rate limit, and order of authentication, as necessary.

[edit system services]


user@host# set telnet connection-limit connection-limit
user@host# set telnet rate-limit rate-limit
user@host# set telnet authentication-order [radius tacplus password]

3. Commit the configuration.

[edit system services]


user@host# commit
41

Enabling NETCONF on Devices Running Junos OS

To enable NETCONF over SSH on the default port (830) on a device running Junos OS:

1. Configure the NETCONF over SSH service.

[edit system services]


user@host# set netconf ssh

2. Commit the configuration.

[edit system services]


user@host# commit

Satisfying Requirements for SSHv2 Connections

The NETCONF server communicates with client applications within the context of a NETCONF session.
The server and client explicitly establish a connection and session before exchanging data, and close the
session and connection when they are finished. The Ansible for Junos OS modules access the NETCONF
server using the SSH protocol and standard SSH authentication mechanisms. When you use Ansible to
manage devices running Junos OS, the most convenient way to access a device is to configure SSH keys.

To establish an SSHv2 connection with a device running Junos OS, you must ensure that the following
requirements are met:

• The NETCONF service over SSH is enabled on each device where a NETCONF session will be established.

• The client application has a user account and can log in to each device where a NETCONF session will
be established.

• The login account used by the client application has an SSH public/private key pair or a text-based
password configured.

• The client application can access the public/private keys or text-based password.

For information about enabling NETCONF on a device running Junos OS and satisfying the requirements
for establishing an SSH session, see the NETCONF XML Management Protocol Developer Guide.

RELATED DOCUMENTATION
42

Ansible for Junos OS Server Requirements | 37


Understanding Ansible for Junos OS | 21
Understanding the Ansible for Junos OS Modules | 23
4 CHAPTER

Using Ansible to Connect to Devices


Running Junos OS

Connecting to Devices Running Junos OS Using Ansible | 45

Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50


45

Connecting to Devices Running Junos OS Using


Ansible

IN THIS SECTION

Connection Methods Overview | 45

Connecting to a Device Using NETCONF over SSH | 46

Connecting to a Device Using Telnet | 47

Connecting to a Device Using a Serial Console Connection | 48

Ansible is an IT automation framework that is used for infrastructure configuration management. Ansible
and Juniper Networks provide collections of Ansible modules that you can use to manage devices running
Junos OS. Starting in Ansible Release 2.1, Ansible natively includes a number of core modules for devices
running Junos OS. In addition, Juniper Networks provides a collection of modules in the Juniper.junos
role, which is hosted on the Ansible Galaxy website. The modules enable you to connect to devices running
Junos OS using different connection methods.

Connection Methods Overview

The Ansible core and Ansible Galaxy modules for Junos OS enable you to connect to a device running
Junos OS using NETCONF over SSH. In addition, the Ansible Galaxy modules also enable you to connect
to devices running Junos OS using a serial console connection and telnet. You must use a serial console
connection when you are physically connected to the CONSOLE port on a device. You can use telnet to
connect to the device’s management interface or to a console server that is directly connected to the
device’s CONSOLE port. New or zeroized devices that have factory-default configurations require access
through a console connection. Thus, you can use Ansible for Junos OS to initially configure a device that
is not yet configured for remote access by using either a serial console connection when you are directly
connected to the device or by using telnet through a console server that is directly connected to the device.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, all Juniper.junos Ansible modules use the
same set of connection and authentication-related options when connecting to the managed
device.
46

By default, Ansible for Junos OS modules connect to a device and establish a NETCONF session over SSH.
The Ansible Galaxy modules in the Juniper.junos role also enable you to specify a different connection
type by including the mode parameter in the module’s argument list. To telnet to a device, set the mode
argument equal to "telnet". To connect to a device using a serial console connection, set the mode argument
equal to "serial". Table 5 on page 46 summarizes the connection methods and their default values for
certain parameters.

Table 5: Ansible for Junos OS Connection Methods

Value of mode First Supported Ansible for


Connection Mode Argument Default Port Junos OS Release

NECONF over SSH (default) – 830 1.0.0

Serial console connection serial /dev/ttyUSB0 2.0.0

Telnet telnet 23 1.4.0

Default port added in 2.0.0

NOTE: Before you can access the management interface using telnet or NETCONF over SSH,
you must first enable the appropriate service at the [edit system services] hierarchy. Because
telnet uses clear-text passwords (therefore creating a potential security vulnerability), we
recommend that you use SSH.

Connecting to a Device Using NETCONF over SSH

By default, Ansible for Junos OS modules connect to a device and establish a NETCONF session over SSH.
To use this connection method, you must first satisfy the requirements outlined in “Setting up Ansible for
Junos OS Managed Nodes” on page 39. In addition, the device must be able to authenticate the user using
standard SSH authentication mechanisms. For more information, see “Authenticating Users Executing
Ansible Modules on Devices Running Junos OS” on page 50.

When establishing a NETCONF session over SSH, Ansible for Junos OS modules first attempt SSH public
key-based authentication and then try password-based authentication. When SSH keys are in use, the
password argument is used as the passphrase for unlocking the private SSH key. When password-based
authentication is used, the password argument is used as the password. If SSH public key-based
authentication is being used and the SSH private key has an empty passphrase, then the password argument
may be omitted. However, SSH private keys with empty passphrases are not recommended.
47

The following sample playbook retrieves the device facts using NETCONF over SSH, which is the default
connection method. The playbook uses SSH keys in the default location.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
host: "{{ inventory_hostname }}"
savedir: "{{ playbook_dir }}"
- name: Print version
debug:
var: junos.version

For information and examples for the Ansible core modules for Junos OS, see
https://docs.ansible.com/ansible/latest/list_of_network_modules.html#junos.

Connecting to a Device Using Telnet

The Ansible Galaxy modules in the Juniper.junos role enable you to connect to a device running Junos OS
using telnet, which provides unencrypted access to the network device. You can telnet to the device’s
management interface or to a console server that is directly connected to the device’s CONSOLE port.
Accessing the device through a console server enables you to initially configure a new or zeroized device
that is not yet configured for remote access. To telnet to the management interface, you must configure
the Telnet service at the [edit system services] hierarchy level on all devices that require access to the
interface.

To telnet to a device running Junos OS, you must set the module’s mode parameter to "telnet", and
optionally include the port parameter to specify a port. When you set mode to "telnet" but omit the port
parameter, the value for port defaults to 23.
48

The following sample playbook telnets to a device running Junos OS using port 7016, retrieves the device
facts, and saves them to a file. The module uses the default user and prompts for the login password.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_prompt:
- name: "DEVICE_PASSWORD"
prompt: "Device password"
private: yes

vars:
provider_info:
host: "{{ inventory_hostname }}"
password: "{{ DEVICE_PASSWORD }}"
mode: "telnet"
port: 7016

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
provider: "{{ provider_info }}"
savedir: "{{ playbook_dir }}"
- name: Print version
debug:
var: junos.version

Connecting to a Device Using a Serial Console Connection

The Ansible Galaxy modules in the Juniper.junos role enable you to connect to a device running Junos OS
using a serial console connection, which is useful when you must initially configure a new or zeroized
device that is not yet configured for remote access. To use this connection method, you must be physically
connected to the device through the CONSOLE port. For detailed instructions about connecting to the
CONSOLE port on your device, see the hardware documentation for your specific device.
49

To connect to a device running Junos OS through a serial console connection, you must set the module’s
mode parameter to "serial", and optionally include the port parameter to specify a port. When you set
mode to "serial" but omit the port parameter, the value for port defaults to /dev/ttyUSB0.

The following sample playbook connects to a device running Junos OS through the CONSOLE port,
retrieves the device facts, and saves them to a file. The module uses the default user and prompts for the
login password.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_prompt:
- name: "DEVICE_PASSWORD"
prompt: "Device password"
private: yes

vars:
provider_info:
host: "{{ inventory_hostname }}"
password: "{{ DEVICE_PASSWORD }}"
mode: "serial"

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
provider: "{{ provider_info }}"
savedir: "{{ playbook_dir }}"
- name: Print version
debug:
var: junos.version

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, all Juniper.junos Ansible modules use the
same set of connection and authentication-related options when connecting to the managed
device.
50

RELATED DOCUMENTATION

Understanding the Ansible for Junos OS Modules | 23


Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50

Authenticating Users Executing Ansible Modules on


Devices Running Junos OS

IN THIS SECTION

Defining Connection and Authentication Options | 51

Understanding the Default Values for the Ansible Galaxy Modules for Junos OS | 52

Authenticating the User Using SSH Keys | 54

Authenticating the User Using a Playbook or Command-Line Password Prompt | 57

Authenticating the User Using an Ansible Vault-Encrypted File | 59

Ansible and Juniper Networks provide Ansible modules that you can use to manage devices running Junos
OS. Starting in Ansible Release 2.1, Ansible natively includes a number of core modules for devices running
Junos OS. In addition, Juniper Networks provides a collection of modules in the Juniper.junos role, which
is hosted on the Ansible Galaxy website.

The Ansible core and Ansible Galaxy modules for Junos OS enable you to connect to devices running
Junos OS using NETCONF over SSH. In addition, the Ansible Galaxy modules enable you to connect to
devices using a serial console connection or telnet. The device must be able to authenticate the user using
a password or other standard SSH authentication mechanisms, depending on the connection method.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the Juniper.junos role includes an enhanced
set of modules. Each new module replaces the functionality of one or more existing modules.
All modules support a common set of connection and authentication parameters, aliases that
enable you to specify the same connection and authentication-related options as the core
modules, and the ability to specify the parameters inside a provider dictionary.
51

The Ansible core and Ansible Galaxy modules for Junos OS support specifying connection and
authentication-related options inside a provider dictionary. In addition, the Ansible Galaxy modules for
Junos OS enable you to define the parameters as top-level module arguments.

When you use Ansible to manage devices running Junos OS, the most convenient way to access the device
is to configure SSH keys. SSH keys enable the device running Junos OS to identify the Ansible user as a
trusted user. Alternatively, you can provide username and password authentication credentials when you
execute modules and playbooks. By default, Ansible for Junos OS modules first attempt SSH public
key-based authentication and then try password-based authentication. To retrieve a password for
password-based authentication or password-protected SSH keys, you can prompt for the password from
the playbook or on the command-line, or you can create a vault-encrypted data file that includes the
password.

The following sections discuss the different aspects of authentication when using Ansible for Junos OS
modules to manage devices running Junos OS:

Defining Connection and Authentication Options

Ansible core networking modules use the provider parameter for passing connection details and
authentication-related options to the module. Starting in Ansible for Junos OS Release 2.0.0, the Ansible
Galaxy modules in the Juniper.junos role also support the provider parameter in addition to supporting
individual top-level module arguments for each of the connection and authentication-related parameters.
The provider parameter enables you to define the connection and authentication parameters for a number
of devices in one place and easily pass those values to a module.

The provider argument accepts a dictionary that contains the connection details required to connect to
and authenticate with a device. The host argument is always required for a connection, but it does not
have to be specified explicitly if the module uses a default value for host. The dictionary can optionally
define additional parameters required for the connection, including username, password, and ssh_keyfile,
among others. For more information about the provider argument for networking modules, see
https://docs.ansible.com/ansible/latest/intro_networking.html. For information about the arguments
accepted for the individual modules, see the individual module documentation.

In the following example, the credentials variable is a dictionary that defines the host, username, and
password parameters:

vars:
credentials:
host: "{{ inventory_hostname }}"
username: "{{ ansible_user }}"
password: "{{ ansible_ssh_pass }}"
52

The following sample playbook uses the single provider argument to pass in the connection details to the
juniper_junos_facts module instead of defining the individual host, username, and password arguments
in the module:

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars:
credentials:
host: "{{ inventory_hostname }}"
username: "{{ ansible_user }}"
password: "{{ ansible_ssh_pass }}"

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
provider: "{{ credentials }}"
savedir: "{{ playbook_dir }}"
- name: Print version
debug:
var: junos.version

Understanding the Default Values for the Ansible Galaxy Modules for Junos
OS

You can explicitly define the connection and authentication parameters for Ansible core and Ansible Galaxy
modules for Junos OS. If you do not define a parameter, the module uses a default value in some cases.
Table 6 on page 53 outlines the default values and parameter aliases for common connection parameters
for the Juniper.junos Ansible Galaxy modules. For information about the arguments accepted for the
individual modules, see the documentation for that module. For information about the default values for
Ansible core modules for Junos OS, see
https://docs.ansible.com/ansible/latest/list_of_network_modules.html#junos.
53

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the Juniper.junos modules support the
same parameter names for connection and authentication-related options as the core modules.

Table 6: Connection Argument Defaults for Ansible Galaxy Modules for Junos OS

Parameter Aliases
Parameter (Ansible Galaxy Default Value for Ansible Galaxy
Name Modules) Description Modules for Junos OS

host hostname Hostname or IP address of the managed {{ inventory_hostname }}


device with which the connection should
ip
be established.

password passwd The user password or SSH key 1. ANSIBLE_NET_PASSWORD


passphrase used to authenticate with environment variable
the managed device. 2. Value specified for -k or
--ask-pass command-line option

ssh_keyfile ssh_private_key_file Path to the SSH private key file used to 1. ANSIBLE_NET_SSH_KEYFILE
authenticate with the managed node. environment variable
2. Value specified for --private-key
If you do not explicitly specify the path
or --key-file command-line option
and no default value is found, then the
module uses the SSH private key file 3. none
specified in the user’s SSH configuration
or the operating-system-specific default.

username user Username used to authenticate with the 1. ANSIBLE_NET_USERNAME


managed node. environment variable
2. remote_user as defined by
Ansible
3. USER environment variable

When executing modules in the Juniper.junos role, the host argument is always required for a connection,
but it does not have to be specified explicitly, because it defaults to {{ inventory_hostname }}.

The Juniper.junos modules first attempt SSH public key-based authentication and then try password-based
authentication. When SSH keys are in use, the password argument is used as the passphrase for unlocking
the private SSH key. When password-based authentication is used, the password argument is used as the
password. If SSH public key-based authentication is being used and the SSH private key has an empty
passphrase, then the password argument may be omitted. However, SSH private keys with empty
passphrases are not recommended.
54

You can execute Juniper.junos modules using any user account that has access to the managed device
running Junos OS. When you execute the modules, Junos OS user account access privileges are enforced,
and the class configured for the Junos OS user account determines the permissions. If you do not specify
a user, the user is set according to the algorithm described for username in Table 6 on page 53. See the
Ansible documentation for the precedence used to define remote_user, which can be defined in a number
of ways, including:

• -u or --user command line option

• ANSIBLE_REMOTE_USER environment variable

• remote_user configuration setting

Authenticating the User Using SSH Keys

To authenticate a user executing Ansible for Junos OS modules using SSH keys, generate the keys on the
Ansible server and configure the keys on each managed device running Junos OS.

To generate SSH keys on the Ansible control machine and configure the public key on devices running
Junos OS:

1. On the Ansible control machine, generate the public and private SSH key pair for the desired user, and
provide any required options, for example:

[user@localhost]$ cd ~/.ssh
[user@localhost .ssh]$ ssh-keygen -t rsa
Enter file in which to save the key (/home/user/.ssh/id_rsa): id_rsa_dc
Enter passphrase (empty for no passphrase): *****
Enter same passphrase again: *****

2. (Optional) Load the key into the native SSH key agent. For example:

[user@localhost .ssh]$ ssh-add ~/.ssh/id_rsa_dc

3. Configure the public key under the appropriate user account on all devices running Junos OS that will
be managed using this key.

The easiest method is to create a file that contains the public key and then load the file into the
configuration.

[edit]
55

[user@router]# set system login user username authentication load-key-file URL


[user@router]# commit

4. Verify that the key works by logging in to the device using the key.

[user@localhost]$ ssh -i ~/.ssh/id_rsa_dc router.example.com


Enter passphrase for key '/home/user/.ssh/id_rsa_dc':
user@router>

After generating the SSH key pair and configuring the public key on the managed device, you can connect
to the device using the key by including the appropriate arguments in the Ansible playbook. The module
arguments are determined by the location of the key, whether the key is actively loaded into an SSH key
agent, and whether the key is password-protected. If you do not explicitly define the module arguments,
the modules use the defaults defined in “Understanding the Default Values for the Ansible Galaxy Modules
for Junos OS” on page 52.

• To connect to the managed device using SSH keys that are actively loaded into the native SSH key agent
or that are in the default location and do not have password protection, you do not need to define any
connection or authentication-related module arguments, unless they differ from the default.

juniper_junos_facts:
savedir: "{{ playbook_dir }}"

• To connect to a device running Junos OS using SSH keys that are not in the default location and do not
have password protection, set the ssh_keyfile module argument to the path of the SSH private key file.
For example:

juniper_junos_facts:
provider: "{{ provider_info }}"
savedir: "{{ playbook_dir }}"

Where:

provider_info:
host: "{{ inventory_hostname }}"
ssh_keyfile: "~/.ssh/id_rsa_private"
56

Alternatively, you can specify the path of the SSH private key by setting the ANSIBLE_NET_SSH_KEYFILE
environment variable or by defining the --private-key or --key-file command-line option when you
execute the playbook.

NOTE: Juniper.junos modules also accept the ssh_private_key_file parameter in place of


ssh_keyfile.

• To connect to a device running Junos OS using a password-protected SSH key file, which is the
recommended method, provide the SSH key file passphrase in the password argument.

It is the user's responsibility to obtain the SSH key file passphrase in a secure manner appropriate for
their environment. It is best practice to either prompt for these authentication credentials during each
invocation of the playbook or store the variables using an encrypted vault rather than storing the
credentials in an unencrypted format. For example, you can execute the playbook with the --ask-pass
command-line option and provide the SSH key file passphrase when prompted.

juniper_junos_facts:
provider: "{{ provider_info }}"
savedir: "{{ playbook_dir }}"

Where:

provider_info:
host: "{{ inventory_hostname }}"
ssh_keyfile: "~/.ssh/id_rsa_dc"

[user@localhost]$ ansible-playbook playbook.yaml --ask-pass

SSH password:

For more information about using a prompt or encrypted vault for the SSH key passphrase, see
“Authenticating the User Using a Playbook or Command-Line Password Prompt” on page 57 and
“Authenticating the User Using an Ansible Vault-Encrypted File” on page 59.
57

Authenticating the User Using a Playbook or Command-Line Password


Prompt

To authenticate a user executing Ansible for Junos OS modules, you can obtain the authentication
credentials by including an interactive prompt in the playbook or by executing the playbook with the -k
or --ask-pass command-line option. When SSH keys are in use, the password argument is used as the
passphrase for unlocking the private SSH key. When password-based authentication is used, the password
argument is used as the password.

The following example shows one method for interactively obtaining the user’s password or SSH key
passphrase:

1. Include code under vars_prompt: that prompts for the user’s password or SSH key passphrase (and
optionally the username) and stores the value in a variable.

---
- name: Get Device Facts
hosts: all
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_prompt:
- name: "USERNAME"
prompt: "Username"
private: no
- name: "DEVICE_PASSWORD"
prompt: "Device password"
private: yes

2. Define a provider dictionary, and set the username and password parameters to reference its respective
variable.

vars:
credentials:
host: "{{ inventory_hostname }}"
username: "{{ USERNAME }}"
password: "{{ DEVICE_PASSWORD }}"
58

3. In the module’s parameter list, set the provider argument to the credentials variable containing the
authentication credentials.

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
provider: "{{ credentials }}"
savedir: "{{ playbook_dir }}"
register: junos
- name: Print facts
debug:
var: junos

4. Execute the playbook, which prompts for the username and password and does not echo the password
on the command line, because the variable is set to private: yes.

[user@localhost]$ ansible-playbook playbook.yaml

User name: user


Device password:

Alternatively, you can execute a playbook with the -k or --ask-pass command-line option to prompt for
the password or passphrase. Consider the following playbook, which uses the default username:

---
- name: Get Device Facts
hosts: all
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
host: "{{ inventory_hostname }}"
savedir: "{{ playbook_dir }}"
register: junos
- name: Print facts
59

debug:
var: junos

Execute the playbook, and include the -k or --ask-pass command-line option, which prompts for the
password and does not echo the password on the command line.

[user@localhost]$ ansible-playbook playbook.yaml --ask-pass

SSH password:

PLAY [Get Device Facts] ***********************************************


...

Authenticating the User Using an Ansible Vault-Encrypted File

To authenticate a user executing Ansible for Junos OS modules using a saved password, you can create
an Ansible vault that stores the password in an vault-encrypted data file. When SSH keys are in use, the
password argument is used as the passphrase for unlocking the private SSH key. When password-based
authentication is used, the password argument is used as the password.

To create and use an Ansible vault file containing required variables including passwords:

1. Create a vault-encrypted data file, and specify the password required to encrypt, decrypt, edit, and use
the data file.

[root@localhost]# ansible-vault create vault-vars.yaml


Vault password:
Confirm Vault password:

2. Include any desired variables in the file, and save the file.

[root@localhost]# ansible-vault edit vault-vars.yaml


Vault password:

# Vault variables
root_credentials:
username: root
password: password
60

3. Verify that the file is encrypted.

[root@localhost]# cat vault-vars.yaml

$ANSIBLE_VAULT;1.1;AES256
31415961343966623035373532313264333633663764353763393066643131306565636463326634
3730326165666565356665343137313161234569336336640a653939633331663935376362376666
65653737653262363235353261626135312345663665396262376339623737366238653436306663
6430376633306339360a343065363331313532633036343866376330623634653538353132314159
3835

4. In the playbook, include the vault-encrypted variable file, and reference the appropriate variables where
required.

---
- name: Get Device Facts
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_files:
- vault-vars.yaml

tasks:
- name: Retrieve facts from devices running Junos OS
juniper_junos_facts:
provider: "{{root_credentials}}"
savedir: "{{ playbook_dir }}"
register: junos
- name: Print version
debug:
var: junos.version

5. Execute the playbook with the --ask-vault-pass option, which prompts for the vault password.

[root@localhost]# ansible-playbook playbook-name.yaml --ask-vault-pass

Vault password:

PLAY [Get Device Facts] ***********************************************


...
61

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the Juniper.junos role includes an
enhanced set of modules.

RELATED DOCUMENTATION

Troubleshooting Ansible Authentication Errors When Managing Devices Running Junos OS | 193
Connecting to Devices Running Junos OS Using Ansible | 45
Understanding Ansible for Junos OS | 21
Understanding the Ansible for Junos OS Modules | 23
5 CHAPTER

Using Ansible to Manage Device


Operations

Using Ansible to Retrieve Facts from Devices Running Junos OS | 65

Using Ansible to Execute Commands and RPCs on Devices Running Junos OS | 67

Using Ansible with Junos PyEZ Tables to Retrieve Operational Information from
Devices Running Junos OS | 76

Using Ansible to Install Software on Devices Running Junos OS | 82

Using Ansible to Halt, Reboot, or Shut Down Devices Running Junos OS | 97

Using Ansible to Restore a Device Running Junos OS to the Factory-Default


Configuration Settings | 107

Using Junos Snapshot Administrator in Python (JSNAPy) in Ansible Playbooks | 116


65

Using Ansible to Retrieve Facts from Devices Running


Junos OS

Juniper Networks provides support for using Ansible to manage devices running Junos OS. Ansible for
Junos OS requires all tasks to run locally on the Ansible control machine and uses NETCONF and the Junos
XML API to interface with managed devices running Junos OS. As a result, playbooks default to gathering
facts from the local Ansible control machine rather than the managed node. The juniper_junos_facts module
in the Juniper.junos role and the junos_facts Ansible core module enable you to gather the device facts
as well as the committed configuration from devices running Junos OS.

This topic discusses using the juniper_junos_facts module to retrieve information from devices running
Junos OS. For information about the junos_facts Ansible core module, see
https://docs.ansible.com/ansible/latest/junos_facts_module.html.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_facts module replaces
the functionality of the junos_get_facts module.

The juniper_junos_facts module uses the Junos PyEZ fact gathering system to retrieve the device facts
from devices running Junos OS. For more information about the Junos PyEZ fact gathering system and
the complete list of returned dictionary keys, see jnpr.junos.facts.

When you use the juniper_junos_facts module to retrieve the device facts, the module returns the facts
in the ansible_facts.junos dictionary. The juniper_junos_facts module also enables you to save the returned
data in a file on the local Ansible control machine. To specify the directory on the local Ansible control
machine in which to save the retrieved information, include the savedir module argument, and define the
path to the target directory. The JSON data for each device is stored in a separate file named
hostname-facts.json, where hostname is the value of the hostname fact retrieved from the device, which
might be different from the hostname passed to the module. In addition, hardware inventory information
for each device is stored as XML in a separate file named hostname-inventory.xml.

The following playbook retrieves the device facts for each device in the inventory group and saves the
data for each device in separate files in the playbook directory on the Ansible control machine. Because
the playbook requires connection: local to run the Ansible for Junos OS modules locally, the playbook
defaults to gathering facts from the Ansible control machine. The playbook uses the juniper_junos_facts
module to retrieve the facts from the managed device and includes the gather_facts: no argument to
prevent the playbook from gathering facts from the Ansible control machine.

---
- name: Get device facts
66

hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Retrieve device facts and save to file
juniper_junos_facts:
savedir: "{{ playbook_dir }}"

By default, the juniper_junos_facts module does not return the device configuration. To return the
committed configuration for a device, in addition to the device facts, include the config_format option,
and specify the format in which to return the configuration. Acceptable format values are 'json', 'set', 'text'
and 'xml'. The requested format must be supported by the Junos OS release running on the device.

When you include the config_format option, the ansible_facts.junos dictionary in the module response
includes the config key with the configuration in the specified format in a single multi-line string. If the
savedir option is included, the configuration data is not written to the file.

TIP: To use Ansible to retrieve configuration data from a device running Junos OS and save the
data to a file, use the juniper_junos_config module instead of the juniper_junos_facts module.
For more information, see “Using Ansible to Retrieve or Compare Junos OS Configurations” on
page 149.

The following playbook retrieves the device facts and committed configuration for each device in the
inventory group, saves the facts and hardware inventory for each device in separate files in the playbook
directory on the Ansible control machine, and prints the configuration for each device to standard output.

---
- name: Get device facts and configuration
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Retrieve device facts and configuration and save facts to file
juniper_junos_facts:
67

savedir: "{{ playbook_dir }}"


config_format: "xml"
register: result

- name: Print configuration


debug:
var: result.ansible_facts.junos.config

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_facts module replaces
the functionality of the junos_get_facts module.

RELATED DOCUMENTATION

Understanding the Ansible for Junos OS Modules | 23


Using Ansible to Execute Commands and RPCs on Devices Running Junos OS | 67
Using Ansible with Junos PyEZ Tables to Retrieve Operational Information from Devices Running Junos
OS | 76

Using Ansible to Execute Commands and RPCs on


Devices Running Junos OS

IN THIS SECTION

Executing Commands with the juniper_junos_command Module | 68

Executing RPCs with the juniper_junos_rpc Module | 69

Understanding the Module Response | 71

Specifying the Format for the Command or RPC Output | 72

Saving the Command or RPC Output to a File | 73


68

Juniper Networks provides support for using Ansible to manage devices running Junos OS. The
juniper_junos_command and juniper_junos_rpc modules in the Juniper.junos Ansible role enable you to
execute operational commands and RPCs on devices running Junos OS to perform operations or retrieve
information. The following sections discuss how to the use the modules, parse the module response, specify
the output format, and save the output to a file.

NOTE: To more easily extract targeted data from operational output, you can also use the
juniper_junos_table module with custom or predefined Junos PyEZ operational tables. For more
information, see “Using Ansible with Junos PyEZ Tables to Retrieve Operational Information
from Devices Running Junos OS” on page 76.

Executing Commands with the juniper_junos_command Module

The juniper_junos_command module enables you to execute CLI commands on devices running Junos
OS. The module requires one argument, commands, which is a list of one or more Junos OS CLI commands
to execute on the device.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_command module
replaces the functionality of the junos_cli module.

The following playbook executes two CLI commands on each device in the inventory group, and displays
the module response in standard output.

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and uptime information
juniper_junos_command:
commands:
- "show version"
69

- "show system uptime"


register: junos_result

- name: Print response


debug:
var: junos_result

For information about the module’s response and output format, see “Understanding the Module Response”
on page 71 and “Specifying the Format for the Command or RPC Output” on page 72.

Executing RPCs with the juniper_junos_rpc Module

The Junos XML API is an XML representation of Junos OS configuration statements and operational mode
commands. It defines an XML equivalent for all statements in the Junos OS configuration hierarchy and
many of the commands that you issue in CLI operational mode. Each operational mode command with a
Junos XML counterpart maps to a request tag element and, if necessary, a response tag element. Request
tags are used in remote procedure calls (RPCs) within NETCONF or Junos XML protocol sessions to request
information from a device running Junos OS. The server returns the response using Junos XML elements
enclosed within the response tag element.

The juniper_junos_rpc module enables you to execute RPCs on devices running Junos OS. The module
requires one argument, rpcs, which is a list of one or more Junos OS RPCs to execute on the device.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_rpc module replaces
the functionality of the junos_rpc module.

The following playbook executes the get-interface-information RPC, which is equivalent to the show
interfaces CLI command, on each device in the inventory group and displays the module response in
standard output.

---
- name: Execute RPC
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
70

tasks:
- name: Get interface information
juniper_junos_rpc:
rpcs: "get-interface-information"
register: junos_result

- name: Print response


debug:
var: junos_result

NOTE: For information about mapping CLI commands to RPC request tags, see the Junos XML
API Explorer for operational tags.

For information about the module’s response and output format, see “Understanding the Module Response”
on page 71 and “Specifying the Format for the Command or RPC Output” on page 72.

The juniper_junos_rpc module supports the kwargs option, which enables you to specify keyword arguments
and values for the RPCs. The value of kwargs can be a single dictionary of keywords and values, or it can
be a list of dictionaries that supply arguments for multiple RPCs. There must be a one-to-one correspondence
between the elements in the kwargs list and the RPCs in the rpcs list. If you execute multiple RPCs, and
an RPC does not require any arguments, set the corresponding list item equal to an empty dictionary {}. If
an individual RPC argument does not require a value, set its value equal to True.

NOTE: You must use underscores in RPC arguments in place of hyphens, which can cause
exceptions or errors in certain circumstances.

The following playbook executes the specified RPCs on each device in the inventory group and displays
the module response in standard output. The get-interface-information RPC requests terse level output
for the lo0.0 interface, and the get-lldp-interface-neighbors RPC requests information for the ge-0/0/0
interface. The get-software-information RPC uses an empty dictionary to execute the RPC with no
additional arguments.

- name: Get Device Information


hosts: dc1a
roles:
- Juniper.junos
connection: local
gather_facts: no
71

tasks:
- name: Get device information
juniper_junos_rpc:
rpcs:
- "get-interface-information"
- "get-lldp-interface-neighbors"
- "get-software-information"
kwargs:
- interface_name: "lo0.0"
terse: True
- interface_device: "ge-0/0/0"
- {}
register: junos_result

- name: Print response


debug:
var: junos_result

Understanding the Module Response

The juniper_junos_command and juniper_junos_rpc modules store the RPC reply from the device within
several different keys in the module response. The data for each key is structured as described here. The
parsed_output key is only returned when the format of the data is XML or JSON.

• stdout—RPC reply is a single multi-line string

• stdout_lines—RPC reply is a list of single line strings

• parsed_output—RPC reply is parsed into a JavaScript Object Notation (JSON) data structure

If the module executes a single command or RPC, the module’s response places the returned keys at the
top level. If the module executes multiple commands or RPCs, the module’s response instead includes a
results key, which is a list of dictionaries. Each element in the list corresponds to a single command or RPC
and includes all the keys that would be returned for that command or RPC.

In some instances, command or RPC output can be extensive, and it might be necessary to suppress the
output in the module’s response. To omit the output keys in the module’s response, include return_output:
false in the module’s argument list.
72

Specifying the Format for the Command or RPC Output

The juniper_junos_command and juniper_junos_rpc modules store the RPC reply from the device within
several different keys in the module response: stdout, stdout_lines, and parsed_output. The parsed_output
key, which is only present when the command or RPC output format is XML or JSON, contains data that
is parsed into a JSON data structure.

The stdout and stdout_lines keys contain data in the default format defined for the module. By default,
the juniper_junos_command module returns the command output in text format, and the juniper_junos_rpc
module returns the RPC output in XML format. To specify a different output format, include the formats
argument, and set the value equal to the desired format. To request text format, Junos XML elements, or
JSON format, use 'text', 'xml', or 'json' respectively. The requested format must be supported by the device
on which the command or RPC is executed.

The formats parameter takes either a string or a list of strings. When you execute multiple commands or
RPCs and only specify a single format, the output format is the same for all executed commands and RPCs.
To specify a different format for the output of each command or RPC, set the formats argument to a list
of the desired formats. The list must specify the same number of formats as there are commands or RPCs.

The following playbook executes two RPCs on each device in the inventory group and requests text format
for the output of all executed RPCs:

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and system uptime information
juniper_junos_rpc:
rpcs:
- "get-software-information"
- "get-system-uptime-information"
formats: "text"
register: junos_result

- name: Print response


debug:
var: junos_result
73

When the playbook is executed, the stdout and stdout_lines keys in the module response contain the RPC
reply in text format.

The following playbook executes two RPCs on each device in the inventory group and requests the output
for the first RPC in text format and the output for the second RPC in JSON format:

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and system uptime information
juniper_junos_rpc:
rpcs:
- "get-software-information"
- "get-system-uptime-information"
formats:
- "text"
- "json"
register: junos_result

- name: Print response


debug:
var: junos_result

Saving the Command or RPC Output to a File

When you use the juniper_junos_command or juniper_junos_rpc module to execute a command or RPC
on a device, you can save the returned data in a file on the local Ansible control machine by including the
dest or dest_dir module arguments. If an output file already exists with the target name, the module
overwrites the file.

To specify the directory on the local Ansible control machine where the retrieved data is saved, include
the dest_dir argument, and define the path to the target directory. The module stores the output for each
command or RPC executed on a device in a separate file named hostname_name.format where:

• hostname—Hostname of the device on which the command or RPC is executed.


74

• name—Name of the command or RPC executed on the managed device. The module replaces spaces in
the command name with underscores ( _ ).

• format—Format of the output, which can be json, text, or xml.

The following playbook executes two RPCs on each device in the inventory group and saves the output
for each RPC for each device in a separate file in the playbook directory on the Ansible control machine:

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and uptime information
juniper_junos_rpc:
rpcs:
- "get-software-information"
- "get-system-uptime-information"
dest_dir: "{{ playbook_dir }}"

The resulting output files for host dc1a.example.net are:

• dc1a.example.net_get-software-information.xml

• dc1a.example.net_get-system-uptime-information.xml

Similarly, the following playbook executes the equivalent commands on each device in the inventory group
and saves the output for each command for each device in a separate file in the playbook directory on the
Ansible control machine:

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and uptime information
juniper_junos_command:
75

commands:
- "show version"
- "show system uptime"
dest_dir: "{{ playbook_dir }}"

The resulting output files for host dc1a.example.net are:

• dc1a.example.net_show_version.text

• dc1a.example.net_show_system_uptime.text

To specify the path and filename to which the command or RPC output is saved on the local Ansible control
machine, include the dest argument, and define the filename or the full path of the file. Whereas the
dest_dir option saves the output for each command or RPC in separate files for a device, the dest option
saves the output for all commands and RPCs in the same file for a device.

If you include the dest argument, but omit the directory, the files are saved in the playbook directory. If
you execute commands or RPCs on multiple devices, the dest argument must include a variable such as
{{ inventory_hostname }} to differentiate the filename for each device. If you do not differentiate the
filenames, the output file for each device will overwrite the output file of the other devices.

The following playbook executes RPCs on each device in the inventory group. The output for all RPCs is
stored in a separate file for each device and the file is placed in the playbook directory on the Ansible
control machine. Each file is uniquely identified by the device hostname.

---
- name: Get device information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get software and uptime information
juniper_junos_rpc:
rpcs:
- "get-software-information"
- "get-system-uptime-information"
dest: "{{ inventory_hostname }}-system-information.xml"

For example, the resulting output file for host dc1a.example.net is dc1a.example.net-system-information.xml
and contains the output for all RPCs executed on the device.

If you are saving the data to a file and do not want to duplicate the command or RPC output in the module’s
response, you can you can optionally include return_output: false in the module’s argument list. Setting
76

return_output to false causes the module to omit the output keys in the module’s response. Doing this
might be necessary if the devices return a significant amount of data.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_command module replaces
the functionality of the junos_cli module.

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_rpc module replaces the
functionality of the junos_rpc module.

RELATED DOCUMENTATION

Using Ansible with Junos PyEZ Tables to Retrieve Operational Information from Devices Running Junos
OS | 76
Using Ansible to Retrieve Facts from Devices Running Junos OS | 65
Understanding the Ansible for Junos OS Modules | 23

Using Ansible with Junos PyEZ Tables to Retrieve


Operational Information from Devices Running Junos
OS

IN THIS SECTION

Understanding the juniper_junos_table Module and Junos PyEZ Tables | 77

Using the juniper_junos_table Module with Junos PyEZ Tables | 77

Specifying RPC Arguments | 80


77

Understanding the juniper_junos_table Module and Junos PyEZ Tables

Junos PyEZ operational (op) Tables provide a simple and efficient way to extract information from complex
operational command output, and the Junos PyEZ jnpr.junos.op module contains predefined Table and
View definitions for some common operational commands. The juniper_junos_table Ansible module in the
Juniper.junos role enables you to leverage Junos PyEZ op Tables from within Ansible playbooks. The
juniper_junos_table module can use the predefined operational Tables that are included with the Junos
PyEZ distribution or it can use user-defined operational Tables and Views to retrieve operational information
from devices running Junos OS.

For general information about Junos PyEZ Tables and Views and for information about Junos PyEZ’s
predefined operational Tables and Views, see Understanding Junos PyEZ Tables and Views and Junos
PyEZ Predefined Operational Tables and Views in the Junos PyEZ Developer Guide.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_table module replaces
the functionality of the junos_get_table module.

NOTE: The juniper_junos_table module does not work with configuration Tables and Views.

Using the juniper_junos_table Module with Junos PyEZ Tables

The juniper_junos_table module requires one argument, file, which is the name of the YAML file that
defines the Junos PyEZ Table and View. The default file path is the location of the predefined Junos PyEZ
op Tables, which reside in the Junos PyEZ install path under the jnpr/junos/op directory. To specify a
different directory, include the path argument and define the path to the directory containing the YAML
file with the Table and View definitions. If a file contains multiple Table definitions or the file contains a
single Table that does not include "Table" in its name, you must also include the table argument to specify
the name of the Table that will be used to retrieve the data.

For example, the following task retrieves data by using a custom table named FPCTable, which is defined
in the fpc.yaml file located in the playbook directory:

tasks:
- name: Get FPC info
juniper_junos_table:
file: "fpc.yaml"
78

path: "{{ playbook_dir }}"


table: "FPCTable"

The juniper_junos_table module’s response includes the resource key, which contains a list of items
returned by the Table. Each list item is a dictionary of the field names defined by the View and the value
extracted from the data for each of the corresponding fields.

Consider the following predefined Table and View, ArpTable and ArpView, in the arp.yml file of the Junos
PyEZ distribution. ArpTable executes the <get-arp-table-information> RPC with the <no-resolve/> option,
which is equivalent to the show arp no-resolve CLI command. The corresponding View extracts the
interface name, IP address, and MAC address for each <arp-table-entry> item in the response.

---
ArpTable:
rpc: get-arp-table-information
args:
no-resolve: True
item: arp-table-entry
key: mac-address
view: ArpView

ArpView:
fields:
mac_address: mac-address
ip_address: ip-address
interface_name: interface-name

The following Ansible playbook executes the juniper_junos_table module, which uses ArpTable to retrieve
Address Resolution Protocol (ARP) information from devices running Junos OS. Because ArpTable is
included with the Junos PyEZ distribution and resides in the default directory for the predefined Junos
PyEZ op Tables, the path module argument is not required to specify the file location. In addition, because
ArpTable is the only Table defined in the file, the table argument is not required to specify the Table.

---
- name: Get ARP information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get ARP information using Junos PyEZ Table
79

juniper_junos_table:
file: "arp.yml"
register: result

- name: Print response


debug:
var: result

The playbook output, which is truncated for brevity, includes the corresponding fields, as defined by the
View, for each <arp-table-entry> item returned by the device.

TASK [Print response] *********************************************************


ok: [dc1a.example.net] => {
"result": {
"changed": false,
"failed": false,
"msg": "Successfully retrieved 2 items from ArpTable.",
"resource": [
{
"interface_name": "em0.0",
"ip_address": "10.0.0.5",
"mac_address": "02:01:00:00:00:06"
},
{
"interface_name": "fxp0.0",
"ip_address": "10.102.70.254",
"mac_address": "f8:c0:01:18:8f:65"
}
]
}
}

The following Ansible playbook leverages the predefined Junos PyEZ operational Table, OspfInterfaceTable
to retrieve information about OSPF interfaces on devices running Junos OS. The ospf.yml file defines
multiple Tables and Views, so the module call includes the table argument to specify which Table to use.

---
- name: Get OSPF information
hosts: dc1
roles:
- Juniper.junos
connection: local
80

gather_facts: no

tasks:
- name: Get OSPF interface information
juniper_junos_table:
file: "ospf.yml"
table: "OspfInterfaceTable"
register: result

- name: Print response


debug:
var: result

Specifying RPC Arguments

Junos PyEZ operational Tables have an optional args option that defines the default command options
and arguments for the RPC executed by that Table. The application executes the RPC with the default
options unless the user overrides the defaults. In Junos PyEZ applications, you can override the default
command options or pass additional options and arguments to the RPC when calling the get() method.

The juniper_junos_table module also enables you to override the default command options defined in the
Table or pass additional options and arguments to the PRC by using the kwargs argument. The kwargs
value is a dictionary of command options and values, which must be supported by the RPC and the device
on which the RPC is executed.

For example, the predefined Junos PyEZ op Table EthPortTable in the ethport.yml file executes the
<get-interface-information> RPC with the media command option and returns information for all interfaces
that match the given regular expression for the interface name.

EthPortTable:
rpc: get-interface-information
args:
media: True
interface_name: '[afgxe][et]-*'
args_key: interface_name
item: physical-interface
view: EthPortView
81

The following Ansible playbook uses EthPortTable to extract information about the interfaces on devices
running Junos OS. The kwargs argument includes interface_name: "ge-1/0/0", which overrides the
EthPortTable default for interface_name and instructs the module to retrieve the requested fields for only
the ge-1/0/0 interface.

---
- name: Get interface information
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Get interface information for Ethernet interfaces
juniper_junos_table:
file: "ethport.yml"
kwargs:
interface_name: "ge-1/0/0"
register: result

- name: Print response


debug:
var: result

For more information about the default and user-supplied command options and arguments in Junos PyEZ
Tables, see Defining Junos PyEZ Operational Tables and Using Junos PyEZ Operational Tables and Views.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_table module replaces
the functionality of the junos_get_table module.

RELATED DOCUMENTATION

Using Ansible to Execute Commands and RPCs on Devices Running Junos OS | 67


Using Ansible to Retrieve Facts from Devices Running Junos OS | 65
Understanding the Ansible for Junos OS Modules | 23
82

Using Ansible to Install Software on Devices Running


Junos OS

IN THIS SECTION

Using Ansible to Install Software | 82

Example: Using Ansible to Install Software | 88

Using Ansible to Install Software

IN THIS SECTION

Specifying the Software Image Location | 83

Installation Process Overview | 84

Specifying Installation Options That Do Not Have an Equivalent Module Argument | 86

Performing ISSU or NSSU | 87

Juniper Networks provides support for using Ansible to manage devices running Junos OS. The
juniper_junos_software module in the Juniper.junos role and the junos_package Ansible core module
enable you to install a Junos OS software image or other software package on devices running Junos OS.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_software module
replaces the functionality of the junos_install_os module.

The following sections discuss how to specify the software image location, the general software installation
process and options, and support for unified in-service software upgrades (unified ISSU) and nonstop
software upgrades (NSSU) when using the juniper_junos_software module to install software packages
on devices running Junos OS. For more information about the junos_package Ansible core module, see
https://docs.ansible.com/ansible/latest/junos_package_module.html.
83

Specifying the Software Image Location

When you use the juniper_junos_software module to install software on devices running Junos OS, you
can download the software package to the Ansible control machine or another remote location, and the
module, by default, copies the package to the target device before performing the installation. You can
also download the software package directly to the managed device running Junos OS and instruct the
module to install it from there.

Table 7 on page 83 outlines the juniper_junos_software module arguments that you must set depending
on the software package location. The module must always include either the local_package or
remote_package argument. The no_copy argument defaults to false, which instructs the module to copy
the software package from the specified location to the target device.

Table 7: juniper_junos_software Module Arguments for Software Package Location

Software
Package no_copy local_package
Location Parameter Parameter remote_package Parameter

Ansible control Omitted or set Absolute or relative file (Optional) File path on the target device to which
machine to false path including the the software package is copied. The default
filename of the software directory is /var/tmp.
package on the server.
If remote_package is a directory (ends with slash
File paths are relative to ( / )), the module copies the package to the
the playbook directory. specified directory.

If remote_package includes a filename, the


filename must match the filename specified in
local_package.

Remote Location Omitted or set – URL from the perspective of the target device
to false running Junos OS from which the software
package is retrieved.

Target device Set to true – 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 machine, the juniper_junos_software module must
include the local_package argument, which specifies the absolute or relative file path to the software
package on the local server. By default, when you include the local_package argument, the module copies
the software package to the target device running Junos OS. The software image is placed in the /var/tmp
directory unless the remote_package argument specifies a different 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.
84

If the software package already resides on the target device running Junos OS, the juniper_junos_software
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 module uses the /var/tmp directory.

If the software package resides at a location other than the Ansible control machine or target device, the
juniper_junos_software 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 device
running Junos OS. 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 device running Junos OS, execute the
juniper_junos_software module, and provide any necessary arguments. For example:

---
- name: Perform a Junos OS software upgrade
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Upgrade Junos OS
juniper_junos_software:
local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz"
no_copy: false
validate: true
register: response
- name: Print the response
debug:
var: response

When the juniper_junos_software module is executed, it performs the following operations:

1. Compares the Junos OS version specified in the version argument, or in the software package filename
if the version argument is omitted, to the installed version on the managed device. If the installed and
desired versions are identical, the module skips the remaining installation steps and sets changed and
failed to false.

2. If the local_package argument is present, the module:


85

• Computes the MD5 checksum of the local software package, if it is not provided in the checksum
argument.

NOTE: To specify a different checksum algorithm, include the checksum_algorithm


argument with the value for the desired algorithm.

• Performs a storage cleanup on the target device to create space for the software package, unless
the cleanfs argument is set to false.

3. Copies the software package to the device, if the no_copy argument is omitted or set to false.

• If the local_package argument is present, and a file with the same name and MD5 checksum does
not already reside in the target location on the device, the module copies the package to the /var/tmp
directory unless the remote_package argument specifies a different directory. The module verifies
the MD5 checksum of the copied package against the checksum computed for the local package.

NOTE: If the cleanfs argument is omitted or set to true, the module copies the file
to the device even if it already exists in the target location, because the storage cleanup
operation removes the existing file. To prevent the module from copying the
local_package file to the device when it already resides at the target location, include
the cleanfs: false argument. If cleanfs: false is present and the file already resides at
the target location, the module skips the file copy operation. If the file does not already
reside at the target location, the module performs the file copy operation.

• If the remote_package argument is present and contains a URL external to the target device, the
module copies the package to the /var/tmp directory on the target device.

Once the software package is on the target device, whether downloaded there initially or copied over by
the juniper_junos_software module, the juniper_junos_software module then performs the following
operations:

4. Validates the configuration against the new package if the validate parameter is set to true.

NOTE: By default, the juniper_junos_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 the validate argument to true.

5. Installs the package on each individual Routing Engine, unless all_re is set to false.
86

6. Reboots each upgraded Routing Engine, unless the reboot argument is set to false.

The default time for an RPC to time out is 30 seconds. During the installation process, the RPC timeout
intervals are increased to 1800 seconds (30 minutes) when copying and installing the package on the
device, to 300 seconds (5 minutes) when computing the checksum, and to 300 seconds (5 minutes) when
performing a storage cleanup. You can change the timeout value for these operations by setting the
install_timeout, checksum_timeout, and cleanfs_timeout arguments, respectively, to the required number
of seconds in the juniper_junos_software module argument list. For example:

juniper_junos_software:
local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz"
no_copy: false
validate: true
install_timeout: 2000
checksum_timeout: 420
cleanfs_timeout: 600

The juniper_junos_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.

Specifying Installation Options That Do Not Have an Equivalent Module Argument

When you use the juniper_junos_software module to install a Junos OS image or other package, the
module invokes the <request-package-add> RPC, which is equivalent to the request system software add
operational mode command. 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 <request-package-add> options that do not have an equivalent
juniper_junos_software argument. The kwargs argument takes a dictionary of key/value pairs of any
options supported by the <request-package-add> RPC.

For the current list of options supported by the juniper_junos_software module, see
https://junos-ansible-modules.readthedocs.io/en/latest/juniper_junos_software.html. For a list of all
available <request-package-add> options, search for the request tag in the Junos XML API Explorer.

NOTE: The juniper_junos_software module should only include installation options that are
supported on the target device running Junos OS.
87

In the following sample playbook, the juniper_junos_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 completed, is equivalent to including
the <unlink/> option in the <request-package-add> RPC.

---
- name: Perform a Junos OS software upgrade
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Upgrade Junos OS
juniper_junos_software:
local_package: "software/jinstall-ppc-17.3R1.10-signed.tgz"
kwargs:
unlink: true
register: response
- name: Print the response
debug:
var: response

Performing ISSU or NSSU

The juniper_junos_software module provides support for 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 juniper_junos_software module must include the issu: true argument. For example:

---
- name: Perform a Junos OS software upgrade
hosts: mx1
roles:
- Juniper.junos
connection: local
gather_facts: no
88

tasks:
- name: Perform a unified ISSU
juniper_junos_software:
local_package: "junos-install-mx-x86-64-17.2R1.13.tgz"
issu: true
register: response
- name: Print the response
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 juniper_junos_software module must include the nssu: true argument. For example:

---
- name: Perform a Junos OS software upgrade
hosts: ex1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Perform an NSSU
juniper_junos_software:
local_package: "jinstall-ex-4300–17.3R1.10-signed.tgz"
nssu: true
register: response
- name: Print the response
debug:
var: response

Example: Using Ansible to Install Software

IN THIS SECTION

Requirements | 89

Overview | 89

Configuration | 90
89

Executing the Playbook | 93

Verification | 94

Juniper Networks provides support for using Ansible to manage devices running Junos OS. The
juniper_junos_software module in the Juniper.junos role enables you to install a Junos OS software image
or other software package on a device running Junos OS. This example outlines how to use the
juniper_junos_software Ansible module to install a software image on a device running Junos OS.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_software module
replaces the functionality of the junos_install_os module.

Requirements

This example uses the following hardware and software components:

• Configuration management server running Ansible 2.1 or later with version 2.0.0 or later of the
Juniper.junos role installed

• Device running Junos OS with NETCONF enabled and a user account configured with appropriate
permissions

• SSH public/private key pair configured for the appropriate user on the Ansible server and device running
Junos OS

• Existing Ansible inventory file with required hosts defined

Overview

The juniper_junos_software module enables you to install a software image on a device running Junos
OS. This example presents an Ansible playbook that uses the juniper_junos_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 machine, 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 Checking NETCONF connectivity task, which utilizes the wait_for module to
try to establish a NETCONF session with the device running Junos OS using the default NETCONF port
90

830. If the control machine fails to establish a NETCONF session with a device during playbook execution,
then it skips over the other tasks in the play for that device.

The task to install the Junos OS software image on the device executes the juniper_junos_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 device running Junos OS. 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 to the new Junos OS image on the Ansible control machine.
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 juniper_junos_software module reboots the device after the installation is
complete; however, this task explicitly sets reboot: true for clarity.

The task stores the module result in the sw 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
machine 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

Step-by-Step Procedure
To create a playbook that uses the juniper_junos_software module to install a software image on a device
running Junos OS:

1. Include the boilerplate for the playbook and this play, which must contain connection: local and the
Juniper.junos role.

---
- name: Install Junos OS
hosts: mx1
roles:
- Juniper.junos
91

connection: local
gather_facts: no

2. 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: "17.3R1.10"
OS_package: "jinstall-ppc-17.3R1.10-signed.tgz"
pkg_dir: "software"
log_dir: "/var/log/ansible"
netconf_port: 830
wait_time: 3600

3. (Optional) Create a task to verify NETCONF connectivity.

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: 5

4. Create the task to install the Junos OS package on the device and notify the handler.

- name: Install Junos OS package


juniper_junos_software:
version: "{{ OS_version }}"
local_package: "{{ pkg_dir }}/{{ OS_package }}"
reboot: true
validate: true
logfile: "{{ log_dir }}/software.log"
register: sw
notify:
- wait_reboot
92

5. (Optional) Create a task to print the module response.

- name: Print response


debug:
var: sw

6. 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
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: "{{ wait_time }}"
when: not sw.check_mode

Results

On the Ansible control machine, 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
roles:
- Juniper.junos
connection: local
gather_facts: no

vars:
OS_version: "17.3R1.10"
OS_package: "jinstall-ppc-17.3R1.10-signed.tgz"
pkg_dir: "software"
log_dir: "/var/log/ansible"
netconf_port: 830
wait_time: 3600

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
93

port: "{{ netconf_port }}"


timeout: 5

- name: Install Junos OS package


juniper_junos_software:
version: "{{ OS_version }}"
local_package: "{{ pkg_dir }}/{{ OS_package }}"
reboot: true
validate: true
logfile: "{{ log_dir }}/software.log"
register: sw
notify:
- wait_reboot

- name: Print response


debug:
var: response

handlers:
- name: wait_reboot
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: "{{ wait_time }}"
when: not sw.check_mode

Executing the Playbook

Step-by-Step Procedure
94

To execute the playbook:

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

user@ansible-cm:~/ansible$ ansible-playbook -v ansible-pb-junos-install-os.yaml

Using /etc/ansible/ansible.cfg as config file

PLAY [Install Junos OS] ****************************************************

TASK: [Checking NETCONF connectivity] **************************************


ok: [mx1a.example.com] => {"changed": false, "elapsed": 0, "failed": false,
"path": null, "port": 830, "search_regex": null, "state": "started"}

TASK: [Install Junos OS package] *******************************************


changed: [mx1a.example.com] => {"changed": true, "check_mode": false, "failed":
false, "msg": "Package
/home/user/ansible/software/jinstall-ppc-17.3R1.10-signed.tgz successfully
installed. Reboot successfully initiated."}

TASK [Print response] ******************************************************


ok: [mx1a.example.com] => {
"sw": {
"changed": true,
"check_mode": false,
"failed": false,
"msg": "Package
/home/user/ansible/software/jinstall-ppc-17.3R1.10-signed.tgz successfully
installed. Reboot successfully initiated."
}
}

RUNNING HANDLER [wait_reboot] **********************************************


ok: [mx1a.example.com] => {"changed": false, "elapsed": 914, "failed": false,
"path": null, "port": 830, "search_regex": null, "state": "started"}

PLAY RECAP *****************************************************************


mx1a.example.com : ok=4 changed=1 unreachable=0 failed=0

Verification

Verifying the Installation


95

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.

user@ansible-cm:~/ansible$ cat /var/log/ansible/software.log

2017-12-08 12:02:43,840 - ncclient.transport.ssh - INFO - Connected (version 2.0,


client OpenSSH_7.2)
2017-12-08 12:02:44,139 - ncclient.transport.ssh - INFO - Authentication (publickey)
successful!
...
2017-12-08 12:02:47,004 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] computing checksum on local package:
/home/user/ansible/software/jinstall-ppc-17.3R1.10-signed.tgz
2017-12-08 12:02:49,030 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] cleaning filesystem ...
2017-12-08 12:02:49,030 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'
2017-12-08 12:03:01,066 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] before copy, computing checksum on remote package:
/var/tmp/jinstall-ppc-17.3R1.10-signed.tgz
2017-12-08 12:03:01,071 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'
2017-12-08 12:03:01,424 - paramiko.transport - INFO - Connected (version 2.0,
client OpenSSH_7.2)
2017-12-08 12:03:01,773 - paramiko.transport - INFO - Authentication (publickey)
successful!
2017-12-08 12:03:55,892 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 36159488 / 361592739 (10%)
2017-12-08 12:04:52,136 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 72318976 / 361592739 (20%)
2017-12-08 12:05:50,010 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 108478464 / 361592739 (30%)
2017-12-08 12:06:48,170 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 144637952 / 361592739 (40%)
2017-12-08 12:07:46,661 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 180797440 / 361592739 (50%)
2017-12-08 12:08:42,598 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 216956928 / 361592739 (60%)
2017-12-08 12:09:40,349 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 253116416 / 361592739 (70%)
2017-12-08 12:10:36,962 - jnpr.ansible_module.juniper_junos_software - INFO -
96

[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 289275904 / 361592739 (80%)


2017-12-08 12:11:32,264 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 325435392 / 361592739 (90%)
2017-12-08 12:12:26,129 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] jinstall-ppc-17.3R1.10-signed.tgz: 361592739 / 361592739 (100%)
2017-12-08 12:12:26,900 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] after copy, computing checksum on remote package:
/var/tmp/jinstall-ppc-17.3R1.10-signed.tgz
2017-12-08 12:12:26,903 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'
2017-12-08 12:12:32,903 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] checksum check passed.
2017-12-08 12:12:32,904 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] validating software against current config, please be patient
...
2017-12-08 12:12:32,905 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'
2017-12-08 12:25:53,347 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] software validate package-result: 0
Output:
Checking compatibility with configuration
...
Initializing...
Using jbase-ppc-17.2R1.13
Verified manifest signed by PackageProductionEc_2017 method ECDSA256+SHA256
Using /var/tmp/jinstall-ppc-17.3R1.10-signed.tgz
Verified jinstall-ppc-17.3R1.10.tgz signed by PackageProductionEc_2017 method
ECDSA256+SHA256
...
Validating against /config/juniper.conf.gz
mgd: commit complete
Validation succeeded
Validating against /config/rescue.conf.gz
mgd: commit complete
Validation succeeded

2017-12-08 12:25:53,348 - jnpr.ansible_module.juniper_junos_software - INFO -


[mx1a.example.com] installing software ... please be patient ...
2017-12-08 12:25:53,348 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'
2017-12-08 12:31:11,822 - jnpr.ansible_module.juniper_junos_software - INFO -
[mx1a.example.com] software pkgadd package-result: 0
Output:
Installing package '/var/tmp/jinstall-ppc-17.3R1.10-signed.tgz' ...
Verified jinstall-ppc-17.3R1.10.tgz signed by PackageProductionEc_2017 method
ECDSA256+SHA256
...
97

Saving state for rollback ...

2017-12-08 12:31:11,823 - ncclient.operations.rpc - INFO - Requesting 'ExecuteRpc'


2017-12-08 12:31:22,212 - ncclient.operations.rpc - INFO - Requesting 'CloseSession'

Meaning
The log file contents indicate that the image was successfully copied to and installed on the target device.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_software module replaces
the functionality of the junos_install_os module.

RELATED DOCUMENTATION

Understanding the Ansible for Junos OS Modules | 23


Using Ansible to Halt, Reboot, or Shut Down Devices Running Junos OS | 97
Using Ansible to Restore a Device Running Junos OS to the Factory-Default Configuration Settings | 107

Using Ansible to Halt, Reboot, or Shut Down Devices


Running Junos OS

IN THIS SECTION

Using Ansible to Halt, Reboot, or Shut Down Devices | 98

Example: Using Ansible to Reboot Devices | 101


98

Using Ansible to Halt, Reboot, or Shut Down Devices

The juniper_junos_system module in the Juniper.junos role enables you to halt, reboot, or shut down
devices running Junos OS. You can perform an immediate system halt, reboot, or shutdown operation,
request the operation with an optional delay, or you can schedule the operation at a specified date and
time. By default, the juniper_junos_system module immediately executes the requested operation and
performs the operation on all Routing Engines, if in a dual Routing Engine or Virtual Chassis setup.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.

The juniper_junos_system module requires one argument, action, which defines the action that the module
performs. Table 8 on page 98 defines the action parameter value that is required to halt, reboot, or shut
down the device running Junos OS and provides a brief description of each action as well as the
corresponding CLI command. For information about the "zeroize" action, see “Using Ansible to Restore a
Device Running Junos OS to the Factory-Default Configuration Settings” on page 107.

Table 8: juniper_junos_system action Parameter Values

Value of action
Parameter Description Equivalent CLI Command

"halt" Gracefully shut down the Junos OS software but request system halt
maintain system power

"reboot" Reboot the Junos OS software request system reboot

"shutdown" Gracefully shut down the Junos OS software and request system power-off
power off the Routing Engines

The following Ansible playbook uses the juniper_junos_system module with action: "reboot" to immediately
reboot all Routing Engines on the hosts in the specified inventory group.

---
- name: Reboot devices running Junos OS
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
99

tasks:
- name: Reboot all REs on the device
juniper_junos_system:
action: "reboot"

To delay the halt, reboot, or shut down operation by a specified number of minutes, set the optional in_min
parameter to the number of minutes that the system should wait before executing the operation. The
following task requests a reboot of all Routing Engines in 30 minutes:

tasks:
- name: Reboot all REs in 30 minutes
juniper_junos_system:
action: "reboot"
in_min: 30

To schedule the halt, reboot, or shutdown at a specific time, include the at parameter, which takes a string
that can be specified in one of the following ways:

• now—Immediately initiate the halt, reboot, or shut down of the software.

• +minutes—Number of minutes from now when the requested action is initiated.

• yymmddhhmm—Absolute time at which to initiate the requested action, specified as year, month, day,
hour, and minute.

• hh:mm—Absolute time on the current day at which to initiate the requested action, specified in 24-hour
time.

The following task schedules a system shutdown of all Routing Engines at 22:30 on the current day:

tasks:
- name: Shut down all REs at 22:30 on the current day
juniper_junos_system:
action: "shutdown"
at: "22:30"

By default the juniper_junos_system module halts, reboots, or shuts down all Routing Engines in a dual
Routing Engine or Virtual Chassis setup. You can also instruct the module to perform the operation on
only the Routing Engine to which the application is connected or to perform the operation on all other
Routing Engines except the one to which the application is connected.
100

To explicitly indicate that the operation should be performed on all Routing Engines in a dual Routing
Engine or Virtual Chassis setup, include the all_re: true argument, which is the default.

tasks:
- name: Reboot all Routing Engines
juniper_junos_system:
action: "reboot"
all_re: true

To perform the requested action on only the Routing Engine to which the application is connected, include
the all_re: false argument.

tasks:
- name: Reboot only the connected Routing Engine
juniper_junos_system:
action: "reboot"
all_re: false

To perform the requested action on all other Routing Engines in the system but not on the Routing Engine
to which the application is connected, include the other_re: true argument.

tasks:
- name: Shut down all other Routing Engines
juniper_junos_system:
action: "shutdown"
other_re: true

Table 9 on page 100 summarizes the all_re and other_re values that are required to execute the requested
operation on specific Routing Engines.

Table 9: juniper_junos_system Parameters for Specifying Routing Engines

Affected Routing Engines all_re Parameter other_re Parameter

All Routing Engines (default) Omitted or set to true Omitted

Only the connected Routing Engine Set to false Omitted

All other Routing Engines except the Routing Engine Omitted Set to true
to which the application is connected
101

Example: Using Ansible to Reboot Devices

IN THIS SECTION

Requirements | 101

Overview | 101

Configuration | 102

Executing the Playbook | 105

Verification | 107

Juniper Networks provides support for using Ansible to manage devices running Junos OS. This example
outlines how to use Ansible to reboot a device running Junos OS.

Requirements

This example uses the following hardware and software components:

• Configuration management server running Ansible 2.1 or later with version 2.0.0 or later of the
Juniper.junos role installed

• Device running Junos OS with NETCONF enabled and a user account configured with appropriate
permissions

• SSH public/private key pair configured for the appropriate user on the Ansible server and device running
Junos OS

• Existing Ansible inventory file with required hosts defined

Overview

The juniper_junos_system module in the Juniper.junos role enables you to halt, reboot, or shut down
devices running Junos OS. The value of the module’s, action argument defines the operation to execute
on the host. This example presents an Ansible playbook that uses the juniper_junos_system module to
reboot a device running Junos OS.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.
102

When calling the module from a playbook, we recommend that you use an interactive prompt to confirm
that the user does intend to reboot the specified devices. If a user unintentionally runs the playbook and
there is no check, it could adversely affect any networks that require the affected devices. As a precaution,
this playbook uses an interactive prompt to verify that the user intends to reboot the devices and requires
that the user manually type 'yes' on the command line to execute the module. If the Confirmation check
task fails, the Ansible control machine skips the other tasks in the play for that device.

This playbook includes the task Checking NETCONF connectivity, which utilizes the Ansible module
wait_for to try to establish a NETCONF session with the device running Junos OS using the NETCONF
default port 830. If the control machine fails to establish a NETCONF session with the device during
playbook execution, it skips the remaining tasks in the play for that device.

The task to reboot the device executes the juniper_junos_system module provided that the confirmation
and NETCONF checks were successful. The action argument is set to the value "reboot", which indicates
that the software should be rebooted. To halt or shut down the device, set the action argument to "halt"
or "shutdown", respectively. The in_min: 2 argument instructs the module to wait for the specified number
of minutes before executing the reboot command. This provides time for any users to log out of the system.

The task stores the module result in the result variable and notifies two handlers. The pause_for_reboot
handler waits a specified amount of time after the reboot operation is initiated to prevent the wait_reboot
handler from falsely detecting that the device is online before the reboot takes place. The wait_reboot
handler then tries to establish a session with the device to verify that the device comes back online after
the reboot. The wait_time_after_reboot variable defines the length of time that the control machine
attempts to reconnect with the device.

Configuration

Creating and Executing the Ansible Playbook

Step-by-Step Procedure
To create a playbook that uses the juniper_junos_system module to reboot a device running Junos OS:

1. Include the boilerplate for the playbook and this play, which must contain connection: local and the
Juniper.junos role.

---
- name: Reboot devices running Junos OS
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
103

2. Define or import any necessary variables.

vars:
wait_time_after_reboot: 300
netconf_port: 830

3. Create an interactive prompt to prevent the accidental execution of the module.

vars_prompt:
- name: "reboot_confirmation"
prompt: "This playbook reboots devices. Enter 'yes' to continue"
private: no

4. Create the task that confirms the users intent.

tasks:
- name: Confirmation check
fail: msg="Playbook run confirmation failed"
when: reboot_confirmation != "yes"

5. (Optional) Create a task to verify NETCONF connectivity.

- name: Checking NETCONF connectivity


wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: 5

6. Create the task to reboot the device after the specified number of minutes.

- name: Reboot all Routing Engines on the device running Junos OS


juniper_junos_system:
action: "reboot"
in_min: 2
all_re: true
register: result
notify:
- pause_for_reboot
- wait_reboot
104

7. (Optional) Create a task to print the response.

- name: Print response


debug:
var: result

8. Create the handler that pauses after rebooting and the handler that verifies that the device comes back
online after rebooting.

The handler names should be the same as those referenced in the installation task.

handlers:
- name: pause_for_reboot
pause:
seconds: 180
when: result.reboot
- name: wait_reboot
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: "{{ wait_time_after_reboot }}"
when: result.reboot

Results

On the Ansible control machine, review the completed playbook. If the playbook does not display the
intended code, repeat the instructions in this example to correct the playbook.

---
- name: Reboot devices running Junos OS
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars:
wait_time_after_reboot: 300
netconf_port: 830

vars_prompt:
- name: "reboot_confirmation"
prompt: "This playbook reboots devices. Enter 'yes' to continue"
105

private: no

tasks:
- name: Confirmation check
fail: msg="Playbook run confirmation failed"
when: reboot_confirmation != "yes"

- name: Checking NETCONF connectivity


wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: 5

- name: Reboot all Routing Engines on the device running Junos OS


juniper_junos_system:
action: "reboot"
in_min: 2
all_re: true
register: result
notify:
- pause_for_reboot
- wait_reboot

- name: Print response


debug:
var: result

handlers:
- name: pause_for_reboot
pause:
seconds: 180
when: result.reboot
- name: wait_reboot
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: "{{ wait_time_after_reboot }}"
when: result.reboot

Executing the Playbook

Step-by-Step Procedure
106

To execute the playbook:

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

user@ansible-cm:~/ansible$ ansible-playbook ansible-pb-junos-reboot.yaml

This playbook reboots devices. Enter 'yes' to continue: yes

PLAY [Reboot devices running Junos OS] ****************************************

TASK [Confirmation check] *****************************************************


skipping: [dc1a.example.net]

TASK [Checking NETCONF connectivity] ******************************************


ok: [dc1a.example.net]

TASK [Reboot all Routing Engines on the device running Junos OS] **************
changed: [dc1a.example.net]

TASK [Print response] *********************************************************


ok: [dc1a.example.net] => {
"result": {
"action": "reboot",
"all_re": true,
"changed": true,
"failed": false,
"media": false,
"msg": "reboot successfully initiated.",
"other_re": false,
"reboot": true
}
}

RUNNING HANDLER [pause_for_reboot] ********************************************


Pausing for 180 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [dc1a.example.net]

RUNNING HANDLER [wait_reboot] *************************************************


ok: [dc1a.example.net]

PLAY RECAP ********************************************************************


dc1a.example.net : ok=5 changed=1 unreachable=0 failed=0
107

Verification

Verifying the Reboot

Purpose
Verify that the device running Junos OS successfully rebooted.

Action
When you execute the playbook, review the execution output of the wait_reboot task.

RUNNING HANDLER [wait_reboot] *************************************************


ok: [dc1a.example.net]

Meaning
The wait_reboot result indicates whether the control machine successfully established a session with the
device after it rebooted. If the result indicates success, the device is online.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.

RELATED DOCUMENTATION

Using Ansible to Restore a Device Running Junos OS to the Factory-Default Configuration Settings | 107
Understanding the Ansible for Junos OS Modules | 23

Using Ansible to Restore a Device Running Junos OS


to the Factory-Default Configuration Settings

IN THIS SECTION

Using Ansible to Restore the Factory-Default Configuration Settings | 108

Example: Using Ansible to Restore the Factory-Default Configuration Settings | 109


108

Using Ansible to Restore the Factory-Default Configuration Settings

The juniper_junos_system module in the Juniper.junos role enables you to restore a device running Junos
OS to the factory-default configuration settings. To restore a device to the factory-default configuration,
the juniper_junos_system module action argument must be set to 'zeroize'. After a device is restored to
the factory-default configuration settings, you must log in through the console as root in order to access
the device.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.

The action: "zeroize" argument causes the juniper_junos_system module to execute the request system
zeroize operational command on the target host. This command removes all configuration information on
the specified Routing Engines, resets all key values on the device, and then reboots the device and resets
it to the factory-default configuration settings. The zeroize operation removes all data files, including
customized configuration and log files, by unlinking the files from their directories, and it also removes all
user-created files from the system including all plain-text passwords, secrets, and private keys for SSH,
local encryption, local authentication, IPsec, RADIUS, TACACS+, and SNMP. For more information about
the request system zeroize command, see request system zeroize.

The following Ansible playbook uses the juniper_junos_system module with action: "zeroize" to restore
all Routing Engines on each host in the inventory group to the factory-default configuration settings.

---
- name: Restore devices running Junos OS to factory-default configuration
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Restore all Routing Engines to factory-default configuration
juniper_junos_system:
action: "zeroize"

By default, the juniper_junos_system module with action: "zeroize" restores all Routing Engines in a dual
Routing Engine or Virtual Chassis setup to the factory-default configuration settings. You can also instruct
the module to perform the operation on only the Routing Engine to which the application is connected.
109

To explicitly indicate that the operation should be performed on all Routing Engines in a dual Routing
Engine or Virtual Chassis setup, include the all_re: true argument, which is the default.

tasks:
- name: Restore all Routing Engines to factory-default configuration
juniper_junos_system:
action: "zeroize"
all_re: true

To perform the requested action on only the Routing Engine to which the application is connected, include
the all_re: false argument.

tasks:
- name: Restore connected Routing Engine to factory-default configuration
juniper_junos_system:
action: "zeroize"
all_re: false

To instruct the juniper_junos_system module to also scrub all memory and media, in addition to removing
all configuration and log files, include the media: true argument. Including the media: true argument is
equivalent to executing the request system zeroize media operational mode command. The media option
scrubs every storage device attached to the system, including disks, flash memory devices, removable
USBs, and so on. The duration of the scrubbing process is dependent on the size of the media being erased.

tasks:
- name: Restore device to the factory-default configuration and scrub all media

juniper_junos_system:
action: "zeroize"
media: true

Example: Using Ansible to Restore the Factory-Default Configuration


Settings

IN THIS SECTION

Requirements | 110

Overview | 110
110

Configuration | 111

Executing the Playbook | 114

Verification | 115

Juniper Networks provides support for using Ansible to manage devices running Junos OS. This example
outlines how to use Ansible and the juniper_junos_system module to restore a device running Junos OS
to the factory-default configuration settings. You can execute the module through the console or through
NETCONF over SSH; however, once you reset the device, you can only access it again through the console
as root.

Requirements

This example uses the following hardware and software components:

• Configuration management server running Ansible 2.1 or later with version 2.0.0 or later of the
Juniper.junos role installed

• Device running Junos OS that has access to the console port through a console server and has a user
account configured with appropriate permissions

• Existing Ansible inventory file with required hosts defined

Overview

The juniper_junos_system module in the Juniper.junos role enables you to restore a device running Junos
OS to the factory-default configuration settings. This example presents an Ansible playbook that uses the
juniper_junos_system module to reset each host in the inventory group to the factory-default configuration
through a console server. The value of the module’s action argument defines the operation to execute on
the host. Setting action to "zeroize" executes the request system zeroize operational command on each
host. This command removes all configuration information on the Routing Engines, resets all key values
on the device, and then reboots the device and resets it to the factory-default configuration settings.

NOTE: The request system zeroize command removes all data files, including customized
configuration and log files, by unlinking the files from their directories. The command also removes
all user-created files from the system including all plain-text passwords, secrets, and private keys
for SSH, local encryption, local authentication, IPsec, RADIUS, TACACS+, and SNMP.
111

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.

When calling the module from a playbook, we recommend that you use an interactive prompt to confirm
that the user does intend to reset the devices. If a user unintentionally runs the playbook and there is no
check, it could inadvertently revert devices back to factory-default configurations and disrupt any networks
that require those devices. As a precaution, this playbook uses an interactive prompt to verify that the
user intends to reset the devices, and requires that the user manually type 'yes' on the command line in
order to execute the module. If the Confirmation check task fails, the Ansible control machine skips the
other tasks in the play for that device.

The task that restores the hosts to the factory-default configuration executes the juniper_junos_system
module provided that the confirmation check was successful. The mode: "telnet" and port: 23 arguments
instruct the module to telnet to port 23 of the console server. The password parameter is set to the value
of the password variable, which the playbook prompts for during execution. After the reboot, you must
log in through the console as root in order to access the device.

Configuration

Creating and Executing the Ansible Playbook

Step-by-Step Procedure
To create a playbook that uses the juniper_junos_system module to restore a device running Junos OS to
its factory-default configuration settings:

1. Include the boilerplate for the playbook and this play, which must contain connection: local and the
Juniper.junos role.

---
- name: Restore devices running Junos OS to factory-default configuration settings

hosts: dc1_console
roles:
- Juniper.junos
connection: local
gather_facts: no
112

2. Create an interactive prompt for the password variable, if the user credentials are not already passed
in through some other means.

vars_prompt:
- name: "device_password"
prompt: "Device password"
private: yes

3. Create an interactive prompt to prevent the accidental execution of the module.

- name: reset_confirmation
prompt: >
This playbook resets hosts to factory-default configurations!
Enter 'yes' to continue.
default: "no"
private: no

4. Create the task that confirms the users intent.

tasks:
- name: Confirmation check
fail: msg="Playbook run confirmation failed"
when: reset_confirmation != "yes"

5. Create the task to reset all Routing Engines on the device to the factory-default configuration settings.

- name: Restore all Routing Engines to factory-default configuration


juniper_junos_system:
provider:
password: "{{ device_password }}"
mode: "telnet"
port: 23
action: "zeroize"
register: result
113

6. (Optional) Create a task to print the response.

- name: Print response


debug:
var: result

Results

On the Ansible control machine, review the completed playbook. If the playbook does not display the
intended code, repeat the instructions in this example to correct the playbook.

---
- name: Restore devices running Junos OS to factory-default configuration settings
hosts: dc1_console
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_prompt:
- name: "device_password"
prompt: "Device password"
private: yes

- name: reset_confirmation
prompt: >
This playbook resets hosts to factory-default configurations!
Enter 'yes' to continue.
default: "no"
private: no

tasks:
- name: Confirmation check
fail: msg="Playbook run confirmation failed"
when: reset_confirmation != "yes"

- name: Restore all Routing Engines to factory-default configuration


juniper_junos_system:
provider:
password: "{{ device_password }}"
mode: "telnet"
port: 23
action: "zeroize"
register: result
114

- name: Print response


debug:
var: result

Executing the Playbook

Step-by-Step Procedure
115

To execute the playbook:

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

root@ansible-cm:~/ansible# ansible-playbook ansible-pb-junos-zeroize.yaml

Device password:
This playbook resets hosts to factory-default configurations! Enter 'yes' to
continue.
[no]: yes

PLAY [Restore devices running Junos OS to factory-default configuration settings]

TASK [Confirmation check] **********************************************


skipping: [dc1a-console.example.net]

TASK [Restore all Routing Engines to factory-default configuration] ****


changed: [dc1a-console.example.net]

TASK [Print response] **************************************************


ok: [dc1a-console.example.net] => {
"result": {
"action": "zeroize",
"all_re": true,
"changed": true,
"failed": false,
"media": false,
"msg": "zeroize successfully initiated.",
"other_re": false,
"reboot": false
}
}

PLAY RECAP ************************************************************


dc1a-console.example.net : ok=2 changed=1 unreachable=0 failed=0

Verification

Verifying Playbook Execution

Purpose
Verify that the devices running Junos OS were successfully reset to the factory-default configuration.
116

Action

Access the device through the console port as root. The device should now be in Amnesiac state.

Amnesiac <ttyd0>

login:

Meaning
The Amnesiac prompt is indicative of a device that is booting from a factory-default configuration and
that does not have a hostname configured.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_system module replaces
the functionality of the junos_shutdown and junos_zeroize modules.

RELATED DOCUMENTATION

Using Ansible to Halt, Reboot, or Shut Down Devices Running Junos OS | 97


Understanding the Ansible for Junos OS Modules | 23

Using Junos Snapshot Administrator in Python


(JSNAPy) in Ansible Playbooks

IN THIS SECTION

juniper_junos_jsnapy Module Overview | 117

Taking and Comparing Snapshots | 120

Performing Snapcheck Operations | 123

Understanding the juniper_junos_jsnapy Module Output | 124

Enabling the jsnapy Callback Plugin | 126

Example: Using the juniper_junos_jsnapy Module to Perform a JSNAPy Snapcheck Operation | 127
117

®
Junos Snapshot Administrator in Python (JSNAPy) enables you to capture and audit runtime environment
snapshots of your network devices running Junos OS. You can capture and verify the operational and
configuration status of a device and verify changes to a device. The juniper_junos_jsnapy Ansible module
in the Juniper.junos role enables you to execute JSNAPy tests against devices running Junos OS as part
of an Ansible playbook.

NOTE: The Ansible control machine must have Junos Snapshot Administrator in Python Release
1.2.1 or later installed in order to use the juniper_junos_jsnapy module. For installation instructions
and information about creating JSNAPy configuration and test files, see the Junos Snapshot
Administrator in Python Documentation.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_jsnapy module replaces
the functionality of the junos_jsnapy module.

The following sections discuss how to use the juniper_junos_jsnapy module in Ansible playbooks:

juniper_junos_jsnapy Module Overview

The juniper_junos_jsnapy Ansible module enables you to execute many of the same JSNAPy functions
from an Ansible playbook as you can execute using JSNAPy on the command line, including capturing and
saving a runtime environment snapshot, comparing two snapshots, or capturing a snapshot and immediately
evaluating it. The juniper_junos_jsnapy module requires the action argument and either the config_file or
the test_files argument.

The action argument specifies the JSNAPy action to perform. Table 10 on page 117 outlines the valid action
values and the equivalent JSNAPy commands.

Table 10: juniper_junos_jsnapy action Argument

Equivalent JSNAPy
action Value Description Command

check Compare two snapshots based on the given test cases, or if no jsnapy --check
test cases are supplied, compare the snapshots node by node.

snap_post Take snapshots for the commands or RPCs specified in the test jsnapy --snap
files after making changes on the given devices.
118

Table 10: juniper_junos_jsnapy action Argument (continued)

Equivalent JSNAPy
action Value Description Command

snap_pre Take snapshots for the commands or RPCs specified in the test jsnapy --snap
files prior to making changes on the given devices.

snapcheck Take snapshots of the commands or RPCs specified in the test jsnapy --snapcheck
files and immediately evaluate the snapshots against pre-defined
criteria in the test cases.

When you execute JSNAPy on the command line, JSNAPy performs the requested action on the hosts
specified in the hosts section of the configuration file. In contrast, the juniper_junos_jsnapy module
executes the requested action on the hosts in the Ansible inventory group defined in the playbook. As a
result, the juniper_junos_jsnapy module can either reference a configuration file, ignoring the hosts section,
or it can directly reference one or more test files.

Thus, in addition to the action argument, the juniper_junos_jsnapy module also requires either the config_file
or the test_files argument to specify the JSNAPy configuration file or the JSNAPy test files to use for the
given action. Table 11 on page 118 outlines the config_file and test_files arguments.

Table 11: juniper_junos_jsnapy File Arguments

Module
argument Value Additional Information

config_file Absolute or relative file path If the path is relative, the module checks for the configuration file in
to a JSNAPy configuration the following locations and in the order indicated:
file.
• Ansible playbook directory
• Directory specified by the dir argument, if provided
• /etc/jsnapy/testfiles directory (only if the dir argument is omitted)
If the configuration file references test files by using a relative file
path, the module first checks for the test files in the playbook directory
and then checks for the test files in the default testfiles directory,
which will vary depending on the JSNAPy release.

test_files Absolute or relative file path For each test file that specifies a relative path, the module checks for
to a JSNAPy test file. This can the file in the following locations and in the order indicated:
be a single file path or a list of
file paths. • Ansible playbook directory
• Directory specified by the dir argument, if provided
• /etc/jsnapy/testfiles directory (only if the dir argument is omitted)
119

The config_file and test_files arguments can take an absolute or relative file path. When using a relative
file path, you can optionally include the dir module argument to specify the directory in which the files
reside. If a config_file or test_files argument uses a relative file path, the module first checks for the file
under the Ansible playbook directory, even if the dir argument is present. If the file does not exist under
the playbook directory, the module checks under the dir argument directory, if it is specified, or under the
/etc/jsnapy/testfiles directory, if the dir argument is omitted. The playbook generates an error message
if the file is not found.

The following sample playbook performs the snap_pre action using the configuration_interface_status.yaml
configuration file. If the configuration file does not exist in the playbook directory, the module checks for
the file in the user’s home directory under the jsnapy/testfiles subdirectory.

---
- name: Junos Snapshot Administrator tests
hosts: dc1a
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Take a pre-maintenance snapshot of the interfaces
juniper_junos_jsnapy:
action: "snap_pre"
dir: "~/jsnapy/testfiles"
config_file: "configuration_interface_status.yaml"

NOTE: Starting in Junos Snapshot Administrator in Python Release 1.3.0, the JSNAPy directory
structure is modified such that the default location for configuration and test files is the
~/jsnapy/testfiles directory.

The juniper_junos_jsnapy module performs the requested action on the hosts specified in the Ansible
playbook, even if the module references a configuration file that includes a hosts section. The module
reports failed if it encounters an error and fails to execute the JSNAPy tests. It does not report failed if
one or more of the JSNAPy tests fail. To check the JSNAPy test results, register the module’s response,
and use the assert module to verify the expected result in the response.

Junos Snapshot Administrator in Python logs information regarding its operations to the
/var/log/jsnapy/jsnapy.log file by default. The juniper_junos_jsnapy module can optionally include the
logfile argument, which specifies the path to a writable file on the Ansible control machine where information
for the particular task is logged. The level of information logged in the file is determined by Ansible’s
verbosity level and debug options. By default, only messages of severity level WARNING or higher are
120

logged. To log messages equal to or higher than severity level INFO or severity level DEBUG, execute the
playbook with the -v or -vv command-line option, respectively.

When you execute JSNAPy tests in an Ansible playbook, you can enable the jsnapy callback plugin to
capture and summarize information for failed JSNAPy tests. To enable the callback plugin, add the
callback_whitelist = jsnapy statement to the Ansible configuration file. For more information, see “Enabling
the jsnapy Callback Plugin” on page 126.

Taking and Comparing Snapshots

JSNAPy enables you to capture runtime environment snapshots of your network devices running Junos
OS before and after a change and compare the snapshots to verify the expected changes or identify
unexpected issues. The juniper_junos_jsnapy Ansible module enables you to take and compare JSNAPy
snapshots as part of an Ansible playbook. The module saves each snapshot for each host in a separate file
in the default JSNAPy snapshot directory using a predetermined filename. For more information about
juniper_junos_jsnapy output files, see “Understanding the juniper_junos_jsnapy Module Output” on page 124.

NOTE: Starting in Junos Snapshot Administrator in Python Release 1.3.0, the default directories
for the JSNAPy test files and snapshots are ~/jsnapy/testfiles and ~/jsnapy/snapshots,
respectively.

To take baseline snapshots of one or more devices prior to making changes, set the juniper_junos_jsnapy
module’s action argument to snap_pre, and specify a configuration file or one or more test files.

The following playbook saves PRE snapshots for each device in the Ansible inventory group. The task
references the configuration_interface_status.yaml configuration file in the ~/jsnapy/testfiles directory
and logs messages to the jsnapy_tests.log file in the playbook directory.

---
- name: Junos Snapshot Administrator tests
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Take a pre-maintenance snapshot of the interfaces
juniper_junos_jsnapy:
121

action: "snap_pre"
dir: "~/jsnapy/testfiles"
config_file: "configuration_interface_status.yaml"
logfile: "jsnapy_tests.log"

To take a snapshot of one or more devices after performing changes, set the juniper_junos_jsnapy module’s
action argument to snap_post, and specify a configuration file or one or more test files.

The following playbook saves POST snapshots for each device in the Ansible inventory group. The task
references the configuration_interface_status.yaml configuration file in the ~/jsnapy/testfiles directory
and logs messages to the jsnapy_tests.log file in the playbook directory.

---
- name: Junos Snapshot Administrator tests
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Take a post-maintenance snapshot of the interfaces
juniper_junos_jsnapy:
action: "snap_post"
dir: "~/jsnapy/testfiles"
config_file: "configuration_interface_status.yaml"
logfile: "jsnapy_tests.log"

When the juniper_junos_jsnapy module performs a snap_pre action or a snap_post action, it saves each
snapshot for each host in a separate file using auto-generated filenames that contain a 'PRE' or 'POST' tag,
respectively. To compare the PRE and POST snapshots to quickly verify the updates or identify any issues
that might have resulted from the changes, set the module’s action argument to check, and specify the
same configuration file or test files that were used to take the snapshots.

When the juniper_junos_jsnapy module performs a check action, the preexisting PRE and POST snapshots
for each test on each device are compared and evaluated against the criteria defined in the tests: section
of the test files. If the test files do not define any test cases, JSNAPy instead compares the snapshots node
by node. To check the test results, register the juniper_junos_jsnapy module’s response, and use the assert
module to verify the expected result in the response.
122

The following playbook compares the snapshots taken for previously executed snap_pre and snap_post
actions for every device in the Ansible inventory group. The results are evaluated using the criteria in the
test files that are referenced in the configuration file. The playbook registers the module’s response as
'test_result' and uses the assert module to verify that all tests passed on the given device.

---
- name: Junos Snapshot Administrator tests
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Compare PRE and POST snapshots
juniper_junos_jsnapy:
action: "check"
dir: "~/jsnapy/testfiles"
config_file: "configuration_interface_status.yaml"
logfile: "jsnapy_tests.log"
register: test_result

- name: Verify JSNAPy tests passed


assert:
that:
- "test_result.passPercentage == 100"

When you run the playbook, the assertions quickly identify which devices failed the tests.

user@host:~$ ansible-playbook jsnapy-interface-check.yaml

PLAY [Junos Snapshot Administrator tests] *************************************

TASK [Compare PRE and POST snapshots] *****************************************


ok: [dc1a.example.net]
ok: [dc1b.example.net]

TASK [Verify JSNAPy tests passed] *********************************************


ok: [dc1b.example.net] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}
123

fatal: [dc1a.example.net]: FAILED! => {


"assertion": "test_result.passPercentage == 100",
"changed": false,
"evaluated_to": false,
"failed": true
}
to retry, use: --limit @/home/user/jsnapy-interface-check.retry

PLAY RECAP ********************************************************************


dc1b.example.net : ok=2 changed=0 unreachable=0 failed=0
dc1a.example.net : ok=1 changed=0 unreachable=0 failed=1

Performing Snapcheck Operations

JSNAPy enables you to take snapshots of the commands or RPCs specified in JSNAPy test files and
immediately evaluate the snapshots against pre-defined criteria in the test cases. The juniper_junos_jsnapy
Ansible module enables you to perform a JSNAPy snapcheck operation as part of an Ansible playbook.

To take a snapshot and immediately evaluate it based on the pre-defined set of criteria in the tests: section
of the test files, set the juniper_junos_jsnapy module’s action argument to snapcheck, and specify a
configuration file or one or more test files. To check the test results, register the module’s response, and
use the assert module to verify the expected result in the response.

For example, for each device in the Ansible inventory group, the following playbook saves a separate
snapshot for each command or RPC in the test files, registers the juniper_junos_jsnapy module’s response,
and uses the assert module to verify that all tests defined in the test files passed on that device.

---
- name: Junos Snapshot Administrator tests
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Take a snapshot and immediately evaluate it
juniper_junos_jsnapy:
action: "snapcheck"
dir: "~/jsnapy/testfiles/"
124

test_files:
- "test_interface_status.yaml"
- "test_bgp_neighbor.yaml"
logfile: "jsnapy_tests.log"
register: test_result

- name: Verify JSNAPy tests passed


assert:
that:
- "test_result.passPercentage == 100"

Understanding the juniper_junos_jsnapy Module Output

When the juniper_junos_jsnapy module performs a snap_pre, snap_post, or snapcheck action, it


automatically saves the snapshots in the default JSNAPy snapshots directory. The juniper_junos_jsnapy
module creates a separate file for each command or RPC executed on each device in the Ansible inventory
group. Table 12 on page 124 outlines the filenames of the snapshot files for each value of the action
argument.

NOTE: Starting in Junos Snapshot Administrator in Python Release 1.3.0, the default directories
for the JSNAPy test files and snapshots are ~/jsnapy/testfiles and ~/jsnapy/snapshots. In earlier
release, the default directories are /etc/jsnapy/testfiles and /etc/jsnapy/snapshots.

Table 12: juniper_junos_jsnapy Output Filenames

action value Output Files

snap_pre hostname_PRE_hash_command.format

snap_post hostname_POST_hash_command.format

snapcheck hostname_snap_temp_hash_command.format

where:

• hostname—Hostname of the device on which the command or RPC is executed.

• hash—Hash generated from kwargs for test files that include the rpc and kwargs keys. If test files use
the same RPC but include different arguments, and the RPCs are executed on the same host, the hash
125

ensures unique output filenames in those cases. If a test file defines the command key, or a test file
defines the rpc key but does not include the kwargs key, the hash value is omitted.

• command—Command or RPC executed on the managed device. The module replaces whitespace and
special characters in the command or RPC name with underscores ( _ ).

• format—Format of the output, for example, xml.

NOTE: The juniper_junos_jsnapy module only differentiates the snapshot filenames for a given
action based on hostname and command or RPC. As a result, if the module takes snapshots on
the same device for the same action using test files that define the same command or RPC, the
module will generate snapshots with the same filename, and the new file will overwrite the old
file.

For example, if the juniper_junos_jsnapy module includes action: "snap_pre" and references test files that
execute the show chassis fpc and show interfaces terse commands on devices dc1a.example.net and
dc1b.example.net, the resulting files would be:

user@ansible-cm:~$ ls jsnapy/snapshots
dc1a.example.net_PRE_show_chassis_fpc.xml
dc1a.example.net_PRE_show_interfaces_terse.xml
dc1b.example.net_PRE_show_chassis_fpc.xml
dc1b.example.net_PRE_show_interfaces_terse.xml

If the juniper_junos_jsnapy module includes action: "snap_post" and references a test file that executes
the get-interface-information RPC with kwargs item interface_name: lo0 on device dc1a.example.net,
the resulting file would be:

dc1a.example.net_POST_r1w59I99HXxC3u0VXXshbw==_get_interface_information.xml

In addition to generating the snapshot files, the juniper_junos_jsnapy module also returns the following
keys in its response:

• action—JSNAPy action performed by the module.

• changed—Indicates if the device’s state changed. Since JSNAPy only reports on state, the value is always
false.

• failed—Indicates if the playbook task failed.

• msg—JSNAPy test results.


126

Enabling the jsnapy Callback Plugin

When you execute JSNAPy tests against devices running Junos OS and one or more tests fail, it can be
difficult to identify and extract the failed tests if the output is extensive. The jsnapy callback plugin enables
you to easily extract and summarize the information for failed JSNAPy tests. When you enable the jsnapy
callback plugin and execute a playbook that includes JSNAPy tests, the plugin summarizes the information
for the failed JSNAPy tests after the playbook PLAY RECAP.

Callback plugins are not enabled by default. To enable the jsnapy callback plugin, add the
callback_whitelist = jsnapy statement to the Ansible configuration file.

[defaults]
callback_whitelist = jsnapy

When you enable the jsnapy callback plugin and run a playbook, the plugin summarizes the failed JSNAPy
tests in a human-readable format. For example:

PLAY RECAP ****************************************************************


qfx10002-01 : ok=3 changed=0 unreachable=0 failed=1
qfx10002-02 : ok=3 changed=0 unreachable=0 failed=1
qfx5100-01 : ok=1 changed=0 unreachable=0 failed=1

JSNAPy Results for: qfx10002-01 *******************************************


Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with
{"peer-as": "64502", "peer-state": "Active", "peer-address": "198.51.100.21"}
Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with
{"peer-as": "64510", "peer-state": "Idle", "peer-address": "192.168.0.1"}
Value of 'oper-status' not 'is-equal' at
'//interface-information/physical-interface[normalize-space(admin-status)='up' and
logical-interface/address-family/address-family-name ]' with {"oper-status":
"down", "name": "et-0/0/18"}

JSNAPy Results for: qfx10002-02 *******************************************


Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with
{"peer-as": "64502", "peer-state": "Active", "peer-address": "198.51.100.21"}
127

Example: Using the juniper_junos_jsnapy Module to Perform a JSNAPy


Snapcheck Operation

IN THIS SECTION

Requirements | 127

Overview | 128

Configuration | 129

Executing the Playbook | 139

Verification | 142

Troubleshooting Ansible Playbook Errors | 143

The juniper_junos_jsnapy module enables you to execute JSNAPy tests against devices running Junos OS
as part of an Ansible playbook. This examples uses the juniper_junos_jsnapy module perform a snapcheck
action to verify the operational state of devices running Junos OS after applying specific configuration
changes.

Requirements

This example uses the following hardware and software components:

• Ansible control machine running:

• Ansible 2.1 or later

• Juniper.junos Ansible role version 2.0.0 or later

• Junos PyEZ Release 2.1.7 or later

• Junos Snapshot Administrator in Python Release 1.3.1 or later

Before executing the Ansible playbook, be sure you have:

• Devices running Junos OS with NETCONF over SSH enabled and a user account configured with
appropriate permissions

• SSH public/private key pair configured for the appropriate user on the Ansible control machine and
device running Junos OS

• Existing Ansible inventory file with required hosts defined


128

Overview

In this example, the Ansible playbook configures BGP peering sessions on three devices running Junos OS
and uses the juniper_junos_jsnapy module to verify that the BGP session is established for each neighbor
address. If the playbook verifies that the sessions are established on a device, it confirms the commit for
the new configuration. If the playbook does not confirm the commit, the device running Junos OS
automatically rolls back to the previously committed configuration. The Ansible project defines the group
and host variables for the playbook under the group_vars and host_vars directories, respectively.

The playbook has two plays. The first play, Load and commit BGP configuration, generates and assembles
the configuration, loads the configuration on the device, and commits it using a commit confirmed operation.
If the configuration is updated, one handler is notified. The play executes the following tasks:

Remove build directory—Deletes the existing build directory for the given device, if present.

Create build directory—Creates a new, empty build directory for the given device.

Build BGP configuration—Uses the template module with the Jinja2 template and host variables to render
the BGP configuration for the given device and save it to a file in the device’s build directory.

Assemble configuration parts—Uses the assemble module to assemble the device configuration file from
the files in that device’s build directory.

In this example, only the BGP configuration file will be present, and thus the resulting configuration
file is identical to the BGP configuration file rendered in the previous task. If you later add new tasks
to generate additional configuration files from other templates, the assemble module will combine all
files into a single configuration.

Load and commit config, require confirmation—Loads the configuration onto the device running Junos
OS and commits the configuration using a commit confirmed operation, which requires explicit
confirmation for the commit to become permanent. If this task makes a change to the configuration,
it also notifies the handler that pauses playbook execution for a specified amount of time to allow the
BGP peers to establish connections before the second play is executed.

If the requested configuration is already present on the device, the juniper_junos_config module does
not load and commit the configuration. In this case, the module returns changed: false, and thus does
not notify the handler.

The second play, Verify BGP, performs a JSNAPy snapcheck operation on each device using the tests in
the JSNAPy test files and confirms the commit, provided all tests pass. The play executes the following
tasks:

Execute snapcheck—Performs a JSNAPy snapcheck operation, which in this case, validates that the BGP
session is established for each of the device’s neighbors and that there are no down peers.
129

In this example, the playbook directly references JSNAPy test files by setting the test_files argument
equal to the list of JSNAPy test files. The dir argument specifies the directory where the test files are
stored.

Confirm commit—Executes a commit check operation, which confirms the previous commit operation,
provided that the first playbook play updated the configuration and that all of the JSNAPy tests passed.
If the playbook updates the configuration but does not confirm the commit, the device running Junos
OS automatically rolls the configuration back to the previously committed configuration.

NOTE: You can confirm the previous commit operation with either a commit check or commit
operation on the device, which corresponds to the check: true or commit: true argument,
respectively, in the juniper_junos_config module.

Verify BGP configuration—(Optional) Explicitly indicates whether the JSNAPy tests passed or failed on
the given device. This task is not specifically required, but it more easily identifies when the JSNAPy
tests fail and on which devices.

Configuration

IN THIS SECTION

Defining the Group Variables | 129

Defining the Host Variables and Jinja2 Template | 130

Creating the JSNAPy Test Files | 133

Creating the Ansible Playbook | 134


Results | 137

Defining the Group Variables

Step-by-Step Procedure
To define the group variables:

• In the group_vars/all file, define variables for the build directory and for the filenames of the
configuration and log files.
130

build_dir: "{{ playbook_dir }}/build_conf/{{ inventory_hostname }}"


junos_conf: "{{ build_dir }}/junos.conf"
logfile: "junos.log"

Defining the Host Variables and Jinja2 Template

Step-by-Step Procedure
To define the host variables that are used with the Jinja2 template to generate the BGP configuration:

1. In the project’s host_vars directory, create a separate file named hostname.yaml for each host.

2. Define the variables for host r1 in the r1.yaml file.

---
loopback: 192.168.0.1
local_asn: 64521
neighbors:
- interface: ge-0/0/0
name: to-r2
asn: 64522
peer_ip: 198.51.100.2
local_ip: 198.51.100.1
peer_loopback: 192.168.0.2
- interface: ge-0/0/1
name: to-r3
asn: 64523
peer_ip: 198.51.100.6
local_ip: 198.51.100.5
peer_loopback: 192.168.0.3

3. Define the variables for host r2 in the r2.yaml file.

---
loopback: 192.168.0.2
local_asn: 64522
neighbors:
- interface: ge-0/0/0
name: to-r1
asn: 64521
peer_ip: 198.51.100.1
local_ip: 198.51.100.2
peer_loopback: 192.168.0.1
131

- interface: ge-0/0/1
name: to-r3
asn: 64523
peer_ip: 198.51.100.10
local_ip: 198.51.100.9
peer_loopback: 192.168.0.3

4. Define the variables for host r3 in the r3.yaml file.

---
loopback: 192.168.0.3
local_asn: 64523
neighbors:
- interface: ge-0/0/0
name: to-r1
asn: 64521
peer_ip: 198.51.100.5
local_ip: 198.51.100.6
peer_loopback: 192.168.0.1
- interface: ge-0/0/1
name: to-r2
asn: 64522
peer_ip: 198.51.100.9
local_ip: 198.51.100.10
peer_loopback: 192.168.0.2

Step-by-Step Procedure
To create the Jinja2 template that is used to generate the BGP configuration:

1. Create a file named bgp-template.j2 in the project’s playbook directory.

2. Add the BGP configuration template to the file.

interfaces {
{% for neighbor in neighbors %}
{{ neighbor.interface }} {
unit 0 {
description "{{ neighbor.name }}";
family inet {
address {{ neighbor.local_ip }}/30;
}
132

}
}
{% endfor %}
lo0 {
unit 0 {
family inet {
address {{ loopback }}/32;
}
}
}
}
protocols {
bgp {
group underlay {
import bgp-in;
export bgp-out;
type external;
local-as {{ local_asn }};
multipath multiple-as;
{% for neighbor in neighbors %}
neighbor {{ neighbor.peer_ip }} {
peer-as {{ neighbor.asn }};
}
{% endfor %}
}
}
lldp {
{% for neighbor in neighbors %}
interface "{{ neighbor.interface }}";
{% endfor %}
}
}
routing-options {
router-id {{ loopback }};
forwarding-table {
export bgp-ecmp;
}
}

policy-options {
policy-statement bgp-ecmp {
then {
load-balance per-packet;
}
133

}
policy-statement bgp-in {
then accept;
}
policy-statement bgp-out {
then {
next-hop self;
accept;
}
}
}

Creating the JSNAPy Test Files

Step-by-Step Procedure
The juniper_junos_jsnapy module references JSNAPy test files in the ~/jsnapy/testfiles directory. To
create the JSNAPy test files:

1. Create the jsnapy_test_file_bgp_states.yaml file, which executes the show bgp neighbor command
and tests that the BGP peer state is established.

bgp_neighbor:
- command: show bgp neighbor
- ignore-null: True
- iterate:
xpath: '//bgp-peer'
id: './peer-address'
tests:
# Check if peers are in the established state
- is-equal: peer-state, Established
err: "Test Failed!! peer <{{post['peer-address']}}> state is not
Established, it is <{{post['peer-states']}}>"
info: "Test succeeded!! peer <{{post['peer-address']}}> state is
<{{post['peer-state']}}>"

2. Create the jsnapy_test_file_bgp_summary.yaml file, which executes the show bgp summary command
and asserts that the BGP down peers count must be 0.

bgp_summary:
- command: show bgp summary
- item:
xpath: '/bgp-information'
134

tests:
- is-equal: down-peer-count, 0
err: "Test Failed!! down-peer-count is not equal to 0. It is equal to
<{{post['down-peer-count']}}>"
info: "Test succeeded!! down-peer-count is equal to
<{{post['down-peer-count']}}>"

Creating the Ansible Playbook

Step-by-Step Procedure
To create the first play, which renders the configuration, loads it on the device, and commits the
configuration as a commit confirmed operation:

1. Include the boilerplate for the playbook and the first play, which must contain connection: local and
the Juniper.junos role.

---
- name: Load and commit BGP configuration
hosts: bgp-routers
connection: local
gather_facts: no
roles:
- Juniper.junos

2. Create the tasks that replace the existing build directory with an empty directory, which will hold the
new configuration files.

tasks:

- name: Remove build directory


file:
path: "{{ build_dir }}"
state: absent

- name: Create build directory


file:
path: "{{ build_dir }}"
state: directory
135

3. Create the task that renders the BGP configuration from the Jinja2 template file and host variables and
stores it in the bgp.conf file in the build directory for that host.

- name: Build BGP configuration


template:
src: "{{playbook_dir}}/bgp-template.j2"
dest: "{{ build_dir }}/bgp.conf"

4. Create a task to assemble the configuration files in the build directory into the final junos.conf
configuration file.

- name: Assemble configuration parts


assemble:
src: "{{ build_dir }}"
dest: "{{ junos_conf }}"

5. Create the task that loads the configuration on the device, performs a commit operation that requires
confirmation, and notifies the given handler, provided the configuration was changed.

- name: Load and commit config, require confirmation


juniper_junos_config:
load: "merge"
format: "text"
src: "{{ junos_conf }}"
confirm: 5
comment: "config by Ansible"
logfile: "{{ logfile }}"
register: config_result

# Notify handler, only if configuration changes.


notify:
- Waiting for BGP peers to establish connections

6. Create the handler that pauses playbook execution if the device configuration is updated, and set the
pause time to an appropriate value for your environment.

handlers:
- name: Waiting for BGP peers to establish connections
pause: seconds=60
136

Step-by-Step Procedure
To create the second play, which performs a JSNAPy snapcheck operation and confirms the committed
configuration, provided that the configuration changed and the JSNAPy tests passed:

1. Include the boilerplate for the second play, which must contain connection: local and the Juniper.junos
role.

- name: Verify BGP


hosts: bgp-routers
connection: local
gather_facts: no
roles:
- Juniper.junos

2. Create a task to perform a JSNAPy snapcheck operation based on the tests in the given JSNAPy test
files, and register the module’s response.

tasks:
- name: Execute snapcheck
juniper_junos_jsnapy:
action: "snapcheck"
dir: "~/jsnapy/testfiles"
test_files:
- "jsnapy_test_file_bgp_states.yaml"
- "jsnapy_test_file_bgp_summary.yaml"
logfile: "{{ logfile }}"
register: snapcheck_result

3. Create the task to confirm the commit provided that the given conditions are met.

# Confirm commit only if configuration changed and JSNAPy tests pass


- name: Confirm commit
juniper_junos_config:
check: true
commit: false
diff: false
logfile: "{{ logfile }}"
when:
- config_result.changed
- "snapcheck_result.passPercentage == 100"
137

4. (Optional) Create a task that uses the assert module to assert that the JSNAPy tests passed.

- name: Verify BGP configuration


assert:
that:
- "snapcheck_result.passPercentage == 100"
msg: "JSNAPy test on {{ inventory_hostname }} failed"

Results

On the Ansible control machine, review the completed playbook. If the playbook does not display the
intended code, repeat the instructions in this section to correct the playbook.

---
- name: Load and commit BGP configuration
hosts: bgp-routers
connection: local
gather_facts: no
roles:
- Juniper.junos

tasks:
- name: Remove build directory
file:
path: "{{ build_dir }}"
state: absent

- name: Create build directory


file:
path: "{{ build_dir }}"
state: directory

- name: Build BGP configuration


template:
src: "{{playbook_dir}}/bgp-template.j2"
dest: "{{ build_dir }}/bgp.conf"

- name: Assemble configuration parts


assemble:
src: "{{ build_dir }}"
dest: "{{ junos_conf }}"
138

- name: Load and commit config, require confirmation


juniper_junos_config:
load: "merge"
format: "text"
src: "{{ junos_conf }}"
confirm: 5
comment: "config by Ansible"
logfile: "{{ logfile }}"
register: config_result

# Notify handler, only if configuration changes.


notify:
- Waiting for BGP peers to establish connections

handlers:
- name: Waiting for BGP peers to establish connections
pause: seconds=60

- name: Verify BGP


hosts: bgp-routers
connection: local
gather_facts: no
roles:
- Juniper.junos

tasks:
- name: Execute snapcheck
juniper_junos_jsnapy:
action: "snapcheck"
dir: "~/jsnapy/testfiles"
test_files:
- "jsnapy_test_file_bgp_states.yaml"
- "jsnapy_test_file_bgp_summary.yaml"
logfile: "{{ logfile }}"
register: snapcheck_result

# Confirm commit only if configuration changed and JSNAPy tests pass


- name: Confirm commit
juniper_junos_config:
check: true
commit: false
diff: false
logfile: "{{ logfile }}"
when:
139

- config_result.changed
- "snapcheck_result.passPercentage == 100"

- name: Verify BGP configuration


assert:
that:
- "snapcheck_result.passPercentage == 100"
msg: "JSNAPy test on {{ inventory_hostname }} failed"

Executing the Playbook

Step-by-Step Procedure
140

To execute the playbook:


141

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

user@ansible-cm:~/ansible$ ansible-playbook ansible-pb-bgp-configuration.yaml

PLAY [Load and commit BGP configuration] *************************************

TASK [Remove build directory] ************************************************


changed: [r1]
changed: [r2]
changed: [r3]

TASK [Create build directory] ************************************************


changed: [r1]
changed: [r2]
changed: [r3]

TASK [Build BGP configuration] ***********************************************


changed: [r2]
changed: [r1]
changed: [r3]

TASK [Assemble configuration parts] ******************************************


changed: [r3]
changed: [r2]
changed: [r1]

TASK [Load and commit config, require confirmation] **************************


changed: [r2]
changed: [r1]
changed: [r3]

RUNNING HANDLER [Waiting for BGP peers to establish connections] *************


Pausing for 60 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [r2]

PLAY [Verify BGP] ************************************************************

TASK [Execute snapcheck] *****************************************************


ok: [r2]
ok: [r1]
142

ok: [r3]

TASK [Confirm commit] ********************************************************


ok: [r2]
ok: [r1]
ok: [r3]

TASK [Verify BGP configuration] **********************************************


ok: [r1] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}
ok: [r2] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}
ok: [r3] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}

PLAY RECAP *******************************************************************


r1 : ok=8 changed=5 unreachable=0 failed=0
r2 : ok=9 changed=5 unreachable=0 failed=0
r3 : ok=8 changed=5 unreachable=0 failed=0

Verification

Verifying BGP Neighbors

Purpose
Verify that the BGP session is established for each neighbor address.

The JSNAPy test files test that the BGP session is established for each neighbor address and that the there
are no down peers. The Verify BGP configuration task output enables you to quickly verify that the given
device passed all JSNAPy tests. If the JSNAPy passPercentage is equal to 100 percent, the task includes
"msg": "All assertions passed" in the task output.

Action
143

Review the Verify BGP configuration task output, and verify that each device returns the All assertions
passed message.

TASK [Verify BGP configuration] **********************************************


ok: [r1] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}
ok: [r2] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}
ok: [r3] => {
"changed": false,
"failed": false,
"msg": "All assertions passed"
}

Troubleshooting Ansible Playbook Errors

IN THIS SECTION

Troubleshooting Configuration Load Errors | 143

Troubleshooting Failed JSNAPy Tests | 144

Troubleshooting Failed Commit Confirmations | 144

Troubleshooting Configuration Load Errors

Problem

The Ansible playbook generates a ConfigLoadError error indicating that it failed to load the configuration
on the device because of a syntax error.

fatal: [r1]: FAILED! => {"changed": false, "failed": true, "msg": "Failure loading
the configuraton: ConfigLoadError(severity: error, bad_element: protocol, message:
error: syntax error\nerror: error recovery ignores input until this point)"}
144

Solution
The playbook renders the Junos OS configuration by using the Jinja2 template and the host variables
defined for that device in the host_vars directory. The playbook generates a syntax error when the Jinja2
template produces an invalid configuration. To correct this error, update the Jinja2 template to correct
the element identified by the bad_element key in the error message.

Troubleshooting Failed JSNAPy Tests

Problem
The Verify BGP configuration task output indicates that the assertion failed, because the JSNAPy
passPercentage was not equal to 100 percent.

TASK [Verify BGP configuration]


*************************************************************
fatal: [r1]: FAILED! => {
"assertion": "snapcheck_result.passPercentage == 100",
"changed": false,
"evaluated_to": false,
"failed": true,
"msg": "JSNAPy test on r1 failed"
}

The assertion fails when the device has not established the BGP session with its neighbor or the session
goes down. If the assertion fails, and the configuration for that device was updated in the first play, the
playbook does not confirm the commit for the new configuration on the device, and the device rolls the
configuration back to the previously committed configuration.

Solution

The JSNAPy tests might fail if the snapcheck operation is taken before the peers can establish the session
or because the BGP neighbors are not configured correctly. If the playbook output indicates that the
configuration was successfully loaded and committed on the device, try increasing the handler’s pause
interval to a suitable value for your environment and rerun the playbook.

handlers:
- name: Waiting for BGP peers to establish connections
pause: seconds=75

If the tests still fail, verify that the Jinja2 template and the host variables for each device contain the correct
data and that the resulting configuration for each device is correct.

Troubleshooting Failed Commit Confirmations

Problem
145

The configuration was not confirmed on one or more devices.

TASK [Confirm commit]


***********************************************************************
skipping: [r2]
skipping: [r2]
skipping: [r3]

Solution
The playbook only confirms the configuration if it changed and the JSNAPy tests pass. If the Load and
commit config, require confirmation task output indicates that the configuration did not change, the
playbook does not execute the task to confirm the commit. If the configuration changed but was not
confirmed, then the JSNAPy tests failed. The JSNAPy tests might fail if the BGP neighbors are not configured
correctly, or if the playbook does not provide enough time between the plays for the devices to establish
the BGP session. For more information, see “Troubleshooting Failed JSNAPy Tests” on page 144.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_jsnapy module replaces
the functionality of the junos_jsnapy module.
6 CHAPTER

Using Ansible to Manage the


Configuration

Using Ansible to Retrieve or Compare Junos OS Configurations | 149

Using Ansible to Configure Devices Running Junos OS | 158


149

Using Ansible to Retrieve or Compare Junos OS


Configurations

IN THIS SECTION

Specifying the Source of the Configuration Data to Return | 150

Specifying the Format of the Configuration Data to Return | 150

Specifying the Scope of the Configuration Data to Return | 151

Specifying Options That Do Not Have an Equivalent Module Argument | 153

Saving Retrieved Configuration Data To a File | 154

Comparing the Active Configuration to a Previous Configuration | 155

Juniper Networks provides support for using Ansible to manage the configuration of devices running
Junos OS. The juniper_junos_config module in the Juniper.junos role enables you to retrieve or compare
Junos OS configurations. You can use the module to request the complete configuration or selected
configuration hierarchies of devices running Junos OS, and you can compare the active configuration with
previously committed configurations.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_config module combines
and replaces the functionality of the junos_commit, junos_get_config, junos_install_config, and
junos_rollback modules.

To retrieve the configuration from a device running Junos OS, execute the juniper_junos_config module
with the retrieve parameter. The module’s response includes the configuration in text format in the config,
config_lines, and config_parsed keys, unless the return_output option is set to false.

The following sections discuss how to use the juniper_junos_config module to retrieve or compare Junos
OS configurations.
150

Specifying the Source of the Configuration Data to Return

When you use the juniper_junos_config module to retrieve the configuration, you must include the retrieve
parameter in the module argument list and specify the configuration database from which to retrieve the
data. You can retrieve data from the candidate configuration database or from the committed configuration
database by setting retrieve to 'candidate' or 'committed', respectively.

For example, the following playbook retrieves the complete committed configuration for each device in
the inventory group:

---
- name: "Get Junos OS configuration."
hosts: junos-all
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Get committed configuration"
juniper_junos_config:
retrieve: "committed"
register: response
- name: "Print result"
debug:
var: response

Specifying the Format of the Configuration Data to Return

When you use the juniper_junos_config module to retrieve the configuration, the module invokes the
Junos XML protocol <get-configuration> operation, which can return Junos OS configuration data as CLI
configuration statements, Junos XML elements, Junos OS set commands, or JavaScript Object Notation
(JSON). By default, the juniper_junos_config module returns configuration data as CLI configuration
statements, or text format, which uses newlines, tabs and other white space, braces, and square brackets
to indicate the hierarchical relationships between the statements.

To specify the format in which to return the configuration data, include the format parameter in the module
argument list and set the value equal to the desired format. To explicitly request text format, or to request
Junos XML elements, Junos OS set commands, or JSON format, set the format value to 'text', 'xml', 'set',
or 'json', respectively.
151

The following playbook retrieves the complete committed configuration for each device in the inventory
group in XML:

---
- name: "Get Junos OS configuration."
hosts: junos-all
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Get configuration in XML format"
juniper_junos_config:
retrieve: "committed"
format: "xml"
register: response
- name: "Print result"
debug:
var: response

Specifying the Scope of the Configuration Data to Return

In addition to retrieving the complete Junos OS configuration, the juniper_junos_config module can retrieve
specific portions of the configuration by including the filter parameter in the module argument list. The
filter parameter takes a string containing the subtree filter that selects the configuration statements to
return. The subtree filter returns the configuration data that matches the selection criteria. When multiple
hierarchies are requested, the value of filter must represent all levels of the configuration hierarchy starting
at the root (represented by the <configuration> element) down to each element to display.

The following playbook retrieves and prints the configuration at the [edit interfaces] and [edit protocols]
hierarchy levels in the committed configuration database:

---
- name: "Get Junos OS configuration hierarchies."
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
152

tasks:
- name: "Get selected configuration hierarchies"
juniper_junos_config:
retrieve: "committed"
filter: "<configuration><interfaces/><protocols/></configuration>"
register: response
- name: "Print result"
debug:
var: response

The following playbook retrieves and prints the configuration for the ge-1/0/1 interface:

---
- name: "Get Junos OS configuration hierarchies."
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Get selected configuration hierarchies"
juniper_junos_config:
retrieve: "committed"
filter: "<interfaces><interface>
<name>ge-1/0/1</name></interface></interfaces>"
register: response
- name: "Print result"
debug:
var: response

The following playbook retrieves and prints the configuration committed at the [edit system services]
hierarchy level:

---
- name: "Get Junos OS configuration hierarchies."
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
153

- name: "Get selected configuration hierarchies"


juniper_junos_config:
retrieve: "committed"
filter: "system/services"
register: response
- name: "Print result"
debug:
var: response

Specifying Options That Do Not Have an Equivalent Module Argument

When you use the juniper_junos_config module to retrieve the configuration, the module invokes the
Junos XML protocol <get-configuration> operation. The module supports explicit arguments for many of
the <get-configuration> attributes, for example, the format attribute. The module also supports the options
argument, which enables you to include any additional <get-configuration> attributes that do not have
an equivalent juniper_junos_config argument. The options argument takes a dictionary of key/value pairs
of any attributes supported by the <get-configuration> operation.

For the complete list of attributes supported by the Junos XML protocol <get-configuration> operation,
see https://www.juniper.net/documentation/en_US/junos/topics/reference/tag-summary/
junos-xml-protocol-get-configuration.html.

For example, the juniper_junos_config module retrieves data from the pre-inheritance configuration, in
which the <groups>, <apply-groups>, <apply-groups-except>, and <interface-range> tags are separate
elements in the configuration output. To retrieve data from the post-inheritance configuration, which
displays statements that are inherited from user-defined groups and ranges as children of the inheriting
statements, you can include the options argument with inherit: "inherit".

For example, the following playbook retrieves the configuration committed at the [edit system services]
hierarchy level from the post-inheritance committed configuration. In this case, if the configuration also
contains statements configured at the [edit groups global system services] hierarchy level, those statements
would be inherited under [edit system services] in the post-inheritance configuration and returned in the
retrieved configuration data.

---
- name: "Get Junos OS configuration hierarchies."
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no
154

tasks:
- name: "Get selected hierarchy from the post-inheritance configuration"
juniper_junos_config:
retrieve: "committed"
filter: "system/services"
options:
inherit: "inherit"
register: response
- name: "Print result"
debug:
var: response

Saving Retrieved Configuration Data To a File

When you use the juniper_junos_config module to retrieve the configuration, you can save the returned
configuration data in a file on the local Ansible control machine by including the dest or dest_dir module
arguments. To specify the directory on the local Ansible control machine where the retrieved configurations
are saved, include the dest_dir argument, and define the path to the target directory. The configuration
for each device is stored in a separate file named hostname.config.

The following playbook retrieves the [edit system services] hierarchy from the committed configuration
database on all devices in the inventory group and saves each device configuration to a separate file in
the playbook directory on the Ansible control machine:

---
- name: "Get Junos OS configuration."
hosts: junos-all
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Get selected configuration hierarchies and save to file"
juniper_junos_config:
retrieve: "committed"
filter: "system/services"
dest_dir: "{{ playbook_dir }}"
155

To specify the path and filenames to which the retrieved configurations are saved on the local Ansible
control machine, include the dest argument, and define the filename or the full path of the file. If you
include the dest argument, but omit the directory, the files are saved in the playbook directory. If you
retrieve the configuration for multiple devices, the dest argument must include a variable such as
{{ inventory_hostname }} to differentiate the filename for each device. If you do not differentiate the
filenames, the configuration file for each device will overwrite the configuration file of the other devices.

The following playbook retrieves the [edit system services] hierarchy from the committed configuration
database on all devices in the inventory group and saves each device configuration to a separate file in
the playbook directory on the Ansible control machine. Each file is uniquely identified by the device
hostname.

---
- name: "Get Junos OS configuration."
hosts: junos-all
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Get selected configuration hierarchies and save to file"
juniper_junos_config:
retrieve: "committed"
filter: "system/services"
dest: "{{ inventory_hostname }}-system-config"

If you are saving the configuration data to files and do not want to duplicate the configuration data in the
module’s response, you can you can optionally include return_output: false in the juniper_junos_config
argument list. Setting return_output to false causes the module to omit the config, config_lines, and
config_parsed keys in the module’s response. Doing this might be necessary if the devices return a
significant amount of configuration data.

Comparing the Active Configuration to a Previous Configuration

The juniper_junos_config module enables you to compare the active configuration to a previously committed
configuration, or rollback configuration. To compare the active configuration to a previous configuration,
include the diff: true and rollback: id arguments in the module’s argument list. By default, when you include
the rollback: id argument, the module reverts the candidate configuration to the specified configuration
and commits the changes. To only compare the configurations and prevent the module from loading and
committing the rollback configuration, you must also include the commit: false argument.
156

The module returns the diff and diff_lines keys, which contain the configuration differences between the
active and previous configuration. diff is a multi-line string and diff_lines is a list of single line strings, both
in diff or patch format.

To save the differences to a file on the local Ansible control machine, include the diffs_file argument, and
define the filename or the full path of the output file. If you include the diffs_file argument but omit the
directory, the files are saved in the playbook directory. If you compare the configurations on multiple
devices, the diffs_file argument must include a variable such as {{ inventory_hostname }} to differentiate
the filename for each device. If you do not differentiate the filenames, the output file for each device will
overwrite the output file of the other devices.

The following playbook prompts for the rollback ID of a previously committed configuration, compares
the committed configuration to the specified rollback configuration, saves the comparison to a
uniquely-named file, and also prints the response to standard output:

---
- name: "Compare configuration"
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

vars_prompt:
- name: "ROLLBACK"
prompt: "Rollback ID to compare with active configuration"
private: no

tasks:
- name: "Compare active to previous configuration"
juniper_junos_config:
rollback: "{{ ROLLBACK }}"
diff: true
diffs_file: "{{ inventory_hostname }}-diff-rollback-{{ ROLLBACK }}"
check: false
commit: false
register: response
- name: "Print diff"
debug:
var: response

user@ansible-cm:~$ ansible-playbook configuration-compare-to-rollback.yaml


157

Rollback ID to compare with active configuration: 2

PLAY [Compare configuration] *************************************************

TASK [Compare active to previous configuration] ******************************


changed: [dc1a.example.net]

TASK [Print diff] ************************************************************


ok: [dc1a.example.net] => {
"response": {
"changed": true,
"diff": "\n[edit system]\n+ services {\n+ netconf {\n+
ssh;\n+ }\n+ }\n",
"diff_lines": [
"",
"[edit system]",
"+ services {",
"+ netconf {",
"+ ssh;",
"+ }",
"+ }"
],
"failed": false,
"msg": "Configuration has been: opened, rolled back, diffed, closed."
}
}

PLAY RECAP ********************************************************************


dc1a.example.net : ok=2 changed=1 unreachable=0 failed=0

user@ansible-cm:~$ cat dc1a.example.net-diff-rollback-2

[edit system]
+ services {
+ netconf {
+ ssh;
+ }
+ }
158

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_config module combines
and replaces the functionality of the junos_commit, junos_get_config, junos_install_config,
and junos_rollback modules.

RELATED DOCUMENTATION

Using Ansible to Configure Devices Running Junos OS | 158


Understanding the Ansible for Junos OS Modules | 23

Using Ansible to Configure Devices Running Junos OS

IN THIS SECTION

juniper_junos_config Module Overview | 159

Specifying the Configuration Mode | 160

Specifying the Load Action | 162

Specifying the Format of the Configuration Data to Load | 162

Loading Configuration Data as Strings | 163

Loading Configuration Data from a Local or Remote File | 165

Loading Configuration Data Using a Jinja2 Template | 167

Loading the Rescue Configuration | 170

Rolling Back the Configuration | 171

Committing the Configuration | 172

Ignoring Warnings When Configuring Devices | 175

Example: Using Ansible to Configure Devices | 176

Juniper Networks provides support for using Ansible to manage the configuration of devices running
Junos OS. The juniper_junos_config module in the Juniper.junos role and the junos_config Ansible core
module enable you to configure devices running Junos OS. The user account that is used to make
159

configuration changes must have permissions to change the relevant portions of the configuration on each
device.

NOTE: Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_config module combines
and replaces the functionality of the junos_commit, junos_get_config, junos_install_config, and
junos_rollback modules.

The following sections discuss how to use the juniper_junos_config module to modify and commit the
configuration on devices running Junos OS. For information about the junos_config Ansible core module,
see https://docs.ansible.com/ansible/latest/junos_config_module.html.

juniper_junos_config Module Overview

The juniper_junos_config module in the Juniper.junos role enables you to modify and commit the
configuration on devices running Junos OS. You can load new configuration data, roll the configuration
back to a previous version, or load a rescue configuration. To modify the configuration, the module argument
list must include either the load parameter to load new configuration data or the rollback parameter to
revert to either the rescue configuration or a previously committed 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. By default, the
juniper_junos_config module makes changes to the candidate configuration database using configure
exclusive mode, which automatically locks and unlocks the configuration database. For more information
about specifying the configuration mode, see “Specifying the Configuration Mode” on page 160.

When loading new configuration data, you can specify the configuration mode, the load operation, and
the source and format of the changes. The value of the load argument defines the load operation used to
load the configuration data into the candidate configuration. The juniper_junos_config module supports
many of the same load actions that are available in the Junos OS command-line interface (Junos OS CLI),
including merge, override, replace, set, and update. For more information, see “Specifying the Load Action”
on page 162.

The juniper_junos_config module enables you to configure devices running Junos OS using one of the
standard, supported formats. You can provide configuration data as strings or as files containing either
configuration data snippets 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. For information about specifying the format of the configuration data, see “Specifying the
Format of the Configuration Data to Load” on page 162.

When you include the load parameter, you must also specify the source of the configuration data to load.
You can specify the source as a list of configuration strings, a file on the local Ansible server, a Jinja2
160

template, or a URL reachable from the client device by including the lines, src, template, or url parameter,
respectively. For more information about specifying the source of the configuration data, see the following
sections:

• Loading Configuration Data as Strings on page 163

• Loading Configuration Data from a Local or Remote File on page 165

• Loading Configuration Data Using a Jinja2 Template on page 167

The juniper_junos_config module 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:

• Loading the Rescue Configuration on page 170

• Rolling Back the Configuration on page 171

By default, the juniper_junos_config module automatically commits the changes to the configuration. To
alter this behavior or supply additional commit options, see “Committing the Configuration” on page 172.

By default, when the juniper_junos_config module includes the load or rollback arguments to change the
configuration, the module automatically returns the configuration changes in diff or patch format in the
module’s response. The differences are returned in the diff and diff_lines variables. To prevent the module
from calculating and returning the differences, set the diff module argument to false.

Specifying the Configuration Mode

You can specify the configuration mode to use when modifying the candidate configuration database. By
default, the juniper_junos_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 changes to
the configuration. Locking the database prevents other users from modifying or committing changes to
the database until the lock is released.

To explicitly specify the mode, include the config_mode parameter in the juniper_junos_config module
argument list. Supported modes include exclusive and private. Both modes discard any uncommitted
changes upon exiting.

The following playbook uses configure private mode to modify the configuration:

---
- name: "Configure Device"
hosts: dc1
161

roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Configure op script"
juniper_junos_config:
config_mode: "private"
load: "set"
lines:
- "set system scripts op file bgp.slax"
register: response
- name: "Print the config changes"
debug:
var: response.diff_lines

user@ansible-cm:~/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
162

Specifying the Load Action

The juniper_junos_config module supports loading configuration changes using a load merge, load replace,
load override, load set, or load update operation. You specify the load operation by including the load
parameter in the module argument list and setting it to the value of the corresponding load operation.
Table 13 on page 162 summarizes the parameter settings required for each type of load operation

Table 13: Parameters for Specifying the Load Operation

Load Operation load Argument Description

load merge load: "merge" Merge the loaded configuration with the existing configuration.

load override load: "override" Replace the entire configuration with the loaded configuration.

load replace load "replace" Merge the loaded configuration with the existing configuration, but replace
statements in the existing configuration with those that specify the replace:
tag in the loaded configuration. If there is no statement in the existing
configuration, the statement in the loaded configuration is added.

load set load: "set" Load configuration data that is in set format. The configuration data is
loaded line by line and can contain configuration mode commands such
as set, delete, and deactivate.

load update load: "update" Compare the complete loaded configuration against the existing
configuration. Each configuration element that is different in the loaded
configuration replaces its corresponding element in the existing
configuration. During the commit operation, only system processes that
are affected by changed configuration elements parse the new
configuration.

Specifying the Format of the Configuration Data to Load

The juniper_junos_config module enables you to configure devices running Junos OS using one of the
standard, supported formats. You can provide configuration data as strings or files. Files can contain either
configuration data snippets 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.
163

NOTE: Starting in Junos OS Release 16.1R1 and later releases, devices running Junos OS support
loading configuration data in JSON format.

The juniper_junos_config module attempts to auto-detect the format of configuration data supplied as
strings using 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 either by adding the appropriate extension to the file or by including the format
argument.

Table 14 on page 163 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.

Table 14: Specifying the Format for Configuration Data

Configuration Data Format File Extension format Parameter

CLI configuration statements (text) .conf "text"

JavaScript Object Notation (JSON) .json "json"

Junos OS set commands .set "set"

Junos XML elements .xml "xml"

NOTE: When you set the juniper_junos_config load argument to 'override' or 'update', you
cannot use the Junos OS set command format.

Loading Configuration Data as Strings

The juniper_junos_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 juniper_junos_config 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 “Specifying the Format of the Configuration Data to Load” on page 162. If you
include the format parameter in the module argument list, it overrides the auto-detect format.
164

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
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Load configuration data using strings and commit
juniper_junos_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
debug:
var: response

The following playbook configures the same statements using lines with configuration data in CLI text
format. In this case, load: "merge" is used.

---
- name: Load and commit configuration
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Load configuration data using strings and commit
juniper_junos_config:
load: "merge"
lines:
- |
system {
scripts {
op {
file bgp.slax;
165

file bgp-neighbor.slax;
}
}
}
register: response
- name: Print the response
debug:
var: response

Loading Configuration Data from a Local or Remote File

The juniper_junos_config module enables you to load configuration data from a file. The file can reside
on the Ansible control machine, on the client device, or at a URL that is reachable from the client device.
When you load configuration data from a file, you must indicate the format of the configuration data in
the file and the location of 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
“Loading Configuration Data Using a Jinja2 Template” on page 167.

You can specify the format of the configuration data either by explicitly including the format parameter
in the module argument list or by adding the appropriate extension to the configuration data file. For
information about specifying the format, see “Specifying the Format of the Configuration Data to Load”
on page 162. If you include the format parameter in the module argument list, it overrides the format
indicated by the file extension. When the configuration data uses Junos XML format, you must enclose
the data in the top-level <configuration> tag.

NOTE: You do not need to enclose configuration data that is formatted as ASCII text, Junos OS
set commands, or JSON in <configuration-text>, <configuration-set>, or <configuration-json>
tags as required when configuring the device directly within a NETCONF session.

Table 15 on page 165 outlines the juniper_junos_config module arguments that you can include to specify
the location of the file.

Table 15: Specifying the Location of the Configuration File

Module Argument Description

src Absolute or relative path to a file on the Ansible control machine. The default directory
is the playbook directory.
166

Table 15: Specifying the Location of the Configuration File (continued)

Module Argument Description

url Absolute or relative path to a file on the client device, or an FTP location, or a Hypertext
Transfer Protocol (HTTP) URL.

The default directory on the client device is the current working directory, which defaults
to the user’s home directory.

To load configuration data from a local file on the Ansible control machine, 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
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Load configuration from a local file and commit
juniper_junos_config:
load: "merge"
src: "build_conf/{{ inventory_hostname }}/junos.conf"
register: response
- name: Print the response
debug:
var: response

To load configuration data from a file on the managed device running Junos OS, or from an FTP or HTTP
URL, use the url parameter and specify the path of the file that contains the configuration data to load.
For example:

---
- name: Load and commit configuration
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
167

- name: Load configuration from a remote file and commit


juniper_junos_config:
load: "merge"
url: "/var/tmp/junos.conf"
register: response
- name: Print the response
debug:
var: response

The value for url can be an absolute or relative local file path, an FTP location, or a Hypertext Transfer
Protocol (HTTP) URL.

• A local filename can have 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.

• A filename on an FTP server has the following form:

ftp://username:password@hostname/path/filename

• A filename 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.

Loading Configuration Data Using a Jinja2 Template

The juniper_junos_config module enables you to render configuration data from a Jinja2 template file on
the Ansible control machine and load and commit the configuration on a device running Junos OS. 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 juniper_junos_config module uses the Jinja2 template and a supplied dictionary of variables
to render the configuration data.
168

To load and commit configuration data using a Jinja2 template, include the template and vars parameters
in the juniper_junos_config module argument list. Set the template argument to the path of the Jinja2
template file. The value of the vars argument is a dictionary of keys and values that are required to render
the Jinja2 template. You must also include the format parameter when the file extension does not indicate
the format of the data. For information about specifying the format, see “Specifying the Format of the
Configuration Data to Load” on page 162.

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_junos_config module to load the Jinja2 template, set the template argument to the
path of the template file and define the variables required by the template in the vars parameter. The
following playbook uses the Jinja2 template and the variables defined in vars to render the configuration
data and load and commit it on the target host. The format parameter indicates the format of the
configuration data in the template file.

---
- name: Load and commit configuration
hosts: dc1
roles:
169

- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Load a configuration from a Jinja2 template and commit
juniper_junos_config:
load: "merge"
template: "build_conf/{{ inventory_hostname }}/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
debug:
var: response

The module generates the following configuration data, which is loaded into the candidate configuration
on the device and committed:

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 {
170

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;
}
}

Loading the Rescue Configuration

A rescue configuration allows 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_junos_config module enables you to revert to an existing rescue configuration on devices
running Junos OS. To load and commit the rescue configuration on devices running Junos OS, include the
rollback: "rescue" module argument. For example:

---
- name: "Revert to rescue configuration"
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Load and commit rescue configuration"
juniper_junos_config:
rollback: "rescue"
register: response
- name: "Print response"
debug:
var: response
171

Rolling Back the Configuration

Devices running Junos OS 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 is
useful when configuration changes cause undesirable results, and you want to revert back to a known
working configuration. Rolling back the configuration is similar to the process for making configuration
changes on the device, but instead of loading configuration data, you perform a rollback, which replaces
the entire candidate configuration with a previously committed configuration.

The juniper_junos_config module enables you to roll back to a previously committed configuration on
devices running Junos OS. To roll back the configuration and commit it, include the rollback module
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 prompts for the rollback ID of the configuration to restore, rolls back the
configuration and commits it, and then prints the configuration changes to standard output.

---
- name: "Roll back the configuration"
hosts: dc1
roles:
- Juniper.junos
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_junos_config:
rollback: "{{ ROLLBACK }}"
register: response
- name: "Print the configuration changes"
debug:
var: response.diff_lines

user@ansible-cm:~/ansible$ ansible-playbook configuration-rollback.yaml


172

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

Committing the Configuration

By default, when you use the juniper_junos_config module to modify the configuration using either the
load or the rollback argument, 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.

Table 16 on page 172 outlines the juniper_junos_config module arguments that you can use to customize
the commit operation.

Table 16: juniper_junos_config Commit Options

Default value
for load or
rollback
Module Argument Description operations

check: boolean Perform a commit check or confirm a previous confirmed true


commit operation.
173

Table 16: juniper_junos_config Commit Options (continued)

Default value
for load or
rollback
Module Argument Description operations

check_commit_wait: seconds Wait the specified number of seconds between the commit –
check and the commit operation.

comment: "string" Log a comment for that commit operation in the system log –
file and in the device’s commit history.

commit: boolean Commit the configuration changes or confirm a previous true


confirmed commit operation.

commit_empty_changes: boolean Commit the configuration changes even if there are no false
differences between the candidate configuration and the
committed configuration.

confirmed: minutes Require that a commit operation be confirmed within a –


specified amount of time after the initial commit. Otherwise,
roll back to the previously committed configuration.

Either the commit: true option or the check: true option must
be used to confirm the commit.

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.

By default, if there are no differences between the candidate configuration and the committed configuration,
the juniper_junos_config module does not commit the changes. To force a commit operation even when
there are no differences, include the commit_empty_changes: true argument.

To require that a commit operation be confirmed within a specified amount of time after the initial commit,
include the confirmed: minutes argument. If the commit is not confirmed 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_junos_config
module with the check: true or commit: true argument.

By default, the juniper_junos_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
174

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 you omit this argument, there might be certain circumstances in which a device initiates the
commit operation before the commit check operation releases its lock on the configuration, resulting in a
CommitError and failed commit operation.

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.
The second task issues a commit check operation to confirm the commit.

---
- name: "Load configuration and confirm within 5 minutes"
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: "Load configuration. Wait 10 seconds between check and commit. Confirm
within 5 min."
juniper_junos_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"
debug:
var: response

- name: "Confirm the commit with a commit check"


juniper_junos_config:
check: true
diff: false
commit: false
register: response
- name: "Print the response"
debug:
var: response
175

Ignoring Warnings When Configuring Devices

The juniper_junos_config module enables you to modify and commit the configuration on devices running
Junos OS. In some cases, the RPC reply might contain <rpc-error> elements with a severity of warning or
higher that cause the module to raise an RpcError exception, thus causing 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_junos_config module
to suppress RpcError exceptions that are raised for warnings by including the ignore_warning parameter
in the module argument list. The ignore_warning argument takes a Boolean, a string, or a list of strings.

To instruct the juniper_junos_config module to ignore all warnings for load and commit operations performed
by the module, include the ignore_warning: true argument in the module argument list. The following
example ignores all warnings for load and commit operations.

---
- name: Configure Device
hosts: dc1
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Configure op script
juniper_junos_config:
config_mode: "private"
load: "set"
lines:
- "set system scripts op file bgp.slax"
ignore_warning: true
register: response
- name: Print the response
debug:
var: response

If you include ignore_warning: true and all of the <rpc-error> elements have a severity 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.
176

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
roles:
- Juniper.junos
connection: local
gather_facts: no

tasks:
- name: Configure device running Junos OS and ignore warnings
juniper_junos_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
debug:
var: response

The module suppresses RpcError exceptions if all of the <rpc-error> elements have a severity of warning
and each warning in the response matches one or more of the specified strings.

Example: Using Ansible to Configure Devices

IN THIS SECTION

Requirements | 177

Overview | 177

Configuration | 178

Executing the Playbook | 180

Verification | 181

Troubleshooting Playbook Errors | 182


177

Ansible and Juniper Networks provide collections of Ansible modules that you can use to manage the
configuration of devices running Junos OS. This example outlines how to use Ansible to make configuration
changes on devices running Junos OS through NETCONF over SSH.

Requirements

This example uses the following hardware and software components:

• Configuration management server running Ansible 2.1 or later with version 2.0.0 or later of the
Juniper.junos role installed

• Device running Junos OS with NETCONF enabled and a user account configured with appropriate
permissions

• SSH public/private key pair configured for the appropriate user on the Ansible server and the device
running Junos OS

• Existing Ansible inventory file with required hosts defined

Overview

The juniper_junos_config module in the Juniper.junos role enables you to manage the configuration on
devices running Junos OS. The user account executing the module must have permissions to change the
relevant portions of the configuration on each target device. When configuring a device with the
juniper_junos_config module, supported formats for the configuration data include CLI configuration
statements, Junos XML elements, Junos OS set commands, and JSON.

This example presents an Ansible playbook that uses the juniper_junos_config module to enable a new
op script in the configuration of the target devices running Junos OS. The configuration data file,
junos-config.conf, contains the relevant configuration data formatted as text.

The playbook includes the Checking NETCONF connectivity task, which utilizes the wait_for Ansible
module to try to establish a NETCONF session with the target device using the NETCONF default port
(830). If the control machine fails to establish a NETCONF session with a target device during playbook
execution, it skips over the other tasks in the play for that device.

The task to configure the device executes the juniper_junos_config module provided that the NETCONF
check was successful. The juniper_junos_config module requires a host argument, but because it uses the
{{ inventory_hostname }} variable by default, this argument is not explicitly included.

The load: "merge" module argument loads the new configuration data into the candidate configuration
using a load merge operation. By default, the juniper_junos_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.
178

Configuration

IN THIS SECTION

Creating the Configuration Data File | 178

Creating the Ansible Playbook | 178

Results | 179

Creating the Configuration Data File

Step-by-Step Procedure
To create the configuration data file that is used by the juniper_junos_config module:

1. Create a new file with the appropriate extension based on the format of the configuration data, which
in this example is text.

2. Include the desired configuration changes in the file, for example:

system {
scripts {
op {
file bgp.slax;
}
}
}

Creating the Ansible Playbook

Step-by-Step Procedure
To create a playbook that uses the juniper_junos_conifg module to make configuration changes on a device
running Junos OS:

1. Include the playbook boilerplate, which must contain connection: local and the Juniper.junos role.

---
- name: Load and commit configuration data on a device running Junos OS
hosts: dc1
roles:
- Juniper.junos
179

connection: local
gather_facts: no

2. (Optional) Create a task to verify NETCONF connectivity.

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: 830
timeout: 5

3. Create the task to load the configuration onto the device and commit it.

- name: Merge configuration data from a file and commit


juniper_junos_config:
load: "merge"
format: "text"
src: "build_conf/{{ inventory_hostname }}/junos-config.conf"
comment: "Configuring op script with Ansible"
register: response

4. (Optional) Create a task to print the response, which includes the configuration changes in diff format.

- name: Print the response


debug:
var: response

Results

On the Ansible control machine, 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 device running Junos OS
hosts: dc1
roles:
- Juniper.junos
connection: local
180

gather_facts: no

tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: 830
timeout: 5

- name: Merge configuration data from a file and commit


juniper_junos_config:
load: "merge"
format: "text"
src: "build_conf/{{ inventory_hostname }}/junos-config.conf"
comment: "Configuring op script with Ansible"
register: response

- name: Print the response


debug:
var: response

Executing the Playbook

Step-by-Step Procedure
181

To execute the playbook:

• Issue the ansible-playbook command on the control machine, and provide the playbook path and any
desired options.

user@ansible-cm:~/ansible$ ansible-playbook ansible-pb-junos-config.yaml

PLAY [Load and commit configuration data on a device running Junos OS] ****

TASK [Checking NETCONF connectivity] **************************************


ok: [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": "\n[edit system scripts op]\n+ file bgp.slax;\n",
"diff_lines": [
"",
"[edit system scripts op]",
"+ file bgp.slax;"
],
"failed": false,
"file":
"/home/user/ansible/build_conf/dc1a.example.net/junos-config.conf",
"msg": "Configuration has been: opened, loaded, checked, diffed,
committed, closed."
}
}

PLAY RECAP ****************************************************************


dc1a.example.net : ok=3 changed=1 unreachable=0 failed=0

Verification

Verifying the Configuration

Purpose
Verify that the configuration was correctly updated on the device running Junos OS.
182

Action

Review the Ansible playbook output to see whether the configuration task succeeded or failed. You can
also log in to the device running Junos OS 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 2017-12-04 14:55:02 PST by user via netconf


Configuring op script with Ansible

user@dc1a> show log messages

Dec 4 14:54:45 dc1a sshd[33441]: Accepted publickey for user from 198.51.100.1
port 53782 ssh2: RSA 5d:dd:59:26:83:57:dd:07:be:ae:42:21:8c:e0:9a:85
Dec 4 14:54:53 dc1a mgd[33444]: UI_COMMIT: User 'user' requested 'commit'
operation (comment: Configuring op script with Ansible)
Dec 4 14:55:08 dc1a mgd[33444]: UI_COMMIT_COMPLETED: commit complete

Troubleshooting Playbook Errors

IN THIS SECTION

Troubleshooting Timeout Errors | 182

Troubleshooting Configuration Lock Errors | 183

Troubleshooting Configuration Change Errors | 184

Troubleshooting Timeout Errors

Problem
183

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 juniper_junos_config timeout argument to an appropriate value and re-run
the playbook.

Troubleshooting Configuration Lock Errors

Problem

The playbook generates a LockError error message indicating that the configuration cannot be locked.
For example:

FAILED! => {"changed": false, "failed": true, "msg": "Unable to open the
configuration in exclusive mode: LockError(severity: error, bad_element: None,
message: configuration database modified)"}

or

FAILED! => {"changed": false, "failed": true, "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
184

permissions, or if appropriate, configure the device running Junos OS to give the current user the necessary
permissions to make the changes.

Troubleshooting 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, "failed": true, "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 device running Junos OS to give the current user the necessary permissions to make the changes.

Release History Table

Release Description

2.0.0 Starting in Ansible for Junos OS Release 2.0.0, the juniper_junos_config module combines
and replaces the functionality of the junos_commit, junos_get_config, junos_install_config,
and junos_rollback modules.

RELATED DOCUMENTATION

Using Ansible to Retrieve or Compare Junos OS Configurations | 149


Understanding the Ansible for Junos OS Modules | 23
7 CHAPTER

Troubleshooting Ansible for Junos OS

Troubleshooting Junos Pyez (junos-eznc) Install Errors for Ansible Modules | 187

Troubleshooting Ansible Role and Module Errors When Managing Devices Running
Junos OS | 188

Troubleshooting Ansible Connection Errors When Managing Devices Running


Junos OS | 190

Troubleshooting Ansible Authentication Errors When Managing Devices Running


Junos OS | 193

Troubleshooting Ansible Errors When Configuring Devices Running Junos OS | 194


187

Troubleshooting Junos Pyez (junos-eznc) Install Errors


for Ansible Modules
Problem
Description:

During execution of a Juniper.junos module or an Ansible core module for Junos OS, the Ansible control
machine generates an error that junos-eznc is not installed. For example:

"msg": "junos-eznc (aka PyEZ) >= 2.1.7 is required for this module. However,
junos-eznc does not appear to be currently installed. See
https://github.com/Juniper/py-junos-eznc#installation for details on installing
junos-eznc."

or

"msg": "junos-eznc is required but does not appear to be installed. It can be


installed using `pip install junos-eznc`"

Cause
The Ansible Galaxy modules in the Juniper.junos role and certain Ansible core modules for Junos OS use
the Juniper Networks Junos PyEZ Python library to perform operations on devices running Junos OS. This
library must be installed on the Ansible control machine before executing the modules. In addition, the
Juniper.junos modules introduced in Release 2.0.0 of Ansible for Junos OS require Junos PyEZ Release
2.1.7 or later on the Ansible control machine.

Solution
Install Junos PyEZ on the control machine and update any necessary environment variables. See
https://github.com/Juniper/py-junos-eznc#installation for more information.

NOTE: If Ansible is run from inside a virtual environment, you must install Junos PyEZ inside
the virtual environment, and you must specify the path to the Python interpreter inside the
virtual environment by using the ansible_python_interpreter Ansible inventory variable.

To verify that Junos PyEZ is successfully installed on the control machine, launch the Python interactive
shell and import the jnpr.junos package.

[user@ansible-cm ~]$ python


188

>>>
>>> import jnpr.junos
>>> jnpr.junos.__version__
'2.1.7'

If the jnpr.junos package is successfully imported and there is no error message, then Junos PyEZ is installed
on the Ansible control machine.

RELATED DOCUMENTATION

Ansible for Junos OS Server Requirements | 37


Troubleshooting Ansible Authentication Errors When Managing Devices Running Junos OS | 193
Troubleshooting Ansible Role and Module Errors When Managing Devices Running Junos OS | 188

Troubleshooting Ansible Role and Module Errors


When Managing Devices Running Junos OS
Problem
Description:

During execution of an Ansible playbook, the control machine generates an error that the Juniper.junos
role was not found or that no action was detected in the task. For example:

ERROR! the role 'Juniper.junos' was not found in


/usr/share/ansible/roles:/etc/ansible/roles ...

or

ERROR! no action detected in task. This often indicates a misspelled module name,
or incorrect module path.

Cause
The Ansible control machine cannot locate the Juniper.junos role and associated modules.

Solution
189

The Juniper.junos role is hosted on the Ansible Galaxy website. In order to use the modules in the role,
you must install the role on the Ansible control machine, and you must include the role in your playbook.

To install the Juniper.junos role on the Ansible server, execute the ansible-galaxy install command, and
specify Juniper.junos.

[root@ansible-cm]# ansible-galaxy install Juniper.junos

NOTE: If you do not install the role in the default location, you might need to define the path
to the role in your playbook or Ansible setup. For more information about installing roles, see
Installing Roles and roles_path in the official Ansible documentation.

To enable the playbook to reference the modules, include the Juniper.junos role in the playbook play. For
example:

---
- name: Get Device Facts
hosts: junos-all
roles:
- Juniper.junos
connection: local
gather_facts: no

RELATED DOCUMENTATION

Ansible for Junos OS Server Requirements | 37


Understanding the Ansible for Junos OS Modules | 23
190

Troubleshooting Ansible Connection Errors When


Managing Devices Running Junos OS

IN THIS SECTION

Troubleshooting Failed or Invalid Connection Errors | 190

Troubleshooting Unknown Host Errors | 191

Troubleshooting Refused Connection Errors | 192

The following sections outline connection errors that you might encounter when using Ansible to manage
devices running Junos OS. These sections also present potential causes and solutions for each error.

Troubleshooting Failed or Invalid Connection Errors


Problem
Description:

During execution of an Ansible module on a device running Junos OS, the Ansible control machine generates
an error about an unknown command or a failed or invalid SSH connection. For example:

unknown command: /bin/sh\r\n

or

UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh:
Permission denied (publickey,password,keyboard-interactive).\r\n"

or

"msg": "invalid connection specified, expected connection=local, got ssh"

Cause
191

These errors can arise when the module or playbook is not run locally. When you execute modules through
Ansible, normally the control machine sends the module to the managed node, where it is executed and
then removed. Ansible normally requires Python on the managed nodes, but it is not required when
managing devices running Junos OS. When using Ansible to manage devices running Junos OS, you must
run all modules locally on the control machine. If Ansible tries to execute a module directly on the device
running Junos OS, it generates an error.

Solution

To direct the Ansible control machine to run the modules locally, include connection: local in the Ansible
playbook, or include the --connection=local command-line argument when executing individual modules.
For example:

---
- name: Get Device Facts
hosts: junos
roles:
- Juniper.junos
connection: local
gather_facts: no

Troubleshooting Unknown Host Errors


Problem
Description:

During execution of a Juniper.junos module, the Ansible control machine generates a


ConnectUnknownHostError error.

"msg": "Unable to make a PyEZ connection: ConnectUnknownHostError(dc1a.example.net)"

Cause
The host is not defined in the Ansible inventory file.

When executing an Ansible module either directly or from a playbook, any host referenced in the module
arguments or the playbook must be defined in the Ansible inventory file. The default location for the
inventory file is /etc/ansible/hosts.
192

NOTE: The Ansible core modules for Junos OS might generate an “unable to open shell” error
for this and other reasons. For more information, see https://docs.ansible.com/ansible/latest/
network_debug_troubleshooting.html#unable-to-open-shell.

Solution
Update the Ansible inventory file to include the missing host.

For information about the Ansible inventory file, see “Understanding the Ansible Inventory File When
Managing Devices Running Junos OS” on page 28 as well as the official Ansible documentation at
https://www.ansible.com/.

Troubleshooting Refused Connection Errors


Problem
Description:

During execution of a Juniper.junos module on a device running Junos OS, the Ansible control machine
generates an error that the connection is refused. For example:

"msg": "Unable to make a PyEZ connection: ConnectRefusedError(dc1a.example.net)"

Cause

The most likely cause for a refused connection error is that NETCONF over SSH is not enabled on the
device running Junos OS.

To quickly test whether NETCONF is enabled, verify that the user account executing the Ansible module
can successfully start a NETCONF session with the device.

[user@ansible-cm]$ ssh [email protected] -p 830 -s netconf

If the user can successfully establish a NETCONF session with the device on either the default NETCONF
port (830) or a port that is specifically configured for NETCONF on your device, then NETCONF is enabled.
Otherwise, you must enable NETCONF over SSH on the device.
193

NOTE: The Ansible core modules for Junos OS might generate an “unable to open shell” error
for this and other reasons. For more information, see https://docs.ansible.com/ansible/latest/
network_debug_troubleshooting.html#unable-to-open-shell.

Solution

Enable NETCONF on the device running Junos OS.

[edit]
user@host# set system services netconf ssh
user@host# commit

RELATED DOCUMENTATION

Setting up Ansible for Junos OS Managed Nodes | 39


Understanding the Ansible Inventory File When Managing Devices Running Junos OS | 28
Troubleshooting Ansible Authentication Errors When Managing Devices Running Junos OS | 193

Troubleshooting Ansible Authentication Errors When


Managing Devices Running Junos OS
Problem
Description:

During execution of a Juniper.junos module, the Ansible control machine generates a ConnectAuthError
error for failed authentication. For example:

"msg": "Unable to make a PyEZ connection: ConnectAuthError(dc1a.example.net)"

Cause
The device running Junos OS might fail to authenticate the user for the following reasons:

• The user does not an have an account on the device running Junos OS.
194

• The user has an account with a text-based password configured on the device running Junos OS, but
the wrong password or no password is supplied for the user when executing the module.

• The user has an account on the device running Junos OS with SSH keys configured, but the SSH keys
are inaccessible on either the device or the control machine.

NOTE: The Ansible core modules for Junos OS might generate an “unable to open shell” error
for this and other reasons. For more information, see https://docs.ansible.com/ansible/latest/
network_debug_troubleshooting.html#unable-to-open-shell.

Solution
Ensure that the user executing the Ansible for Junos OS modules has a Junos OS login account on all target
devices running Junos OS and that an SSH public/private key pair or text-based password is configured
for the account. If SSH keys are configured, verify that the user can access them.

RELATED DOCUMENTATION

Setting up Ansible for Junos OS Managed Nodes | 39


Authenticating Users Executing Ansible Modules on Devices Running Junos OS | 50
Troubleshooting Ansible Connection Errors When Managing Devices Running Junos OS | 190

Troubleshooting Ansible Errors When Configuring


Devices Running Junos OS

IN THIS SECTION

Troubleshooting Configuration Timeout Errors | 195

Troubleshooting Configuration Lock Errors | 195

Troubleshooting Configuration Change Errors | 196

Troubleshooting Commit Errors | 197


195

The following sections outline errors that you might encounter when using Ansible to configure devices
running Junos OS. These sections also present potential causes and solutions for each error.

Troubleshooting Configuration Timeout Errors


Problem
Description: 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

Cause
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 juniper_junos_config timeout argument to an appropriate value and re-run
the playbook.

Troubleshooting Configuration Lock Errors


Problem
Description:

The playbook generates an error message indicating that the configuration cannot be locked. For example:

FAILED! => {"changed": false, "failed": true, "msg": "Unable to open the
configuration in exclusive mode: LockError(severity: error, bad_element: None,
message: configuration database modified)"}

or

FAILED! => {"changed": false, "failed": true, "msg": "Unable to open the
configuration in exclusive mode: LockError(severity: error, bad_element:
lock-configuration, message: permission denied)"}
196

Cause
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 device running Junos OS to give the current user the necessary
permissions to make the changes.

Troubleshooting Configuration Change Errors


Problem
Description:

The playbook generates a ConfigLoadError error message indicating that the configuration cannot be
modified, because permission is denied.

FAILED! => {"changed": false, "failed": true, "msg": "Failure loading the
configuraton: ConfigLoadError(severity: error, bad_element: scripts, message:
error: permission denied)"}

Cause
This error message is generated when the user executing the Ansible module has permission to modify
the configuration but does not have permission to alter the requested section of the configuration.

Solution
To solve this issue, either execute the playbook with a user who has the necessary permissions, or if
appropriate, configure the device running Junos OS to give the current user the necessary permissions to
make the changes.
197

Troubleshooting Commit Errors


Problem
Description:

The juniper_junos_config module or the older junos_install_config module generates a CommitError error
message indicating that the commit operation failed due to a configuration lock error.

FAILED! => {"changed": false, "failed": true, "msg": "Unable to commit


configuration: CommitError(edit_path: None, bad_element: None, message: error:
remote lock-configuration failed on re0\n\nnote: consider using 'commit synchronize
force' to\nterminate remote edit sessions and force the commit)"}

Cause
A configuration lock error can occur for the reasons described in “Troubleshooting Configuration Lock
Errors” on page 195. However, a configuration lock failed message might be generated as part of a
CommitError instead of a LockError in the event that the task requests a commit check and a commit
operation, and the device initiates the commit operation before the commit check operation releases the
configuration lock.

Solution
To enable sufficient time for the device to complete the commit check operation and release the
configuration lock before initiating the commit operation, set the juniper_junos_config or junos_install_config
module’s check_commit_wait parameter to an appropriate value and re-run the playbook. The
check_commit_wait value is the number of seconds to wait between the commit check and commit
operations.

The following sample task waits five seconds between the commit check and commit operations:

- name: "Load configuration. Wait 5 seconds between check and commit"


juniper_junos_config:
load: "merge"
format: "text"
src: "build_conf/{{ inventory_hostname }}/junos.conf"
check_commit_wait: 5
comment: "updated using Ansible"

RELATED DOCUMENTATION

Using Ansible to Configure Devices Running Junos OS | 158

You might also like