Topic: tech juniper jaut prev next
tech juniper jaut > Junos Platform Automation and DevOps (JAUT)
Junos Snapshot Administrator in Python creates snapshots and performs tests. It is a Python version of JSNAP, which was written in SLAX.
snap
takes a snapshotcheck
compares two snapshots based on user-defined test casessnapcheck
compares the current state against user-defined test casesdiff
compares snapshots line by line without test casesCommon workflows are snapcheck, snap-snap-check and snap-snap-diff.
The snapcheck workflow is used for audits, checking that the state of a device
complies with rules. It requires only a single JSNAPy command, ‘snapcheck
’.
The snap-snap-check workflow takes two snapshots, before and after the maintenance. It compares the states in the snapshots before and after the maintenance, to check that there were no undesired changes.
The snap-snap-diff workflow checks for differences between the before and after states, with no predefined test conditions.
JSNAPy runs on a management server. It uses PyEZ to make NETCONF connections.
It uses YAML formatted configuration and tests. JSNAPy runs from the command
line or as a module. The root configuration file is in
‘/etc/jsnapy.jsnapy.cfg
’. Snapshots are optionally stored in a SQLite
database.
JSNAPy can be installed from Pip. The package name is ‘jsnapy
’. It can be
run from a Python virtual environment.
The ‘hosts
’ section is mandatory. It lists hosts and may include an external
file. The ‘tests
’ section contains a list of files, each of which contains
tests. This section is also mandatory. The ‘sqlite
’ setion contains
information required to use a SQLite database. This section is optional. The
‘mail
’ section provides information to send the results through email. This
section is also optional.
---
hosts:
- include: devices.yml
group: EX
tests:
- test_is_equal.yml
- test_is_in.yml
sqlite:
- store_in_sqlite: yes
check_from_sqlite: yes
database_name: jbb.db
mail: send_mail.yml
The hosts section, or the included hosts file, has the following format. When including a hosts file, a group can be specified, and all hosts become part of that group.
hosts:
- device: <ip address>
username: ...
passwd: ...
Sample ‘devices.yml
’ file, in which hosts are arranged by group;
EX:
- device: <ip address>
username: ...
passwd: ...
MX:
- device: <ip address>
username: ...
passwd: ...
jsnapy --snap pre_snapname -f main_configfile
jsnapy --check post_snapname pre_snapname -f main_configfile
jsnapy --snapcheck snapname -f main_configfile
jsnapy --diff pre_snapname post_snapname -f main_configfile
Using the snap-snap-check workflow, take two snapshots (before and after). Use the same configuration file for all operations.
jsnapy --snap pre_snapname -f main_configfile
# ... make some changes ...
jsnapy --snap post_snapname -f main_configfile
jsnapy --check post_snapname pre_snapname -f main_configfile
Note that snap names are not filenames. Filenames are constructed from the
hostname, the snap name, and the command or RPC. Each test is put in its own
file, even if multiple tests are performed from the same test file. The
default snapshot directory is ‘~/jsnapy/snapshots/
’
Test name:
- rpc | command: <Junos RPC or command>
kwargs: <keyword args for RPC>
# 'item' matches the first node in the xpath, 'iterate' loops through all
- item | iterate:
xpath: <xpath for tests>
tests:
- <operator>: <values to comapre>
info: <log on success>
err: <log on failure>
# optionally, limit execution to specific tests within this file
tests_include:
Check that all interfaces on a device have an admin status of ‘up’. The check is made against a rule, rather than an earlier state, so the snap-check workflow is used.
The file ‘config_interfaces_up.yml
’;
hosts:
- device: 172...
username: ...
passwd: ...
tests:
- test_interfaces_up.yml
The file ‘test_interfaces_up.yml
’;
Test interface admin status:
- rpc: get-interface-information
kwargs:
terse: True
- iterate:
xpath: physical-interface
tests:
- is-equal: admin-status, up
info: "Test succeeded - admin-status of {{pre['name']}} is equal to {{pre['admin-status'}} with oper-status {{pre[['oper-status']}}"
err: "Test failed - admin-status of {{pre['name']}} is equal to {{pre['admin-status'}} with oper-status {{pre[['oper-status']}}"
Run the above example with;
jsnapy --snapcheck snap-interfaces -f config_interfaces_up.yml
Check that the physical interface state is the same before and after the change. This compares ‘before’ and ‘after’ states, so the snap-snap-check workflow must be used.
The file ‘config_interfaces_unchanged.yml
’. This is almost the same as
‘config_interfaces_up.yml
’ config file above;
hosts:
- device: 172...
username: ...
passwd: ...
tests:
- test_interfaces_unchanged.yml
The file ‘test_interfaces_unchanged.yml
’. Similarly, this is almost the same
as the ‘test_interfaces_up.yml
’ test file above. The main difference is the
use of the ‘no-diff
’ check, rather than ‘is-equal
’;
Test interfaces unchanged:
- rpc: get-interface-information
kwargs:
terse: True
- iterate:
xpath: physical-interface
tests:
- no-diff: admin-status
info: "Test succeeded - admin-status of {{pre['name']}} is equal to {{pre['admin-status'}} with oper-status {{pre[['oper-status']}}"
err: "Test failed - admin-status of {{pre['name']}} is equal to {{pre['admin-status'}} with oper-status {{pre[['oper-status']}}"
The test is now executed in three steps;
jsnapy --snap interfaces-pre -f config_interfaces_unchanged.yml
jsnapy --snap interfaces-post -f config_interfaces_unchanged.yml
jsnapy --check interfaces-pre interfaces-post -f config_interfaces_unchanged.yml
Some operators require two snapshots, so only work with the snap-snap-check workflow.
Consider the workflow to decide on the operators to use. For example, snap-check only uses one snapshot, so operators that require two snapshots won’t work.
Ansible has a module named juniperjunosjsnapy which is part of the Juniper.junos role in Ansible Galaxy. Ansible will not report on individual failed tests, so it is recommended that the result is stored in a variable.
tasks:
- name: Snapcheck interface status
juniper_junos_jsnapy:
action: snapcheck
config_file: ...
logfile: ...
provider: {"user": ..., "passwd" ...}
register: result
JSNAPy can be called from Python code. Import the SnapAdmin
class from
jnpr.jsnapy
. Call the snap()
, check()
or snapcheck()
methods.
js = SnapAdmin()
snapchk = js.snapcheck(config_data, 'pre')
for val in snapchk:
print("Tested on " + val.device ...)
# use val.device, val.result, val.no_passed, val.no_failed
# pprint(dict(val.test_details))
Any other tool that supports the execution of custom Python code, such as Salt, can support JSNAPy.