Skip to content
This repository has been archived by the owner on Sep 17, 2019. It is now read-only.

Commit

Permalink
Merge pull request #251 from napalm-automation/develop
Browse files Browse the repository at this point in the history
Preparing napalm-base 0.24.0
  • Loading branch information
mirceaulinic authored May 31, 2017
2 parents 6f37907 + 30f3d66 commit 8f644bb
Show file tree
Hide file tree
Showing 18 changed files with 206 additions and 40 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ language: python

python:
- 2.7
- 3.4
- 3.4
- 3.5

install:
- pip install .
- pip install -r requirements-dev.txt
- pip install -r requirements.txt
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install -r test/unit/requirements.txt; fi
- if [[ $TRAVIS_PYTHON_VERSION == 3.4 ]]; then pip install -r test/unit/requirements_py3.txt; fi
- pip install -r test/unit/requirements.txt

deploy:
provider: pypi
Expand Down
56 changes: 56 additions & 0 deletions napalm_base/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,40 @@ class ModuleImportError(Exception):


class ConnectionException(Exception):
'''
Unable to connect to the network device.
'''
pass


class ConnectAuthError(ConnectionException):
'''
Unable to connect to the network device
due to invalid credentials.
'''
pass


class ConnectTimeoutError(ConnectionException):
'''
Exception raised when the connection to the
network device takes too long.
This may be avoided by adjusting the `timeout`
argument.
'''
pass


class ConnectionClosedException(ConnectionException):
'''
The network device closed the connection.
Raised whenever we try to execute a certain
function, but we detect that the connection
is not usable anymore. This can happen for
various reasons: the network device terminates the
session or it is dropped by a firewall or
the server.
'''
pass


Expand All @@ -33,6 +67,28 @@ class MergeConfigException(Exception):
pass


class CommitError(Exception):
'''
Raised when unable to commit the candidate config
into the running config.
'''
pass


class LockError(Exception):
'''
Unable to lock the candidate config.
'''
pass


class UnlockError(Exception):
'''
Unable to unlock the candidate config.
'''
pass


class SessionLockedException(Exception):
pass

Expand Down
21 changes: 18 additions & 3 deletions napalm_base/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,19 @@ def mac(raw):
return py23_compat.text_type(EUI(raw, dialect=_MACFormat))


def ip(addr):
def ip(addr, version=None):
"""
Converts a raw string to a valid IP address.
Converts a raw string to a valid IP address. Optional version argument will detect that \
object matches specified version.
Motivation: the groups of the IP addreses may contain leading zeros. IPv6 addresses can \
contain sometimes uppercase characters. E.g.: 2001:0dB8:85a3:0000:0000:8A2e:0370:7334 has \
the same logical value as 2001:db8:85a3::8a2e:370:7334. However, their values as strings are \
not the same.
:param raw: the raw string containing the value of the IP Address
:param version: (optional) insist on a specific IP address version.
:type version: int.
:return: a string containing the IP Address in a standard format (no leading zeros, \
zeros-grouping, lowercase)
Expand All @@ -239,4 +242,16 @@ def ip(addr):
>>> ip('2001:0dB8:85a3:0000:0000:8A2e:0370:7334')
u'2001:db8:85a3::8a2e:370:7334'
"""
return py23_compat.text_type(IPAddress(addr))
addr_obj = IPAddress(addr)
if version and addr_obj.version != version:
raise ValueError("{} is not an ipv{} address".format(addr, version))
return py23_compat.text_type(addr_obj)


def as_number(as_number):
"""Convert AS Number to standardized asplain notation as an integer."""
if '.' in as_number:
big, little = as_number.split('.')
return (int(big) << 16) + int(little)
else:
return int(as_number)
16 changes: 14 additions & 2 deletions napalm_base/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,12 @@ def _compare_getter(src, dst):
return _compare_getter_dict(src, dst, mode)
else:
if isinstance(src, py23_compat.string_types):
m = re.search(src, py23_compat.text_type(dst))
return m is not None
if src.startswith('<') or src.startswith('>'):
cmp_result = compare_numeric(src, dst)
return cmp_result
else:
m = re.search(src, py23_compat.text_type(dst))
return m is not None
elif(type(src) == type(dst) == list):
pairs = zip(src, dst)
diff_lists = [[(k, x[k], y[k])
Expand All @@ -133,6 +137,14 @@ def _compare_getter(src, dst):
return src == dst


def compare_numeric(src_num, dst_num):
"""Compare numerical values. You can use '<%d','>%d'."""
complies = eval(str(dst_num)+src_num)
if not isinstance(complies, bool):
return False
return complies


def empty_tree(input_list):
"""Recursively iterate through values in nested lists."""
for item in input_list:
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pytest-json
pytest-pythonpath
pylama
flake8-import-order
nose
-r requirements.txt
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@

setup(
name="napalm-base",
version='0.23.3',
version='0.24.0',
packages=find_packages(),
author="David Barroso",
author_email="[email protected]",
author="David Barroso, Kirk Byers, Mircea Ulinic",
author_email="[email protected], [email protected], [email protected]",
description="Network Automation and Programmability Abstraction Layer with Multivendor support",
classifiers=[
'Topic :: Utilities',
Expand Down
13 changes: 2 additions & 11 deletions test/unit/TestGetNetworkDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,13 @@
from napalm_base import get_network_driver
from napalm_base.base import NetworkDriver
from napalm_base.exceptions import ModuleImportError
from napalm_base.utils.py23_compat import PY2, PY3


@ddt
class TestGetNetworkDriver(unittest.TestCase):
"""Test the method get_network_driver."""

drivers_common = ('eos', 'ios', 'iosxr', 'IOS-XR', 'junos', 'ros', 'nxos',
'pluribus', 'panos', 'vyos')
drivers_py2_only = ('fortios', )
if PY2:
# All drivers support python2
network_drivers = drivers_common + drivers_py2_only
elif PY3:
# Drivers that support python2 and python3
network_drivers = drivers_common
network_drivers = ('eos', 'fortios', 'ios', 'iosxr', 'IOS-XR', 'junos', 'ros', 'nxos',
'pluribus', 'panos', 'vyos')

@data(*network_drivers)
def test_get_network_driver(self, driver):
Expand Down
22 changes: 18 additions & 4 deletions test/unit/TestHelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,24 +284,38 @@ def test_mac(self):
self.assertEqual(napalm_base.helpers.mac('123.4567.89ab'), '01:23:45:67:89:AB')

def test_ip(self):

"""
Tests the helper function ```ip```:
* check if raises AddrFormatError when invalid IP address
* check if calls using incorrect version raises ValueError
* check if IPv6 address returned as expected
"""

self.assertTrue(HAS_NETADDR)

# test that raises AddrFormatError when wrong format
self.assertRaises(AddrFormatError, napalm_base.helpers.ip, 'fake')
self.assertRaises(ValueError, napalm_base.helpers.ip, '2001:db8:85a3::8a2e:370:7334',
version=4)
self.assertRaises(ValueError, napalm_base.helpers.ip, '192.168.17.1',
version=6)
self.assertEqual(
napalm_base.helpers.ip(
'2001:0dB8:85a3:0000:0000:8A2e:0370:7334'
),
napalm_base.helpers.ip('2001:0dB8:85a3:0000:0000:8A2e:0370:7334'),
'2001:db8:85a3::8a2e:370:7334'
)
self.assertEqual(
napalm_base.helpers.ip('2001:0DB8::0003', version=6),
'2001:db8::3'
)

def test_as_number(self):
"""Test the as_number helper function."""
self.assertEqual(napalm_base.helpers.as_number('64001'), 64001)
self.assertEqual(napalm_base.helpers.as_number('1.0'), 65536)
self.assertEqual(napalm_base.helpers.as_number('1.100'), 65636)
self.assertEqual(napalm_base.helpers.as_number('1.65535'), 131071)
self.assertEqual(napalm_base.helpers.as_number('65535.65535'), 4294967295)

def test_convert_uptime_string_seconds(self):
"""
Expand Down
3 changes: 2 additions & 1 deletion test/unit/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
ddt
lxml
napalm-eos
napalm-fortios
napalm-ios
napalm-iosxr
napalm-junos
napalm-nxos
napalm-pluribus
napalm-panos
napalm-pluribus
napalm-ros
napalm-vyos
11 changes: 0 additions & 11 deletions test/unit/requirements_py3.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"cpu": {
"0/RP0/CPU0": {
"%usage": 100.0
}
},
"fans": {},
"memory": {
"available_ram": 90.0,
"used_ram": 10.0
},
"power": {},
"temperature": {}
}
38 changes: 38 additions & 0 deletions test/unit/validate/mocked_data/non_strict_fail/report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,41 @@ get_route_to:
present: []
nested: true
skipped: []

get_environment:
complies: false
extra: []
missing: []
present:
cpu:
complies: False
diff:
complies: False
extra: []
missing: []
present:
0/RP0/CPU0:
complies: False
diff:
complies: False
extra: []
missing: []
present:
'%usage':
actual_value: 100.0
complies: False
nested: False
nested: True
nested: True
memory:
complies: False
diff:
complies: False
extra: []
missing: []
present:
available_ram:
actual_value: 90.0
complies: False
nested: False
nested: True
7 changes: 7 additions & 0 deletions test/unit/validate/mocked_data/non_strict_fail/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@
- next_hop: 10.155.180.22
outgoing_interface: "irb.0"
protocol: "OSPF"

- get_environment:
memory:
available_ram: "<20.0"
cpu:
0/RP0/CPU0:
"%usage": "<20.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"cpu": {
"0/RP0/CPU0": {
"%usage": 15.0
}
},
"fans": {},
"memory": {
"available_ram": 10.0,
"used_ram": 90.0
},
"power": {},
"temperature": {}
}
7 changes: 7 additions & 0 deletions test/unit/validate/mocked_data/non_strict_pass/report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ get_route_to:
missing: []
present:
10.155.180.192/26: {complies: true, nested: true}
get_environment:
complies: true
extra: []
missing: []
present:
cpu: {complies: true, nested: true}
memory: {complies: true, nested: true}
7 changes: 7 additions & 0 deletions test/unit/validate/mocked_data/non_strict_pass/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@
- next_hop: 10.155.180.22
outgoing_interface: "irb.0"
protocol: "BGP"

- get_environment:
memory:
available_ram: "<20.0"
cpu:
0/RP0/CPU0:
"%usage": "<20.0"
2 changes: 1 addition & 1 deletion test/unit/validate/mocked_data/strict_pass/report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ get_lldp_neighbors:
missing: []
present:
ge-1/0/2: {complies: true, nested: false}
ge-1/0/3: {complies: true, nested: False}
ge-1/0/3: {complies: true, nested: False}
2 changes: 1 addition & 1 deletion test/unit/validate/mocked_data/strict_pass/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@
port: "ethernet1/13"
ge-1/0/3:
- hostname: "border2.private.lon2"
port: "519"
port: "519"

0 comments on commit 8f644bb

Please sign in to comment.