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_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_ntp_stats(self): """FTOS implementation of get_ntp_stats.""" entries = self._get_ntp_assoc() stats = [] for idx, entry in enumerate(entries): # cast ints for key in ['stratum', 'hostpoll', 'reachability']: try: entry[key] = int(entry[key]) except ValueError: entry[key] = 0 # cast floats for key in ['delay', 'offset', 'jitter']: try: entry[key] = float(entry[key]) except ValueError: entry[key] = 0.0 # cast ips for k in ['referenceid', 'remote']: if len(entry[k].strip()) > 0: entry[k] = ip(entry[k]) entry['synchronized'] = (entry['type'] == '*') stats.append(entry) return stats
def get_ntp_peers(self): """FTOS implementation of get_ntp_peers.""" entries = self._get_ntp_assoc() peers = {} for idx, entry in enumerate(entries): peers[ip(entry['remote'])] = {} return peers
def ping(self, destination, source=u'', ttl=255, timeout=2, size=100, count=5, vrf=u''): """FTOS implementation of ping.""" # build command string based on input cmd = ["ping"] if len(vrf.strip()) > 0: cmd.append("vrf %s" % vrf) cmd.append(destination) cmd.append("timeout %d" % timeout) cmd.append("datagram-size %d" % size) if len(source.strip()) > 0: cmd.append("source ip %s" % source) cmd.append("count %d" % count) 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)} # try to parse the output m = re.search( r'Success rate is [\d\.]+ percent \((\d+)\/(\d+)\).+ = (\d+)\/(\d+)\/(\d+)', result) if not m: return { 'error': 'could not parse output', } g = m.groups() return { 'success': { 'probes_sent': int(g[1]), 'packet_loss': int(g[1]) - int(g[0]), 'rtt_min': float(g[2]), 'rtt_avg': float(g[3]), 'rtt_max': float(g[4]), 'rtt_stddev': 0.0, # not implemented 'results': [{ 'ip_address': ip(destination), 'rtt': float(g[3]), }], } }
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_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_interfaces_ip(self): """FTOS implementation of get_interfaces_ip.""" addr = {} # get IPv4 info ip_cmd = "show ip interface" ip_res = self._send_command(ip_cmd) # parse IP addresses iface = None for line in ip_res.splitlines(): # interface line m = re.search(r'^(\w+( \d+(\/\d+)?)?) is \w+', line) if m: # capture interface name and move on to next line iface = m.group(1) continue # look for IPv4 address line m = re.search(r'^Internet address is ([0-9\.]+)(?:\/(\d+))?', line) if not m: continue # prepare address dict for this interface addr = prep_addr(addr, iface) address = ip(m.group(1)) # try to get subnet mask from output as well # otherwise assume /32 mask = 32 if m.group(2): mask = int(m.group(2)) # remove subnet mask from address address = address.replace('/%d' % mask, '') addr[iface][u'ipv4'][address] = { 'prefix_length': mask } ip6_cmd = "show ipv6 interface brief" ip6_res = self._send_command(ip6_cmd) # parse IPv6 addresses iface = None for line in ip6_res.splitlines(): # interface line m = re.search(r'^(\w+( \d+(\/\d+)?)?)\s+', line) if m: # capture interface name and move on to next line iface = m.group(1) continue # look for IPv6 address line m = re.search(r'^\s*([a-f0-9:]+)(?:\/(\d+))?', line) if not m: continue # prepare address dict for this interface addr = prep_addr(addr, iface, u'ipv6') address = ip(m.group(1)) # try to get prefix length from output as well # otherwise assume /128 preflen = 128 if m.group(2): preflen = int(m.group(2)) # remove prefix length from address address = address.replace('/%d' % preflen, '') # for link-local addresses assume prefix length /64 elif re.search(r'^fe80', address): preflen = 64 addr[iface][u'ipv6'][address] = { 'prefix_length': preflen } return addr
def get_bgp_neighbors_detail(self, neighbor_address=u''): """FTOS implementation of get_bgp_neighbors_detail.""" table = {} vrfs = self._get_vrfs() for vrf in vrfs: if vrf['vrf_name'] not in table: table[vrf['vrf_name']] = {} cmd = ["show ip bgp vrf "+vrf['vrf_name']+" 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) for idx, entry in enumerate(neighbors): if not entry['router_id']: continue neighbor = { "up": (entry['connection_state'] == 'ESTABLISHED'), "local_as": -1, # unimplemented "router_id": ip(entry['router_id']), "local_address": py23_compat.text_type(entry['local_address']), "routing_table": vrf['vrf_name'], "local_address_configured": False, # unimplemented "local_port": entry['local_port'], "remote_address": ip(entry['remote_address']), "remote_as": int(entry['remote_as']), "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 neighbor['remote_as'] not in table[vrf['vrf_name']]: table[vrf['vrf_name']][neighbor['remote_as']] = [] table[vrf['vrf_name']][neighbor['remote_as']].append(neighbor) return table