def getarpentry(ip=None, vrf='all'): # Check the output of the ARP table for the IP address in question if ip: arpoutput = json.loads(clid('show ip arp {0} vrf {1}'.format(ip, vrf))) else: arpoutput = json.loads(clid('show ip arp vrf {0}'.format(vrf))) rowadjlist = findkey(arpoutput, 'ROW_adj') if not rowadjlist: return None # flatten out the data received from show ip arp into a list of dicts arpentries = [] for rowadj in rowadjlist: if isinstance(rowadj, dict): arpentries.append(rowadj) elif isinstance(rowadj, list): arpentries.extend(rowadj) arplist = [] for arp in arpentries: try: arplist.append( [arp['ip-addr-out'], arp['time-stamp'], arp['mac'], arp['intf-out']]) except KeyError: continue return arplist
def main(): """Main method to configure VLANs on interfaces.""" interface_data = {} interfaces = [(interface['interface'], interface['state'], interface['portmode']) for interface in json.loads(cli.clid("show interface brief")) ['TABLE_interface']['ROW_interface'] if 'Eth' in interface['interface']] vlans = [(vlan['vlanshowbr-vlanid-utf'], vlan['vlanshowplist-ifidx']) for vlan in json.loads(cli.clid("show vlan"))['TABLE_vlanbrief'] ['ROW_vlanbrief'] if 'vlanshowplist-ifidx' in vlan.keys()] macs = [(mac['disp_mac_addr'], mac['disp_port']) for mac in json.loads(cli.clid("show mac address-table")) ['TABLE_mac_address']['ROW_mac_address'] if 'Eth' in mac['disp_port']] for interface in interfaces: int_info = [interface[1], interface[2]] interface_data[interface[0]] = {'int_info': int_info} vlan_ids = [vlan[0] for vlan in vlans if interface[0] in vlan[1]] interface_data[interface[0]].update({'vlan_ids': vlan_ids}) mac_addrs = [mac[0] for mac in macs if interface[0] in mac[1]] interface_data[interface[0]].update({'mac_addresses': mac_addrs}) pprint.pprint(interface_data)
def getarpentry(ip=None, vrf='all'): # Check the output of the ARP table for the IP address in question if ip: arpoutput = json.loads(clid('show ip arp {0} vrf {1}'.format(ip, vrf))) else: arpoutput = json.loads(clid('show ip arp vrf {0}'.format(vrf))) rowadjlist = findkey(arpoutput, 'ROW_adj') if not rowadjlist: return None # flatten out the data received from show ip arp into a list of dicts arpentries = [] # print "TITU : ", arpoutput for rowadj in rowadjlist: if isinstance(rowadj, dict): arpentries.append(rowadj) elif isinstance(rowadj, list): arpentries.extend(rowadj) arplist = [] for arp in arpentries: try: # print "TITU Int : ", arp['intf-out'] arplist.append([ arp['ip-addr-out'], arp['time-stamp'], arp['mac'], arp['intf-out'] ]) except KeyError: continue return arplist
def main(): import json # Python module names vary depending on nxos version try: from cli import clid except: from cisco import clid data = {} try: all = json.loads(clid('show snmp')) data['snmp'] = all except: pass try: community = json.loads(clid('show snmp community')) data['community'] = community except: pass try: host = json.loads(clid('show snmp host')) data['host'] = host except: pass try: group = json.loads(clid('show snmp group')) data['group'] = group except: pass return data
def cdpneigh(): u"""Getting CDP neighbours information """ cmd = 'show cdp neighbor' cdp_dict = {} cdp = json.loads(cli.clid(cmd))['TABLE_cdp_neighbor_brief_info']['ROW_cdp_neighbor_brief_info'] patern = re.compile('xen|kvm|esx|ubuntu|vmware', re.IGNORECASE) for row in cdp: if (re.search(patern, str(row)) != None): int_id = row['intf_id'] if int_id not in cdp_dict: cdp_dict[int_id] = {} cdp_dict[int_id]['intf_id'] = int_id cdp_dict[int_id]['platform_id'] = row['platform_id'] cdp_dict[int_id]['port_id'] = row['port_id'] try: for key, value in cdp_dict.items(): if 'port_id' in value and 'device_id' in value and 'intf_id' in value: continue except AttributeError: print ('There are not such attributes') finally: for key, value in cdp_dict.items(): neighbour = cli.cli('show cdp neighbors interface ' + value['intf_id'] + ' detail') ip = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})', neighbour)[0] ipadd = str(ip) print ('{0:15} \t\t {1:10} {2:25} {3:10} {4:15}'.format (value['platform_id'].ljust(15), value['port_id'].ljust(29) , str(ip).ljust(34), 'CDP'.ljust(27), value['intf_id']))
def cdpneigh(): u"""Getting CDP neighbours information """ cmd = 'show cdp neighbor' cdp_dict = {} cdp = json.loads(cli.clid( cmd))['TABLE_cdp_neighbor_brief_info']['ROW_cdp_neighbor_brief_info'] patern = re.compile('xen|kvm|esx|ubuntu|vmware', re.IGNORECASE) for row in cdp: if (re.search(patern, str(row)) != None): int_id = row['intf_id'] if int_id not in cdp_dict: cdp_dict[int_id] = {} cdp_dict[int_id]['intf_id'] = int_id cdp_dict[int_id]['platform_id'] = row['platform_id'] cdp_dict[int_id]['port_id'] = row['port_id'] try: for key, value in cdp_dict.items(): if 'port_id' in value and 'device_id' in value and 'intf_id' in value: continue except AttributeError: print('There are not such attributes') finally: for key, value in cdp_dict.items(): neighbour = cli.cli('show cdp neighbors interface ' + value['intf_id'] + ' detail') ip = re.findall( r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})', neighbour)[0] ipadd = str(ip) print('{0:15} \t\t {1:10} {2:25} {3:10} {4:15}'.format( value['platform_id'].ljust(15), value['port_id'].ljust(29), str(ip).ljust(34), 'CDP'.ljust(27), value['intf_id']))
def check_cpu(): # below example using cli method # o = cli('show proc cpu | in "CPU util"').split(',')[2].strip().split(' ')[0].strip('%') # below example much better using clid method o = json.loads(clid('show proc cpu'))['idle_percent'].encode('UTF-8') return float(o)
def getcdpentry(port): # Next use the interface we found the device on from CAM and look it up in # CDP cdp = json.loads(clid('show cdp neighbor interface {0}'.format(port))) cdp = findkey(cdp, 'ROW_cdp_neighbor_brief_info') if not cdp: raise Exception('Unable to find {0} in CDP output'.format(port)) if len(cdp) > 0: cdp = cdp[0] return cdp
def getmacentry(mac, vlanfilter=None): try: macaddroutput = json.loads( clid('show mac address-table address {0}'.format(mac))) except UnstructuredOutput: return None macaddrlist = findkey(macaddroutput, 'ROW_mac_address') if not macaddrlist: return None macentries = [] for macaddr in macaddrlist: if isinstance(macaddr, dict): macentries.append(macaddr) elif isinstance(macaddr, list): macentries.extend(macaddr) entries = [] # print "TITU:mac, ", mac # print "TITU: ", macaddroutput # print "TITU", macentries for macaddr in macentries: vlan = macaddr['disp_vlan'] mac = macaddr['disp_mac_addr'] entrytype = macaddr['disp_type'] age = macaddr['disp_age'] secure = macaddr['disp_is_secure'] ntfy = macaddr['disp_is_ntfy'] port = macaddr['disp_port'] # print "TITU", port if vlanfilter and vlan != vlanfilter: continue # If a MAC is on a port channel, dereference it and use the first entry if 'po' in port.lower(): members = getportchannelmembers(port) if not members: raise Exception( 'Unable to find any member interfaces in {0}'.format(port)) entries.extend( [[vlan, mac, entrytype, age, secure, ntfy, memberport, port] for memberport in members]) elif 'vlan' in port.lower(): continue else: entries.append( [vlan, mac, entrytype, age, secure, ntfy, port, port]) return entries
def get_user_desc( intf): txt = cli.clid('show interface %s desc' %intf) try: if type(txt) == str: d = json.loads(txt) desc = d['TABLE_interface']['ROW_interface']['desc'] else: desc = txt['TABLE_interface']['ROW_interface']['desc'] if desc != None and len(desc) > 1: msg = desc.split(':') return msg[0].strip() if len(msg) > 1 else '' except: pass return ''
def main(): import json # Python module names vary depending on nxos version try: from cli import clid except: from cisco import clid data = {} try: data = json.loads(clid('show version')) except: pass return data
def connports(): u"""Gathering information about connected ports""" cmd = 'show interface brief' out = json.loads(cli.clid(cmd)) i = 0 connectedports = [] while i < len(out['TABLE_interface']['ROW_interface']): interf = out['TABLE_interface']['ROW_interface'][i] i = i + 1 if interf['state'] == 'up': connectedports.append(interf['interface']) return connectedports
def deviceinfo(): u"""Getting information about current device""" info = json.loads(cli.clid('show version')) print(color.CYAN + '\nSwitch information:\n' + color.ENDCOLOR) try: if 'kickstart_ver_str' in info.keys() and 'host_name' in info.keys( ) and 'kern_uptm_mins' in info.keys(): print('NXOS version: '.upper() + info.get('kickstart_ver_str')) print('Device name: '.upper() + info.get('host_name') + '\n\t') else: print('General device info: ') for k in info.keys(): print "%30s = %s" % (k, out[k]) except AttributeError: print('No such attribute...')
def deviceinfo(): u"""Getting information about current device""" info=json.loads(cli.clid('show version')) print (color.CYAN + '\nSwitch information:\n' + color.ENDCOLOR) try: if 'kickstart_ver_str' in info.keys() and 'host_name' in info.keys() and 'kern_uptm_mins' in info.keys(): print ('NXOS version: '.upper() + info.get('kickstart_ver_str') ) print ('Device name: '.upper() + info.get('host_name') + '\n\t') else: print ('General device info: ') for k in info.keys(): print "%30s = %s" % (k, out[k]) except AttributeError: print ('No such attribute...')
def connports(): u"""Gathering information about connected ports""" cmd = 'show interface brief' out = json.loads(cli.clid(cmd)) i=0 connectedports = [] while i < len(out['TABLE_interface']['ROW_interface']): interf=out['TABLE_interface']['ROW_interface'][i] i=i+1 if interf['state'] == 'up': connectedports.append(interf['interface']) return connectedports
def main(): import json # Python module names vary depending on nxos version try: from cli import clid except: from cisco import clid data = {} try: # get the version in json form in a temporary string so we can manipulate it dataString = clid('show version') # The "as is" in the license header string from 'show version' # will cause json.dumps within taskrunner.py to produce an invalid json string # This is resolved by replacing the additional escapes (\) with a raw string dataString = dataString.replace("\\\"as is,\\\"", "as is") data = json.loads(dataString) except: pass return data
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # # This script will gather details from the CDP database and generate # interface descriptions based on the neighbor name and remote interface # and then print out the configuration needed to apply these descriptions. # import cli import json cdp_dict = {} cdp = json.loads( cli.clid('show cdp neighbor' ))['TABLE_cdp_neighbor_brief_info']['ROW_cdp_neighbor_brief_info'] for entry in cdp: intf_id = entry['intf_id'] if intf_id not in cdp_dict: cdp_dict[intf_id] = {} cdp_dict[intf_id]['intf_id'] = intf_id cdp_dict[intf_id]['device_id'] = entry['device_id'] cdp_dict[intf_id]['port_id'] = entry['port_id'] for key, value in cdp_dict.items(): if 'port_id' in value and 'device_id' in value and 'intf_id' in value: cli.cli('conf t ; interface ' + value['intf_id'] + ' ; description ' + value['device_id'] + ' ' + value['port_id'])
#!/usr/bin/env python## Copyright (C) 2014 Cisco Systems Inc.## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.## This script demonstrates how you can write a single script that runs on both# on box and off box, using the same APIs on Nexus 9000.## The workflow will gather details from the CDP database and generate# interface descriptions based on the neighbor name and remote interface# and then print out the configuration needed to apply these descriptions.# This version executes via the NX-API, and will simply print out the# generated configuration output, as opposed to applying it# # Define your list of switches here, with their IP addresses and credentialsswitches = [ ['172.31.216.131', 'admin', 'cisco123'], ['172.31.216.131', 'admin', 'cisco123']] import sysimport pprintimport jsonsys.path.append("./cisco")sys.path.append("./utils") onbox = Falsetry: from cli import clid, cliexcept ImportError: try: from nxapi_utils import NXAPITransport from cisco.interface import Interface onbox = False except ImportError: print 'Script is unsupported on this platform' raise from nxapi_utils import NXAPITransportfrom cisco.interface import Interfacedef findkey(dct, key, value=None): """This method recursively searches through a JSON dict for a key name and returns a list of the matching results """ found = [] if isinstance(dct, list): for item in dct: f = findkey(item, key, value) if f: found.extend(f) if isinstance(dct, dict): for k, v in dct.items(): if isinstance(v, list) or isinstance(v, dict): f = findkey(v, key, value) if f: found.extend(f) if str(k) == str(key): if (value and str(v) == str(value)) or not value: found.append(v) return found if len(found) > 0 else None for switch in switches: cdp_dict = {} if not onbox: target_url = "http://%s/ins" % switch[0] username = switch[1] password = switch[2] NXAPITransport.init( target_url=target_url, username=username, password=password) def smartcli(*args): """This wrapper function provides a less intrusive way to call the appropriate msg_type for configuration based commands """ cmd = args[0] if cmd[:4] == 'conf': NXAPITransport.send_cmd(cmd, msg_type='cli_conf') else: NXAPITransport.cli(cmd) cli = smartcli clid = NXAPITransport.clid cdp_dict = {} cdp = json.loads(clid('show cdp neighbor')) cdp = findkey(cdp, 'ROW_cdp_neighbor_brief_info')[0] for entry in cdp: intf_id = entry['intf_id'] if intf_id not in cdp_dict: cdp_dict[intf_id] = { 'intf_id': intf_id, 'device_id': entry['device_id'], 'port_id': entry['port_id'] } for key, value in cdp_dict.items(): if 'port_id' in value and 'device_id' in value and 'intf_id' in value: fields = { 'interface': value['intf_id'].strip().encode('UTF-8'), 'device_id': value['device_id'].strip().encode('UTF-8'), 'port_id': value['port_id'].strip().encode('UTF-8') } cmd = 'conf t ; interface {interface} ; description {device_id} {port_id}'.format( **fields) print(cmd) cli(cmd)
# collect a other command outputs in that case # import cli import json import re from argparse import ArgumentParser # Perform some basic argument parsing for parameters passed to the script parser = ArgumentParser('Supercommand') parser.add_argument('ip') args = parser.parse_args() ip = args.ip # Check the output of the ARP table for the IP address in question arp = json.loads(cli.clid('show ip arp %s vrf all' % ip))['TABLE_vrf']['ROW_vrf']['TABLE_adj']['ROW_adj'] if len(arp) == 0: raise Exception('Unable to find %s in ARP output' % ip) # Take the resulting output and collect the fields we want ip, timer, mac, interface = arp['ip-addr-out'], arp['time-stamp'], arp['mac'], arp['intf-out'] # Now use the MAC address we extracted for the IP and look it up in the CAM table for cam in cli.cli('show mac address-table address %s' % (mac)).split('\n'): if mac in cam: break else: raise Exception('Unable to find %s in CAM output' % mac) cam_fields = cam.split() if cam_fields[0] in ['*', 'G', 'R', '+']: cam_fields.pop(0)
import sys if __name__ == "__main__": parser = argparse.ArgumentParser(description='run show interfaces and check tresholds in output') parser.add_argument('-c', action='store', dest='config', help='Path to config with tresholds', metavar="config", required=True) args = parser.parse_args() with open(args.config, 'r') as content_file: content = content_file.readlines() params = {} for line in content: (param, threshold) = line.split(":") params[param] = threshold interfaces = json.loads(cli.clid("show interface")) ifaces_data = [] for iface in interfaces["TABLE_interface"]["ROW_interface"]: data = {} thresh_reached = False for p in params: threshold = params[p] if p == "input rate" or p == "output rate": key = "vdc_lvl_in_avg_bits" if p == "input rate" else "vdc_lvl_out_avg_bits" value = iface.get(key) if not value: key = "eth_inrate1_bits" if p =="input rate" else "eth_outrate1_bits" value = iface.get(key) if value: if long(value) >= long(threshold): thresh_reached = True
import cli if __name__ == '__main__': tryy = cli.clid('show vlan') print tryy
def getportchannelmembers(port): po = json.loads(clid('show port-channel summary int {0}'.format(port))) members = findkey(po, 'port') return members
def smartcli(*args): """This wrapper function provides a less intrusive way to call the appropriate msg_type for configuration based commands """ cmd = args[0] if cmd[:4] == 'conf': NXAPITransport.send_cmd(cmd, msg_type='cli_conf') else: NXAPITransport.cli(cmd) cli = smartcli clid = NXAPITransport.clid cdp_dict = {} cdp = json.loads(clid('show cdp neighbor')) cdp = findkey(cdp, 'ROW_cdp_neighbor_brief_info')[0] for entry in cdp: intf_id = entry['intf_id'] if intf_id not in cdp_dict: cdp_dict[intf_id] = { 'intf_id': intf_id, 'device_id': entry['device_id'], 'port_id': entry['port_id'] } for key, value in cdp_dict.items(): if 'port_id' in value and 'device_id' in value and 'intf_id' in value: fields = { 'interface': value['intf_id'].strip().encode('UTF-8'), 'device_id': value['device_id'].strip().encode('UTF-8'),
else: devices = [ neighbors['TABLE_cdp_neighbor_brief_info']['ROW_cdp_neighbor_brief_info'] ] for device in devices: desc = get_user_desc(device['intf_id']) + " : to %(port_id)s of %(device_id)s" %device r = cli.cli('conf t ; interface %s ; desc %s' %(device['intf_id'], desc)) print r def update_desc_with_cdp_neighbors_nexus72( neighbors): mydevices = {} for item in neighbors.keys(): keys = item.split('/') if keys[1] in ['intf_id', 'port_id', 'device_id'] : if not mydevices.has_key( keys[2]): dev = {} dev[ keys[1]] = neighbors[item] mydevices[ keys[2]] = dev for idx in mydevices.keys(): desc = "to %(port_id)s of %(device_id)s" %mydevices[idx] r = cli.cli('conf t ; interface %s ; desc %s' %(mydevices[idx]['intf_id'], desc)) print r if __name__ == '__main__': txt = cli.clid('show cdp nei') print txt if type(txt) == str: update_desc_with_cdp_neighbors(json.loads(txt)) else: update_desc_with_cdp_neighbors_nexus72 (txt)
def getportchannelmembers(port): po = json.loads( clid('show port-channel summary int {0}'.format(port))) members = findkey(po, 'port') return members
def data(self, **kwargs): s = kwargs['s'] ip = s.client_address[0] r = json.loads(cli.clid('show ip route %s vrf management' % ip)) return self.printroute(r)
import syslog from cli import clid import json data = json.loads(clid("show ip route")) route = [ x["ipprefix"] for x in data['TABLE_vrf']['ROW_vrf']['TABLE_addrf'] ['ROW_addrf']['TABLE_prefix']['ROW_prefix'] ] if " ".join(route) == "1.1.1.1/32 2.2.2.2/32 3.3.3.3/32": syslog.syslog(3, "We got 3 routes , mission completed!!!")
import argparse import sys import time import re import smtplib if __name__ == "__main__": parser = argparse.ArgumentParser(description='Check icmp-echo from IP SLA') parser.add_argument("--email", help="Send alert to this email", action="store", required=True) parser.add_argument("--smtp_server", help="SMTP server for email", action="store", default="192.168.1.2") parser.add_argument('--threshold', action='store', type=int, help='Number of failed attempts before shutdown the interface', default=100) parser.add_argument("--verbosity", help="Increase output verbosity", action="store_true") parser.add_argument("--dest_ip", help="IP-adders to ping", action="store", required=True) args = parser.parse_args() res = json.loads( cli.clid("show ip sla configuration") ) maxindex = 0 for r in res["TABLE_oper"]: row = r["ROW_oper"] if "index" in row: indx = int(row["index"]) if indx > maxindex: maxindex = indx # if row["oper-type"] == "icmp-echo" and row["dest-ip"] == args.dest_ip: # print "ip sla operaion already exists" # sys.exit(1) maxindex += 1 cli.cli("configure terminal ; feature sla sender ; ip sla %d ; icmp-echo %s ; threshold 1 ; timeout 1 ; frequency 1 ; end" % (maxindex, args.dest_ip) ) cli.cli("configure terminal ; ip sla schedule %d life forever start-time now" % maxindex ) try: time.sleep(args.threshold)
# collect a other command outputs in that case # import cli import json import re from argparse import ArgumentParser # Perform some basic argument parsing for parameters passed to the script parser = ArgumentParser('Supercommand') parser.add_argument('ip') args = parser.parse_args() ip = args.ip # Check the output of the ARP table for the IP address in question arp = json.loads(cli.clid('show ip arp %s vrf all' % ip))['TABLE_vrf']['ROW_vrf']['TABLE_adj']['ROW_adj'] if len(arp) == 0: raise Exception('Unable to find %s in ARP output' % ip) # Take the resulting output and collect the fields we want ip, timer, mac, interface = arp['ip-addr-out'], arp['time-stamp'], arp[ 'mac'], arp['intf-out'] # Now use the MAC address we extracted for the IP and look it up in the CAM table for cam in cli.cli('show mac address-table address %s' % (mac)).split('\n'): if mac in cam: break else: raise Exception('Unable to find %s in CAM output' % mac) cam_fields = cam.split() if cam_fields[0] in ['*', 'G', 'R', '+']: cam_fields.pop(0)
Author: Alex Feng email: [email protected] scheduler job name check_rt python bootflash:/check_routes.py end-job scheduler schedule name check_rt_sch job name check_rt time start 2019:11:29:11:27 repeat 0:0:1 ''' import syslog import json import cli expected_routes = ["1.1.1.1/32","2.2.2.2/32","3.3.3.3/32"] route_table = cli.clid('sh ip route') route_table_json = json.loads(route_table) count = 0 for prefix in route_table_json['TABLE_vrf']['ROW_vrf']['TABLE_addrf']['ROW_addrf']['TABLE_prefix']['ROW_prefix']: if prefix['ipprefix'] in expected_routes: count +=1 if count == 3: syslog.syslog(1,'We got 3 routes , mission completed!')
else: return dirname if __name__ == "__main__": parser = argparse.ArgumentParser(description='Check the nexus for overall health') parser.add_argument('--cpu_hogs_limit', action='store', type=int, help='How many CPU hogs save to log', default=5) parser.add_argument('--mem_hogs_limit', action='store', type=int, help='How many memory hogs save to log', default=5) parser.add_argument('--cpu_threshold', action='store', type=int, help='CPU hog\'s threshold, %', default=50) parser.add_argument('--mem_threshold', action='store', type=int, help='Memory hog\'s threshold, %', default=70) parser.add_argument("--logdir", help="Where logs store", action="store", required=True, type=is_dir) parser.add_argument("--threshold_script", help="Where threshold_monitor_nexus.py script located", action="store", default = "./threshold_monitor_nexus.py", required=True) parser.add_argument("--threshold_script_conf", help="Where config located", default = "./config.txt", action="store" ) args = parser.parse_args() sys_res = json.loads(cli.clid("show system resources")) user_cpu = sys_res["cpu_state_user"] kernel_cpu = sys_res["cpu_state_kernel"] cpu_load = float(user_cpu) + float(kernel_cpu) cpu_hogs = [] if cpu_load > args.cpu_threshold: proc_cpu = json.loads(cli.clid("show processes cpu sort")) rows = proc_cpu["TABLE_process_cpu"]["ROW_process_cpu"] i = 0 while i < len(rows): cpu_hogs.append( rows[i]["process"] ) i += 1 if i > args.cpu_hogs_limit: break
## This entire block of code is aimed at detecting of we have access to cli and# the clid command. If we do not have them, we attempt to import cli from the# cisco package (which is present on other NXOS platforms). If that fails, we# cannot proceed further. However, if it does succeed, then we need to create# an equivalent of clid(), so we introduce an external dependency on xmltodict# which is used to convert the XML output of the commands into a JSON dict.## Finally, after that we check to see if cli() returns a tuple, if so that means# we are on a 5K or similar, and we need to patch the output to return it as# just the command output, and not the two-tuple class UnstructuredOutput(Exception): pass try: from cli import clid, cliexcept ImportError: try: from cisco import cli except ImportError: print 'Script is unsupported on this platform' raise def clid(cmd): try: import xmltodict except ImportError: print 'Script is unsupported on this platform: requires xmltodict' raise tag = '__readonly__' starttag, endtag = '<' + tag + '>', '</' + tag + '>' output = cli('{0} | xml'.format(cmd)) start_index, end_index = output.find(starttag), output.find(endtag) if start_index == -1 or end_index == -1: raise UnstructuredOutput( 'Command {0} does not support structured output: {1}'.format( cmd, output)) output = xmltodict.parse( output[start_index:end_index + len(endtag)]) json_output = json.dumps(output[tag]) return json_output def cli_decorator(target_function): def wrapper(cmd): return target_function(cmd)[1] return wrapper if isinstance(cli('show version'), tuple): cli = cli_decorator(cli) def findkey(dct, key, value=None): found = [] if isinstance(dct, list): for item in dct: f = findkey(item, key, value) if f: found.extend(f) if isinstance(dct, dict): for k, v in dct.items(): if isinstance(v, list) or isinstance(v, dict): f = findkey(v, key, value) if f: found.extend(f) if str(k) == str(key): if (value and str(v) == str(value)) or not value: found.append(v) return found if len(found) > 0 else None def getarpentry(ip=None, vrf='all'): # Check the output of the ARP table for the IP address in question if ip: arpoutput = json.loads(clid('show ip arp {0} vrf {1}'.format(ip, vrf))) else: arpoutput = json.loads(clid('show ip arp vrf {0}'.format(vrf))) rowadjlist = findkey(arpoutput, 'ROW_adj') if not rowadjlist: return None # flatten out the data received from show ip arp into a list of dicts arpentries = [] # print "TITU : ", arpoutput for rowadj in rowadjlist: if isinstance(rowadj, dict): arpentries.append(rowadj) elif isinstance(rowadj, list): arpentries.extend(rowadj) arplist = [] for arp in arpentries: try: # print "TITU Int : ", arp['intf-out'] arplist.append( [arp['ip-addr-out'], arp['time-stamp'], arp['mac'], arp['intf-out']]) except KeyError: continue return arplist def getmacentry(mac, vlanfilter=None): try: macaddroutput = json.loads( clid('show mac address-table address {0}'.format(mac))) except UnstructuredOutput: return None macaddrlist = findkey(macaddroutput, 'ROW_mac_address') if not macaddrlist: return None macentries = [] for macaddr in macaddrlist: if isinstance(macaddr, dict): macentries.append(macaddr) elif isinstance(macaddr, list): macentries.extend(macaddr) entries = [] # print "TITU:mac, ", mac # print "TITU: ", macaddroutput # print "TITU", macentries for macaddr in macentries: vlan = macaddr['disp_vlan'] mac = macaddr['disp_mac_addr'] entrytype = macaddr['disp_type'] age = macaddr['disp_age'] secure = macaddr['disp_is_secure'] ntfy = macaddr['disp_is_ntfy'] port = macaddr['disp_port'] # print "TITU", port if vlanfilter and vlan != vlanfilter: continue # If a MAC is on a port channel, dereference it and use the first entry if 'po' in port.lower(): members = getportchannelmembers(port) if not members: raise Exception( 'Unable to find any member interfaces in {0}'.format(port)) entries.extend( [[vlan, mac, entrytype, age, secure, ntfy, memberport, port] for memberport in members]) elif 'vlan' in port.lower(): continue else: entries.append( [vlan, mac, entrytype, age, secure, ntfy, port, port]) return entries def getportchannelmembers(port): po = json.loads( clid('show port-channel summary int {0}'.format(port))) members = findkey(po, 'port') return members def getcdpentry(port): # Next use the interface we found the device on from CAM and look it up in # CDP cdp = json.loads(clid('show cdp neighbor interface {0}'.format(port))) cdp = findkey(cdp, 'ROW_cdp_neighbor_brief_info') if not cdp: raise Exception('Unable to find {0} in CDP output'.format(port)) if len(cdp) > 0: cdp = cdp[0] return cdp def main(): # Perform some basic argument parsing for parameters passed to the script parser = ArgumentParser('Supercommand') parser.add_argument( 'ip', help='IP address to query. Use all for every IP in arp') args = parser.parse_args() ip = args.ip output = []