Topic: tech juniper jaut prev next

tech juniper jaut > Junos Platform Automation and DevOps (JAUT)

Junos Platform Automation and DevOps (JAUT)

Module 12: JSNAPy

Junos Snapshot Administrator in Python creates snapshots and performs tests. It is a Python version of JSNAP, which was written in SLAX.

Commands and Workflows

Common 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.

Architecture

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.

Configuration Files

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: ...

Commands

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 File Structure

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:

Example

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

Example

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

Operators

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.

Integration with Other Tools

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.