Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NX-OS ping implementation using more shared common code #642

Merged
merged 9 commits into from
Feb 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ test/unit/test_devices.py

report.json
tags
.pytest_cache/

docs/integrations/ansible/modules/napalm_*/
docs/integrations/ansible/modules/source/*.json
docs/napalm_ansible_repo/
docs/napalm_ansible_repo/
116 changes: 116 additions & 0 deletions napalm/nxos/nxos.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,115 @@ def commit_config(self):
else:
raise ReplaceConfigException('No config loaded.')

def ping(self,
destination,
source=c.PING_SOURCE,
ttl=c.PING_TTL,
timeout=c.PING_TIMEOUT,
size=c.PING_SIZE,
count=c.PING_COUNT,
vrf=c.PING_VRF):
"""
Execute ping on the device and returns a dictionary with the result.
Output dictionary has one of following keys:
* success
* error
In case of success, inner dictionary will have the followin keys:
* probes_sent (int)
* packet_loss (int)
* rtt_min (float)
* rtt_max (float)
* rtt_avg (float)
* rtt_stddev (float)
* results (list)
'results' is a list of dictionaries with the following keys:
* ip_address (str)
* rtt (float)
"""
ping_dict = {}

version = ''
try:
version = '6' if IPAddress(destination).version == 6 else ''
except AddrFormatError:
# Allow use of DNS names
pass

command = 'ping{version} {destination}'.format(
version=version,
destination=destination)
command += ' timeout {}'.format(timeout)
command += ' packet-size {}'.format(size)
command += ' count {}'.format(count)
if source != '':
command += ' source {}'.format(source)

if vrf != '':
command += ' vrf {}'.format(vrf)
output = self._send_command(command)

if 'connect:' in output:
ping_dict['error'] = output
elif 'PING' in output:
ping_dict['success'] = {
'probes_sent': 0,
'packet_loss': 0,
'rtt_min': 0.0,
'rtt_max': 0.0,
'rtt_avg': 0.0,
'rtt_stddev': 0.0,
'results': []
}
results_array = []
for line in output.splitlines():
fields = line.split()
if 'icmp' in line:
if 'Unreachable' in line:
if "(" in fields[2]:
results_array.append(
{
'ip_address': py23_compat.text_type(fields[2][1:-1]),
'rtt': 0.0,
}
)
else:
results_array.append({'ip_address': py23_compat.text_type(fields[1]),
'rtt': 0.0})
elif 'truncated' in line:
if "(" in fields[4]:
results_array.append(
{
'ip_address': py23_compat.text_type(fields[4][1:-2]),
'rtt': 0.0,
}
)
else:
results_array.append(
{
'ip_address': py23_compat.text_type(fields[3][:-1]),
'rtt': 0.0,
}
)
elif fields[1] == 'bytes':
if version == '6':
m = fields[5][5:]
else:
m = fields[6][5:]
results_array.append({'ip_address': py23_compat.text_type(fields[3][:-1]),
'rtt': float(m)})
elif 'packets transmitted' in line:
ping_dict['success']['probes_sent'] = int(fields[0])
ping_dict['success']['packet_loss'] = int(fields[0]) - int(fields[3])
elif 'min/avg/max' in line:
m = fields[3].split('/')
ping_dict['success'].update({
'rtt_min': float(m[0]),
'rtt_avg': float(m[1]),
'rtt_max': float(m[2]),
})
ping_dict['success'].update({'results': results_array})
return ping_dict


class NXOSDriver(NXOSDriverBase):
def __init__(self, hostname, username, password, timeout=60, optional_args=None):
Expand Down Expand Up @@ -110,6 +219,13 @@ def close(self):
self._delete_file(self.backup_file)
self.device = None

def _send_command(self, command):
"""Wrapper for CLI method in NX-API.

Allows more code sharing between NX-API and SSH.
"""
return self.cli([command]).get(command)

@staticmethod
def _compute_timestamp(stupid_cisco_output):
"""
Expand Down
4 changes: 4 additions & 0 deletions napalm/nxos_ssh/nxos_ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,10 @@ def close(self):
self.device.disconnect()
self.device = None

def _send_command(self, command):
"""Wrapper for Netmiko's send_command method."""
return self.device.send_command(command)

@staticmethod
def parse_uptime(uptime_str):
"""
Expand Down
32 changes: 32 additions & 0 deletions test/nxos/mocked_data/test_ping/normal/expected_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"success": {
"rtt_stddev": 0,
"rtt_min": 18.104,
"results": [
{
"ip_address": "8.8.8.8",
"rtt": 18.411
},
{
"ip_address": "8.8.8.8",
"rtt": 18.189
},
{
"ip_address": "8.8.8.8",
"rtt": 18.13
},
{
"ip_address": "8.8.8.8",
"rtt": 18.16
},
{
"ip_address": "8.8.8.8",
"rtt": 18.104
}
],
"rtt_max": 18.411,
"packet_loss": 0,
"rtt_avg": 18.198,
"probes_sent": 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
PING 8.8.8.8 (8.8.8.8): 100 data bytes
108 bytes from 8.8.8.8: icmp_seq=0 ttl=57 time=18.411 ms
108 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=18.189 ms
108 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=18.13 ms
108 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=18.16 ms
108 bytes from 8.8.8.8: icmp_seq=4 ttl=57 time=18.104 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 packets received, 0.00% packet loss
round-trip min/avg/max = 18.104/18.198/18.411 ms
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"success": {
"rtt_stddev": 0.0,
"rtt_min": 0.0,
"results": [],
"rtt_max": 0.0,
"packet_loss": 5,
"rtt_avg": 0.0,
"probes_sent": 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PING 8.8.8.8 (8.8.8.8): 100 data bytes
Request 0 timed out
Request 1 timed out
Request 2 timed out
Request 3 timed out
Request 4 timed out

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 0 packets received, 100.00% packet loss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"success": {
"rtt_stddev": 0.0,
"rtt_min": 0.0,
"results": [],
"rtt_max": 0.0,
"packet_loss": 5,
"rtt_avg": 0.0,
"probes_sent": 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
5 packets transmitted, 0 packets received, 100.00% packet loss

PING 8.8.8.8 (8.8.8.8): 100 data bytes
36 bytes from 10.150.102.3: Destination Host Unreachable
Request 0 timed out
36 bytes from 10.150.102.3: Destination Host Unreachable
Request 1 timed out
36 bytes from 10.150.102.3: Destination Host Unreachable
Request 2 timed out
36 bytes from 10.150.102.3: Destination Host Unreachable
Request 3 timed out
36 bytes from 10.150.102.3: Destination Host Unreachable
Request 4 timed out

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 0 packets received, 100.00% packet loss
32 changes: 32 additions & 0 deletions test/nxos_ssh/mocked_data/test_ping/normal/expected_result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"success": {
"rtt_stddev": 0,
"rtt_min": 18.104,
"results": [
{
"ip_address": "8.8.8.8",
"rtt": 18.411
},
{
"ip_address": "8.8.8.8",
"rtt": 18.189
},
{
"ip_address": "8.8.8.8",
"rtt": 18.13
},
{
"ip_address": "8.8.8.8",
"rtt": 18.16
},
{
"ip_address": "8.8.8.8",
"rtt": 18.104
}
],
"rtt_max": 18.411,
"packet_loss": 0,
"rtt_avg": 18.198,
"probes_sent": 5
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
PING 8.8.8.8 (8.8.8.8): 100 data bytes
108 bytes from 8.8.8.8: icmp_seq=0 ttl=57 time=18.411 ms
108 bytes from 8.8.8.8: icmp_seq=1 ttl=57 time=18.189 ms
108 bytes from 8.8.8.8: icmp_seq=2 ttl=57 time=18.13 ms
108 bytes from 8.8.8.8: icmp_seq=3 ttl=57 time=18.16 ms
108 bytes from 8.8.8.8: icmp_seq=4 ttl=57 time=18.104 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 packets received, 0.00% packet loss
round-trip min/avg/max = 18.104/18.198/18.411 ms