Skip to content

Commit

Permalink
Merge pull request #2015 from napalm-automation/eos-423plus
Browse files Browse the repository at this point in the history
eos: Require EOS 4.23+
  • Loading branch information
bewing authored Oct 20, 2023
2 parents d0ea707 + 9c09afe commit cca35cf
Show file tree
Hide file tree
Showing 93 changed files with 932 additions and 1,765 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
93 changes: 38 additions & 55 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 @@ -691,13 +680,16 @@ def get_re_group(res, key, default=None):
except KeyError:
return default

NEIGHBOR_FILTER = "bgp neighbors vrf all | include IPv[46] (Unicast|6PE):.*[0-9]+ | grep -v ' IPv[46] Unicast:/.' | remote AS |^Local AS|Desc|BGP state |remote router ID" # noqa
NEIGHBOR_FILTER = "vrf all | include IPv[46] (Unicast|6PE):.*[0-9]+ | grep -v ' IPv[46] Unicast:/.' | remote AS |^Local AS|Desc|BGP state |remote router ID" # noqa
output_summary_cmds = self._run_commands(
["show ipv6 bgp summary vrf all", "show ip bgp summary vrf all"],
encoding="json",
)
output_neighbor_cmds = self._run_commands(
["show ip " + NEIGHBOR_FILTER, "show ipv6 " + NEIGHBOR_FILTER],
[
"show ip bgp neighbors " + NEIGHBOR_FILTER,
"show ipv6 bgp peers " + NEIGHBOR_FILTER,
],
encoding="text",
)

Expand Down Expand Up @@ -831,10 +823,13 @@ def extract_temperature_data(data):
yield name, values

sh_version_out = self._run_commands(["show version"])
is_veos = sh_version_out[0]["modelName"].lower() == "veos"
commands = ["show environment cooling", "show environment temperature"]
is_veos = sh_version_out[0]["modelName"].lower() in ["veos", "ceoslab"]
commands = [
"show system environment cooling",
"show system environment temperature",
]
if not is_veos:
commands.append("show environment power")
commands.append("show system environment power")
fans_output, temp_output, power_output = self._run_commands(commands)
else:
fans_output, temp_output = self._run_commands(commands)
Expand Down Expand Up @@ -1527,23 +1522,12 @@ 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(
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,
)
)
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 @@ -1656,7 +1640,11 @@ def get_snmp_information(self):
# Default values
snmp_dict = {"chassis_id": "", "location": "", "contact": "", "community": {}}

commands = ["show snmp chassis", "show snmp location", "show snmp contact"]
commands = [
"show snmp v2-mib chassis",
"show snmp v2-mib location",
"show snmp v2-mib contact",
]
snmp_config = self._run_commands(commands, encoding="json")
for line in snmp_config:
for k, v in line.items():
Expand Down Expand Up @@ -1691,7 +1679,7 @@ def _sshkey_type(sshkey):

users = {}

commands = ["show user-account"]
commands = ["show users accounts"]
user_items = self._run_commands(commands)[0].get("users", {})

for user, user_details in user_items.items():
Expand Down Expand Up @@ -1950,7 +1938,7 @@ def _append(bgp_dict, peer_info):
summary_commands = []
if not neighbor_address:
commands.append("show ip bgp neighbors vrf all")
commands.append("show ipv6 bgp neighbors vrf all")
commands.append("show ipv6 bgp peers vrf all")
summary_commands.append("show ip bgp summary vrf all")
summary_commands.append("show ipv6 bgp summary vrf all")
else:
Expand All @@ -1963,7 +1951,7 @@ def _append(bgp_dict, peer_info):
commands.append("show ip bgp neighbors %s vrf all" % neighbor_address)
summary_commands.append("show ip bgp summary vrf all")
elif peer_ver == 6:
commands.append("show ipv6 bgp neighbors %s vrf all" % neighbor_address)
commands.append("show ipv6 bgp peers %s vrf all" % neighbor_address)
summary_commands.append("show ipv6 bgp summary vrf all")

raw_output = self._run_commands(commands, encoding="text")
Expand Down Expand Up @@ -2169,18 +2157,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 cca35cf

Please sign in to comment.