Skip to content
This repository has been archived by the owner on Mar 7, 2018. It is now read-only.

Commit

Permalink
Merge pull request #141 from napalm-automation/develop
Browse files Browse the repository at this point in the history
Release 0.5.5
  • Loading branch information
mirceaulinic committed Mar 3, 2017
2 parents 3250c1c + aa65953 commit e03dc5c
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 29 deletions.
98 changes: 70 additions & 28 deletions napalm_eos/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)
self.password = password
self.timeout = timeout
self.config_session = None
self.locked = False

if optional_args is None:
optional_args = {}
Expand Down Expand Up @@ -122,15 +123,26 @@ def is_alive(self):
'is_alive': True # always true as eAPI is HTTP-based
}

def _load_config(self, filename=None, config=None, replace=True):
if self.config_session is not None:
raise SessionLockedException('Session is already in use by napalm')
def _lock(self):
if not self.locked:
self.locked = True
else:
self.config_session = 'napalm_{}'.format(datetime.now().microsecond)
# already locked
raise SessionLockedException('Session is already in use by napalm')

def _unlock(self):
if self.locked:
self.locked = False

def _load_config(self, filename=None, config=None, replace=True):
commands = []
commands.append('configure session {}'.format(self.config_session))

self._lock()
if self.config_session is None:
# create a new session
# otherwise will preserve the previous configuration session
self.config_session = 'napalm_{}'.format(datetime.now().microsecond)
commands.append('configure session {}'.format(self.config_session))
if replace:
commands.append('rollback clean-config')

Expand All @@ -155,11 +167,12 @@ def _load_config(self, filename=None, config=None, replace=True):
self.device.run_commands(commands)
except pyeapi.eapilib.CommandError as e:
self.discard_config()

if replace:
raise ReplaceConfigException(e.message)
else:
raise MergeConfigException(e.message)
finally:
self._unlock()

def load_replace_candidate(self, filename=None, config=None):
"""Implementation of NAPALM method load_replace_candidate."""
Expand Down Expand Up @@ -523,9 +536,12 @@ def get_lldp_neighbors_detail(self, interface=''):
for neighbor in interface_neighbors:
if interface not in lldp_neighbors_out.keys():
lldp_neighbors_out[interface] = []
capabilities = neighbor.get('systemCapabilities')
capabilities = neighbor.get('systemCapabilities', {})
capabilities_list = list(capabilities.keys())
capabilities_list.sort()
remote_chassis_id = neighbor.get('chassisId', u'')
if neighbor.get("chassisIdType", u'') == "macAddress":
remote_chassis_id = napalm_base.helpers.mac(remote_chassis_id)
lldp_neighbors_out[interface].append(
{
'parent_interface': interface, # no parent interfaces
Expand All @@ -534,8 +550,7 @@ def get_lldp_neighbors_detail(self, interface=''):
'remote_port_description': u'',
'remote_system_name': neighbor.get('systemName', u''),
'remote_system_description': neighbor.get('systemDescription', u''),
'remote_chassis_id': napalm_base.helpers.mac(
neighbor.get('chassisId', u'')),
'remote_chassis_id': remote_chassis_id,
'remote_system_capab': py23_compat.text_type(', '.join(capabilities_list)),
'remote_system_enable_capab': py23_compat.text_type(', '.join(
[capability for capability in capabilities_list
Expand Down Expand Up @@ -1173,8 +1188,17 @@ def traceroute(self,
destination,
source=c.TRACEROUTE_SOURCE,
ttl=c.TRACEROUTE_TTL,
timeout=c.TRACEROUTE_TIMEOUT):

timeout=c.TRACEROUTE_TIMEOUT,
vrf=c.TRACEROUTE_VRF):
'''
.. note:
`vrf` is partially supported by eOS: if the user
want to execute a traceroute from a certain VRF, the rest
of the arguments will be ignored.
So one can either request a traceroute using `source`, `ttl` or `timeout`,
either using the `vrf` argument.
'''
_HOP_ENTRY_PROBE = [
'\s+',
'(', # beginning of host_name (ip_address) RTT group
Expand Down Expand Up @@ -1208,27 +1232,39 @@ def traceroute(self,
probes = 3
# in case will be added one further param to adjust the number of probes/hop

if source:
source_opt = '-s {source}'.format(source=source)
if ttl:
ttl_opt = '-m {ttl}'.format(ttl=ttl)
if timeout:
timeout_opt = '-w {timeout}'.format(timeout=timeout)
if not vrf:
if source:
source_opt = '-s {source}'.format(source=source)
if ttl:
ttl_opt = '-m {ttl}'.format(ttl=ttl)
if timeout:
timeout_opt = '-w {timeout}'.format(timeout=timeout)
total_timeout = timeout * ttl
# `ttl`, `source` and `timeout` are not supported by default CLI
# so we need to go through the bash and set a specific timeout
commands = [
('bash timeout {total_timeout} traceroute {destination} '
'{source_opt} {ttl_opt} {timeout_opt}').format(
total_timeout=total_timeout,
destination=destination,
source_opt=source_opt,
ttl_opt=ttl_opt,
timeout_opt=timeout_opt
)
]
else:
timeout = 5

command = 'traceroute {destination} {source_opt} {ttl_opt} {timeout_opt}'.format(
destination=destination,
source_opt=source_opt,
ttl_opt=ttl_opt,
timeout_opt=timeout_opt
)
commands = [
'traceroute {vrf} {destination}'.format(
vrf=vrf,
destination=destination
)
]

try:
traceroute_raw_output = self.device.run_commands(
[command], encoding='text')[0].get('output')
commands, encoding='text')[0].get('output')
except CommandErrorException:
return {'error': 'Cannot execute traceroute on the device: {}'.format(command)}
return {'error': 'Cannot execute traceroute on the device: {}'.format(commands[0])}

hop_regex = ''.join(_HOP_ENTRY + _HOP_ENTRY_PROBE * probes)

Expand Down Expand Up @@ -1581,7 +1617,7 @@ def get_network_instances(self, name=''):
return vrfs

def ping(self, destination, source=c.PING_SOURCE, ttl=c.PING_TTL, timeout=c.PING_TIMEOUT,
size=c.PING_SIZE, count=c.PING_COUNT):
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:
Expand All @@ -1598,6 +1634,12 @@ def ping(self, destination, source=c.PING_SOURCE, ttl=c.PING_TTL, timeout=c.PING
'results' is a list of dictionaries with the following keys:
* ip_address (str)
* rtt (float)
.. note:
`vrf` is not supported on eOS. Although the user is able
to set this argument, it will not be interepreted by the
operating system.
"""
ping_dict = {}
command = 'ping {}'.format(destination)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name="napalm-eos",
version="0.5.3",
version="0.5.5",
packages=find_packages(),
author="David Barroso, Mircea Ulinic",
author_email="dbarrosop@dravetech.com, mircea@cloudflare.com",
Expand Down

0 comments on commit e03dc5c

Please sign in to comment.