Skip to content

Commit

Permalink
eos: add explicit minimum version check
Browse files Browse the repository at this point in the history
Require 4.23.0F or later EOS image
Require pyeapi >= 1.0.2 resolves #1958
Remove all references to FN0039 and any configuration alterations
Remove text-based VRF parsing in favor of JSON version
Update all tests to reflect
  • Loading branch information
bewing committed Jul 8, 2023
1 parent 50ab9f7 commit 565c259
Show file tree
Hide file tree
Showing 46 changed files with 799 additions and 1,637 deletions.
4 changes: 4 additions & 0 deletions napalm/base/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class ConnectionClosedException(ConnectionException):
pass


class UnsupportedVersion(ConnectionException):
pass


class ReplaceConfigException(NapalmException):
pass

Expand Down
57 changes: 16 additions & 41 deletions napalm/eos/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,10 @@
ReplaceConfigException,
SessionLockedException,
CommandErrorException,
UnsupportedVersion,
)
from napalm.eos.constants import LLDP_CAPAB_TRANFORM_TABLE
from napalm.eos.pyeapi_syntax_wrapper import Node
from napalm.eos.utils.versions import EOSVersion
from napalm.eos.utils.cli_syntax import cli_convert
import napalm.base.constants as c

# local modules
Expand Down Expand Up @@ -123,15 +122,13 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)
self.timeout = timeout
self.config_session = None
self.locked = False
self.cli_version = 1

self.platform = "eos"
self.profile = [self.platform]
self.optional_args = optional_args or {}

self.enablepwd = self.optional_args.pop("enable_password", "")
self.eos_autoComplete = self.optional_args.pop("eos_autoComplete", None)
self.fn0039_config = self.optional_args.pop("eos_fn0039_config", False)

# Define locking method
self.lock_disable = self.optional_args.pop("lock_disable", False)
Expand Down Expand Up @@ -201,10 +198,6 @@ def open(self):
device_type="arista_eos",
netmiko_optional_args=self.netmiko_optional_args,
)
# let's try to determine if we need to use new EOS cli syntax
sh_ver = self._run_commands(["show version"])
if EOSVersion(sh_ver[0]["version"]) >= EOSVersion("4.23.0"):
self.cli_version = 2
else:
try:
connection = self.transport_class(
Expand All @@ -216,22 +209,24 @@ def open(self):
)

if self.device is None:
self.device = Node(connection, enablepwd=self.enablepwd)
self.device = pyeapi.client.Node(
connection, enablepwd=self.enablepwd
)
# does not raise an Exception if unusable

# let's try to determine if we need to use new EOS cli syntax
sh_ver = self.device.run_commands(["show version"])
self.cli_version = (
2 if EOSVersion(sh_ver[0]["version"]) >= EOSVersion("4.23.0") else 1
)

self.device.update_cli_version(self.cli_version)
except ConnectionError as ce:
# and this is raised either if device not avaiable
# either if HTTP(S) agent is not enabled
# show management api http-commands
raise ConnectionException(str(ce))

# endif self.transport

sh_ver = self._run_commands(["show version"])
self._eos_version = EOSVersion(sh_ver[0]["version"])
if self._eos_version < EOSVersion("4.23.0"):
raise UnsupportedVersion(self._eos_version)

def close(self):
"""Implementation of NAPALM method close."""
self.discard_config()
Expand Down Expand Up @@ -263,11 +258,6 @@ def is_alive(self):

def _run_commands(self, commands, **kwargs):
if self.transport == "ssh":
if self.fn0039_config:
if isinstance(commands, str):
commands = [cli_convert(commands, self.cli_version)]
else:
commands = [cli_convert(cmd, self.cli_version) for cmd in commands]
ret = []
for command in commands:
if kwargs.get("encoding") == "text":
Expand Down Expand Up @@ -463,10 +453,9 @@ def _load_config(self, filename=None, config=None, replace=True):
self._run_commands(
commands,
autoComplete=self.eos_autoComplete,
fn0039_transform=self.fn0039_config,
)
else:
self._run_commands(commands, fn0039_transform=self.fn0039_config)
self._run_commands(commands)
except pyeapi.eapilib.CommandError as e:
self.discard_config()
msg = str(e)
Expand Down Expand Up @@ -1527,23 +1516,14 @@ def get_route_to(self, destination="", protocol="", longer=False):
nexthop_interface_map[nexthop_ip] = next_hop.get("interface")
metric = route_details.get("metric")
if _vrf not in vrf_cache.keys():
if self.cli_version == 1:
command = "show ip{ipv} bgp {dest} {longer} detail vrf {_vrf}".format(
command = (
"show ip{ipv} bgp {dest} {longer} detail vrf {_vrf}".format(
ipv=ipv,
dest=destination,
longer="longer-prefixes" if longer else "",
_vrf=_vrf,
)
else:
# Newer EOS can't mix longer-prefix and detail
command = (
"show ip{ipv} bgp {dest} {longer} vrf {_vrf}".format(
ipv=ipv,
dest=destination,
longer="longer-prefixes" if longer else "",
_vrf=_vrf,
)
)
)
vrf_cache.update(
{
_vrf: self._run_commands([command])[0]
Expand Down Expand Up @@ -2169,18 +2149,13 @@ def _show_vrf_text(self):
return vrfs

def _show_vrf(self):
if self.cli_version == 2:
return self._show_vrf_json()
else:
return self._show_vrf_text()
return self._show_vrf_json()

def _get_vrfs(self):
output = self._show_vrf()

vrfs = [str(vrf["name"]) for vrf in output]

vrfs.append("default")

return vrfs

def get_network_instances(self, name=""):
Expand Down
42 changes: 0 additions & 42 deletions napalm/eos/pyeapi_syntax_wrapper.py

This file was deleted.

Loading

0 comments on commit 565c259

Please sign in to comment.