Skip to content

Instantly share code, notes, and snippets.

@jeremyschulman
Last active November 6, 2020 16:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jeremyschulman/6728381 to your computer and use it in GitHub Desktop.
Save jeremyschulman/6728381 to your computer and use it in GitHub Desktop.
Python script to admin up/down a Junos interface using the SNMP ifTable index value. Requires the "ncclient" module found at www.github.com/Juniper/ncclient
# Copyright (c) 1999-2011, Juniper Networks Inc.
# All rights reserved.
# Author: Jeremy Schulman
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of the Juniper Networks nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import sys
from ncclient import manager as NC
from lxml import etree
### ---------------------------------------------------------------------------
### unix invocation:
### $ python change_interface_admin.py <hostname> <port_iftbl_idx> [up|down]
###
### example:
### $ python admin_ifd_byidx.py 192.168.10.21 507 down
### ---------------------------------------------------------------------------
CONNECT_TIMEOUT = 5 # 5 seconds to reach device, then error
CONNECT_USERNAME = 'root' # ! you should change this
CONNECT_PASSWORD = 'juniper1' # ! you should change this
# The following are exit() codes to indicate failure reason to the
# calling program
ERROR_DEVUNREACHABLE = 1 # unable to connect to device
ERROR_INVALIDPORT = 2 # invalid snmp index
ERROR_ONCHANGE = 3 # when commiting change
# extract program arguments from the command link invocation
# nothing fancy here ...
arg_host = sys.argv[1]
arg_snmp_ifidx = sys.argv[2]
arg_admin_state = False if sys.argv[3] == 'down' else True
# login structure that will be later used to connect
# to the Junos device.
g_login = {
'host': arg_host,
'username': CONNECT_USERNAME,
'password': CONNECT_PASSWORD,
'timeout': CONNECT_TIMEOUT,
}
### -----------------------------------------------------------------
### build_rpc_cmd - helper function to create XML API command
### -----------------------------------------------------------------
def build_rpc_cmd( rpc_cmd, rpc_args ):
"""
rpc_cmd - str: command
rpc_args - dict: key/value rpc arguments
"""
rpc = etree.Element( rpc_cmd )
if rpc_args:
for name, value in rpc_args.items():
arg = etree.SubElement( rpc, name )
if value != True: arg.text = value
return rpc
### -----------------------------------------------------------------
### build_rpc_cmd - helper function to create XML API command
### -----------------------------------------------------------------
def ifd_by_snmpidx( ncdev, ifidx ):
cmd = build_rpc_cmd('get-snmp-object', {
'snmp-object-name': 'ifDescr.'+str(ifidx)
})
try:
rsp = ncdev.rpc( cmd )
ifd = rsp.xpath('.//object-value')[0].text.strip()
except:
sys.exit( ERROR_INVALIDPORT )
return ifd
### -----------------------------------------------------------------
### set_port_admin - change the port admin state
### -----------------------------------------------------------------
def set_port_admin( ncdev, port_name, admin_state=arg_admin_state ):
"""
Change the admin state of a port.
ncdev - netconf device object
port_name - str: name of the interface
admin_state - True (enable), False (disable)
Notes:
(1) change is exclusive
(2) exceptions are bubbled up
"""
try:
ncdev.lock()
# disabling a port means setting 'disable' on the port
set_config = "{cmd} interfaces {name} disable".format(
name=port_name,
cmd=('set' if not admin_state else 'delete'))
rsp = ncdev.load_configuration(action='set', config=set_config)
ncdev.commit()
ncdev.unlock()
except:
sys.exit( ERROR_ONCHANGE )
return admin_state
### -----------------------------------------------------------------
### get_port_status - used to retrieve basic port information
### -----------------------------------------------------------------
def get_port_status( ncdev, port_name ):
"""
get basic port information, returns a dict of information
or False if the provided interface name (ifd_name) does
not exist on the device
ncdev - netconf device object
port_name - str: the name of the interface, e.g. 'ge-0/0/0'
"""
cmd = build_rpc_cmd('get-interface-information', {
'interface-name': port_name,
'media': True
})
try:
rpc = ncdev.rpc( cmd )
ifd_xml = rpc.xpath('//physical-interface')[0]
except IndexError:
sys.exit( ERROR_INVALIDPORT )
xpath_item = lambda xpath: ifd_xml.xpath(xpath)[0].text.strip()
status = {}
status['name'] = port_name
status['status'] = xpath_item('oper-status')
status['admin'] = xpath_item('admin-status')
status['speed'] = xpath_item('speed')
status['duplex'] = xpath_item('duplex')
status['mtu'] = xpath_item('mtu')
return status
if __name__ == "__main__":
# do not require ssh hostkey checking
g_login['hostkey_verify'] = False
# try to login to the device. If it fails
# for any reason, exit the program with the
# given exit code
try:
ncdev = NC.connect( **g_login )
except:
sys.exit( ERROR_DEVUNREACHABLE )
ifd_name = ifd_by_snmpidx( ncdev, arg_snmp_ifidx )
set_port_admin( ncdev, ifd_name )
ncdev.close_session()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment