From 81fc3a05b0656a4edc045e0c6d0e2ed8e6faaf5a Mon Sep 17 00:00:00 2001 From: Diogo Andre Date: Mon, 24 Oct 2016 01:57:55 -0200 Subject: [PATCH 01/41] Add get_ntp_servers --- .travis.yml | 1 + napalm_ios/ios.py | 27 +++++++++++++++++++ .../show_run___include_ntp_server.txt | 4 +++ 3 files changed, 32 insertions(+) create mode 100644 test/unit/ios/mock_data/show_run___include_ntp_server.txt diff --git a/.travis.yml b/.travis.yml index bd77900..46a96ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ script: - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_lldp_neighbors - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_lldp_neighbors_detail - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_mac_address_table +- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_ntp_servers - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_ntp_stats - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_snmp_information - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ios_only_bgp_time_conversion diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 1d4c8ba..e243cab 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1192,6 +1192,33 @@ def cli(self, commands=None): return cli_output + def get_ntp_servers(self): + """Implementation of get_ntp_servers for IOS. + + Returns the NTP servers configuration as dictionary. + The keys of the dictionary represent the IP Addresses of the servers. + Inner dictionaries do not have yet any available keys. + Example:: + { + '192.168.0.1': {}, + '17.72.148.53': {}, + '37.187.56.220': {}, + '162.158.20.18': {} + } + """ + ntp_servers = {} + command = 'show run | include ntp server' + output = self.device.send_command(command) + + for line in output.splitlines(): + split_line = line.split() + if "vrf" == split_line[2]: + ntp_servers[split_line[4]] = {} + else: + ntp_servers[split_line[2]] = {} + print(ntp_servers) + return ntp_servers + def get_ntp_stats(self): """Implementation of get_ntp_stats for IOS.""" ntp_stats = [] diff --git a/test/unit/ios/mock_data/show_run___include_ntp_server.txt b/test/unit/ios/mock_data/show_run___include_ntp_server.txt new file mode 100644 index 0000000..3eb59b5 --- /dev/null +++ b/test/unit/ios/mock_data/show_run___include_ntp_server.txt @@ -0,0 +1,4 @@ +ntp server 192.168.0.1 prefer +ntp server 17.72.148.53 +ntp server vrf NAPALM 37.187.56.220 +ntp server 2001:DB8:0:0:8:800:200C:417A version 4 From 8e367ebf4b75c9ba9f23d25c0f98d77f8f4fca67 Mon Sep 17 00:00:00 2001 From: Diogo Andre Date: Mon, 24 Oct 2016 02:21:11 -0200 Subject: [PATCH 02/41] Remove whitespace --- napalm_ios/ios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index e243cab..4d4eb86 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1209,7 +1209,7 @@ def get_ntp_servers(self): ntp_servers = {} command = 'show run | include ntp server' output = self.device.send_command(command) - + for line in output.splitlines(): split_line = line.split() if "vrf" == split_line[2]: From b7d2e95d269ed7819dd173ebbbc7a017645dc5b8 Mon Sep 17 00:00:00 2001 From: Diogo Date: Tue, 1 Nov 2016 16:04:16 -0200 Subject: [PATCH 03/41] Clean up --- napalm_ios/ios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 4d4eb86..753e892 100644 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1216,7 +1216,7 @@ def get_ntp_servers(self): ntp_servers[split_line[4]] = {} else: ntp_servers[split_line[2]] = {} - print(ntp_servers) + return ntp_servers def get_ntp_stats(self): From a5940949237237566c22dd7e5527a211c36f12c8 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 16 Nov 2016 16:21:56 +0000 Subject: [PATCH 04/41] Add ISSUE_TEMPLATE and PULL_REQUEST_TEMPLATE --- .github/ISSUE_TEMPLATE | 32 ++++++++++++++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE | 1 + 2 files changed, 33 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..4fe7a8c --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,32 @@ +### Description of Issue/Question + + +### Did you follow the steps from https://github.com/napalm-automation/napalm#faq +- [ ] Yes +- [ ] No + + +### Setup + +### napalm-ios version +(Paste verbatim output from `pip freeze | grep napalm-ios` between quotes below) + +``` + +``` + +### IOS version +(Paste verbatim output from `show version` between quotes below) + +``` + +``` + +### Steps to Reproduce the Issue + +### Error Traceback +(Paste the complete traceback of the exception between quotes below) + +``` + +``` diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..8767eea --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1 @@ + From 8f1a7150fc4fcd7c09cd8a7413a6f5386c751ed1 Mon Sep 17 00:00:00 2001 From: ubajze Date: Thu, 24 Nov 2016 16:05:48 +0100 Subject: [PATCH 05/41] Adding get_config method to IOS driver --- napalm_ios/ios.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) mode change 100644 => 100755 napalm_ios/ios.py diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py old mode 100644 new mode 100755 index 9e31bb3..c2b0888 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1438,3 +1438,26 @@ def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): ping_dict['success'].update({'results': results_array}) return ping_dict + + + def get_config(self, retrieve='all'): + + configs = { + 'startup': '', + 'running': '', + 'candidate': '', + } + + if retrieve in ('startup', 'all'): + command = 'show startup-config' + output = self.device.send_command(command) + configs['startup'] = output + + if retrieve in ('running', 'all'): + command = 'show running-config' + output = self.device.send_command(command) + configs['running'] = output + + return configs + + From 4f881b3728ecb2d6b427984b35db70ee9ecb7706 Mon Sep 17 00:00:00 2001 From: ubajze Date: Thu, 24 Nov 2016 20:13:46 +0100 Subject: [PATCH 06/41] adding test data --- .travis.yml | 1 + napalm_ios/ios.py | 8 +- .../ios/mock_data/show_running-config.txt | 151 ++++++++++++++++++ .../ios/mock_data/show_startup-config.txt | 148 +++++++++++++++++ 4 files changed, 307 insertions(+), 1 deletion(-) mode change 100644 => 100755 .travis.yml create mode 100755 test/unit/ios/mock_data/show_running-config.txt create mode 100755 test/unit/ios/mock_data/show_startup-config.txt diff --git a/.travis.yml b/.travis.yml old mode 100644 new mode 100755 index 6e7fc1d..1411758 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ script: - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_snmp_information - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ios_only_bgp_time_conversion - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ping +- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_config - cd ../.. - coverage combine test/unit/.coverage after_success: coveralls diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index c2b0888..821c784 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1439,8 +1439,14 @@ def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): return ping_dict - def get_config(self, retrieve='all'): + """Implementation of get_config for IOS. + + Returns the startup or/and running configuration as dictionary. + The keys of the dictionary represent the type of + configuration (startup or running). The candidate is always empty string, + since IOS does not support candidate configuration. + """ configs = { 'startup': '', diff --git a/test/unit/ios/mock_data/show_running-config.txt b/test/unit/ios/mock_data/show_running-config.txt new file mode 100755 index 0000000..448a777 --- /dev/null +++ b/test/unit/ios/mock_data/show_running-config.txt @@ -0,0 +1,151 @@ +Building configuration... + +Current configuration : 1366 bytes +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file diff --git a/test/unit/ios/mock_data/show_startup-config.txt b/test/unit/ios/mock_data/show_startup-config.txt new file mode 100755 index 0000000..5f95c93 --- /dev/null +++ b/test/unit/ios/mock_data/show_startup-config.txt @@ -0,0 +1,148 @@ +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file From 4a3b2624243b50bd5bca0be045cda7929d9f1e1b Mon Sep 17 00:00:00 2001 From: ubajze Date: Thu, 24 Nov 2016 20:43:40 +0100 Subject: [PATCH 07/41] fixing PEP8 issues in ios.py --- napalm_ios/ios.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 821c784..9ac5845 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1443,8 +1443,8 @@ def get_config(self, retrieve='all'): """Implementation of get_config for IOS. Returns the startup or/and running configuration as dictionary. - The keys of the dictionary represent the type of - configuration (startup or running). The candidate is always empty string, + The keys of the dictionary represent the type of configuration + (startup or running). The candidate is always empty string, since IOS does not support candidate configuration. """ @@ -1465,5 +1465,3 @@ def get_config(self, retrieve='all'): configs['running'] = output return configs - - From 43bf6606ac6aa2a830f58a64446085050e21623d Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 03:44:53 +0100 Subject: [PATCH 08/41] Adding traceroute method for Cisco IOS --- .travis.yml | 1 + napalm_ios/ios.py | 97 +++++++++++++++++++ .../unit/ios/mock_data/traceroute_8.8.8.8.txt | 16 +++ 3 files changed, 114 insertions(+) create mode 100755 test/unit/ios/mock_data/traceroute_8.8.8.8.txt diff --git a/.travis.yml b/.travis.yml index 1411758..b0246f3 100755 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ script: - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_snmp_information - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ios_only_bgp_time_conversion - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ping +- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_traceroute - nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_config - cd ../.. - coverage combine test/unit/.coverage diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 9ac5845..6ec1baa 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1439,6 +1439,103 @@ def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): return ping_dict + def traceroute(self, destination, source='', ttl=0, timeout=0): + """ + Executes traceroute on the device and returns a dictionary with the result. + + :param destination: Host or IP Address of the destination + :param source (optional): Use a specific IP Address to execute the traceroute + :param ttl (optional): Maimum number of hops -> should be int between 0 and 255 + :param timeout (optional): Number of seconds to wait for response -> should be int between 1 and 3600 + + Output dictionary has one of the following keys: + + * success + * error + + In case of success, the keys of the dictionary represent the hop ID, while values are + dictionaries containing the probes results: + * rtt (float) + * ip_address (str) + * host_name (str) + """ + + command = "traceroute {}".format(destination) + if source: + command += " source {}".format(source) + if ttl: + if isinstance(ttl, int) and 0 <= timeout <= 255: + command += " ttl 0 {}".format(str(ttl)) + if timeout: + # Timeout should be intiger between 1 and 3600 + if isinstance(timeout, int) and 1 <= timeout <= 3600: + command += " timeout {}".format(str(timeout)) + # Have to extend "send_command timeout" since traceroute can last for long time + output = self.device.send_command(command, max_loops=3000) + + # Prepare return dict + traceroute_dict = dict() + if re.search('Unrecognized host or address', output): + traceroute_dict['error'] = 'unknown host %s' % destination + return traceroute_dict + else: + traceroute_dict['success'] = dict() + + results = dict() + # Find all hops + hops = re.findall('\\n\s+[0-9]{1,3}\s', output) + for hop in hops: + # Search for hop in the output + hop_match = re.search(hop, output) + # Find the start index for hop + start_index = hop_match.start() + # If this is last hop + if hops.index(hop) + 1 == len(hops): + # Set the stop index for hop to len of output + stop_index = len(output) + # else, find the start index for next hop + else: + next_hop_match = re.search(hops[hops.index(hop) + 1], output) + stop_index = next_hop_match.start() + # Now you have the start and stop index for each hop + # and you can parse the probes + # Set the hop_variable, and remove spaces between msec for easier matching + hop_string = output[start_index:stop_index].replace(' msec', 'msec') + hop_list = hop_string.split() + current_hop = int(hop_list.pop(0)) + # Prepare dictionary for each hop (assuming there are 3 probes in each hop) + results[current_hop] = dict() + results[current_hop]['probes'] = dict() + results[current_hop]['probes'][1] = {'rtt': None, 'ip_address': None, 'host_name': None} + results[current_hop]['probes'][2] = {'rtt': None, 'ip_address': None, 'host_name': None} + results[current_hop]['probes'][3] = {'rtt': None, 'ip_address': None, 'host_name': None} + current_probe = 1 + ip_address = '' + host_name = '' + while hop_list: + current_element = hop_list.pop(0) + # If current_element is * move index in dictionary to next probe + if current_element == '*': + current_probe += 1 + # If current_element contains msec record the entry for probe + elif 'msec' in current_element: + results[current_hop]['probes'][current_probe]['ip_address'] = ip_address + results[current_hop]['probes'][current_probe]['host_name'] = host_name + results[current_hop]['probes'][current_probe]['rtt'] = float(current_element.replace('msec', '')) + # After recording the entry move the index to next probe + current_probe += 1 + # If element contains '(' and ')' it means that output was in format 'FQDN (IP_ADDRESS)' + # Save the IP address + elif '(' in current_element: + ip_address = current_element.replace('(', '').replace(')', '') + # Save the probe's ip_address and host_name + else: + host_name = current_element + ip_address = current_element + + traceroute_dict['success'] = results + return traceroute_dict + def get_config(self, retrieve='all'): """Implementation of get_config for IOS. diff --git a/test/unit/ios/mock_data/traceroute_8.8.8.8.txt b/test/unit/ios/mock_data/traceroute_8.8.8.8.txt new file mode 100755 index 0000000..c67be57 --- /dev/null +++ b/test/unit/ios/mock_data/traceroute_8.8.8.8.txt @@ -0,0 +1,16 @@ +Type escape sequence to abort. +Tracing the route to google-public-dns-a.google.com (8.8.8.8) +VRF info: (vrf in name/id, vrf out name/id) + 1 10.0.4.2 14 msec 11 msec 11 msec + 2 BSN-access.dynamic.siol.net (213.250.19.90) 175 msec 157 msec 157 msec + 3 95.176.241.222 178 msec 266 msec 208 msec + 4 BSN-250-1-130.static.siol.net (213.250.1.130) 320 msec 300 msec 138 msec + 5 BSN-209.85.248.115.static.siol.net (209.85.248.115) 122 msec + 209.85.248.217 157 msec + 72.14.237.184 195 msec + 6 BSN-0.static.siol.net (209.85.248.1) 122 msec + 209.85.248.217 157 msec 195 msec + 7 * + 209.85.1.1 157 msec 195 msec + 8 * * * + 9 google-public-dns-a.google.com (8.8.8.8) 213 msec 210 msec 197 msec \ No newline at end of file From 5231cc454482a83a7642e4ec1c4e8472e9f7cb76 Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 04:03:11 +0100 Subject: [PATCH 09/41] fixing pep8 issues --- napalm_ios/ios.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 6ec1baa..fd0b1cd 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1445,8 +1445,8 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): :param destination: Host or IP Address of the destination :param source (optional): Use a specific IP Address to execute the traceroute - :param ttl (optional): Maimum number of hops -> should be int between 0 and 255 - :param timeout (optional): Number of seconds to wait for response -> should be int between 1 and 3600 + :param ttl (optional): Maimum number of hops -> int (0-255) + :param timeout (optional): Number of seconds to wait for response -> int (1-3600) Output dictionary has one of the following keys: @@ -1519,12 +1519,13 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): current_probe += 1 # If current_element contains msec record the entry for probe elif 'msec' in current_element: + rtt = float(current_element.replace('msec', '')) results[current_hop]['probes'][current_probe]['ip_address'] = ip_address results[current_hop]['probes'][current_probe]['host_name'] = host_name - results[current_hop]['probes'][current_probe]['rtt'] = float(current_element.replace('msec', '')) + results[current_hop]['probes'][current_probe]['rtt'] = rtt # After recording the entry move the index to next probe current_probe += 1 - # If element contains '(' and ')' it means that output was in format 'FQDN (IP_ADDRESS)' + # If element contains '(' and ')', the output format is 'FQDN (IP_ADDRESS)' # Save the IP address elif '(' in current_element: ip_address = current_element.replace('(', '').replace(')', '') From 395562a2252eb4898bb9b3b547ec64b0d3f04fdb Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 04:22:46 +0100 Subject: [PATCH 10/41] replacing send_command with send_command_expect to be able to add parameters --- napalm_ios/ios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index fd0b1cd..7729db1 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1471,7 +1471,7 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): if isinstance(timeout, int) and 1 <= timeout <= 3600: command += " timeout {}".format(str(timeout)) # Have to extend "send_command timeout" since traceroute can last for long time - output = self.device.send_command(command, max_loops=3000) + output = self.device.send_command_expect(command, max_loops=3000) # Prepare return dict traceroute_dict = dict() From f31bca7d8525724bcf05f1e28ddd2e5ab54ca2f3 Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 05:06:41 +0100 Subject: [PATCH 11/41] Adding **kvargs to send_command method in FakeIOSDevice class to allow any extra arg for the tests. --- napalm_ios/ios.py | 2 +- test/unit/TestIOSDriver.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 test/unit/TestIOSDriver.py diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 7729db1..fd0b1cd 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1471,7 +1471,7 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): if isinstance(timeout, int) and 1 <= timeout <= 3600: command += " timeout {}".format(str(timeout)) # Have to extend "send_command timeout" since traceroute can last for long time - output = self.device.send_command_expect(command, max_loops=3000) + output = self.device.send_command(command, max_loops=3000) # Prepare return dict traceroute_dict = dict() diff --git a/test/unit/TestIOSDriver.py b/test/unit/TestIOSDriver.py old mode 100644 new mode 100755 index d95898c..2b7821d --- a/test/unit/TestIOSDriver.py +++ b/test/unit/TestIOSDriver.py @@ -173,13 +173,13 @@ def read_txt_file(filename): with open(filename) as data_file: return data_file.read() - def send_command_expect(self, command): + def send_command_expect(self, command, **kvargs): """Fake execute a command in the device by just returning the content of a file.""" cmd = re.sub(r'[\[\]\*\^\+\s\|]', '_', command) output = self.read_txt_file('ios/mock_data/{}.txt'.format(cmd)) return py23_compat.text_type(output) - def send_command(self, command): + def send_command(self, command, **kvargs): """Fake execute a command in the device by just returning the content of a file.""" return self.send_command_expect(command) From 896d4e064f4076e82502867ebd91753cc27ebef2 Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 06:05:19 +0100 Subject: [PATCH 12/41] adding dynamic calculation of max_loops, changing the initial probe data model --- napalm_ios/ios.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index fd0b1cd..72bb11b 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1471,7 +1471,20 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): if isinstance(timeout, int) and 1 <= timeout <= 3600: command += " timeout {}".format(str(timeout)) # Have to extend "send_command timeout" since traceroute can last for long time - output = self.device.send_command(command, max_loops=3000) + # The formula to calculate the max_loops parameter is: + # (5 * expected_hops * timeout ) + 150 + # 5 -> because the default sleep time in send_command is 0.2s + # ttl_value -> based on expected hops, 255 if not set + # timeout -> configured timeout, 10 is used when not configured + # 150 -> to make some buffer + ttl_value = 255 + if ttl != 0: + ttl_value = ttl + timeout_value = 10 + if timeout != 0: + timeout_value = timeout + max_loops = (5 * ttl_value * timeout_value) + 150 + output = self.device.send_command(command, max_loops=max_loops) # Prepare return dict traceroute_dict = dict() @@ -1506,9 +1519,9 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): # Prepare dictionary for each hop (assuming there are 3 probes in each hop) results[current_hop] = dict() results[current_hop]['probes'] = dict() - results[current_hop]['probes'][1] = {'rtt': None, 'ip_address': None, 'host_name': None} - results[current_hop]['probes'][2] = {'rtt': None, 'ip_address': None, 'host_name': None} - results[current_hop]['probes'][3] = {'rtt': None, 'ip_address': None, 'host_name': None} + results[current_hop]['probes'][1] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} + results[current_hop]['probes'][2] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} + results[current_hop]['probes'][3] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} current_probe = 1 ip_address = '' host_name = '' From 20919953ce37460a67e14a53f7cce1d8aeec556e Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 06:12:14 +0100 Subject: [PATCH 13/41] fixing some pep8 issues and data model --- napalm_ios/ios.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 72bb11b..fb1d652 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1519,9 +1519,15 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): # Prepare dictionary for each hop (assuming there are 3 probes in each hop) results[current_hop] = dict() results[current_hop]['probes'] = dict() - results[current_hop]['probes'][1] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} - results[current_hop]['probes'][2] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} - results[current_hop]['probes'][3] = {'rtt': float(), 'ip_address': str(), 'host_name': str()} + results[current_hop]['probes'][1] = {'rtt': float(), + 'ip_address': unicode(), + 'host_name': unicode()} + results[current_hop]['probes'][2] = {'rtt': float(), + 'ip_address': unicode(), + 'host_name': unicode()} + results[current_hop]['probes'][3] = {'rtt': float(), + 'ip_address': unicode(), + 'host_name': unicode()} current_probe = 1 ip_address = '' host_name = '' From 9976ea2978e57cb7c9e289a0489c8996221d151f Mon Sep 17 00:00:00 2001 From: ubajze Date: Fri, 25 Nov 2016 06:50:45 +0100 Subject: [PATCH 14/41] adding support for python 2 and 3 in ios traceroute method --- napalm_ios/ios.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index fb1d652..7f04d5d 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1520,14 +1520,14 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): results[current_hop] = dict() results[current_hop]['probes'] = dict() results[current_hop]['probes'][1] = {'rtt': float(), - 'ip_address': unicode(), - 'host_name': unicode()} + 'ip_address': '', + 'host_name': ''} results[current_hop]['probes'][2] = {'rtt': float(), - 'ip_address': unicode(), - 'host_name': unicode()} + 'ip_address': '', + 'host_name': ''} results[current_hop]['probes'][3] = {'rtt': float(), - 'ip_address': unicode(), - 'host_name': unicode()} + 'ip_address': '', + 'host_name': ''} current_probe = 1 ip_address = '' host_name = '' @@ -1538,6 +1538,8 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): current_probe += 1 # If current_element contains msec record the entry for probe elif 'msec' in current_element: + ip_address = py23_compat.text_type(ip_address) + host_name = py23_compat.text_type(host_name) rtt = float(current_element.replace('msec', '')) results[current_hop]['probes'][current_probe]['ip_address'] = ip_address results[current_hop]['probes'][current_probe]['host_name'] = host_name From 75496efa728023f5268b0ff6a875e3d9f63f7e74 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Fri, 25 Nov 2016 16:55:18 +0000 Subject: [PATCH 15/41] Add --- napalm_ios/ios.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 9ac5845..6201d53 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -109,6 +109,12 @@ def close(self): """Close the connection to the device.""" self.device.disconnect() + def is_alive(self): + """Returns a flag with the state of the SSH connection.""" + return { + 'is_alive': self.device.remote_conn.transport.is_active() + } + def load_replace_candidate(self, filename=None, config=None): """ SCP file to device filesystem, defaults to candidate_config. From 79a575503823931f1ef0bbfc30116587674f245a Mon Sep 17 00:00:00 2001 From: ogenstad Date: Wed, 30 Nov 2016 23:19:47 +0100 Subject: [PATCH 16/41] Added pytest tests --- .travis.yml | 24 +- requirements-dev.txt | 1 + test/unit/conftest.py | 66 ++++ .../normal/expected_result.json | 41 +++ .../normal/show_arp___exclude_Incomplete.txt | 9 + .../normal/expected_result.json | 1 + ...ors_192_168_0_2___inc_Prefixes_Current.txt | 1 + ..._neighbors_192_168_0_2___inc_router_ID.txt | 1 + ...ors_192_168_0_2___section_Local_Policy.txt | 2 + ...ors_192_168_0_3___inc_Prefixes_Current.txt | 1 + ..._neighbors_192_168_0_3___inc_router_ID.txt | 1 + ...ors_192_168_0_3___section_Local_Policy.txt | 2 + .../normal/show_ip_bgp_summary.txt | 6 + .../show_ip_bgp_summary___begin_Neighbor.txt | 3 + .../normal/expected_result.json | 5 + .../normal/show_running_config.txt | 151 +++++++++ .../normal/show_startup_config.txt | 148 +++++++++ .../normal/expected_result.json | 5 + .../normal/show_running_config.txt | 151 +++++++++ .../normal/show_startup_config.txt | 148 +++++++++ .../normal/expected_result.json | 30 ++ .../normal/show_memory_statistics.txt | 4 + .../normal/show_proc_cpu.txt | 300 ++++++++++++++++++ .../normal/expected_result.json | 10 + .../test_get_facts/normal/show_hosts.txt | 7 + .../normal/show_ip_interface_brief.txt | 14 + .../test_get_facts/normal/show_version.txt | 59 ++++ .../normal/expected_result.json | 26 ++ .../show_interface_GigabitEthernet1.txt | 28 ++ .../show_interface_GigabitEthernet2.txt | 30 ++ .../show_interface_GigabitEthernet3.txt | 27 ++ .../normal/show_ip_interface_brief.txt | 4 + .../normal/expected_result.json | 44 +++ .../normal/show_interfaces.txt | 83 +++++ .../normal/expected_result.json | 19 ++ .../normal/show_ip_interface_brief.txt | 6 + .../show_run_interface_GigabitEthernet0_5.txt | 8 + .../show_run_interface_Port_channel1.txt | 7 + .../normal/show_run_interface_Vlan20.txt | 7 + .../normal/show_run_interface_Vlan40.txt | 7 + .../normal/show_run_interface_Vlan41.txt | 8 + .../normal/expected_result.json | 10 + .../normal/show_int_Gi1.txt | 28 ++ .../normal/show_int_Gi2.txt | 30 ++ .../normal/show_lldp_neighbors.txt | 9 + .../normal/expected_result.json | 22 ++ .../normal/show_int_Gi1.txt | 28 ++ .../normal/show_int_Gi2.txt | 30 ++ .../normal/show_lldp_neighbors.txt | 10 + ...lldp_neighbors_GigabitEthernet1_detail.txt | 22 ++ ...lldp_neighbors_GigabitEthernet2_detail.txt | 22 ++ .../normal/expected_result.json | 153 +++++++++ .../normal/show_mac_address_table.txt | 21 ++ .../normal/expected_result.json | 6 + .../normal/show_run___include_ntp_server.txt | 4 + .../normal/expected_result.json | 13 + .../normal/show_ntp_associations.txt | 4 + .../normal/expected_result.json | 23 ++ .../normal/show_run___include_snmp_server.txt | 7 + .../test_is_alive/normal/expected_result.json | 3 + .../test_ping/normal/expected_result.json | 26 ++ ...ng_8_8_8_8_timeout_2_size_100_repeat_5.txt | 5 + test/unit/test_getters.py | 13 + 63 files changed, 1964 insertions(+), 20 deletions(-) create mode 100644 test/unit/conftest.py create mode 100644 test/unit/mocked_data/test_get_arp_table/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_arp_table/normal/show_arp___exclude_Incomplete.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary___begin_Neighbor.txt create mode 100644 test/unit/mocked_data/test_get_config/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_config/normal/show_running_config.txt create mode 100644 test/unit/mocked_data/test_get_config/normal/show_startup_config.txt create mode 100644 test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_config_filtered/normal/show_running_config.txt create mode 100644 test/unit/mocked_data/test_get_config_filtered/normal/show_startup_config.txt create mode 100644 test/unit/mocked_data/test_get_environment/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_environment/normal/show_memory_statistics.txt create mode 100644 test/unit/mocked_data/test_get_environment/normal/show_proc_cpu.txt create mode 100644 test/unit/mocked_data/test_get_facts/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_facts/normal/show_hosts.txt create mode 100644 test/unit/mocked_data/test_get_facts/normal/show_ip_interface_brief.txt create mode 100644 test/unit/mocked_data/test_get_facts/normal/show_version.txt create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet1.txt create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet2.txt create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet3.txt create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/show_ip_interface_brief.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_counters/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_ip_interface_brief.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_GigabitEthernet0_5.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Port_channel1.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan20.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan40.txt create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan41.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi1.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi2.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors/normal/show_lldp_neighbors.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi1.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi2.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet1_detail.txt create mode 100644 test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet2_detail.txt create mode 100644 test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_mac_address_table/normal/show_mac_address_table.txt create mode 100644 test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_ntp_servers/normal/show_run___include_ntp_server.txt create mode 100644 test/unit/mocked_data/test_get_ntp_stats/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_ntp_stats/normal/show_ntp_associations.txt create mode 100644 test/unit/mocked_data/test_get_snmp_information/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_get_snmp_information/normal/show_run___include_snmp_server.txt create mode 100644 test/unit/mocked_data/test_is_alive/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_ping/normal/expected_result.json create mode 100644 test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_timeout_2_size_100_repeat_5.txt create mode 100644 test/unit/test_getters.py diff --git a/.travis.yml b/.travis.yml index 1411758..c774c32 100755 --- a/.travis.yml +++ b/.travis.yml @@ -15,24 +15,8 @@ deploy: tags: true branch: master script: +- py.test --cov-report= --cov=napalm_ios test/ - pylama . -- cd test/unit -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_arp_table -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_bgp_neighbors -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_environment -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_facts -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_interfaces -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_interfaces_counters -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_interfaces_ip -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_lldp_neighbors -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_lldp_neighbors_detail -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_mac_address_table -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_ntp_servers -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_ntp_stats -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_snmp_information -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ios_only_bgp_time_conversion -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_ping -- nosetests --with-coverage --cover-package napalm_ios -v TestIOSDriver:TestGetterIOSDriver.test_get_config -- cd ../.. -- coverage combine test/unit/.coverage -after_success: coveralls +after_success: +- coveralls +- if [ $TRAVIS_TAG ]; then curl -X POST https://readthedocs.org/build/napalm; fi diff --git a/requirements-dev.txt b/requirements-dev.txt index e2b6fc0..ebb92dd 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ +future coveralls pytest pytest-cov diff --git a/test/unit/conftest.py b/test/unit/conftest.py new file mode 100644 index 0000000..bc3ddc1 --- /dev/null +++ b/test/unit/conftest.py @@ -0,0 +1,66 @@ +"""Test fixtures.""" +from __future__ import print_function +from __future__ import unicode_literals + +from builtins import super + +import pytest +from napalm_base.test import conftest as parent_conftest + +from napalm_base.test.double import BaseTestDouble +from napalm_base.utils import py23_compat + +from napalm_ios import ios + + +@pytest.fixture(scope='class') +def set_device_parameters(request): + """Set up the class.""" + def fin(): + request.cls.device.close() + request.addfinalizer(fin) + + request.cls.driver = ios.IOSDriver + request.cls.patched_driver = PatchedIOSDriver + request.cls.vendor = 'ios' + parent_conftest.set_device_parameters(request) + + +def pytest_generate_tests(metafunc): + """Generate test cases dynamically.""" + parent_conftest.pytest_generate_tests(metafunc, __file__) + + +class PatchedIOSDriver(ios.IOSDriver): + """Patched IOS Driver.""" + + def __init__(self, hostname, username, password, timeout=60, optional_args=None): + + super().__init__(hostname, username, password, timeout, optional_args) + + self.patched_attrs = ['device'] + self.device = FakeIOSDevice() + + def disconnect(self): + pass + + def is_alive(self): + return { + 'is_alive': True # In testing everything works.. + } + + def open(self): + pass + + +class FakeIOSDevice(BaseTestDouble): + """IOS device test double.""" + + def send_command(self, command): + filename = '{}.txt'.format(self.sanitize_text(command)) + full_path = self.find_file(filename) + result = self.read_txt_file(full_path) + return py23_compat.text_type(result) + + def disconnect(self): + pass diff --git a/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json b/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json new file mode 100644 index 0000000..c8de3b1 --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/normal/expected_result.json @@ -0,0 +1,41 @@ +[{ + "interface": "Vlan20", + "ip": "172.29.50.1", + "mac": "84b8.0276.ac0e", + "age": 8.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.2", + "mac": "0019.0725.344a", + "age": 221.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.3", + "mac": "0024.f7dd.7741", + "age": 0.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.10", + "mac": "6805.ca12.71c2", + "age": 37.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.33", + "mac": "84b8.0276.ac0e", + "age": 61.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.34", + "mac": "0024.f7dd.7743", + "age": 0.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.40", + "mac": "a099.9b1c.dfa7", + "age": 3.0 +}, { + "interface": "Vlan41", + "ip": "192.168.81.34", + "mac": "0024.f7dd.7743", + "age": 0.0 +}] diff --git a/test/unit/mocked_data/test_get_arp_table/normal/show_arp___exclude_Incomplete.txt b/test/unit/mocked_data/test_get_arp_table/normal/show_arp___exclude_Incomplete.txt new file mode 100644 index 0000000..c0979f4 --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/normal/show_arp___exclude_Incomplete.txt @@ -0,0 +1,9 @@ +Protocol Address Age (min) Hardware Addr Type Interface +Internet 172.29.50.1 8 84b8.0276.ac0e ARPA Vlan20 +Internet 172.29.50.2 221 0019.0725.344a ARPA Vlan20 +Internet 172.29.50.3 - 0024.f7dd.7741 ARPA Vlan20 +Internet 172.29.50.10 37 6805.ca12.71c2 ARPA Vlan20 +Internet 172.29.52.33 61 84b8.0276.ac0e ARPA Vlan41 +Internet 172.29.52.34 - 0024.f7dd.7743 ARPA Vlan41 +Internet 172.29.52.40 3 a099.9b1c.dfa7 ARPA Vlan41 +Internet 192.168.81.34 - 0024.f7dd.7743 ARPA Vlan41 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/expected_result.json b/test/unit/mocked_data/test_get_bgp_neighbors/normal/expected_result.json new file mode 100644 index 0000000..424d220 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/expected_result.json @@ -0,0 +1 @@ +{"global": {"router_id": "192.168.0.1", "peers": {"192.168.0.2": {"is_enabled": true, "uptime": -1, "remote_as": 65001, "description": "", "remote_id": "0.0.0.0", "local_as": 65000, "is_up": false, "address_family": {"ipv4": {"sent_prefixes": 0, "accepted_prefixes": 0, "received_prefixes": 0} }}, "192.168.0.3": {"is_enabled": true, "uptime": -1, "remote_as": 65010, "description": "", "remote_id": "192.168.0.3", "local_as": 65000, "is_up": false, "address_family": {"ipv4": {"sent_prefixes": 0, "accepted_prefixes": 0, "received_prefixes": 0} }}}}} diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt new file mode 100644 index 0000000..f954dae --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt @@ -0,0 +1 @@ + Prefixes Current: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt new file mode 100644 index 0000000..0e46fd0 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt @@ -0,0 +1 @@ + BGP version 4, remote router ID 0.0.0.0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt new file mode 100644 index 0000000..d40bb2b --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt @@ -0,0 +1,2 @@ +Local Policy Denied Prefixes: -------- ------- + Total: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt new file mode 100644 index 0000000..f954dae --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt @@ -0,0 +1 @@ + Prefixes Current: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt new file mode 100644 index 0000000..5095e78 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt @@ -0,0 +1 @@ + BGP version 4, remote router ID 192.168.0.3 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt new file mode 100644 index 0000000..d40bb2b --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt @@ -0,0 +1,2 @@ +Local Policy Denied Prefixes: -------- ------- + Total: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.txt new file mode 100644 index 0000000..a4382f8 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.txt @@ -0,0 +1,6 @@ +BGP router identifier 192.168.0.1, local AS number 65000 +BGP table version is 1, main routing table version 1 + +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd +192.168.0.2 4 65001 0 0 1 0 0 never Idle +192.168.0.3 4 65010 0 0 1 0 0 never Active diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary___begin_Neighbor.txt b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary___begin_Neighbor.txt new file mode 100644 index 0000000..9d7e939 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary___begin_Neighbor.txt @@ -0,0 +1,3 @@ +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd +192.168.0.2 4 65001 0 0 1 0 0 never Idle +192.168.0.3 4 65010 0 0 1 0 0 never Active diff --git a/test/unit/mocked_data/test_get_config/normal/expected_result.json b/test/unit/mocked_data/test_get_config/normal/expected_result.json new file mode 100644 index 0000000..f92b306 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/normal/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "!\n! Last configuration change at 18:41:02 UTC Thu Nov 24 2016\n!\nversion 15.5\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nno platform punt-keepalive disable-kernel-core\nplatform console auto\n!\nhostname CSR1\n!\nboot-start-marker\nboot-end-marker\n!\n!\nenable password cisco\n!\naaa new-model\n!\n!\naaa authentication login default local\naaa authorization exec default local\n!\n!\n!\n!\n!\naaa session-id common\n!\nip vrf MGMT\n!\n!\n!\n!\n!\n!\n!\n!\n!\n\n\nip domain name example.local\n\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nsubscriber templating\n!\nmultilink bundle-name authenticated\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nlicense udi pid CSR1000V sn 9OSEGKJXRHE\nspanning-tree extend system-id\n!\nusername cisco privilege 15 password 0 cisco\n!\nredundancy\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\ninterface Loopback0\n ip address 1.1.1.1 255.255.255.255\n!\ninterface GigabitEthernet1\n ip vrf forwarding MGMT\n ip address 192.168.35.121 255.255.255.0\n negotiation auto\n!\ninterface GigabitEthernet2\n ip address 10.1.1.1 255.255.255.0\n negotiation auto\n!\ninterface GigabitEthernet3\n no ip address\n shutdown\n negotiation auto\n!\nrouter ospf 1\n redistribute connected subnets\n network 10.1.1.0 0.0.0.255 area 0\n!\n!\nvirtual-service csr_mgmt\n!\nip forward-protocol nd\n!\nno ip http server\nno ip http secure-server\n!\n!\n!\n!\n!\n!\ncontrol-plane\n!\n !\n !\n !\n !\n!\n!\n!\n!\n!\nline con 0\nline vty 0 4\n!\n!\nend", + "running": "Building configuration...\n\nCurrent configuration : 1366 bytes\n!\n! Last configuration change at 18:41:02 UTC Thu Nov 24 2016\n!\nversion 15.5\nservice timestamps debug datetime msec\nservice timestamps log datetime msec\nno platform punt-keepalive disable-kernel-core\nplatform console auto\n!\nhostname CSR1\n!\nboot-start-marker\nboot-end-marker\n!\n!\nenable password cisco\n!\naaa new-model\n!\n!\naaa authentication login default local\naaa authorization exec default local\n!\n!\n!\n!\n!\naaa session-id common\n!\nip vrf MGMT\n!\n!\n!\n!\n!\n!\n!\n!\n!\n\n\nip domain name example.local\n\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nsubscriber templating\n!\nmultilink bundle-name authenticated\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\nlicense udi pid CSR1000V sn 9OSEGKJXRHE\nspanning-tree extend system-id\n!\nusername cisco privilege 15 password 0 cisco\n!\nredundancy\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\ninterface Loopback0\n ip address 1.1.1.1 255.255.255.255\n!\ninterface GigabitEthernet1\n ip vrf forwarding MGMT\n ip address 192.168.35.121 255.255.255.0\n negotiation auto\n!\ninterface GigabitEthernet2\n ip address 10.1.1.1 255.255.255.0\n negotiation auto\n!\ninterface GigabitEthernet3\n no ip address\n shutdown\n negotiation auto\n!\nrouter ospf 1\n redistribute connected subnets\n network 10.1.1.0 0.0.0.255 area 0\n!\n!\nvirtual-service csr_mgmt\n!\nip forward-protocol nd\n!\nno ip http server\nno ip http secure-server\n!\n!\n!\n!\n!\n!\ncontrol-plane\n!\n !\n !\n !\n !\n!\n!\n!\n!\n!\nline con 0\nline vty 0 4\n!\n!\nend", + "candidate": "" +} diff --git a/test/unit/mocked_data/test_get_config/normal/show_running_config.txt b/test/unit/mocked_data/test_get_config/normal/show_running_config.txt new file mode 100644 index 0000000..448a777 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/normal/show_running_config.txt @@ -0,0 +1,151 @@ +Building configuration... + +Current configuration : 1366 bytes +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config/normal/show_startup_config.txt b/test/unit/mocked_data/test_get_config/normal/show_startup_config.txt new file mode 100644 index 0000000..5f95c93 --- /dev/null +++ b/test/unit/mocked_data/test_get_config/normal/show_startup_config.txt @@ -0,0 +1,148 @@ +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json b/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json new file mode 100644 index 0000000..dcddbba --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/normal/expected_result.json @@ -0,0 +1,5 @@ +{ + "startup": "", + "running": "", + "candidate": "" +} diff --git a/test/unit/mocked_data/test_get_config_filtered/normal/show_running_config.txt b/test/unit/mocked_data/test_get_config_filtered/normal/show_running_config.txt new file mode 100644 index 0000000..448a777 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/normal/show_running_config.txt @@ -0,0 +1,151 @@ +Building configuration... + +Current configuration : 1366 bytes +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_config_filtered/normal/show_startup_config.txt b/test/unit/mocked_data/test_get_config_filtered/normal/show_startup_config.txt new file mode 100644 index 0000000..5f95c93 --- /dev/null +++ b/test/unit/mocked_data/test_get_config_filtered/normal/show_startup_config.txt @@ -0,0 +1,148 @@ +! +! Last configuration change at 18:41:02 UTC Thu Nov 24 2016 +! +version 15.5 +service timestamps debug datetime msec +service timestamps log datetime msec +no platform punt-keepalive disable-kernel-core +platform console auto +! +hostname CSR1 +! +boot-start-marker +boot-end-marker +! +! +enable password cisco +! +aaa new-model +! +! +aaa authentication login default local +aaa authorization exec default local +! +! +! +! +! +aaa session-id common +! +ip vrf MGMT +! +! +! +! +! +! +! +! +! + + +ip domain name example.local + +! +! +! +! +! +! +! +! +! +! +subscriber templating +! +multilink bundle-name authenticated +! +! +! +! +! +! +! +! +! +! +! +! +! +license udi pid CSR1000V sn 9OSEGKJXRHE +spanning-tree extend system-id +! +username cisco privilege 15 password 0 cisco +! +redundancy +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +! +interface Loopback0 + ip address 1.1.1.1 255.255.255.255 +! +interface GigabitEthernet1 + ip vrf forwarding MGMT + ip address 192.168.35.121 255.255.255.0 + negotiation auto +! +interface GigabitEthernet2 + ip address 10.1.1.1 255.255.255.0 + negotiation auto +! +interface GigabitEthernet3 + no ip address + shutdown + negotiation auto +! +router ospf 1 + redistribute connected subnets + network 10.1.1.0 0.0.0.255 area 0 +! +! +virtual-service csr_mgmt +! +ip forward-protocol nd +! +no ip http server +no ip http secure-server +! +! +! +! +! +! +control-plane +! + ! + ! + ! + ! +! +! +! +! +! +line con 0 +line vty 0 4 +! +! +end \ No newline at end of file diff --git a/test/unit/mocked_data/test_get_environment/normal/expected_result.json b/test/unit/mocked_data/test_get_environment/normal/expected_result.json new file mode 100644 index 0000000..53dfc79 --- /dev/null +++ b/test/unit/mocked_data/test_get_environment/normal/expected_result.json @@ -0,0 +1,30 @@ +{ + "fans": { + "invalid": { + "status": true + } + }, + "temperature": { + "invalid": { + "is_alert": false, + "temperature": -1.0, + "is_critical": false + } + }, + "cpu": { + "0": { + "%usage": 6.0 + } + }, + "power": { + "invalid": { + "status": true, + "output": -1.0, + "capacity": -1.0 + } + }, + "memory": { + "available_ram": 4826256, + "used_ram": 20873476 + } +} diff --git a/test/unit/mocked_data/test_get_environment/normal/show_memory_statistics.txt b/test/unit/mocked_data/test_get_environment/normal/show_memory_statistics.txt new file mode 100644 index 0000000..e081aaf --- /dev/null +++ b/test/unit/mocked_data/test_get_environment/normal/show_memory_statistics.txt @@ -0,0 +1,4 @@ +Head Total(b) Used(b) Free(b) Lowest(b) Largest(b) +Processor 277B88C 21505428 18498044 3007384 2136352 2061756 +I/O 2C00000 4194304 2375432 1818872 1581372 1817552 +Driver te 18C0000 1048576 44 1048532 1048532 1048532 diff --git a/test/unit/mocked_data/test_get_environment/normal/show_proc_cpu.txt b/test/unit/mocked_data/test_get_environment/normal/show_proc_cpu.txt new file mode 100644 index 0000000..e67e6c5 --- /dev/null +++ b/test/unit/mocked_data/test_get_environment/normal/show_proc_cpu.txt @@ -0,0 +1,300 @@ +CPU utilization for five seconds: 5%/0%; one minute: 6%; five minutes: 6% + PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process + 1 9 193 46 0.00% 0.00% 0.00% 0 Chunk Manager + 2 5032 3335727 1 0.00% 0.00% 0.00% 0 Load Meter + 3 0 1 0 0.00% 0.00% 0.00% 0 Connection Mgr + 4 134047004 7159038 18724 0.00% 0.71% 0.74% 0 Check heaps + 5 333 277978 1 0.00% 0.00% 0.00% 0 Pool Manager + 6 0 1 0 0.00% 0.00% 0.00% 0 DiscardQ Backgro + 7 0 2 0 0.00% 0.00% 0.00% 0 Timers + 8 17 1565 10 0.00% 0.00% 0.00% 0 WATCH_AFS + 9 3304 273 12102 0.00% 0.00% 0.00% 0 crypto sw pk pro + 10 0 1 0 0.00% 0.00% 0.00% 0 Crash writer + 11 0 1 0 0.00% 0.00% 0.00% 0 Exception contro + 12 356620 1375208 259 0.00% 0.00% 0.00% 0 ARP Input + 13 11309 17323327 0 0.00% 0.00% 0.00% 0 ARP Background + 14 0 13113 0 0.00% 0.00% 0.00% 0 AAA_SERVER_DEADT + 15 0 1 0 0.00% 0.00% 0.00% 0 Policy Manager + 16 16 19 842 0.00% 0.00% 0.00% 0 Entity MIB API + 17 0 1 0 0.00% 0.00% 0.00% 0 IFS Agent Manage + 18 311 3330342 0 0.00% 0.00% 0.00% 0 IPC Event Notifi + 19 5811 16204770 0 0.00% 0.00% 0.00% 0 IPC Mcast Pendin + 20 92 277960 0 0.00% 0.00% 0.00% 0 IPC Dynamic Cach + 21 0 1 0 0.00% 0.00% 0.00% 0 IPC Session Serv + 22 0 1 0 0.00% 0.00% 0.00% 0 IPC Zone Manager + 23 6656 16204770 0 0.00% 0.00% 0.00% 0 IPC Periodic Tim + 24 6517 16204770 0 0.00% 0.00% 0.00% 0 IPC Deferred Por + 25 0 1 0 0.00% 0.00% 0.00% 0 IPC Process leve + 26 0 1 0 0.00% 0.00% 0.00% 0 IPC Seat Manager + 27 107 952671 0 0.00% 0.00% 0.00% 0 IPC Check Queue + 28 0 1 0 0.00% 0.00% 0.00% 0 IPC Seat RX Cont + 29 0 1 0 0.00% 0.00% 0.00% 0 IPC Seat TX Cont + 30 760 1667867 0 0.00% 0.00% 0.00% 0 IPC Keep Alive M + 31 723 3330345 0 0.00% 0.00% 0.00% 0 IPC Loadometer + 32 116 7 16571 0.00% 0.00% 0.00% 0 PrstVbl + 33 0 2 0 0.00% 0.00% 0.00% 0 XML Proxy Client + 34 1641 16564383 0 0.00% 0.00% 0.00% 0 Dynamic ARP Insp + 35 0 1 0 0.00% 0.00% 0.00% 0 ARP Snoop + 36 0 2 0 0.00% 0.00% 0.00% 0 SMART + 37 8633 16678628 0 0.00% 0.00% 0.00% 0 GraphIt + 38 0 1 0 0.00% 0.00% 0.00% 0 Critical Bkgnd + 39 682024 2001479 340 0.00% 0.00% 0.00% 0 Net Background + 40 0 1 0 0.00% 0.00% 0.00% 0 IDB Work + 41 121 47135 2 0.00% 0.00% 0.00% 0 Logger + 42 1658 16564357 0 0.00% 0.00% 0.00% 0 TTY Background + 43 9 7 1285 0.00% 0.00% 0.00% 0 IF-MGR control p + 44 0 8261 0 0.00% 0.00% 0.00% 0 IF-MGR event pro + 45 57198 993179 57 0.00% 0.00% 0.00% 0 Net Input + 46 23197 3335729 6 0.00% 0.00% 0.00% 0 Compute load avg + 47 6996691 556361 12575 0.00% 0.02% 0.00% 0 Per-minute Jobs + 48 50567 16678656 3 0.00% 0.00% 0.00% 0 Per-Second Jobs + 49 0 1 0 0.00% 0.00% 0.00% 0 AggMgr Process + 50 0 111 0 0.00% 0.00% 0.00% 0 Transport Port A + 51 29202 4993423 5 0.00% 0.00% 0.00% 0 HC Counter Timer + 52 0 1 0 0.00% 0.00% 0.00% 0 SFF8472 + 53 31825 330492090 0 0.00% 0.00% 0.00% 0 DownWhenLooped + 54 0 1 0 0.00% 0.00% 0.00% 0 HULC ACL Tcam Me + 55 0 1 0 0.00% 0.00% 0.00% 0 HRPC lpip reques + 56 0 2 0 0.00% 0.00% 0.00% 0 HLPIP Sync Proce + 57 0 1 0 0.00% 0.00% 0.00% 0 HRPC EnergyWise + 58 0 1 0 0.00% 0.00% 0.00% 0 HRPC actual powe + 59 345 555839 0 0.00% 0.00% 0.00% 0 PSP Timer + 60 0 1 0 0.00% 0.00% 0.00% 0 HULC QM Tcam Mem + 61 24520370 219209 111858 0.00% 0.01% 0.09% 0 Authenticate Pro + 62 0 1 0 0.00% 0.00% 0.00% 0 HULC PBR Tcam Me + 63 17 17023 0 0.00% 0.00% 0.00% 0 EEM ED ND + 64 0 18 0 0.00% 0.00% 0.00% 0 EEM ED Identity + 65 9 35 257 0.00% 0.00% 0.00% 0 EEM ED MAT + 66 0 5 0 0.00% 0.00% 0.00% 0 HL2MCM + 67 9 5 1800 0.00% 0.00% 0.00% 0 HL2MCM + 68 0 1 0 0.00% 0.00% 0.00% 0 HRPC asic-stats + 69 0 1 0 0.00% 0.00% 0.00% 0 HRPC hsm request + 70 0 7 0 0.00% 0.00% 0.00% 0 Stack Mgr + 71 67 7 9571 0.00% 0.00% 0.00% 0 Stack Mgr Notifi + 72 1146328 885749250 1 0.00% 0.00% 0.00% 0 Fifo Error Detec + 73 16 9 1777 0.00% 0.00% 0.00% 0 Adjust Regions + 74 12126 8317697 1 0.00% 0.00% 0.00% 0 hrpc -> response + 75 0 19 0 0.00% 0.00% 0.00% 0 hrpc -> request + 76 3012 2776764 1 0.00% 0.00% 0.00% 0 hrpc <- response + 77 0 1 0 0.00% 0.00% 0.00% 0 HRPC hcomp reque + 78 8 3 2666 0.00% 0.00% 0.00% 0 HULC Device Mana + 79 0 3 0 0.00% 0.00% 0.00% 0 HRPC hdm non blo + 80 0 2 0 0.00% 0.00% 0.00% 0 HRPC hdm blockin + 81 555 3330338 0 0.00% 0.00% 0.00% 0 HIPC bkgrd proce + 82 2914 16720 174 0.00% 0.00% 0.00% 0 Hulc Port-Securi + 83 0 1 0 0.00% 0.00% 0.00% 0 HRPC hpsecure re + 84 0 1 0 0.00% 0.00% 0.00% 0 HRPC hlfm reques + 85 393285 494966923 0 0.00% 0.00% 0.00% 0 HLFM address lea + 86 1831 16564362 0 0.00% 0.00% 0.00% 0 HLFM aging proce + 87 338212 495218973 0 0.00% 0.00% 0.00% 0 HLFM address ret + 88 0 1 0 0.00% 0.00% 0.00% 0 HRPC hulc misc r + 89 1392348 1666770 835 0.15% 0.01% 0.00% 0 HULC Tcam Memory + 90 5930 5553243 1 0.00% 0.00% 0.00% 0 HVLAN main bkgrd + 91 0 2 0 0.00% 0.00% 0.00% 0 HVLAN Mapped Vla + 92 0 2 0 0.00% 0.00% 0.00% 0 Vlan shutdown Pr + 93 0 3 0 0.00% 0.00% 0.00% 0 HRPC vlan reques + 94 0 1 0 0.00% 0.00% 0.00% 0 HULC VLAN REF Ba + 95 0 1 0 0.00% 0.00% 0.00% 0 HRPC ilp request + 96 0 1 0 0.00% 0.00% 0.00% 0 HULC PM Vector P + 97 0 1 0 0.00% 0.00% 0.00% 0 HPM Msg Retry Pr + 98 1410 4302 327 0.00% 0.00% 0.00% 0 SpanTree Helper + 99 172886 33130161 5 0.00% 0.00% 0.00% 0 hpm main process + 100 41 17040 2 0.00% 0.00% 0.00% 0 HPM Stack Sync P + 101 0 1 0 0.00% 0.00% 0.00% 0 HRPC pm request + 102 179346 16678629 10 0.00% 0.00% 0.00% 0 hpm counter proc + 103 0 1 0 0.00% 0.00% 0.00% 0 HRPC pm-counters + 104 0 1 0 0.00% 0.00% 0.00% 0 hpm vp events ca + 105 0 1 0 0.00% 0.00% 0.00% 0 HRPC hcmp reques + 106 0 1 0 0.00% 0.00% 0.00% 0 HACL Queue Proce + 107 0 1 0 0.00% 0.00% 0.00% 0 HRPC acl request + 108 9 107 84 0.00% 0.00% 0.00% 0 HACL Acl Manager + 109 0 1 0 0.00% 0.00% 0.00% 0 HRPC backup inte + 110 2185 281 7775 0.00% 0.08% 0.31% 1 SSH Process + 111 0 1 0 0.00% 0.00% 0.00% 0 HRPC cdp request + 112 0 1 0 0.00% 0.00% 0.00% 0 HULC CISP Proces + 113 0 1 0 0.00% 0.00% 0.00% 0 HRPC lldp reques + 114 0 1 0 0.00% 0.00% 0.00% 0 HRPC dot1x reque + 115 0 3 0 0.00% 0.00% 0.00% 0 HULC DOT1X Proce + 116 0 1 0 0.00% 0.00% 0.00% 0 HRPC system mtu + 117 0 1 0 0.00% 0.00% 0.00% 0 SMI MSG Retry Pr + 118 0 1 0 0.00% 0.00% 0.00% 0 HRPC Smart Insta + 119 0 1 0 0.00% 0.00% 0.00% 0 HRPC sdm request + 120 58881 82734029 0 0.00% 0.00% 0.00% 0 Hulc Storm Contr + 121 0 2 0 0.00% 0.00% 0.00% 0 HSTP Sync Proces + 122 0 1 0 0.00% 0.00% 0.00% 0 HRPC stp_cli req + 123 0 1 0 0.00% 0.00% 0.00% 0 HRPC stp_state_s + 124 0 2 0 0.00% 0.00% 0.00% 0 S/W Bridge Proce + 125 0 1 0 0.00% 0.00% 0.00% 0 HRPC hudld reque + 126 0 1 0 0.00% 0.00% 0.00% 0 HRPC vqpc reques + 127 0 1 0 0.00% 0.00% 0.00% 0 HRPC aim request + 128 366 7951 46 0.00% 0.00% 0.00% 0 HCEF ADJ Refresh + 129 0 1 0 0.00% 0.00% 0.00% 0 HRPC hled reques + 130 1451588 416433725 3 0.00% 0.00% 0.00% 0 Hulc LED Process + 131 140072 12201333 11 0.00% 0.00% 0.00% 0 HL3U bkgrd proce + 132 0 1 0 0.00% 0.00% 0.00% 0 HRPC hl3u reques + 133 21578 3808338 5 0.00% 0.00% 0.00% 0 HIPV6 bkgrd proc + 134 0 1 0 0.00% 0.00% 0.00% 0 HRPC IPv6 Unicas + 135 3376 3808616 0 0.00% 0.00% 0.00% 0 HL3U PBR bkgrd p + 136 145 138981 1 0.00% 0.00% 0.00% 0 HL3U PBR n-h res + 137 0 1 0 0.00% 0.00% 0.00% 0 HRPC dtp request + 138 0 1 0 0.00% 0.00% 0.00% 0 HRPC show_forwar + 139 0 1 0 0.00% 0.00% 0.00% 0 HRPC snmp reques + 140 0 1 0 0.00% 0.00% 0.00% 0 HULC SNMP Proces + 141 14659 3330353 4 0.00% 0.00% 0.00% 0 HQM Stack Proces + 142 101856 6660687 15 0.00% 0.00% 0.00% 0 HRPC qos request + 143 0 1 0 0.00% 0.00% 0.00% 0 HRPC span reques + 144 0 1 0 0.00% 0.00% 0.00% 0 HRPC system post + 145 0 1 0 0.00% 0.00% 0.00% 0 Hulc Reload Mana + 146 0 1 0 0.00% 0.00% 0.00% 0 HRPC hrcli-event + 147 0 2 0 0.00% 0.00% 0.00% 0 image mgr + 148 895 277979 3 0.00% 0.00% 0.00% 0 HULC Pilsner The + 149 58605 16564360 3 0.00% 0.00% 0.00% 0 PI MATM Aging Pr + 150 0 2 0 0.00% 0.00% 0.00% 0 Switch Backup In + 151 182 277959 0 0.00% 0.00% 0.00% 0 MMN bkgrd proces + 152 20949 16250853 1 0.00% 0.00% 0.00% 0 Auth Manager + 153 0 1 0 0.00% 0.00% 0.00% 0 AUTH POLICY Fram + 154 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Mgr Proces + 155 142268 12544 11341 0.00% 0.00% 0.00% 0 802.1x switch + 156 0 1 0 0.00% 0.00% 0.00% 0 802.1x Webauth F + 157 6464 1667546 3 0.00% 0.00% 0.00% 0 DTP Protocol + 158 0 1 0 0.00% 0.00% 0.00% 0 EAP Framework + 159 0 1 0 0.00% 0.00% 0.00% 0 EAP Test + 160 0 1 0 0.00% 0.00% 0.00% 0 HRPC IPv6 Host r + 161 0 2 0 0.00% 0.00% 0.00% 0 IPv6 Platform Ho + 162 0 1 0 0.00% 0.00% 0.00% 0 HRPC dai request + 163 2060989 7151117 288 0.00% 0.00% 0.00% 0 HULC DAI Process + 164 0 1 0 0.00% 0.00% 0.00% 0 HRPC ip device t + 165 0 1 0 0.00% 0.00% 0.00% 0 HRPC ip source g + 166 0 1 0 0.00% 0.00% 0.00% 0 HULC IP Source g + 167 37411 166652517 0 0.00% 0.00% 0.00% 0 UDLD + 168 341 555955 0 0.00% 0.00% 0.00% 0 Port-Security + 169 3941 8361 471 0.00% 0.00% 0.00% 0 IP Host Track Pr + 170 0 1 0 0.00% 0.00% 0.00% 0 Link State Group + 171 1673 6271 266 0.00% 0.00% 0.00% 0 VMATM Callback + 172 0 2 0 0.00% 0.00% 0.00% 0 CMD HANDLER + 173 0 2 0 0.00% 0.00% 0.00% 0 CEF switching ba + 174 0 1 0 0.00% 0.00% 0.00% 0 ADJ NSF process + 175 0 1 0 0.00% 0.00% 0.00% 0 HRPC sisf reques + 176 0 2 0 0.00% 0.00% 0.00% 0 HULC SISF Proces + 177 0 1 0 0.00% 0.00% 0.00% 0 HULC SISF Source + 178 0 171 0 0.00% 0.00% 0.00% 0 AAA Server + 179 8286 32674 253 0.00% 0.00% 0.00% 0 AAA ACCT Proc + 180 0 1 0 0.00% 0.00% 0.00% 0 ACCT Periodic Pr + 181 0 1 0 0.00% 0.00% 0.00% 0 AAA System Acct + 182 0 1 0 0.00% 0.00% 0.00% 0 Auth-proxy AAA B + 183 74 55596 1 0.00% 0.00% 0.00% 0 IP Admin SM Proc + 184 45733 2643616 17 0.00% 0.00% 0.00% 0 CDP Protocol + 185 719 2095 343 0.00% 0.00% 0.00% 0 SpanTree Flush + 186 0 13113 0 0.00% 0.00% 0.00% 0 Critical Auth + 187 0 2 0 0.00% 0.00% 0.00% 0 AAA Dictionary R + 188 184 138989 1 0.00% 0.00% 0.00% 0 DHCP Snooping + 189 0 1 0 0.00% 0.00% 0.00% 0 DHCP Snooping db + 190 17 249 68 0.00% 0.00% 0.00% 0 IP ARP Adjacency + 191 301220 494966993 0 0.00% 0.00% 0.00% 0 IP ARP Retry Age + 192 2140263 8161932 262 0.00% 0.01% 0.02% 0 IP Input + 193 0 1 0 0.00% 0.00% 0.00% 0 ICMP event handl + 194 12564 32182298 0 0.00% 0.00% 0.00% 0 IP ARP Track + 195 0 1 0 0.00% 0.00% 0.00% 0 IPv6 ping proces + 196 32067 15112649 2 0.00% 0.00% 0.00% 0 NTP + 197 0 13 0 0.00% 0.00% 0.00% 0 SMI Director DB + 198 0 244 0 0.00% 0.00% 0.00% 0 SMI CDP Update H + 199 0 1 0 0.00% 0.00% 0.00% 0 SMI Backup Proce + 200 0 2 0 0.00% 0.00% 0.00% 0 SMI IBC server p + 201 0 1 0 0.00% 0.00% 0.00% 0 SMI IBC client p + 202 0 2 0 0.00% 0.00% 0.00% 0 SMI IBC Download + 203 2851721 57269407 49 0.00% 0.00% 0.00% 0 Spanning Tree + 204 82 277963 0 0.00% 0.00% 0.00% 0 Spanning Tree St + 205 1090 1666774 0 0.00% 0.00% 0.00% 0 Ethchnl + 206 235 4846 48 0.15% 0.01% 0.00% 0 TCP Timer + 207 25 108 231 0.00% 0.00% 0.00% 0 TCP Protocols + 208 0 1 0 0.00% 0.00% 0.00% 0 Socket Timers + 209 118 55605 2 0.00% 0.00% 0.00% 0 HTTP CORE + 210 132 208479 0 0.00% 0.00% 0.00% 0 Cluster L2 + 211 1309 1666772 0 0.00% 0.00% 0.00% 0 Cluster RARP + 212 1979 2084109 0 0.00% 0.00% 0.00% 0 Cluster Base + 213 790 338380 2 0.00% 0.00% 0.00% 0 CEF background p + 214 0 1 0 0.00% 0.00% 0.00% 0 fib_fib_bfd_sb e + 215 0 1 0 0.00% 0.00% 0.00% 0 IP IRDP + 216 0 3 0 0.00% 0.00% 0.00% 0 RARP Input + 217 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Supplicant + 218 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Supplicant + 219 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Supplicant + 220 0 1 0 0.00% 0.00% 0.00% 0 MAB Framework + 221 0 1 0 0.00% 0.00% 0.00% 0 HRPC dhcp snoopi + 222 0 4 0 0.00% 0.00% 0.00% 0 HULC DHCP Snoopi + 223 1053 8884 118 0.00% 0.00% 0.00% 0 IGMPSN L2MCM + 224 0 1 0 0.00% 0.00% 0.00% 0 IGMPSN MRD + 225 110843 271956 407 0.00% 0.00% 0.00% 0 IGMPSN + 226 0 1 0 0.00% 0.00% 0.00% 0 IGMPQR + 227 8 3 2666 0.00% 0.00% 0.00% 0 L2TRACE SERVER + 228 1322 8881 148 0.00% 0.00% 0.00% 0 MLDSN L2MCM + 229 0 1 0 0.00% 0.00% 0.00% 0 MRD + 230 0 1 0 0.00% 0.00% 0.00% 0 MLD_SNOOP + 231 0 2 0 0.00% 0.00% 0.00% 0 Routing Topology + 232 75632 25899567 2 0.00% 0.00% 0.00% 0 CEF: IPv4 proces + 233 0 2 0 0.00% 0.00% 0.00% 0 ADJ background + 234 0 3 0 0.00% 0.00% 0.00% 0 ADJ resolve proc + 235 26 7 3714 0.00% 0.00% 0.00% 0 IP RIB Update + 236 0 7 0 0.00% 0.00% 0.00% 0 Collection proce + 237 323 9268 34 0.00% 0.00% 0.00% 0 NIST rng proc + 238 0 6 0 0.00% 0.00% 0.00% 0 static + 239 0 1 0 0.00% 0.00% 0.00% 0 IPv6 RIB Event H + 240 3504 1666772 2 0.00% 0.00% 0.00% 0 QoS stats proces + 241 0 14 0 0.00% 0.00% 0.00% 0 SNMP Timers + 242 0 2 0 0.00% 0.00% 0.00% 0 TPLUS + 243 35 92660 0 0.00% 0.00% 0.00% 0 HCMP sync proces + 244 0 1 0 0.00% 0.00% 0.00% 0 EPM MAIN PROCESS + 245 0 2 0 0.00% 0.00% 0.00% 0 AAA Cached Serve + 246 168 987 170 0.00% 0.00% 0.00% 0 LOCAL AAA + 247 0 2 0 0.00% 0.00% 0.00% 0 ENABLE AAA + 248 0 2 0 0.00% 0.00% 0.00% 0 LINE AAA + 249 0 3 0 0.00% 0.00% 0.00% 0 LDAP process + 250 2225160 7746493 287 0.00% 0.00% 0.00% 0 IP SNMP + 251 0 1 0 0.00% 0.00% 0.00% 0 HRPC hl2mcm igmp + 252 0 1 0 0.00% 0.00% 0.00% 0 HRPC hl2mcm mlds + 253 0 1 0 0.00% 0.00% 0.00% 0 HRPC x_setup req + 254 0 2 0 0.00% 0.00% 0.00% 0 crypto engine pr + 255 0 1 0 0.00% 0.00% 0.00% 0 encrypt proc + 256 226 4 56500 0.00% 0.00% 0.00% 0 Crypto CA + 257 0 1 0 0.00% 0.00% 0.00% 0 Crypto PKI-CRL + 258 0 84 0 0.00% 0.00% 0.00% 0 VTP Trap Process + 259 324 27686 11 0.00% 0.00% 0.00% 0 ASP Process Crea + 260 0 2 0 0.00% 0.00% 0.00% 0 DHCP Security He + 261 0 1 0 0.00% 0.00% 0.00% 0 HCD Process + 262 0 1 0 0.00% 0.00% 0.00% 0 HRPC cable diagn + 263 539444 3871826 139 0.00% 0.00% 0.00% 0 PDU DISPATCHER + 264 20304 17313372 1 0.00% 0.00% 0.00% 0 PM Callback + 265 329 1333536 0 0.00% 0.00% 0.00% 0 dhcp snooping sw + 266 0 2 0 0.00% 0.00% 0.00% 0 DiagCard1/-1 + 267 1542 29621 52 0.00% 0.00% 0.00% 0 AAA SEND STOP EV + 268 0 1 0 0.00% 0.00% 0.00% 0 Test AAA Client + 269 0 1 0 0.00% 0.00% 0.00% 0 Syslog Traps + 270 862 277959 3 0.00% 0.00% 0.00% 0 RADIUS IO STATS + 271 0 1 0 0.00% 0.00% 0.00% 0 Online Diag EEM + 272 17 29 586 0.00% 0.00% 0.00% 0 EEM Server + 273 0 2 0 0.00% 0.00% 0.00% 0 EEM Policy Direc + 274 6622343 3871987 1710 0.00% 0.00% 0.04% 0 SNMP ENGINE + 275 0 2 0 0.00% 0.00% 0.00% 0 EEM ED OIR + 276 519 434771 1 0.00% 0.00% 0.00% 0 EEM ED Timer + 277 169 26358 6 0.00% 0.00% 0.00% 0 Syslog + 278 0 2 0 0.00% 0.00% 0.00% 0 STP FAST TRANSIT + 279 0 2 0 0.00% 0.00% 0.00% 0 CSRT RAPID TRANS + 280 16 2 8000 0.00% 0.00% 0.00% 0 Call Home proces + 281 0 2 0 0.00% 0.00% 0.00% 0 EEM ED Test + 282 0 3 0 0.00% 0.00% 0.00% 0 EEM ED Config + 283 0 3 0 0.00% 0.00% 0.00% 0 EEM ED Env + 284 0 3 0 0.00% 0.00% 0.00% 0 EM ED GOLD + 285 25 29 862 0.00% 0.00% 0.00% 0 VLAN Manager + 286 236 277959 0 0.00% 0.00% 0.00% 0 Call Home Timer + 287 8 4635 1 0.00% 0.00% 0.00% 0 SSH Event handle + 288 8 1 8000 0.00% 0.00% 0.00% 0 IP SNMPV6 + 289 0 1 0 0.00% 0.00% 0.00% 0 SNMP ConfCopyPro + 290 17 2843 5 0.00% 0.00% 0.00% 0 SNMP Traps + 291 1107 200 5535 0.00% 0.30% 0.24% 2 SSH Process + 294 0 3 0 0.00% 0.00% 0.00% 0 RADIUS POD SERVE + 295 340 286318 1 0.00% 0.00% 0.00% 0 IP Background + 296 52 12500 4 0.00% 0.00% 0.00% 0 IP Connected Rou + 297 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Authentica + 298 0 2 0 0.00% 0.00% 0.00% 0 Dot1x Authentica + 300 23889 3909607 6 0.00% 0.00% 0.00% 0 LLDP Protocol + 302 12657 195517 64 0.00% 0.00% 0.00% 0 RADIUS diff --git a/test/unit/mocked_data/test_get_facts/normal/expected_result.json b/test/unit/mocked_data/test_get_facts/normal/expected_result.json new file mode 100644 index 0000000..014e678 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/expected_result.json @@ -0,0 +1,10 @@ +{ + "os_version": "C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1)", + "uptime": 16676160, + "interface_list": ["Vlan1", "Vlan20", "Vlan40", "Vlan41", "GigabitEthernet0/1", "GigabitEthernet0/2", "GigabitEthernet0/3", "GigabitEthernet0/4", "GigabitEthernet0/5", "GigabitEthernet0/6", "GigabitEthernet0/7", "GigabitEthernet0/8", "Port-channel1"], + "vendor": "Cisco", + "serial_number": "FOC1308V5NB", + "model": "WS-C2960G-8TC-L", + "hostname": "NS2903-ASW-01", + "fqdn": "NS2903-ASW-01.int.ogenstad.com" +} diff --git a/test/unit/mocked_data/test_get_facts/normal/show_hosts.txt b/test/unit/mocked_data/test_get_facts/normal/show_hosts.txt new file mode 100644 index 0000000..1bf1c5e --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/show_hosts.txt @@ -0,0 +1,7 @@ +Default domain is int.ogenstad.com +Name/address lookup uses static mappings + +Codes: u - unknown, e - expired, * - OK, ? - revalidate + t - temporary, p - permanent + +Host Port Flags Age Type Address(es) diff --git a/test/unit/mocked_data/test_get_facts/normal/show_ip_interface_brief.txt b/test/unit/mocked_data/test_get_facts/normal/show_ip_interface_brief.txt new file mode 100644 index 0000000..124222b --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/show_ip_interface_brief.txt @@ -0,0 +1,14 @@ +Interface IP-Address OK? Method Status Protocol +Vlan1 unassigned YES NVRAM administratively down down +Vlan20 172.29.50.3 YES NVRAM up up +Vlan40 unassigned YES unset up up +Vlan41 172.29.52.34 YES NVRAM up up +GigabitEthernet0/1 unassigned YES unset up up +GigabitEthernet0/2 unassigned YES unset up up +GigabitEthernet0/3 unassigned YES unset up up +GigabitEthernet0/4 unassigned YES unset down down +GigabitEthernet0/5 unassigned YES unset up up +GigabitEthernet0/6 unassigned YES unset up up +GigabitEthernet0/7 unassigned YES unset up up +GigabitEthernet0/8 unassigned YES unset up up +Port-channel1 unassigned YES unset administratively down down diff --git a/test/unit/mocked_data/test_get_facts/normal/show_version.txt b/test/unit/mocked_data/test_get_facts/normal/show_version.txt new file mode 100644 index 0000000..bc64acd --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/show_version.txt @@ -0,0 +1,59 @@ +Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1) +Technical Support: http://www.cisco.com/techsupport +Copyright (c) 1986-2013 by Cisco Systems, Inc. +Compiled Wed 26-Jun-13 02:49 by prod_rel_team + +ROM: Bootstrap program is C2960 boot loader +BOOTLDR: C2960 Boot Loader (C2960-HBOOT-M) Version 12.2(35r)SE2, RELEASE SOFTWARE (fc1) + +NS2903-ASW-01 uptime is 27 weeks, 4 days, 16 minutes +System returned to ROM by power-on +System restarted at 15:46:58 UTC Sun May 22 2016 +System image file is "flash:/c2960-lanbasek9-mz.150-2.SE4.bin" + + +This product contains cryptographic features and is subject to United +States and local country laws governing import, export, transfer and +use. Delivery of Cisco cryptographic products does not imply +third-party authority to import, export, distribute or use encryption. +Importers, exporters, distributors and users are responsible for +compliance with U.S. and local country laws. By using this product you +agree to comply with applicable laws and regulations. If you are unable +to comply with U.S. and local laws, return this product immediately. + +A summary of U.S. laws governing Cisco cryptographic products may be found at: +http://www.cisco.com/wwl/export/crypto/tool/stqrg.html + +If you require further assistance please contact us by sending email to +export@cisco.com. + +cisco WS-C2960G-8TC-L (PowerPC405) processor (revision A0) with 65536K bytes of memory. +Processor board ID FOC1308V5NB +Last reset from power-on +4 Virtual Ethernet interfaces +8 Gigabit Ethernet interfaces +The password-recovery mechanism is enabled. + +64K bytes of flash-simulated non-volatile configuration memory. +Base ethernet MAC Address : 00:24:F7:DD:77:00 +Motherboard assembly number : 73-10613-08 +Power supply part number : 341-0208-01 +Motherboard serial number : FOC13083EGE +Power supply serial number : LIT1250099N +Model revision number : A0 +Motherboard revision number : B0 +Model number : WS-C2960G-8TC-L +System serial number : FOC1308V5NB +Top Assembly Part Number : 800-28133-01 +Top Assembly Revision Number : E0 +Version ID : V01 +CLEI Code Number : COM7S00ARA +Hardware Board Revision Number : 0x01 + + +Switch Ports Model SW Version SW Image +------ ----- ----- ---------- ---------- +* 1 8 WS-C2960G-8TC-L 15.0(2)SE4 C2960-LANBASEK9-M + + +Configuration register is 0xF diff --git a/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json b/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json new file mode 100644 index 0000000..706c2b9 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/expected_result.json @@ -0,0 +1,26 @@ +{ + "GigabitEthernet3": { + "speed": 1000, + "mac_address": "0800.2782.516b", + "is_up": false, + "last_flapped": -1.0, + "description": "N/A", + "is_enabled": false + }, + "GigabitEthernet2": { + "speed": 1000, + "mac_address": "0800.2779.e896", + "is_up": true, + "last_flapped": -1.0, + "description": "blah bleh", + "is_enabled": true + }, + "GigabitEthernet1": { + "speed": 1000, + "mac_address": "0800.27f8.e842", + "is_up": true, + "last_flapped": -1.0, + "description": "N/A", + "is_enabled": true + } +} diff --git a/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet1.txt b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet1.txt new file mode 100644 index 0000000..2b6cdc9 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet1.txt @@ -0,0 +1,28 @@ +GigabitEthernet1 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.27f8.e842 (bia 0800.27f8.e842) + Internet address is 10.0.2.15/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:42:01, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 1000 bits/sec, 1 packets/sec + 5 minute output rate 1000 bits/sec, 1 packets/sec + 14028 packets input, 1766902 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 9446 packets output, 1379617 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out diff --git a/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet2.txt b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet2.txt new file mode 100644 index 0000000..ef18819 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet2.txt @@ -0,0 +1,30 @@ +GigabitEthernet2 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.2779.e896 (bia 0800.2779.e896) + Description: blah bleh + Internet address is 192.168.0.1/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:00:04, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 118 packets input, 11502 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 177 packets output, 19267 bytes, 0 underruns + 0 output errors, 0 collisions, 1 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out + diff --git a/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet3.txt b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet3.txt new file mode 100644 index 0000000..206548d --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/show_interface_GigabitEthernet3.txt @@ -0,0 +1,27 @@ +GigabitEthernet3 is administratively down, line protocol is down + Hardware is CSR vNIC, address is 0800.2782.516b (bia 0800.2782.516b) + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input never, output never, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 0 packets input, 0 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 3 packets output, 258 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out diff --git a/test/unit/mocked_data/test_get_interfaces/normal/show_ip_interface_brief.txt b/test/unit/mocked_data/test_get_interfaces/normal/show_ip_interface_brief.txt new file mode 100644 index 0000000..5373f48 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/show_ip_interface_brief.txt @@ -0,0 +1,4 @@ +Interface IP-Address OK? Method Status Protocol +GigabitEthernet1 10.0.2.15 YES DHCP up up +GigabitEthernet2 192.168.0.1 YES manual up up +GigabitEthernet3 unassigned YES unset administratively down down diff --git a/test/unit/mocked_data/test_get_interfaces_counters/normal/expected_result.json b/test/unit/mocked_data/test_get_interfaces_counters/normal/expected_result.json new file mode 100644 index 0000000..65e00a0 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_counters/normal/expected_result.json @@ -0,0 +1,44 @@ +{ + "GigabitEthernet1": { + "tx_discards": -1, + "tx_broadcast_packets": -1, + "rx_multicast_packets": 0, + "tx_unicast_packets": 9297, + "rx_octets": 2, + "rx_broadcast_packets": 0, + "rx_errors": 0, + "tx_octets": 1, + "rx_discards": -1, + "tx_multicast_packets": -1, + "tx_errors": 0, + "rx_unicast_packets": 13799 + }, + "GigabitEthernet2": { + "tx_discards": -1, + "tx_broadcast_packets": -1, + "rx_multicast_packets": 0, + "tx_unicast_packets": 154, + "rx_octets": 3, + "rx_broadcast_packets": 0, + "rx_errors": 0, + "tx_octets": 7, + "rx_discards": -1, + "tx_multicast_packets": -1, + "tx_errors": 0, + "rx_unicast_packets": 105 + }, + "GigabitEthernet3": { + "tx_discards": -1, + "tx_broadcast_packets": -1, + "rx_multicast_packets": 0, + "tx_unicast_packets": 3, + "rx_octets": 0, + "rx_broadcast_packets": 0, + "rx_errors": 0, + "tx_octets": 8, + "rx_discards": -1, + "tx_multicast_packets": -1, + "tx_errors": 0, + "rx_unicast_packets": 0 + } +} diff --git a/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces.txt b/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces.txt new file mode 100644 index 0000000..67ce552 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces.txt @@ -0,0 +1,83 @@ +GigabitEthernet1 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.27f8.e842 (bia 0800.27f8.e842) + Internet address is 10.0.2.15/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:39:57, output 00:00:00, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 1000 bits/sec, 1 packets/sec + 5 minute output rate 1000 bits/sec, 1 packets/sec + 13799 packets input, 1748592 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 9297 packets output, 1355261 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out +GigabitEthernet2 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.2779.e896 (bia 0800.2779.e896) + Internet address is 192.168.0.1/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:00:25, output 00:00:04, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 105 packets input, 10383 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 154 packets output, 16467 bytes, 0 underruns + 0 output errors, 0 collisions, 1 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out +GigabitEthernet3 is administratively down, line protocol is down + Hardware is CSR vNIC, address is 0800.2782.516b (bia 0800.2782.516b) + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input never, output never, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 0 packets input, 0 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 3 packets output, 258 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json b/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json new file mode 100644 index 0000000..cbc1e60 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/expected_result.json @@ -0,0 +1,19 @@ +{ + "Vlan20": { + "ipv4": { + "172.29.50.3": { + "prefix_length": 27 + } + } + }, + "Vlan41": { + "ipv4": { + "172.29.52.34": { + "prefix_length": 27 + }, + "192.168.81.34": { + "prefix_length": 24 + } + } + } +} diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_ip_interface_brief.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_ip_interface_brief.txt new file mode 100644 index 0000000..804c8db --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_ip_interface_brief.txt @@ -0,0 +1,6 @@ +Interface IP-Address OK? Method Status Protocol +Vlan20 172.29.50.3 YES NVRAM up up +Vlan40 unassigned YES unset up up +Vlan41 172.29.52.34 YES NVRAM up up +GigabitEthernet0/5 unassigned YES unset up up +Port-channel1 unassigned YES unset administratively down down diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_GigabitEthernet0_5.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_GigabitEthernet0_5.txt new file mode 100644 index 0000000..99c588d --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_GigabitEthernet0_5.txt @@ -0,0 +1,8 @@ +Building configuration... + +Current configuration : 87 bytes +! +interface GigabitEthernet0/5 + switchport access vlan 41 + switchport mode access +end diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Port_channel1.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Port_channel1.txt new file mode 100644 index 0000000..5fbb78a --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Port_channel1.txt @@ -0,0 +1,7 @@ +Building configuration... + +Current configuration : 41 bytes +! +interface Port-channel1 + shutdown +end diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan20.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan20.txt new file mode 100644 index 0000000..27e1039 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan20.txt @@ -0,0 +1,7 @@ +Building configuration... + +Current configuration : 64 bytes +! +interface Vlan20 + ip address 172.29.50.3 255.255.255.224 +end diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan40.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan40.txt new file mode 100644 index 0000000..e4abaed --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan40.txt @@ -0,0 +1,7 @@ +Building configuration... + +Current configuration : 39 bytes +! +interface Vlan40 + no ip address +end diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan41.txt b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan41.txt new file mode 100644 index 0000000..10868c6 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_run_interface_Vlan41.txt @@ -0,0 +1,8 @@ +Building configuration... + +Current configuration : 115 bytes +! +interface Vlan41 + ip address 192.168.81.34 255.255.255.0 secondary + ip address 172.29.52.34 255.255.255.224 +end diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json new file mode 100644 index 0000000..444ecce --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/expected_result.json @@ -0,0 +1,10 @@ +{ + "GigabitEthernet1": [{ + "port": "17", + "hostname": "twb-sf-hpsw1" + }], + "GigabitEthernet2": [{ + "port": "18", + "hostname": "twb-sf-hpsw2" + }] +} diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi1.txt b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi1.txt new file mode 100644 index 0000000..2b6cdc9 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi1.txt @@ -0,0 +1,28 @@ +GigabitEthernet1 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.27f8.e842 (bia 0800.27f8.e842) + Internet address is 10.0.2.15/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:42:01, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 1000 bits/sec, 1 packets/sec + 5 minute output rate 1000 bits/sec, 1 packets/sec + 14028 packets input, 1766902 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 9446 packets output, 1379617 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi2.txt b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi2.txt new file mode 100644 index 0000000..ef18819 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_int_Gi2.txt @@ -0,0 +1,30 @@ +GigabitEthernet2 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.2779.e896 (bia 0800.2779.e896) + Description: blah bleh + Internet address is 192.168.0.1/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:00:04, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 118 packets input, 11502 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 177 packets output, 19267 bytes, 0 underruns + 0 output errors, 0 collisions, 1 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out + diff --git a/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_lldp_neighbors.txt b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_lldp_neighbors.txt new file mode 100644 index 0000000..97cecaf --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors/normal/show_lldp_neighbors.txt @@ -0,0 +1,9 @@ +Capability codes: + (R) Router, (B) Bridge, (T) Telephone, (C) DOCSIS Cable Device + (W) WLAN Access Point, (P) Repeater, (S) Station, (O) Other + +Device ID Local Intf Hold-time Capability Port ID +twb-sf-hpsw1 Gi1 120 B 17 +twb-sf-hpsw2 Gi2 120 B 18 + +Total entries displayed: 2 diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json new file mode 100644 index 0000000..a6310b7 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/expected_result.json @@ -0,0 +1,22 @@ +{ + "GigabitEthernet2": [{ + "parent_interface": "N/A", + "remote_system_capab": "B", + "remote_system_description": "ProCurve J9019A Switch 2510-24, revision Q.10.01, ROM Q.10.02 (/sw/code/build/harp(harp))", + "remote_port": "18", + "remote_chassis_id": "0018.fe1e.b020", + "remote_system_name": "twb-sf-hpsw2", + "remote_system_enable_capab": "B", + "remote_port_description": "18" + }], + "GigabitEthernet1": [{ + "parent_interface": "N/A", + "remote_system_capab": "B", + "remote_system_description": "ProCurve J9019A Switch 2510-24, revision Q.10.01, ROM Q.10.02 (/sw/code/build/harp(harp))", + "remote_port": "17", + "remote_chassis_id": "0018.fe1e.b020", + "remote_system_name": "twb-sf-hpsw1", + "remote_system_enable_capab": "B", + "remote_port_description": "17" + }] +} diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi1.txt b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi1.txt new file mode 100644 index 0000000..2b6cdc9 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi1.txt @@ -0,0 +1,28 @@ +GigabitEthernet1 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.27f8.e842 (bia 0800.27f8.e842) + Internet address is 10.0.2.15/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:42:01, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 1000 bits/sec, 1 packets/sec + 5 minute output rate 1000 bits/sec, 1 packets/sec + 14028 packets input, 1766902 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 9446 packets output, 1379617 bytes, 0 underruns + 0 output errors, 0 collisions, 0 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi2.txt b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi2.txt new file mode 100644 index 0000000..ef18819 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_int_Gi2.txt @@ -0,0 +1,30 @@ +GigabitEthernet2 is up, line protocol is up + Hardware is CSR vNIC, address is 0800.2779.e896 (bia 0800.2779.e896) + Description: blah bleh + Internet address is 192.168.0.1/24 + MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec, + reliability 255/255, txload 1/255, rxload 1/255 + Encapsulation ARPA, loopback not set + Keepalive set (10 sec) + Full Duplex, 1000Mbps, link type is auto, media type is RJ45 + output flow-control is unsupported, input flow-control is unsupported + ARP type: ARPA, ARP Timeout 04:00:00 + Last input 00:00:04, output 00:00:05, output hang never + Last clearing of "show interface" counters never + Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0 + Queueing strategy: fifo + Output queue: 0/40 (size/max) + 5 minute input rate 0 bits/sec, 0 packets/sec + 5 minute output rate 0 bits/sec, 0 packets/sec + 118 packets input, 11502 bytes, 0 no buffer + Received 0 broadcasts (0 IP multicasts) + 0 runts, 0 giants, 0 throttles + 0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored + 0 watchdog, 0 multicast, 0 pause input + 177 packets output, 19267 bytes, 0 underruns + 0 output errors, 0 collisions, 1 interface resets + 0 unknown protocol drops + 0 babbles, 0 late collision, 0 deferred + 0 lost carrier, 0 no carrier, 0 pause output + 0 output buffer failures, 0 output buffers swapped out + diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors.txt b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors.txt new file mode 100644 index 0000000..53cc327 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors.txt @@ -0,0 +1,10 @@ +Capability codes: + (R) Router, (B) Bridge, (T) Telephone, (C) DOCSIS Cable Device + (W) WLAN Access Point, (P) Repeater, (S) Station, (O) Other + +Device ID Local Intf Hold-time Capability Port ID +twb-sf-hpsw1 Gi1 120 B 17 +twb-sf-hpsw2 Gi2 120 B 18 + +Total entries displayed: 2 + diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet1_detail.txt b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet1_detail.txt new file mode 100644 index 0000000..b09ba0d --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet1_detail.txt @@ -0,0 +1,22 @@ +------------------------------------------------ +Chassis id: 0018.fe1e.b020 +Port id: 17 +Port Description: 17 +System Name: twb-sf-hpsw1 + +System Description: +ProCurve J9019A Switch 2510-24, revision Q.10.01, ROM Q.10.02 (/sw/code/build/harp(harp)) + +Time remaining: 93 seconds +System Capabilities: B +Enabled Capabilities: B +Management Addresses: + IP: 10.220.88.10 +Auto Negotiation - not supported +Physical media capabilities - not advertised +Media Attachment Unit type - not advertised +Vlan ID: - not advertised + + +Total entries displayed: 1 + diff --git a/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet2_detail.txt b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet2_detail.txt new file mode 100644 index 0000000..17b9ab0 --- /dev/null +++ b/test/unit/mocked_data/test_get_lldp_neighbors_detail/normal/show_lldp_neighbors_GigabitEthernet2_detail.txt @@ -0,0 +1,22 @@ +------------------------------------------------ +Chassis id: 0018.fe1e.b020 +Port id: 18 +Port Description: 18 +System Name: twb-sf-hpsw2 + +System Description: +ProCurve J9019A Switch 2510-24, revision Q.10.01, ROM Q.10.02 (/sw/code/build/harp(harp)) + +Time remaining: 93 seconds +System Capabilities: B +Enabled Capabilities: B +Management Addresses: + IP: 10.220.88.11 +Auto Negotiation - not supported +Physical media capabilities - not advertised +Media Attachment Unit type - not advertised +Vlan ID: - not advertised + + +Total entries displayed: 1 + diff --git a/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json new file mode 100644 index 0000000..ed12c29 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/normal/expected_result.json @@ -0,0 +1,153 @@ +[{ + "static": false, + "active": true, + "vlan": 1, + "mac": "6400.f1cf.2cc6", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 1, + "mac": "a493.4cc1.67a7", + "interface": "Vlan1", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "000c.2906.17d6", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "000c.2913.421b", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0018.0ab3.59f1", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0018.dd32.1f7c", + "interface": "FastEthernet6", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0025.64f5.d352", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0026.abb9.a503", + "interface": "FastEthernet4", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 100, + "mac": "a493.4cc1.67a7", + "interface": "Vlan100", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "ac3a.7a1a.ba4b", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "b0a7.376f.b3b4", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "bc5f.f435.fa0e", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "dc3a.5e67.1a98", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "dc3a.5ee2.6a95", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "f04f.7c92.5a45", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "0009.b754.1a88", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "10bd.1801.a0b4", + "interface": "FastEthernet3", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "204c.9ed7.cb80", + "interface": "FastEthernet2", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 200, + "mac": "a493.4cc1.67a7", + "interface": "Vlan200", + "moves": -1, + "last_move": -1.0 +}] diff --git a/test/unit/mocked_data/test_get_mac_address_table/normal/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/normal/show_mac_address_table.txt new file mode 100644 index 0000000..c4123f1 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/normal/show_mac_address_table.txt @@ -0,0 +1,21 @@ +Destination Address Address Type VLAN Destination Port +------------------- ------------ ---- -------------------- +6400.f1cf.2cc6 Dynamic 1 Wlan-GigabitEthernet0 +a493.4cc1.67a7 Self 1 Vlan1 +000c.2906.17d6 Dynamic 100 FastEthernet7 +000c.2913.421b Dynamic 100 FastEthernet7 +0018.0ab3.59f1 Dynamic 100 FastEthernet7 +0018.dd32.1f7c Dynamic 100 FastEthernet6 +0025.64f5.d352 Dynamic 100 FastEthernet7 +0026.abb9.a503 Dynamic 100 FastEthernet4 +a493.4cc1.67a7 Self 100 Vlan100 +ac3a.7a1a.ba4b Dynamic 100 Wlan-GigabitEthernet0 +b0a7.376f.b3b4 Dynamic 100 FastEthernet7 +bc5f.f435.fa0e Dynamic 100 FastEthernet7 +dc3a.5e67.1a98 Dynamic 100 FastEthernet7 +dc3a.5ee2.6a95 Dynamic 100 Wlan-GigabitEthernet0 +f04f.7c92.5a45 Dynamic 100 Wlan-GigabitEthernet0 +0009.b754.1a88 Dynamic 200 FastEthernet7 +10bd.1801.a0b4 Dynamic 200 FastEthernet3 +204c.9ed7.cb80 Dynamic 200 FastEthernet2 +a493.4cc1.67a7 Self 200 Vlan200 diff --git a/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json b/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json new file mode 100644 index 0000000..e66f88e --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_servers/normal/expected_result.json @@ -0,0 +1,6 @@ +{ + "2001:DB8:0:0:8:800:200C:417A": {}, + "17.72.148.53": {}, + "192.168.0.1": {}, + "37.187.56.220": {} +} diff --git a/test/unit/mocked_data/test_get_ntp_servers/normal/show_run___include_ntp_server.txt b/test/unit/mocked_data/test_get_ntp_servers/normal/show_run___include_ntp_server.txt new file mode 100644 index 0000000..3eb59b5 --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_servers/normal/show_run___include_ntp_server.txt @@ -0,0 +1,4 @@ +ntp server 192.168.0.1 prefer +ntp server 17.72.148.53 +ntp server vrf NAPALM 37.187.56.220 +ntp server 2001:DB8:0:0:8:800:200C:417A version 4 diff --git a/test/unit/mocked_data/test_get_ntp_stats/normal/expected_result.json b/test/unit/mocked_data/test_get_ntp_stats/normal/expected_result.json new file mode 100644 index 0000000..5b8431a --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_stats/normal/expected_result.json @@ -0,0 +1,13 @@ +[{ + "jitter": 18.659, + "synchronized": true, + "offset": 0.122, + "referenceid": "83.168.200.199", + "remote": "172.29.50.34", + "reachability": 377, + "when": "54", + "delay": 1.186, + "hostpoll": 1024, + "stratum": 3, + "type": "-" +}] diff --git a/test/unit/mocked_data/test_get_ntp_stats/normal/show_ntp_associations.txt b/test/unit/mocked_data/test_get_ntp_stats/normal/show_ntp_associations.txt new file mode 100644 index 0000000..67a1a3e --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_stats/normal/show_ntp_associations.txt @@ -0,0 +1,4 @@ + + address ref clock st when poll reach delay offset disp +*~172.29.50.34 83.168.200.199 3 54 1024 377 1.186 0.122 18.659 + * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured diff --git a/test/unit/mocked_data/test_get_snmp_information/normal/expected_result.json b/test/unit/mocked_data/test_get_snmp_information/normal/expected_result.json new file mode 100644 index 0000000..1dbc51a --- /dev/null +++ b/test/unit/mocked_data/test_get_snmp_information/normal/expected_result.json @@ -0,0 +1,23 @@ +{ + "location": "123 Anytown USA Rack 404", + "community": { + "public": { + "acl": "11", + "mode": "ro" + }, + "private": { + "acl": "12", + "mode": "rw" + }, + "public_named_acl": { + "acl": "ALLOW-SNMP-ACL", + "mode": "ro" + }, + "public_no_acl": { + "acl": "N/A", + "mode": "ro" + } + }, + "chassis_id": "Asset Tag 54670", + "contact": "Config rev 028" +} diff --git a/test/unit/mocked_data/test_get_snmp_information/normal/show_run___include_snmp_server.txt b/test/unit/mocked_data/test_get_snmp_information/normal/show_run___include_snmp_server.txt new file mode 100644 index 0000000..fefa94f --- /dev/null +++ b/test/unit/mocked_data/test_get_snmp_information/normal/show_run___include_snmp_server.txt @@ -0,0 +1,7 @@ +snmp-server community public RO 11 +snmp-server community private RW 12 +snmp-server community public_no_acl RO +snmp-server community public_named_acl RO ALLOW-SNMP-ACL +snmp-server location 123 Anytown USA Rack 404 +snmp-server contact Config rev 028 +snmp-server chassis-id Asset Tag 54670 \ No newline at end of file diff --git a/test/unit/mocked_data/test_is_alive/normal/expected_result.json b/test/unit/mocked_data/test_is_alive/normal/expected_result.json new file mode 100644 index 0000000..22d3fb2 --- /dev/null +++ b/test/unit/mocked_data/test_is_alive/normal/expected_result.json @@ -0,0 +1,3 @@ +{ + "is_alive": true +} diff --git a/test/unit/mocked_data/test_ping/normal/expected_result.json b/test/unit/mocked_data/test_ping/normal/expected_result.json new file mode 100644 index 0000000..4bcefb7 --- /dev/null +++ b/test/unit/mocked_data/test_ping/normal/expected_result.json @@ -0,0 +1,26 @@ +{ + "success": { + "results": [{ + "ip_address": "8.8.8.8", + "rtt": 0.0 + }, { + "ip_address": "8.8.8.8", + "rtt": 0.0 + }, { + "ip_address": "8.8.8.8", + "rtt": 0.0 + }, { + "ip_address": "8.8.8.8", + "rtt": 0.0 + }, { + "ip_address": "8.8.8.8", + "rtt": 0.0 + }], + "rtt_avg": 1.0, + "packet_loss": 0, + "rtt_min": 1.0, + "rtt_max": 4.0, + "rtt_stddev": 0.0, + "probes_sent": 5 + } +} diff --git a/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_timeout_2_size_100_repeat_5.txt b/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_timeout_2_size_100_repeat_5.txt new file mode 100644 index 0000000..1ac0dc3 --- /dev/null +++ b/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_timeout_2_size_100_repeat_5.txt @@ -0,0 +1,5 @@ + +Type escape sequence to abort. +Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds: +!!!!! +Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/4 ms diff --git a/test/unit/test_getters.py b/test/unit/test_getters.py new file mode 100644 index 0000000..6156b91 --- /dev/null +++ b/test/unit/test_getters.py @@ -0,0 +1,13 @@ +"""Tests for getters.""" +from __future__ import print_function +from __future__ import unicode_literals + +from napalm_base.test.getters import BaseTestGetters + + +import pytest + + +@pytest.mark.usefixtures("set_device_parameters") +class TestGetter(BaseTestGetters): + """Test get_* methods.""" From 7d81c84dfec4156fcd10dfdebce75b67f44bfe0e Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 3 Dec 2016 09:01:54 -0800 Subject: [PATCH 17/41] Fix#74 - BGP getters issue with trailing newline --- napalm_ios/ios.py | 8 ++++++++ .../regex_strip/expected_result.json | 1 + ...p_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt | 1 + .../show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt | 1 + ...p_bgp_neighbors_192_168_0_2___section_Local_Policy.txt | 2 ++ ...p_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt | 1 + .../show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt | 1 + ...p_bgp_neighbors_192_168_0_3___section_Local_Policy.txt | 2 ++ .../regex_strip/show_ip_bgp_summary.txt | 7 +++++++ .../regex_strip/show_ip_bgp_summary___begin_Neighbor.txt | 4 ++++ 10 files changed, 28 insertions(+) create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/expected_result.json create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 6201d53..4a54d2e 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -30,6 +30,10 @@ WEEK_SECONDS = 7 * DAY_SECONDS YEAR_SECONDS = 365 * DAY_SECONDS +# IP addresses +IP_ADDR_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" +RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) + class IOSDriver(NetworkDriver): """NAPALM Cisco IOS Handler.""" @@ -899,6 +903,8 @@ def get_bgp_neighbors(self): bgp_neighbor_data['global'] = {} output = self.device.send_command(cmd_bgp_summary).strip() + # Cisco issue where new lines are inserted after neighbor IP + output = re.sub(RE_IPADDR_STRIP, r"\1", output) if 'Neighbor' not in output: return {} for line in output.splitlines(): @@ -914,6 +920,8 @@ def get_bgp_neighbors(self): cmd_neighbor_table = 'show ip bgp summary | begin Neighbor' output = self.device.send_command(cmd_neighbor_table).strip() + # Cisco issue where new lines are inserted after neighbor IP + output = re.sub(RE_IPADDR_STRIP, r"\1", output) for line in output.splitlines(): line = line.strip() if 'Neighbor' in line or line == '': diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/expected_result.json b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/expected_result.json new file mode 100644 index 0000000..424d220 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/expected_result.json @@ -0,0 +1 @@ +{"global": {"router_id": "192.168.0.1", "peers": {"192.168.0.2": {"is_enabled": true, "uptime": -1, "remote_as": 65001, "description": "", "remote_id": "0.0.0.0", "local_as": 65000, "is_up": false, "address_family": {"ipv4": {"sent_prefixes": 0, "accepted_prefixes": 0, "received_prefixes": 0} }}, "192.168.0.3": {"is_enabled": true, "uptime": -1, "remote_as": 65010, "description": "", "remote_id": "192.168.0.3", "local_as": 65000, "is_up": false, "address_family": {"ipv4": {"sent_prefixes": 0, "accepted_prefixes": 0, "received_prefixes": 0} }}}}} diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt new file mode 100644 index 0000000..f954dae --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_Prefixes_Current.txt @@ -0,0 +1 @@ + Prefixes Current: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt new file mode 100644 index 0000000..0e46fd0 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___inc_router_ID.txt @@ -0,0 +1 @@ + BGP version 4, remote router ID 0.0.0.0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt new file mode 100644 index 0000000..d40bb2b --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_2___section_Local_Policy.txt @@ -0,0 +1,2 @@ +Local Policy Denied Prefixes: -------- ------- + Total: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt new file mode 100644 index 0000000..f954dae --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_Prefixes_Current.txt @@ -0,0 +1 @@ + Prefixes Current: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt new file mode 100644 index 0000000..5095e78 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___inc_router_ID.txt @@ -0,0 +1 @@ + BGP version 4, remote router ID 192.168.0.3 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt new file mode 100644 index 0000000..d40bb2b --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_neighbors_192_168_0_3___section_Local_Policy.txt @@ -0,0 +1,2 @@ +Local Policy Denied Prefixes: -------- ------- + Total: 0 0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt new file mode 100644 index 0000000..7896ea2 --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt @@ -0,0 +1,7 @@ +BGP router identifier 192.168.0.1, local AS number 65000 +BGP table version is 1, main routing table version 1 + +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd +192.168.0.2 + 4 65001 0 0 1 0 0 never Idle +192.168.0.3 4 65010 0 0 1 0 0 never Active diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt new file mode 100644 index 0000000..1c9aaef --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt @@ -0,0 +1,4 @@ +Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd +192.168.0.2 + 4 65001 0 0 1 0 0 never Idle +192.168.0.3 4 65010 0 0 1 0 0 never Active From 1e2c7e946c6534645dd212718b816edbdaf382e6 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 3 Dec 2016 13:58:33 -0800 Subject: [PATCH 18/41] Adding a post processor to send_command --- napalm_ios/ios.py | 85 +++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 4a54d2e..068d7de 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -30,7 +30,7 @@ WEEK_SECONDS = 7 * DAY_SECONDS YEAR_SECONDS = 365 * DAY_SECONDS -# IP addresses +# IP Address IP_ADDR_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) @@ -113,6 +113,11 @@ def close(self): """Close the connection to the device.""" self.device.disconnect() + def _send_command(self, command): + """Wrapper for self.device.send.command()""" + output = self.device.send_command(command) + return self.send_command_postprocess(output) + def is_alive(self): """Returns a flag with the state of the SSH connection.""" return { @@ -401,11 +406,23 @@ def _expand_interface_name(self, interface_brief): else: return interface_brief + @staticmethod + def send_command_postprocess(output): + """ + Cleanup actions on send_command() for NAPALM getters. + + Remove "Load for five sec; one minute if in output" + Remove "Time source is" + """ + output = re.sub(r"^Load for five secs.*$", "", output, flags=re.M) + output = re.sub(r"^Time source is .*$", "", output, flags=re.M) + return output.strip() + def get_lldp_neighbors(self): """IOS implementation of get_lldp_neighbors.""" lldp = {} command = 'show lldp neighbors' - output = self.device.send_command(command) + output = self._send_command(command) # Check if router supports the command if '% Invalid input' in output: @@ -452,7 +469,7 @@ def pad_list_entries(my_list, list_length): for interface in lldp_neighbors: command = "show lldp neighbors {} detail".format(interface) - output = self.device.send_command(command) + output = self._send_command(command) # Check if router supports the command if '% Invalid input' in output: @@ -542,9 +559,9 @@ def get_facts(self): serial_number, fqdn, os_version, hostname = (u'Unknown', u'Unknown', u'Unknown', u'Unknown') # obtain output from device - show_ver = self.device.send_command('show version') - show_hosts = self.device.send_command('show hosts') - show_ip_int_br = self.device.send_command('show ip interface brief') + show_ver = self._send_command('show version') + show_hosts = self._send_command('show hosts') + show_ip_int_br = self._send_command('show ip interface brief') # uptime/serial_number/IOS version for line in show_ver.splitlines(): @@ -641,7 +658,7 @@ def get_interfaces(self): speed_regex = r".*BW\s(?P\d+)\s(?P\S+).*" command = 'show ip interface brief' - output = self.device.send_command(command) + output = self._send_command(command) for line in output.splitlines(): if 'Interface' in line and 'Status' in line: continue @@ -687,7 +704,7 @@ def get_interfaces(self): for interface in interface_list: show_command = "show interface {0}".format(interface) - interface_output = self.device.send_command(show_command) + interface_output = self._send_command(show_command) try: # description filter description = re.search(r" Description: (.+)", interface_output) @@ -745,7 +762,7 @@ def get_interfaces_ip(self): interfaces = {} command = 'show ip interface brief' - output = self.device.send_command(command) + output = self._send_command(command) for line in output.splitlines(): if 'Interface' in line and 'Status' in line: continue @@ -759,7 +776,7 @@ def get_interfaces_ip(self): # Parse IP Address and Subnet Mask from Interfaces for interface in interfaces: show_command = "show run interface {0}".format(interface) - interface_output = self.device.send_command(show_command) + interface_output = self._send_command(show_command) for line in interface_output.splitlines(): if 'ip address ' in line and 'no ip address' not in line: fields = line.split() @@ -767,7 +784,7 @@ def get_interfaces_ip(self): # Check for 'ip address dhcp', convert to ip address and mask if fields[2] == 'dhcp': cmd = "show interface {} | in Internet address is".format(interface) - show_int = self.device.send_command(cmd) + show_int = self._send_command(cmd) int_fields = show_int.split() ip_address, subnet = int_fields[3].split(r'/') interfaces[interface]['ipv4'] = {ip_address: {}} @@ -902,7 +919,7 @@ def get_bgp_neighbors(self): bgp_neighbor_data = {} bgp_neighbor_data['global'] = {} - output = self.device.send_command(cmd_bgp_summary).strip() + output = self._send_command(cmd_bgp_summary).strip() # Cisco issue where new lines are inserted after neighbor IP output = re.sub(RE_IPADDR_STRIP, r"\1", output) if 'Neighbor' not in output: @@ -919,7 +936,7 @@ def get_bgp_neighbors(self): bgp_neighbor_data['global']['peers'] = {} cmd_neighbor_table = 'show ip bgp summary | begin Neighbor' - output = self.device.send_command(cmd_neighbor_table).strip() + output = self._send_command(cmd_neighbor_table).strip() # Cisco issue where new lines are inserted after neighbor IP output = re.sub(RE_IPADDR_STRIP, r"\1", output) for line in output.splitlines(): @@ -949,7 +966,7 @@ def get_bgp_neighbors(self): cmd_remote_rid = 'show ip bgp neighbors {} | inc router ID'.format(peer_id) # output: BGP version 4, remote router ID 1.1.1.1 - remote_rid_out = self.device.send_command(cmd_remote_rid).strip() + remote_rid_out = self._send_command(cmd_remote_rid) remote_rid = remote_rid_out.split()[-1] bgp_neighbor_data['global']['peers'].setdefault(peer_id, {}) @@ -964,7 +981,7 @@ def get_bgp_neighbors(self): cmd_current_prefixes = 'show ip bgp neighbors {} | inc Prefixes Current'.format(peer_id) # output: Prefixes Current: 0 0 - current_prefixes_out = self.device.send_command(cmd_current_prefixes).strip() + current_prefixes_out = self._send_command(cmd_current_prefixes) pattern = r'Prefixes Current:\s+(\d+)\s+(\d+).*' # Prefixes Current: 0 0 match = re.search(pattern, current_prefixes_out) if match: @@ -978,7 +995,7 @@ def get_bgp_neighbors(self): # Local Policy Denied Prefixes: -------- ------- # prefix-list 0 2 # Total: 0 2 - filtered_prefixes_out = self.device.send_command(cmd_filtered_prefix).strip() + filtered_prefixes_out = self._send_command(cmd_filtered_prefix) sent_prefixes = int(sent_prefixes) pattern = r'Total:\s+\d+\s+(\d+).*' # Total: 0 2 match = re.search(pattern, filtered_prefixes_out) @@ -1022,8 +1039,7 @@ def get_interfaces_counters(self): """ counters = {} command = 'show interfaces' - output = self.device.send_command(command) - output = output.strip() + output = self._send_command(command) # Break output into per-interface sections interface_strings = re.split(r'.* line protocol is .*', output, flags=re.M) @@ -1098,8 +1114,7 @@ def get_environment(self): cpu_cmd = 'show proc cpu' mem_cmd = 'show memory statistics' - output = self.device.send_command(cpu_cmd) - output = output.strip() + output = self._send_command(cpu_cmd) environment.setdefault('cpu', {}) environment['cpu'][0] = {} environment['cpu'][0]['%usage'] = 0.0 @@ -1111,8 +1126,7 @@ def get_environment(self): environment['cpu'][0]['%usage'] = float(match.group(1)) break - output = self.device.send_command(mem_cmd) - output = output.strip() + output = self._send_command(mem_cmd) for line in output.splitlines(): if 'Processor' in line: _, _, _, proc_used_mem, proc_free_mem = line.split()[:5] @@ -1163,11 +1177,11 @@ def get_arp_table(self): arp_table = [] command = 'show arp | exclude Incomplete' - output = self.device.send_command(command) - output = output.split('\n') + output = self._send_command(command) # Skip the first line which is a header - output = output[1:-1] + output = output.split('\n') + output = output[1:] for line in output: if len(line) == 0: @@ -1211,7 +1225,7 @@ def cli(self, commands=None): raise TypeError('Please enter a valid list of commands!') for command in commands: - output = self.device.send_command(command) + output = self._send_command(command) if 'Invalid input detected' in output: raise ValueError('Unable to execute command "{}"'.format(command)) cli_output.setdefault(command, {}) @@ -1235,7 +1249,7 @@ def get_ntp_servers(self): """ ntp_servers = {} command = 'show run | include ntp server' - output = self.device.send_command(command) + output = self._send_command(command) for line in output.splitlines(): split_line = line.split() @@ -1251,7 +1265,7 @@ def get_ntp_stats(self): ntp_stats = [] command = 'show ntp associations' - output = self.device.send_command(command) + output = self._send_command(command) for line in output.splitlines(): # Skip first two lines and last line of command output @@ -1297,8 +1311,8 @@ def get_mac_address_table(self): """ mac_address_table = [] command = 'show mac-address-table' - output = self.device.send_command(command) - output = output.strip().split('\n') + output = self._send_command(command) + output = output.split('\n') # Skip the first two lines which are headers output = output[2:] @@ -1353,7 +1367,7 @@ def get_snmp_information(self): 'location': u'unknown' } command = 'show run | include snmp-server' - output = self.device.send_command(command) + output = self._send_command(command) for line in output.splitlines(): fields = line.split() if 'snmp-server community' in line: @@ -1378,7 +1392,7 @@ def get_snmp_information(self): # If SNMP Chassis wasn't found; obtain using direct command if snmp_dict['chassis_id'] == 'unknown': command = 'show snmp chassis' - snmp_chassis = self.device.send_command(command) + snmp_chassis = self._send_command(command) snmp_dict['chassis_id'] = snmp_chassis return snmp_dict @@ -1409,8 +1423,7 @@ def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): if source != '': command += ' source {}'.format(source) - output = self.device.send_command(command) - + output = self._send_command(command) if '%' in output: ping_dict['error'] = output elif 'Sending' in output: @@ -1470,12 +1483,12 @@ def get_config(self, retrieve='all'): if retrieve in ('startup', 'all'): command = 'show startup-config' - output = self.device.send_command(command) + output = self._send_command(command) configs['startup'] = output if retrieve in ('running', 'all'): command = 'show running-config' - output = self.device.send_command(command) + output = self._send_command(command) configs['running'] = output return configs From f4a7d139097368068145846d57ea026bc46fcd45 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 3 Dec 2016 14:00:08 -0800 Subject: [PATCH 19/41] update send_command postprocessor --- napalm_ios/ios.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 068d7de..65c0728 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -396,8 +396,7 @@ def _expand_interface_name(self, interface_brief): if self.interface_map.get(interface_brief): return self.interface_map.get(interface_brief) command = 'show int {}'.format(interface_brief) - output = self.device.send_command(command) - output = output.strip() + output = self._send_command(command) first_line = output.splitlines()[0] if 'line protocol' in first_line: full_int_name = first_line.split()[0] From 5582604043e1ced76abf7d724bf95eef96561379 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sat, 3 Dec 2016 17:09:40 -0800 Subject: [PATCH 20/41] Adding handler for alternate form of show mac addr --- napalm_ios/ios.py | 19 ++- .../alt_show_cmd/expected_result.json | 153 ++++++++++++++++++ .../alt_show_cmd/show_mac_address_table.txt | 21 +++ 3 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json create mode 100644 test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/show_mac_address_table.txt diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 65c0728..47d027c 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -34,6 +34,10 @@ IP_ADDR_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) +IOS_COMMANDS = { + 'show_mac_address': ['show mac-address table', 'show mac address-table'], +} + class IOSDriver(NetworkDriver): """NAPALM Cisco IOS Handler.""" @@ -114,8 +118,17 @@ def close(self): self.device.disconnect() def _send_command(self, command): - """Wrapper for self.device.send.command()""" - output = self.device.send_command(command) + """Wrapper for self.device.send.command(). + + If command is an interable will iterate through commands until valid command. + """ + if hasattr(command, '__iter__'): + for cmd in command: + output = self.device.send_command(cmd) + if "% Invalid" not in output: + break + else: + output = self.device.send_command(command) return self.send_command_postprocess(output) def is_alive(self): @@ -1309,7 +1322,7 @@ def get_mac_address_table(self): * last_move (float) """ mac_address_table = [] - command = 'show mac-address-table' + command = IOS_COMMANDS['show_mac_address'] output = self._send_command(command) output = output.split('\n') diff --git a/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json new file mode 100644 index 0000000..face4f4 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json @@ -0,0 +1,153 @@ +[{ + "static": false, + "active": true, + "vlan": 1, + "mac": "400.f1cf.2cc6", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 1, + "mac": "a493.4cc1.67a7", + "interface": "Vlan1", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "000c.2906.17d6", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "000c.2913.421b", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0018.0ab3.59f1", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0018.dd32.1f7c", + "interface": "FastEthernet6", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0025.64f5.d352", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "0026.abb9.a503", + "interface": "FastEthernet4", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 100, + "mac": "a493.4cc1.67a7", + "interface": "Vlan100", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "ac3a.7a1a.ba4b", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "b0a7.376f.b3b4", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "bc5f.f435.fa0e", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "dc3a.5e67.1a98", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "dc3a.5ee2.6a95", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 100, + "mac": "f04f.7c92.5a45", + "interface": "Wlan-GigabitEthernet0", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "0009.b754.1a88", + "interface": "FastEthernet7", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "10bd.1801.a0b4", + "interface": "FastEthernet3", + "moves": -1, + "last_move": -1.0 +}, { + "static": false, + "active": true, + "vlan": 200, + "mac": "204c.9ed7.cb80", + "interface": "FastEthernet2", + "moves": -1, + "last_move": -1.0 +}, { + "static": true, + "active": false, + "vlan": 200, + "mac": "a493.4cc1.67a7", + "interface": "Vlan200", + "moves": -1, + "last_move": -1.0 +}] diff --git a/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/show_mac_address_table.txt new file mode 100644 index 0000000..c4123f1 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/show_mac_address_table.txt @@ -0,0 +1,21 @@ +Destination Address Address Type VLAN Destination Port +------------------- ------------ ---- -------------------- +6400.f1cf.2cc6 Dynamic 1 Wlan-GigabitEthernet0 +a493.4cc1.67a7 Self 1 Vlan1 +000c.2906.17d6 Dynamic 100 FastEthernet7 +000c.2913.421b Dynamic 100 FastEthernet7 +0018.0ab3.59f1 Dynamic 100 FastEthernet7 +0018.dd32.1f7c Dynamic 100 FastEthernet6 +0025.64f5.d352 Dynamic 100 FastEthernet7 +0026.abb9.a503 Dynamic 100 FastEthernet4 +a493.4cc1.67a7 Self 100 Vlan100 +ac3a.7a1a.ba4b Dynamic 100 Wlan-GigabitEthernet0 +b0a7.376f.b3b4 Dynamic 100 FastEthernet7 +bc5f.f435.fa0e Dynamic 100 FastEthernet7 +dc3a.5e67.1a98 Dynamic 100 FastEthernet7 +dc3a.5ee2.6a95 Dynamic 100 Wlan-GigabitEthernet0 +f04f.7c92.5a45 Dynamic 100 Wlan-GigabitEthernet0 +0009.b754.1a88 Dynamic 200 FastEthernet7 +10bd.1801.a0b4 Dynamic 200 FastEthernet3 +204c.9ed7.cb80 Dynamic 200 FastEthernet2 +a493.4cc1.67a7 Self 200 Vlan200 From d714da61f832dcea831fbd24e8a25b4faff91190 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 09:03:12 -0800 Subject: [PATCH 21/41] Test fix --- setup.cfg | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.cfg b/setup.cfg index ffae4a5..8178cc1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,3 +4,8 @@ ignore = D203,C901 [pylama:pep8] max_line_length = 100 + +[tool:pytest] +addopts = --cov=./ -vs +json_report = report.json +jsonapi = true From 2178e78a5560d2a5ce191b58502501276e4c5823 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 09:03:59 -0800 Subject: [PATCH 22/41] Fix get mac address to support two different show commands --- napalm_ios/ios.py | 2 ++ .../alt_show_cmd/expected_result.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 47d027c..0191ef6 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -124,7 +124,9 @@ def _send_command(self, command): """ if hasattr(command, '__iter__'): for cmd in command: + print(cmd) output = self.device.send_command(cmd) + print(output) if "% Invalid" not in output: break else: diff --git a/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json index face4f4..ed12c29 100644 --- a/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json +++ b/test/unit/mocked_data/test_get_mac_address_table/alt_show_cmd/expected_result.json @@ -2,7 +2,7 @@ "static": false, "active": true, "vlan": 1, - "mac": "400.f1cf.2cc6", + "mac": "6400.f1cf.2cc6", "interface": "Wlan-GigabitEthernet0", "moves": -1, "last_move": -1.0 From 0397f08caaeeecd988b26d4a61cf0a3d50c06b40 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 09:14:38 -0800 Subject: [PATCH 23/41] Removing setup.cfg change --- setup.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 8178cc1..000de24 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ ignore = D203,C901 [pylama:pep8] max_line_length = 100 -[tool:pytest] -addopts = --cov=./ -vs -json_report = report.json -jsonapi = true +#[tool:pytest] +#addopts = --cov=./ -vs +#json_report = report.json +#jsonapi = true From 8d231b2d988a84cbed52695b646d73ed698f8d5a Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 09:45:06 -0800 Subject: [PATCH 24/41] Fixing issue determinining iterable py2 vs py3 --- napalm_ios/ios.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 0191ef6..e030776 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -120,9 +120,9 @@ def close(self): def _send_command(self, command): """Wrapper for self.device.send.command(). - If command is an interable will iterate through commands until valid command. + If command is a list will iterate through commands until valid command. """ - if hasattr(command, '__iter__'): + if isinstance(command, list): for cmd in command: print(cmd) output = self.device.send_command(cmd) From 26f06c316135e7de44c8d8fa5e8e9fb1090392ab Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 09:45:56 -0800 Subject: [PATCH 25/41] Restore setup.cfg changes --- setup.cfg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 000de24..8178cc1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ ignore = D203,C901 [pylama:pep8] max_line_length = 100 -#[tool:pytest] -#addopts = --cov=./ -vs -#json_report = report.json -#jsonapi = true +[tool:pytest] +addopts = --cov=./ -vs +json_report = report.json +jsonapi = true From 8a476267260cb270f514b15d7e6eb6ded5ef0c41 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 11:39:33 -0800 Subject: [PATCH 26/41] Fixing mac-address command error --- napalm_ios/ios.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index e030776..e3b8f55 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -35,7 +35,7 @@ RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) IOS_COMMANDS = { - 'show_mac_address': ['show mac-address table', 'show mac address-table'], + 'show_mac_address': ['show mac-address-table', 'show mac address-table'], } From c9cf4ad2b757720270ad6cc6b589f1ef62411a84 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 12:07:28 -0800 Subject: [PATCH 27/41] Fixes#76 - Static arp entries --- .gitignore | 2 ++ napalm_ios/ios.py | 46 +++++++++++++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 1bc81f8..7b231ee 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,5 @@ test/unit/TestIOSDriverKB.py #test/unit/ios/*.diff test/unit/ios/cleanup.sh test/unit/ios/prep_test.sh + +report.json diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index e3b8f55..1ba501f 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -30,9 +30,12 @@ WEEK_SECONDS = 7 * DAY_SECONDS YEAR_SECONDS = 365 * DAY_SECONDS -# IP Address +# STD REGEX PATTERNS IP_ADDR_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" +MAC_REGEX = r"[a-fA-F0-9]{4}\.[a-fA-F0-9]{4}\.[a-fA-F0-9]{4}" +RE_IPADDR = re.compile(r"{}".format(IP_ADDR_REGEX)) RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) +RE_MAC = re.compile(r"{}".format(MAC_REGEX)) IOS_COMMANDS = { 'show_mac_address': ['show mac-address-table', 'show mac address-table'], @@ -124,9 +127,7 @@ def _send_command(self, command): """ if isinstance(command, list): for cmd in command: - print(cmd) output = self.device.send_command(cmd) - print(output) if "% Invalid" not in output: break else: @@ -1200,24 +1201,35 @@ def get_arp_table(self): for line in output: if len(line) == 0: return {} - if len(line.split()) == 6: + if len(line.split()) == 5: + # Static ARP entries have no interface + # Internet 10.0.0.1 - 0010.2345.1cda ARPA + interface = '' + protocol, address, age, mac, eth_type = line.split() + elif len(line.split()) == 6: protocol, address, age, mac, eth_type, interface = line.split() - try: - if age == '-': - age = 0 - age = float(age) - except ValueError: - print("Unable to convert age value to float: {}".format(age)) - entry = { - 'interface': interface, - 'mac': mac, - 'ip': address, - 'age': age - } - arp_table.append(entry) else: raise ValueError("Unexpected output from: {}".format(line.split())) + try: + if age == '-': + age = 0 + age = float(age) + except ValueError: + raise ValueError("Unable to convert age value to float: {}".format(age)) + + # Validate we matched correctly + if not re.search(RE_IPADDR, address): + raise ValueError("Invalid IP Address detected: {}".format(address)) + if not re.search(RE_MAC, mac): + raise ValueError("Invalid MAC Address detected: {}".format(mac)) + entry = { + 'interface': interface, + 'mac': mac, + 'ip': address, + 'age': age + } + arp_table.append(entry) return arp_table def cli(self, commands=None): From 82dd13e1968825bde772c8ae55f48e354534e742 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 12:09:40 -0800 Subject: [PATCH 28/41] Adding unit test for static ARP entry --- .../static_arp_entry/expected_result.json | 41 +++++++++++++++++++ .../show_arp___exclude_Incomplete.txt | 9 ++++ 2 files changed, 50 insertions(+) create mode 100644 test/unit/mocked_data/test_get_arp_table/static_arp_entry/expected_result.json create mode 100644 test/unit/mocked_data/test_get_arp_table/static_arp_entry/show_arp___exclude_Incomplete.txt diff --git a/test/unit/mocked_data/test_get_arp_table/static_arp_entry/expected_result.json b/test/unit/mocked_data/test_get_arp_table/static_arp_entry/expected_result.json new file mode 100644 index 0000000..de89360 --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/static_arp_entry/expected_result.json @@ -0,0 +1,41 @@ +[{ + "interface": "", + "ip": "172.29.50.1", + "mac": "84b8.0276.ac0e", + "age": 8.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.2", + "mac": "0019.0725.344a", + "age": 221.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.3", + "mac": "0024.f7dd.7741", + "age": 0.0 +}, { + "interface": "Vlan20", + "ip": "172.29.50.10", + "mac": "6805.ca12.71c2", + "age": 37.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.33", + "mac": "84b8.0276.ac0e", + "age": 61.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.34", + "mac": "0024.f7dd.7743", + "age": 0.0 +}, { + "interface": "Vlan41", + "ip": "172.29.52.40", + "mac": "a099.9b1c.dfa7", + "age": 3.0 +}, { + "interface": "Vlan41", + "ip": "192.168.81.34", + "mac": "0024.f7dd.7743", + "age": 0.0 +}] diff --git a/test/unit/mocked_data/test_get_arp_table/static_arp_entry/show_arp___exclude_Incomplete.txt b/test/unit/mocked_data/test_get_arp_table/static_arp_entry/show_arp___exclude_Incomplete.txt new file mode 100644 index 0000000..80efdc0 --- /dev/null +++ b/test/unit/mocked_data/test_get_arp_table/static_arp_entry/show_arp___exclude_Incomplete.txt @@ -0,0 +1,9 @@ +Protocol Address Age (min) Hardware Addr Type Interface +Internet 172.29.50.1 8 84b8.0276.ac0e ARPA +Internet 172.29.50.2 221 0019.0725.344a ARPA Vlan20 +Internet 172.29.50.3 - 0024.f7dd.7741 ARPA Vlan20 +Internet 172.29.50.10 37 6805.ca12.71c2 ARPA Vlan20 +Internet 172.29.52.33 61 84b8.0276.ac0e ARPA Vlan41 +Internet 172.29.52.34 - 0024.f7dd.7743 ARPA Vlan41 +Internet 172.29.52.40 3 a099.9b1c.dfa7 ARPA Vlan41 +Internet 192.168.81.34 - 0024.f7dd.7743 ARPA Vlan41 From 04ee26cc0523150d91069b9461cb71ba7d1d3207 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 14:48:28 -0800 Subject: [PATCH 29/41] Fixing BGP peer id with a '*' in it --- napalm_ios/ios.py | 1 + .../test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt | 2 +- .../regex_strip/show_ip_bgp_summary___begin_Neighbor.txt | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 1ba501f..a532e3b 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -961,6 +961,7 @@ def get_bgp_neighbors(self): fields = line.split()[:10] peer_id, bgp_version, remote_as, msg_rcvd, msg_sent, table_version, in_queue, \ out_queue, up_time, state_prefix = fields + peer_id = peer_id.replace('*', '') if '(Admin)' in state_prefix: is_enabled = False diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt index 7896ea2..2f34114 100644 --- a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary.txt @@ -2,6 +2,6 @@ BGP router identifier 192.168.0.1, local AS number 65000 BGP table version is 1, main routing table version 1 Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd -192.168.0.2 +*192.168.0.2 4 65001 0 0 1 0 0 never Idle 192.168.0.3 4 65010 0 0 1 0 0 never Active diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt index 1c9aaef..2dbb097 100644 --- a/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt +++ b/test/unit/mocked_data/test_get_bgp_neighbors/regex_strip/show_ip_bgp_summary___begin_Neighbor.txt @@ -1,4 +1,4 @@ Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd -192.168.0.2 +*192.168.0.2 4 65001 0 0 1 0 0 never Idle 192.168.0.3 4 65010 0 0 1 0 0 never Active From 1239176f6f1b267ce7d0e41d2b437997f01a8c63 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 15:48:24 -0800 Subject: [PATCH 30/41] Supporting other show mac address table formats --- napalm_ios/ios.py | 92 ++++++++++++++----- .../6500_format/expected_result.json | 9 ++ .../6500_format/show_mac_address_table.txt | 7 ++ 3 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json create mode 100644 test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index a532e3b..cab6779 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1335,39 +1335,81 @@ def get_mac_address_table(self): * static (boolean) * moves (int) * last_move (float) + + Format1: + Destination Address Address Type VLAN Destination Port + ------------------- ------------ ---- -------------------- + 6400.f1cf.2cc6 Dynamic 1 Wlan-GigabitEthernet0 + + Cat 6500: + Legend: * - primary entry + age - seconds since last seen + n/a - not available + + vlan mac address type learn age ports + ------+----------------+--------+-----+----------+-------------------------- + * 999 1111.2222.3333 dynamic Yes 0 Port-channel1 + + Cat 4948 + Unicast Entries + vlan mac address type protocols port + -------+---------------+--------+---------------------+-------------------- + 999 1111.2222.3333 dynamic ip Port-channel1 + + Cat 2960 + Mac Address Table + ------------------------------------------- + + Vlan Mac Address Type Ports + ---- ----------- -------- ----- + All 1111.2222.3333 STATIC CPU """ + + def process_mac_fields(vlan, mac, mac_type, interface): + """Return proper data for mac address fields.""" + if mac_type.lower() in ['self', 'static']: + static = True + else: + static = False + if mac_type.lower() in ['dynamic']: + active = True + else: + active = False + return { + 'mac': mac, + 'interface': interface, + 'vlan': int(vlan), + 'static': static, + 'active': active, + 'moves': -1, + 'last_move': -1.0 + } + mac_address_table = [] command = IOS_COMMANDS['show_mac_address'] output = self._send_command(command) - output = output.split('\n') - # Skip the first two lines which are headers - output = output[2:] - for line in output: - if len(line) == 0: - return mac_address_table - elif len(line.split()) == 4: - mac, mac_type, vlan, interface = line.split() - if mac_type.lower() in ['self', 'static']: - static = True + # Skip the header lines + output = re.split(r'^----.*', output, flags=re.M)[1:] + output = "\n".join(output).strip() + for line in output.splitlines(): + # Format1 + if re.search(r"^" + MAC_REGEX, line): + if len(line.split()) == 4: + mac, mac_type, vlan, interface = line.split() + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) else: - static = False - if mac_type.lower() in ['dynamic']: - active = True + raise ValueError("Unexpected output from: {}".format(line.split())) + # Cat6500 format + # * 999 1111.2222.3333 dynamic Yes 0 Port-channel1 + elif re.search(r"^\*\s+\d+\s+" + MAC_REGEX, line): + if len(line.split()) == 7: + _, vlan, mac, mac_type, _, _, interface = line.split() + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) else: - active = False - entry = { - 'mac': mac, - 'interface': interface, - 'vlan': int(vlan), - 'static': static, - 'active': active, - 'moves': -1, - 'last_move': -1.0 - } - mac_address_table.append(entry) + raise ValueError("Unexpected output from: {}".format(line.split())) else: - raise ValueError("Unexpected output from: {}".format(line.split())) + raise ValueError("Unexpected output from: {}".format(repr(line))) return mac_address_table def get_snmp_information(self): diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json new file mode 100644 index 0000000..47417d8 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json @@ -0,0 +1,9 @@ +[{ + "static": false, + "active": true, + "vlan": 999, + "mac": "1111.2222.3333", + "interface": "Port-channel1", + "moves": -1, + "last_move": -1.0 +}] diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt new file mode 100644 index 0000000..8aace2a --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt @@ -0,0 +1,7 @@ +Legend: * - primary entry + age - seconds since last seen + n/a - not available + + vlan mac address type learn age ports +------+----------------+--------+-----+----------+-------------------------- +* 999 1111.2222.3333 dynamic Yes 0 Port-channel1 From 2675cf8d1f5d3efd92e7aefbd180fcc840ea2db7 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 15:58:09 -0800 Subject: [PATCH 31/41] 4948 show mac address format --- napalm_ios/ios.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index cab6779..ea7943a 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -1408,6 +1408,14 @@ def process_mac_fields(vlan, mac, mac_type, interface): mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) else: raise ValueError("Unexpected output from: {}".format(line.split())) + # Cat4948 format + # 999 1111.2222.3333 dynamic ip Port-channel1 + elif re.search(r"^\s+\d+\s+" + MAC_REGEX, line) or re.search(r"^\d+\s+" + MAC_REGEX, line): + if len(line.split()) == 5: + vlan, mac, mac_type, _, interface = line.split() + mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) + else: + raise ValueError("Unexpected output from: {}".format(line.split())) else: raise ValueError("Unexpected output from: {}".format(repr(line))) return mac_address_table From 837b79242ac031a4b297ae4b14e6b65c20571664 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 15:58:32 -0800 Subject: [PATCH 32/41] 4948 show mac address format tests --- .../4948_format/expected_result.json | 9 +++++++++ .../4948_format/show_mac_address_table.txt | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 test/unit/mocked_data/test_get_mac_address_table/4948_format/expected_result.json create mode 100644 test/unit/mocked_data/test_get_mac_address_table/4948_format/show_mac_address_table.txt diff --git a/test/unit/mocked_data/test_get_mac_address_table/4948_format/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/4948_format/expected_result.json new file mode 100644 index 0000000..47417d8 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/4948_format/expected_result.json @@ -0,0 +1,9 @@ +[{ + "static": false, + "active": true, + "vlan": 999, + "mac": "1111.2222.3333", + "interface": "Port-channel1", + "moves": -1, + "last_move": -1.0 +}] diff --git a/test/unit/mocked_data/test_get_mac_address_table/4948_format/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/4948_format/show_mac_address_table.txt new file mode 100644 index 0000000..7cb8ab4 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/4948_format/show_mac_address_table.txt @@ -0,0 +1,4 @@ +Unicast Entries + vlan mac address type protocols port +-------+---------------+--------+---------------------+-------------------- + 999 1111.2222.3333 dynamic ip Port-channel1 From 296a39e7112fd91402fa8433ddfbafc120ad4daa Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Sun, 4 Dec 2016 18:13:44 -0800 Subject: [PATCH 33/41] Fixing MAC address format issues including new tests --- napalm_ios/ios.py | 47 ++++++++++++++----- .../2960_format/expected_result.json | 18 +++++++ .../2960_format/show_mac_address_table.txt | 7 +++ .../6500_format/expected_result.json | 9 ++++ .../6500_format/show_mac_address_table.txt | 1 + 5 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 test/unit/mocked_data/test_get_mac_address_table/2960_format/expected_result.json create mode 100644 test/unit/mocked_data/test_get_mac_address_table/2960_format/show_mac_address_table.txt diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index ea7943a..acab323 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -33,6 +33,7 @@ # STD REGEX PATTERNS IP_ADDR_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" MAC_REGEX = r"[a-fA-F0-9]{4}\.[a-fA-F0-9]{4}\.[a-fA-F0-9]{4}" +VLAN_REGEX = r"\d{1,4}" RE_IPADDR = re.compile(r"{}".format(IP_ADDR_REGEX)) RE_IPADDR_STRIP = re.compile(r"({})\n".format(IP_ADDR_REGEX)) RE_MAC = re.compile(r"{}".format(MAC_REGEX)) @@ -1349,6 +1350,7 @@ def get_mac_address_table(self): vlan mac address type learn age ports ------+----------------+--------+-----+----------+-------------------------- * 999 1111.2222.3333 dynamic Yes 0 Port-channel1 + 999 1111.2222.3333 dynamic Yes 0 Port-channel1 Cat 4948 Unicast Entries @@ -1365,10 +1367,21 @@ def get_mac_address_table(self): All 1111.2222.3333 STATIC CPU """ + 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_2960_1 = r"^All\s+{}".format(MAC_REGEX) + RE_MACTABLE_2960_2 = r"^{}\s+{}\s+".format(VLAN_REGEX, MAC_REGEX) # 4 fields + def process_mac_fields(vlan, mac, mac_type, interface): """Return proper data for mac address fields.""" if mac_type.lower() in ['self', 'static']: static = True + if vlan.lower() == 'all': + vlan = 0 + if interface.lower() == 'cpu': + interface = '' else: static = False if mac_type.lower() in ['dynamic']: @@ -1391,31 +1404,39 @@ def process_mac_fields(vlan, mac, mac_type, interface): # Skip the header lines output = re.split(r'^----.*', output, flags=re.M)[1:] + print(output) output = "\n".join(output).strip() for line in output.splitlines(): + line = line.strip() + if line == '': + continue # Format1 - if re.search(r"^" + MAC_REGEX, line): + elif re.search(RE_MACTABLE_DEFAULT, line): if len(line.split()) == 4: mac, mac_type, vlan, interface = line.split() mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) else: raise ValueError("Unexpected output from: {}".format(line.split())) # Cat6500 format - # * 999 1111.2222.3333 dynamic Yes 0 Port-channel1 - elif re.search(r"^\*\s+\d+\s+" + MAC_REGEX, line): + elif (re.search(RE_MACTABLE_6500_1, line) or re.search(RE_MACTABLE_6500_2, line)) and \ + len(line.split()) >= 6: if len(line.split()) == 7: _, vlan, mac, mac_type, _, _, interface = line.split() - mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) - else: - raise ValueError("Unexpected output from: {}".format(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)) # Cat4948 format - # 999 1111.2222.3333 dynamic ip Port-channel1 - elif re.search(r"^\s+\d+\s+" + MAC_REGEX, line) or re.search(r"^\d+\s+" + MAC_REGEX, line): - if len(line.split()) == 5: - vlan, mac, mac_type, _, interface = line.split() - mac_address_table.append(process_mac_fields(vlan, mac, mac_type, interface)) - else: - raise ValueError("Unexpected output from: {}".format(line.split())) + elif re.search(RE_MACTABLE_4500, 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 + elif re.search(r"^Vlan\s+Mac Address\s+", line): + continue + # Cat2960 format + elif (re.search(RE_MACTABLE_2960_1, line) or re.search(RE_MACTABLE_2960_2, 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)) else: raise ValueError("Unexpected output from: {}".format(repr(line))) return mac_address_table diff --git a/test/unit/mocked_data/test_get_mac_address_table/2960_format/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/2960_format/expected_result.json new file mode 100644 index 0000000..5397daa --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/2960_format/expected_result.json @@ -0,0 +1,18 @@ +[{ + "static": true, + "active": false, + "vlan": 0, + "mac": "1111.2222.3333", + "interface": "", + "moves": -1, + "last_move": -1.0 +}, +{ + "static": false, + "active": true, + "vlan": 6, + "mac": "0018.b974.528f", + "interface": "Fa0/16", + "moves": -1, + "last_move": -1.0 +}] diff --git a/test/unit/mocked_data/test_get_mac_address_table/2960_format/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/2960_format/show_mac_address_table.txt new file mode 100644 index 0000000..55c0706 --- /dev/null +++ b/test/unit/mocked_data/test_get_mac_address_table/2960_format/show_mac_address_table.txt @@ -0,0 +1,7 @@ +Mac Address Table +------------------------------------------- + +Vlan Mac Address Type Ports +---- ----------- -------- ----- +All 1111.2222.3333 STATIC CPU + 6 0018.b974.528f DYNAMIC Fa0/16 diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json b/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json index 47417d8..86c76a4 100644 --- a/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format/expected_result.json @@ -6,4 +6,13 @@ "interface": "Port-channel1", "moves": -1, "last_move": -1.0 +}, +{ + "static": false, + "active": true, + "vlan": 999, + "mac": "1111.2222.3333", + "interface": "Port-channel2", + "moves": -1, + "last_move": -1.0 }] diff --git a/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt b/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt index 8aace2a..7213266 100644 --- a/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt +++ b/test/unit/mocked_data/test_get_mac_address_table/6500_format/show_mac_address_table.txt @@ -5,3 +5,4 @@ Legend: * - primary entry vlan mac address type learn age ports ------+----------------+--------+-----+----------+-------------------------- * 999 1111.2222.3333 dynamic Yes 0 Port-channel1 + 999 1111.2222.3333 dynamic Yes 0 Port-channel2 From 1d368374ad3d66c88116f493253900a35e4fe739 Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 7 Dec 2016 10:08:34 +0000 Subject: [PATCH 34/41] Fix NTP peers templates --- napalm_ios/templates/delete_ntp_peers.j2 | 4 ++-- napalm_ios/templates/set_ntp_peers.j2 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/napalm_ios/templates/delete_ntp_peers.j2 b/napalm_ios/templates/delete_ntp_peers.j2 index 159c33d..cee41bf 100644 --- a/napalm_ios/templates/delete_ntp_peers.j2 +++ b/napalm_ios/templates/delete_ntp_peers.j2 @@ -1,3 +1,3 @@ -{% for peer in template_vars %} -no ntp server {{peer}} +{% for peer in peers %} +no ntp peer {{peer}} {% endfor %} diff --git a/napalm_ios/templates/set_ntp_peers.j2 b/napalm_ios/templates/set_ntp_peers.j2 index c5e8423..1dd886b 100644 --- a/napalm_ios/templates/set_ntp_peers.j2 +++ b/napalm_ios/templates/set_ntp_peers.j2 @@ -1,3 +1,3 @@ -{% for peer in template_vars %} -ntp server {{peer}} +{% for peer in peers %} +ntp peer {{peer}} {% endfor %} From adaac999fb66f0a50660816f1ef1c7047d800cdf Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 7 Dec 2016 10:09:10 +0000 Subject: [PATCH 35/41] Templates for NTP servers and SNMP --- napalm_ios/templates/delete_ntp_servers.j2 | 3 +++ napalm_ios/templates/delete_snmp_config.j2 | 14 ++++++++++++++ napalm_ios/templates/set_ntp_servers.j2 | 3 +++ napalm_ios/templates/snmp_config.j2 | 22 ++++++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 napalm_ios/templates/delete_ntp_servers.j2 create mode 100644 napalm_ios/templates/delete_snmp_config.j2 create mode 100644 napalm_ios/templates/set_ntp_servers.j2 create mode 100644 napalm_ios/templates/snmp_config.j2 diff --git a/napalm_ios/templates/delete_ntp_servers.j2 b/napalm_ios/templates/delete_ntp_servers.j2 new file mode 100644 index 0000000..38accdf --- /dev/null +++ b/napalm_ios/templates/delete_ntp_servers.j2 @@ -0,0 +1,3 @@ +{% for server in servers %} +no ntp server {{server}} +{% endfor %} diff --git a/napalm_ios/templates/delete_snmp_config.j2 b/napalm_ios/templates/delete_snmp_config.j2 new file mode 100644 index 0000000..0543dfe --- /dev/null +++ b/napalm_ios/templates/delete_snmp_config.j2 @@ -0,0 +1,14 @@ +{% if (location is defined) and location %} +no snmp-server location "{{location}}" +{% endif %} +{% if (contact is defined) and contact %} +no snmp-server contact "{{contact}}" +{% endif %} +{% if (chassis_id is defined) and chassis_id %} +no snmp-server chassis-id "{{chassis_id}}" +{% endif %} +{% if (community is defined) and community %} +{% for comm_name, comm_details in community.iteritems() %} +no community {{comm_name}} +{% endfor %} +{% endif %} diff --git a/napalm_ios/templates/set_ntp_servers.j2 b/napalm_ios/templates/set_ntp_servers.j2 new file mode 100644 index 0000000..1cebc15 --- /dev/null +++ b/napalm_ios/templates/set_ntp_servers.j2 @@ -0,0 +1,3 @@ +{% for server in servers %} +ntp server {{server}} +{% endfor %} diff --git a/napalm_ios/templates/snmp_config.j2 b/napalm_ios/templates/snmp_config.j2 new file mode 100644 index 0000000..4e98e56 --- /dev/null +++ b/napalm_ios/templates/snmp_config.j2 @@ -0,0 +1,22 @@ +{% if (location is defined) and location %} +snmp-server location "{{location}}" +{% endif %} +{% if (contact is defined) and contact %} +snmp-server contact "{{contact}}" +{% endif %} +{% if (chassis_id is defined) and chassis_id %} +snmp-server chassis-id "{{chassis_id}}" +{% endif %} +{% if (community is defined) and community %} +{% for comm_name, comm_details in community.iteritems() %} +{% if (comm_details is defined) and comm_details %} +{% if (comm_details.get('mode') is defined) and comm_details.get('mode') == 'rw' %} +community {{comm_name}} rw +{% else %} +community {{comm_name}} ro +{% endif %} +{% else %} +community {{comm_name}} ro +{% endif %} +{% endfor %} +{% endif %} From 54de3aee8bff87beadbb0bb9fd725ae15cd43bb0 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Wed, 7 Dec 2016 17:44:09 -0800 Subject: [PATCH 36/41] Rationalize napalm-ios to adhere to napalm-base requirements --- napalm_ios/ios.py | 81 ++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index acab323..9150e1e 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -133,7 +133,7 @@ def _send_command(self, command): break else: output = self.device.send_command(command) - return self.send_command_postprocess(output) + return self._send_command_postprocess(output) def is_alive(self): """Returns a flag with the state of the SSH connection.""" @@ -151,9 +151,9 @@ def load_replace_candidate(self, filename=None, config=None): if config: raise NotImplementedError if filename: - (return_status, msg) = self.scp_file(source_file=filename, - dest_file=self.candidate_cfg, - file_system=self.dest_file_system) + (return_status, msg) = self._scp_file(source_file=filename, + dest_file=self.candidate_cfg, + file_system=self.dest_file_system) if not return_status: if msg == '': msg = "SCP transfer to remote device failed" @@ -169,16 +169,16 @@ def load_merge_candidate(self, filename=None, config=None): if config: raise NotImplementedError if filename: - (return_status, msg) = self.scp_file(source_file=filename, - dest_file=self.merge_cfg, - file_system=self.dest_file_system) + (return_status, msg) = self._scp_file(source_file=filename, + dest_file=self.merge_cfg, + file_system=self.dest_file_system) if not return_status: if msg == '': msg = "SCP transfer to remote device failed" raise MergeConfigException(msg) @staticmethod - def normalize_compare_config(diff): + def _normalize_compare_config(diff): """Filter out strings that should not show up in the diff.""" ignore_strings = ['Contextual Config Diffs', 'No changes were found', 'file prompt quiet', 'ntp clock-period'] @@ -207,31 +207,28 @@ def _normalize_merge_diff(diff): new_diff.append('! No changes specified in merge file.') return "\n".join(new_diff) - def compare_config(self, - base_file='running-config', - new_file=None, - base_file_system='system:', - new_file_system=None): + def compare_config(self): """ show archive config differences . Default operation is to compare system:running-config to self.candidate_cfg """ - # Set defaults if not passed as arguments - if new_file is None: - if self.config_replace: - new_file = self.candidate_cfg - else: - new_file = self.merge_cfg - if new_file_system is None: - new_file_system = self.dest_file_system - base_file_full = self.gen_full_path(filename=base_file, file_system=base_file_system) - new_file_full = self.gen_full_path(filename=new_file, file_system=new_file_system) + # Set defaults + base_file = 'running-config' + base_file_system = 'system:' + if self.config_replace: + new_file = self.candidate_cfg + else: + new_file = self.merge_cfg + new_file_system = self.dest_file_system + + base_file_full = self._gen_full_path(filename=base_file, file_system=base_file_system) + new_file_full = self._gen_full_path(filename=new_file, file_system=new_file_system) if self.config_replace: cmd = 'show archive config differences {} {}'.format(base_file_full, new_file_full) diff = self.device.send_command_expect(cmd) - diff = self.normalize_compare_config(diff) + diff = self._normalize_compare_config(diff) else: cmd = 'more {}'.format(new_file_full) diff = self.device.send_command_expect(cmd) @@ -253,7 +250,7 @@ def _commit_hostname_handler(self, cmd): output = '' return output - def commit_config(self, filename=None): + def commit_config(self): """ If replacement operation, perform 'configure replace' for the entire config. @@ -264,9 +261,8 @@ def commit_config(self, filename=None): if self.config_replace: # Replace operation - if filename is None: - filename = self.candidate_cfg - cfg_file = self.gen_full_path(filename) + filename = self.candidate_cfg + cfg_file = self._gen_full_path(filename) if not self._check_file_exists(cfg_file): raise ReplaceConfigException("Candidate config file does not exist") if self.auto_rollback_on_error: @@ -279,9 +275,8 @@ def commit_config(self, filename=None): raise ReplaceConfigException("Candidate config could not be applied") else: # Merge operation - if filename is None: - filename = self.merge_cfg - cfg_file = self.gen_full_path(filename) + filename = self.merge_cfg + cfg_file = self._gen_full_path(filename) if not self._check_file_exists(cfg_file): raise MergeConfigException("Merge source config file does not exist") cmd = 'copy {} running-config'.format(cfg_file) @@ -298,24 +293,23 @@ def commit_config(self, filename=None): def discard_config(self): """Set candidate_cfg to current running-config. Erase the merge_cfg file.""" - discard_candidate = 'copy running-config {}'.format(self.gen_full_path(self.candidate_cfg)) - discard_merge = 'copy null: {}'.format(self.gen_full_path(self.merge_cfg)) + discard_candidate = 'copy running-config {}'.format(self._gen_full_path(self.candidate_cfg)) + discard_merge = 'copy null: {}'.format(self._gen_full_path(self.merge_cfg)) self._disable_confirm() self.device.send_command_expect(discard_candidate) self.device.send_command_expect(discard_merge) self._enable_confirm() - def rollback(self, filename=None): + def rollback(self): """Rollback configuration to filename or to self.rollback_cfg file.""" - if filename is None: - filename = self.rollback_cfg - cfg_file = self.gen_full_path(filename) + filename = self.rollback_cfg + cfg_file = self._gen_full_path(filename) if not self._check_file_exists(cfg_file): raise ReplaceConfigException("Rollback config file does not exist") cmd = 'configure replace {} force'.format(cfg_file) self.device.send_command_expect(cmd) - def scp_file(self, source_file, dest_file, file_system): + def _scp_file(self, source_file, dest_file, file_system): """ SCP file to remote device. @@ -364,7 +358,7 @@ def _disable_confirm(self): cmd = 'file prompt quiet' self.device.send_config_set([cmd]) - def gen_full_path(self, filename, file_system=None): + def _gen_full_path(self, filename, file_system=None): """Generate full file path on remote device.""" if file_system is None: return '{}/{}'.format(self.dest_file_system, filename) @@ -375,7 +369,7 @@ def gen_full_path(self, filename, file_system=None): def _gen_rollback_cfg(self): """Save a configuration that can be used for rollback.""" - cfg_file = self.gen_full_path(self.rollback_cfg) + cfg_file = self._gen_full_path(self.rollback_cfg) cmd = 'copy running-config {}'.format(cfg_file) self._disable_confirm() self.device.send_command_expect(cmd) @@ -423,7 +417,7 @@ def _expand_interface_name(self, interface_brief): return interface_brief @staticmethod - def send_command_postprocess(output): + def _send_command_postprocess(output): """ Cleanup actions on send_command() for NAPALM getters. @@ -464,7 +458,7 @@ def get_lldp_neighbors(self): return lldp - def get_lldp_neighbors_detail(self): + def get_lldp_neighbors_detail(self, interface=''): """ IOS implementation of get_lldp_neighbors_detail. @@ -1234,7 +1228,7 @@ def get_arp_table(self): arp_table.append(entry) return arp_table - def cli(self, commands=None): + def cli(self, commands): """ Execute a list of commands and return the output in a dictionary format using the command as the key. @@ -1248,7 +1242,6 @@ def cli(self, commands=None): """ cli_output = dict() - if type(commands) is not list: raise TypeError('Please enter a valid list of commands!') From abacf290f487770a9ce8f450eac4b4a92738a8e8 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Thu, 8 Dec 2016 10:00:25 -0800 Subject: [PATCH 37/41] Merge Traceroute PR and update to new test framework --- napalm_ios/ios.py | 27 +++++++------------ test/unit/TestIOSDriver.py | 4 +-- test/unit/conftest.py | 2 +- .../normal/expected_result.json | 1 + ...traceroute_8_8_8_8_ttl_0_255_timeout_2.txt | 16 +++++++++++ 5 files changed, 30 insertions(+), 20 deletions(-) create mode 100644 test/unit/mocked_data/test_traceroute/normal/expected_result.json create mode 100755 test/unit/mocked_data/test_traceroute/normal/traceroute_8_8_8_8_ttl_0_255_timeout_2.txt diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index 5a8f25f..a794858 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -23,6 +23,7 @@ from napalm_base.base import NetworkDriver from napalm_base.exceptions import ReplaceConfigException, MergeConfigException from napalm_base.utils import py23_compat +import napalm_base.constants as C # Easier to store these as constants HOUR_SECONDS = 3600 @@ -1397,7 +1398,6 @@ def process_mac_fields(vlan, mac, mac_type, interface): # Skip the header lines output = re.split(r'^----.*', output, flags=re.M)[1:] - print(output) output = "\n".join(output).strip() for line in output.splitlines(): line = line.strip() @@ -1557,7 +1557,8 @@ def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): return ping_dict - def traceroute(self, destination, source='', ttl=0, timeout=0): + def traceroute(self, destination, source=C.TRACEROUTE_SOURCE, + ttl=C.TRACEROUTE_TTL, timeout=C.TRACEROUTE_TIMEOUT): """ Executes traceroute on the device and returns a dictionary with the result. @@ -1585,23 +1586,15 @@ def traceroute(self, destination, source='', ttl=0, timeout=0): if isinstance(ttl, int) and 0 <= timeout <= 255: command += " ttl 0 {}".format(str(ttl)) if timeout: - # Timeout should be intiger between 1 and 3600 + # Timeout should be an integer between 1 and 3600 if isinstance(timeout, int) and 1 <= timeout <= 3600: command += " timeout {}".format(str(timeout)) - # Have to extend "send_command timeout" since traceroute can last for long time - # The formula to calculate the max_loops parameter is: - # (5 * expected_hops * timeout ) + 150 - # 5 -> because the default sleep time in send_command is 0.2s - # ttl_value -> based on expected hops, 255 if not set - # timeout -> configured timeout, 10 is used when not configured - # 150 -> to make some buffer - ttl_value = 255 - if ttl != 0: - ttl_value = ttl - timeout_value = 10 - if timeout != 0: - timeout_value = timeout - max_loops = (5 * ttl_value * timeout_value) + 150 + + # Calculation to leave enough time for traceroute to complete assumes send_command + # delay of .2 seconds. + max_loops = (5 * ttl * timeout) + 150 + if max_loops < 500: # Make sure max_loops isn't set artificially low + max_loops = 500 output = self.device.send_command(command, max_loops=max_loops) # Prepare return dict diff --git a/test/unit/TestIOSDriver.py b/test/unit/TestIOSDriver.py index 2b7821d..557a411 100755 --- a/test/unit/TestIOSDriver.py +++ b/test/unit/TestIOSDriver.py @@ -173,13 +173,13 @@ def read_txt_file(filename): with open(filename) as data_file: return data_file.read() - def send_command_expect(self, command, **kvargs): + def send_command_expect(self, command, **kwargs): """Fake execute a command in the device by just returning the content of a file.""" cmd = re.sub(r'[\[\]\*\^\+\s\|]', '_', command) output = self.read_txt_file('ios/mock_data/{}.txt'.format(cmd)) return py23_compat.text_type(output) - def send_command(self, command, **kvargs): + def send_command(self, command, **kwargs): """Fake execute a command in the device by just returning the content of a file.""" return self.send_command_expect(command) diff --git a/test/unit/conftest.py b/test/unit/conftest.py index bc3ddc1..fd0d443 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -56,7 +56,7 @@ def open(self): class FakeIOSDevice(BaseTestDouble): """IOS device test double.""" - def send_command(self, command): + def send_command(self, command, **kwargs): filename = '{}.txt'.format(self.sanitize_text(command)) full_path = self.find_file(filename) result = self.read_txt_file(full_path) diff --git a/test/unit/mocked_data/test_traceroute/normal/expected_result.json b/test/unit/mocked_data/test_traceroute/normal/expected_result.json new file mode 100644 index 0000000..6a0cdbe --- /dev/null +++ b/test/unit/mocked_data/test_traceroute/normal/expected_result.json @@ -0,0 +1 @@ +{"success": {"1": {"probes": {"1": {"ip_address": "10.0.4.2", "rtt": 14.0, "host_name": "10.0.4.2"}, "2": {"ip_address": "10.0.4.2", "rtt": 11.0, "host_name": "10.0.4.2"}, "3": {"ip_address": "10.0.4.2", "rtt": 11.0, "host_name": "10.0.4.2"}}}, "2": {"probes": {"1": {"ip_address": "213.250.19.90", "rtt": 175.0, "host_name": "BSN-access.dynamic.siol.net"}, "2": {"ip_address": "213.250.19.90", "rtt": 157.0, "host_name": "BSN-access.dynamic.siol.net"}, "3": {"ip_address": "213.250.19.90", "rtt": 157.0, "host_name": "BSN-access.dynamic.siol.net"}}}, "3": {"probes": {"1": {"ip_address": "95.176.241.222", "rtt": 178.0, "host_name": "95.176.241.222"}, "2": {"ip_address": "95.176.241.222", "rtt": 266.0, "host_name": "95.176.241.222"}, "3": {"ip_address": "95.176.241.222", "rtt": 208.0, "host_name": "95.176.241.222"}}}, "4": {"probes": {"1": {"ip_address": "213.250.1.130", "rtt": 320.0, "host_name": "BSN-250-1-130.static.siol.net"}, "2": {"ip_address": "213.250.1.130", "rtt": 300.0, "host_name": "BSN-250-1-130.static.siol.net"}, "3": {"ip_address": "213.250.1.130", "rtt": 138.0, "host_name": "BSN-250-1-130.static.siol.net"}}}, "5": {"probes": {"1": {"ip_address": "209.85.248.115", "rtt": 122.0, "host_name": "BSN-209.85.248.115.static.siol.net"}, "2": {"ip_address": "209.85.248.217", "rtt": 157.0, "host_name": "209.85.248.217"}, "3": {"ip_address": "72.14.237.184", "rtt": 195.0, "host_name": "72.14.237.184"}}}, "6": {"probes": {"1": {"ip_address": "209.85.248.1", "rtt": 122.0, "host_name": "BSN-0.static.siol.net"}, "2": {"ip_address": "209.85.248.217", "rtt": 157.0, "host_name": "209.85.248.217"}, "3": {"ip_address": "209.85.248.217", "rtt": 195.0, "host_name": "209.85.248.217"}}}, "7": {"probes": {"1": {"ip_address": "", "rtt": 0.0, "host_name": ""}, "2": {"ip_address": "209.85.1.1", "rtt": 157.0, "host_name": "209.85.1.1"}, "3": {"ip_address": "209.85.1.1", "rtt": 195.0, "host_name": "209.85.1.1"}}}, "8": {"probes": {"1": {"ip_address": "", "rtt": 0.0, "host_name": ""}, "2": {"ip_address": "", "rtt": 0.0, "host_name": ""}, "3": {"ip_address": "", "rtt": 0.0, "host_name": ""}}}, "9": {"probes": {"1": {"ip_address": "8.8.8.8", "rtt": 213.0, "host_name": "google-public-dns-a.google.com"}, "2": {"ip_address": "8.8.8.8", "rtt": 210.0, "host_name": "google-public-dns-a.google.com"}, "3": {"ip_address": "8.8.8.8", "rtt": 197.0, "host_name": "google-public-dns-a.google.com"}}}}} diff --git a/test/unit/mocked_data/test_traceroute/normal/traceroute_8_8_8_8_ttl_0_255_timeout_2.txt b/test/unit/mocked_data/test_traceroute/normal/traceroute_8_8_8_8_ttl_0_255_timeout_2.txt new file mode 100755 index 0000000..c67be57 --- /dev/null +++ b/test/unit/mocked_data/test_traceroute/normal/traceroute_8_8_8_8_ttl_0_255_timeout_2.txt @@ -0,0 +1,16 @@ +Type escape sequence to abort. +Tracing the route to google-public-dns-a.google.com (8.8.8.8) +VRF info: (vrf in name/id, vrf out name/id) + 1 10.0.4.2 14 msec 11 msec 11 msec + 2 BSN-access.dynamic.siol.net (213.250.19.90) 175 msec 157 msec 157 msec + 3 95.176.241.222 178 msec 266 msec 208 msec + 4 BSN-250-1-130.static.siol.net (213.250.1.130) 320 msec 300 msec 138 msec + 5 BSN-209.85.248.115.static.siol.net (209.85.248.115) 122 msec + 209.85.248.217 157 msec + 72.14.237.184 195 msec + 6 BSN-0.static.siol.net (209.85.248.1) 122 msec + 209.85.248.217 157 msec 195 msec + 7 * + 209.85.1.1 157 msec 195 msec + 8 * * * + 9 google-public-dns-a.google.com (8.8.8.8) 213 msec 210 msec 197 msec \ No newline at end of file From 9ceb34003279077383902363ea4efc659f01d661 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 13 Dec 2016 11:56:27 -0800 Subject: [PATCH 38/41] Fixing issue with lldp neighbors detail and padding --- napalm_ios/ios.py | 17 ++--------------- setup.cfg | 1 + 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index a794858..a604968 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -465,16 +465,6 @@ def get_lldp_neighbors_detail(self, interface=''): Calls get_lldp_neighbors. """ - def pad_list_entries(my_list, list_length): - """Normalize the length of all the LLDP fields.""" - if len(my_list) < list_length: - for i in range(list_length): - try: - my_list[i] - except IndexError: - my_list[i] = u"N/A" - return my_list - lldp = {} lldp_neighbors = self.get_lldp_neighbors() @@ -501,14 +491,11 @@ def pad_list_entries(my_list, list_length): lldp_fields = [port_id, port_description, chassis_id, system_name, system_description, system_capabilities, enabled_capabilities, remote_address] - # Check length of each list + # re.findall will return a list. Make sure same number of entries always returned. for test_list in lldp_fields: - if len(test_list) > number_entries: + if len(test_list) != number_entries: raise ValueError("Failure processing show lldp neighbors detail") - # Pad any missing entries with "N/A" - lldp_fields = [pad_list_entries(field, number_entries) for field in lldp_fields] - # Standardize the fields port_id, port_description, chassis_id, system_name, system_description, \ system_capabilities, enabled_capabilities, remote_address = lldp_fields diff --git a/setup.cfg b/setup.cfg index 8178cc1..7e73a45 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,7 @@ [pylama] linters = mccabe,pep8,pyflakes ignore = D203,C901 +skip = build/*,.tox/* [pylama:pep8] max_line_length = 100 From 4e319f31b5b19378a448aef6b7e9f61c78bca220 Mon Sep 17 00:00:00 2001 From: Kirk Byers Date: Tue, 13 Dec 2016 12:27:09 -0800 Subject: [PATCH 39/41] Fixing get_lldp_neighbors_details to support interface argument --- napalm_ios/ios.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/napalm_ios/ios.py b/napalm_ios/ios.py index a604968..e3048d6 100755 --- a/napalm_ios/ios.py +++ b/napalm_ios/ios.py @@ -468,6 +468,14 @@ def get_lldp_neighbors_detail(self, interface=''): lldp = {} lldp_neighbors = self.get_lldp_neighbors() + # Filter to specific interface + if interface: + lldp_data = lldp_neighbors.get(interface) + if lldp_data: + lldp_neighbors = {interface: lldp_data} + else: + lldp_neighbors = {} + for interface in lldp_neighbors: command = "show lldp neighbors {} detail".format(interface) output = self._send_command(command) From 16bbb79e40b55b5959f9b32a39c6aed701441d4f Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Wed, 14 Dec 2016 03:20:17 +0000 Subject: [PATCH 40/41] Adapt SNMP templates to IOS syntax --- napalm_ios/templates/delete_snmp_config.j2 | 8 ++++---- napalm_ios/templates/snmp_config.j2 | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/napalm_ios/templates/delete_snmp_config.j2 b/napalm_ios/templates/delete_snmp_config.j2 index 0543dfe..dc8e056 100644 --- a/napalm_ios/templates/delete_snmp_config.j2 +++ b/napalm_ios/templates/delete_snmp_config.j2 @@ -1,14 +1,14 @@ {% if (location is defined) and location %} -no snmp-server location "{{location}}" +no snmp-server location {% endif %} {% if (contact is defined) and contact %} -no snmp-server contact "{{contact}}" +no snmp-server contact {% endif %} {% if (chassis_id is defined) and chassis_id %} -no snmp-server chassis-id "{{chassis_id}}" +no snmp-server chassis-id {% endif %} {% if (community is defined) and community %} {% for comm_name, comm_details in community.iteritems() %} -no community {{comm_name}} +no snmp-server community {{comm_name}} {% endfor %} {% endif %} diff --git a/napalm_ios/templates/snmp_config.j2 b/napalm_ios/templates/snmp_config.j2 index 4e98e56..ac4486f 100644 --- a/napalm_ios/templates/snmp_config.j2 +++ b/napalm_ios/templates/snmp_config.j2 @@ -11,12 +11,12 @@ snmp-server chassis-id "{{chassis_id}}" {% for comm_name, comm_details in community.iteritems() %} {% if (comm_details is defined) and comm_details %} {% if (comm_details.get('mode') is defined) and comm_details.get('mode') == 'rw' %} -community {{comm_name}} rw +community {{comm_name}} RW {% else %} -community {{comm_name}} ro +community {{comm_name}} RO {% endif %} {% else %} -community {{comm_name}} ro +community {{comm_name}} RO {% endif %} {% endfor %} {% endif %} From aab6851c97b14dad9eefd69ac703560799d78b5b Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Fri, 16 Dec 2016 11:02:12 +0800 Subject: [PATCH 41/41] Version bump to 0.5.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 716be0a..6ff16f8 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="napalm-ios", - version="0.4.0", + version="0.5.0", packages=find_packages(), author="Kirk Byers", author_email="ktbyers@twb-tech.com",