From e5a7c31405c1d8e9aa04f6919b779ef3c06af23a Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Sun, 18 Dec 2016 19:09:17 +0100 Subject: [PATCH 01/11] add vm port, don't expect established bgp session --- setup.py | 8 ++++---- test/unit/conftest.py | 1 + .../test_get_bgp_neighbors/normal/expected_result.json | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 02223f6..c469729 100644 --- a/setup.py +++ b/setup.py @@ -5,17 +5,17 @@ from setuptools import setup, find_packages from pip.req import parse_requirements -__author__ = 'Shota Muto ' +__author__ = 'Piotr Pieprzycki ' install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1()) reqs = [str(ir.req) for ir in install_reqs] setup( name="napalm-vyos", - version="0.1.1", + version="0.1.2", packages=find_packages(), - author="Shota Muto", - author_email="dos9954@gmail.com", + author="Piotr Pieprzycki, Shota Muto", + author_email="piotr.pieprzycki@dreamlab.pl, dos9954@gmail.com", description="Network Automation and Programmability Abstraction Layer with Multivendor support", classifiers=[ 'Topic :: Utilities', diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 8358f78..6b5028d 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -31,6 +31,7 @@ class PatchedVyOSDriver(vyos.VyOSDriver): """Patched VyOS Driver.""" def __init__(self, hostname, username, password, timeout=60, optional_args=None): + optional_args = {'port': '12206'} super().__init__(hostname, username, password, timeout, optional_args) self.patched_attrs = ['device'] 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 index ecc4db8..cd2a323 100644 --- 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 @@ -1 +1 @@ -{"global": {"router_id": "...", "peers": {"10.0.1.100": {"is_enabled": true, "uptime": "...", "remote_as": 65001, "description": "", "remote_id": "...", "local_as": 65002, "is_up": true, "address_family": {"ipv4": {"sent_prefixes": -1, "accepted_prefixes": "...", "received_prefixes": "..."}}}}}} +{"global": {"router_id": "...", "peers": {"10.0.1.100": {"is_enabled": true, "uptime": "...", "remote_as": 65001, "description": "", "remote_id": "...", "local_as": 65002, "is_up": "...", "address_family": {"ipv4": {"sent_prefixes": -1, "accepted_prefixes": "...", "received_prefixes": "..."}}}}}} From 5249d52caf555b9d55149cfb5b1b27629e169c5b Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Mon, 19 Dec 2016 09:27:40 +0100 Subject: [PATCH 02/11] update port --- test/unit/TestVyOSDriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/TestVyOSDriver.py b/test/unit/TestVyOSDriver.py index 9ebcb74..cde1693 100644 --- a/test/unit/TestVyOSDriver.py +++ b/test/unit/TestVyOSDriver.py @@ -26,7 +26,7 @@ def setUpClass(cls): username = 'vagrant' password = 'vagrant' cls.vendor = 'vyos' - cls.port = '2200' + cls.port = '12206' optional_args = {'port': '12206'} cls.device = vyos.VyOSDriver(hostname, username, password, From aa1ad764f102c1d2f92c361c14f29987afc484a3 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Mon, 19 Dec 2016 09:58:09 +0100 Subject: [PATCH 03/11] remove print from load functions --- napalm_vyos/vyos.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 2a22b88..a65a98f 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -115,7 +115,7 @@ def load_replace_candidate(self, filename=None, config=None): if filename is not None: if os.path.exists(filename) is True: self._scp_client.scp_transfer_file(filename, self._DEST_FILENAME) - print self._device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME) + self._device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME) output_loadcmd = self._device.send_config_set(['load '+self._DEST_FILENAME]) match_loaded = re.findall("Load complete.", output_loadcmd) match_notchanged = re.findall("No configuration changes to commit", output_loadcmd) @@ -142,8 +142,8 @@ def load_merge_candidate(self, filename=None, config=None): if filename is not None: if os.path.exists(filename) is True: with open(filename) as f: - print self._device.send_command("cp "+self._BOOT_FILENAME+" " - + self._BACKUP_FILENAME) + self._device.send_command("cp "+self._BOOT_FILENAME+" " + + self._BACKUP_FILENAME) self._new_config = f.read() cfg = [x for x in self._new_config.split("\n") if x is not ""] output_loadcmd = self._device.send_config_set(cfg) From 37ae8512c0ee5d502bb386016db170546b5d94da Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Mon, 19 Dec 2016 12:22:05 +0100 Subject: [PATCH 04/11] PatchedDriver overload --- test/unit/conftest.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 6b5028d..ce5fce4 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -37,6 +37,18 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.patched_attrs = ['device'] self.device = FakeVyOSDevice() + def disconnect(self): + pass + + def is_alive(self): + return { + 'is_alive': True # In testing everything works.. + } + + def open(self): + pass + + class FakeVyOSDevice(BaseTestDouble): """VyOS device test double.""" From a63df96adedef542717d05e53fad2536e7b301b6 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 13:03:59 +0100 Subject: [PATCH 05/11] changes in mock tests --- AUTHORS | 5 +- napalm_vyos/vyos.py | 223 ++++++++++-------- setup.py | 4 +- test/unit/conftest.py | 38 ++- .../normal/expected_result.json | 2 +- .../normal/expected_result.json | 2 +- .../normal/expected_result.json | 2 +- .../test_is_alive/normal/expected_result.json | 1 + 8 files changed, 148 insertions(+), 129 deletions(-) create mode 100644 test/unit/mocked_data/test_is_alive/normal/expected_result.json diff --git a/AUTHORS b/AUTHORS index b4c1c5c..f3beb72 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,3 @@ -David Barroso -Elisa Jasinska -Shota Muto +Shota Muto Piotr Pieprzycki +David Barroso diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index a65a98f..8a026aa 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -198,8 +198,16 @@ def get_environment(self): r b swpd free buff cache si so bi bo in cs us sy id wa 0 0 0 61404 139624 139360 0 0 0 0 9 14 0 0 100 0 """ - output_cpu = self._device.send_command("vmstat").split("\n")[-1] - cpu = 100 - int(output_cpu.split()[-2]) + output_cpu_list = list() + output_cpu = self._device.send_command("vmstat") + output_cpu = str(output_cpu) + output_cpu_list = output_cpu.split("\n") + if len(output_cpu_list[-1]) > 0: + output_cpu_list = output_cpu_list[-1] + else: + output_cpu_list = output_cpu_list[-2] + output_cpu_idle = output_cpu_list.split()[-2] + cpu = 100 - int(output_cpu_idle) """ 'free' output: @@ -365,48 +373,50 @@ def get_ntp_stats(self): 133.130.120.204 133.243.238.164 2 u 46 64 377 7.717 987996. 1669.77 """ - output = self._device.send_command("ntpq -np").split("\n")[2:] + output = self._device.send_command("ntpq -np") + output = output.split("\n")[2:] ntp_stats = list() for ntp_info in output: - - remote, refid, st, t, when, hostpoll, reachability, delay, offset, \ - jitter = ntp_info.split() - - # 'remote' contains '*' if the machine synchronized with NTP server - synchronized = "*" in remote - - match = re.search("(\d+\.\d+\.\d+\.\d+)", remote) - ip = match.group(1) - - when = when if when != '-' else 0 - - ntp_stats.append({ - "remote": unicode(ip), - "referenceid": unicode(refid), - "synchronized": bool(synchronized), - "stratum": int(st), - "type": unicode(t), - "when": unicode(when), - "hostpoll": int(hostpoll), - "reachability": int(reachability), - "delay": float(delay), - "offset": float(offset), - "jitter": float(jitter) - }) + if len(ntp_info) > 0: + remote, refid, st, t, when, hostpoll, reachability, delay, offset, \ + jitter = ntp_info.split() + + # 'remote' contains '*' if the machine synchronized with NTP server + synchronized = "*" in remote + + match = re.search("(\d+\.\d+\.\d+\.\d+)", remote) + ip = match.group(1) + + when = when if when != '-' else 0 + + ntp_stats.append({ + "remote": unicode(ip), + "referenceid": unicode(refid), + "synchronized": bool(synchronized), + "stratum": int(st), + "type": unicode(t), + "when": unicode(when), + "hostpoll": int(hostpoll), + "reachability": int(reachability), + "delay": float(delay), + "offset": float(offset), + "jitter": float(jitter) + }) return ntp_stats def get_ntp_peers(self): - output = self._device.send_command("ntpq -np").split("\n")[2:] - + output = self._device.send_command("ntpq -np") + output_peers = output.split("\n")[2:] ntp_peers = dict() - for line in output: - match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line) - ntp_peers.update({ - unicode(match.group(1)): {} - }) + for line in output_peers: + if len(line) > 0: + match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line) + ntp_peers.update({ + unicode(match.group(1)): {} + }) return ntp_peers @@ -426,7 +436,8 @@ def get_bgp_neighbors(self): 192.168.1.4 4 64522 0 0 0 0 0 never Active """ - output = self._device.send_command("show ip bgp summary").split("\n") + output = self._device.send_command("show ip bgp summary") + output = output.split("\n") match = re.search(".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)", output[0]) @@ -444,65 +455,66 @@ def get_bgp_neighbors(self): bgp_info = [i.strip() for i in output[6:-2] if i is not ""] for i in bgp_info: - peer_id, bgp_version, remote_as, msg_rcvd, msg_sent, table_version, \ - in_queue, out_queue, up_time, state_prefix = i.split() - - is_enabled = "(Admin)" not in state_prefix - - received_prefixes = None - - try: - state_prefix = int(state_prefix) - received_prefixes = int(state_prefix) - is_up = True - except ValueError: - is_up = False - - if bgp_version == "4": - address_family = "ipv4" - elif bgp_version == "6": - address_family = "ipv6" - else: - raise ValueError("BGP neighbor parsing failed") - - """ - 'show ip bgp neighbors 192.168.1.1' output example: - BGP neighbor is 192.168.1.1, remote AS 64519, local AS 64520, external link - BGP version 4, remote router ID 192.168.1.1 - For address family: IPv4 Unicast - ~~~ - Community attribute sent to this neighbor(both) - 1 accepted prefixes - ~~~ - """ - bgp_detail = self._device.send_command("show ip bgp neighbors %s" % peer_id) - - match_rid = re.search("remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail) - remote_rid = match_rid.group(1) - - match_prefix_accepted = re.search("(\d+) accepted prefixes", bgp_detail) - accepted_prefixes = match_prefix_accepted.group(1) - - bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {}) - peer_dict = { - "description": unicode(""), - "is_enabled": bool(is_enabled), - "local_as": int(local_as), - "is_up": bool(is_up), - "remote_id": unicode(remote_rid), - "uptime": int(self._bgp_time_conversion(up_time)), - "remote_as": int(remote_as) - } + if len(i) > 0: + peer_id, bgp_version, remote_as, msg_rcvd, msg_sent, table_version, \ + in_queue, out_queue, up_time, state_prefix = i.split() + + is_enabled = "(Admin)" not in state_prefix + + received_prefixes = None + + try: + state_prefix = int(state_prefix) + received_prefixes = int(state_prefix) + is_up = True + except ValueError: + is_up = False + + if bgp_version == "4": + address_family = "ipv4" + elif bgp_version == "6": + address_family = "ipv6" + else: + raise ValueError("BGP neighbor parsing failed") + + """ + 'show ip bgp neighbors 192.168.1.1' output example: + BGP neighbor is 192.168.1.1, remote AS 64519, local AS 64520, external link + BGP version 4, remote router ID 192.168.1.1 + For address family: IPv4 Unicast + ~~~ + Community attribute sent to this neighbor(both) + 1 accepted prefixes + ~~~ + """ + bgp_detail = self._device.send_command("show ip bgp neighbors %s" % peer_id) + + match_rid = re.search("remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail) + remote_rid = match_rid.group(1) + + match_prefix_accepted = re.search("(\d+) accepted prefixes", bgp_detail) + accepted_prefixes = match_prefix_accepted.group(1) + + bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {}) + peer_dict = { + "description": unicode(""), + "is_enabled": bool(is_enabled), + "local_as": int(local_as), + "is_up": bool(is_up), + "remote_id": unicode(remote_rid), + "uptime": int(self._bgp_time_conversion(up_time)), + "remote_as": int(remote_as) + } - af_dict = dict() - af_dict[address_family] = { - "sent_prefixes": int(-1), - "accepted_prefixes": int(accepted_prefixes), - "received_prefixes": int(received_prefixes) - } + af_dict = dict() + af_dict[address_family] = { + "sent_prefixes": int(-1), + "accepted_prefixes": int(accepted_prefixes), + "received_prefixes": int(received_prefixes) + } - peer_dict["address_family"] = af_dict - bgp_neighbor_data["global"]["peers"][peer_id] = peer_dict + peer_dict["address_family"] = af_dict + bgp_neighbor_data["global"]["peers"][peer_id] = peer_dict return bgp_neighbor_data @@ -553,8 +565,10 @@ def get_interfaces_counters(self): """ output = self._device.send_command("show interfaces detail") interfaces = re.findall("(\S+): <.*", output) - count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+", output) + # count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+", output) + count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output) counters = dict() + j = 0 for i in count: @@ -681,13 +695,15 @@ def get_interfaces_ip(self): output = output.split("\n") # delete the header line and the interfaces which has no ip address - ifaces = [x for x in output[3:-1] if "-" not in x] + if len(output[-1]) > 0: + ifaces = [x for x in output[3:] if "-" not in x] + else: + ifaces = [x for x in output[3:-1] if "-" not in x] ifaces_ip = dict() for iface in ifaces: iface = iface.split() - if len(iface) != 1: iface_name = iface[0] @@ -782,7 +798,12 @@ def ping(self, destination, source="", ttl=255, timeout=5, size=100, count=5): # 'packet_info' example: # ['5', 'packets', 'transmitted,' '5', 'received,' '0%', 'packet', # 'loss,', 'time', '3997ms'] - packet_info = output_ping.split("\n")[-2] + packet_info = output_ping.split("\n") + + if len(packet_info[-1]) > 0: + packet_info = packet_info[-2] + else: + packet_info = packet_info[-3] packet_info = [x.strip() for x in packet_info.split()] @@ -792,7 +813,13 @@ def ping(self, destination, source="", ttl=255, timeout=5, size=100, count=5): # 'rtt_info' example: # ["0.307/0.396/0.480/0.061"] - rtt_info = output_ping.split("\n")[-1] + rtt_info = output_ping.split("\n") + + if len(rtt_info[-1]) > 0: + rtt_info = rtt_info[-1] + else: + rtt_info = rtt_info[-2] + match = re.search("([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+)", rtt_info) if match is not None: diff --git a/setup.py b/setup.py index c469729..d486e82 100644 --- a/setup.py +++ b/setup.py @@ -14,8 +14,8 @@ name="napalm-vyos", version="0.1.2", packages=find_packages(), - author="Piotr Pieprzycki, Shota Muto", - author_email="piotr.pieprzycki@dreamlab.pl, dos9954@gmail.com", + author="Piotr Pieprzycki", + author_email="piotr.pieprzycki@dreamlab.pl", description="Network Automation and Programmability Abstraction Layer with Multivendor support", classifiers=[ 'Topic :: Utilities', diff --git a/test/unit/conftest.py b/test/unit/conftest.py index ce5fce4..bf287a1 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -5,6 +5,7 @@ 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_vyos import vyos @@ -36,34 +37,25 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.patched_attrs = ['device'] self.device = FakeVyOSDevice() + self._device = FakeVyOSDevice() - def disconnect(self): - pass + def close(self): + pass - def is_alive(self): - return { - 'is_alive': True # In testing everything works.. - } - - def open(self): - pass + def is_alive(self): + return { + 'is_alive': True # In testing everything works.. + } + def open(self): + pass class FakeVyOSDevice(BaseTestDouble): """VyOS device test double.""" - def run_commands(self, command_list, encoding='json'): - """Fake run_commands.""" - result = list() - - for command in command_list: - filename = '{}.{}'.format(self.sanitize_text(command), encoding) - full_path = self.find_file(filename) - - if encoding == 'json': - result.append(self.read_json_file(full_path)) - else: - result.append({'output': self.read_txt_file(full_path)}) - - return result + def send_command(self, command, **kwargs): + filename = '{}.text'.format(self.sanitize_text(command)) + full_path = self.find_file(filename) + result = self.read_txt_file(full_path) + return py23_compat.text_type(result) 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 index cd2a323..ecc4db8 100644 --- 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 @@ -1 +1 @@ -{"global": {"router_id": "...", "peers": {"10.0.1.100": {"is_enabled": true, "uptime": "...", "remote_as": 65001, "description": "", "remote_id": "...", "local_as": 65002, "is_up": "...", "address_family": {"ipv4": {"sent_prefixes": -1, "accepted_prefixes": "...", "received_prefixes": "..."}}}}}} +{"global": {"router_id": "...", "peers": {"10.0.1.100": {"is_enabled": true, "uptime": "...", "remote_as": 65001, "description": "", "remote_id": "...", "local_as": 65002, "is_up": true, "address_family": {"ipv4": {"sent_prefixes": -1, "accepted_prefixes": "...", "received_prefixes": "..."}}}}}} 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 index a450a60..ab7d4c5 100644 --- 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 @@ -1 +1 @@ -{"eth1": {"tx_discards": 0, "tx_unicast_packets": "...", "rx_broadcast_packets": -1, "rx_discards": 0, "tx_multicast_packets": -1, "tx_octets": "...", "tx_errors": 0, "rx_octets": "...", "rx_errors": 0, "tx_broadcast_packets": -1, "rx_multicast_packets": "...", "rx_unicast_packets": "..."}, "eth0": {"tx_discards": 0, "tx_unicast_packets": "...", "rx_broadcast_packets": -1, "rx_discards": 0, "tx_multicast_packets": -1, "tx_octets": "...", "tx_errors": 0, "rx_octets": "...", "rx_errors": 0, "tx_broadcast_packets": -1, "rx_multicast_packets": "...", "rx_unicast_packets": "..."}, "eth2": {"tx_discards": 0, "tx_unicast_packets": "...", "rx_broadcast_packets": -1, "rx_discards": 0, "tx_multicast_packets": -1, "tx_octets": "...", "tx_errors": 0, "rx_octets": "...", "rx_errors": 0, "tx_broadcast_packets": -1, "rx_multicast_packets": "...", "rx_unicast_packets": "..."}} +{"lo": {"tx_multicast_packets": "...", "tx_discards": "...", "tx_octets": "...", "tx_errors": "...", "rx_octets": "...", "tx_unicast_packets": "...", "rx_errors": "...", "tx_broadcast_packets": "...", "rx_multicast_packets": "...", "rx_broadcast_packets": "...", "rx_discards": "...", "rx_unicast_packets": "..."},"eth1": {"tx_discards": "...", "tx_unicast_packets": "...", "rx_broadcast_packets": "...", "rx_discards": "...", "tx_multicast_packets": "...", "tx_octets": "...", "tx_errors": "...", "rx_octets": "...", "rx_errors": "...", "tx_broadcast_packets": "...", "rx_multicast_packets": "...", "rx_unicast_packets": "..."}, "eth0": {"tx_discards": "...", "tx_unicast_packets": "...", "rx_broadcast_packets": "...", "rx_discards": "...", "tx_multicast_packets": "...", "tx_octets": "...", "tx_errors": "...", "rx_octets": "...", "rx_errors": "...", "tx_broadcast_packets": "...", "rx_multicast_packets": "...", "rx_unicast_packets": "..."}, "eth2": {"tx_discards": "...", "tx_unicast_packets": "...", "rx_broadcast_packets": "...", "rx_discards": "...", "tx_multicast_packets": "...", "tx_octets": "...", "tx_errors": "...", "rx_octets": "...", "rx_errors": "...", "tx_broadcast_packets": "...", "rx_multicast_packets": "...", "rx_unicast_packets": "..."}} 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 index 8f641ca..456fae8 100644 --- 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 @@ -1 +1 @@ -{"lo": {"ipv4": {"8.8.8.8": {"prefix_length": 32}, "127.0.0.1": {"prefix_length": 8}, "10.2.2.2": {"prefix_length": 32}}}, "eth1": {"ipv4": {"10.0.1.222": {"prefix_length": 24}}}, "eth0": {"ipv4": {"10.0.2.15": {"prefix_length": 24}}}} +{"lo": {"ipv4": {"8.8.8.8": {"prefix_length": 32}, "127.0.0.1": {"prefix_length": 8}, "10.2.2.2": {"prefix_length": 32}}, "ipv6": {"::1": {"prefix_length": 128}}}, "eth1": {"ipv4": {"10.0.1.222": {"prefix_length": 24}}}, "eth0": {"ipv4": {"10.0.2.15": {"prefix_length": 24}}}} 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..43b92ac --- /dev/null +++ b/test/unit/mocked_data/test_is_alive/normal/expected_result.json @@ -0,0 +1 @@ +{"is_alive": true} From 875ad85bd752381dd2f9527fd4ba908bf827343e Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 13:49:40 +0100 Subject: [PATCH 06/11] Change variable in vyos.py, add mocked data --- napalm_vyos/vyos.py | 64 ++++----- test/unit/conftest.py | 5 +- .../test_get_arp_table/normal/show_arp.text | 5 +- .../show_ip_bgp_neighbors_10_0_12_1.text | 43 ------ .../show_ip_bgp_neighbors_10_0_1_100.text | 36 +++++ .../normal/show_ip_bgp_summary.text | 4 +- .../cat__proc_uptime___awk___print__1__.text | 1 + .../normal/show_configuration.text | 124 ++++++++++++++++++ .../test_get_facts/normal/show_version.text | 13 ++ .../normal/show_configuration.text | 124 ++++++++++++++++++ .../normal/show_interfaces_detail.text | 44 +++++++ .../normal/show_interfaces.text | 10 ++ .../test_get_ntp_peers/normal/ntpq__np.text | 3 + .../test_get_ntp_stats/normal/ntpq__np.text | 3 + .../normal/show_configuration.text | 124 ++++++++++++++++++ .../normal/show_configuration_commands.text | 39 ++++++ ...ttl_255_deadline_5_size_100_count_5_.text} | 0 17 files changed, 561 insertions(+), 81 deletions(-) delete mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_12_1.text create mode 100644 test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_1_100.text create mode 100644 test/unit/mocked_data/test_get_facts/normal/cat__proc_uptime___awk___print__1__.text create mode 100644 test/unit/mocked_data/test_get_facts/normal/show_configuration.text create mode 100644 test/unit/mocked_data/test_get_facts/normal/show_version.text create mode 100644 test/unit/mocked_data/test_get_interfaces/normal/show_configuration.text create mode 100644 test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces_detail.text create mode 100644 test/unit/mocked_data/test_get_interfaces_ip/normal/show_interfaces.text create mode 100644 test/unit/mocked_data/test_get_ntp_peers/normal/ntpq__np.text create mode 100644 test/unit/mocked_data/test_get_ntp_stats/normal/ntpq__np.text create mode 100644 test/unit/mocked_data/test_get_snmp_information/normal/show_configuration.text create mode 100644 test/unit/mocked_data/test_get_users/normal/show_configuration_commands.text rename test/unit/mocked_data/test_ping/normal/{ping_8.8.8.8_timeout_2_size_100_repeat_5.text => ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text} (100%) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 8a026aa..ac96390 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -51,7 +51,7 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self._username = username self._password = password self._timeout = timeout - self._device = None + self.device = None self._scp_client = None self._new_config = None self._old_config = None @@ -91,19 +91,19 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.port = optional_args.get('port', 22) def open(self): - self._device = ConnectHandler(device_type='vyos', + self.device = ConnectHandler(device_type='vyos', host=self._hostname, username=self._username, password=self._password, **self.netmiko_optional_args) try: - self._scp_client = SCPConn(self._device) + self._scp_client = SCPConn(self.device) except: raise ConnectionException("Failed to open connection ") def close(self): - self._device.disconnect() + self.device.disconnect() def load_replace_candidate(self, filename=None, config=None): """ @@ -115,8 +115,8 @@ def load_replace_candidate(self, filename=None, config=None): if filename is not None: if os.path.exists(filename) is True: self._scp_client.scp_transfer_file(filename, self._DEST_FILENAME) - self._device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME) - output_loadcmd = self._device.send_config_set(['load '+self._DEST_FILENAME]) + self.device.send_command("cp "+self._BOOT_FILENAME+" "+self._BACKUP_FILENAME) + output_loadcmd = self.device.send_config_set(['load '+self._DEST_FILENAME]) match_loaded = re.findall("Load complete.", output_loadcmd) match_notchanged = re.findall("No configuration changes to commit", output_loadcmd) match_failed = re.findall("Failed to parse specified config file", output_loadcmd) @@ -142,11 +142,11 @@ def load_merge_candidate(self, filename=None, config=None): if filename is not None: if os.path.exists(filename) is True: with open(filename) as f: - self._device.send_command("cp "+self._BOOT_FILENAME+" " + self.device.send_command("cp "+self._BOOT_FILENAME+" " + self._BACKUP_FILENAME) self._new_config = f.read() cfg = [x for x in self._new_config.split("\n") if x is not ""] - output_loadcmd = self._device.send_config_set(cfg) + output_loadcmd = self.device.send_config_set(cfg) match_setfailed = re.findall("Delete failed", output_loadcmd) match_delfailed = re.findall("Set failed", output_loadcmd) @@ -161,10 +161,10 @@ def load_merge_candidate(self, filename=None, config=None): raise MergeConfigException("no configuration found") def discard_config(self): - self._device.exit_config_mode() + self.device.exit_config_mode() def compare_config(self): - output_compare = self._device.send_config_set(['compare']) + output_compare = self.device.send_config_set(['compare']) match = re.findall("No changes between working and active configurations", output_compare) if match: @@ -174,22 +174,22 @@ def compare_config(self): return diff def commit_config(self): - if self._device.commit(): - self._device.send_config_set(['save']) - self._device.exit_config_mode() + if self.device.commit(): + self.device.send_config_set(['save']) + self.device.exit_config_mode() def rollback(self, filename=None): """Rollback configuration to filename or to self.rollback_cfg file.""" if filename is None: filename = self._BACKUP_FILENAME - output_loadcmd = self._device.send_config_set(['load '+filename]) + output_loadcmd = self.device.send_config_set(['load '+filename]) match = re.findall("Load complete.", output_loadcmd) if not match: raise ReplaceConfigException("Failed rollback config: " + output_loadcmd) else: - self._device.send_config_set(['commit', 'save']) + self.device.send_config_set(['commit', 'save']) def get_environment(self): """ @@ -199,7 +199,7 @@ def get_environment(self): 0 0 0 61404 139624 139360 0 0 0 0 9 14 0 0 100 0 """ output_cpu_list = list() - output_cpu = self._device.send_command("vmstat") + output_cpu = self.device.send_command("vmstat") output_cpu = str(output_cpu) output_cpu_list = output_cpu.split("\n") if len(output_cpu_list[-1]) > 0: @@ -216,7 +216,7 @@ def get_environment(self): -/+ buffers/cache: 167800 340356 Swap: 0 0 0 """ - output_ram = self._device.send_command("free").split("\n")[1] + output_ram = self.device.send_command("free").split("\n")[1] available_ram, used_ram = output_ram.split()[1:3] environment = { @@ -265,7 +265,7 @@ def get_interfaces(self): lo 127.0.0.1/8 u/u ::1/128 """ - output_iface = self._device.send_command("show interfaces") + output_iface = self.device.send_command("show interfaces") # Collect all interfaces' name and status match = re.findall("(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface) @@ -275,7 +275,7 @@ def get_interfaces(self): iface_state = {iface_name: {"State": state, "Link": link} for iface_name, state, link in match} - output_conf = self._device.send_command("show configuration") + output_conf = self.device.send_command("show configuration") # Convert the configuration to dictionary config = vyattaconfparser.parse_conf(output_conf) @@ -334,7 +334,7 @@ def get_arp_table(self): 10.129.2.97 ether 00:50:56:9f:64:09 C eth0 192.168.1.3 ether 00:50:56:86:7b:06 C eth1 """ - output = self._device.send_command("show arp") + output = self.device.send_command("show arp") output = output.split("\n") # Skip the header line @@ -373,7 +373,7 @@ def get_ntp_stats(self): 133.130.120.204 133.243.238.164 2 u 46 64 377 7.717 987996. 1669.77 """ - output = self._device.send_command("ntpq -np") + output = self.device.send_command("ntpq -np") output = output.split("\n")[2:] ntp_stats = list() @@ -407,7 +407,7 @@ def get_ntp_stats(self): return ntp_stats def get_ntp_peers(self): - output = self._device.send_command("ntpq -np") + output = self.device.send_command("ntpq -np") output_peers = output.split("\n")[2:] ntp_peers = dict() @@ -436,7 +436,7 @@ def get_bgp_neighbors(self): 192.168.1.4 4 64522 0 0 0 0 0 never Active """ - output = self._device.send_command("show ip bgp summary") + output = self.device.send_command("show ip bgp summary") output = output.split("\n") match = re.search(".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)", @@ -487,7 +487,7 @@ def get_bgp_neighbors(self): 1 accepted prefixes ~~~ """ - bgp_detail = self._device.send_command("show ip bgp neighbors %s" % peer_id) + bgp_detail = self.device.send_command("show ip bgp neighbors %s" % peer_id) match_rid = re.search("remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail) remote_rid = match_rid.group(1) @@ -563,7 +563,7 @@ def get_interfaces_counters(self): TX: bytes packets errors dropped carrier collisions 32776498 279273 0 0 0 0 """ - output = self._device.send_command("show interfaces detail") + output = self.device.send_command("show interfaces detail") interfaces = re.findall("(\S+): <.*", output) # count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+", output) count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output) @@ -603,7 +603,7 @@ def get_interfaces_counters(self): def get_snmp_information(self): # 'acl' is not implemented yet - output = self._device.send_command("show configuration") + output = self.device.send_command("show configuration") # convert the configuration to dictionary config = vyattaconfparser.parse_conf(output) @@ -630,11 +630,11 @@ def get_snmp_information(self): return {} def get_facts(self): - output_uptime = self._device.send_command("cat /proc/uptime | awk '{print $1}'") + output_uptime = self.device.send_command("cat /proc/uptime | awk '{print $1}'") uptime = int(float(output_uptime)) - output = self._device.send_command("show version").split("\n") + output = self.device.send_command("show version").split("\n") ver_str = [line for line in output if "Version" in line][0] version = self.parse_version(ver_str) @@ -644,7 +644,7 @@ def get_facts(self): hwmodel_str = [line for line in output if "HW model" in line][0] hwmodel = self.parse_hwmodel(hwmodel_str) - output = self._device.send_command("show configuration") + output = self.device.send_command("show configuration") config = vyattaconfparser.parse_conf(output) if "host-name" in config["system"]: @@ -691,7 +691,7 @@ def parse_hwmodel(model_str): return model[1].strip() def get_interfaces_ip(self): - output = self._device.send_command("show interfaces") + output = self.device.send_command("show interfaces") output = output.split("\n") # delete the header line and the interfaces which has no ip address @@ -732,7 +732,7 @@ def _get_ip_version(ip_address): return "ipv4" def get_users(self): - output = self._device.send_command("show configuration commands").split("\n") + output = self.device.send_command("show configuration commands").split("\n") user_conf = [x.split() for x in output if "login user" in x] @@ -785,7 +785,7 @@ def ping(self, destination, source="", ttl=255, timeout=5, size=100, count=5): command += "interface %s " % source ping_result = dict() - output_ping = self._device.send_command(command) + output_ping = self.device.send_command(command) if "Unknown host" in output_ping: err = "Unknown host" diff --git a/test/unit/conftest.py b/test/unit/conftest.py index bf287a1..0a5b115 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -37,7 +37,7 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.patched_attrs = ['device'] self.device = FakeVyOSDevice() - self._device = FakeVyOSDevice() + #self._device = FakeVyOSDevice() def close(self): pass @@ -54,8 +54,11 @@ def open(self): class FakeVyOSDevice(BaseTestDouble): """VyOS device test double.""" + + def send_command(self, command, **kwargs): filename = '{}.text'.format(self.sanitize_text(command)) + print filename full_path = self.find_file(filename) result = self.read_txt_file(full_path) return py23_compat.text_type(result) diff --git a/test/unit/mocked_data/test_get_arp_table/normal/show_arp.text b/test/unit/mocked_data/test_get_arp_table/normal/show_arp.text index 6e5efde..0580ae9 100644 --- a/test/unit/mocked_data/test_get_arp_table/normal/show_arp.text +++ b/test/unit/mocked_data/test_get_arp_table/normal/show_arp.text @@ -1,5 +1,4 @@ Address HWtype HWaddress Flags Mask Iface -10.0.12.33 (incomplete) eth1 -10.0.12.1 ether 08:00:27:60:0f:ee C eth1 -10.0.2.2 ether 52:54:00:12:35:02 C eth0 10.0.2.3 ether 52:54:00:12:35:03 C eth0 +10.0.1.100 ether 08:00:27:27:03:8e C eth1 +10.0.2.2 ether 52:54:00:12:35:02 C eth0 diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_12_1.text b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_12_1.text deleted file mode 100644 index 6f12f68..0000000 --- a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_12_1.text +++ /dev/null @@ -1,43 +0,0 @@ -BGP neighbor is 10.0.12.1, remote AS 65001, local AS 65002, external link - BGP version 4, remote router ID 10.1.1.1 - BGP state = Established, up for 01w3d00h - Last read 03:39:29, hold time is 90, keepalive interval is 30 seconds - Neighbor capabilities: - 4 Byte AS: advertised and received - Route refresh: advertised and received(old & new) - Address family IPv4 Unicast: advertised and received - Graceful Restart Capabilty: received - Remote Restart timer is 120 seconds - Address families by peer: - none - Graceful restart informations: - End-of-RIB send: IPv4 Unicast - End-of-RIB received: - Message statistics: - Inq depth is 0 - Outq depth is 0 - Sent Rcvd - Opens: 2 2 - Notifications: 1 0 - Updates: 4 2 - Keepalives: 33375 36937 - Route Refresh: 0 0 - Capability: 0 0 - Total: 33382 36941 - Minimum time between advertisement runs is 30 seconds - - For address family: IPv4 Unicast - Community attribute sent to this neighbor(both) - Outbound path policy configured - Route map for outgoing advertisements is *EXPORT-POLICY - 4 accepted prefixes - - Connections established 2; dropped 1 - Last reset 01w3d00h, due to User reset -Local host: 10.0.12.2, Local port: 33945 -Foreign host: 10.0.12.1, Foreign port: 179 -Nexthop: 10.0.12.2 -Nexthop global: fe80::a00:27ff:fe41:d5f8 -Nexthop local: :: -BGP connection: non shared network -Read thread: on Write thread: off diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_1_100.text b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_1_100.text new file mode 100644 index 0000000..20542ad --- /dev/null +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_neighbors_10_0_1_100.text @@ -0,0 +1,36 @@ +BGP neighbor is 10.0.1.100, remote AS 65001, local AS 65002, external link + BGP version 4, remote router ID 10.0.2.100 + BGP state = Established, up for 03w0d00h + Last read 11:37:17, hold time is 180, keepalive interval is 60 seconds + Neighbor capabilities: + 4 Byte AS: advertised and received + Route refresh: advertised and received(old & new) + Address family IPv4 Unicast: advertised and received + Message statistics: + Inq depth is 0 + Outq depth is 0 + Sent Rcvd + Opens: 2 0 + Notifications: 0 0 + Updates: 1 0 + Keepalives: 30257 30255 + Route Refresh: 0 0 + Capability: 0 0 + Total: 30260 30255 + Minimum time between advertisement runs is 30 seconds + + For address family: IPv4 Unicast + Community attribute sent to this neighbor(both) + Outbound path policy configured + Route map for outgoing advertisements is *EXPORT-POLICY + 0 accepted prefixes + + Connections established 1; dropped 0 + Last reset never +Local host: 10.0.1.222, Local port: 179 +Foreign host: 10.0.1.100, Foreign port: 44363 +Nexthop: 10.0.1.222 +Nexthop global: fe80::a00:27ff:feeb:7af9 +Nexthop local: :: +BGP connection: non shared network +Read thread: on Write thread: off diff --git a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.text b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.text index 25c5a56..0164737 100644 --- a/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.text +++ b/test/unit/mocked_data/test_get_bgp_neighbors/normal/show_ip_bgp_summary.text @@ -1,9 +1,9 @@ BGP router identifier 10.2.2.2, local AS number 65002 IPv4 Unicast - max multipaths: ebgp 1 ibgp 1 -RIB entries 9, using 864 bytes of memory +RIB entries 1, using 96 bytes of memory Peers 1, using 4560 bytes of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd -10.0.12.1 4 65001 36938 33380 0 0 0 01w3d00h 4 +10.0.1.100 4 65001 30254 30259 0 0 0 03w0d00h 0 Total number of neighbors 1 diff --git a/test/unit/mocked_data/test_get_facts/normal/cat__proc_uptime___awk___print__1__.text b/test/unit/mocked_data/test_get_facts/normal/cat__proc_uptime___awk___print__1__.text new file mode 100644 index 0000000..a7635e7 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/cat__proc_uptime___awk___print__1__.text @@ -0,0 +1 @@ +1815398.39 diff --git a/test/unit/mocked_data/test_get_facts/normal/show_configuration.text b/test/unit/mocked_data/test_get_facts/normal/show_configuration.text new file mode 100644 index 0000000..06701fe --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/show_configuration.text @@ -0,0 +1,124 @@ +interfaces { + ethernet eth0 { + address dhcp + duplex auto + smp_affinity auto + speed auto + } + ethernet eth1 { + address 10.0.1.222/24 + duplex auto + smp_affinity auto + speed auto + } + loopback lo { + address 10.2.2.2/32 + address 8.8.8.8/32 + } +} +policy { + prefix-list EXPORT { + rule 1 { + action permit + prefix 172.16.2.0/24 + } + rule 65535 { + action permit + prefix 10.2.2.2/32 + } + } + route-map EXPORT-POLICY { + rule 1 { + action permit + match { + ip { + address { + prefix-list EXPORT + } + } + } + } + } +} +protocols { + bgp 65002 { + neighbor 10.0.1.100 { + remote-as 65001 + route-map { + export EXPORT-POLICY + } + } + redistribute { + connected { + route-map EXPORT-POLICY + } + } + } +} +service { + snmp { + community commro { + authorization ro + } + contact admin@foo.corp + location PL,Krakow + } + ssh { + disable-host-validation + port 22 + } +} +system { + config-management { + commit-revisions 20 + } + host-name vyos2 + login { + banner { + pre-login "My banner for all devices" + } + user vagrant { + authentication { + encrypted-password $6$fcHhBu3T$WLmiu6/txlEfWK5uh4mKE8v7qocuftsoAN1oHqPIIoogXAX8zS.SKhB105EExYU6yBy4cKHUD/Q6Mm7CUbVTr. + plaintext-password "" + public-keys vagrant { + key AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== + type ssh-rsa + } + } + level admin + } + user vyos { + authentication { + encrypted-password $1$yHIMnG/J$aWDkd3oDYSYps8twB5vpw1 + plaintext-password "" + } + level admin + } + } + ntp { + server 10.0.1.100 { + } + } + package { + auto-sync 1 + repository community { + components main + distribution helium + password "" + url http://packages.vyos.net/vyos + username "" + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } + time-zone UTC +} diff --git a/test/unit/mocked_data/test_get_facts/normal/show_version.text b/test/unit/mocked_data/test_get_facts/normal/show_version.text new file mode 100644 index 0000000..3750652 --- /dev/null +++ b/test/unit/mocked_data/test_get_facts/normal/show_version.text @@ -0,0 +1,13 @@ +Version: VyOS 1.1.7 +Description: VyOS 1.1.7 (helium) +Copyright: 2016 VyOS maintainers and contributors +Built by: maintainers@vyos.net +Built on: Wed Feb 17 09:57:31 UTC 2016 +Build ID: 1602170957-4459750 +System type: x86 64-bit +Boot via: image +Hypervisor: VMware +HW model: VirtualBox +HW S/N: 0 +HW UUID: 9728B94A-52FA-4C1A-AC83-7C6CA76F6F13 +Uptime: 12:44:18 up 21 days, 20 min, 1 user, load average: 0.00, 0.01, 0.05 diff --git a/test/unit/mocked_data/test_get_interfaces/normal/show_configuration.text b/test/unit/mocked_data/test_get_interfaces/normal/show_configuration.text new file mode 100644 index 0000000..06701fe --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces/normal/show_configuration.text @@ -0,0 +1,124 @@ +interfaces { + ethernet eth0 { + address dhcp + duplex auto + smp_affinity auto + speed auto + } + ethernet eth1 { + address 10.0.1.222/24 + duplex auto + smp_affinity auto + speed auto + } + loopback lo { + address 10.2.2.2/32 + address 8.8.8.8/32 + } +} +policy { + prefix-list EXPORT { + rule 1 { + action permit + prefix 172.16.2.0/24 + } + rule 65535 { + action permit + prefix 10.2.2.2/32 + } + } + route-map EXPORT-POLICY { + rule 1 { + action permit + match { + ip { + address { + prefix-list EXPORT + } + } + } + } + } +} +protocols { + bgp 65002 { + neighbor 10.0.1.100 { + remote-as 65001 + route-map { + export EXPORT-POLICY + } + } + redistribute { + connected { + route-map EXPORT-POLICY + } + } + } +} +service { + snmp { + community commro { + authorization ro + } + contact admin@foo.corp + location PL,Krakow + } + ssh { + disable-host-validation + port 22 + } +} +system { + config-management { + commit-revisions 20 + } + host-name vyos2 + login { + banner { + pre-login "My banner for all devices" + } + user vagrant { + authentication { + encrypted-password $6$fcHhBu3T$WLmiu6/txlEfWK5uh4mKE8v7qocuftsoAN1oHqPIIoogXAX8zS.SKhB105EExYU6yBy4cKHUD/Q6Mm7CUbVTr. + plaintext-password "" + public-keys vagrant { + key AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== + type ssh-rsa + } + } + level admin + } + user vyos { + authentication { + encrypted-password $1$yHIMnG/J$aWDkd3oDYSYps8twB5vpw1 + plaintext-password "" + } + level admin + } + } + ntp { + server 10.0.1.100 { + } + } + package { + auto-sync 1 + repository community { + components main + distribution helium + password "" + url http://packages.vyos.net/vyos + username "" + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } + time-zone UTC +} diff --git a/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces_detail.text b/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces_detail.text new file mode 100644 index 0000000..3c6f4bd --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_counters/normal/show_interfaces_detail.text @@ -0,0 +1,44 @@ +eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 08:00:27:0f:ec:bf brd ff:ff:ff:ff:ff:ff + inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0 + valid_lft forever preferred_lft forever + inet6 fe80::a00:27ff:fe0f:ecbf/64 scope link + valid_lft forever preferred_lft forever + + RX: bytes packets errors dropped overrun mcast + 1307723 13601 0 0 0 0 + TX: bytes packets errors dropped carrier collisions + 2199213 9708 0 0 0 0 +eth1: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 08:00:27:eb:7a:f9 brd ff:ff:ff:ff:ff:ff + inet 10.0.1.222/24 brd 10.0.1.255 scope global eth1 + valid_lft forever preferred_lft forever + inet6 fe80::a00:27ff:feeb:7af9/64 scope link + valid_lft forever preferred_lft forever + + RX: bytes packets errors dropped overrun mcast + 7009338 96514 0 0 0 0 + TX: bytes packets errors dropped carrier collisions + 7072471 97453 0 0 0 0 +eth2: mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000 + link/ether 08:00:27:b9:f5:4a brd ff:ff:ff:ff:ff:ff + + RX: bytes packets errors dropped overrun mcast + 0 0 0 0 0 0 + TX: bytes packets errors dropped carrier collisions + 818 7 0 0 0 0 +lo: mtu 65536 qdisc noqueue state UNKNOWN group default + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + inet 10.2.2.2/32 scope global lo + valid_lft forever preferred_lft forever + inet 8.8.8.8/32 scope global lo + valid_lft forever preferred_lft forever + inet6 ::1/128 scope host + valid_lft forever preferred_lft forever + + RX: bytes packets errors dropped overrun mcast + 198185 2394 0 0 0 0 + TX: bytes packets errors dropped carrier collisions + 198185 2394 0 0 0 0 diff --git a/test/unit/mocked_data/test_get_interfaces_ip/normal/show_interfaces.text b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_interfaces.text new file mode 100644 index 0000000..d199bd0 --- /dev/null +++ b/test/unit/mocked_data/test_get_interfaces_ip/normal/show_interfaces.text @@ -0,0 +1,10 @@ +Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down +Interface IP Address S/L Description +--------- ---------- --- ----------- +eth0 10.0.2.15/24 u/u +eth1 10.0.1.222/24 u/u +eth2 - A/D +lo 127.0.0.1/8 u/u + 10.2.2.2/32 + 8.8.8.8/32 + ::1/128 diff --git a/test/unit/mocked_data/test_get_ntp_peers/normal/ntpq__np.text b/test/unit/mocked_data/test_get_ntp_peers/normal/ntpq__np.text new file mode 100644 index 0000000..b713dcb --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_peers/normal/ntpq__np.text @@ -0,0 +1,3 @@ + remote refid st t when poll reach delay offset jitter +============================================================================== + 10.0.1.100 .INIT. 16 u 301 1024 0 0.000 0.000 0.000 diff --git a/test/unit/mocked_data/test_get_ntp_stats/normal/ntpq__np.text b/test/unit/mocked_data/test_get_ntp_stats/normal/ntpq__np.text new file mode 100644 index 0000000..b713dcb --- /dev/null +++ b/test/unit/mocked_data/test_get_ntp_stats/normal/ntpq__np.text @@ -0,0 +1,3 @@ + remote refid st t when poll reach delay offset jitter +============================================================================== + 10.0.1.100 .INIT. 16 u 301 1024 0 0.000 0.000 0.000 diff --git a/test/unit/mocked_data/test_get_snmp_information/normal/show_configuration.text b/test/unit/mocked_data/test_get_snmp_information/normal/show_configuration.text new file mode 100644 index 0000000..06701fe --- /dev/null +++ b/test/unit/mocked_data/test_get_snmp_information/normal/show_configuration.text @@ -0,0 +1,124 @@ +interfaces { + ethernet eth0 { + address dhcp + duplex auto + smp_affinity auto + speed auto + } + ethernet eth1 { + address 10.0.1.222/24 + duplex auto + smp_affinity auto + speed auto + } + loopback lo { + address 10.2.2.2/32 + address 8.8.8.8/32 + } +} +policy { + prefix-list EXPORT { + rule 1 { + action permit + prefix 172.16.2.0/24 + } + rule 65535 { + action permit + prefix 10.2.2.2/32 + } + } + route-map EXPORT-POLICY { + rule 1 { + action permit + match { + ip { + address { + prefix-list EXPORT + } + } + } + } + } +} +protocols { + bgp 65002 { + neighbor 10.0.1.100 { + remote-as 65001 + route-map { + export EXPORT-POLICY + } + } + redistribute { + connected { + route-map EXPORT-POLICY + } + } + } +} +service { + snmp { + community commro { + authorization ro + } + contact admin@foo.corp + location PL,Krakow + } + ssh { + disable-host-validation + port 22 + } +} +system { + config-management { + commit-revisions 20 + } + host-name vyos2 + login { + banner { + pre-login "My banner for all devices" + } + user vagrant { + authentication { + encrypted-password $6$fcHhBu3T$WLmiu6/txlEfWK5uh4mKE8v7qocuftsoAN1oHqPIIoogXAX8zS.SKhB105EExYU6yBy4cKHUD/Q6Mm7CUbVTr. + plaintext-password "" + public-keys vagrant { + key AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== + type ssh-rsa + } + } + level admin + } + user vyos { + authentication { + encrypted-password $1$yHIMnG/J$aWDkd3oDYSYps8twB5vpw1 + plaintext-password "" + } + level admin + } + } + ntp { + server 10.0.1.100 { + } + } + package { + auto-sync 1 + repository community { + components main + distribution helium + password "" + url http://packages.vyos.net/vyos + username "" + } + } + syslog { + global { + facility all { + level notice + } + facility protocols { + level debug + } + } + } + time-zone UTC +} diff --git a/test/unit/mocked_data/test_get_users/normal/show_configuration_commands.text b/test/unit/mocked_data/test_get_users/normal/show_configuration_commands.text new file mode 100644 index 0000000..c82bff5 --- /dev/null +++ b/test/unit/mocked_data/test_get_users/normal/show_configuration_commands.text @@ -0,0 +1,39 @@ +set interfaces ethernet eth0 address 'dhcp' +set interfaces ethernet eth1 address '10.0.1.222/24' +set interfaces loopback lo address '10.2.2.2/32' +set interfaces loopback lo address '8.8.8.8/32' +set policy prefix-list EXPORT rule 1 action 'permit' +set policy prefix-list EXPORT rule 1 prefix '172.16.2.0/24' +set policy prefix-list EXPORT rule 65535 action 'permit' +set policy prefix-list EXPORT rule 65535 prefix '10.2.2.2/32' +set policy route-map EXPORT-POLICY rule 1 action 'permit' +set policy route-map EXPORT-POLICY rule 1 match ip address prefix-list 'EXPORT' +set protocols bgp 65002 neighbor 10.0.1.100 remote-as '65001' +set protocols bgp 65002 neighbor 10.0.1.100 route-map export 'EXPORT-POLICY' +set protocols bgp 65002 redistribute connected route-map 'EXPORT-POLICY' +set service snmp community commro authorization 'ro' +set service snmp contact 'admin@foo.corp' +set service snmp location 'PL,Krakow' +set service ssh 'disable-host-validation' +set service ssh port '22' +set system config-management commit-revisions '20' +set system host-name 'vyos2' +set system login banner pre-login 'My banner for all devices' +set system login user vagrant authentication encrypted-password '$6$fcHhBu3T$WLmiu6/txlEfWK5uh4mKE8v7qocuftsoAN1oHqPIIoogXAX8zS.SKhB105EExYU6yBy4cKHUD/Q6Mm7CUbVTr.' +set system login user vagrant authentication plaintext-password '' +set system login user vagrant authentication public-keys vagrant key 'AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ==' +set system login user vagrant authentication public-keys vagrant type 'ssh-rsa' +set system login user vagrant level 'admin' +set system login user vyos authentication encrypted-password '$1$yHIMnG/J$aWDkd3oDYSYps8twB5vpw1' +set system login user vyos authentication plaintext-password '' +set system login user vyos level 'admin' +set system ntp server '10.0.1.100' +set system package auto-sync '1' +set system package repository community components 'main' +set system package repository community distribution 'helium' +set system package repository community password '' +set system package repository community url 'http://packages.vyos.net/vyos' +set system package repository community username '' +set system syslog global facility all level 'notice' +set system syslog global facility protocols level 'debug' +set system time-zone 'UTC' diff --git a/test/unit/mocked_data/test_ping/normal/ping_8.8.8.8_timeout_2_size_100_repeat_5.text b/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text similarity index 100% rename from test/unit/mocked_data/test_ping/normal/ping_8.8.8.8_timeout_2_size_100_repeat_5.text rename to test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text From f1de371d373a3f5cfe0ea010fd1f10b036ba4b39 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 13:51:52 +0100 Subject: [PATCH 07/11] fixes for pylama --- napalm_vyos/vyos.py | 10 +++++----- test/unit/conftest.py | 3 --- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index ac96390..7b3a5bc 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -92,10 +92,10 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) def open(self): self.device = ConnectHandler(device_type='vyos', - host=self._hostname, - username=self._username, - password=self._password, - **self.netmiko_optional_args) + host=self._hostname, + username=self._username, + password=self._password, + **self.netmiko_optional_args) try: self._scp_client = SCPConn(self.device) @@ -143,7 +143,7 @@ def load_merge_candidate(self, filename=None, config=None): if os.path.exists(filename) is True: with open(filename) as f: self.device.send_command("cp "+self._BOOT_FILENAME+" " - + self._BACKUP_FILENAME) + + self._BACKUP_FILENAME) self._new_config = f.read() cfg = [x for x in self._new_config.split("\n") if x is not ""] output_loadcmd = self.device.send_config_set(cfg) diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 0a5b115..a81ab39 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -37,7 +37,6 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.patched_attrs = ['device'] self.device = FakeVyOSDevice() - #self._device = FakeVyOSDevice() def close(self): pass @@ -54,8 +53,6 @@ def open(self): class FakeVyOSDevice(BaseTestDouble): """VyOS device test double.""" - - def send_command(self, command, **kwargs): filename = '{}.text'.format(self.sanitize_text(command)) print filename From f9e023954ede4d5907cbc728cdecdf16f9cde113 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 21:31:13 +0100 Subject: [PATCH 08/11] add def is_alive --- napalm_vyos/vyos.py | 44 ++++++++++++------- test/unit/conftest.py | 1 - ...tl_255_deadline_10_size_100_count_5_.text} | 0 3 files changed, 27 insertions(+), 18 deletions(-) rename test/unit/mocked_data/test_ping/normal/{ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text => ping_8_8_8_8_ttl_255_deadline_10_size_100_count_5_.text} (100%) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 7b3a5bc..8b25069 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -47,10 +47,10 @@ class VyOSDriver(NetworkDriver): _BOOT_FILENAME = "/config/config.boot" def __init__(self, hostname, username, password, timeout=60, optional_args=None): - self._hostname = hostname - self._username = username - self._password = password - self._timeout = timeout + self.hostname = hostname + self.username = username + self.password = password + self.timeout = timeout self.device = None self._scp_client = None self._new_config = None @@ -82,19 +82,20 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) # Build dict of any optional Netmiko args self.netmiko_optional_args = {} - for k, v in netmiko_argument_map.items(): - try: - self.netmiko_optional_args[k] = optional_args[k] - except KeyError: - pass - self.global_delay_factor = optional_args.get('global_delay_factor', 1) - self.port = optional_args.get('port', 22) + if optional_args is not None: + for k, v in netmiko_argument_map.items(): + try: + self.netmiko_optional_args[k] = optional_args[k] + except KeyError: + pass + self.global_delay_factor = optional_args.get('global_delay_factor', 1) + self.port = optional_args.get('port', 22) def open(self): self.device = ConnectHandler(device_type='vyos', - host=self._hostname, - username=self._username, - password=self._password, + host=self.hostname, + username=self.username, + password=self.password, **self.netmiko_optional_args) try: @@ -105,6 +106,12 @@ def open(self): def close(self): 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): """ Only configuration files are supported with load_replace_candidate. @@ -178,8 +185,9 @@ def commit_config(self): self.device.send_config_set(['save']) self.device.exit_config_mode() - def rollback(self, filename=None): + def rollback(self): """Rollback configuration to filename or to self.rollback_cfg file.""" + filename = None if filename is None: filename = self._BACKUP_FILENAME @@ -773,12 +781,14 @@ def get_users(self): return user_auth - def ping(self, destination, source="", ttl=255, timeout=5, size=100, count=5): + def ping(self, destination, source='', ttl=255, timeout=2, size=100, count=5): # does not support multiple destination yet + deadline = timeout * count + command = "ping %s " % destination command += "ttl %d " % ttl - command += "deadline %d " % timeout + command += "deadline %d " % deadline command += "size %d " % size command += "count %d " % count if source != "": diff --git a/test/unit/conftest.py b/test/unit/conftest.py index a81ab39..7c5bf36 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -32,7 +32,6 @@ class PatchedVyOSDriver(vyos.VyOSDriver): """Patched VyOS Driver.""" def __init__(self, hostname, username, password, timeout=60, optional_args=None): - optional_args = {'port': '12206'} super().__init__(hostname, username, password, timeout, optional_args) self.patched_attrs = ['device'] diff --git a/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text b/test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_10_size_100_count_5_.text similarity index 100% rename from test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_5_size_100_count_5_.text rename to test/unit/mocked_data/test_ping/normal/ping_8_8_8_8_ttl_255_deadline_10_size_100_count_5_.text From 1a6d88145025c866d103418b46f48ea2bc24925a Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 21:50:46 +0100 Subject: [PATCH 09/11] get_facts expected_result --- test/unit/conftest.py | 1 - .../unit/mocked_data/test_get_facts/normal/expected_result.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/conftest.py b/test/unit/conftest.py index 7c5bf36..c69c044 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -54,7 +54,6 @@ class FakeVyOSDevice(BaseTestDouble): def send_command(self, command, **kwargs): filename = '{}.text'.format(self.sanitize_text(command)) - print filename full_path = self.find_file(filename) result = self.read_txt_file(full_path) return py23_compat.text_type(result) 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 index bb2280b..41d938f 100644 --- a/test/unit/mocked_data/test_get_facts/normal/expected_result.json +++ b/test/unit/mocked_data/test_get_facts/normal/expected_result.json @@ -1 +1 @@ -{"os_version": "1.1.7", "uptime": "...", "interface_list": ["eth1", "eth0", "lo"], "vendor": "VyOS", "serial_number": "0", "model": "VirtualBox", "hostname": "vyos2", "fqdn": ""} +{"os_version": "1.1.7", "uptime": "...", "interface_list": "...", "vendor": "VyOS", "serial_number": "0", "model": "VirtualBox", "hostname": "vyos2", "fqdn": ""} From 7e2a8ba420475888c18ff31a1666e59b76ad44d9 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 22:00:39 +0100 Subject: [PATCH 10/11] switch tox to py27 only --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 5ae5d81..910c4f4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,py34,py35 +envlist = py27 [testenv] deps = From be5f80a427642d97a2d5ba6eb12027fb157bc354 Mon Sep 17 00:00:00 2001 From: Pieprzycki Piotr Date: Wed, 21 Dec 2016 22:55:32 +0100 Subject: [PATCH 11/11] fixes for python3 --- napalm_vyos/__init__.py | 2 +- napalm_vyos/vyos.py | 53 +++++++++++++++++++++-------------------- tox.ini | 2 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/napalm_vyos/__init__.py b/napalm_vyos/__init__.py index ae4e880..cb39e74 100644 --- a/napalm_vyos/__init__.py +++ b/napalm_vyos/__init__.py @@ -13,7 +13,7 @@ # the License. """napalm_vyos package.""" -from vyos import VyOSDriver +from napalm_vyos.vyos import VyOSDriver import pkg_resources try: diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 8b25069..fdf1c02 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -30,6 +30,7 @@ from netmiko import SCPConn # NAPALM base +from napalm_base.utils import py23_compat from napalm_base.base import NetworkDriver from napalm_base.exceptions import ConnectionException, \ MergeConfigException, ReplaceConfigException @@ -314,10 +315,10 @@ def get_interfaces(self): iface_name: { "is_up": bool(is_up), "is_enabled": bool(is_enabled), - "description": unicode(description), + "description": py23_compat.text_type(description), "last_flapped": float(-1), "speed": int(speed), - "mac_address": unicode(hw_id) + "mac_address": py23_compat.text_type(hw_id) } }) @@ -356,15 +357,15 @@ def get_arp_table(self): # ["10.129.2.254", "ether", "00:50:56:97:af:b1", "C", "eth0"] # [u'10.0.12.33', u'(incomplete)', u'eth1'] if "incomplete" in line[1]: - macaddr = unicode("00:00:00:00:00:00") + macaddr = py23_compat.text_type("00:00:00:00:00:00") else: - macaddr = unicode(line[2]) + macaddr = py23_compat.text_type(line[2]) arp_table.append( { - 'interface': unicode(line[-1]), + 'interface': py23_compat.text_type(line[-1]), 'mac': macaddr, - 'ip': unicode(line[0]), + 'ip': py23_compat.text_type(line[0]), 'age': 0.0 } ) @@ -399,12 +400,12 @@ def get_ntp_stats(self): when = when if when != '-' else 0 ntp_stats.append({ - "remote": unicode(ip), - "referenceid": unicode(refid), + "remote": py23_compat.text_type(ip), + "referenceid": py23_compat.text_type(refid), "synchronized": bool(synchronized), "stratum": int(st), - "type": unicode(t), - "when": unicode(when), + "type": py23_compat.text_type(t), + "when": py23_compat.text_type(when), "hostpoll": int(hostpoll), "reachability": int(reachability), "delay": float(delay), @@ -423,7 +424,7 @@ def get_ntp_peers(self): if len(line) > 0: match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line) ntp_peers.update({ - unicode(match.group(1)): {} + py23_compat.text_type(match.group(1)): {} }) return ntp_peers @@ -451,7 +452,7 @@ def get_bgp_neighbors(self): output[0]) if not match: return {} - router_id = unicode(match.group(1)) + router_id = py23_compat.text_type(match.group(1)) local_as = int(match.group(2)) bgp_neighbor_data = dict() @@ -505,11 +506,11 @@ def get_bgp_neighbors(self): bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {}) peer_dict = { - "description": unicode(""), + "description": py23_compat.text_type(""), "is_enabled": bool(is_enabled), "local_as": int(local_as), "is_up": bool(is_up), - "remote_id": unicode(remote_rid), + "remote_id": py23_compat.text_type(remote_rid), "uptime": int(self._bgp_time_conversion(up_time)), "remote_as": int(remote_as) } @@ -589,7 +590,7 @@ def get_interfaces_counters(self): rx_broadcast_packets = -1 else: counters.update({ - interfaces[j / 2]: { + interfaces[j // 2]: { "tx_errors": int(i[2]), "tx_discards": int(i[3]), "tx_octets": int(i[0]), @@ -622,15 +623,15 @@ def get_snmp_information(self): for i in config["service"]["snmp"]["community"]: snmp["community"].update({ i: { - "acl": unicode(""), - "mode": unicode(config["service"]["snmp"]["community"][i]["authorization"]) + "acl": py23_compat.text_type(""), + "mode": py23_compat.text_type(config["service"]["snmp"]["community"][i]["authorization"]) } }) snmp.update({ - "chassis_id": unicode(""), - "contact": unicode(config["service"]["snmp"]["contact"]), - "location": unicode(config["service"]["snmp"]["location"]) + "chassis_id": py23_compat.text_type(""), + "contact": py23_compat.text_type(config["service"]["snmp"]["contact"]), + "location": py23_compat.text_type(config["service"]["snmp"]["location"]) }) return snmp @@ -672,12 +673,12 @@ def get_facts(self): facts = { "uptime": int(uptime), - "vendor": unicode("VyOS"), - "os_version": unicode(version), - "serial_number": unicode(snumber), - "model": unicode(hwmodel), - "hostname": unicode(hostname), - "fqdn": unicode(fqdn), + "vendor": py23_compat.text_type("VyOS"), + "os_version": py23_compat.text_type(version), + "serial_number": py23_compat.text_type(snumber), + "model": py23_compat.text_type(hwmodel), + "hostname": py23_compat.text_type(hostname), + "fqdn": py23_compat.text_type(fqdn), "interface_list": iface_list } diff --git a/tox.ini b/tox.ini index 910c4f4..5ae5d81 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27 +envlist = py27,py34,py35 [testenv] deps =