def get_interfaces_counters(self): """ Return interface counters and errors. 'tx_errors': int, 'rx_errors': int, 'tx_discards': int, 'rx_discards': int, 'tx_octets': int, 'rx_octets': int, 'tx_unicast_packets': int, 'rx_unicast_packets': int, 'tx_multicast_packets': int, 'rx_multicast_packets': int, 'tx_broadcast_packets': int, 'rx_broadcast_packets': int, Currently doesn't determine output broadcasts, multicasts """ counters = {} interface_count = len(self.get_interfaces()) command_counters = "show packet ports 1-{}".format(interface_count) output_counter = self._send_command(command_counters) raw_counters = textfsm_extractor(self, "get_interfaces_counters", output_counter) raw_counters = {row.pop("interface"): row for row in raw_counters} command_errors = "show error ports 1-{}".format(interface_count) output_errors = self._send_command(command_errors) raw_errors = textfsm_extractor(self, "get_interfaces_errors", output_errors) for raw_error in raw_errors: interface = raw_error.pop("interface") counters[interface] = {**raw_counters[interface], **raw_error} return counters
def get_facts(self): show_version = self._send_command("show version") info = textfsm_extractor(self, "show_version", show_version)[0] show_interface_detail = self._send_command("show interface detail") interfaces = textfsm_extractor(self, "show_interface_detail", show_interface_detail) # Return interface list including virtual interfaces interface_list = self._expand_port_list(info["validports"]) for i in interfaces: interface_list.append(i["vif"]) uptime = 0 if info["uptimedays"]: uptime += int(info["uptimedays"]) * 86400 if info["uptimehours"]: uptime += int(info["uptimehours"]) * 3600 if info["uptimemins"]: uptime += int(info["uptimemins"]) * 60 return { "hostname": self.hostname, "fqdn": "false", "vendor": "MRV", "model": info["model"], "serial_number": info["serialnumber"], "interface_list": interface_list, "os_version": info["masteros"], "uptime": uptime, }
def get_snmp_information(self): """ Returns a dict of dicts Example Output: { 'chassis_id': u'Asset Tag 54670', 'community': { u'private': { 'acl': u'12', 'mode': u'rw'}, u'public': { 'acl': u'11', 'mode': u'ro'}, u'public_named_acl': { 'acl': u'ALLOW-SNMP-ACL', 'mode': u'ro'}, u'public_no_acl': { 'acl': u'N/A', 'mode': u'ro'}}, 'contact': u'Joe Smith', 'location': u'123 Anytown USA Rack 404'} """ # TODO: Command 'show config current_config include snmp' too slow. Maybe require to use separated commands. # TODO: Add output from 'create snmp group...' # show_switch = self.get_facts() # # # # snmp_dict = { # "chassis_id": "unknown", # "community": {}, # "contact": show_switch["contact"] or "unknown", # "location": show_switch["location"] or "unknown", # } # # return snmp_dict mode_short = {"ReadOnly": "ro", "ReadWrite": "rw"} command = "show config current_config include snmp" output = self._send_command(command) snmp = textfsm_extractor(self, "snmp", output)[0] communities = textfsm_extractor(self, "snmp_community", output) chassis_id = snmp["chassis_id"] or "unknown" contact = snmp["contact"] or "unknown" location = snmp["location"] or "unknown" community_dict = {} for line in communities: community_name = line["community"] mode = line["mode"] community_dict[community_name] = { "acl": "N/A", "mode": mode_short[mode] } return { "chassis_id": chassis_id, "community": community_dict, "contact": contact, "location": location, }
def get_interfaces_vlans(self): """return dict as documented at https://github.com/napalm-automation/napalm/issues/919#issuecomment-485905491""" port_info = textfsm_extractor( self, "show_port_details", self._send_command("show port details") ) interface_info = textfsm_extractor( self, "show_interface_detail", self._send_command("show interface detail") ) result = {} # Add ports to results dict for port in port_info: if port["outboundtagged"] == "untagged": mode = "access" else: mode = "trunk" result[port["port"]] = { "mode": mode, "access-vlan": -1, "trunk-vlans": [], "native-vlan": -1, "tagged-native-vlan": False, } # Add interfaces to results dict, populate vlans from vifs for interface in interface_info: result[interface["vif"]] = { "mode": "access", "access-vlan": -1, "trunk-vlans": [], "native-vlan": -1, "tagged-native-vlan": False, } m = re.match(r"^vif(\d+)", interface["vif"]) if m: vlan_id = int(interface["tag"]) # Ignore VLANs higher than 4094 and vifs that are down if vlan_id < 4095 and interface["linkstate"].lower() == "up": # Add port and vif to list of interfaces for intf in self._expand_port_list(interface["ports"]): if result[intf]["mode"] == "access": result[intf]["access-vlan"] = vlan_id else: result[intf]["trunk-vlans"].append(vlan_id) result[interface["vif"]]["access-vlan"] = vlan_id return result
def get_environment(self): """FTOS implementation of get_environment.""" env = { 'fans': {}, 'temperature': {}, 'power': {}, 'cpu': {}, 'memory': { 'available_ram': 0, 'used_ram': 0, }, } # get fan data # # get sensor data environment = self._send_command("show environment stack-unit") environment = textfsm_extractor(self, 'show_environment_stack-unit', environment) for idx, entry in enumerate(environment): name = "Unit %d" % int(entry['unit']) # temperature env['temperature'][name] = { 'temperature': float(entry['temperature']), 'is_alert': (entry['temp_status'] != '2'), 'is_critical': (entry['temp_status'] != '2') } # power env['power'][name] = { 'status': (entry['volt_status'] == 'ok'), 'capacity': -1.0, # not implemented 'output': -1.0, # not implemented } # get CPU data processes = self._send_command("show processes cpu summary") processes = textfsm_extractor(self, 'show_processes_cpu_summary', processes) for idx, entry in enumerate(processes): env['cpu']["Unit %d" % int(entry['unit'])] = { '%usage': float(entry['omin']), } # get memory data memory = self._send_command("show memory") memory = textfsm_extractor(self, "show_memory", memory) for idx, entry in enumerate(memory): env['memory']['available_ram'] += int(entry['total']) env['memory']['used_ram'] += int(entry['used']) return env
def _get_lldp_ports(self): show_port_details = self._send_command("show port details") ports = textfsm_extractor(self, "show_port_details", show_port_details) portnums = [int(d["port"]) for d in ports if re.match(r"^[0-9]", d["port"])] portlist = "{}-{}".format(min(portnums), max(portnums)) lldp_ports = textfsm_extractor( self, "show_lldp_port", self.device.send_config_set(["lldp", "show lldp port {}".format(portlist)]), ) return lldp_ports
def get_route_to(self, destination="", protocol=""): routes = {} vrfs = self._get_vrfs() for _vrf in vrfs: cmd = ["show ip route"] cmd.append('vrf '+_vrf['vrf_name']) cmd.append(destination) command = ' '.join(cmd) result = self._send_command(command) if 'Routing entry' not in result: break result = textfsm_extractor(self, 'show_ip_route_destination', result) for item in result: if item['prefix'] not in routes: routes[item['prefix']] = [] for next_hop in item['next_hop']: if not next_hop: continue route = { "current_active": -1, # Not implimented "last_active": -1, # Not implimented "age": -1, "next_hop": "", "protocol": item['protocol'], "outgoing_interface": item['outgoing_interface'], "preference": 0, # Not implimented "inactive_reason": -1, # Not implimented "routing_table": _vrf['vrf_name'], "selected_next_hop": -1, # Not implimented "protocol_attributes": {}, } if item['distance']: route['preference'] = int(item['distance']) if item['age']: age = 0 matches = re.finditer(r'(?P<week>\d+(?=w))?(?P<day>\d+(?=d))?(?P<hour>\d+(?=h))?',item['age']) if matches: for match in matches: if match.group('week'): age += int(match.group('week')) * 7 * 24 if match.group('day'): age += int(match.group('day')) * 24 if match.group('hour'): age += int(match.group('hour')) route['age'] = age route['next_hop'] = next_hop routes[item['prefix']].append(route) return routes
def get_vlans(self): """FTOS implementation of vlans.""" cmd = ["show", "vlan"] command = ' '.join(cmd) result = self._send_command(command) result = textfsm_extractor(self, 'show_vlans', result) res_dict = {} for vid in result: vlan = {"name": "Vlan {}".format(vid['vlan_id'])} ifnames = vid['ports'] vlan['interfaces'] = [] for ifname in ifnames: if vid['port_speed'] == 'Te': speed = 'TenGigabitEthernet' elif vid['port_speed'] == 'Fo': speed = 'fortyGigE' elif vid['port_speed'] == 'Hu': speed = 'hundredGigE' if '-' in ifname: start_r, end_r = ifname.split("-")[0], ifname.split( "-")[-1] for i in range(int(start_r.split('/')[-1]), int(end_r.split('/')[-1]) + 1): vlan['interfaces'].append('{} {}/{}'.format( speed, '/'.join(start_r.split('/')[:-1]), i)) else: vlan['interfaces'].append('{} {}'.format(speed, ifname)) res_dict[int(vid['vlan_id'])] = vlan return res_dict
def get_lldp_neighbors_detail(self, interface=""): """ Get lldp neighbor details return textfsm table with the following row: { local_port chassis_type chassis_id port_type port_id system_name system_description port_description system_capabilities_supported system_capabilities_enabled remote_mgmt_ip_family remote_mgmt_ip } """ raw_lldp_out = self._send_command('show lldp info remote-device ' + interface) show_lldp_entries = textfsm_extractor(self, "show_lldp_info_remote_device", raw_lldp_out) print(f' --- LLDP neighbour info ---\n') print( dumps(show_lldp_entries, sort_keys=True, indent=4, separators=(',', ': '))) if len(show_lldp_entries) == 0: return {} return show_lldp_entries
def get_lldp_neighbors_detail(self, interface=""): """ lldp cli commands depends on comware version return diction format { [ 'local_interface' :'', 'local_interface_idx' :'', 'remote_chassis_id' :'', 'remote_port' :'', 'remote_port_description' :'', 'remote_system_name' :'', 'remote_system_description' :'', 'remote_system_capab' :'', 'remote_system_enable_capab' :'', ] } """ version_dict = self.get_version() if interface: if version_dict['os_version'].startswith('5.'): command = 'display lldp neighbor-information interface ' + str( interface) elif version_dict['os_version'].startswith('7.'): command = 'display lldp neighbor-information interface ' + str( interface) + ' verbose' else: # display all lldp neigh interfaces command command = "display lldp neighbor-information " raw_out = self._send_command(command) lldp_entries = textfsm_extractor( self, "display_lldp_neighbor_information_interface", raw_out) if len(lldp_entries) == 0: return {} return lldp_entries
def get_version(self): """ Return Comware version, vendor, model and uptime. Use it as part of get_facts { 'os_version': '5.20.105', 'os_version_release': '1808P21', 'vendor': 'HP', 'model': 'A5800-24G-SFP', 'uptime': 14888460 } """ raw_out = self._send_command('display version') # get only first row of text FSM table version_entries = textfsm_extractor(self, "display_version", raw_out)[0] # convert uptime from '24 weeks, 4 days, 7 hours, 41 minutes to seconds uptime_str = version_entries['uptime'] uptime = 0 match = re.findall(r'(\d+)\s*(\w+){0,5}', uptime_str) for timer in match: if 'year' in timer[1]: uptime += int(timer[0]) * self._YEAR_SECONDS elif 'week' in timer[1]: uptime += int(timer[0]) * self._WEEK_SECONDS elif 'day' in timer[1]: uptime += int(timer[0]) * self._DAY_SECONDS elif 'hour' in timer[1]: uptime += int(timer[0]) * self._HOUR_SECONDS elif 'minute' in timer[1]: uptime += int(timer[0]) * self._MINUTE_SECONDS version_entries['uptime'] = uptime return version_entries
def get_lldp_neighbors_detail(self, interface=""): lldp = {} if interface: command = "show lldp remote_ports {} mode detailed".format( interface) else: command = "show lldp remote_ports mode detailed" lldp_entries = self._send_command(command) lldp_entries = textfsm_extractor(self, "show_lldp_remote_ports_detail", lldp_entries) if len(lldp_entries) == 0: return {} for idx, lldp_entry in enumerate(lldp_entries): local_intf = lldp_entry.pop("local_interface") # Add fields missing on Dlink lldp_entry["parent_interface"] = lldp_entry[ "remote_system_enable_capab"] = "" # Standarding "remote system capab" if lldp_entry["remote_system_capab"]: lldp_entry["remote_system_capab"] = sorted( lldp_entry["remote_system_capab"].strip().lower().split( ",")) else: lldp_entry["remote_system_capab"] = [] # Turn the interfaces into their long version local_intf = canonical_interface_name(local_intf) lldp.setdefault(local_intf, []) lldp[local_intf].append(lldp_entry) return lldp
def get_arp_table(self, vrf=u''): """FTOS implementation of get_arp_table.""" if vrf: msg = "VRF support has not been added for this getter on this platform." raise NotImplementedError(msg) command = "show arp" arp_entries = self._send_command(command) arp_entries = textfsm_extractor(self, 'show_arp', arp_entries) table = [] for idx, arp in enumerate(arp_entries): entry = { 'interface': arp['interface'], 'ip': ip(arp['ip']), 'mac': mac(arp['mac']), } try: # age is given in minutes entry['age'] = float(arp['age']) * 60 except ValueError: entry['age'] = -1.0 table.append(entry) return table
def get_mac_address_table(self, raw_mac_table=None): """ Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address Table, having the following keys: * mac (string) * interface (string) * vlan (int) * active (boolean) * static (boolean) * moves (int) * last_move (float) However, please note that not all vendors provide all these details. E.g.: field last_move is not available on JUNOS devices etc. Example:: [ { 'mac' : '00:1C:58:29:4A:71', 'interface' : 'Ethernet47', 'vlan' : 100, 'static' : False, 'active' : True, 'moves' : 1, 'last_move' : 1454417742.58 }, { 'mac' : '00:1C:58:29:4A:C1', 'interface' : 'xe-1/0/1', 'vlan' : 100, 'moves' : 2, 'last_move' : 1453191948.11 }, { 'mac' : '00:1C:58:29:4A:C2', 'interface' : 'ae7.900', 'vlan' : 900, 'static' : False, 'active' : True, 'moves' : None, 'last_move' : None } ] """ if raw_mac_table is not None: if 'No mac address found' in raw_mac_table: return ['No mac address found'] out_mac_table = raw_mac_table else: # Disable Pageing of the device self.disable_pageing() raw_out = self._send_command('display mac-address') mac_table_entries = textfsm_extractor(self, "display_mac_address_all", raw_out) # owerwrite some values in order to be compliant for row in mac_table_entries: row['mac'] = self.format_mac_cisco_way(row['mac']) row['interface'] = self.normalize_port_name(row['interface']) return mac_table_entries
def get_active_physical_ports(self, aggregation_port): """ Return textFSM table with physical ports joined as "aggregation_port" """ from IPython import embed embed() from IPython.core import debugger debug = debugger.Pdb().set_trace debug() raw_out = self._send_command('display link-aggregation verbose ' + str(aggregation_port)) port_entries = textfsm_extractor(self, "display_link_aggregation_verbose", raw_out) a_ports = list() for row in port_entries: # Return only active ports if row['status'].lower() == 's': a_ports.append(self.normalize_port_name(row['port_name'])) if a_ports: print( f' --- Active ports of the aggregation_port {aggregation_port} ---' ) print( dumps(a_ports, sort_keys=True, indent=4, separators=(',', ': '))) return a_ports else: raise HpNoActiePortsInAggregation
def get_bgp_neighbors_detail(self, neighbor_address=u''): """FTOS implementation of get_bgp_neighbors_detail.""" cmd = ["show ip bgp neighbors"] if len(neighbor_address.strip()) > 0: cmd.append(neighbor_address) command = ' '.join(cmd) neighbors = self._send_command(command) neighbors = textfsm_extractor(self, 'show_ip_bgp_neighbors', neighbors) table = {u'global': {}} for idx, entry in enumerate(neighbors): # TODO: couldn't detect VRF from output vrf = u'global' neighbor = { "up": (entry['connection_state'] == 'ESTABLISHED'), "local_as": -1, # unimplemented "router_id": ip(entry['router_id']), "local_address": str(entry['local_address']), "routing_table": u'', # unimplemented "local_address_configured": False, # unimplemented "local_port": entry['local_port'], "remote_address": ip(entry['remote_address']), "multihop": False, # unimplemented "multipath": False, # unimplemented "remove_private_as": False, # unimplemented "import_policy": u'', # unimplemented "export_policy": u'', # unimplemented "connection_state": entry['connection_state'], "previous_connection_state": u'', # unimplemented "last_event": u'', # unimplemented "suppress_4byte_as": False, # unimplemented "local_as_prepend": False, # unimplemented "configured_holdtime": -1, # unimplemented "configured_keepalive": -1, # unimplemented "active_prefix_count": -1, # unimplemented "received_prefix_count": -1, # unimplemented "suppressed_prefix_count": -1, # unimplemented } # cast some integers for k in [ 'remote_as', 'local_port', 'remote_port', 'input_messages', 'output_messages', 'input_updates', 'output_updates', 'messages_queued_out', 'holdtime', 'keepalive', 'accepted_prefix_count', 'advertised_prefix_count', 'flap_count' ]: try: neighbor[k] = int(entry[k]) except ValueError: neighbor[k] = -1 if entry['remote_as'] not in table[vrf]: table[vrf][int(entry['remote_as'])] = [] table[vrf][int(entry['remote_as'])].append(neighbor) return table
def get_current_privilege(self): """ Get current privilege "show telnet" output depends on os_version of the device !!!@#!@#!#$ """ raw_out = self.device.send_command_timing('show telnet', delay_factor=2) dev_version = self.get_version() if dev_version.startswith(('K.', 'YA.', 'WC.')): show_telnet_entries = textfsm_extractor(self, "show_telnet_vK", raw_out) else: show_telnet_entries = textfsm_extractor(self, "show_telnet", raw_out) for row in show_telnet_entries: if row['session'].startswith('**'): self.current_user_level = row['user_level'] return self.current_user_level
def get_arp_table(self): """Get device's ARP table.""" raw_arp = self._run_cmd("show arp") arp_table = textfsm_extractor(self, "show_arp", raw_arp) for arp in arp_table: arp['interface'] = arp.pop('port') arp['mac'] = self._mac_reformat(arp['mac']) arp['age'] = 'N/A' return arp_table
def get_facts(self): """ Return a set of facts from the devices. """ # default values. serial_number, fqdn, os_version, hostname, domain_name = ( "Unknown", ) * 5 output = self._send_command("show switch") show_switch = textfsm_extractor(self, "show_switch", output)[0] uptime = self.parse_uptime(show_switch["uptime"]) vendor = "Dlink" os_version = show_switch["os_version"] serial_number = show_switch["serial_number"] model = show_switch["model"] # In Dlink device can't change hostname. Add system_name. hostname = fqdn = show_switch["system_name"] # Get interface list show_ports = self._send_command("show ports") interface_list = re.findall(r'^\d+', show_ports, re.MULTILINE) return { "uptime": uptime, "vendor": vendor, "os_version": str(os_version), "serial_number": str(serial_number), "model": str(model), "hostname": str(hostname), "fqdn": fqdn, "interface_list": interface_list, # Additional data "mac_addr": mac(show_switch["mac_addr"]), "ip_addr": show_switch["ip_addr"], "vlan_name": show_switch["vlan_name"], "subnet_mask": show_switch["subnet_mask"], "gateway": show_switch["gateway"], "boot_version": show_switch["boot_version"], "protocol_version": show_switch["protocol_version"], "hardware_version": show_switch["hardware_version"], "system_time": show_switch["system_time"], "location": show_switch["location"], "contact": show_switch["contact"], "stp": show_switch["stp"], "gvrp": show_switch["gvrp"], "igmp_snooping": show_switch["igmp_snooping"], "radius": show_switch["radius"], "telnet": show_switch["telnet"], "web": show_switch["web"], "rmon": show_switch["rmon"], "ssh": show_switch["ssh"], "vlan_trunk": show_switch["vlan_trunk"], "syslog": show_switch["syslog"], "cli_paging": show_switch["cli_paging"], "password_encryption": show_switch["password_encryption"], }
def get_interfaces(self): """Get interface list""" show_version = self._send_command("show version") version = textfsm_extractor(self, "show_version", show_version)[0] show_port_details = self._send_command("show port details") ports = textfsm_extractor(self, "show_port_details", show_port_details) show_interface_detail = self._send_command("show interface detail") interfaces = textfsm_extractor(self, "show_interface_detail", show_interface_detail) result = {} for port in ports: result[port["port"]] = { "is_up": port["linkstate"] == "ON", "is_enabled": port["adminstate"] == "ENABLE", "description": port["description"], "speed": self._convert_speed(port["actualspeed"]), "mtu": -1, "last_flapped": -1.0, "mac_address": version["basemac"], } if port["parent"]: if "children" not in result[port["parent"]].keys(): result[port["parent"]]["children"] = [] result[port["parent"]]["children"].append(port["port"]) result.update( { i["vif"]: { "is_up": i["linkstate"] == "UP", "is_enabled": i["active"] == "Yes", "description": i["description"], "speed": -1, "mtu": self._convert_mtu(i["mtu"]), "last_flapped": -1.0, "mac_address": i["macaddress"], } for i in interfaces } ) return result
def get_interfaces_ip(self): info = textfsm_extractor( self, "show_interface_detail", self._send_command("show interface detail") ) ips = {} for item in info: if item["ipaddress"] and item["ipaddress"] != "not defined": ip, prefix_length = item["ipaddress"].split("/") ips.update( {item["vif"]: {"ipv4": {ip: {"prefix_length": int(prefix_length.strip())}}}} ) return ips
def get_lldp_neighbors_detail(self, interface=''): """FTOS implementation of get_lldp_neighbors_detail.""" if interface: command = "show lldp neighbors interface {} detail".format( interface) else: command = "show lldp neighbors detail" lldp_entries = self._send_command(command) lldp_entries = textfsm_extractor(self, 'show_lldp_neighbors_detail', lldp_entries) lldp = {} for idx, lldp_entry in enumerate(lldp_entries): # TODO: the current textfsm template keeps adding an empty entry at # the end of each interface and I couldn't fix it so at some point # it was just easier to get rid of these empty entries in code nonZero = False for key in lldp_entry.keys(): # local_interface is set to Filldown so that is always filled if key == 'local_interface': continue if len(lldp_entry[key].strip()) > 0: nonZero = True break if not nonZero: continue # get pretty interface name local_intf = canonical_interface_name( lldp_entry.pop('local_interface')) # cast some mac addresses for k in ['remote_port', 'remote_chassis_id']: if len(lldp_entry[k].strip()) > 0: try: lldp_entry[k] = mac(lldp_entry[k]) except AddrFormatError: pass # transform capabilities for k in ['remote_system_capab', 'remote_system_enable_capab']: lldp_entry[k] = transform_lldp_capab(lldp_entry[k]) # not implemented lldp_entry['parent_interface'] = u'' lldp.setdefault(local_intf, []) lldp[local_intf].append(lldp_entry) return lldp
def get_mac_address_table(self): """ Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address Table, having the following keys * mac (string) * interface (string) * vlan (int) * active (boolean) * static (boolean) * moves (int) * last_move (float) Format: VID VLAN Name MAC Address Port Type ---- -------------------------------- ----------------- ---- --------------- 903 ACswmgmt C0-A0-BB-DB-7D-C5 CPU Self 903 ACswmgmt 28-8A-1C-A8-1A-96 25 Dynamic 903 ACswmgmt 70-62-B8-A8-94-13 25 Dynamic """ mac_address_table = [] output = self._send_command("show fdb") show_fdb = textfsm_extractor(self, "show_fdb", output) for line in show_fdb: mac_addr = mac(line["mac"]) interface = line["interface"] vlan = int(line["vlan"]) static = False if line["mac_type"].lower() in ["self", "static", "system"]: static = True if (line["interface"].lower() == "cpu" or re.search(r"router", line["mac_type"].lower()) or re.search(r"switch", line["mac_type"].lower())): interface = "" mac_address_table.append({ "mac": mac_addr, "interface": interface, "vlan": vlan, "static": static, "active": True, "moves": -1, "last_move": -1.0, }) return mac_address_table
def get_route_to(self, destination='', protocol=''): """Get active route for a given destination.""" v4_table = [] v6_table = [] if destination != '': ip_address = IPNetwork(destination) if ip_address.version == 4: raw_v4_table = self._run_cmd( "show ip route {} {}".format(protocol, ip_address.ip)) v4_table = textfsm_extractor( self, "show_ip_route", raw_v4_table) elif ip_address.version == 6: raw_v6_table = self._run_cmd( "show ipv6 route {} {}".format(protocol, ip_address.ip)) v6_table = textfsm_extractor( self, "show_ipv6_route", raw_v6_table) else: raw_v4_table = self._run_cmd( "show ip route {} {}".format(protocol, destination)) v4_table = textfsm_extractor( self, "show_ip_route", raw_v4_table) raw_v6_table = self._run_cmd( "show ipv6 route {} {}".format(protocol, destination)) v6_table = textfsm_extractor(self, "show_ipv6_route", raw_v6_table) route_table = v4_table + v6_table out = {} for route in route_table: if not out.get(route['destination']): out[route['destination']] = [] new_path = {} new_path['protocol'] = route['type'] new_path['preference'] = int(route['distance']) new_path['next_hop'] = route['gateway'] out[route['destination']].append(new_path) return out
def get_interfaces(self): """ Get interface details. last_flapped and mac_address is not implemented Example Output: { u'Vlan1': { 'description': u'N/A', 'is_enabled': True, 'is_up': True, 'last_flapped': -1.0, 'mac_address': u'a493.4cc1.67a7', 'speed': 100}, u'Vlan100': { 'description': u'Data Network', 'is_enabled': True, 'is_up': True, 'last_flapped': -1.0, 'mac_address': u'a493.4cc1.67a7', 'speed': 100}, u'Vlan200': { 'description': u'Voice Network', 'is_enabled': True, 'is_up': True, 'last_flapped': -1.0, 'mac_address': u'a493.4cc1.67a7', 'speed': 100}} """ interface_dict = {} command = "show ports description" output = self._send_command(command) raw_interfaces = textfsm_extractor(self, "show_ports", output) for raw_interface in raw_interfaces: interface_dict[raw_interface["interface"]] = { "is_enabled": True if raw_interface["is_enabled"] == "Enabled" else False, "is_up": True if "Down" not in raw_interface["is_up"] else False, "description": raw_interface["description"].strip(), "mac_address": "", "last_flapped": -1.0, "speed": raw_interface["speed"], } return interface_dict
def traceroute(self, destination, source=u'', ttl=255, timeout=2, vrf=u''): """FTOS implementation of traceroute.""" # source, ttl and timeout are not implemented and therefore ignored cmd = ["traceroute"] if len(vrf.strip()) > 0: cmd.append("vrf %s" % vrf) cmd.append(destination) command = ' '.join(cmd) result = self._send_command(command) # check if output holds an error m = re.search(r'% Error: (.+)', result) if m: return { 'error': m.group(1) } # process results of succesful traceroute result = textfsm_extractor(self, 'traceroute', result) trace = {} ttl = None for idx, entry in enumerate(result): if len(entry['ttl'].strip()) > 0 and ttl != int(entry['ttl']): ttl = int(entry['ttl']) trace[ttl] = {'probes': {}} ctr = 1 # rewrite probes for easier splitting probes = re.sub(r'\s+', ' ', entry['probes'].replace('ms', '').strip()) if len(probes) == 0: probes = [] else: probes = probes.split(' ') for probe in probes: trace[ttl]['probes'][ctr] = { 'rtt': float(probe), 'ip_address': ip(str(entry['hop'])), 'host_name': str(entry['hop']), } ctr += 1 return { 'success': trace, }
def get_mac_address_table(self): """FTOS implementation of get_mac_address_table.""" mac_entries = self._send_command("show mac-address-table") mac_entries = textfsm_extractor(self, 'show_mac-address-table', mac_entries) mac_table = [] for idx, entry in enumerate(mac_entries): entry['mac'] = mac(entry['mac']) entry['interface'] = canonical_interface_name(entry['interface']) entry['vlan'] = int(entry['vlan']) entry['static'] = (entry['static'] == 'Static') entry['active'] = (entry['active'] == 'Active') entry['moves'] = -1 # not implemented entry['last_move'] = -1.0 # not implemented mac_table.append(entry) return mac_table
def get_arp_table(self, vrf=u''): if vrf: msg = "VRF support has not been added for this getter on this platform." raise NotImplementedError(msg) command = "arp -van" arp_entries = self._send_command(command) arp_entries = textfsm_extractor(self, 'show_arp', arp_entries) table = [] for idx, arp in enumerate(arp_entries): entry = { 'interface': arp['interface'], 'ip': ip(arp['ip']), 'mac': mac(arp['mac']), } table.append(entry) return table
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" output = self._send_command(command) section_username_tabled_output = helpers.textfsm_extractor( self, "users", 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_snmp_information(self): snmp_information = {} command = "show running-config" output = self._send_command(command) snmp_config = helpers.textfsm_extractor(self, "snmp_config", 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