commit
fe3d5560ab
|
|
@ -1,6 +1,5 @@
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- 2.7
|
|
||||||
- 3.6
|
- 3.6
|
||||||
- 3.7
|
- 3.7
|
||||||
- 3.8
|
- 3.8
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ from netmiko import SCPConn
|
||||||
|
|
||||||
# NAPALM base
|
# NAPALM base
|
||||||
import napalm.base.constants as C
|
import napalm.base.constants as C
|
||||||
from napalm.base.utils import py23_compat
|
|
||||||
from napalm.base.base import NetworkDriver
|
from napalm.base.base import NetworkDriver
|
||||||
from napalm.base.exceptions import ConnectionException, MergeConfigException, \
|
from napalm.base.exceptions import ConnectionException, MergeConfigException, \
|
||||||
ReplaceConfigException, CommitError, \
|
ReplaceConfigException, CommitError, \
|
||||||
|
|
@ -179,7 +178,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
self.device.send_command("cp "+self._BOOT_FILENAME+" "
|
self.device.send_command("cp "+self._BOOT_FILENAME+" "
|
||||||
+ self._BACKUP_FILENAME)
|
+ self._BACKUP_FILENAME)
|
||||||
self._new_config = f.read()
|
self._new_config = f.read()
|
||||||
cfg = [x for x in self._new_config.split("\n") if x is not ""]
|
cfg = [x for x in self._new_config.split("\n") if x]
|
||||||
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_setfailed = re.findall("Delete failed", output_loadcmd)
|
||||||
match_delfailed = re.findall("Set failed", output_loadcmd)
|
match_delfailed = re.findall("Set failed", output_loadcmd)
|
||||||
|
|
@ -309,7 +308,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
output_iface = self.device.send_command("show interfaces")
|
output_iface = self.device.send_command("show interfaces")
|
||||||
|
|
||||||
# Collect all interfaces' name and status
|
# Collect all interfaces' name and status
|
||||||
match = re.findall("(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface)
|
match = re.findall(r"(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface)
|
||||||
|
|
||||||
# 'match' example:
|
# 'match' example:
|
||||||
# [("br0", "u", "D"), ("eth0", "u", "u"), ("eth1", "u", "u")...]
|
# [("br0", "u", "D"), ("eth0", "u", "u"), ("eth1", "u", "u")...]
|
||||||
|
|
@ -328,17 +327,12 @@ class VyOSDriver(NetworkDriver):
|
||||||
ifaces_detail = config["interfaces"][iface_type]
|
ifaces_detail = config["interfaces"][iface_type]
|
||||||
|
|
||||||
for iface_name in ifaces_detail:
|
for iface_name in ifaces_detail:
|
||||||
description = self._get_value("description", ifaces_detail[iface_name])
|
details = ifaces_detail[iface_name]
|
||||||
if description is None:
|
description = details.get("description", "")
|
||||||
description = ""
|
speed = details.get("speed", "0")
|
||||||
speed = self._get_value("speed", ifaces_detail[iface_name])
|
|
||||||
if speed is None:
|
|
||||||
speed = 0
|
|
||||||
if speed == "auto":
|
if speed == "auto":
|
||||||
speed = 0
|
speed = 0
|
||||||
hw_id = self._get_value("hw-id", ifaces_detail[iface_name])
|
hw_id = details.get("hw-id", "00:00:00:00:00:00")
|
||||||
if hw_id is None:
|
|
||||||
hw_id = "00:00:00:00:00:00"
|
|
||||||
|
|
||||||
is_up = (iface_state[iface_name]["Link"] == "u")
|
is_up = (iface_state[iface_name]["Link"] == "u")
|
||||||
is_enabled = (iface_state[iface_name]["State"] == "u")
|
is_enabled = (iface_state[iface_name]["State"] == "u")
|
||||||
|
|
@ -347,23 +341,16 @@ class VyOSDriver(NetworkDriver):
|
||||||
iface_name: {
|
iface_name: {
|
||||||
"is_up": bool(is_up),
|
"is_up": bool(is_up),
|
||||||
"is_enabled": bool(is_enabled),
|
"is_enabled": bool(is_enabled),
|
||||||
"description": py23_compat.text_type(description),
|
"description": description,
|
||||||
"last_flapped": float(-1),
|
"last_flapped": float(-1),
|
||||||
"mtu": -1,
|
"mtu": -1,
|
||||||
"speed": int(speed),
|
"speed": int(speed),
|
||||||
"mac_address": py23_compat.text_type(hw_id)
|
"mac_address": hw_id,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return iface_dict
|
return iface_dict
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _get_value(key, target_dict):
|
|
||||||
if key in target_dict:
|
|
||||||
return target_dict[key]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_arp_table(self, vrf=""):
|
def get_arp_table(self, vrf=""):
|
||||||
# 'age' is not implemented yet
|
# 'age' is not implemented yet
|
||||||
|
|
||||||
|
|
@ -377,7 +364,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
192.168.1.3 ether 00:50:56:86:7b:06 C eth1
|
192.168.1.3 ether 00:50:56:86:7b:06 C eth1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if vrf:
|
if vrf:
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"VRF support has not been added for this getter on this platform."
|
"VRF support has not been added for this getter on this platform."
|
||||||
)
|
)
|
||||||
|
|
@ -396,16 +383,16 @@ class VyOSDriver(NetworkDriver):
|
||||||
# ["10.129.2.254", "ether", "00:50:56:97:af:b1", "C", "eth0"]
|
# ["10.129.2.254", "ether", "00:50:56:97:af:b1", "C", "eth0"]
|
||||||
# [u'10.0.12.33', u'(incomplete)', u'eth1']
|
# [u'10.0.12.33', u'(incomplete)', u'eth1']
|
||||||
if "incomplete" in line[1]:
|
if "incomplete" in line[1]:
|
||||||
macaddr = py23_compat.text_type("00:00:00:00:00:00")
|
macaddr = "00:00:00:00:00:00"
|
||||||
else:
|
else:
|
||||||
macaddr = py23_compat.text_type(line[2])
|
macaddr = line[2]
|
||||||
|
|
||||||
arp_table.append(
|
arp_table.append(
|
||||||
{
|
{
|
||||||
'interface': py23_compat.text_type(line[-1]),
|
'interface': line[-1],
|
||||||
'mac': macaddr,
|
'mac': macaddr,
|
||||||
'ip': py23_compat.text_type(line[0]),
|
'ip': line[0],
|
||||||
'age': 0.0
|
'age': 0.0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -433,23 +420,23 @@ class VyOSDriver(NetworkDriver):
|
||||||
# 'remote' contains '*' if the machine synchronized with NTP server
|
# 'remote' contains '*' if the machine synchronized with NTP server
|
||||||
synchronized = "*" in remote
|
synchronized = "*" in remote
|
||||||
|
|
||||||
match = re.search("(\d+\.\d+\.\d+\.\d+)", remote)
|
match = re.search(r"(\d+\.\d+\.\d+\.\d+)", remote)
|
||||||
ip = match.group(1)
|
ip = match.group(1)
|
||||||
|
|
||||||
when = when if when != '-' else 0
|
when = when if when != '-' else 0
|
||||||
|
|
||||||
ntp_stats.append({
|
ntp_stats.append({
|
||||||
"remote": py23_compat.text_type(ip),
|
"remote": ip,
|
||||||
"referenceid": py23_compat.text_type(refid),
|
"referenceid": refid,
|
||||||
"synchronized": bool(synchronized),
|
"synchronized": bool(synchronized),
|
||||||
"stratum": int(st),
|
"stratum": int(st),
|
||||||
"type": py23_compat.text_type(t),
|
"type": t,
|
||||||
"when": py23_compat.text_type(when),
|
"when": when,
|
||||||
"hostpoll": int(hostpoll),
|
"hostpoll": int(hostpoll),
|
||||||
"reachability": int(reachability),
|
"reachability": int(reachability),
|
||||||
"delay": float(delay),
|
"delay": float(delay),
|
||||||
"offset": float(offset),
|
"offset": float(offset),
|
||||||
"jitter": float(jitter)
|
"jitter": float(jitter),
|
||||||
})
|
})
|
||||||
|
|
||||||
return ntp_stats
|
return ntp_stats
|
||||||
|
|
@ -461,9 +448,9 @@ class VyOSDriver(NetworkDriver):
|
||||||
|
|
||||||
for line in output_peers:
|
for line in output_peers:
|
||||||
if len(line) > 0:
|
if len(line) > 0:
|
||||||
match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line)
|
match = re.search(r"(\d+\.\d+\.\d+\.\d+)\s+", line)
|
||||||
ntp_peers.update({
|
ntp_peers.update({
|
||||||
py23_compat.text_type(match.group(1)): {}
|
match.group(1): {}
|
||||||
})
|
})
|
||||||
|
|
||||||
return ntp_peers
|
return ntp_peers
|
||||||
|
|
@ -487,11 +474,11 @@ class VyOSDriver(NetworkDriver):
|
||||||
output = self.device.send_command("show ip bgp summary")
|
output = self.device.send_command("show ip bgp summary")
|
||||||
output = output.split("\n")
|
output = output.split("\n")
|
||||||
|
|
||||||
match = re.search(".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)",
|
match = re.search(r".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)",
|
||||||
output[0])
|
output[0])
|
||||||
if not match:
|
if not match:
|
||||||
return {}
|
return {}
|
||||||
router_id = py23_compat.text_type(match.group(1))
|
router_id = match.group(1)
|
||||||
local_as = int(match.group(2))
|
local_as = int(match.group(2))
|
||||||
|
|
||||||
bgp_neighbor_data = dict()
|
bgp_neighbor_data = dict()
|
||||||
|
|
@ -500,7 +487,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
bgp_neighbor_data["global"]["peers"] = {}
|
bgp_neighbor_data["global"]["peers"] = {}
|
||||||
|
|
||||||
# delete the header and empty element
|
# delete the header and empty element
|
||||||
bgp_info = [i.strip() for i in output[6:-2] if i is not ""]
|
bgp_info = [i.strip() for i in output[6:-2] if i]
|
||||||
|
|
||||||
for i in bgp_info:
|
for i in bgp_info:
|
||||||
if len(i) > 0:
|
if len(i) > 0:
|
||||||
|
|
@ -539,19 +526,19 @@ class VyOSDriver(NetworkDriver):
|
||||||
"""
|
"""
|
||||||
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)
|
match_rid = re.search(r"remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail)
|
||||||
remote_rid = match_rid.group(1)
|
remote_rid = match_rid.group(1)
|
||||||
|
|
||||||
match_prefix_accepted = re.search("(\d+) accepted prefixes", bgp_detail)
|
match_prefix_accepted = re.search(r"(\d+) accepted prefixes", bgp_detail)
|
||||||
accepted_prefixes = match_prefix_accepted.group(1)
|
accepted_prefixes = match_prefix_accepted.group(1)
|
||||||
|
|
||||||
bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {})
|
bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {})
|
||||||
peer_dict = {
|
peer_dict = {
|
||||||
"description": py23_compat.text_type(""),
|
"description": "",
|
||||||
"is_enabled": bool(is_enabled),
|
"is_enabled": bool(is_enabled),
|
||||||
"local_as": int(local_as),
|
"local_as": int(local_as),
|
||||||
"is_up": bool(is_up),
|
"is_up": bool(is_up),
|
||||||
"remote_id": py23_compat.text_type(remote_rid),
|
"remote_id": remote_rid,
|
||||||
"uptime": int(self._bgp_time_conversion(up_time)),
|
"uptime": int(self._bgp_time_conversion(up_time)),
|
||||||
"remote_as": int(remote_as)
|
"remote_as": int(remote_as)
|
||||||
}
|
}
|
||||||
|
|
@ -575,19 +562,19 @@ class VyOSDriver(NetworkDriver):
|
||||||
return -1
|
return -1
|
||||||
else:
|
else:
|
||||||
if "y" in bgp_uptime:
|
if "y" in bgp_uptime:
|
||||||
match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
||||||
uptime = ((int(match.group(1)) * self._YEAR_SECONDS) +
|
uptime = ((int(match.group(1)) * self._YEAR_SECONDS) +
|
||||||
(int(match.group(3)) * self._WEEK_SECONDS) +
|
(int(match.group(3)) * self._WEEK_SECONDS) +
|
||||||
(int(match.group(5)) * self._DAY_SECONDS))
|
(int(match.group(5)) * self._DAY_SECONDS))
|
||||||
return uptime
|
return uptime
|
||||||
elif "w" in bgp_uptime:
|
elif "w" in bgp_uptime:
|
||||||
match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
||||||
uptime = ((int(match.group(1)) * self._WEEK_SECONDS) +
|
uptime = ((int(match.group(1)) * self._WEEK_SECONDS) +
|
||||||
(int(match.group(3)) * self._DAY_SECONDS) +
|
(int(match.group(3)) * self._DAY_SECONDS) +
|
||||||
(int(match.group(5)) * self._HOUR_SECONDS))
|
(int(match.group(5)) * self._HOUR_SECONDS))
|
||||||
return uptime
|
return uptime
|
||||||
elif "d" in bgp_uptime:
|
elif "d" in bgp_uptime:
|
||||||
match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime)
|
||||||
uptime = ((int(match.group(1)) * self._DAY_SECONDS) +
|
uptime = ((int(match.group(1)) * self._DAY_SECONDS) +
|
||||||
(int(match.group(3)) * self._HOUR_SECONDS) +
|
(int(match.group(3)) * self._HOUR_SECONDS) +
|
||||||
(int(match.group(5)) * self._MINUTE_SECONDS))
|
(int(match.group(5)) * self._MINUTE_SECONDS))
|
||||||
|
|
@ -637,9 +624,9 @@ class VyOSDriver(NetworkDriver):
|
||||||
32776498 279273 0 0 0 0
|
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)
|
interfaces = re.findall(r"(\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)
|
count = re.findall(r"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output)
|
||||||
counters = dict()
|
counters = dict()
|
||||||
|
|
||||||
j = 0
|
j = 0
|
||||||
|
|
@ -687,15 +674,15 @@ class VyOSDriver(NetworkDriver):
|
||||||
for i in config["service"]["snmp"]["community"]:
|
for i in config["service"]["snmp"]["community"]:
|
||||||
snmp["community"].update({
|
snmp["community"].update({
|
||||||
i: {
|
i: {
|
||||||
"acl": py23_compat.text_type(""),
|
"acl": "",
|
||||||
"mode": py23_compat.text_type(config["service"]["snmp"]["community"][i]["authorization"])
|
"mode": config["service"]["snmp"]["community"][i]["authorization"],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
snmp.update({
|
snmp.update({
|
||||||
"chassis_id": py23_compat.text_type(""),
|
"chassis_id": "",
|
||||||
"contact": py23_compat.text_type(config["service"]["snmp"]["contact"]),
|
"contact": config["service"]["snmp"]["contact"],
|
||||||
"location": py23_compat.text_type(config["service"]["snmp"]["location"])
|
"location": config["service"]["snmp"]["location"],
|
||||||
})
|
})
|
||||||
|
|
||||||
return snmp
|
return snmp
|
||||||
|
|
@ -737,13 +724,13 @@ class VyOSDriver(NetworkDriver):
|
||||||
|
|
||||||
facts = {
|
facts = {
|
||||||
"uptime": int(uptime),
|
"uptime": int(uptime),
|
||||||
"vendor": py23_compat.text_type("VyOS"),
|
"vendor": "VyOS",
|
||||||
"os_version": py23_compat.text_type(version),
|
"os_version": version,
|
||||||
"serial_number": py23_compat.text_type(snumber),
|
"serial_number": snumber,
|
||||||
"model": py23_compat.text_type(hwmodel),
|
"model": hwmodel,
|
||||||
"hostname": py23_compat.text_type(hostname),
|
"hostname": hostname,
|
||||||
"fqdn": py23_compat.text_type(fqdn),
|
"fqdn": fqdn,
|
||||||
"interface_list": iface_list
|
"interface_list": iface_list,
|
||||||
}
|
}
|
||||||
|
|
||||||
return facts
|
return facts
|
||||||
|
|
@ -874,7 +861,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
else:
|
else:
|
||||||
err = ""
|
err = ""
|
||||||
|
|
||||||
if err is not "":
|
if err:
|
||||||
ping_result["error"] = err
|
ping_result["error"] = err
|
||||||
else:
|
else:
|
||||||
# 'packet_info' example:
|
# 'packet_info' example:
|
||||||
|
|
@ -902,7 +889,7 @@ class VyOSDriver(NetworkDriver):
|
||||||
else:
|
else:
|
||||||
rtt_info = rtt_info[-2]
|
rtt_info = rtt_info[-2]
|
||||||
|
|
||||||
match = re.search("([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+)", rtt_info)
|
match = re.search(r"([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+)", rtt_info)
|
||||||
|
|
||||||
if match is not None:
|
if match is not None:
|
||||||
rtt_min = float(match.group(1))
|
rtt_min = float(match.group(1))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
future
|
|
||||||
coveralls
|
coveralls
|
||||||
pytest
|
pytest
|
||||||
pytest-cov
|
pytest-cov
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
napalm>=2.5,<3.0
|
napalm>=3.0
|
||||||
paramiko
|
paramiko
|
||||||
netmiko<3.0
|
netmiko>=3.1.0
|
||||||
vyattaconfparser
|
vyattaconfparser
|
||||||
|
|
|
||||||
4
setup.py
4
setup.py
|
|
@ -11,7 +11,7 @@ __author__ = 'Piotr Pieprzycki <piotr.pieprzycki@dreamlab.pl>'
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="napalm-vyos",
|
name="napalm-vyos",
|
||||||
version="0.1.7",
|
version="0.2.0",
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
author="Piotr Pieprzycki",
|
author="Piotr Pieprzycki",
|
||||||
author_email="piotr.pieprzycki@dreamlab.pl",
|
author_email="piotr.pieprzycki@dreamlab.pl",
|
||||||
|
|
@ -19,8 +19,6 @@ setup(
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Topic :: Utilities',
|
'Topic :: Utilities',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
|
||||||
'Programming Language :: Python :: 2.7',
|
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.6',
|
'Programming Language :: Python :: 3.6',
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import pytest
|
||||||
from napalm.base.test import conftest as parent_conftest
|
from napalm.base.test import conftest as parent_conftest
|
||||||
|
|
||||||
from napalm.base.test.double import BaseTestDouble
|
from napalm.base.test.double import BaseTestDouble
|
||||||
from napalm.base.utils import py23_compat
|
|
||||||
|
|
||||||
from napalm_vyos import vyos
|
from napalm_vyos import vyos
|
||||||
|
|
||||||
|
|
@ -55,5 +54,4 @@ class FakeVyOSDevice(BaseTestDouble):
|
||||||
def send_command(self, command, **kwargs):
|
def send_command(self, command, **kwargs):
|
||||||
filename = '{}.text'.format(self.sanitize_text(command))
|
filename = '{}.text'.format(self.sanitize_text(command))
|
||||||
full_path = self.find_file(filename)
|
full_path = self.find_file(filename)
|
||||||
result = self.read_txt_file(full_path)
|
return self.read_txt_file(full_path)
|
||||||
return py23_compat.text_type(result)
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue