[PYTHON] I tried using PyEZ and JSNAPy. Part 2: I tried using PyEZ

I tried using PyEZ and JSNAPy. It is a sequel to. This time, I will introduce the contents of using PyEZ.

-I tried using PyEZ and JSNAPy. Part 1: Overview -I tried using PyEZ and JSNAPy. Part 2: I tried using PyEZ (Imakoko) -I tried using PyEZ and JSNAPy. Part 3: I tried using JSNAPy -I tried using PyEZ and JSNAPy. Part 4: Automating ISP setting work with PyEZ and JSNAPy

About PyEZ

PyEZ is a Python library for configuring JUNOS routers. By the way, it seems that a Ruby library called RubyEZ is also available.

Screen Shot 2016-11-02 at 11.00.31 AM.png

Communication with the router uses NETCONF over SSH and is designed to operate on the TCP 830 port recommended by RFC by default.

PyEZ seems to be available from JUNOS version 11.4. Compared to other manufacturers, automation tools can only be used with newer OS versions in many cases, but with the combination of JUNOS + PyEZ, it can be used with JUNOS routers that have already been installed and operated at many operation sites. Therefore, it can be said that it is an easy-to-use tool due to the low threshold of introduction. (In the actual network operation site, in order to avoid performance deterioration and defects, many organizations may adopt only the OS version with dead bugs. "The new OS cannot be used unless the bugs are dead." "Results I imagine that there may be cases where the consideration and introduction of automation is postponed by several years.)

What PyEZ can do

--Router config input --load (merge / overload / replace option can be specified)

I haven't tried all the features, but it seems like I can almost do it manually with PyEZ. If you find something you can't do while using PyEZ, please share your knowledge.

Reference material

Understanding will be quicker if you proceed while looking at the following articles / documents. They are arranged in the order that was helpful.

Japanese introduction blog -Note 1 to try Juniper JUNOS PyEz (python library) ~ PyEz Overview ~ -Note 2 to try Juniper JUNOS PyEz (python library) ~ ~ Get information by PyEz ~ -Note 3 to try Juniper JUNOS PyEz (python library) ~ ~ Change settings by PyEz ~

PyEZ Github

Juniper Official Document

Advance preparation

Here, Python 2.7.10 is used as the server that runs the tool, and firefly is used as the JUNOS router.

First, install PyEZ with the pip command. Here, the latest version 2.0.1 is used.

pip install junos-eznc

pip list
junos-eznc (2.0.1)

Also, on the JUNOS router side, input the settings to enable NETCONF.

Router information


root@firefly1> show version
Hostname: firefly1
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

NETCONF enabled configuration


system {
    services {
        netconf {
            ssh;
        }
      }
    }
}

Simply configure the router as above and it will start listening for TCP 830 for NETCONF over SSH.

root@firefly1> show system connections | grep 830
tcp4       0      0  *.830     *.*      LISTEN

PyEZ Use Case 1: Change the host name of the router

The minimum configuration program for PyEZ to run is shown below. Here, the host name is changed from firefly1 to firefly1_changed_by_PyEZ.

set_firefly1_change_hostname.Excerpt from py's PyEZ setting part only


#! /usr/bin/env python
# -*- coding: utf-8 -*-

from jnpr.junos import Device
from jnpr.junos.utils.config import Config

#Define the information to be controlled
dev1 = Device(
            host="192.168.34.16",
            user="user1",
            password="password1"
        )   
dev1.open()

#Establish a session
dev1.open()
dev1.bind(cu=Config)

#Show host name
print "Hostname : ",
print dev1.facts["hostname"]

#Locked so that settings are not changed from other sessions
dev1.cu.lock()

#Configuration file(./configs/change_hostname.conf")Read
#At this point, the candidate config is only updated, and commit has not been executed.
conf_filename = "./configs/change_hostname.conf"
dev1.cu.load(path=conf_filename, format="text", merge=True)

#Execute commit check. Judge whether there is a problem with the settings.
print "Commit Check : ",
if dev1.cu.commit_check() :
    print "OK"
else:
    print "Error"

#Entrust the user to choose whether or not to commit(Of course, automatic commit is also possible)
print "Do you commit? y/n"
choice = raw_input().lower()
if choice == "y":
    #Commit.
    dev1.cu.commit()
    print "Commit candidate config : OK"
else:
    #Rollback without commit. The candidate config is deleted.
    dev1.cu.rollback()
    print "Rollback : OK"

#Session unlock
dev1.cu.unlock()

#End of session
dev1.close()

:./configs/change_hostname.conf


system {
    host-name firefly1_changed_by_PyEZ;
}

With the above program, it is possible to submit the host name change config.

As a demo code, the one implemented with the display part added is published on github. https://github.com/taijiji/sample_pyez/blob/master/set_firefly1_change_hostname.py

The execution result is as follows. Screen Shot 2016-11-26 at 7.09.58 PM.png

  1. Read the file (./configs/change_hostname.conf) containing the router config into the router (commit not executed at this point).
  2. Check the setting difference with diff
  3. commit check
  4. Execute commit

I was able to change the Hostname using the same execution procedure as the manual setting. Of course, I was able to confirm that the host name of the actual router was changed.

Check the host name on the router


root@firefly1_changed_by_PyEZ>
root@firefly1_changed_by_PyEZ> show version
Hostname: firefly1_changed_by_PyEZ
Model: firefly-perimeter
JUNOS Software Release [12.1X47-D20.7]

PyEZ usage example 2: Add router interface (variable part of config file)

Earlier, we used a statically generated config file in advance, but with PyEZ, it is possible to make a part of the config file variable as shown below by using the template engine.

interfaces {
   {{ if_name }} {
        unit 0 {            
            description {{ if_description }};
            family inet {
                address {{ if_address_ipv4 }}/{{ if_subnet_ipv4 }};
            }
        }
    }
} 

When using static config, it is necessary to prepare / manage similar config files for configuration settings with multiple parameters such as interface and BGP neighbor, and as a result, it is necessary to manage a large number of config files. It will come out. By making a part of the configuration file variable / template here, you can reduce the target of the configuration file to be managed.

PyEZ uses Jinaja2, one of the template engines, to make the config file variable. I have introduced Jinja2 on my blog in the past, so please refer to it here. How to use Template Engine for Network Engineer

Here, only the difference from PyEZ usage example 1 is introduced. Please check github for the sample code for the demo that you actually wrote. https://github.com/taijiji/sample_pyez/blob/master/set_firefly1_add_interface.py

set_firefly1_add_interface.Excerpt from py


dev1 = Device(
            host="192.168.34.16",
            user="user1",
            password="password1"
        )   
dev1.open()

# interface ge-0/0/Display the settings of 2 in RPC format
if_info = dev1.rpc.get_interface_information(
                    interface_name='ge-0/0/2',
                    terse=True)
print etree.tostring(if_info)

#Specify the template file name
template_filename = "./configs/add_interface.jinja2"
#Specify variables in the template file
add_if_param = {
    'if_name' : 'ge-0/0/2',
    'if_description' : 'add_by_PyEZ',
    'if_address_ipv4' : '192.168.35.1',
    'if_subnet_ipv4' : '30'
}

#Load the config using the template file
dev1.cu.load(
    template_path=template_filename, 
    template_vars=add_if_param, 
    format="text",
    merge=True
)

#Commit config
dev1.cu.commit()

:./configs/add_interface.jinja2


interfaces {
   {{ if_name }} {
        unit 0 {            
            description {{ if_description }};
            family inet {
                address {{ if_address_ipv4 }}/{{ if_subnet_ipv4 }};
            }
        }
    }
} 

This is the execution result of the demo program.

Execution result


% python set_firefly1_add_interface.py 

##### Operation : Start #######
Connecting to device :  OK
Hostname :  firefly1
Interfaces ge-0/0/2 :
##############################
<interface-information style="terse">
<physical-interface>
<name>
ge-0/0/2
</name>
<admin-status>
up
</admin-status>
<oper-status>
up
</oper-status>
</physical-interface>
</interface-information>

##############################
Load config :
OK
Target template : ./configs/add_interface.jinja2
##############################
interfaces {
   ge-0/0/2 {
        unit 0 {
            description add_by_PyEZ;
            family inet {
                address 192.168.35.1/30;
            }
        }
    }
}
##############################
Diff :
##############################

[edit interfaces]
+   ge-0/0/2 {
+       unit 0 {
+           description add_by_PyEZ;
+           family inet {
+               address 192.168.35.1/30;
+           }
+       }
+   }

##############################
Commit Check :  OK
Do you commit? y/n
y
Commit candidate config : OK
Interfaces ge-0/0/2 :
##############################
<interface-information style="terse">
<physical-interface>
<name>
ge-0/0/2
</name>
<admin-status>
up
</admin-status>
<oper-status>
up
</oper-status>
<logical-interface>
<name>
ge-0/0/2.0
</name>
<admin-status>
up
</admin-status>
<oper-status>
up
</oper-status>
<description>
add_by_PyEZ
</description>
<filter-information>
</filter-information>
<address-family>
<address-family-name>
inet
</address-family-name>
<interface-address>
<ifa-local emit="emit">
192.168.35.1/30
</ifa-local>
</interface-address>
</address-family>
</logical-interface>
</physical-interface>
</interface-information>

##############################
##### Operation : End #####

It is a little difficult to understand because the information acquisition with PyEZ is in XML-RPC format, but you can see that the IP address and description are set to ge-0 / 0/2, which was not before the setting.

If you check it with an actual router, you can see that it is set as follows.

Check with router


root@firefly1> show configuration interfaces ge-0/0/2
unit 0 {
    description add_by_PyEZ;
    family inet {
        address 192.168.35.1/30;
    }
}

Summary

This time, we introduced PyEZ with a focus on usage examples. I have tried some functions that I did not introduce in this article, so please refer to the sample code on Github. https://github.com/taijiji/sample_pyez

Next time, I will introduce JSNAPy. I tried using PyEZ and JSNAPy. Part 3: I tried using JSNAPy

Recommended Posts

I tried using PyEZ and JSNAPy. Part 2: I tried using PyEZ
I tried using PyEZ and JSNAPy. Part 1: Overview
I tried using PyEZ and JSNAPy. Part 4: Automate ISP setup with PyEZ and JSNAPy
I tried using parameterized
I tried using argparse
I tried using mimesis
I tried using anytree
I tried using Summpy
I tried using coturn
I tried using Pipenv
I tried using matplotlib
I tried using "Anvil".
I tried using Hubot
I tried using ESPCN
I tried using openpyxl
I tried using Ipython
I tried using PyCaret
I tried using cron
I tried using ngrok
I tried using face_recognition
I tried using Jupyter
I tried using PyCaret
I tried using Heapq
I tried using doctest
I tried using folium
I tried using jinja2
I tried using folium
I tried using time-window
I tried web scraping using python and selenium
[I tried using Pythonista 3] Introduction
I tried using easydict (memo).
I tried face recognition using Face ++
I tried using Random Forest
I tried using BigQuery ML
I tried using Amazon Glacier
I tried using git inspector
[Python] I tried using OpenPose
I tried using magenta / TensorFlow
I tried using AWS Chalice
I tried using Slack emojinator
I tried to get Web information using "Requests" and "lxml"
I tried crawling and scraping a horse racing site Part 2
I tried using Rotrics Dex Arm # 2
I tried using Rotrics Dex Arm
I tried using GrabCut of OpenCV
I tried using Thonny (Python / IDE)
I tried server-client communication using tmux
I tried reinforcement learning using PyBrain
I tried deep learning using Theano
Somehow I tried using jupyter notebook
[Kaggle] I tried undersampling using imbalanced-learn
I tried shooting Kamehameha using OpenPose
I tried using the checkio API
[Python] I tried using YOLO v3
I tried asynchronous processing using asyncio
I tried using docomo speech recognition API and Google Speech API in Java
I tried using Amazon SQS with django-celery
I installed DSX Desktop and tried it
I tried playing a ○ ✕ game using TensorFlow
I tried using YOUTUBE Data API V3
I tried using Selenium with Headless chrome