Try using Junos On-box Python # 2 Commit Script

Overview

Last time, I introduced Op Script, which is one of the easy ways to use Junos On-box Python.

Continuing from the last time, I would like to introduce Commit Script this time.

What is Commit Script?

A Commit Script is a script of Junos scripting mechanism called Junoscript that is executed triggered by "commit by user".

The Commit Script is called when the user executes a commit, and controls the commit or modifies the committed config depending on the information such as the committed user and time, the config to be committed, the current state of the device, etc. You can do things like do.

For example, the following use cases are possible.

In the form of saying, various usages can be considered depending on the idea.

This time, I will introduce Commit Script in On-box Python with a simple sample.

Setting

In order to use Commit Script, you need to write the script you want to use in the settings as follows.

set system scripts language python
set system scripts commit file commit-script.py

The script described here should be prepared in / var / db / scripts / commit.

If you want to enable the * Transient Configuration * change method among the setting change methods at Commit, make the following additional settings.

set system scripts commit allow-transients

Details will be described later, but it is necessary every time there is a setting that you want to dynamically generate from the script, such as expanding the setting by macro.

Example 1: Reject a commit for a config that does not contain the required settings

Now let's try Commit Script.

For example, the script that rejects a Config that does not have a host name set is:

commit-script.py


from junos import Junos_Configuration
import jcs

def main():
  root = Junos_Configuration

  if root.find('./system/host-name') == None:
    jcs.emit_error("Hostname is not defined!!!")


if __name__ == '__main__':
  main()

There are unique terms such as Junos_Configuration and jcs, but Junos-Configuration is the XML root of the Configuration that is about to be committed, and you can check this to set it. You can check and change it. jcs is a namespace that defines methods for event generation, status acquisition, etc. in Commit Script. See the Official Documentation (https://www.juniper.net/techpubs/en_US/junos16.1/topics/concept/junos-script-automation-junos-extension-functions-jcs-namespace.html) for more information. please.

The content of the script is simple: extract the XML at the position / system / host-name from the configuration, and when the result is None, call jcs.emit_error and get an error Is output.

The output result will be as follows.

[edit]
root@vmx1# show system host-name
host-name vmx1;

[edit]
root@vmx1# delete system host-name

[edit]
root@vmx1# commit check
error: Hostname is not defined!!!
error: 1 error reported by commit scripts
error: commit script failure

[edit]
root@vmx1# rollback 0
load complete

[edit]
root@vmx1# commit check
configuration check succeeds

In this way, the Commit check will only fail if the host name is not included. By the way, if you want to pass the Commit check but only display the warning, use jcs.emit_warning instead of jcs.emit_error.

Example 2: Change the settings

Next, I would like to introduce an example of changing the settings.

There are two ways to change the settings, one is to make permanent edits like a normal user, and the other is to make non-persistent (transient) edits.

First, let's try permanent editing. For example, here is an example script that changes the system timezone to ʻAsia / Tokyo`:

commit-script.py


import jcs

def main():
  xml = '<system><time-zone>Asia/Tokyo</time-zone></system>'

  jcs.emit_change(xml, "change", "xml")

if __name__ == '__main__':
  main()

The settings can be changed by specifying the changes, change method, and format in the jcs.emit_change method. The format is currently xml only.

When I run this script, it looks like this:

[edit]
root@vmx1# show system time-zone

[edit]
root@vmx1# commit check
configuration check succeeds

[edit]
root@vmx1# show | compare
[edit system]
+  time-zone Asia/Tokyo;

In this way, the time zone is added when the Commit Script is executed.

Example 3: Dynamic generation of settings and non-persistent application

The following is an example of implementing a so-called macro thing and transparently reflecting the generated settings on the device. As an example (I can't think of a simple and good example), here is an example script that defines the Default Description of an interface and sets the Default Description when there is an interface that does not contain a Description. Will be.

commit-script.py


from junos import Junos_Configuration
import jcs

def main():
  root = Junos_Configuration

  apply_macro = root.find("./interfaces/apply-macro[name='default-description']")

  xml_tmpl = '<interfaces>{0}</interfaces>'
  interface_xml_tmpl = '<interface><name>{0}</name><description>{1}</description></interface>'

  xml = ""

  if apply_macro:
    description_template = apply_macro.find('./data/name').text

    for element in root.findall("./interfaces/interface"):
      if element.find('description') is None:
        ifd_name = element.find('name').text
        xml += interface_xml_tmpl.format(ifd_name, description_template.format(ifd_name))

    xml = xml_tmpl.format(xml)

    jcs.emit_change(xml, "transient-change", "xml")

if __name__ == '__main__':
  main()

In this script, if Macro called default-description is defined directly under interfaces, the interface list is checked, and for interfaces for which Description is not set, the text specified in the default-description macro is specified. Make a move.

The point of generating changes in XML is the same as before, but the second argument of jcs.emit_change has changed from"change"to"transient-change". This is an option to treat the setting as temporary and not save it in the configuration file.

As mentioned above, when using transient-change, it is necessary to input the following settings.

set system scripts commit allow-transients

When this script is applied, it behaves as follows.

root@vmx1# show interfaces | display set
set interfaces apply-macro default-description "Description is not configured({0})"
set interfaces ge-0/0/0 disable
set interfaces ge-0/0/0 vlan-tagging
set interfaces ge-0/0/0 unit 1001 vlan-id 1001
set interfaces ge-0/0/0 unit 1001 family inet address 10.0.1.1/24
set interfaces ge-0/0/1 description test
set interfaces ge-0/0/1 unit 0 family inet
set interfaces fxp0 unit 0 family inet address 172.23.1.111/24

[edit]
root@vmx1# commit
commit complete

[edit]
root@vmx1# run show interfaces descriptions
Interface       Admin Link Description
ge-0/0/0        down  down Description is not configured(ge-0/0/0)
ge-0/0/1        up    down test
fxp0            up    up   Description is not configured(fxp0)

[edit]
root@vmx1# run show configuration interfaces | display set
set interfaces apply-macro default-description "Description is not configured({0})"
set interfaces ge-0/0/0 disable
set interfaces ge-0/0/0 vlan-tagging
set interfaces ge-0/0/0 unit 1001 vlan-id 1001
set interfaces ge-0/0/0 unit 1001 family inet address 10.0.1.1/24
set interfaces ge-0/0/1 description test
set interfaces ge-0/0/1 unit 0 family inet
set interfaces fxp0 unit 0 family inet address 172.23.1.111/24

Can you see the difference from the previous one? In # 2, the settings were changed during the commit check stage, and the changes appeared in the settings. On the other hand, if you use transient-change, it seems that the config has not been changed at first glance, but if you check the actual operation, you can see that the Description is set in Interface.

With transient-change, it is possible to macroize the settings in this way and hide the actual device settings other than the essential parameters. For example, if there are a large number of customers and a large number of settings are required, but the differences between customers are insignificant, it will be possible to make settings efficiently and with good visibility.

By the way, if you want to check the settings that are actually running on the device, you can check as follows.

root@vmx1> show configuration interfaces | display set | display commit-scripts
set interfaces apply-macro default-description "Description is not configured({0})"
set interfaces ge-0/0/0 description "Description is not configured(ge-0/0/0)"
set interfaces ge-0/0/0 disable
set interfaces ge-0/0/0 vlan-tagging
set interfaces ge-0/0/0 unit 1001 vlan-id 1001
set interfaces ge-0/0/0 unit 1001 family inet address 10.0.1.1/24
set interfaces ge-0/0/1 description test
set interfaces ge-0/0/1 unit 0 family inet
set interfaces fxp0 description "Description is not configured(fxp0)"
set interfaces fxp0 unit 0 family inet address 172.23.1.111/24

in conclusion

This time, I introduced Commit Script as one of the uses of Junoscript by On-box Python. I hope you can understand that there are many possible uses. The contents introduced this time can only be implemented using XSLT / Slax, but I think that it has become possible to write in Python and it has become very easy to get involved.

Next time, I would like to introduce how to use it in Event Script.

Recommended Posts

Try using Junos On-box Python # 2 Commit Script
Try using Junos On-box Python # 1 Op Script
Try using Junos' On-box Python #Bonus 1 Something like ChatOps / Commit and post to Slack
Try using Tweepy [Python2.7]
[Python] Try using Tkinter's canvas
Try using Kubernetes Client -Python-
Try using Pleasant's API (python / FastAPI)
Try using LevelDB in Python (plyvel)
Try using Python argparse's action API
Try using the Python Cmd module
Try using Leap Motion in Python
Try using Amazon DynamoDB from Python
Try python
Try mathematical formulas using Σ with python
Try using the Kraken API in Python
Try using Dialogflow (formerly API.AI) Python SDK #dialogflow
Try using Python with Google Cloud Functions
Try to operate Excel using Python (Xlwings)
Script python file
Try using docker-py
python script skeleton
Try using cookiecutter
Try using PDFMiner
Try using the BitFlyer Ligntning API in Python
Python script profiling
Python: Try using the UI on Pythonista 3 on iPad
Start using Python
Import python script
Try using Selenium
Try using scipy
Python> try: / except:
Try using the Python web framework Tornado Part 1
Try using pandas.DataFrame
Try Juniper JUNOS PyEz (python library) Memo 1 ~ PyEz Overview ~
Try using the collections module (ChainMap) of python3
Try using tensorflow ① Build python environment and introduce tensorflow
Try using django-swiftbrowser
Try using matplotlib
Try using the Python web framework Tornado Part 2
Try using tf.metrics
Try using PyODE
Run a python script from excel (using xlwings)
Scraping using Python
Try using ChatWork API and Qiita API in Python
Try using the DropBox Core API in Python
[Unity (C #), Python] Try running Python code in Unity using IronPython
Try creating a compressed file using Python and zlib
(Python) Try to develop a web application using Django
Try projective transformation of images using OpenCV with Python
Try to extract high frequency words using NLTK (python)
Try scraping with Python.
Operate Redmine using Python Redmine
Fibonacci sequence using Python
python try ~ except ~ else
Data analysis using Python 0
Data cleaning using Python
[Azure] Try using Azure Functions
Try Debian + Python 3.4 + django1.7 ...
Using Python #external packages
Try using virtualenv now
DynamoDB Script Memo (Python)