Install juniper/pyez-ansible Docker image

Main page:  1- Ansible


https://hub.docker.com/r/juniper/pyez-ansible/




Configuration on the Device

vMX config for ansible + Netconfig

set system login user ansible class super-user
set system login user ansible authentication encrypted-password "$1$rgdhLoHQ$/eV08mYSvYSBsaHbyaPTp/"            ## ansible123
set system services ssh root-login allow
set system services ssh protocol-version v2
set system services netconf ssh

Local netconfig Test:


Remote netconfig test

ssh ansible@192.168.56.11 -p 830 -s netconf



Install Docker

Start by clicking on the docker icon ( windows ) 

search for available containerdocker search juniper
pull the image ( optional)

docker pull juniper/pyez-ansible

docker images



Check Ansible roles

Juniper.junos role is hosted on the Ansible Galaxy website

install module

ansible-galaxy install Juniper.junos

ansible-galaxy list -p roles


list roles
/project # ansible-galaxy  list -p roles
# /root/.ansible/roles
- Juniper.junos, 2.3.2
# /etc/ansible/roles
- Juniper.junos, (unknown version)
[WARNING]: - the configured path /project/roles does not exist.
[WARNING]: - the configured path /usr/share/ansible/roles does not exist.
/project #
Create Ansible files and playbooks

Create an directory ( on the windows host )  + 


mkdir facts_playbooks

 cd facts_playbook/


and create the hosts 

vi hosts 

hosts
[vMX]
192.168.99.11

and create playbook.yml 

new module
/project # more pbk_getfacts.yml
---
- name: Get facts
  hosts: All-srx
  connection: local
  gather_facts: no
  roles:
    - Juniper.junos

  tasks:
    - name: Get junos facts
      juniper_junos_facts:
        host: "{{ inventory_hostname }}"
        user: "Netbox"
        passwd: "Netbox"
      register: junos
    - name: Print facts
      debug:
        var: junos

vi playbook.yml    with OLD module

playbook.yml
---
- name: Get facts
  hosts: vMX
  connection: local
  gather_facts: no
  
  roles:
  - Juniper.junos
  
  #vars_prompt:
  #- name: ADMUSER
  #    prompt: Username
  #    private: no
  #- name: ADMPASS
  #   prompt: password
  #   private: yes

  tasks:
  - name: Get junos facts
    junos_get_facts:
      #host: "{{ inventory_hostname }}"
      host: vMX
      #user: "{{ ADMUSER }}"
      user: "ansible"
      #passwd: "{{ ADMPASS }}"
      passwd: "ansible123"
    register: junos
  - name: Print facts
    debug:
      var: junos
Start and log back in : RUN & EXEC

Start the container:


cd   ~/Documents/ansiblescript/facts_playbook


docker run -it --rm -v $PWD:/project juniper/pyez-ansible ash


-it
--rm
-v    / --volume    $PWD         is the host directory
                              :                 seperator
                              /project    is the container directory

juniper/pyez-ansible   is the docker image




ansible version
/project # ansible --version
ansible 2.9.5
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Apr 22 2019, 10:28:12) [GCC 6.3.0]

/project # python --version
Python 3.6.8



log back in the container ( exec <container> )

docker ps

docker exec -it funny_kirch ash

/playbooks # cd /project/




basic  playbook

Basic test with hosts & playbook.yml file:

cd project

ansible-playbook -i hosts playbook.yml


output of playbook
/project # ansible-playbook -i hosts pbk_getfacts.yml
[DEPRECATION WARNING]: The TRANSFORM_INVALID_GROUP_CHARS settings is set to allow bad characters in group names by
default, this will change, but still be user configurable on deprecation. This feature will be removed in version
2.10. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details

PLAY [Get facts] ***************************************************************************************************

TASK [Get junos facts] *********************************************************************************************
[WARNING]: Platform linux on host 172.30.95.174 is using the discovered Python interpreter at /usr/bin/python, but
future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [172.30.95.174]

TASK [Print facts] *************************************************************************************************
ok: [172.30.95.174] => {
    "junos": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python",
            "junos": {
                "HOME": "/var/home/********",
                "RE0": {
                    "last_reboot_reason": "0x200:normal shutdown",
                    "mastership_state": "master",
                    "model": "RE-SRX300",
                    "status": "OK",
                    "up_time": "103 days, 18 hours, 47 minutes, 47 seconds"
                },
                "RE1": null,
                "RE_hw_mi": false,
                "current_re": [
                    "master",
                    "node",
                    "fwdd",
                    "member",
                    "pfem",
                    "backup",
                    "fpc0",
                    "re0",
                    "fpc0.pic0"
                ],
                "domain": null,
                "fqdn": null,
                "has_2RE": false,
                "hostname": "SRX300-1-RL102",
                "hostname_info": {
                    "re0": "SRX300-1-RL102"
                },
                "ifd_style": "CLASSIC",
                "junos_info": {
                    "re0": {
                        "object": {
                            "build": 10,
                            "major": [
                                19,
                                4
                            ],
                            "minor": "1",
                            "type": "R"
                        },
                        "text": "19.4R1.10"
                    }
                },
                "master": "RE0",
                "master_state": true,
                "model": "SRX300",
                "model_info": {
                    "re0": "SRX300"
                },
                "personality": "SRX_BRANCH",
                "re_info": {
                    "default": {
                        "0": {
                            "last_reboot_reason": "0x200:normal shutdown",
                            "mastership_state": "master",
                            "model": "RE-SRX300",
                            "status": "OK"
                        },
                        "default": {
                            "last_reboot_reason": "0x200:normal shutdown",
                            "mastership_state": "master",
                            "model": "RE-SRX300",
                            "status": "OK"
                        }
                    }
                },
                "re_master": {
                    "default": "0"
                },
                "re_name": "re0",
                "serialnumber": "CV3016AF0526",
                "srx_cluster": false,
                "srx_cluster_id": null,
                "srx_cluster_redundancy_group": null,
                "switch_style": "VLAN_L2NG",
                "vc_capable": false,
                "vc_fabric": null,
                "vc_master": null,
                "vc_mode": null,
                "version": "19.4R1.10",
                "version_RE0": "19.4R1.10",
                "version_RE1": null,
                "version_info": {
                    "build": 10,
                    "major": [
                        19,
                        4
                    ],
                    "minor": "1",
                    "type": "R"
                },
                "virtual": false
            }
        },
        "changed": false,
        "facts": {
            "HOME": "/var/home/********",
            "RE0": {
                "last_reboot_reason": "0x200:normal shutdown",
                "mastership_state": "master",
                "model": "RE-SRX300",
                "status": "OK",
                "up_time": "103 days, 18 hours, 47 minutes, 47 seconds"
            },
            "RE1": null,
            "RE_hw_mi": false,
            "current_re": [
                "master",
                "node",
                "fwdd",
                "member",
                "pfem",
                "backup",
                "fpc0",
                "re0",
                "fpc0.pic0"
            ],
            "domain": null,
            "fqdn": null,
            "has_2RE": false,
            "hostname": "SRX300-1-RL102",
            "hostname_info": {
                "re0": "SRX300-1-RL102"
            },
            "ifd_style": "CLASSIC",
            "junos_info": {
                "re0": {
                    "object": {
                        "build": 10,
                        "major": [
                            19,
                            4
                        ],
                        "minor": "1",
                        "type": "R"
                    },
                    "text": "19.4R1.10"
                }
            },
            "master": "RE0",
            "master_state": true,
            "model": "SRX300",
            "model_info": {
                "re0": "SRX300"
            },
            "personality": "SRX_BRANCH",
            "re_info": {
                "default": {
                    "0": {
                        "last_reboot_reason": "0x200:normal shutdown",
                        "mastership_state": "master",
                        "model": "RE-SRX300",
                        "status": "OK"
                    },
                    "default": {
                        "last_reboot_reason": "0x200:normal shutdown",
                        "mastership_state": "master",
                        "model": "RE-SRX300",
                        "status": "OK"
                    }
                }
            },
            "re_master": {
                "default": "0"
            },
            "re_name": "re0",
            "serialnumber": "CV3016AF0526",
            "srx_cluster": false,
            "srx_cluster_id": null,
            "srx_cluster_redundancy_group": null,
            "switch_style": "VLAN_L2NG",
            "vc_capable": false,
            "vc_fabric": null,
            "vc_master": null,
            "vc_mode": null,
            "version": "19.4R1.10",
            "version_RE0": "19.4R1.10",
            "version_RE1": null,
            "version_info": {
                "build": 10,
                "major": [
                    19,
                    4
                ],
                "minor": "1",
                "type": "R"
            },
            "virtual": false
        },
        "failed": false,
        "warnings": [
            "Platform linux on host 172.30.95.174 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information."
        ]
    }
}

PLAY RECAP *********************************************************************************************************
172.30.95.174              : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

/project # 


Check connectivity

Basic check netconfig

ansible-playbook -i hosts chk_netconf.yml -k -u Netbox


check netconfig
more chk_netconf.yml
---
- name: Get Device Facts
  hosts: All-srx
  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



Basic jsnapy
check jsnapy

pip3 install -U jsnapy

jsnapy --version
JSNAPy version: 1.3.4

default jsnapy folder

ls /etc/jsnapy/ -al

more /etc/jsnapy/jsnapy.cfg

more /etc/jsnapy/logging.yml

/etc/jsnapy
/project # ls /etc/jsnapy/ -al
total 20
drwxr-xr-x    2 root     root          4096 Feb 25 06:01 .
drwxr-xr-x    1 root     root          4096 Jun 24 13:24 ..
-rw-r--r--    1 root     root           381 May 31  2018 jsnapy.cfg
-rw-r--r--    1 root     root          1695 May 31  2018 logging.yml
/project # more /etc/jsnapy/jsnapy.cfg
# This file can be overwritten
# It contains default path for
# config file, snapshots and testfiles
# If required, overwrite the path with your path
#config_file_path: path of main config file
#snapshot_path : path of snapshot file
#test_file_path: path of test file

[DEFAULT]
config_file_path= /etc/jsnapy
snapshot_path = ~/jsnapy/snapshots
test_file_path = ~/jsnapy/testfiles
/project # more /etc/jsnapy/logging.yml
version: 1

disable_existing_loggers: True

## use formatters to cutomize your output
## add of remove parameters accordingly
##

formatters:
    custom_format:
        format: "%(asctime)s - %(name)s - %(levelname)s - %(hostname)s ............. \n %(message)s"
    simple:
        format: "%(hostname)s-- %(message)s"
    default:
        format: "%(message)s"
    default_file:
        format:  "%(asctime)s - %(name)s - %(levelname)s - \n %(message)s"
handlers:
    console:
        class: logging.StreamHandler
        level: INFO
        formatter: default
        stream: ext://sys.stdout

    info_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: INFO
        formatter: default_file
        filename: /var/log/jsnapy/jsnapy.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    error_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: ERROR
        formatter: default_file
        filename: /var/log/jsnapy/jsnapy.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    critical_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: CRITICAL
        formatter: default_file
        filename: /var/log/jsnapy/jsnapy.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    debug_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: DEBUG
        formatter: default_file
        filename: /var/log/jsnapy/jsnapy.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

root:
    level: DEBUG
    handlers: [console, debug_file_handler]

/project #

config file
test file


Basic jsnapy command
config file

/project # more /project/jsnapy-demo/configfiles/config1.yml

config file
---
  hosts:
    - device: 172.30.95.177
      username : Netbox
      passwd: Netbox
  tests:
    - /project/jsnapy-demo/testfiles/show_bgp_summary.yml

test file

/project # vi /project/jsnapy-demo/testfiles/show_bgp_summary.yml

check bgp neigbor
/project # vi /project/jsnapy-demo/testfiles/show_bgp_summary.yml
tests_include:
  - test_command_bgp
#  - test_rpc_bgp

test_command_bgp:
  - command: show bgp neighbor
  - iterate:
      xpath: '/bgp-information/bgp-peer'
      tests:
        - contains: peer-address, 192.168.100.2       # element in which test is performed
          err: "Test Failed!! peer-address got changed, it is now <{{post['peer-address']}}>"
          info: "Test succeeded!! peer-address is equal to <{{post['peer-address']}}>"

        - in-range: peer-as, 65100,65200        # element in which test is performed
          err: "Test Failed!! peer-as is not in range of 100-200, it is: <{{post['peer-as']}}>"
          info: "Test succeeded!! peer-as is in range of 100-200, it is now <{{post['peer-as']}}>"


run jsnapyjsnapy --snapcheck pre -f jsnapy-demo/configfiles/config1.yml
snapshot output file

sudo apt-get install libxml2-utils

xmllint --format ~/jsnapy/snapshots/172.30.95.177_pre_show_bgp_neighbor.xml


snapshot pre
Localtion in the container:
/project # ls ~/jsnapy/snapshots/
172.30.95.177_PRE_show_bgp_summary.xml   172.30.95.177_pre_show_bgp_summary.xml
172.30.95.177_pre_show_bgp_neighbor.xml



xmllint --format snapshot/172.30.95.177_pre_show_bgp_neighbor.xml
<?xml version="1.0"?>
<bgp-information>
  <bgp-peer style="detail">
    <peer-address>192.168.100.2+61132</peer-address>
    <peer-as>65100</peer-as>
    <local-address>192.168.100.1+179</local-address>
    <local-as>65200</local-as>
    <peer-group>eBGP</peer-group>
    <peer-cfg-rti>vRouter200</peer-cfg-rti>
    <peer-fwd-rti>vRouter200</peer-fwd-rti>
    <peer-type>External</peer-type>
    <peer-state>Established</peer-state>
    <peer-flags>Sync RSync</peer-flags>
    <last-state>EstabSync</last-state>
    <last-event>RecvKeepAlive</last-event>
    <last-error>None</last-error>
    <bgp-option-information>
      <export-policy>
exp-2-2BGP-in-vROuter200
</export-policy>
      <bgp-options>Preference PeerAS Refresh</bgp-options>
      <bgp-options2/>
      <bgp-options-extended/>
      <holdtime>90</holdtime>
      <preference>170</preference>
    </bgp-option-information>
    <flap-count>1</flap-count>
    <last-flap-event>RecvNotify</last-flap-event>
    <bgp-error>
      <name>Cease</name>
      <send-count>0</send-count>
      <receive-count>1</receive-count>
    </bgp-error>
    <peer-id>192.168.100.10</peer-id>
    <local-id>192.168.100.1</local-id>
    <active-holdtime>90</active-holdtime>
    <keepalive-interval>30</keepalive-interval>
    <group-index>0</group-index>
    <peer-index>0</peer-index>
    <snmp-index>0</snmp-index>
    <bgp-peer-iosession>
      <iosession-thread-name>bgpio-0</iosession-thread-name>
      <iosession-state>Enabled</iosession-state>
    </bgp-peer-iosession>
    <bgp-bfd>
      <bfd-configuration-state>disabled</bfd-configuration-state>
      <bfd-operational-state>down</bfd-operational-state>
    </bgp-bfd>
    <local-interface-name>ae1.0</local-interface-name>
    <local-interface-index>615</local-interface-index>
    <peer-restart-nlri-configured>inet-unicast</peer-restart-nlri-configured>
    <nlri-type-peer>inet-unicast</nlri-type-peer>
    <nlri-type-session>inet-unicast</nlri-type-session>
    <peer-refresh-capability>2</peer-refresh-capability>
    <peer-stale-route-time-configured>300</peer-stale-route-time-configured>
    <peer-no-restart/>
    <peer-restart-flags-received>Notification</peer-restart-flags-received>
    <peer-restart-nlri-negotiated>inet-unicast</peer-restart-nlri-negotiated>
    <peer-end-of-rib-received>inet-unicast</peer-end-of-rib-received>
    <peer-end-of-rib-sent>inet-unicast</peer-end-of-rib-sent>
    <peer-end-of-rib-scheduled/>
    <peer-no-llgr-restarter/>
    <peer-4byte-as-capability-advertised>65100</peer-4byte-as-capability-advertised>
    <peer-addpath-not-supported/>
    <bgp-rib style="detail">
      <name>vRouter200.inet.0</name>
      <rib-bit>20000</rib-bit>
      <bgp-rib-state>BGP restart is complete</bgp-rib-state>
      <vpn-rib-state>VPN restart is complete</vpn-rib-state>
      <send-state>in sync</send-state>
      <active-prefix-count>6</active-prefix-count>
      <received-prefix-count>6</received-prefix-count>
      <accepted-prefix-count>6</accepted-prefix-count>
      <suppressed-prefix-count>0</suppressed-prefix-count>
      <advertised-prefix-count>1</advertised-prefix-count>
    </bgp-rib>
    <last-received>17</last-received>
    <last-sent>25</last-sent>
    <last-checked>846086</last-checked>
    <input-messages>31116</input-messages>
    <input-updates>2</input-updates>
    <input-refreshes>0</input-refreshes>
    <input-octets>591306</input-octets>
    <output-messages>31345</output-messages>
    <output-updates>1</output-updates>
    <output-refreshes>0</output-refreshes>
    <output-octets>595587</output-octets>
    <bgp-output-queue>
      <number>1</number>
      <count>0</count>
      <table-name>vRouter200.inet.0</table-name>
      <rib-adv-nlri>inet-unicast</rib-adv-nlri>
    </bgp-output-queue>
  </bgp-peer>
</bgp-information>


snapshot database