If you are like me at some point you got psyched that Python was coming to NetMRI. This article will get you started with Python in NetMRI from the basics “run this command” on my devices to advance “grab some data via an API call” and trigger an action within NetMRI.
Before you get started…Need to Know about Python Scripts
Note: Well-known variables for Python scripting are listed in the topic Scripting Well-Known Variables (Perl, Python, and CCS).
Python scripts use a script header similar to a CCS script, contained within a well-known comment block.
The script header block influences a number of runtime behaviors, including:
Script-Timeout
Specifies the per-command timeout for the entire script in seconds.
- Type: Integer
- Required: No
- Default if not specified: 60
Script-Login
Specifies whether the job engine should automatically establish a connection with the target device.
- Type: Boolean
- Required: No
- Default if not specified: true
Script-Variables
- Specifies inputs needed by the script.
- Type: Tuple (ordered list of elements)
- Required: No
- Default if not specified: None
Script-Filter
Specifies the device types processed by the script.
- Type: String
- Required: Yes
A Python Script header block must be defined inside of comments within a “well known” comment section (between # BEGIN-SCRIPT-BLOCK and a # END-SCRIPT-BLOCK). The following example demonstrates the difference between a CCS and Python Script header block that specifies a Script-Filter that applies to all Cisco IOS devices.
As a comparison, a CCS implementation is straightforward:
Script-Filter: $Vendor == “Cisco” and $sysDesc like /IOS/
You can filter by the network view:
Script-Filter: $network == “blue”
A comparable Python implementation is as follows:
# BEGIN-SCRIPT-BLOCK
# Script-Filter: $Vendor == “Cisco” and $sysDesc like /IOS/
# END-SCRIPT-BLOCK
Working Environment
- NetMRI System version 7.2(Python was added as a scripting option in NetMRI)
- Sandbox System
- Python scripts run inside the sandbox, using the Python API to communicate with the Device Interaction Server (DIS) on NetMRI. The DIS proxies CLI requests/responses to/from network devices on behalf of the Python scripts.
Before commands can be sent to a network device, a Python script must first establish a DIS session (see v2 API object DisSession). After a session has been established, a CLI connection with the target device must be established for the given session (see v2 API object CliConnection).
The majority of the time, a Python script will follow this same initialization sequence. First, establish the API session, establish the DIS session, then establish a CLI connection with the target device. For this reason, netmri_easy.py, a pre-installed Python library, is provided in the appliance (see Configuration Management –> Job Management –> Library –> netmri_easy).
Practical Examples
Script 1 – Sending a basic command
Goal: Run a simple command via scripting. Understand and see the impact of DEBUG option.
This will show you the example of sending “show version” on a device. The second command is to show you that we can use the CCS DEBUG option which will not run “show version” on the device but show you that we would have if you remove the DEBUG.
# BEGIN-SCRIPT-BLOCK
#
# Script-Filter:
# true
#
# END-SCRIPT-BLOCK
from infoblox_netmri.easy import NetMRIEasy
# This values will be provided by NetMRI before execution
defaults = {
“api_url”: api_url,
“http_username”: http_username,
“http_password”: http_password,
“job_id”: job_id,
“device_id”: device_id,
“batch_id”: batch_id
}
# Create NetMRI context manager. It will close session after execution
with NetMRIEasy(**defaults) as easy:
easy.send_command(‘show version’)
easy.send_command(‘DEBUG:show version’)
Script 2 – Using Script Variables
Goal: Use Scripting to change the password on a device.
Just like using Script Variables in CCS and PERL we can do the same in Python, the only difference is that we can NOT use “Well Known Variables.”
This example script will first prompt for a new password ($new_password), and then NetMRI uses that variable to change the password on our target devices.
# BEGIN-SCRIPT-BLOCK
#
# Script-Filter: true
#
# Script-Variables:
# $new_password password “password”
#
# END-SCRIPT-BLOCK
from infoblox_netmri.easy import NetMRIEasy
# This values will be provided by NetMRI before execution
defaults = {
“api_url”: api_url,
“http_username”: http_username,
“http_password”: http_password,
“job_id”: job_id,
“device_id”: device_id,
“batch_id”: batch_id
}
# Create NetMRI context manager. It will close session after execution
with NetMRIEasy(**defaults) as easy:
easy.send_command(‘config t’)
easy.send_command(“username name secret 0 {}”.format(new_password))
easy.send_command(‘end’)
easy.send_command(‘wr mem’)
Script 3 – Generate a Custom Issue
Goal: Create a custom issue to drive additional responses from NetMRI, based on the script output.
This will run “show vtp status” on a switch, parse each line of the output looking for “VTP Operating Mode” where, if the devices we select are configured as Server, we will generate an issue.
# BEGIN-SCRIPT-BLOCK
#
# Script-Filter:
# true
#
# END-SCRIPT-BLOCK
import requests, json, re
from infoblox_netmri.easy import NetMRIEasy
# This values will be provided by NetMRI before execution
defaults = {
“api_url”: api_url,
“http_username”: http_username,
“http_password”: http_password,
“job_id”: job_id,
“device_id”: device_id,
“batch_id”: batch_id
}
# Create NetMRI context manager. It will close session after execution
with NetMRIEasy(**defaults) as easy:
vtpstatus = easy.send_command(‘show vtp status’)
regexp = re.compile(r”VTP Operating Mode\s*: (.*)”)
if regexp.search(vtpstatus):
#print (‘matched’)
status = re.search(‘(?<=VTP Operating Mode\s.)(.*)’, vtpstatus, re.MULTILINE).group()
if re.search(r’Server’, status):
issue_id = easy.generate_issue(“info”, “siftest”,**{
“Host”:device_devicename,
“IPAddress”:device_deviceipdotted,
“noclue1”:’test1′,
“noclue2”:’test2′,
“device_id”: device_id,
“batch_id”: batch_id
})
else:
print (‘no match’)
Script 4 – Adding data to Custom Fields
Goal: Parse needed information out of a show command, and then populate into a custom field.
Wrote this one for a customer because SNMP did not have the correct Serial number for Cisco ASAs, We will run “show inventory” and parse the output looking for the System Serial number and update our Custom field named “Sif Test2.”
# BEGIN-SCRIPT-BLOCK
#
# Script-Filter:
# $vendor eq “Cisco” and $type eq “Firewall”
#
# END-SCRIPT-BLOCK
from infoblox_netmri.easy import NetMRIEasy
import re
# This values will be provided by NetMRI before execution
defaults = {
“api_url”: api_url,
“http_username”: http_username,
“http_password”: http_password,
“job_id”: job_id,
“device_id”: device_id,
“batch_id”: batch_id
}
# Create NetMRI context manager. It will close the session after execution
with NetMRIEasy(**defaults) as easy:
# Everything has to be indented under the context manager if we are sending commands to NetMRI
#
# This is how you will create a custom field name, we are using “Sif Test2”
#
broker = easy.client.get_broker(‘CustomFields’)
broker.create_field(
model=’Device’,
name=’Sif Test2′,
type=’string’
)
# get device
device = easy.get_device()
#
# The method for retrieving the serial number via the
# CLI depends on the type of device.
#
# This portion of the code will run if the Device is a Router
# For the gather the serial number we are using RegEx – check out FB/ArtOfRegex
#
if device.DeviceType == ‘Router’:
inventory = easy.send_command(‘show inventory’)
serial = re.search(‘(?<=SN: ).*$’, inventory).group()
#
# This portion of the code will run if the Device is anything but a Router
# For the gather the serial number we are using RegEx – check out FB/ArtOfRegex
#
else:
info = easy.send_command(‘show version | inc System serial’)
serial = re.search(‘(?<=System serial number: ).*$’, info).group()
# Custom field “sif_test” update
# all custom fields should start with ‘custom_’
device_broker = easy.client.get_broker(‘Device’)
field_name = “custom_{}”.format(‘sif_test2’)
params = {
‘DeviceID’: device.DeviceID,
field_name: serial
}
result = device_broker.update(**params)
print(result)
Script 5 – Grab Networks from DDI
Goal: Automate the addition of a new network in DDI into the NetMRI scanners.
Automation does not have to be complex in order to be useful. In a use case where you want to automatically keep the NetMRI scanning system in sync with the Infoblox grid, this simple check can accomplish it with minimal hassle.
In order to enable this functionality, we will first create an Extensible Attribute (EA) associated with network objects in the NIOS IPAM system.
This script will grab data from NIOS where EA:NetMRI equal to “Add”, we will take the networks from NIOS and add it to NetMRI discovery then update the EA:NetMRI to “Done”
# BEGIN-SCRIPT-BLOCK
#
# Script-Filter:
# true
#
# Script-Variables:
# $gmuser string “Grid Master Username”
# $gmpassword password “Grid Master Password”
# $gmipaddress string “192.168.1.2”
#
# END-SCRIPT-BLOCK
import requests
import json, re
# This will not error when you are not verifying Certs for https
#
requests.packages.urllib3.disable_warnings()
#
# gmip is a variable we asked for the Grid Master IP/FQDN
gmip = “https://{}/wapi/”.format(gmipaddress)
#
# The version of WAPI you are using
wapi = “v2.5”
#
# The WPI call that we are going to use
call = “/network?*NetMRI%3A=Yes&_return_fields%2B=extattrs”
#
# Now we combine all the above to equal “url”
# https://192.168.1.2/wapi/v2.5/network?network=10.10.10.0/24
url = gmip + wapi + call
r = requests.get(url, auth=(gmuser, gmpassword), verify=False)
json_input = r.text
decoded = json.loads(json_input)
#print (decoded[‘network’])
for j in decoded:
print (j[‘network’], j[‘network_view’],j[‘_ref’])
url1 = “{}/api/3.2/discovery_settings/create?range_value=”.format(api_url)
url2 = j[‘network’]
url3 = “&range_type=CIDR&discovery_status=INCLUDE”
url4 = url1 + url2 + url3
add_net = requests.get(url4, auth=(gmuser, gmpassword), verify=False)
print (“Added”)
call2 = j[‘_ref’]
url_update = gmip + wapi + “/” + call2
payload = “{\n\t\”extattrs\”: {\n\t\t\”NetMRI\”: {\n\t\t\t\”value\”: \”Done\”\n\t\t}\n\t}\n}”
response = requests.request(“PUT”, url_update,auth=(gmuser, gmpassword), data=payload, verify=False)
print(“Updated NIOS EA”)
Conclusion
NetMRI gives you a framework to focus your automation tasks around. By providing a common interface to numerous APIs and CLIs, you are already embracing the paradigm shift towards automate/virtualize/cloud/software defined everything that has become the latest solution to deal with scaling up into large network infrastructures.