Skip to content

Commit 456f736

Browse files
mirceaulinicExaneServerTeamspinoshidependabot-preview[bot]ktbyers
authored
Prepare release 3.0.1 (#1203)
* Bugfix/ios get interfaces counters mgmt0 (#1201) * IOS: fix get_interfaces_counters when interface = canonical Fixes #1200 mgmt0 interface is not translated to it's canonical name on the 'show interface' command. Thix fix attempt to use the expected Canonical name first and fallback to the interface name in case of a KeyError is raised * Add test * Make black happy ! * Version 3.0.1 (#1202) * Junos: close configuration in case configure_private is set to avoid configure session to stay forever. (#1199) This is done in commit_config and discard_config functions. Co-authored-by: Mircea Ulinic <[email protected]> * Bugfix/ios get optics input na (#1206) * IOS: fix get_optics when input is N/A Extend the current check to ouput value to the input value. Input value could also be N/A Fixes #1205 * Add test * Bugfix/ios get optics support vss (#1208) * IOS: support get_optics on VSS Setup Introduce a new class function: _is_vss If the current swith is a VSS setup, run the following commands an parse the output:: show interfaces transceiver switch 1 show interfaces transceiver switch 2 * Add test * Make black happy * Bump pytest from 5.4.1 to 5.4.2 (#1204) Bumps [pytest](https://github.com/pytest-dev/pytest) from 5.4.1 to 5.4.2. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/master/CHANGELOG.rst) - [Commits](pytest-dev/pytest@5.4.1...5.4.2) Signed-off-by: dependabot-preview[bot] <[email protected]> Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Mircea Ulinic <[email protected]> * Update README.md and setup.py so branch has some differences (#1209) * Fix cmd_verify and null character on NX-OS (#1214) * Bump ddt from 1.3.1 to 1.4.1 (#1219) Bumps [ddt](https://github.com/datadriventests/ddt) from 1.3.1 to 1.4.1. - [Release notes](https://github.com/datadriventests/ddt/releases) - [Commits](datadriventests/ddt@1.3.1...1.4.1) Signed-off-by: dependabot-preview[bot] <[email protected]> Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> * Add eos_fn0039_config optional arg to toggle FN 0039 on config commands (#1212) Co-authored-by: Kirk Byers <[email protected]> Co-authored-by: Exane Server Team <[email protected]> Co-authored-by: spinoshi <[email protected]> Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> Co-authored-by: Kirk Byers <[email protected]>
1 parent 803f764 commit 456f736

20 files changed

+1038
-25
lines changed

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,18 @@ Podcasts
129129
Authors
130130
=======
131131
* David Barroso ([[email protected]](mailto:[email protected]))
132+
* Mircea Ulinic ([[email protected]](mailto:[email protected]))
133+
* Kirk Byers ([[email protected]](mailto:[email protected]))
132134
* Elisa Jasinska ([[email protected]](mailto:[email protected]))
133135
* Many others, check the [contributors](https://github.com/napalm-automation/napalm/graphs/contributors) page for details.
134136

135137

136138
Thanks
137139
======
138140

139-
This project was founded by David Barroso as part of [Spotify][spotify] and Elisa Jasinska as part of [BigWave IT][bigwave]. Originally it was hosted by the [Spotify][spotify] organization but due to the many contributions received by third parties we agreed creating a dedicated organization for NAPALM and give a big thanks to [Spotify][spotify] for the support.
141+
This project is maintained by David Barroso, Mircea Ulinic, and Kirk Byers and a set of other contributors.
142+
143+
Originally it was hosted by the [Spotify][spotify] organization but due to the many contributions received by third parties we agreed creating a dedicated organization for NAPALM and give a big thanks to [Spotify][spotify] for the support.
140144

141145
[spotify]: http://www.spotify.com
142146
[bigwave]: http://bigwaveit.org/

docs/support/index.rst

+7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ ____________________________________
133133
* :code:`transport` (eos, ios, nxos) - Protocol to connect with (see `The transport argument`_ for more information).
134134
* :code:`use_keys` (ios, iosxr, nxos_ssh) - Paramiko argument, enable searching for discoverable private key files in ``~/.ssh/`` (default: ``False``).
135135
* :code:`eos_autoComplete` (eos) - Allows to set `autoComplete` when running commands. (default: ``None`` equivalent to ``False``)
136+
* :code:`eos_fn0039_config` (eos) - Transform old style configuration to the new
137+
style, available beginning with EOS release 4.23.0, as per FN 0039. Beware
138+
that enabling this option will change the configuration you're loading
139+
through NAPALM. Default: ``False`` (won't change your configuration
140+
commands).
141+
142+
.. versionadded:: 3.0.1
136143

137144
The transport argument
138145
______________________

napalm/eos/eos.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ def _process_optional_args(self, optional_args):
129129
transport = optional_args.get(
130130
"transport", optional_args.get("eos_transport", "https")
131131
)
132+
self.fn0039_config = optional_args.pop("eos_fn0039_config", False)
132133
try:
133134
self.transport_class = pyeapi.client.TRANSPORTS[transport]
134135
except KeyError:
@@ -285,9 +286,13 @@ def _load_config(self, filename=None, config=None, replace=True):
285286

286287
try:
287288
if self.eos_autoComplete is not None:
288-
self.device.run_commands(commands, autoComplete=self.eos_autoComplete)
289+
self.device.run_commands(
290+
commands,
291+
autoComplete=self.eos_autoComplete,
292+
fn0039_transform=self.fn0039_config,
293+
)
289294
else:
290-
self.device.run_commands(commands)
295+
self.device.run_commands(commands, fn0039_transform=self.fn0039_config)
291296
except pyeapi.eapilib.CommandError as e:
292297
self.discard_config()
293298
msg = str(e)

napalm/eos/pyeapi_syntax_wrapper.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ def run_commands(self, commands, **kwargs):
3232
:param kwargs: other args
3333
:return: list of outputs
3434
"""
35-
if isinstance(commands, str):
36-
new_commands = [cli_convert(commands, self.cli_version)]
37-
else:
38-
new_commands = [cli_convert(cmd, self.cli_version) for cmd in commands]
35+
fn0039_transform = kwargs.pop("fn0039_transform", True)
36+
if fn0039_transform:
37+
if isinstance(commands, str):
38+
commands = [cli_convert(commands, self.cli_version)]
39+
else:
40+
commands = [cli_convert(cmd, self.cli_version) for cmd in commands]
3941

40-
return super(Node, self).run_commands(new_commands, **kwargs)
42+
return super(Node, self).run_commands(commands, **kwargs)

napalm/ios/ios.py

+46-8
Original file line numberDiff line numberDiff line change
@@ -753,21 +753,46 @@ def _send_command_postprocess(output):
753753
output = re.sub(r"^Time source is .*$", "", output, flags=re.M)
754754
return output.strip()
755755

756+
def _is_vss(self):
757+
"""
758+
Returns True if a Virtual Switching System (VSS) is setup
759+
"""
760+
vss_re = re.compile("Switch mode[ ]+: Virtual Switch", re.M)
761+
command = "show switch virtual"
762+
output = self._send_command(command)
763+
764+
return bool(vss_re.search(output))
765+
756766
def get_optics(self):
757767
command = "show interfaces transceiver"
758768
output = self._send_command(command)
769+
is_vss = False
759770

760771
# Check if router supports the command
761772
if "% Invalid input" in output:
762773
return {}
774+
elif "% Incomplete command" in output:
775+
if self._is_vss():
776+
is_vss = True
777+
command1 = "show interfaces transceiver switch 1"
778+
command2 = "show interfaces transceiver switch 2"
779+
output1 = self._send_command(command1)
780+
output2 = self._send_command(command2)
763781

764782
# Formatting data into return data structure
765783
optics_detail = {}
766784

767-
try:
768-
split_output = re.split(r"^---------.*$", output, flags=re.M)[1]
769-
except IndexError:
770-
return {}
785+
if is_vss:
786+
try:
787+
split_output = re.split(r"^---------.*$", output1, flags=re.M)[1]
788+
split_output += re.split(r"^---------.*$", output2, flags=re.M)[1]
789+
except IndexError:
790+
return {}
791+
else:
792+
try:
793+
split_output = re.split(r"^---------.*$", output, flags=re.M)[1]
794+
except IndexError:
795+
return {}
771796

772797
split_output = split_output.strip()
773798

@@ -786,12 +811,17 @@ def get_optics(self):
786811

787812
port_detail = {"physical_channels": {"channel": []}}
788813

789-
# If interface is shutdown it returns "N/A" as output power.
814+
# If interface is shutdown it returns "N/A" as output power
815+
# or "N/A" as input power
790816
# Converting that to -100.0 float
791817
try:
792818
float(output_power)
793819
except ValueError:
794820
output_power = -100.0
821+
try:
822+
float(input_power)
823+
except ValueError:
824+
input_power = -100.0
795825

796826
# Defaulting avg, min, max values to -100.0 since device does not
797827
# return these values
@@ -2129,9 +2159,17 @@ def get_interfaces_counters(self):
21292159
)
21302160
match = re.search(regex, line)
21312161
if match:
2132-
interface = canonical_interface_name(interface)
2133-
counters[interface]["rx_discards"] = int(match.group("IQD"))
2134-
counters[interface]["tx_discards"] = int(match.group("OQD"))
2162+
can_interface = canonical_interface_name(interface)
2163+
try:
2164+
counters[can_interface]["rx_discards"] = int(
2165+
match.group("IQD")
2166+
)
2167+
counters[can_interface]["tx_discards"] = int(
2168+
match.group("OQD")
2169+
)
2170+
except KeyError:
2171+
counters[interface]["rx_discards"] = int(match.group("IQD"))
2172+
counters[interface]["tx_discards"] = int(match.group("OQD"))
21352173

21362174
return counters
21372175

napalm/junos/junos.py

+4
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,16 @@ def commit_config(self, message=""):
283283
self.device.cu.commit(ignore_warning=self.ignore_warning, **commit_args)
284284
if not self.lock_disable and not self.session_config_lock:
285285
self._unlock()
286+
if self.config_private:
287+
self.device.rpc.close_configuration()
286288

287289
def discard_config(self):
288290
"""Discard changes (rollback 0)."""
289291
self.device.cu.rollback(rb_id=0)
290292
if not self.lock_disable and not self.session_config_lock:
291293
self._unlock()
294+
if self.config_private:
295+
self.device.rpc.close_configuration()
292296

293297
def rollback(self):
294298
"""Rollback to previous commit."""

napalm/nxos_ssh/nxos_ssh.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -438,13 +438,13 @@ def open(self):
438438
def close(self):
439439
self._netmiko_close()
440440

441-
def _send_command(self, command, raw_text=False):
441+
def _send_command(self, command, raw_text=False, cmd_verify=True):
442442
"""
443443
Wrapper for Netmiko's send_command method.
444444
445445
raw_text argument is not used and is for code sharing with NX-API.
446446
"""
447-
return self.device.send_command(command)
447+
return self.device.send_command(command, cmd_verify=cmd_verify)
448448

449449
def _send_command_list(self, commands, expect_string=None):
450450
"""Wrapper for Netmiko's send_command method (for list of commands."""
@@ -506,7 +506,7 @@ def is_alive(self):
506506
return {"is_alive": False}
507507
else:
508508
# Try sending ASCII null byte to maintain the connection alive
509-
self._send_command(null)
509+
self._send_command(null, cmd_verify=False)
510510
except (socket.error, EOFError):
511511
# If unable to send, we can tell for sure that the connection is unusable,
512512
# hence return False.

requirements-dev.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
black==19.10b0
22
coveralls==2.0.0
3-
ddt==1.3.1
3+
ddt==1.4.1
44
flake8-import-order==0.18.1
5-
pytest==5.4.1
5+
pytest==5.4.2
66
pytest-cov==2.8.1
77
pytest-json==0.4.0
88
pytest-pythonpath==0.7.3

setup.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@
44
with open("requirements.txt", "r") as fs:
55
reqs = [r for r in fs.read().splitlines() if (len(r) > 0 and not r.startswith("#"))]
66

7+
with open("README.md", "r") as fs:
8+
long_description = fs.read()
9+
710

811
__author__ = "David Barroso <[email protected]>"
912

1013
setup(
1114
name="napalm",
12-
version="3.0.0",
15+
version="3.0.1",
1316
packages=find_packages(exclude=("test*",)),
1417
test_suite="test_base",
1518
author="David Barroso, Kirk Byers, Mircea Ulinic",
1619
1720
description="Network Automation and Programmability Abstraction Layer with Multivendor support",
21+
long_description=long_description,
22+
long_description_content_type="text/markdown",
1823
classifiers=[
1924
"Topic :: Utilities",
2025
"Programming Language :: Python",

test/eos/test_heredoc.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ def test_heredoc(self):
5757
"idle-timeout 15",
5858
]
5959

60-
self.device.device.run_commands.assert_called_with(expected_result)
60+
self.device.device.run_commands.assert_called_with(
61+
expected_result, fn0039_transform=False
62+
)
6163

6264
def test_mode_comment(self):
6365
raw_config = dedent(
@@ -108,7 +110,9 @@ def test_mode_comment(self):
108110
"permit host 192.0.2.3",
109111
]
110112

111-
self.device.device.run_commands.assert_called_with(expected_result)
113+
self.device.device.run_commands.assert_called_with(
114+
expected_result, fn0039_transform=False
115+
)
112116

113117
def test_heredoc_with_bangs(self):
114118

@@ -145,4 +149,6 @@ def test_heredoc_with_bangs(self):
145149
"idle-timeout 15",
146150
]
147151

148-
self.device.device.run_commands.assert_called_with(expected_result)
152+
self.device.device.run_commands.assert_called_with(
153+
expected_result, fn0039_transform=False
154+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"mgmt0": {
3+
"rx_unicast_packets": 10039584,
4+
"rx_octets": 860372462,
5+
"rx_broadcast_packets": 10025891,
6+
"rx_multicast_packets": 6,
7+
"rx_errors": 0,
8+
"rx_discards": 0,
9+
"tx_unicast_packets": 309048,
10+
"tx_octets": 110610635,
11+
"tx_broadcast_packets": -1,
12+
"tx_multicast_packets": -1,
13+
"tx_errors": 0,
14+
"tx_discards": 0
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
3+
*: interface is up
4+
IHQ: pkts in input hold queue IQD: pkts dropped from input queue
5+
OHQ: pkts in output hold queue OQD: pkts dropped from output queue
6+
RXBS: rx rate (bits/sec) RXPS: rx rate (pkts/sec)
7+
TXBS: tx rate (bits/sec) TXPS: tx rate (pkts/sec)
8+
TRTL: throttle count
9+
10+
Interface IHQ IQD OHQ OQD RXBS RXPS TXBS TXPS TRTL
11+
-----------------------------------------------------------------------------------------------------------------
12+
* mgmt0 0 0 0 0 0 1 0 0 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
mgmt0 is up, line protocol is up (connected)
2+
Hardware is I82580 MGMT, address is 0008.e3ff.fd68 (bia 0008.e3ff.fd68)
3+
Internet address is 10.211.127.1/24
4+
MTU 1500 bytes, BW 1000000 Kbit/sec, DLY 10 usec,
5+
reliability 255/255, txload 1/255, rxload 1/255
6+
Encapsulation ARPA, loopback not set
7+
Keepalive not supported
8+
Full-duplex, 1000Mb/s
9+
Media-type configured as RJ45 connector
10+
input flow-control is off, output flow-control is unsupported
11+
Clock mode is auto
12+
ARP type: ARPA, ARP Timeout 04:00:00
13+
Last input 00:00:01, output never, output hang never
14+
Last clearing of "show interface" counters 23w5d
15+
Input queue: 0/1000/0/0 (size/max/drops/flushes); Total output drops: 0
16+
Queueing strategy: fifo
17+
Output queue: 0/40 (size/max)
18+
5 minute input rate 0 bits/sec, 0 packets/sec
19+
5 minute output rate 0 bits/sec, 0 packets/sec
20+
10039584 packets input, 860372462 bytes, 0 no buffer
21+
Received 10025891 broadcasts (416 IP multicasts)
22+
0 runts, 0 giants, 0 throttles
23+
0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
24+
0 watchdog, 0 multicast, 0 pause input
25+
0 input packets with dribble condition detected
26+
309048 packets output, 110610635 bytes, 0 underruns
27+
0 output errors, 0 collisions, 25 interface resets
28+
0 unknown protocol drops
29+
0 babbles, 0 late collision, 0 deferred
30+
0 lost carrier, 0 no carrier, 0 pause output
31+
0 output buffer failures, 0 output buffers swapped out

0 commit comments

Comments
 (0)