diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 0a5b939..051df5a 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -21,13 +21,13 @@ import uuid import socket import tempfile +import telnetlib import copy from netmiko import ConnectHandler, FileTransfer, InLineTransfer -from netmiko import __version__ as netmiko_version from napalm_base.base import NetworkDriver from napalm_base.exceptions import ReplaceConfigException, MergeConfigException, \ - ConnectionClosedException + ConnectionClosedException, CommandErrorException from napalm_base.utils import py23_compat import napalm_base.constants as C @@ -76,14 +76,19 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.password = password self.timeout = timeout + self.transport = optional_args.get('transport', 'ssh') + # Retrieve file names self.candidate_cfg = optional_args.get('candidate_cfg', 'candidate_config.txt') self.merge_cfg = optional_args.get('merge_cfg', 'merge_config.txt') self.rollback_cfg = optional_args.get('rollback_cfg', 'rollback_config.txt') self.inline_transfer = optional_args.get('inline_transfer', False) + if self.transport == 'telnet': + # Telnet only supports inline_transfer + self.inline_transfer = True # None will cause autodetection of dest_file_system - self.dest_file_system = optional_args.get('dest_file_system', None) + self._dest_file_system = optional_args.get('dest_file_system', None) self.auto_rollback_on_error = optional_args.get('auto_rollback_on_error', True) # Netmiko possible arguments @@ -100,16 +105,9 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) 'alt_host_keys': False, 'alt_key_file': '', 'ssh_config_file': None, + 'allow_agent': False, } - fields = netmiko_version.split('.') - fields = [int(x) for x in fields] - maj_ver, min_ver, bug_fix = fields - if maj_ver >= 2: - netmiko_argument_map['allow_agent'] = False - elif maj_ver == 1 and min_ver >= 1: - netmiko_argument_map['allow_agent'] = False - # Build dict of any optional Netmiko args self.netmiko_optional_args = {} for k, v in netmiko_argument_map.items(): @@ -117,8 +115,12 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.netmiko_optional_args[k] = optional_args[k] except KeyError: pass - self.global_delay_factor = optional_args.get('global_delay_factor', 1) - self.port = optional_args.get('port', 22) + + default_port = { + 'ssh': 22, + 'telnet': 23 + } + self.port = optional_args.get('port', default_port[self.transport]) self.device = None self.config_replace = False @@ -128,19 +130,24 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) def open(self): """Open a connection to the device.""" - self.device = ConnectHandler(device_type='cisco_ios', + device_type = 'cisco_ios' + if self.transport == 'telnet': + device_type = 'cisco_ios_telnet' + self.device = ConnectHandler(device_type=device_type, host=self.hostname, username=self.username, password=self.password, **self.netmiko_optional_args) # ensure in enable mode self.device.enable() - if not self.dest_file_system: - try: - self.dest_file_system = self.device._autodetect_fs() - except AttributeError: - raise AttributeError("Netmiko _autodetect_fs not found please upgrade Netmiko or " - "specify dest_file_system in optional_args.") + + def _discover_file_system(self): + try: + return self.device._autodetect_fs() + except Exception: + msg = "Netmiko _autodetect_fs failed (to workaround specify " \ + "dest_file_system in optional_args.)" + raise CommandErrorException(msg) def close(self): """Close the connection to the device.""" @@ -164,22 +171,31 @@ def _send_command(self, command): raise ConnectionClosedException(str(e)) def is_alive(self): - """Returns a flag with the state of the SSH connection.""" + """Returns a flag with the state of the connection.""" null = chr(0) - try: - # Try sending ASCII null byte to maintain - # the connection alive - self.device.send_command(null) - except (socket.error, EOFError): - # If unable to send, we can tell for sure - # that the connection is unusable, - # hence return False. - return { - 'is_alive': False - } - return { - 'is_alive': self.device.remote_conn.transport.is_active() - } + if self.device is None: + return {'is_alive': False} + if self.transport == 'telnet': + try: + # Try sending IAC + NOP (IAC is telnet way of sending command + # IAC = Interpret as Command (it comes before the NOP) + self.device.write_channel(telnetlib.IAC + telnetlib.NOP) + return {'is_alive': True} + except UnicodeDecodeError: + # Netmiko logging bug (remove after Netmiko >= 1.4.3) + return {'is_alive': True} + except AttributeError: + return {'is_alive': False} + else: + # SSH + try: + # Try sending ASCII null byte to maintain the connection alive + self.device.write_channel(null) + return {'is_alive': self.device.remote_conn.transport.is_active()} + except (socket.error, EOFError): + # If unable to send, we can tell for sure that the connection is unusable + return {'is_alive': False} + return {'is_alive': False} @staticmethod def _create_tmp_file(config): @@ -411,7 +427,8 @@ def commit_config(self): self._enable_confirm() if 'Invalid input detected' in output: self.rollback() - merge_error = "Configuration merge failed; automatic rollback attempted" + err_header = "Configuration merge failed; automatic rollback attempted" + merge_error = "{0}:\n{1}".format(err_header, output) raise MergeConfigException(merge_error) # Save config to startup (both replace and merge) @@ -435,6 +452,9 @@ def rollback(self): cmd = 'configure replace {} force'.format(cfg_file) self.device.send_command_expect(cmd) + # Save config to startup + self.device.send_command_expect("write mem") + def _inline_tcl_xfer(self, source_file=None, source_config=None, dest_file=None, file_system=None): """ @@ -1042,6 +1062,8 @@ def get_interfaces_ip(self): if fields[2] == 'dhcp': cmd = "show interface {} | in Internet address is".format(interface) show_int = self._send_command(cmd) + if not show_int: + continue int_fields = show_int.split() ip_address, subnet = int_fields[3].split(r'/') interfaces[interface]['ipv4'] = {ip_address: {}} @@ -1778,7 +1800,9 @@ def get_mac_address_table(self): RE_MACTABLE_DEFAULT = r"^" + MAC_REGEX RE_MACTABLE_6500_1 = r"^\*\s+{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 7 fields RE_MACTABLE_6500_2 = r"^{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 6 fields - RE_MACTABLE_4500 = r"^{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 5 fields + RE_MACTABLE_6500_3 = r"^\s{51}\S+" # Fill down from prior + RE_MACTABLE_4500_1 = r"^{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 5 fields + RE_MACTABLE_4500_2 = r"^\s{32}\S+" # Fill down from prior RE_MACTABLE_2960_1 = r"^All\s+{}".format(MAC_REGEX) RE_MACTABLE_GEN_1 = r"^{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 4 fields (2960/4500) @@ -1816,7 +1840,21 @@ def process_mac_fields(vlan, mac, mac_type, interface): output = "\n".join(output).strip() # Strip any leading astericks output = re.sub(r"^\*", "", output, flags=re.M) + fill_down_vlan = fill_down_mac = fill_down_mac_type = '' for line in output.splitlines(): + # Cat6500 one off anf 4500 multicast format + if (re.search(RE_MACTABLE_6500_3, line) or re.search(RE_MACTABLE_4500_2, line)): + interface = line.strip() + if ',' in interface: + interfaces = interface.split(',') + else: + interfaces = [] + interfaces.append(interface) + for single_interface in interfaces: + mac_address_table.append(process_mac_fields(fill_down_vlan, fill_down_mac, + fill_down_mac_type, + single_interface)) + continue line = line.strip() if line == '': continue @@ -1838,9 +1876,18 @@ def process_mac_fields(vlan, mac, mac_type, interface): _, vlan, mac, mac_type, _, _, interface = line.split() elif len(line.split()) == 6: vlan, mac, mac_type, _, _, interface = line.split() - mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) + if ',' in interface: + interfaces = interface.split(',') + fill_down_vlan = vlan + fill_down_mac = mac + fill_down_mac_type = mac_type + for single_interface in interfaces: + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, + single_interface)) + else: + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) # Cat4500 format - elif re.search(RE_MACTABLE_4500, line) and len(line.split()) == 5: + elif re.search(RE_MACTABLE_4500_1, line) and len(line.split()) == 5: vlan, mac, mac_type, _, interface = line.split() mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) # Cat2960 format - ignore extra header line @@ -1850,7 +1897,16 @@ def process_mac_fields(vlan, mac, mac_type, interface): elif (re.search(RE_MACTABLE_2960_1, line) or re.search(RE_MACTABLE_GEN_1, line)) and \ len(line.split()) == 4: vlan, mac, mac_type, interface = line.split() - mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) + if ',' in interface: + interfaces = interface.split(',') + fill_down_vlan = vlan + fill_down_mac = mac + fill_down_mac_type = mac_type + for single_interface in interfaces: + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, + single_interface)) + else: + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) elif re.search(r"Total Mac Addresses", line): continue elif re.search(r"Multicast Entries", line): @@ -2132,3 +2188,10 @@ def get_config(self, retrieve='all'): configs['running'] = output return configs + + @property + def dest_file_system(self): + # The self.device check ensures napalm has an open connection + if self.device and self._dest_file_system is None: + self._dest_file_system = self._discover_file_system() + return self._dest_file_system diff --git a/requirements.txt b/requirements.txt index a560cde..bcdb5aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -napalm_base>=0.24.0 -netmiko>=1.4.1 +napalm_base>=0.25.0 +netmiko>=1.4.2 diff --git a/setup.py b/setup.py index 031e32b..888b57f 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="napalm-ios", - version="0.7.0", + version="0.8.0", packages=find_packages(), author="Kirk Byers", author_email="ktbyers@twb-tech.com", diff --git a/test/unit/mocked_data/test_get_mac_address_table/4500_format/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/4500_format/expected_result.json index 02d9b3a..40b91b5 100644 --- a/test/unit/mocked_data/test_get_mac_address_table/4500_format/expected_result.json +++ b/test/unit/mocked_data/test_get_mac_address_table/4500_format/expected_result.json @@ -1 +1,128 @@ -[{"moves": -1, "interface": "Port-channel1", "vlan": 1, "static": false, "mac": "30:A3:30:A3:A1:C3", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C4", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C5", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C6", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C7", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C8", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:C9", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Port-channel1", "vlan": 99, "static": false, "mac": "30:A3:30:A3:A1:CA", "active": true, "last_move": -1.0}, {"moves": -1, "interface": "Po1", "vlan": 1, "static": true, "mac": "01:00:0C:CC:CC:CE", "active": false, "last_move": -1.0}, {"moves": -1, "interface": "Po1", "vlan": 1, "static": true, "mac": "FF:FF:FF:FF:FF:FF", "active": false, "last_move": -1.0}, {"moves": -1, "interface": "", "vlan": 39, "static": true, "mac": "FF:FF:FF:FF:FF:FF", "active": false, "last_move": -1.0}] +[ + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 1, + "static": false, + "mac": "30:A3:30:A3:A1:C3", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C4", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C5", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C6", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C7", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C8", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:C9", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Port-channel1", + "vlan": 99, + "static": false, + "mac": "30:A3:30:A3:A1:CA", + "active": true, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Po1", + "vlan": 1, + "static": true, + "mac": "01:00:0C:CC:CC:CE", + "active": false, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Po1", + "vlan": 1, + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "active": false, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Gi10/31", + "vlan": 39, + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "active": false, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Gi10/32", + "vlan": 39, + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "active": false, + "last_move": -1 + }, + { + "moves": -1, + "interface": "", + "vlan": 39, + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "active": false, + "last_move": -1 + }, + { + "moves": -1, + "interface": "Po1", + "vlan": 39, + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "active": false, + "last_move": -1 + } +] diff --git a/test/unit/mocked_data/test_get_mac_address_table/4500_format2/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/4500_format2/expected_result.json new file mode 100644 index 0000000..9eaa4ce --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/4500_format2/expected_result.json @@ -0,0 +1,227 @@ +[ + { + "vlan": 1, + "interface": "Port-channel21", + "static": false, + "mac": "00:11:21:E4:87:10", + "moves": -1, + "active": true, + "last_move": -1 + }, + { + "vlan": 1, + "interface": "", + "static": true, + "mac": "00:12:DA:F7:0C:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 1, + "interface": "Port-channel21", + "static": false, + "mac": "00:17:94:15:EE:C0", + "moves": -1, + "active": true, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "GigabitEthernet3/15", + "static": true, + "mac": "00:04:F2:FE:7F:95", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "GigabitEthernet2/47", + "static": true, + "mac": "00:04:F2:FE:82:DA", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 1, + "interface": "Po21", + "static": true, + "mac": "01:00:0C:CC:CC:CE", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 1, + "interface": "", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 1, + "interface": "Po21", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/4", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/5", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/8", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/11", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/12", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/13", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/19", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/41", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/42", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/43", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi2/47", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi3/10", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi3/15", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 11, + "interface": "Gi3/16", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 24, + "interface": "Po21", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 27, + "interface": "Gi3/30", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + }, + { + "vlan": 27, + "interface": "Po21", + "static": true, + "mac": "FF:FF:FF:FF:FF:FF", + "moves": -1, + "active": false, + "last_move": -1 + } +] diff --git a/test/unit/mocked_data/test_get_mac_address_table/4500_format2/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/4500_format2/show_mac_address_table.txt new file mode 100644 index 0000000..c799074 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/4500_format2/show_mac_address_table.txt @@ -0,0 +1,19 @@ +Unicast Entries + vlan mac address type protocols port +-------+---------------+--------+---------------------+-------------------- + 1 0011.21e4.8710 dynamic ip,assigned,other Port-channel21 + 1 0012.daf7.0cff static ip,ipx,assigned,other Switch + 1 0017.9415.eec0 dynamic ip,assigned Port-channel21 + 11 0004.f2fe.7f95 static ip,ipx,assigned,other GigabitEthernet3/15 + 11 0004.f2fe.82da static ip,ipx,assigned,other GigabitEthernet2/47 + +Multicast Entries + vlan mac address type ports +-------+---------------+-------+-------------------------------------------- + 1 0100.0ccc.ccce system Po21 + 1 ffff.ffff.ffff system Switch,Po21 + 11 ffff.ffff.ffff system Gi2/4,Gi2/5,Gi2/8,Gi2/11,Gi2/12,Gi2/13,Gi2/19 + Gi2/41,Gi2/42,Gi2/43,Gi2/47,Gi3/10,Gi3/15 + Gi3/16 + 24 ffff.ffff.ffff system Po21 + 27 ffff.ffff.ffff system Gi3/30,Po21 diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format3/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/6500_format3/expected_result.json new file mode 100644 index 0000000..18eeafb --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format3/expected_result.json @@ -0,0 +1,245 @@ +[ + { + "vlan": 19, + "active": true, + "last_move": -1, + "static": false, + "mac": "00:FF:9A:B4:03:AD", + "moves": -1, + "interface": "Te7/1" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "C0:FF:BC:1F:72:F2", + "moves": -1, + "interface": "Gi4/28" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "10:FF:AE:63:7A:9E", + "moves": -1, + "interface": "Gi1/14" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "D4:FF:56:B2:95:27", + "moves": -1, + "interface": "Gi2/1" + }, + { + "vlan": 100, + "active": false, + "last_move": -1, + "static": true, + "mac": "1C:FF:0F:C9:11:80", + "moves": -1, + "interface": "" + }, + { + "vlan": 0, + "active": false, + "last_move": -1, + "static": true, + "mac": "00:FF:00:00:00:00", + "moves": -1, + "interface": "" + }, + { + "vlan": 118, + "active": false, + "last_move": -1, + "static": true, + "mac": "50:FF:9D:CC:18:2B", + "moves": -1, + "interface": "Gi2/16" + }, + { + "vlan": 118, + "active": false, + "last_move": -1, + "static": true, + "mac": "50:FF:9D:CC:16:67", + "moves": -1, + "interface": "Gi3/29" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "10:FF:AE:63:9F:FE", + "moves": -1, + "interface": "Gi4/18" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/1" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/2" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/3" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/4" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/6" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/7" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/8" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi1/9" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi10/44" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi10/45" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi10/46" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi10/48" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "33:33:00:00:00:FF", + "moves": -1, + "interface": "Gi10/43" + }, + { + "vlan": 197, + "active": false, + "last_move": -1, + "static": true, + "mac": "C0:FF:BC:1F:71:B7", + "moves": -1, + "interface": "Gi5/8" + }, + { + "vlan": 118, + "active": false, + "last_move": -1, + "static": true, + "mac": "3C:FF:0E:D0:0F:7B", + "moves": -1, + "interface": "Gi4/16" + } +] diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format3/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/6500_format3/show_mac_address_table.txt new file mode 100644 index 0000000..d25fbc7 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format3/show_mac_address_table.txt @@ -0,0 +1,22 @@ +Legend: * - primary entry + age - seconds since last seen + n/a - not available + + vlan mac address type learn age ports +------+----------------+--------+-----+----------+-------------------------- +* 19 00ff.9ab4.03ad dynamic Yes 25 Te7/1 + 197 c0ff.bc1f.72f2 static Yes - Gi4/28 + 197 10ff.ae63.7a9e static Yes - Gi1/14 + 197 d4ff.56b2.9527 static Yes - Gi2/1 +* 100 1cff.0fc9.1180 static No - Router +* --- 00ff.0000.0000 static No - Router + 118 50ff.9dcc.182b static Yes - Gi2/16 + 118 50ff.9dcc.1667 static Yes - Gi3/29 + 197 10ff.ae63.9ffe static Yes - Gi4/18 +* 197 3333.0000.00ff static Yes - Gi1/1,Gi1/2,Gi1/3,Gi1/4 + Gi1/6,Gi1/7,Gi1/8,Gi1/9 + Gi10/44,Gi10/45,Gi10/46 + Gi10/48,Router,Switch,Stby-Switch + Gi10/43 + 197 c0ff.bc1f.71b7 static Yes - Gi5/8 + 118 3cff.0ed0.0f7b static Yes - Gi4/16