Post JSON data to URL from Junos, now in Python
In my previous post Post JSON data to URL from Junos, “Event-driven” I wrote the event/op script in SLAX, mainly because my Python skills are still rough and I fell back to my “muscle memory” to get the job done.
Well, got some spare time and thought, why not exploring the same task in Python. After all, Junos supports on box Python for some time now. Check out Understanding Python Automation Scripts for Devices Running Junos OS for more details.
Turns out, the final script is even a few lines shorter, thanks to PyEz in Junos:
import argparse
import httplib
import jcs
from jnpr.junos import Device
import json
import socket
logprefix = "collect_and_post.py: "
arguments = {'url': 'URL to post data to (e.g. http://192.168.1.100:8000)'}
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-url', required=True)
args = parser.parse_args()
dev = Device()
dev.open()
mactable = dev.rpc.get_bridge_mac_table({'format': 'json'})
lldp_nb = dev.rpc.get_lldp_neighbors_information({'format': 'json'})
html_post = [
mactable,
lldp_nb
]
args.url = args.url + "/"
proto, url, path = args.url.split("/")[-3:]
conn = httplib.HTTPConnection(url)
try:
conn.request('POST', path, body=json.dumps(html_post))
res = conn.getresponse()
message = "Data sent to %s: %d %s" % (args.url, res.status, res.reason)
print(message)
jcs.syslog("user.notice", logprefix, message)
except (httplib.HTTPException, socket.error) as ex:
message = "Error: %s" % ex
print(message)
jcs.syslog("user.error", logprefix, message)
dev.close()
if __name__ == '__main__':
main()
Upload the script to /var/db/scripts/op and /var/db/scripts/event, then add the following configuration to the device:
set system scripts language python
set system scripts op file collect_and_post.py
set event-options policy interface-up events lldp_neighbor_up
set event-options policy interface-up events snmp_trap_link_up
set event-options policy interface-up then event-script collect_and_post.py arguments url http://192.168.1.100:8000
set event-options event-script file collect_and_post.py python-script-user mwiget
Replace the script-user with a valid user-name that matches the owner of the event script on the Junos device. Otherwise it won’t trigger.
To test, clear the LLDP neighbors, then check the log and your webserver:
mwiget@vmx1> clear lldp neighbors
mwiget@vmx1> show lldp neighbors
mwiget@vmx1> show lldp neighbors
mwiget@vmx1> show lldp neighbors
mwiget@vmx1> show lldp neighbors
Local Interface Parent Interface Chassis Id Port info System Name
ge-0/0/3 - 2c:6b:f5:26:18:c0 521 vmx2
mwiget@vmx1> show log messages |match collect
Aug 27 16:56:36 vmx1 cscript.crypto: collect_and_post.py: Data sent to http://192.168.1.100:8000/: 200 OK
Readers familiar with Python will probably question the use of httlib instead of the requests Python module. Junos currently supports the following Python Modules on Devices Running Junos OS and requests isn’t one of them. Hence the fallback to httplib. Same truth applies to urllib, which would have been handy to parse the URL.
Update Aug 28th: urlparse module is available, should have used that one. urllib is available too, but because of Python2, it doesn’t contain urllib.parse).
While my parsing worked for my demo use case, I’m sure it has issues and needs some proper coding. Suggestions are more than welcome.