import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning from getpass import getpass from lxml import etree from nxapi_plumbing import Device # import device class # Disable SSL cert warning we get as we're using self-signed cert requests.packages.urllib3.disable_warnings(InsecureRequestWarning) # Create device object device = Device( api_format="xml", host="nxos1.lasthop.io", username="******", password=getpass(), transport="https", port=8443, verify=False, # Turn off SSL cert verification ) # Config commands to send to the device cmds = [ 'interface loopback 100', 'description nxapi test lo', 'interface loopback 101', 'description nxapi test lo2' ] # Send config commands list to the device output = device.config_list(cmds) # Loop through returned list of command output and print to the screen for entry in output: print(etree.tostring(entry).decode()) input('Press Enter to continue: ')
intf_output.find(".//eth_mtu").text, ) ) # Exercise 7b print("\n\n") print("Capture and print XML output from multiple show commands") print("-" * 20) show_output = device.show_list(["show system uptime", "show system resources"]) for output in show_output: print(etree.tostring(output, encoding="unicode")) print("-" * 20) print("\n\n") # Exercise 7c print() print("Create two new loopbacks with descriptions") print("-" * 20) commands = [ "interface loopback101", "description loopback101", "no shutdown", "interface loopback102", "description loopback102", "no shutdown", ] output = device.config_list(commands) # Look at the output XML for each configuration command for msg in output: print(etree.tostring(msg, encoding="unicode"))
device = Device( api_format="xml", host="nxos1.lasthop.io", username="******", password=getpass(), transport="https", port=8443, verify=False, ) cmds = ["show hostname", "show version", "show lldp neighbors"] output = device.show_list(cmds) for entry in output: print(etree.tostring(entry).decode()) input("Hit enter to continue: ") cmds = ["show version"] output = device.show_list(cmds, raw_text=True) print(etree.tostring(output[0]).decode()) cfg_cmd = ["logging history size 200"] output = device.config_list(cfg_cmd) print(etree.tostring(output[0]).decode()) output = device.save() print(output) # output = device.checkpoint(filename="my_checkpoint2") # print(output)
if __name__ == "__main__": output = device.show("show interface Ethernet2/1") # Task a print("-" * 20) print("Interface Report : ") print("Interface : {0}, State : {1}, MTU : {2}".format( output.find(".//interface").text, output.find(".//admin_state").text, output.find(".//eth_mtu").text)) # Task b list_cmds = ["show system uptime", "show system resources"] output = device.show_list(list_cmds) print("") print("-" * 20) print("System Report :") for element in output: bstring = etree.tostring(element) print(bstring.decode()) # Task c list_cmds = [ "interface loopback151", "description dev01", "ip address 10.111.222.254/32" ] output = device.config_list(list_cmds) bstring = etree.tostring(element) print(bstring.decode())
host="nxos1.lasthop.io", username="******", password=getpass(), transport="https", port=8443, verify=False) output = nxos1.show("show interface Ethernet1/1") # Exercise 7a print("Interface: {}; State: {}; MTU: {}".format( output.find(".//interface").text, output.find(".//state").text, output.find(".//eth_mtu").text, )) # Exercise 7b cmds = ["show system uptime", "show system resources"] output = nxos1.show_list(cmds) for entry in output: print(etree.tostring(entry).decode()) # Exercise 7c cfg_cmds = [ "interface Loopback120", "description My loopback", "interface Loopback121", "description My loopback again" ] output = nxos1.config_list(cfg_cmds)
interface_show.find(".//interface").text, interface_show.find(".//state").text, interface_show.find(".//eth_mtu").text)) print("+=" * 30) # 7b show_commands_result = nxos1_conn.show_list(SHOW_COMMANDS) # print resut print("Result of show commands:") for command_result in show_commands_result: print(etree.tostring(command_result, encoding="unicode")) print("+=" * 30) # 7c print("Configuring Loopback interfaces") result = nxos1_conn.config_list(CONFIG_LOOPBACK) # print XML output of each command for output_message in result: print(etree.tostring(output_message, encoding="unicode")) ''' In [11]: pprint(etree.tostring(interface_show).decode()) ('<output>\n' ' <body>\n' ' <TABLE_interface>\n' ' <ROW_interface>\n' ' <interface>Ethernet1/1</interface>\n' ' <state>up</state>\n' ' <admin_state>up</admin_state>\n' ' <share_state>Dedicated</share_state>\n' ' <eth_hw_desc>100/1000/10000 Ethernet</eth_hw_desc>\n' ' <eth_hw_addr>000c.29d1.0001</eth_hw_addr>\n'
MTU = my_xml.findall(".//eth_mtu")[0].text print("\n") pprint("Interface: {}; State: {}; MTU: {}".format(INT, STATE, MTU)) print("\n") print("Exercise 7b - Run the following two show commands on the nxos1 device") print("-" * 40) cmd = ["show system uptime", "show system resources"] for i in cmd: print(i) print("-" * 20) my_xml1 = device.show_list(i) print(my_xml1) STRING = etree.tostring(my_xml1[0]).decode() print(STRING) print("Exercise 7c - Configure Loopbacks on the nxos1 device") print("-" * 30) cmd = [ 'interface Loopback 187', 'description Loopback187', 'interface Loopback 189', 'description Loopback188' ] my_xml2 = device.config_list(cmd) print(my_xml2) CONFIG = etree.tostring(my_xml2[0]).decode() print(CONFIG)
class NXOSDriver(NXOSDriverBase): def __init__(self, hostname, username, password, timeout=60, optional_args=None): super().__init__(hostname, username, password, timeout=timeout, optional_args=optional_args) if optional_args is None: optional_args = {} # nxos_protocol is there for backwards compatibility, transport is the preferred method self.transport = optional_args.get('transport', optional_args.get('nxos_protocol', 'https')) if self.transport == 'https': self.port = optional_args.get('port', 443) elif self.transport == 'http': self.port = optional_args.get('port', 80) self.ssl_verify = optional_args.get('ssl_verify', False) self.platform = 'nxos' def open(self): try: self.device = NXOSDevice(host=self.hostname, username=self.username, password=self.password, timeout=self.timeout, port=self.port, transport=self.transport, verify=self.ssl_verify, api_format="jsonrpc") self._send_command('show hostname') except (NXAPIConnectionError, NXAPIAuthError): # unable to open connection raise ConnectionException('Cannot connect to {}'.format(self.hostname)) def close(self): self.device = None def _send_command(self, command, raw_text=False): """ Wrapper for NX-API show method. Allows more code sharing between NX-API and SSH. """ return self.device.show(command, raw_text=raw_text) def _send_command_list(self, commands): return self.device.config_list(commands) def _send_config(self, commands): if isinstance(commands, py23_compat.string_types): # Has to be a list generator and not generator expression (not JSON serializable) commands = [command for command in commands.splitlines() if command] return self.device.config_list(commands) @staticmethod def _compute_timestamp(stupid_cisco_output): """ Some fields such `uptime` are returned as: 23week(s) 3day(s) This method will determine the epoch of the event. e.g.: 23week(s) 3day(s) -> 1462248287 """ if not stupid_cisco_output or stupid_cisco_output == 'never': return -1.0 if '(s)' in stupid_cisco_output: pass elif ':' in stupid_cisco_output: stupid_cisco_output = stupid_cisco_output.replace(':', 'hour(s) ', 1) stupid_cisco_output = stupid_cisco_output.replace(':', 'minute(s) ', 1) stupid_cisco_output += 'second(s)' else: stupid_cisco_output = stupid_cisco_output.replace('d', 'day(s) ') stupid_cisco_output = stupid_cisco_output.replace('h', 'hour(s)') things = { 'second(s)': { 'weight': 1 }, 'minute(s)': { 'weight': 60 }, 'hour(s)': { 'weight': 3600 }, 'day(s)': { 'weight': 24 * 3600 }, 'week(s)': { 'weight': 7 * 24 * 3600 }, 'year(s)': { 'weight': 365.25 * 24 * 3600 } } things_keys = things.keys() for part in stupid_cisco_output.split(): for key in things_keys: if key in part: things[key]['count'] = napalm.base.helpers.convert( int, part.replace(key, ''), 0) delta = sum([det.get('count', 0) * det.get('weight') for det in things.values()]) return time.time() - delta @staticmethod def _get_table_rows(parent_table, table_name, row_name): """ Inconsistent behavior: {'TABLE_intf': [{'ROW_intf': { vs {'TABLE_mac_address': {'ROW_mac_address': [{ vs {'TABLE_vrf': {'ROW_vrf': {'TABLE_adj': {'ROW_adj': { """ _table = parent_table.get(table_name) _table_rows = [] if isinstance(_table, list): _table_rows = [_table_row.get(row_name) for _table_row in _table] elif isinstance(_table, dict): _table_rows = _table.get(row_name) if not isinstance(_table_rows, list): _table_rows = [_table_rows] return _table_rows def _get_reply_table(self, result, table_name, row_name): return self._get_table_rows(result, table_name, row_name) def _get_command_table(self, command, table_name, row_name): json_output = self._send_command(command) return self._get_reply_table(json_output, table_name, row_name) def is_alive(self): if self.device: return {'is_alive': True} else: return {'is_alive': False} def _copy_run_start(self): results = self.device.save(filename='startup-config') if not results: msg = 'Unable to save running-config to startup-config!' raise CommandErrorException(msg) def _load_cfg_from_checkpoint(self): commands = ['terminal dont-ask', 'rollback running-config file {}'.format(self.candidate_cfg), 'no terminal dont-ask'] try: rollback_result = self._send_command_list(commands) except ConnectionError: # requests will raise an error with verbose warning output (don't fail on this). return finally: self.changed = True # For nx-api a list is returned so extract the result associated with the # 'rollback' command. rollback_result = rollback_result[1] msg = rollback_result.get('msg') if rollback_result.get('msg') else rollback_result error_msg = True if rollback_result.get('error') else False if 'Rollback failed.' in msg or error_msg: raise ReplaceConfigException(msg) elif rollback_result == []: raise ReplaceConfigException def rollback(self): if self.changed: self.device.rollback(self.rollback_cfg) self._copy_run_start() self.changed = False def get_facts(self): facts = {} facts['vendor'] = "Cisco" show_version = self._send_command("show version") facts['model'] = show_version.get("chassis_id", "") facts['hostname'] = show_version.get("host_name", "") facts['serial_number'] = show_version.get("proc_board_id", "") facts['os_version'] = show_version.get("sys_ver_str", "") uptime_days = show_version.get("kern_uptm_days", 0) uptime_hours = show_version.get("kern_uptm_hrs", 0) uptime_mins = show_version.get("kern_uptm_mins", 0) uptime_secs = show_version.get("kern_uptm_secs", 0) uptime = 0 uptime += uptime_days * 24 * 60 * 60 uptime += uptime_hours * 60 * 60 uptime += uptime_mins * 60 uptime += uptime_secs facts['uptime'] = uptime iface_cmd = 'show interface' interfaces_out = self._send_command(iface_cmd) interfaces_body = interfaces_out['TABLE_interface']['ROW_interface'] interface_list = [intf_data['interface'] for intf_data in interfaces_body] facts['interface_list'] = interface_list hostname_cmd = 'show hostname' hostname = self._send_command(hostname_cmd).get('hostname') if hostname: facts['fqdn'] = hostname return facts def get_interfaces(self): interfaces = {} iface_cmd = 'show interface' interfaces_out = self._send_command(iface_cmd) interfaces_body = interfaces_out['TABLE_interface']['ROW_interface'] for interface_details in interfaces_body: interface_name = interface_details.get('interface') # Earlier version of Nexus returned a list for 'eth_bw' (observed on 7.1(0)N1(1a)) interface_speed = interface_details.get('eth_bw', 0) if isinstance(interface_speed, list): interface_speed = interface_speed[0] interface_speed = int(interface_speed / 1000) if 'admin_state' in interface_details: is_up = interface_details.get('admin_state', '') == 'up' else: is_up = interface_details.get('state', '') == 'up' interfaces[interface_name] = { 'is_up': is_up, 'is_enabled': (interface_details.get('state') == 'up'), 'description': py23_compat.text_type(interface_details.get('desc', '').strip('"')), 'last_flapped': self._compute_timestamp( interface_details.get('eth_link_flapped', '')), 'speed': interface_speed, 'mac_address': napalm.base.helpers.convert( napalm.base.helpers.mac, interface_details.get('eth_hw_addr')), } return interfaces def get_lldp_neighbors(self): results = {} try: command = 'show lldp neighbors' lldp_raw_output = self.cli([command]).get(command, '') lldp_neighbors = napalm.base.helpers.textfsm_extractor( self, 'lldp_neighbors', lldp_raw_output) except NXAPICommandError: lldp_neighbors = [] for neighbor in lldp_neighbors: local_iface = neighbor.get('local_interface') if neighbor.get(local_iface) is None: if local_iface not in results: results[local_iface] = [] neighbor_dict = {'hostname': py23_compat.text_type(neighbor.get('neighbor')), 'port': py23_compat.text_type(neighbor.get('neighbor_interface'))} results[local_iface].append(neighbor_dict) return results def get_bgp_neighbors(self): results = {} bgp_state_dict = { 'Idle': {'is_up': False, 'is_enabled': True}, 'Active': {'is_up': False, 'is_enabled': True}, 'Open': {'is_up': False, 'is_enabled': True}, 'Established': {'is_up': True, 'is_enabled': True}, 'Closing': {'is_up': True, 'is_enabled': True}, 'Shutdown': {'is_up': False, 'is_enabled': False}, } """ af_name_dict = { 'af-id': {'safi': "af-name"}, 'af-id': {'safi': "af-name"}, 'af-id': {'safi': "af-name"} } """ af_name_dict = { 1: {1: 'ipv4', 128: 'vpnv4'}, 2: {1: 'ipv6', 128: 'vpnv6'}, 25: {70: 'l2vpn'} } try: cmd = 'show bgp all summary vrf all' vrf_list = self._get_command_table(cmd, 'TABLE_vrf', 'ROW_vrf') except NXAPICommandError: vrf_list = [] for vrf_dict in vrf_list: result_vrf_dict = { 'router_id': py23_compat.text_type(vrf_dict['vrf-router-id']), 'peers': {} } af_list = vrf_dict.get('TABLE_af', {}).get('ROW_af', []) if isinstance(af_list, dict): af_list = [af_list] for af_dict in af_list: saf_dict = af_dict.get('TABLE_saf', {}).get('ROW_saf', {}) neighbors_list = saf_dict.get('TABLE_neighbor', {}).get('ROW_neighbor', []) if isinstance(neighbors_list, dict): neighbors_list = [neighbors_list] for neighbor_dict in neighbors_list: neighborid = napalm.base.helpers.ip(neighbor_dict['neighborid']) remoteas = napalm.base.helpers.as_number(neighbor_dict['neighboras']) state = py23_compat.text_type(neighbor_dict['state']) bgp_state = bgp_state_dict[state] afid_dict = af_name_dict[int(af_dict['af-id'])] safi_name = afid_dict[int(saf_dict['safi'])] result_peer_dict = { 'local_as': int(vrf_dict['vrf-local-as']), 'remote_as': remoteas, 'remote_id': neighborid, 'is_enabled': bgp_state['is_enabled'], 'uptime': -1, 'description': '', 'is_up': bgp_state['is_up'], 'address_family': { safi_name: { 'sent_prefixes': -1, 'accepted_prefixes': -1, 'received_prefixes': int(neighbor_dict['prefixreceived']) } } } result_vrf_dict['peers'][neighborid] = result_peer_dict vrf_name = vrf_dict['vrf-name-out'] if vrf_name == 'default': vrf_name = 'global' results[vrf_name] = result_vrf_dict return results def get_lldp_neighbors_detail(self, interface=''): lldp_neighbors = {} filter = '' if interface: filter = 'interface {name} '.format(name=interface) command = 'show lldp neighbors {filter}detail'.format(filter=filter) # seems that some old devices may not return JSON output... try: lldp_neighbors_table_str = self.cli([command]).get(command) # thus we need to take the raw text output lldp_neighbors_list = lldp_neighbors_table_str.splitlines() except NXAPICommandError: lldp_neighbors_list = [] if not lldp_neighbors_list: return lldp_neighbors # empty dict CHASSIS_REGEX = r'^(Chassis id:)\s+([a-z0-9\.]+)$' PORT_REGEX = r'^(Port id:)\s+([0-9]+)$' LOCAL_PORT_ID_REGEX = r'^(Local Port id:)\s+(.*)$' PORT_DESCR_REGEX = r'^(Port Description:)\s+(.*)$' SYSTEM_NAME_REGEX = r'^(System Name:)\s+(.*)$' SYSTEM_DESCR_REGEX = r'^(System Description:)\s+(.*)$' SYST_CAPAB_REEGX = r'^(System Capabilities:)\s+(.*)$' ENABL_CAPAB_REGEX = r'^(Enabled Capabilities:)\s+(.*)$' VLAN_ID_REGEX = r'^(Vlan ID:)\s+(.*)$' lldp_neighbor = {} interface_name = None for line in lldp_neighbors_list: chassis_rgx = re.search(CHASSIS_REGEX, line, re.I) if chassis_rgx: lldp_neighbor = { 'remote_chassis_id': napalm.base.helpers.mac(chassis_rgx.groups()[1]) } continue lldp_neighbor['parent_interface'] = '' port_rgx = re.search(PORT_REGEX, line, re.I) if port_rgx: lldp_neighbor['parent_interface'] = py23_compat.text_type(port_rgx.groups()[1]) continue local_port_rgx = re.search(LOCAL_PORT_ID_REGEX, line, re.I) if local_port_rgx: interface_name = local_port_rgx.groups()[1] continue port_descr_rgx = re.search(PORT_DESCR_REGEX, line, re.I) if port_descr_rgx: lldp_neighbor['remote_port'] = py23_compat.text_type(port_descr_rgx.groups()[1]) lldp_neighbor['remote_port_description'] = py23_compat.text_type( port_descr_rgx.groups()[1]) continue syst_name_rgx = re.search(SYSTEM_NAME_REGEX, line, re.I) if syst_name_rgx: lldp_neighbor['remote_system_name'] = py23_compat.text_type( syst_name_rgx.groups()[1]) continue syst_descr_rgx = re.search(SYSTEM_DESCR_REGEX, line, re.I) if syst_descr_rgx: lldp_neighbor['remote_system_description'] = py23_compat.text_type( syst_descr_rgx.groups()[1]) continue syst_capab_rgx = re.search(SYST_CAPAB_REEGX, line, re.I) if syst_capab_rgx: lldp_neighbor['remote_system_capab'] = py23_compat.text_type( syst_capab_rgx.groups()[1]) continue syst_enabled_rgx = re.search(ENABL_CAPAB_REGEX, line, re.I) if syst_enabled_rgx: lldp_neighbor['remote_system_enable_capab'] = py23_compat.text_type( syst_enabled_rgx.groups()[1]) continue vlan_rgx = re.search(VLAN_ID_REGEX, line, re.I) if vlan_rgx: # at the end of the loop if interface_name not in lldp_neighbors.keys(): lldp_neighbors[interface_name] = [] lldp_neighbors[interface_name].append(lldp_neighbor) return lldp_neighbors def cli(self, commands): cli_output = {} if type(commands) is not list: raise TypeError('Please enter a valid list of commands!') for command in commands: command_output = self._send_command(command, raw_text=True) cli_output[py23_compat.text_type(command)] = command_output return cli_output def get_arp_table(self): arp_table = [] command = 'show ip arp' arp_table_vrf = self._get_command_table(command, 'TABLE_vrf', 'ROW_vrf') arp_table_raw = self._get_table_rows(arp_table_vrf[0], 'TABLE_adj', 'ROW_adj') for arp_table_entry in arp_table_raw: raw_ip = arp_table_entry.get('ip-addr-out') raw_mac = arp_table_entry.get('mac') age = arp_table_entry.get('time-stamp') if age == '-': age_sec = -1.0 elif ':' not in age: # Cisco sometimes returns a sub second arp time 0.411797 try: age_sec = float(age) except ValueError: age_sec = -1.0 else: fields = age.split(':') if len(fields) == 3: try: fields = [float(x) for x in fields] hours, minutes, seconds = fields age_sec = 3600 * hours + 60 * minutes + seconds except ValueError: age_sec = -1.0 age_sec = round(age_sec, 1) interface = py23_compat.text_type(arp_table_entry.get('intf-out')) arp_table.append({ 'interface': interface, 'mac': napalm.base.helpers.convert( napalm.base.helpers.mac, raw_mac, raw_mac), 'ip': napalm.base.helpers.ip(raw_ip), 'age': age_sec }) return arp_table def _get_ntp_entity(self, peer_type): ntp_entities = {} command = 'show ntp peers' ntp_peers_table = self._get_command_table(command, 'TABLE_peers', 'ROW_peers') for ntp_peer in ntp_peers_table: if ntp_peer.get('serv_peer', '').strip() != peer_type: continue peer_addr = napalm.base.helpers.ip(ntp_peer.get('PeerIPAddress').strip()) ntp_entities[peer_addr] = {} return ntp_entities def get_ntp_peers(self): return self._get_ntp_entity('Peer') def get_ntp_servers(self): return self._get_ntp_entity('Server') def get_ntp_stats(self): ntp_stats = [] command = 'show ntp peer-status' ntp_stats_table = self._get_command_table(command, 'TABLE_peersstatus', 'ROW_peersstatus') for ntp_peer in ntp_stats_table: peer_address = napalm.base.helpers.ip(ntp_peer.get('remote').strip()) syncmode = ntp_peer.get('syncmode') stratum = int(ntp_peer.get('st')) hostpoll = int(ntp_peer.get('poll')) reachability = int(ntp_peer.get('reach')) delay = float(ntp_peer.get('delay')) ntp_stats.append({ 'remote': peer_address, 'synchronized': (syncmode == '*'), 'referenceid': peer_address, 'stratum': stratum, 'type': '', 'when': '', 'hostpoll': hostpoll, 'reachability': reachability, 'delay': delay, 'offset': 0.0, 'jitter': 0.0 }) return ntp_stats def get_interfaces_ip(self): interfaces_ip = {} ipv4_command = 'show ip interface' ipv4_interf_table_vrf = self._get_command_table(ipv4_command, 'TABLE_intf', 'ROW_intf') for interface in ipv4_interf_table_vrf: interface_name = py23_compat.text_type(interface.get('intf-name', '')) addr_str = interface.get('prefix') unnumbered = py23_compat.text_type(interface.get('unnum-intf', '')) if addr_str: address = napalm.base.helpers.ip(addr_str) prefix = int(interface.get('masklen', '')) if interface_name not in interfaces_ip.keys(): interfaces_ip[interface_name] = {} if 'ipv4' not in interfaces_ip[interface_name].keys(): interfaces_ip[interface_name]['ipv4'] = {} if address not in interfaces_ip[interface_name].get('ipv4'): interfaces_ip[interface_name]['ipv4'][address] = {} interfaces_ip[interface_name]['ipv4'][address].update({ 'prefix_length': prefix }) elif unnumbered: for interf in ipv4_interf_table_vrf: interf_name = py23_compat.text_type(interf.get('intf-name', '')) if interf_name == unnumbered: address = napalm.base.helpers.ip(interf.get('prefix')) prefix = int(interf.get('masklen', '')) if interface_name not in interfaces_ip.keys(): interfaces_ip[interface_name] = {} if 'ipv4' not in interfaces_ip[interface_name].keys(): interfaces_ip[interface_name]['ipv4'] = {} if address not in interfaces_ip[interface_name].get('ipv4'): interfaces_ip[interface_name]['ipv4'][address] = {} interfaces_ip[interface_name]['ipv4'][address].update({ 'prefix_length': prefix }) secondary_addresses = interface.get('TABLE_secondary_address', {}) \ .get('ROW_secondary_address', []) if type(secondary_addresses) is dict: secondary_addresses = [secondary_addresses] for secondary_address in secondary_addresses: secondary_address_ip = napalm.base.helpers.ip(secondary_address.get('prefix1')) secondary_address_prefix = int(secondary_address.get('masklen1', '')) if 'ipv4' not in interfaces_ip[interface_name].keys(): interfaces_ip[interface_name]['ipv4'] = {} if secondary_address_ip not in interfaces_ip[interface_name].get('ipv4'): interfaces_ip[interface_name]['ipv4'][secondary_address_ip] = {} interfaces_ip[interface_name]['ipv4'][secondary_address_ip].update({ 'prefix_length': secondary_address_prefix }) ipv6_command = 'show ipv6 interface' ipv6_interf_table_vrf = self._get_command_table(ipv6_command, 'TABLE_intf', 'ROW_intf') for interface in ipv6_interf_table_vrf: interface_name = py23_compat.text_type(interface.get('intf-name', '')) if interface_name not in interfaces_ip.keys(): interfaces_ip[interface_name] = {} if 'ipv6' not in interfaces_ip[interface_name].keys(): interfaces_ip[interface_name]['ipv6'] = {} if type(interface.get('addr', '')) is list: for ipv6_address in interface.get('addr', ''): address = napalm.base.helpers.ip(ipv6_address.split('/')[0]) prefix = int(ipv6_address.split('/')[-1]) if address not in interfaces_ip[interface_name].get('ipv6'): interfaces_ip[interface_name]['ipv6'][address] = {} interfaces_ip[interface_name]['ipv6'][address].update({ 'prefix_length': prefix }) else: address = napalm.base.helpers.ip(interface.get('addr', '').split('/')[0]) prefix = interface.get('prefix', '').split('/')[-1] if prefix: prefix = int(interface.get('prefix', '').split('/')[-1]) else: prefix = 128 if address not in interfaces_ip[interface_name].get('ipv6'): interfaces_ip[interface_name]['ipv6'][address] = {} interfaces_ip[interface_name]['ipv6'][address].update({ 'prefix_length': prefix }) return interfaces_ip def get_mac_address_table(self): mac_table = [] command = 'show mac address-table' mac_table_raw = self._get_command_table(command, 'TABLE_mac_address', 'ROW_mac_address') for mac_entry in mac_table_raw: raw_mac = mac_entry.get('disp_mac_addr') interface = py23_compat.text_type(mac_entry.get('disp_port')) vlan = int(mac_entry.get('disp_vlan')) active = True static = (mac_entry.get('disp_is_static') != '0') moves = 0 last_move = 0.0 mac_table.append({ 'mac': napalm.base.helpers.mac(raw_mac), 'interface': interface, 'vlan': vlan, 'active': active, 'static': static, 'moves': moves, 'last_move': last_move }) return mac_table def get_snmp_information(self): snmp_information = {} snmp_command = 'show running-config' snmp_raw_output = self.cli([snmp_command]).get(snmp_command, '') snmp_config = napalm.base.helpers.textfsm_extractor(self, 'snmp_config', snmp_raw_output) if not snmp_config: return snmp_information snmp_information = { 'contact': py23_compat.text_type(''), 'location': py23_compat.text_type(''), 'community': {}, 'chassis_id': py23_compat.text_type('') } for snmp_entry in snmp_config: contact = py23_compat.text_type(snmp_entry.get('contact', '')) if contact: snmp_information['contact'] = contact location = py23_compat.text_type(snmp_entry.get('location', '')) if location: snmp_information['location'] = location community_name = py23_compat.text_type(snmp_entry.get('community', '')) if not community_name: continue if community_name not in snmp_information['community'].keys(): snmp_information['community'][community_name] = { 'acl': py23_compat.text_type(snmp_entry.get('acl', '')), 'mode': py23_compat.text_type(snmp_entry.get('mode', '').lower()) } else: acl = py23_compat.text_type(snmp_entry.get('acl', '')) if acl: snmp_information['community'][community_name]['acl'] = acl mode = py23_compat.text_type(snmp_entry.get('mode', '').lower()) if mode: snmp_information['community'][community_name]['mode'] = mode return snmp_information def get_users(self): _CISCO_TO_CISCO_MAP = { 'network-admin': 15, 'network-operator': 5 } _DEFAULT_USER_DICT = { 'password': '', 'level': 0, 'sshkeys': [] } users = {} command = 'show running-config' section_username_raw_output = self.cli([command]).get(command, '') section_username_tabled_output = napalm.base.helpers.textfsm_extractor( self, 'users', section_username_raw_output) for user in section_username_tabled_output: username = user.get('username', '') if not username: continue if username not in users: users[username] = _DEFAULT_USER_DICT.copy() password = user.get('password', '') if password: users[username]['password'] = py23_compat.text_type(password.strip()) level = 0 role = user.get('role', '') if role.startswith('priv'): level = int(role.split('-')[-1]) else: level = _CISCO_TO_CISCO_MAP.get(role, 0) if level > users.get(username).get('level'): # unfortunately on Cisco you can set different priv levels for the same user # Good news though: the device will consider the highest level users[username]['level'] = level sshkeytype = user.get('sshkeytype', '') sshkeyvalue = user.get('sshkeyvalue', '') if sshkeytype and sshkeyvalue: if sshkeytype not in ['ssh-rsa', 'ssh-dsa']: continue users[username]['sshkeys'].append(py23_compat.text_type(sshkeyvalue)) return users def get_network_instances(self, name=''): """ get_network_instances implementation for NX-OS """ # command 'show vrf detail' returns all VRFs with detailed information # format: list of dictionaries with keys such as 'vrf_name' and 'rd' command = u'show vrf detail' vrf_table_raw = self._get_command_table(command, u'TABLE_vrf', u'ROW_vrf') # command 'show vrf interface' returns all interfaces including their assigned VRF # format: list of dictionaries with keys 'if_name', 'vrf_name', 'vrf_id' and 'soo' command = u'show vrf interface' intf_table_raw = self._get_command_table(command, u'TABLE_if', u'ROW_if') # create a dictionary with key = 'vrf_name' and value = list of interfaces vrf_intfs = defaultdict(list) for intf in intf_table_raw: vrf_intfs[intf[u'vrf_name']].append(py23_compat.text_type(intf['if_name'])) vrfs = {} for vrf in vrf_table_raw: vrf_name = py23_compat.text_type(vrf.get('vrf_name')) vrfs[vrf_name] = {} vrfs[vrf_name][u'name'] = vrf_name # differentiate between VRF type 'DEFAULT_INSTANCE' and 'L3VRF' if vrf_name == u'default': vrfs[vrf_name][u'type'] = u'DEFAULT_INSTANCE' else: vrfs[vrf_name][u'type'] = u'L3VRF' vrfs[vrf_name][u'state'] = {u'route_distinguisher': py23_compat.text_type(vrf.get('rd'))} # convert list of interfaces (vrf_intfs[vrf_name]) to expected format # format = dict with key = interface name and empty values vrfs[vrf_name][u'interfaces'] = {} vrfs[vrf_name][u'interfaces'][u'interface'] = dict.fromkeys(vrf_intfs[vrf_name], {}) # if name of a specific VRF was passed as an argument # only return results for this particular VRF if name: if name in vrfs.keys(): return {py23_compat.text_type(name): vrfs[name]} else: return {} # else return results for all VRFs else: return vrfs
#!/usr/bin/python import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning from pprint import pprint from getpass import getpass from nxapi_plumbing import Device from lxml import etree requests.packages.urllib3.disable_warnings(InsecureRequestWarning) nxos1 = Device( api_format='xml', host='nxos1.lasthop.io', username='******', password=getpass(), transport='https', port=8443, verify=False, ) commands = [ 'interface loopback 100', 'description LOOPBACK 100', 'interface loopback 199', 'description LOOPBACK 199' ] output = nxos1.config_list(commands) for out in output: pprint(etree.tostring(out).decode())
import requests from requests.packages.urllib3.exceptions import InsecureRequestWarning from getpass import getpass from nxapi_plumbing import Device from lxml import etree requests.packages.urllib3.disable_warnings(InsecureRequestWarning) password = getpass() device = Device( api_format="xml", host="nxos1.lasthop.io", username="******", password=password, transport="https", port=8443, verify=False, ) config = device.config_list([ "interface loopback180", "ip address 10.50.10.10/32", "interface loopback170", "ip address 10.50.20.20/32" ]) for output_list in config: print(etree.tostring(output_list).decode())