From 27da089eadbbda108158d1056d55352385644ba3 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Fri, 9 Feb 2018 06:22:33 -0500 Subject: [PATCH 01/21] Bump dev version --- VERSION | 2 +- pyeapi/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 100435b..8a6a5a9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.2 +0.8.2-rc0 diff --git a/pyeapi/__init__.py b/pyeapi/__init__.py index 0c069f4..84be709 100644 --- a/pyeapi/__init__.py +++ b/pyeapi/__init__.py @@ -29,7 +29,7 @@ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -__version__ = '0.8.2' +__version__ = '0.8.2-rc0' __author__ = 'Arista EOS+' From 722f615ca3b262ab728756ba4555a3c5ee742d67 Mon Sep 17 00:00:00 2001 From: Jere Julian Date: Fri, 9 Feb 2018 06:23:00 -0500 Subject: [PATCH 02/21] Add development requirements file --- requirements-dev.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 requirements-dev.txt diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..cf4dd93 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,5 @@ +-r requirements.txt +flake8 +pep8 +pyflakes +twine From 46aaa8d923ceb7a2f9265d193bb3e7454cc79ef3 Mon Sep 17 00:00:00 2001 From: Alex Feigenson Date: Mon, 16 Apr 2018 07:55:25 -0500 Subject: [PATCH 03/21] Fixing typo in bgp.py --- pyeapi/api/bgp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyeapi/api/bgp.py b/pyeapi/api/bgp.py index 54e74f9..5ac297c 100644 --- a/pyeapi/api/bgp.py +++ b/pyeapi/api/bgp.py @@ -234,7 +234,7 @@ def _parse_description(self, config, name): return dict(description=value) def _parse_next_hop_self(self, config, name): - exp = 'no neighobr {} next-hop-self'.format(name) + exp = 'no neighbor {} next-hop-self'.format(name) value = exp in config return dict(next_hop_self=not value) From 3ef84bad6010163b4810efc984e4343cbea6a61e Mon Sep 17 00:00:00 2001 From: Xavier Hardy Date: Sat, 28 Jul 2018 17:59:36 +0100 Subject: [PATCH 04/21] Remove leaked base64 authentication string in debug logs --- pyeapi/eapilib.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index 26eed35..c6ce8f3 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -240,20 +240,21 @@ def authentication(self, username, password): the eAPI connection with """ + _auth_text = '{}:{}'.format(username, password) + # Work around for Python 2.7/3.x compatibility if int(sys.version[0]) > 2: # For Python 3.x - _auth_text = '{}:{}'.format(username, password) _auth_bin = base64.encodebytes(_auth_text.encode()) _auth = _auth_bin.decode() _auth = _auth.replace('\n', '') self._auth = _auth else: # For Python 2.7 - _auth = base64.encodestring('{}:{}'.format(username, password)) + _auth = base64.encodestring(_auth_text) self._auth = str(_auth).replace('\n', '') - _LOGGER.debug('Autentication string is: {}'.format(self._auth)) + _LOGGER.debug('Autentication string is: {}:***'.format(username)) def request(self, commands, encoding=None, reqid=None, **kwargs): """Generates an eAPI request object From 96a74faef1fe3bd79c4e900aed29c9956a0587d6 Mon Sep 17 00:00:00 2001 From: Xavier Hardy Date: Sat, 28 Jul 2018 18:36:38 +0100 Subject: [PATCH 05/21] Remove useless requirements-dev.txt file --- dev-requirements.txt | 4 +--- requirements-dev.txt | 5 ----- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 requirements-dev.txt diff --git a/dev-requirements.txt b/dev-requirements.txt index aa05d1f..3accc1f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,4 +1,4 @@ -netaddr +-r requirements.txt mock coveralls twine @@ -12,5 +12,3 @@ flake8 flake8-print flake8-debugger pep8-naming - - diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index cf4dd93..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,5 +0,0 @@ --r requirements.txt -flake8 -pep8 -pyflakes -twine From a58f39235014889b633930158590231f9673aa5a Mon Sep 17 00:00:00 2001 From: mharista Date: Thu, 6 Jun 2019 13:41:09 -0400 Subject: [PATCH 06/21] Add ability to use eapi with certs. Handle both ignoring server validation against CA and requiring server validation against CA. --- pyeapi/client.py | 21 +++++++++--- pyeapi/eapilib.py | 72 +++++++++++++++++++++++++++++++++++++++- test/unit/test_client.py | 15 ++++++--- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/pyeapi/client.py b/pyeapi/client.py index 52e80d6..8a0947e 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -106,6 +106,7 @@ from pyeapi.utils import load_module, make_iterable, debug from pyeapi.eapilib import HttpEapiConnection, HttpsEapiConnection +from pyeapi.eapilib import HttpsEapiCertConnection from pyeapi.eapilib import SocketEapiConnection, HttpLocalEapiConnection from pyeapi.eapilib import CommandError @@ -115,7 +116,8 @@ 'socket': SocketEapiConnection, 'http_local': HttpLocalEapiConnection, 'http': HttpEapiConnection, - 'https': HttpsEapiConnection + 'https': HttpsEapiConnection, + 'https_certs': HttpsEapiCertConnection } DEFAULT_TRANSPORT = 'https' @@ -327,6 +329,7 @@ def load_config(filename): """ return config.load(filename) + def config_for(name): """ Function to get settings for named config @@ -344,6 +347,7 @@ def config_for(name): """ return config.get_connection(name) + def hosts_for_tag(tag): """ Returns the hosts assocated with the specified tag @@ -361,6 +365,7 @@ def hosts_for_tag(tag): """ return config.tags.get(tag) + def make_connection(transport, **kwargs): """ Creates a connection instance based on the transport @@ -386,7 +391,8 @@ def make_connection(transport, **kwargs): def connect(transport=None, host='localhost', username='admin', - password='', port=None, timeout=60, return_node=False, **kwargs): + password='', port=None, key_file=None, cert_file=None, + ca_file=None, timeout=60, return_node=False, **kwargs): """ Creates a connection using the supplied settings This function will create a connection to an Arista EOS node using @@ -405,6 +411,10 @@ def connect(transport=None, host='localhost', username='admin', port (int): The TCP port of the endpoint for the eAPI connection. If this keyword is not specified, the default value is automatically determined by the transport type. (http=80, https=443) + key_file (str): Path to private key file for ssl validation + cert_file (str): Path to PEM formatted cert file for ssl validation + ca_file (str): Path to CA PEM formatted cert file for ssl validation + timeout (int): timeout return_node (bool): Returns a Node object if True, otherwise returns an EapiConnection object. @@ -415,10 +425,13 @@ def connect(transport=None, host='localhost', username='admin', """ transport = transport or DEFAULT_TRANSPORT connection = make_connection(transport, host=host, username=username, - password=password, port=port, timeout=timeout) + password=password, key_file=key_file, + cert_file=cert_file, ca_file=ca_file, + port=port, timeout=timeout) if return_node: return Node(connection, transport=transport, host=host, - username=username, password=password, port=port, **kwargs) + username=username, password=password, key_file=key_file, + cert_file=cert_file, ca_file=ca_file, port=port, **kwargs) return connection diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index c6ce8f3..4f9208a 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -58,6 +58,7 @@ DEFAULT_HTTP_PORT = 80 DEFAULT_HTTPS_PORT = 443 DEFAULT_HTTP_LOCAL_PORT = 8080 +DEFAULT_HTTPS_LOCAL_PORT = 8443 DEFAULT_HTTP_PATH = '/command-api' DEFAULT_UNIX_SOCKET = '/var/run/command-api.sock' @@ -207,6 +208,58 @@ def __repr__(self): return 'https://%s:%s/%s' % (self.host, self.port, self.path) +class HTTPSCertConnection(HTTPSConnection): + """ Class to make a HTTPS connection, with support + for full client-based SSL Authentication. + """ + + def __init__(self, path, host, port, key_file, cert_file, ca_file, + timeout=None): + HTTPSConnection.__init__(self, host, key_file=key_file, + cert_file=cert_file) + self.key_file = key_file + self.cert_file = cert_file + self.ca_file = ca_file + self.timeout = timeout + self.path = path + self.port = port + + def __str__(self): + return 'https://%s:%s/%s - %s,%s' % (self.host, self.port, self.path, + self.key_file, self.cert_file) + + def __repr__(self): + return 'https://%s:%s/%s - %s,%s' % (self.host, self.port, self.path, + self.key_file, self.cert_file) + + def connect(self): + """ Connect to a host on a given (SSL) port. + If ca_file is pointing somewhere, use it + to check Server Certificate. + + Redefined/copied and extended from httplib.py:1105 (Python 2.6.x). + This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter + to ssl.wrap_socket(), which forces SSL to check server certificate + against our client certificate. + """ + print('IN CONNECT') + sock = socket.create_connection((self.host, self.port), self.timeout) + if self._tunnel_host: + self.sock = sock + self._tunnel() + # If there's no CA File, don't force Server Certificate Check + if self.ca_file: + print('VERIFY SERVER USING CA FILE') + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + ca_certs=self.ca_file, + cert_reqs=ssl.CERT_REQUIRED) + else: + print('NO VERIFY SERVER. NO CA FILE') + self.sock = ssl.wrap_socket(sock, self.key_file, + self.cert_file, + cert_reqs=ssl.CERT_NONE) + + class EapiConnection(object): """Creates a connection to eAPI for sending and receiving eAPI requests @@ -551,7 +604,7 @@ def __init__(self, host, port=None, path=None, username=None, def disable_certificate_verification(self): # SSL/TLS certificate verification is enabled by default in latest # Python releases and causes self-signed certificates generated - # on EOS to fail validation (unless explicitely imported). + # on EOS to fail validation (unless explicitly imported). # Disable the SSL/TLS certificate verification for now. # Use the approach in PEP476 to disable certificate validation. # TODO: @@ -560,3 +613,20 @@ def disable_certificate_verification(self): # temporary until a proper fix is implemented. if hasattr(ssl, '_create_unverified_context'): return ssl._create_unverified_context() + + +class HttpsEapiCertConnection(EapiConnection): + def __init__(self, host, port=None, path=None, key_file=None, + cert_file=None, ca_file=None, timeout=60): + if key_file is None or cert_file is None: + raise ValueError("For https_cert connections both a key_file and " + "cert_file are required. A ca_file is also " + "recommended") + super(HttpsEapiCertConnection, self).__init__() + port = port or DEFAULT_HTTPS_PORT + path = path or DEFAULT_HTTP_PATH + + self.transport = HTTPSCertConnection(path, host, int(port), + key_file=key_file, + cert_file=cert_file, + ca_file=ca_file, timeout=timeout) diff --git a/test/unit/test_client.py b/test/unit/test_client.py index 1cf3977..b5c6ecc 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -310,7 +310,8 @@ def test_hosts_for_tag_returns_names(self): def test_connect_types(self, connection): transports = list(pyeapi.client.TRANSPORTS.keys()) kwargs = dict(host='localhost', username='admin', password='', - port=None, timeout=60) + port=None, key_file=None, cert_file=None, + ca_file=None, timeout=60) for transport in transports: pyeapi.client.connect(transport) @@ -408,7 +409,8 @@ def test_connect_default_type(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): pyeapi.client.connect() kwargs = dict(host='localhost', username='admin', password='', - port=None, timeout=60) + port=None, key_file=None, cert_file=None, + ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) def test_connect_return_node(self): @@ -420,7 +422,8 @@ def test_connect_return_node(self): password='password', port=None, timeout=60, return_node=True) kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, timeout=60) + password='password', port=None, key_file=None, + cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertIsNone(node._enablepwd) @@ -434,7 +437,8 @@ def test_connect_return_node_enablepwd(self): timeout=60, enablepwd='enablepwd', return_node=True) kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, timeout=60) + password='password', port=None, key_file=None, + cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') @@ -445,7 +449,8 @@ def test_connect_to_with_config(self): pyeapi.client.load_config(filename=conf) node = pyeapi.client.connect_to('test1') kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, timeout=60) + password='password', port=None, key_file=None, + cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') From 280735745701f2e86040198b031a0bb1c846d629 Mon Sep 17 00:00:00 2001 From: mharista Date: Thu, 6 Jun 2019 16:13:55 -0400 Subject: [PATCH 07/21] Add kwargs handling to HttpsEapiCertConnection class. --- pyeapi/eapilib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index 4f9208a..2b074ca 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -617,7 +617,7 @@ def disable_certificate_verification(self): class HttpsEapiCertConnection(EapiConnection): def __init__(self, host, port=None, path=None, key_file=None, - cert_file=None, ca_file=None, timeout=60): + cert_file=None, ca_file=None, timeout=60, **kwargs): if key_file is None or cert_file is None: raise ValueError("For https_cert connections both a key_file and " "cert_file are required. A ca_file is also " From bd96810e206f318a5fc9e7c1a9e486f1c7ba9101 Mon Sep 17 00:00:00 2001 From: mharista Date: Thu, 6 Jun 2019 16:21:50 -0400 Subject: [PATCH 08/21] Remove print statements. --- pyeapi/eapilib.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyeapi/eapilib.py b/pyeapi/eapilib.py index 2b074ca..3e0f679 100644 --- a/pyeapi/eapilib.py +++ b/pyeapi/eapilib.py @@ -242,19 +242,16 @@ def connect(self): to ssl.wrap_socket(), which forces SSL to check server certificate against our client certificate. """ - print('IN CONNECT') sock = socket.create_connection((self.host, self.port), self.timeout) if self._tunnel_host: self.sock = sock self._tunnel() # If there's no CA File, don't force Server Certificate Check if self.ca_file: - print('VERIFY SERVER USING CA FILE') self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ca_certs=self.ca_file, cert_reqs=ssl.CERT_REQUIRED) else: - print('NO VERIFY SERVER. NO CA FILE') self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, cert_reqs=ssl.CERT_NONE) From eff975ef150c9394c544a3fd5c7aae74aef149bc Mon Sep 17 00:00:00 2001 From: mharista Date: Wed, 26 Jun 2019 13:33:10 -0400 Subject: [PATCH 09/21] Update docs for new certificate parameters. --- docs/configfile.rst | 28 +++++++++++++++++++++++++++- docs/quickstart.rst | 1 + 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/configfile.rst b/docs/configfile.rst index 49689c3..b34a304 100644 --- a/docs/configfile.rst +++ b/docs/configfile.rst @@ -39,13 +39,15 @@ The following configuration options are available for defining node entries: - http_local (available in EOS 4.14.5 or later) - http - https + - https_certs :port: Configures the port to use for the eAPI connection. A default port is used if this parameter is absent, based on the transport setting using the following values: - transport: http, default port: 80 - - transport: https, deafult port: 443 + - transport: https, default port: 443 + - transport: https_certs, default port: 443 - transport: http_local, default port: 8080 - transport: socket, default port: n/a @@ -62,6 +64,7 @@ Transport eapi.conf Required Script run from Authentication Required =========== ================== =============== ======================== http Yes On/Off-switch Yes https Yes On/Off-switch Yes +https_certs Yes On/Off-switch Yes (Auth done via certs, not un/pw) http_local Yes On-switch only No socket No On-switch only No =========== ================== =============== ======================== @@ -169,6 +172,29 @@ As the table above indicates, a pyeapi configuration file is required in username: admin password: admin +Using HTTPS with Certificates +============================= + +The https_certs transport options allows users to do authentication for pyeapi +with certificates instead of username/password. This requires functional +certificate chains are setup, copied to the proper location and trusted by +EOS beforehand. The ca_file parameter is optional. If provided the switches +certificate will also be validated against the provided CA cert. If no CA cert +is provided then no server side validation will be done. + +.. code-block:: console + + [connection:veos01] + transport: https_certs + cert_file: /path/to/certificate/file + key_file: /path/to/private/key/file + ca_file: /path/to/CA/certificate/file + + [connection:veos02] + transport: https_certs + cert_file: /path/to/certificate/file + key_file: /path/to/private/key/file + ******************* The DEFAULT Section ******************* diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 8934cd6..333bd54 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -19,6 +19,7 @@ include: - HTTP - HTTPS + - HTTPS Certificates - HTTP Local - Unix Socket From 9dbd98c0e4d5bc0b3c9b9ff71875409efecd36a7 Mon Sep 17 00:00:00 2001 From: MattH Date: Wed, 6 Nov 2019 10:05:24 -0500 Subject: [PATCH 10/21] Updated imp usages to importlib. --- pyeapi/utils.py | 16 ++++++++++++++++ test/unit/test_utils.py | 3 +++ 2 files changed, 19 insertions(+) diff --git a/pyeapi/utils.py b/pyeapi/utils.py index 4386cad..0030ea0 100644 --- a/pyeapi/utils.py +++ b/pyeapi/utils.py @@ -32,6 +32,7 @@ import os import sys import imp +import importlib import inspect import logging import logging.handlers @@ -77,6 +78,10 @@ def import_module(name): Returns: The module that was imported + """ + print('import_module') + print('name - %s' % name) + """ parts = name.split('.') path = None @@ -88,18 +93,29 @@ def import_module(name): path = [path] if path is not None else path try: + print('IN TRY - PART %s' % part) + print('IN TRY - PATH %s' % path) fhandle, path, descr = imp.find_module(part, path) if module_name in sys.modules: + print('FOUND IN SYS.MODULES %s' % module_name) # since imp.load_module works like reload, need to be sure not # to reload a previously loaded module mod = sys.modules[module_name] else: + print('LOAD %s' % module_name) mod = imp.load_module(module_name, fhandle, path, descr) finally: + print('IN FINALLY') # lets be sure to clean up after ourselves if fhandle: fhandle.close() + """ + if name in sys.modules: + mod = sys.modules[name] + else: + mod = importlib.import_module(name) + print('PRE RETURN') return mod diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index b04de5e..64825f0 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -5,6 +5,7 @@ import pyeapi.utils + class TestUtils(unittest.TestCase): @patch('pyeapi.utils.import_module') @@ -40,10 +41,12 @@ def test_make_iterable_raises_type_error(self): pyeapi.utils.make_iterable(object()) def test_import_module(self): + print('test_import_module') result = pyeapi.utils.import_module('pyeapi.api.vlans') self.assertIsNotNone(result) def test_import_module_raises_import_error(self): + print('test_import_module_error') with self.assertRaises(ImportError): pyeapi.utils.import_module('fake.module.test') From 3a0c8ff9db99650d3ec312dbbe57c7461ed05133 Mon Sep 17 00:00:00 2001 From: MattH Date: Wed, 6 Nov 2019 11:12:23 -0500 Subject: [PATCH 11/21] Remove old imp code and print statements. Fix flake8 issues. --- pyeapi/api/routemaps.py | 4 ++-- pyeapi/api/staticroute.py | 6 ++--- pyeapi/api/system.py | 2 +- pyeapi/api/varp.py | 2 +- pyeapi/api/vrrp.py | 2 +- pyeapi/client.py | 4 ++-- pyeapi/utils.py | 34 ----------------------------- test/system/test_api_staticroute.py | 4 ++-- test/system/test_api_system.py | 4 +--- test/system/test_client.py | 7 +++--- test/unit/test_utils.py | 2 -- 11 files changed, 16 insertions(+), 55 deletions(-) diff --git a/pyeapi/api/routemaps.py b/pyeapi/api/routemaps.py index 6c513c8..6addc7a 100644 --- a/pyeapi/api/routemaps.py +++ b/pyeapi/api/routemaps.py @@ -239,7 +239,7 @@ def set_match_statements(self, name, action, seqno, statements): """ try: current_statements = self.get(name)[action][seqno]['match'] - except: + except Exception: current_statements = [] commands = list() @@ -275,7 +275,7 @@ def set_set_statements(self, name, action, seqno, statements): """ try: current_statements = self.get(name)[action][seqno]['set'] - except: + except Exception: current_statements = [] commands = list() diff --git a/pyeapi/api/staticroute.py b/pyeapi/api/staticroute.py index 5b1ce13..f5a5637 100644 --- a/pyeapi/api/staticroute.py +++ b/pyeapi/api/staticroute.py @@ -158,13 +158,13 @@ def getall(self): # Get the four identifying components ip_dest = match[0] next_hop = match[1] - next_hop_ip = None if match[2] is '' else match[2] + next_hop_ip = None if match[2] == '' else match[2] distance = int(match[3]) # Create the data dict with the remaining components data = {} - data['tag'] = None if match[4] is '' else int(match[4]) - data['route_name'] = None if match[5] is '' else match[5] + data['tag'] = None if match[4] == '' else int(match[4]) + data['route_name'] = None if match[5] == '' else match[5] # Build the complete dict entry from the four components # and the data. diff --git a/pyeapi/api/system.py b/pyeapi/api/system.py index 01de13d..ef9107b 100644 --- a/pyeapi/api/system.py +++ b/pyeapi/api/system.py @@ -105,7 +105,7 @@ def _parse_banners(self): into the resource dict """ motd_value = login_value = None - matches = re.findall('^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n', + matches = re.findall(r'^banner\s+(login|motd)\s?$\n(.*?)$\nEOF$\n', self.config, re.DOTALL | re.M) for match in matches: if match[0].strip() == "motd": diff --git a/pyeapi/api/varp.py b/pyeapi/api/varp.py index b68b126..c2715d4 100644 --- a/pyeapi/api/varp.py +++ b/pyeapi/api/varp.py @@ -178,7 +178,7 @@ def set_addresses(self, name, addresses=None, default=False, elif addresses is not None: try: current_addresses = self.get(name)['addresses'] - except: + except Exception: current_addresses = [] # remove virtual-router addresses not present in addresses list diff --git a/pyeapi/api/vrrp.py b/pyeapi/api/vrrp.py index a63af21..c6a8b2b 100644 --- a/pyeapi/api/vrrp.py +++ b/pyeapi/api/vrrp.py @@ -1156,7 +1156,7 @@ def _vrrp_set(self, name, vrid, **kwargs): if primary_ip in ('no', None): cmd = self.set_primary_ip(name, vrid, value=None, disable=True, run=False) - elif primary_ip is 'default': + elif primary_ip == 'default': cmd = self.set_primary_ip(name, vrid, value=None, default=True, run=False) else: diff --git a/pyeapi/client.py b/pyeapi/client.py index 8a0947e..e8c834e 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -530,13 +530,13 @@ def _get_version_properties(self): # Parse out version info output = self.enable('show version') self._version = str(output[0]['result']['version']) - match = re.match('[\d.\d]+', output[0]['result']['version']) + match = re.match(r'[\d.\d]+', output[0]['result']['version']) if match: self._version_number = str(match.group(0)) else: self._version_number = str(output[0]['result']['version']) # Parse out model number - match = re.search('\d\d\d\d', output[0]['result']['modelName']) + match = re.search(r'\d\d\d\d', output[0]['result']['modelName']) if match: self._model = str(match.group(0)) else: diff --git a/pyeapi/utils.py b/pyeapi/utils.py index 0030ea0..8a6e425 100644 --- a/pyeapi/utils.py +++ b/pyeapi/utils.py @@ -31,7 +31,6 @@ # import os import sys -import imp import importlib import inspect import logging @@ -79,43 +78,10 @@ def import_module(name): The module that was imported """ - print('import_module') - print('name - %s' % name) - - """ - parts = name.split('.') - path = None - module_name = '' - fhandle = None - - for index, part in enumerate(parts): - module_name = part if index == 0 else '%s.%s' % (module_name, part) - path = [path] if path is not None else path - - try: - print('IN TRY - PART %s' % part) - print('IN TRY - PATH %s' % path) - fhandle, path, descr = imp.find_module(part, path) - if module_name in sys.modules: - print('FOUND IN SYS.MODULES %s' % module_name) - # since imp.load_module works like reload, need to be sure not - # to reload a previously loaded module - mod = sys.modules[module_name] - else: - print('LOAD %s' % module_name) - mod = imp.load_module(module_name, fhandle, path, descr) - finally: - print('IN FINALLY') - # lets be sure to clean up after ourselves - if fhandle: - fhandle.close() - """ if name in sys.modules: mod = sys.modules[name] else: mod = importlib.import_module(name) - - print('PRE RETURN') return mod diff --git a/test/system/test_api_staticroute.py b/test/system/test_api_staticroute.py index 1082812..2b4395f 100644 --- a/test/system/test_api_staticroute.py +++ b/test/system/test_api_staticroute.py @@ -52,14 +52,14 @@ def _ip_addr(): def _next_hop(): next_hop = choice(NEXT_HOPS) - if next_hop is 'Null0': + if next_hop == 'Null0': return (next_hop, None) ip1 = random_int(0, 223) ip2 = random_int(0, 255) ip3 = random_int(0, 255) ip4 = random_int(0, 255) ip_addr = "%s.%s.%s.%s" % (ip1, ip2, ip3, ip4) - if next_hop is 'IP': + if next_hop == 'IP': return (ip_addr, None) return (next_hop, ip_addr) diff --git a/test/system/test_api_system.py b/test/system/test_api_system.py index c281079..8474f0e 100644 --- a/test/system/test_api_system.py +++ b/test/system/test_api_system.py @@ -160,7 +160,7 @@ def test_set_banner_motd(self): def test_set_banner_motd_donkey(self): for dut in self.duts: - donkey_chicken = """ + donkey_chicken = r""" /\ /\ ( \\ // ) \ \\ // / @@ -187,8 +187,6 @@ def test_set_banner_motd_donkey(self): self.assertTrue(resp, 'dut=%s' % dut) self.assertIn(donkey_chicken, dut.running_config) - - def test_set_banner_motd_default(self): for dut in self.duts: dut.config([dict(cmd="banner motd", diff --git a/test/system/test_client.py b/test/system/test_client.py index 200ef59..980825e 100644 --- a/test/system/test_client.py +++ b/test/system/test_client.py @@ -274,11 +274,11 @@ def test_exception_trace(self): # Send an incomplete command cases.append(('show run', rfmt % (1002, 'invalid command', - 'incomplete token \(at token \d+: \'.*\'\)'))) + r'incomplete token \(at token \d+: \'.*\'\)'))) # Send a mangled command cases.append(('shwo version', rfmt % (1002, 'invalid command', - 'Invalid input \(at token \d+: \'.*\'\)'))) + r'Invalid input \(at token \d+: \'.*\'\)'))) # Send a command that cannot be run through the api # note the command for reload looks to change in new EOS # in 4.15 the reload now is replaced with 'force' if you are @@ -295,8 +295,7 @@ def test_exception_trace(self): # Send a command that has insufficient priv cases.append(('show running-config', rfmt % (1002, 'invalid command', - 'Invalid input \(privileged mode required\)'))) - + r'Invalid input \(privileged mode required\)'))) for dut in self.duts: for (cmd, regex) in cases: diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index 64825f0..ed44123 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -41,12 +41,10 @@ def test_make_iterable_raises_type_error(self): pyeapi.utils.make_iterable(object()) def test_import_module(self): - print('test_import_module') result = pyeapi.utils.import_module('pyeapi.api.vlans') self.assertIsNotNone(result) def test_import_module_raises_import_error(self): - print('test_import_module_error') with self.assertRaises(ImportError): pyeapi.utils.import_module('fake.module.test') From 65be6c03c932d3a659626f8a293e06216bcd735b Mon Sep 17 00:00:00 2001 From: MattH Date: Wed, 6 Nov 2019 11:24:40 -0500 Subject: [PATCH 12/21] Add import_module comment back in. --- pyeapi/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyeapi/utils.py b/pyeapi/utils.py index 8a6e425..14d7931 100644 --- a/pyeapi/utils.py +++ b/pyeapi/utils.py @@ -79,6 +79,7 @@ def import_module(name): """ if name in sys.modules: + # Be sure not to reload a previously loaded module mod = sys.modules[name] else: mod = importlib.import_module(name) From 5174ae6c98a8ddcef26320b0e6a8a6640fee9e77 Mon Sep 17 00:00:00 2001 From: Joker Date: Mon, 11 Nov 2019 14:38:46 -0800 Subject: [PATCH 13/21] Update acl.py --- pyeapi/api/acl.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pyeapi/api/acl.py b/pyeapi/api/acl.py index 498e544..bff0fdc 100644 --- a/pyeapi/api/acl.py +++ b/pyeapi/api/acl.py @@ -243,17 +243,18 @@ def _parse_entries(self, config): entries = dict() for item in re.finditer(r'\d+ [p|d].*$', config, re.M): match = self.entry_re.match(item.group(0)) - entry = dict() - entry['action'] = match.group(2) - entry['protocol'] = match.group(3) - entry['srcaddr'] = match.group(5) or 'any' - entry['srclen'] = match.group(6) - entry['srcport'] = match.group(7) - entry['dstaddr'] = match.group(9) or 'any' - entry['dstlen'] = match.group(10) - entry['dstport'] = match.group(12) - entry['other'] = match.group(13) - entries[match.group(1)] = entry + if match: + entry = dict() + entry['action'] = match.group(2) + entry['protocol'] = match.group(3) + entry['srcaddr'] = match.group(5) or 'any' + entry['srclen'] = match.group(6) + entry['srcport'] = match.group(7) + entry['dstaddr'] = match.group(9) or 'any' + entry['dstlen'] = match.group(10) + entry['dstport'] = match.group(12) + entry['other'] = match.group(13) + entries[match.group(1)] = entry return dict(entries=entries) def create(self, name): From 54bb000628aa7303a43e3ec155f6144ceed92b5d Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 Dec 2019 16:49:24 +0000 Subject: [PATCH 14/21] Add 4.20.0F and 4.21.3F command syntax change --- pyeapi/api/vrrp.py | 591 ++++++++++++++++++++++++++++++++++- test/system/test_api_vrrp.py | 84 ++--- 2 files changed, 618 insertions(+), 57 deletions(-) diff --git a/pyeapi/api/vrrp.py b/pyeapi/api/vrrp.py index c6a8b2b..cd3b87d 100644 --- a/pyeapi/api/vrrp.py +++ b/pyeapi/api/vrrp.py @@ -157,11 +157,20 @@ from pyeapi.api import EntityCollection -PROPERTIES = ['primary_ip', 'priority', 'description', 'secondary_ip', - 'ip_version', 'enable', 'timers_advertise', - 'mac_addr_adv_interval', 'preempt', - 'preempt_delay_min', 'preempt_delay_reload', - 'delay_reload', 'track', 'bfd_ip'] +PROPERTIES = ['primary_ip', 'primary_ipv4', + 'priority', 'priority_level', + 'description', 'session_description', + 'secondary_ip', 'secondary_ipv4', + 'ip_version', 'ipv4_version', + 'enable', 'enabled', + 'timers_advertise', 'advertisement interval', + 'mac_addr_adv_interval', + 'preempt', + 'preempt_delay_min', + 'preempt_delay_reload', + 'delay_reload', 'timers_delay_reload', + 'track', + 'bfd_ip'] class Vrrp(EntityCollection): @@ -256,23 +265,54 @@ def _parse_enable(self, config, vrid): return dict(enable=False) return dict(enable=True) + def _parse_enabled(self, config, vrid): + match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) + if match: + return dict(enabled=False) + return dict(enabled=True) + def _parse_primary_ip(self, config, vrid): match = re.search(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+)$' % vrid, config, re.M) value = match.group(1) if match else None return dict(primary_ip=value) + def _parse_primary_ipv4(self, config, vrid): + match = re.search(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+)$' % + vrid, config, re.M) + value = match.group(1) if match else None + return dict(primary_ipv4=value) + + def _parse_primary_ipv6(self, config, vrid): + match = re.search(r'^\s+vrrp %s ' + r'ipv6 (^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4})$' % + vrid, config, re.M) + value = match.group(1) if match else None + return dict(primary_ipv6=value) + def _parse_priority(self, config, vrid): match = re.search(r'^\s+vrrp %s priority (\d+)$' % vrid, config, re.M) value = int(match.group(1)) if match else None return dict(priority=value) + def _parse_priority_level(self, config, vrid): + match = re.search(r'^\s+vrrp %s ' + r'priority-level (\d+)$' % vrid, config, re.M) + value = int(match.group(1)) if match else None + return dict(priority_level=value) + def _parse_timers_advertise(self, config, vrid): match = re.search(r'^\s+vrrp %s timers advertise (\d+)$' % vrid, config, re.M) value = int(match.group(1)) if match else None return dict(timers_advertise=value) + def _parse_advertisement_interval(self, config, vrid): + match = re.search(r'^\s+vrrp %s advertisement interval (\d+)$' % + vrid, config, re.M) + value = int(match.group(1)) if match else None + return dict(advertisement_interval=value) + def _parse_preempt(self, config, vrid): match = re.search(r'^\s+vrrp %s preempt$' % vrid, config, re.M) if match: @@ -285,6 +325,12 @@ def _parse_secondary_ip(self, config, vrid): value = matches if matches else [] return dict(secondary_ip=value) + def _parse_secondary_ipv4(self, config, vrid): + matches = re.findall(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+) ' + r'secondary$' % vrid, config, re.M) + value = matches if matches else [] + return dict(secondary_ipv4=value) + def _parse_description(self, config, vrid): match = re.search(r'^\s+vrrp %s description(.*)$' % vrid, config, re.M) @@ -292,6 +338,13 @@ def _parse_description(self, config, vrid): return dict(description=match.group(1).lstrip()) return dict(description='') + def _parse_session_description(self, config, vrid): + match = re.search(r'^\s+vrrp %s session description(.*)$' % + vrid, config, re.M) + if match: + return dict(description=match.group(1).lstrip()) + return dict(session_description='') + def _parse_mac_addr_adv_interval(self, config, vrid): match = re.search(r'^\s+vrrp %s mac-address advertisement-interval ' r'(\d+)$' % vrid, config, re.M) @@ -324,12 +377,30 @@ def _parse_ip_version(self, config, vrid): value = int(match.group(1)) if match else None return dict(ip_version=value) + def _parse_ipv4_version(self, config, vrid): + match = re.search(r'^\s+vrrp %s ipv4 version (\d+)$' % + vrid, config, re.M) + value = int(match.group(1)) if match else None + return dict(ipv4_version=value) + + def _parse_ipv6_version(self, config, vrid): + match = re.search(r'^\s+vrrp %s ipv6 version (\d+)$' % + vrid, config, re.M) + value = int(match.group(1)) if match else None + return dict(ipv6_version=value) + def _parse_delay_reload(self, config, vrid): match = re.search(r'^\s+vrrp %s delay reload (\d+)$' % vrid, config, re.M) value = int(match.group(1)) if match else None return dict(delay_reload=value) + def _parse_timers_delay_reload(self, config, vrid): + match = re.search(r'^\s+vrrp %s timers delay reload (\d+)$' % + vrid, config, re.M) + value = int(match.group(1)) if match else None + return dict(timers_delay_reload=value) + def _parse_track(self, config, vrid): matches = re.findall(r'^\s+vrrp %s track (\S+) ' r'(decrement|shutdown)(?:( \d+$|$))' % @@ -459,6 +530,44 @@ def set_enable(self, name, vrid, value=False, run=True): # Otherwise return the formatted command return cmd + def set_enabled(self, name, vrid, value=False, run=True): + """Set the enabled property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (boolean): True to enable the vrrp, False to disable. + run (boolean): True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if value is False: + cmd = "vrrp %d disabled" % vrid + elif value is True: + cmd = "no vrrp %d disabled" % vrid + else: + raise ValueError("vrrp property 'enabled' must be " + "True or False") + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + def set_primary_ip(self, name, vrid, value=None, disable=False, default=False, run=True): """Set the primary_ip property of the vrrp @@ -505,10 +614,98 @@ def set_primary_ip(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd + + def set_primary_ipv4(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the primary_ipv4 property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (string): IP address to be set. + disable (boolean): Unset primary ip if True. + default (boolean): Set primary ip to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if default is True: + vrrps = self.get(name) + primary_ipv4 = vrrps[vrid]['primary_ipv4'] + cmd = "default vrrp %d ipv4 %s" % (vrid, primary_ipv4) + elif disable is True or value is None: + vrrps = self.get(name) + primary_ipv4 = vrrps[vrid]['primary_ipv4'] + cmd = "no vrrp %d ipv4 %s" % (vrid, primary_ipv4) + elif re.match(r'^\d+\.\d+\.\d+\.\d+$', str(value)): + cmd = "vrrp %d ipv4 %s" % (vrid, value) + else: + raise ValueError("vrrp property 'primary_ipv4' must be " + "a properly formatted IP address") + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd def set_priority(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the primary_ip property of the vrrp + """Set the priority property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (integer): Priority to assign to the vrrp. + disable (boolean): Unset priority if True. + default (boolean): Set priority to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if not default and not disable: + if not str(value).isdigit() or value < 1 or value > 254: + raise ValueError("vrrp property 'priority' must be " + "an integer in the range 1-254") + + cmd = self.command_builder('vrrp %d priority' % vrid, value=value, + default=default, disable=disable) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + + def set_priority_level(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the priority_level property of the vrrp Args: name (string): The interface to configure. @@ -583,6 +780,42 @@ def set_description(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd + def set_session_description(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the session_description property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (string): Session_description to assign to the vrrp. + disable (boolean): Unset session_description if True. + default (boolean): Set session_description to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + cmd = self.command_builder('vrrp %d session description' % vrid, value=value, + default=default, disable=disable) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + def set_ip_version(self, name, vrid, value=None, disable=False, default=False, run=True): """Set the ip_version property of the vrrp @@ -623,6 +856,46 @@ def set_ip_version(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd + def set_ipv4_version(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the ipv4_version property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (integer): IPv4 version to assign to the vrrp. + disable (boolean): Unset ipv4_version if True. + default (boolean): Set ipv4_version to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if not default and not disable: + if value not in (2, 3): + raise ValueError("vrrp property 'ipv4_version' must be 2 or 3") + + cmd = self.command_builder('vrrp %d ipv4 version' % vrid, value=value, + default=default, disable=disable) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + def set_secondary_ips(self, name, vrid, secondary_ips, run=True): """Configure the secondary_ip property of the vrrp @@ -693,9 +966,80 @@ def set_secondary_ips(self, name, vrid, secondary_ips, run=True): # Otherwise return the formatted command return cmds + def set_secondary_ipv4s(self, name, vrid, secondary_ipv4s, run=True): + """Configure the secondary_ipv4 property of the vrrp + + Notes: + set_secondary_ipv4s takes a list of secondary ipv4 addresses + which are to be set on the virtal router. An empty list will + remove any existing secondary ipv4 addresses from the vrrp. + A list containing addresses will configure the virtual router + with only the addresses specified in the list - any existing + addresses not included in the list will be removed. + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + secondary_ips (list): A list of secondary ipv4 addresses to + be assigned to the virtual router. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + cmds = [] + + # Get the current set of tracks defined for the vrrp + curr_sec_ips = [] + vrrps = self.get(name) + if vrrps and vrid in vrrps: + curr_sec_ips = vrrps[vrid]['secondary_ipv4'] + + # Validate the list of ip addresses + for sec_ip in secondary_ipv4s: + if type(sec_ip) is not str or \ + not re.match(r'^\d+\.\d+\.\d+\.\d+$', sec_ip): + raise ValueError("vrrp property 'secondary_ipv4' " + "must be a list " + "of properly formatted ip address strings") + + intersection = list(set(curr_sec_ips) & set(secondary_ipv4s)) + + # Delete the intersection from both lists to determine which + # addresses need to be added or removed from the vrrp + remove = list(set(curr_sec_ips) - set(intersection)) + add = list(set(secondary_ipv4s) - set(intersection)) + + # Build the commands to add and remove the secondary ip addresses + for sec_ip in remove: + cmds.append("no vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + + for sec_ip in add: + cmds.append("vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + + cmds = sorted(cmds) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmds) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmds + def set_timers_advertise(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the ip_version property of the vrrp + """Set the timers_advertise property of the vrrp Args: name (string): The interface to configure. @@ -735,6 +1079,49 @@ def set_timers_advertise(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd + def set_advertisement_interval(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the advertisement_interval property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (integer): Advertisement interval value + to assign to the vrrp. + disable (boolean): Unset interval advertise if True. + default (boolean): Set interval advertise to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if not default and not disable: + if not int(value) or int(value) < 1 or int(value) > 255: + raise ValueError("vrrp property 'advertisement_interval' must be" + "in the range 1-255") + + cmd = self.command_builder('vrrp %d advertisement interval' % vrid, + value=value, default=default, + disable=disable) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + def set_mac_addr_adv_interval(self, name, vrid, value=None, disable=False, default=False, run=True): """Set the mac_addr_adv_interval property of the vrrp @@ -908,14 +1295,14 @@ def set_preempt_delay_reload(self, name, vrid, value=None, disable=False, def set_delay_reload(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the preempt_delay_min property of the vrrp + """Set the delay_reload property of the vrrp Args: name (string): The interface to configure. vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Preempt delay reload value to set on the vrrp. - disable (boolean): Unset preempt delay reload if True. - default (boolean): Set preempt delay reload to default if True. + value (integer): Delay reload value to set on the vrrp. + disable (boolean): Unset delay reload if True. + default (boolean): Set delay reload to default if True. run (boolean): Set to True to execute the command, False to return a string with the formatted command. @@ -947,6 +1334,48 @@ def set_delay_reload(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd + def set_timers_delay_reload(self, name, vrid, value=None, disable=False, + default=False, run=True): + """Set the timers_delay_reload property of the vrrp + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + value (integer): Timers delay_reload value to set on the vrrp. + disable (boolean): Unset preempt delay reload if True. + default (boolean): Set timers delay reload to default if True. + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + if not default and not disable: + if not int(value) or int(value) < 1 or int(value) > 3600: + raise ValueError("vrrp property 'timers_delay_reload' must be" + "in the range 0-3600 %r" % value) + + cmd = self.command_builder('vrrp %d timers delay reload' + % vrid, value=value, + default=default, disable=disable) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmd) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmd + def set_tracks(self, name, vrid, tracks, run=True): """Configure the track property of the vrrp @@ -1151,6 +1580,11 @@ def _vrrp_set(self, name, vrid, **kwargs): cmd = self.set_enable(name, vrid, value=enable, run=False) commands.append(cmd) + enabled = vrconf.get('enabled', '__NONE__') + if enabled != '__NONE__': + cmd = self.set_enabled(name, vrid, value=enabled, run=False) + commands.append(cmd) + primary_ip = vrconf.get('primary_ip', '__NONE__') if primary_ip != '__NONE__': if primary_ip in ('no', None): @@ -1164,6 +1598,19 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) + primary_ipv4 = vrconf.get('primary_ipv4', '__NONE__') + if primary_ipv4 != '__NONE__': + if primary_ipv4 in ('no', None): + cmd = self.set_primary_ipv4(name, vrid, value=None, + disable=True, run=False) + elif primary_ipv4 == 'default': + cmd = self.set_primary_ipv4(name, vrid, value=None, + default=True, run=False) + else: + cmd = self.set_primary_ipv4(name, vrid, value=primary_ipv4, + run=False) + commands.append(cmd) + priority = vrconf.get('priority', '__NONE__') if priority != '__NONE__': if priority in ('no', None): @@ -1173,22 +1620,63 @@ def _vrrp_set(self, name, vrid, **kwargs): cmd = self.set_priority(name, vrid, value=priority, default=True, run=False) else: - cmd = self.set_priority(name, vrid, value=priority, run=False) + cmd = self.set_priority(name, vrid, + value=priority, run=False) + commands.append(cmd) + + priority_level = vrconf.get('priority_level', '__NONE__') + if priority_level != '__NONE__': + if priority_level in ('no', None): + cmd = self.set_priority_level(name, vrid, + value=priority_level, + disable=True, run=False) + elif priority == 'default': + cmd = self.set_priority_level(name, vrid, + value=priority_level, + default=True, run=False) + else: + cmd = self.set_priority_level(name, vrid, + value=priority_level, run=False) commands.append(cmd) description = vrconf.get('description', '__NONE__') if description != '__NONE__': if description in ('no', None): - cmd = self.set_description(name, vrid, value=description, + cmd = self.set_description(name, + vrid, + value=description, disable=True, run=False) elif description == 'default': - cmd = self.set_description(name, vrid, value=description, + cmd = self.set_description(name, + vrid, + value=description, default=True, run=False) else: - cmd = self.set_description(name, vrid, value=description, + cmd = self.set_description(name, + vrid, + value=description, run=False) commands.append(cmd) + session_description = vrconf.get('session_description', '__NONE__') + if session_description != '__NONE__': + if session_description in ('no', None): + cmd = self.set_session_description(name, + vrid, + value=session_description, + disable=True, run=False) + elif session_description == 'default': + cmd = self.set_session_description(name, + vrid, + value=session_description, + default=True, run=False) + else: + cmd = self.set_session_description(name, + vrid, + value=session_description, + run=False) + commands.append(cmd) + ip_version = vrconf.get('ip_version', '__NONE__') if ip_version != '__NONE__': if ip_version in ('no', None): @@ -1202,12 +1690,31 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) + ipv4_version = vrconf.get('ipv4_version', '__NONE__') + if ipv4_version != '__NONE__': + if ipv4_version in ('no', None): + cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, + disable=True, run=False) + elif ipv4_version == 'default': + cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, + default=True, run=False) + else: + cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, + run=False) + commands.append(cmd) + secondary_ip = vrconf.get('secondary_ip', '__NONE__') if secondary_ip != '__NONE__': cmds = self.set_secondary_ips(name, vrid, secondary_ip, run=False) for cmd in cmds: commands.append(cmd) + secondary_ipv4 = vrconf.get('secondary_ipv4', '__NONE__') + if secondary_ip != '__NONE__': + cmds = self.set_secondary_ipv4s(name, vrid, secondary_ipv4, run=False) + for cmd in cmds: + commands.append(cmd) + timers_advertise = vrconf.get('timers_advertise', '__NONE__') if timers_advertise != '__NONE__': if timers_advertise in ('no', None): @@ -1224,6 +1731,22 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) + advertisement_interval = vrconf.get('advertisement_interval', '__NONE__') + if advertisement_interval != '__NONE__': + if advertisement_interval in ('no', None): + cmd = self.set_advertisement_interval( + name, vrid, value=advertisement_interval, + disable=True, run=False) + elif advertisement_interval == 'default': + cmd = self.set_advertisement_interval( + name, vrid, value=advertisement_interval, + default=True, run=False) + else: + cmd = self.set_advertisement_interval( + name, vrid, value=advertisement_interval, + run=False) + commands.append(cmd) + mac_addr_adv_interval = \ vrconf.get('mac_addr_adv_interval', '__NONE__') if mac_addr_adv_interval != '__NONE__': @@ -1301,6 +1824,22 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) + timers_delay_reload = vrconf.get('timers_delay_reload', '__NONE__') + if timers_delay_reload != '__NONE__': + if timers_delay_reload in ('no', None): + cmd = self.set_timers_delay_reload(name, vrid, + value=timers_delay_reload, + disable=True, run=False) + elif delay_reload == 'default': + cmd = self.set_timers_delay_reload(name, vrid, + value=timers_delay_reload, + default=True, run=False) + else: + cmd = self.set_timers_delay_reload(name, vrid, + value=timers_delay_reload, + run=False) + commands.append(cmd) + track = vrconf.get('track', '__NONE__') if track != '__NONE__': cmds = self.set_tracks(name, vrid, track, run=False) @@ -1343,22 +1882,41 @@ def vrconf_format(self, vrconfig): # primary_ip: default, no, None results in address of 0.0.0.0 if fixed['primary_ip'] in ('no', 'default', None): fixed['primary_ip'] = '0.0.0.0' + # primary_ipv4: default, no, None results in address of 0.0.0.0 + if fixed['primary_ipv4'] in ('no', 'default', None): + fixed['primary_ipv4'] = '0.0.0.0' # priority: default, no, None results in priority of 100 if fixed['priority'] in ('no', 'default', None): fixed['priority'] = 100 + # priority-level: default, no, None results in priority of 100 + if fixed['priority_level'] in ('no', 'default', None): + fixed['priority-level'] = 100 # description: default, no, None results in None if fixed['description'] in ('no', 'default', None): fixed['description'] = None + # session_description: default, no, None results in None + if fixed['session_description'] in ('no', 'default', None): + fixed['session_description'] = None # secondary_ip: list should be exactly what is required, # just sort it for easier comparison if 'secondary_ip' in fixed: fixed['secondary_ip'] = sorted(fixed['secondary_ip']) + # secondary_ipv4: list should be exactly what is required, + # just sort it for easier comparison + if 'secondary_ipv4' in fixed: + fixed['secondary_ipv4'] = sorted(fixed['secondary_ipv4']) # ip_version: default, no, None results in value of 2 if fixed['ip_version'] in ('no', 'default', None): fixed['ip_version'] = 2 + # ipv4_version: default, no, None results in value of 2 + if fixed['ipv4_version'] in ('no', 'default', None): + fixed['ipv4_version'] = 2 # timers_advertise: default, no, None results in value of 1 if fixed['timers_advertise'] in ('no', 'default', None): fixed['timers_advertise'] = 1 + # advertisement_interval: default, no, None results in value of 1 + if fixed['advertisement_interval'] in ('no', 'default', None): + fixed['advertisement_interval'] = 1 # mac_address_advertisement_interaval: # default, no, None results in value of 30 if fixed['mac_addr_adv_interval'] in \ @@ -1376,6 +1934,9 @@ def vrconf_format(self, vrconfig): # delay_reload: default, no, None results in value of 0 if fixed['delay_reload'] in ('no', 'default', None): fixed['delay_reload'] = 0 + # timers_delay_reload: default, no, None results in value of 0 + if fixed['timers_delay_reload'] in ('no', 'default', None): + fixed['timers_delay_reload'] = 0 # track: list should be exactly what is required, # just sort it for easier comparison if 'track' in fixed: diff --git a/test/system/test_api_vrrp.py b/test/system/test_api_vrrp.py index fd1ee10..accfde6 100644 --- a/test/system/test_api_vrrp.py +++ b/test/system/test_api_vrrp.py @@ -39,18 +39,18 @@ IP_PREFIX = '10.10.10.' VR_CONFIG = { - 'primary_ip': '10.10.10.2', - 'priority': 200, - 'description': 'modified vrrp 10 on an interface', - 'secondary_ip': ['10.10.10.11'], - 'ip_version': 3, - 'enable': False, - 'timers_advertise': 2, - 'mac_addr_adv_interval': 3, + 'primary_ipv4': '10.10.10.2', + 'priority_level': 200, + 'session_description': 'modified vrrp 10 on an interface', + 'secondary_ipv4': ['10.10.10.11'], + 'ipv4_version': 3, + 'enabled': False, + 'advertisement_interval': 2, + 'mac_addr_adv_interval': 30, 'preempt': False, 'preempt_delay_min': 1, 'preempt_delay_reload': None, - 'delay_reload': 1, + 'timers_delay_reload': 1, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, @@ -74,7 +74,7 @@ def test_get(self): for dut in self.duts: interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) response = dut.api('vrrp').get(interface) @@ -86,11 +86,11 @@ def test_getall(self): for dut in self.duts: interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit', 'interface vlan $', - 'vrrp %d shutdown' % vrid, - 'vrrp %d shutdown' % vrid2, + 'vrrp %d disabled' % vrid, + 'vrrp %d disabled' % vrid2, 'exit']) response = dut.api('vrrp').getall() @@ -124,7 +124,7 @@ def test_delete(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) response = dut.api('vrrp').delete(interface, vrid) @@ -136,7 +136,7 @@ def test_default(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) response = dut.api('vrrp').delete(interface, vrid) @@ -160,10 +160,10 @@ def test_update_with_create(self): # Update some of the information on the vrrp vrrp_update = { - 'primary_ip': '10.10.10.12', - 'priority': 200, - 'description': 'updated vrrp 10 on an interface', - 'secondary_ip': ['10.10.10.13', '10.10.10.23'], + 'primary_ipv4': '10.10.10.12', + 'priority_level': 200, + 'session_description': 'updated vrrp 10 on an interface', + 'secondary_ipv4': ['10.10.10.13', '10.10.10.23'], 'ip_version': 2, 'enable': True, 'timers_advertise': None, @@ -171,7 +171,7 @@ def test_update_with_create(self): 'preempt': True, 'preempt_delay_min': 'default', 'preempt_delay_reload': 'default', - 'delay_reload': 'default', + 'timers_delay_reload': 'default', 'track': [ {'name': 'Ethernet2', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, @@ -200,7 +200,7 @@ def test_set_enable(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'vrrp %d ip 10.10.10.2' % vrid, 'exit']) @@ -222,11 +222,11 @@ def test_set_primary_ip(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for p_ip in primary_ip_cases: - response = dut.api('vrrp').set_primary_ip( + response = dut.api('vrrp').set_primary_ipv4( interface, vrid, **p_ip) self.assertIs(response, True) @@ -243,11 +243,11 @@ def test_set_priority(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for priority in priority_cases: - response = dut.api('vrrp').set_priority( + response = dut.api('vrrp').set_priority_level( interface, vrid, **priority) self.assertIs(response, True) @@ -264,11 +264,11 @@ def test_set_description(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for description in desc_cases: - response = dut.api('vrrp').set_description( + response = dut.api('vrrp').set_session_description( interface, vrid, **description) self.assertIs(response, True) @@ -283,7 +283,7 @@ def test_set_secondary_ips(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for s_ip_list in secondary_ip_cases: @@ -305,7 +305,7 @@ def test_set_ip_version(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for ip_version in ip_version_cases: @@ -326,7 +326,7 @@ def test_set_timers_advertise(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for timers_advertise in timers_adv_cases: @@ -347,7 +347,7 @@ def test_set_mac_addr_adv_interval(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for mac_addr_adv_intvl in mac_addr_adv_int_cases: @@ -369,7 +369,7 @@ def test_set_preempt(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for preempt in preempt_cases: @@ -390,7 +390,7 @@ def test_set_preempt_delay_min(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for preempt_delay_min in preempt_delay_min_cases: @@ -411,7 +411,7 @@ def test_set_preempt_delay_reload(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for preempt_delay_reload in preempt_delay_reload_cases: @@ -419,9 +419,9 @@ def test_set_preempt_delay_reload(self): interface, vrid, **preempt_delay_reload) self.assertIs(response, True) - def test_set_delay_reload(self): + def test_set_timers_delay_reload(self): vrid = 104 - delay_reload_cases = [ + timers_delay_reload_cases = [ {'value': 30}, {'default': True}, {'value': 25}, @@ -432,12 +432,12 @@ def test_set_delay_reload(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) - for delay_reload in delay_reload_cases: - response = dut.api('vrrp').set_delay_reload( - interface, vrid, **delay_reload) + for timers_delay_reload in timers_delay_reload_cases: + response = dut.api('vrrp').set_timers_delay_reload( + interface, vrid, **timers_delay_reload) self.assertIs(response, True) def test_set_tracks(self): @@ -465,7 +465,7 @@ def test_set_tracks(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for track_list in track_cases: @@ -486,7 +486,7 @@ def test_set_bfd_ip(self): interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, - 'vrrp %d shutdown' % vrid, + 'vrrp %d disabled' % vrid, 'exit']) for bfd_ip in bfd_ip_cases: From b906e450c196a15c5fea845e6141fd8c3bbcc32d Mon Sep 17 00:00:00 2001 From: root Date: Tue, 10 Dec 2019 16:52:31 +0000 Subject: [PATCH 15/21] Add 'peer-address heartbeat' (4.20.0F), vrrp coniguration CLI change (4.21.3F) --- Makefile | 2 +- dev-requirements.txt | 3 +- pyeapi/api/acl.py | 22 +- pyeapi/api/mlag.py | 34 +- pyeapi/api/vrrp.py | 350 ++++++++++++++------ test/fixtures/dut.conf | 6 +- test/fixtures/eapi.conf | 6 +- test/fixtures/running_config.text | 6 +- test/fixtures/running_config.vrrp | 68 +++- test/system/test_api_mlag.py | 9 + test/system/test_api_vrrp.py | 129 +++++--- test/system/test_client.py | 4 +- test/unit/test_api_vrrp.py | 514 +++++++++++++++++++++++++----- test/unit/test_client.py | 32 +- 14 files changed, 913 insertions(+), 272 deletions(-) diff --git a/Makefile b/Makefile index 7cbd456..76150fa 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ VERSION := $(shell cat VERSION) all: clean check pep8 flake8 tests pep8: - -pep8 -r --ignore=E402,E731,E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 pyeapi/ test/ + pycodestyle -r --ignore=E402,E731,E501,E221,W291,W391,E302,E251,E203,W293,E231,E303,E201,E225,E261,E241 pyeapi/ test/ pyflakes: pyflakes pyeapi/ test/ diff --git a/dev-requirements.txt b/dev-requirements.txt index 3accc1f..903885c 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -3,7 +3,7 @@ mock coveralls twine check-manifest -pep8 +pycodestyle pyflakes coverage sphinx @@ -11,4 +11,3 @@ sphinxcontrib-napoleon flake8 flake8-print flake8-debugger -pep8-naming diff --git a/pyeapi/api/acl.py b/pyeapi/api/acl.py index bff0fdc..4b45139 100644 --- a/pyeapi/api/acl.py +++ b/pyeapi/api/acl.py @@ -244,17 +244,17 @@ def _parse_entries(self, config): for item in re.finditer(r'\d+ [p|d].*$', config, re.M): match = self.entry_re.match(item.group(0)) if match: - entry = dict() - entry['action'] = match.group(2) - entry['protocol'] = match.group(3) - entry['srcaddr'] = match.group(5) or 'any' - entry['srclen'] = match.group(6) - entry['srcport'] = match.group(7) - entry['dstaddr'] = match.group(9) or 'any' - entry['dstlen'] = match.group(10) - entry['dstport'] = match.group(12) - entry['other'] = match.group(13) - entries[match.group(1)] = entry + entry = dict() + entry['action'] = match.group(2) + entry['protocol'] = match.group(3) + entry['srcaddr'] = match.group(5) or 'any' + entry['srclen'] = match.group(6) + entry['srcport'] = match.group(7) + entry['dstaddr'] = match.group(9) or 'any' + entry['dstlen'] = match.group(10) + entry['dstport'] = match.group(12) + entry['other'] = match.group(13) + entries[match.group(1)] = entry return dict(entries=entries) def create(self, name): diff --git a/pyeapi/api/mlag.py b/pyeapi/api/mlag.py index 6c523d8..9c4e48c 100644 --- a/pyeapi/api/mlag.py +++ b/pyeapi/api/mlag.py @@ -144,10 +144,25 @@ def _parse_peer_address(self, config): dict: A dict object that is intended to be merged into the resource dict """ - match = re.search(r'peer-address ([^\s]+)', config) + match = re.search(r'peer-address (\d+\.\d+\.\d+\.\d+)$', config) value = match.group(1) if match else None return dict(peer_address=value) + def _parse_peer_address_heartbeat(self, config): + """Scans the config block and parses the peer-address heartbeat value + + Args: + config (str): The config block to scan + + Returns: + dict: A dict object that is intended to be merged into the + resource dict + """ + match = re.search(r'peer-address heartbeat ' + r'(\d+\.\d+\.\d+\.\d+)$', config) + value = match.group(1) if match else None + return dict(peer_address_heartbeat=value) + def _parse_peer_link(self, config): """Scans the config block and parses the peer-link value @@ -238,6 +253,23 @@ def set_peer_address(self, value=None, default=False, disable=False): """ return self._configure_mlag('peer-address', value, default, disable) + def set_peer_address_heartbeat(self, + value=None, default=False, disable=False): + """Configures the mlag peer-address heartbeat value + + Args: + value (str): The value to configure the peer-address + default (bool): Configures the peer-address heartbeat using the + default keyword + disable (bool): Negates the peer-address heartbeat using the + no keyword + + Returns: + bool: Returns True if the commands complete successfully + """ + return self._configure_mlag('peer-address heartbeat', + value, default, disable) + def set_peer_link(self, value=None, default=False, disable=False): """Configures the mlag peer-link value diff --git a/pyeapi/api/vrrp.py b/pyeapi/api/vrrp.py index cd3b87d..26cc2ae 100644 --- a/pyeapi/api/vrrp.py +++ b/pyeapi/api/vrrp.py @@ -157,19 +157,19 @@ from pyeapi.api import EntityCollection -PROPERTIES = ['primary_ip', 'primary_ipv4', +PROPERTIES = ['primary_ip', 'primary_ipv4', 'priority', 'priority_level', 'description', 'session_description', 'secondary_ip', 'secondary_ipv4', 'ip_version', 'ipv4_version', - 'enable', 'enabled', - 'timers_advertise', 'advertisement interval', + 'enable', + 'timers_advertise', 'advertisement_interval', 'mac_addr_adv_interval', 'preempt', 'preempt_delay_min', 'preempt_delay_reload', 'delay_reload', 'timers_delay_reload', - 'track', + 'track', 'tracked_object', 'bfd_ip'] @@ -218,18 +218,26 @@ def get(self, name): # Parse the vrrp configuration for the vrid(s) in the list subd.update(self._parse_delay_reload(config, vrid)) + subd.update(self._parse_timers_delay_reload(config, vrid)) + subd.update(self._parse_advertisement_interval(config, vrid)) subd.update(self._parse_description(config, vrid)) + subd.update(self._parse_session_description(config, vrid)) subd.update(self._parse_enable(config, vrid)) subd.update(self._parse_ip_version(config, vrid)) + subd.update(self._parse_ipv4_version(config, vrid)) subd.update(self._parse_mac_addr_adv_interval(config, vrid)) subd.update(self._parse_preempt(config, vrid)) subd.update(self._parse_preempt_delay_min(config, vrid)) subd.update(self._parse_preempt_delay_reload(config, vrid)) subd.update(self._parse_primary_ip(config, vrid)) + subd.update(self._parse_primary_ipv4(config, vrid)) subd.update(self._parse_priority(config, vrid)) + subd.update(self._parse_priority_level(config, vrid)) subd.update(self._parse_secondary_ip(config, vrid)) + subd.update(self._parse_secondary_ipv4(config, vrid)) subd.update(self._parse_timers_advertise(config, vrid)) subd.update(self._parse_track(config, vrid)) + subd.update(self._parse_tracked_object(config, vrid)) subd.update(self._parse_bfd_ip(config, vrid)) result.update({int(vrid): subd}) @@ -260,17 +268,11 @@ def getall(self): return vrrps def _parse_enable(self, config, vrid): - match = re.search(r'^\s+vrrp %s shutdown$' % vrid, config, re.M) + match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) if match: return dict(enable=False) return dict(enable=True) - def _parse_enabled(self, config, vrid): - match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) - if match: - return dict(enabled=False) - return dict(enabled=True) - def _parse_primary_ip(self, config, vrid): match = re.search(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+)$' % vrid, config, re.M) @@ -342,7 +344,7 @@ def _parse_session_description(self, config, vrid): match = re.search(r'^\s+vrrp %s session description(.*)$' % vrid, config, re.M) if match: - return dict(description=match.group(1).lstrip()) + return dict(session_description=match.group(1).lstrip()) return dict(session_description='') def _parse_mac_addr_adv_interval(self, config, vrid): @@ -383,12 +385,6 @@ def _parse_ipv4_version(self, config, vrid): value = int(match.group(1)) if match else None return dict(ipv4_version=value) - def _parse_ipv6_version(self, config, vrid): - match = re.search(r'^\s+vrrp %s ipv6 version (\d+)$' % - vrid, config, re.M) - value = int(match.group(1)) if match else None - return dict(ipv6_version=value) - def _parse_delay_reload(self, config, vrid): match = re.search(r'^\s+vrrp %s delay reload (\d+)$' % vrid, config, re.M) @@ -422,6 +418,27 @@ def _parse_track(self, config, vrid): track_list = sorted(value, key=lambda k: (k['name'], k['action'])) return dict(track=track_list) + def _parse_tracked_object(self, config, vrid): + matches = re.findall(r'^\s+vrrp %s tracked-object (\S+) ' + r'(decrement|shutdown)(?:( \d+$|$))' % + vrid, config, re.M) + value = [] + for match in matches: + tr_obj = match[0] + action = match[1] + amount = None if match[2] == '' else int(match[2]) + entry = { + 'name': tr_obj, + 'action': action, + } + if amount: + entry.update({'amount': amount}) + value.append(entry) + + # Return the list, sorted for easier comparison + track_list = sorted(value, key=lambda k: (k['name'], k['action'])) + return dict(tracked_object=track_list) + def create(self, interface, vrid, **kwargs): """Creates a vrrp instance from an interface @@ -511,50 +528,12 @@ def set_enable(self, name, vrid, value=False, run=True): """ - if value is False: - cmd = "vrrp %d shutdown" % vrid - elif value is True: - cmd = "no vrrp %d shutdown" % vrid - else: - raise ValueError("vrrp property 'enable' must be " - "True or False") - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_enabled(self, name, vrid, value=False, run=True): - """Set the enabled property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (boolean): True to enable the vrrp, False to disable. - run (boolean): True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure - - If run is False, returns the formatted command string which can - be passed to the node - - """ - if value is False: cmd = "vrrp %d disabled" % vrid elif value is True: cmd = "no vrrp %d disabled" % vrid else: - raise ValueError("vrrp property 'enabled' must be " + raise ValueError("vrrp property 'enable' must be " "True or False") # Run the command if requested @@ -614,8 +593,9 @@ def set_primary_ip(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd - - def set_primary_ipv4(self, name, vrid, value=None, disable=False, + + def set_primary_ipv4(self, name, vrid, + value=None, disable=False, default=False, run=True): """Set the primary_ipv4 property of the vrrp @@ -727,10 +707,11 @@ def set_priority_level(self, name, vrid, value=None, disable=False, if not default and not disable: if not str(value).isdigit() or value < 1 or value > 254: - raise ValueError("vrrp property 'priority' must be " + raise ValueError("vrrp property 'priority_level' must be " "an integer in the range 1-254") - cmd = self.command_builder('vrrp %d priority' % vrid, value=value, + cmd = self.command_builder('vrrp %d priority-level' % vrid, + value=value, default=default, disable=disable) # Run the command if requested @@ -802,7 +783,8 @@ def set_session_description(self, name, vrid, value=None, disable=False, """ - cmd = self.command_builder('vrrp %d session description' % vrid, value=value, + cmd = self.command_builder('vrrp %d session description' % vrid, + value=value, default=default, disable=disable) # Run the command if requested @@ -926,7 +908,7 @@ def set_secondary_ips(self, name, vrid, secondary_ips, run=True): cmds = [] - # Get the current set of tracks defined for the vrrp + # Get the current set of secondary ips defined for the vrrp curr_sec_ips = [] vrrps = self.get(name) if vrrps and vrid in vrrps: @@ -996,7 +978,7 @@ def set_secondary_ipv4s(self, name, vrid, secondary_ipv4s, run=True): cmds = [] - # Get the current set of tracks defined for the vrrp + # Get the current set of secondary ipv4s defined for the vrrp curr_sec_ips = [] vrrps = self.get(name) if vrrps and vrid in vrrps: @@ -1061,7 +1043,7 @@ def set_timers_advertise(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 255: - raise ValueError("vrrp property 'timers_advertise' must be" + raise ValueError("vrrp property 'timers_advertise' must be " "in the range 1-255") cmd = self.command_builder('vrrp %d timers advertise' % vrid, @@ -1086,7 +1068,7 @@ def set_advertisement_interval(self, name, vrid, value=None, disable=False, Args: name (string): The interface to configure. vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Advertisement interval value + value (integer): Advertisement interval value to assign to the vrrp. disable (boolean): Unset interval advertise if True. default (boolean): Set interval advertise to default if True. @@ -1104,7 +1086,8 @@ def set_advertisement_interval(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 255: - raise ValueError("vrrp property 'advertisement_interval' must be" + raise ValueError("vrrp property " + "'advertisement_interval' must be " "in the range 1-255") cmd = self.command_builder('vrrp %d advertisement interval' % vrid, @@ -1233,7 +1216,7 @@ def set_preempt_delay_min(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'preempt_delay_min' must be" + raise ValueError("vrrp property 'preempt_delay_min' must be " "in the range 0-3600 %r" % value) cmd = self.command_builder('vrrp %d preempt delay minimum' @@ -1275,8 +1258,8 @@ def set_preempt_delay_reload(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'preempt_delay_reload' must be" - "in the range 0-3600 %r" % value) + raise ValueError("vrrp property 'preempt_delay_reload' " + "must be in the range 0-3600 %r" % value) cmd = self.command_builder('vrrp %d preempt delay reload' % vrid, value=value, default=default, @@ -1317,7 +1300,7 @@ def set_delay_reload(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'delay_reload' must be" + raise ValueError("vrrp property 'delay_reload' must be " "in the range 0-3600 %r" % value) cmd = self.command_builder('vrrp %d delay reload' % vrid, value=value, @@ -1358,10 +1341,10 @@ def set_timers_delay_reload(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'timers_delay_reload' must be" + raise ValueError("vrrp property 'timers_delay_reload' must be " "in the range 0-3600 %r" % value) - cmd = self.command_builder('vrrp %d timers delay reload' + cmd = self.command_builder('vrrp %d timers delay reload' % vrid, value=value, default=default, disable=disable) @@ -1526,6 +1509,160 @@ def set_tracks(self, name, vrid, tracks, run=True): # Otherwise return the formatted command return cmds + def set_tracked_objects(self, name, vrid, tracked_objects, run=True): + """Configure the tracked_object property of the vrrp + + Notes: + set_tracked_objects takes a list of tracked objects which are + to be set on the virtual router. An empty list will remove + any existing tracked objects from the vrrp. A list containing + tracked_object entries configures the virtual router to track + only the + objects specified in the list - any existing tracked objects + on the vrrp not included in the list will be removed. + + Args: + name (string): The interface to configure. + vrid (integer): The vrid number for the vrrp to be managed. + tracked_objects (list): A list of track definition dictionaries. + Each dictionary is a definition of a tracked object in one + of the two formats:: + + {'name': tracked_object_name, + 'action': 'shutdown'} + {'name': tracked_object_name, + 'action': 'decrement', + 'amount': amount_of_decrement} + + run (boolean): Set to True to execute the command, False to + return a string with the formatted command. + + Returns: + If run is True, returns True if the command executed successfully, + error if failure. + + If run is False, returns the formatted command string which can + be passed to the node + + """ + + cmds = [] + + # Get the current set of tracked_objects defined for the vrrp + curr_tracks = [] + vrrps = self.get(name) + if vrrps and vrid in vrrps: + curr_tracks = vrrps[vrid]['tracked_object'] + + # Determine which tracked objects are in both lists using + # sets of temporary strings built from the track specifications + unset = '_none_' + tracks_set = [] + for track in tracked_objects: + keys = track.keys() + + # Validate no extraneous keys in track definition + err_keys = set(keys).difference(('name', 'action', 'amount')) + if err_keys: + err_keys = ', '.join(err_keys) + raise ValueError("Error found in vrrp property " + "'tracked_object': " + "unknown key(s) '%s' found. Valid keys are " + "name, action, and amount" % err_keys) + + # Validate required keys in track definition + if not set(keys).issuperset(('name', 'action')): + raise ValueError("Error found in vrrp property " + "'tracked_object': " + "track definition must contain 'name' and " + "'action' keys") + + tr_obj = track['name'] + action = track['action'] + amount = track['amount'] if 'amount' in track else unset + + # Validate values in track definition + error = False + if action not in ('shutdown', 'decrement'): + error = True + if action == 'shutdown' and amount != unset: + error = True + if amount != unset and not str(amount).isdigit(): + error = True + if error: + raise ValueError("Error found in vrrp property 'track'. " + "See documentation for format specification.") + + tid = "%s %s %s" % (tr_obj, action, amount) + tracks_set.append(tid) + + curr_set = [] + for track in curr_tracks: + tr_obj = track['name'] + action = track['action'] + amount = track['amount'] if 'amount' in track else unset + + # Validate track definition + error = False + if action not in ('shutdown', 'decrement'): + error = True + if action == 'shutdown' and amount != unset: + error = True + if amount != unset and not str(amount).isdigit(): + error = True + if error: + raise ValueError("Error found in vrrp property " + "'tracked_object'. " + "See documentation for format specification.") + + tid = "%s %s %s" % (tr_obj, action, amount) + curr_set.append(tid) + + intersection = list(set(tracks_set) & set(curr_set)) + + # Delete the intersection from both lists to determine which + # track definitions need to be added or removed from the vrrp + remove = list(set(curr_set) - set(intersection)) + add = list(set(tracks_set) - set(intersection)) + + # Build the commands to add and remove the tracked objects + for track in remove: + match = re.match(r'(\S+)\s+(\S+)\s+(\S+)', track) + if match: + (tr_obj, action, amount) = \ + (match.group(1), match.group(2), match.group(3)) + + if amount == unset: + amount = '' + t_cmd = ("no vrrp %d tracked-object %s %s %s" + % (vrid, tr_obj, action, amount)) + cmds.append(t_cmd.rstrip()) + + for track in add: + match = re.match(r'(\S+)\s+(\S+)\s+(\S+)', track) + if match: + (tr_obj, action, amount) = \ + (match.group(1), match.group(2), match.group(3)) + + if amount == unset: + amount = '' + t_cmd = ("vrrp %d tracked-object %s %s %s" + % (vrid, tr_obj, action, amount)) + cmds.append(t_cmd.rstrip()) + + cmds = sorted(cmds) + + # Run the command if requested + if run: + result = self.configure_interface(name, cmds) + # And verify the command succeeded + if result is False: + return self.error + return result + + # Otherwise return the formatted command + return cmds + def set_bfd_ip(self, name, vrid, value=None, disable=False, default=False, run=True): """Set the bfd_ip property of the vrrp @@ -1580,11 +1717,6 @@ def _vrrp_set(self, name, vrid, **kwargs): cmd = self.set_enable(name, vrid, value=enable, run=False) commands.append(cmd) - enabled = vrconf.get('enabled', '__NONE__') - if enabled != '__NONE__': - cmd = self.set_enabled(name, vrid, value=enabled, run=False) - commands.append(cmd) - primary_ip = vrconf.get('primary_ip', '__NONE__') if primary_ip != '__NONE__': if primary_ip in ('no', None): @@ -1620,40 +1752,40 @@ def _vrrp_set(self, name, vrid, **kwargs): cmd = self.set_priority(name, vrid, value=priority, default=True, run=False) else: - cmd = self.set_priority(name, vrid, + cmd = self.set_priority(name, vrid, value=priority, run=False) commands.append(cmd) priority_level = vrconf.get('priority_level', '__NONE__') if priority_level != '__NONE__': if priority_level in ('no', None): - cmd = self.set_priority_level(name, vrid, + cmd = self.set_priority_level(name, vrid, value=priority_level, disable=True, run=False) - elif priority == 'default': - cmd = self.set_priority_level(name, vrid, + elif priority_level == 'default': + cmd = self.set_priority_level(name, vrid, value=priority_level, default=True, run=False) else: - cmd = self.set_priority_level(name, vrid, + cmd = self.set_priority_level(name, vrid, value=priority_level, run=False) commands.append(cmd) description = vrconf.get('description', '__NONE__') if description != '__NONE__': if description in ('no', None): - cmd = self.set_description(name, - vrid, + cmd = self.set_description(name, + vrid, value=description, disable=True, run=False) elif description == 'default': - cmd = self.set_description(name, - vrid, + cmd = self.set_description(name, + vrid, value=description, default=True, run=False) else: - cmd = self.set_description(name, - vrid, + cmd = self.set_description(name, + vrid, value=description, run=False) commands.append(cmd) @@ -1661,18 +1793,18 @@ def _vrrp_set(self, name, vrid, **kwargs): session_description = vrconf.get('session_description', '__NONE__') if session_description != '__NONE__': if session_description in ('no', None): - cmd = self.set_session_description(name, - vrid, + cmd = self.set_session_description(name, + vrid, value=session_description, disable=True, run=False) elif session_description == 'default': - cmd = self.set_session_description(name, - vrid, + cmd = self.set_session_description(name, + vrid, value=session_description, default=True, run=False) else: - cmd = self.set_session_description(name, - vrid, + cmd = self.set_session_description(name, + vrid, value=session_description, run=False) commands.append(cmd) @@ -1710,8 +1842,9 @@ def _vrrp_set(self, name, vrid, **kwargs): commands.append(cmd) secondary_ipv4 = vrconf.get('secondary_ipv4', '__NONE__') - if secondary_ip != '__NONE__': - cmds = self.set_secondary_ipv4s(name, vrid, secondary_ipv4, run=False) + if secondary_ipv4 != '__NONE__': + cmds = self.set_secondary_ipv4s(name, vrid, + secondary_ipv4, run=False) for cmd in cmds: commands.append(cmd) @@ -1731,7 +1864,8 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) - advertisement_interval = vrconf.get('advertisement_interval', '__NONE__') + advertisement_interval = vrconf.get('advertisement_interval', + '__NONE__') if advertisement_interval != '__NONE__': if advertisement_interval in ('no', None): cmd = self.set_advertisement_interval( @@ -1827,15 +1961,15 @@ def _vrrp_set(self, name, vrid, **kwargs): timers_delay_reload = vrconf.get('timers_delay_reload', '__NONE__') if timers_delay_reload != '__NONE__': if timers_delay_reload in ('no', None): - cmd = self.set_timers_delay_reload(name, vrid, + cmd = self.set_timers_delay_reload(name, vrid, value=timers_delay_reload, disable=True, run=False) - elif delay_reload == 'default': - cmd = self.set_timers_delay_reload(name, vrid, + elif timers_delay_reload == 'default': + cmd = self.set_timers_delay_reload(name, vrid, value=timers_delay_reload, default=True, run=False) else: - cmd = self.set_timers_delay_reload(name, vrid, + cmd = self.set_timers_delay_reload(name, vrid, value=timers_delay_reload, run=False) commands.append(cmd) @@ -1845,6 +1979,12 @@ def _vrrp_set(self, name, vrid, **kwargs): cmds = self.set_tracks(name, vrid, track, run=False) for cmd in cmds: commands.append(cmd) + tracked_object = vrconf.get('tracked_object', '__NONE__') + if tracked_object != '__NONE__': + cmds = self.set_tracked_objects(name, vrid, + tracked_object, run=False) + for cmd in cmds: + commands.append(cmd) bfd_ip = vrconf.get('bfd_ip', '__NONE__') if bfd_ip != '__NONE__': @@ -1890,7 +2030,7 @@ def vrconf_format(self, vrconfig): fixed['priority'] = 100 # priority-level: default, no, None results in priority of 100 if fixed['priority_level'] in ('no', 'default', None): - fixed['priority-level'] = 100 + fixed['priority_level'] = 100 # description: default, no, None results in None if fixed['description'] in ('no', 'default', None): fixed['description'] = None @@ -1942,6 +2082,10 @@ def vrconf_format(self, vrconfig): if 'track' in fixed: fixed['track'] = \ sorted(fixed['track'], key=lambda k: (k['name'], k['action'])) + if 'tracked_object' in fixed: + fixed['tracked_object'] = \ + sorted(fixed['tracked_object'], + key=lambda k: (k['name'], k['action'])) # bfd_ip: default, no, None results in '' if fixed['bfd_ip'] in ('no', 'default', None): fixed['bfd_ip'] = '' diff --git a/test/fixtures/dut.conf b/test/fixtures/dut.conf index 036a7d0..6cf2160 100644 --- a/test/fixtures/dut.conf +++ b/test/fixtures/dut.conf @@ -1,5 +1,5 @@ [connection:veos01] -host: 192.168.1.16 -username: eapi -password: password +host: 192.168.0.10 +username: arista +password: arista transport: http diff --git a/test/fixtures/eapi.conf b/test/fixtures/eapi.conf index 0454f24..b1096f3 100644 --- a/test/fixtures/eapi.conf +++ b/test/fixtures/eapi.conf @@ -1,7 +1,7 @@ [connection:test1] -host: 192.168.1.16 -username: eapi -password: password +host: 192.168.0.10 +username: arista +password: arista enablepwd: enablepwd tags: tag1, tag2 diff --git a/test/fixtures/running_config.text b/test/fixtures/running_config.text index 9b0a503..1f609f4 100644 --- a/test/fixtures/running_config.text +++ b/test/fixtures/running_config.text @@ -315,8 +315,8 @@ spanning-tree transmit hold-count 6 spanning-tree max-hops 20 no spanning-tree portfast bpduguard default no spanning-tree portfast bpdufilter default -spanning-tree bridge assurance -no spanning-tree loopguard default +spanning-tree transmit active +no spanning-tree guard loop default no spanning-tree portchannel guard misconfig spanning-tree bpduguard rate-limit default logging event spanning-tree global @@ -348,7 +348,7 @@ no aaa accounting system default no aaa accounting dot1x default no aaa accounting commands all default ! -no enable secret +no enable password no aaa root aaa authentication policy local allow-nopassword-remote-login no aaa authorization policy local default-role diff --git a/test/fixtures/running_config.vrrp b/test/fixtures/running_config.vrrp index d847eff..ff3e6e6 100644 --- a/test/fixtures/running_config.vrrp +++ b/test/fixtures/running_config.vrrp @@ -245,22 +245,29 @@ interface Port-Channel10 no switchport tap default group no switchport tool group no switchport tool dot1q remove outer + vrrp 10 priority-level 150 vrrp 10 priority 150 vrrp 10 timers advertise 1 + vrrp 10 advertisement interval 1 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 + vrrp 10 timers delay reload 0 vrrp 10 delay reload 0 no vrrp 10 authentication - vrrp 10 ip 10.10.5.10 - vrrp 10 ip 10.10.5.20 secondary + vrrp 10 ipv4 10.10.5.10 + vrrp 10 ipv4 10.10.5.20 secondary + vrrp 10 ip 10.10.5.11 + vrrp 10 ip 10.10.5.21 secondary vrrp 10 ipv6 :: vrrp 10 description vrrp 10 on Port-Channel10 - no vrrp 10 shutdown + vrrp 10 session description vrrp 10 on Port-Channel10 + no vrrp 10 disabled no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 + vrrp 10 ipv4 version 2 ! interface Ethernet1 no description @@ -396,21 +403,27 @@ interface Ethernet1 no switchport tap default group no switchport tool group no switchport tool dot1q remove outer - vrrp 10 priority 175 + vrrp 10 priority 100 + vrrp 10 priority-level 175 vrrp 10 timers advertise 1 + vrrp 10 advertisement interval 1 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 + vrrp 10 timers delay reload 0 vrrp 10 delay reload 0 no vrrp 10 authentication - vrrp 10 ip 10.10.6.10 + vrrp 10 ip 10.10.6.11 + vrrp 10 ipv4 10.10.6.10 vrrp 10 ipv6 :: + vrrp 10 session description vrrp 10 on Ethernet1 vrrp 10 description vrrp 10 on Ethernet1 - no vrrp 10 shutdown + no vrrp 10 disable no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 + vrrp 10 ipv4 version 2 ! interface Vlan50 no description @@ -472,62 +485,93 @@ interface Vlan50 no ip pim bsr-border no ip virtual address vrrp 10 priority 200 - vrrp 10 timers advertise 3 + vrrp 10 priority-level 200 + vrrp 10 advertisement interval 3 + vrrp 10 timers advertise 1 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 vrrp 10 delay reload 0 + vrrp 10 timers delay reload 0 no vrrp 10 authentication vrrp 10 ip 10.10.4.10 vrrp 10 ip 10.10.4.21 secondary vrrp 10 ip 10.10.4.22 secondary vrrp 10 ip 10.10.4.23 secondary vrrp 10 ip 10.10.4.24 secondary + vrrp 10 ipv4 10.10.4.11 + vrrp 10 ipv4 10.10.4.21 secondary + vrrp 10 ipv4 10.10.4.22 secondary + vrrp 10 ipv4 10.10.4.23 secondary + vrrp 10 ipv4 10.10.4.24 secondary vrrp 10 ipv6 :: + no vrrp 10 session description no vrrp 10 description - no vrrp 10 shutdown + no vrrp 10 disabled vrrp 10 track Ethernet1 decrement 10 vrrp 10 track Ethernet1 shutdown vrrp 10 track Ethernet2 decrement 50 vrrp 10 track Ethernet2 shutdown vrrp 10 track Ethernet11 decrement 75 vrrp 10 track Ethernet11 shutdown + vrrp 10 tracked-object Ethernet1 decrement 10 + vrrp 10 tracked-object Ethernet1 shutdown + vrrp 10 tracked-object Ethernet2 decrement 50 + vrrp 10 tracked-object Ethernet2 shutdown + vrrp 10 tracked-object Ethernet11 decrement 75 + vrrp 10 tracked-object Ethernet11 shutdown no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 + vrrp 10 ipv4 version 2 vrrp 20 priority 100 - vrrp 20 timers advertise 5 + vrrp 20 priority-level 100 + vrrp 20 advertisement interval 5 + vrrp 20 timers advertise 1 vrrp 20 mac-address advertisement-interval 30 no vrrp 20 preempt vrrp 20 preempt delay minimum 0 vrrp 20 preempt delay reload 0 vrrp 20 delay reload 0 + vrrp 20 timers delay reload 0 vrrp 20 authentication text 12345 vrrp 20 ip 10.10.4.20 + vrrp 20 ipv4 10.10.4.20 vrrp 20 ipv6 :: + no vrrp 20 session description no vrrp 20 description - vrrp 20 shutdown + vrrp 20 disabled vrrp 20 track Ethernet1 shutdown vrrp 20 track Ethernet2 decrement 1 vrrp 20 track Ethernet2 shutdown + vrrp 20 tracked-object Ethernet1 shutdown + vrrp 20 tracked-object Ethernet2 decrement 1 + vrrp 20 tracked-object Ethernet2 shutdown no vrrp 20 bfd ip no vrrp 20 bfd ipv6 vrrp 20 ip version 2 - vrrp 30 priority 50 + vrrp 20 ipv4 version 2 + vrrp 30 priority 100 + vrrp 30 priority-level 50 + vrrp 30 advertisement interval 1 vrrp 30 timers advertise 1 vrrp 30 mac-address advertisement-interval 30 vrrp 30 preempt vrrp 30 preempt delay minimum 0 vrrp 30 preempt delay reload 0 vrrp 30 delay reload 0 + vrrp 30 timers delay reload 0 vrrp 30 authentication ietf-md5 key-string 7 bu1yTgzm0RDgraNS0MNkaA== vrrp 30 ip 10.10.4.30 + vrrp 30 ipv4 10.10.4.30 vrrp 30 ipv6 :: + no vrrp 30 session description no vrrp 30 description - no vrrp 30 shutdown + no vrrp 30 disable vrrp 30 bfd ip 10.10.4.33 no vrrp 30 bfd ipv6 vrrp 30 ip version 2 + vrrp 30 ipv4 version 2 ! ! diff --git a/test/system/test_api_mlag.py b/test/system/test_api_mlag.py index 7c395c7..0ecd765 100644 --- a/test/system/test_api_mlag.py +++ b/test/system/test_api_mlag.py @@ -114,6 +114,15 @@ def test_set_peer_address_with_value(self): self.assertTrue(result) self.assertIn('peer-address 1.2.3.4', api.get_block('mlag configuration')) + def test_set_peer_address_heartbeat_with_value(self): + for dut in self.duts: + dut.config('default mlag configuration') + api = dut.api('mlag') + self.assertIn('no peer-address heartbeat', api.get_block('mlag configuration')) + result = dut.api('mlag').set_peer_address_heartbeat('1.2.3.4') + self.assertTrue(result) + self.assertIn('peer-address heartbeat 1.2.3.4', api.get_block('mlag configuration')) + def test_set_peer_address_with_no_value(self): for dut in self.duts: dut.config(['interface Vlan1234', 'ip address 1.2.3.1/24', diff --git a/test/system/test_api_vrrp.py b/test/system/test_api_vrrp.py index accfde6..2b43004 100644 --- a/test/system/test_api_vrrp.py +++ b/test/system/test_api_vrrp.py @@ -39,27 +39,38 @@ IP_PREFIX = '10.10.10.' VR_CONFIG = { + 'primary_ip': '10.10.10.2', + 'secondary_ip': [], + 'priority': 100, + 'description': '', + 'ip_version': 2, + 'timers_advertise': 1, + 'delay_reload': 1, + 'enable': False, + 'mac_addr_adv_interval': 30, + 'preempt': False, + 'preempt_delay_min': 1, + 'preempt_delay_reload': None, 'primary_ipv4': '10.10.10.2', 'priority_level': 200, 'session_description': 'modified vrrp 10 on an interface', 'secondary_ipv4': ['10.10.10.11'], 'ipv4_version': 3, - 'enabled': False, 'advertisement_interval': 2, - 'mac_addr_adv_interval': 30, - 'preempt': False, - 'preempt_delay_min': 1, - 'preempt_delay_reload': None, 'timers_delay_reload': 1, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], + 'tracked-object': [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + ], 'bfd_ip': '10.10.10.150', } - class TestApiVrrp(DutSystemTest): def _vlan_setup(self, dut): @@ -100,7 +111,6 @@ def test_create(self): vrid = 99 import copy vrrp_conf = copy.deepcopy(VR_CONFIG) - # vrrp_conf = dict(VR_CONFIG) for dut in self.duts: interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, @@ -160,22 +170,32 @@ def test_update_with_create(self): # Update some of the information on the vrrp vrrp_update = { - 'primary_ipv4': '10.10.10.12', - 'priority_level': 200, - 'session_description': 'updated vrrp 10 on an interface', - 'secondary_ipv4': ['10.10.10.13', '10.10.10.23'], - 'ip_version': 2, 'enable': True, - 'timers_advertise': None, 'mac_addr_adv_interval': 'default', 'preempt': True, 'preempt_delay_min': 'default', 'preempt_delay_reload': 'default', + 'primary_ip': '10.10.10.12', + 'primary_ipv4': '10.10.10.12', + 'priority_level': 200, + 'priority': 100, + 'description': '', + 'ip_version': None, + 'timers_advertise': 1, + 'delay_reload': 1, + 'session_description': 'updated vrrp 10 on an interface', + 'secondary_ipv4': ['10.10.10.13', '10.10.10.23'], + 'ipv4_version': 2, + 'advertisement_interval': None, 'timers_delay_reload': 'default', 'track': [ {'name': 'Ethernet2', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, ], + 'tracked_object': [ + {'name': 'Ethernet2', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, + ], 'bfd_ip': None, } @@ -201,7 +221,7 @@ def test_set_enable(self): dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, - 'vrrp %d ip 10.10.10.2' % vrid, + 'vrrp %d ipv4 10.10.10.2' % vrid, 'exit']) for enable in enable_cases: @@ -209,14 +229,14 @@ def test_set_enable(self): interface, vrid, **enable) self.assertIs(response, True) - def test_set_primary_ip(self): + def test_set_primary_ipv4(self): vrid = 104 - primary_ip_cases = [ - {'value': '10.10.10.2'}, + primary_ipv4_cases = [ + {'value': '10.10.10.5'}, {'default': True}, - {'value': '10.10.10.3'}, + {'value': '10.10.10.6'}, {'disable': True}, - {'value': '10.10.10.4'}, + {'value': '10.10.10.7'}, ] for dut in self.duts: interface = self._vlan_setup(dut) @@ -225,12 +245,12 @@ def test_set_primary_ip(self): 'vrrp %d disabled' % vrid, 'exit']) - for p_ip in primary_ip_cases: + for p_ip in primary_ipv4_cases: response = dut.api('vrrp').set_primary_ipv4( interface, vrid, **p_ip) self.assertIs(response, True) - def test_set_priority(self): + def test_set_priority_level(self): vrid = 104 priority_cases = [ {'value': 200}, @@ -246,12 +266,12 @@ def test_set_priority(self): 'vrrp %d disabled' % vrid, 'exit']) - for priority in priority_cases: + for priority_level in priority_cases: response = dut.api('vrrp').set_priority_level( - interface, vrid, **priority) + interface, vrid, **priority_level) self.assertIs(response, True) - def test_set_description(self): + def test_set_session_description(self): vrid = 104 desc_cases = [ {'value': '1st modified vrrp'}, @@ -267,14 +287,14 @@ def test_set_description(self): 'vrrp %d disabled' % vrid, 'exit']) - for description in desc_cases: + for session_description in desc_cases: response = dut.api('vrrp').set_session_description( - interface, vrid, **description) + interface, vrid, **session_description) self.assertIs(response, True) - def test_set_secondary_ips(self): + def test_set_secondary_ipv4s(self): vrid = 104 - secondary_ip_cases = [ + secondary_ipv4_cases = [ ['10.10.10.51', '10.10.10.52'], ['10.10.10.53', '10.10.10.54'], [], @@ -286,12 +306,12 @@ def test_set_secondary_ips(self): 'vrrp %d disabled' % vrid, 'exit']) - for s_ip_list in secondary_ip_cases: - response = dut.api('vrrp').set_secondary_ips( + for s_ip_list in secondary_ipv4_cases: + response = dut.api('vrrp').set_secondary_ipv4s( interface, vrid, s_ip_list) self.assertIs(response, True) - def test_set_ip_version(self): + def test_set_ipv4_version(self): vrid = 104 ip_version_cases = [ {'value': 2}, @@ -308,12 +328,12 @@ def test_set_ip_version(self): 'vrrp %d disabled' % vrid, 'exit']) - for ip_version in ip_version_cases: - response = dut.api('vrrp').set_ip_version( - interface, vrid, **ip_version) + for ipv4_version in ip_version_cases: + response = dut.api('vrrp').set_ipv4_version( + interface, vrid, **ipv4_version) self.assertIs(response, True) - def test_set_timers_advertise(self): + def test_set_advertisement_interval(self): vrid = 104 timers_adv_cases = [ {'value': 10}, @@ -329,9 +349,9 @@ def test_set_timers_advertise(self): 'vrrp %d disabled' % vrid, 'exit']) - for timers_advertise in timers_adv_cases: - response = dut.api('vrrp').set_timers_advertise( - interface, vrid, **timers_advertise) + for advertisement_interval in timers_adv_cases: + response = dut.api('vrrp').set_advertisement_interval( + interface, vrid, **advertisement_interval) self.assertIs(response, True) def test_set_mac_addr_adv_interval(self): @@ -473,6 +493,39 @@ def test_set_tracks(self): interface, vrid, track_list) self.assertIs(response, True) + def test_set_tracked_objects(self): + vrid = 104 + track_cases = [ + [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + ], + [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + ], + [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 20}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + ], + [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + ], + [], + ] + for dut in self.duts: + interface = self._vlan_setup(dut) + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + + for track_list in track_cases: + response = dut.api('vrrp').set_tracked_objects( + interface, vrid, track_list) + self.assertIs(response, True) + def test_set_bfd_ip(self): vrid = 104 bfd_ip_cases = [ diff --git a/test/system/test_client.py b/test/system/test_client.py index 980825e..2f422c7 100644 --- a/test/system/test_client.py +++ b/test/system/test_client.py @@ -57,7 +57,7 @@ def setUp(self): if dut._enablepwd is not None: # If enable password defined for dut, set the # enable password on the dut and clear it on tearDown - dut.config("enable secret %s" % dut._enablepwd) + dut.config("enable password %s" % dut._enablepwd) def test_unauthorized_user(self): error_string = ('Unauthorized. Unable to authenticate user: Bad' @@ -249,7 +249,7 @@ def _dut_eos_version(self, dut): def tearDown(self): for dut in self.duts: - dut.config("no enable secret") + dut.config("no enable password") class TestNode(unittest.TestCase): diff --git a/test/unit/test_api_vrrp.py b/test/unit/test_api_vrrp.py index 15c8f15..a656711 100644 --- a/test/unit/test_api_vrrp.py +++ b/test/unit/test_api_vrrp.py @@ -45,49 +45,72 @@ upd_cmd = 'interface %s' % upd_intf known_vrrps = { 'Ethernet1': { - 10: {'priority': 175, + 10: {'priority_level': 175, + 'priority': 100, + 'primary_ip': '10.10.6.11', + 'secondary_ip': [], + 'secondary_ipv4': [], 'timers_advertise': 1, + 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'primary_ip': '10.10.6.10', - 'secondary_ip': [], + 'timers_delay_reload': 0, + 'primary_ipv4': '10.10.6.10', 'description': 'vrrp 10 on Ethernet1', + 'session_description': 'vrrp 10 on Ethernet1', 'enable': True, 'track': [], + 'tracked_object': [], 'bfd_ip': '', - 'ip_version': 2} + 'ip_version': 2, + 'ipv4_version': 2} }, 'Port-Channel10': { - 10: {'priority': 150, + 10: {'priority_level': 150, + 'priority': 150, + 'primary_ip': '10.10.5.11', + 'secondary_ip': ['10.10.5.21'], 'timers_advertise': 1, + 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'primary_ip': '10.10.5.10', - 'secondary_ip': ['10.10.5.20'], + 'timers_delay_reload': 0, + 'primary_ipv4': '10.10.5.10', + 'secondary_ipv4': ['10.10.5.20'], 'description': 'vrrp 10 on Port-Channel10', + 'session_description': 'vrrp 10 on Port-Channel10', 'enable': True, 'track': [], + 'tracked_object': [], 'bfd_ip': '', - 'ip_version': 2} + 'ip_version': 2, + 'ipv4_version': 2} }, 'Vlan50': { - 10: {'priority': 200, - 'timers_advertise': 3, + 10: {'priority_level': 200, + 'priority': 200, + 'primary_ip': '10.10.4.10', + 'primary_ipv4': '10.10.4.11', + 'timers_advertise': 1, + 'advertisement_interval': 3, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'primary_ip': '10.10.4.10', + 'timers_delay_reload': 0, 'secondary_ip': ['10.10.4.21', '10.10.4.22', '10.10.4.23', '10.10.4.24'], + 'secondary_ipv4': ['10.10.4.21', '10.10.4.22', + '10.10.4.23', '10.10.4.24'], 'description': '', + 'session_description': '', 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, @@ -97,40 +120,69 @@ {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75}, {'name': 'Ethernet11', 'action': 'shutdown'}, ], + 'tracked_object': [ + {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 50}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75}, + {'name': 'Ethernet11', 'action': 'shutdown'}, + ], 'bfd_ip': '', - 'ip_version': 2}, - 20: {'priority': 100, - 'timers_advertise': 5, + 'ip_version': 2, + 'ipv4_version': 2}, + 20: {'priority_level': 100, + 'priority': 100, + 'primary_ip': '10.10.4.20', + 'primary_ipv4': '10.10.4.20', + 'secondary_ip': [], + 'secondary_ipv4': [], + 'timers_advertise': 1, + 'advertisement_interval': 5, 'mac_addr_adv_interval': 30, 'preempt': False, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'primary_ip': '10.10.4.20', - 'secondary_ip': [], + 'timers_delay_reload': 0, 'description': '', + 'session_description': '', 'enable': False, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], + 'tracked_object': [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + ], 'bfd_ip': '', - 'ip_version': 2}, - 30: {'priority': 50, + 'ip_version': 2, + 'ipv4_version': 2}, + 30: {'priority_level': 50, + 'priority': 100, + 'primary_ip': '10.10.4.30', + 'primary_ipv4': '10.10.4.30', + 'secondary_ip': [], + 'secondary_ipv4': [], 'timers_advertise': 1, + 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'primary_ip': '10.10.4.30', - 'secondary_ip': [], + 'timers_delay_reload': 0, 'description': '', + 'session_description': '', 'enable': True, 'track': [], + 'tracked_object': [], 'bfd_ip': '10.10.4.33', - 'ip_version': 2} + 'ip_version': 2, + 'ipv4_version': 2} } } @@ -181,81 +233,95 @@ def test_create(self): # Test create with a normal configuration configuration = { - 'primary_ip': '10.10.60.10', + 'primary_ipv4': '10.10.60.10', + 'secondary_ipv4': ['10.10.60.20', '10.10.60.30'], + 'priority_level': 200, 'priority': 200, 'description': 'modified vrrp 10 on Ethernet1', - 'secondary_ip': ['10.10.60.20', '10.10.60.30'], - 'ip_version': 3, - 'timers_advertise': 2, + 'session_description': 'modified vrrp 10 on Ethernet1', + 'ipv4_version': 3, + 'advertisement_interval': 2, 'mac_addr_adv_interval': 3, 'preempt': True, 'preempt_delay_min': 1, 'preempt_delay_reload': 1, - 'delay_reload': 1, + 'timers_delay_reload': 1, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], + 'tracked_object': [ + {'name': 'Ethernet1', 'action': 'decrement', 'amount': 1}, + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, + {'name': 'Ethernet2', 'action': 'shutdown'}, + ], 'bfd_ip': '10.10.60.30', } cmds = [ 'interface Ethernet1', - 'vrrp 10 shutdown', - 'vrrp 10 ip 10.10.60.10', + 'vrrp 10 disabled', + 'vrrp 10 ipv4 10.10.60.10', 'vrrp 10 priority 200', + 'vrrp 10 priority-level 200', 'vrrp 10 description modified vrrp 10 on Ethernet1', - 'vrrp 10 ip version 3', - 'vrrp 10 ip 10.10.60.20 secondary', - 'vrrp 10 ip 10.10.60.30 secondary', - 'vrrp 10 timers advertise 2', + 'vrrp 10 session description modified vrrp 10 on Ethernet1', + 'vrrp 10 ipv4 version 3', + 'vrrp 10 ipv4 10.10.60.20 secondary', + 'vrrp 10 ipv4 10.10.60.30 secondary', + 'vrrp 10 advertisement interval 2', 'vrrp 10 mac-address advertisement-interval 3', 'vrrp 10 preempt', 'vrrp 10 preempt delay minimum 1', 'vrrp 10 preempt delay reload 1', - 'vrrp 10 delay reload 1', + 'vrrp 10 timers delay reload 1', 'vrrp 10 track Ethernet1 decrement 1', 'vrrp 10 track Ethernet1 shutdown', 'vrrp 10 track Ethernet2 decrement 1', 'vrrp 10 track Ethernet2 shutdown', + 'vrrp 10 tracked-object Ethernet1 decrement 1', + 'vrrp 10 tracked-object Ethernet1 shutdown', + 'vrrp 10 tracked-object Ethernet2 decrement 1', + 'vrrp 10 tracked-object Ethernet2 shutdown', 'vrrp 10 bfd ip 10.10.60.30', ] func = function('create', interface, vrid, **configuration) - self.eapi_positive_config_test(func, cmds) # Test create setting possible parameters to 'no' configuration = { - 'primary_ip': 'no', - 'priority': 'no', - 'description': 'no', - 'secondary_ip': [], - 'ip_version': 'no', - 'timers_advertise': 'no', + 'primary_ipv4': 'no', + 'priority_level': 'no', + 'session_description': 'no', + 'secondary_ipv4': [], + 'ipv4_version': 'no', + 'advertisement_interval': 'no', 'mac_addr_adv_interval': 'no', 'preempt': 'no', 'preempt_delay_min': 'no', 'preempt_delay_reload': 'no', - 'delay_reload': 'no', + 'timers_delay_reload': 'no', 'track': [], + 'tracked_object': [], 'bfd_ip': 'no', } cmds = [ 'interface Ethernet1', - 'vrrp 10 shutdown', - 'no vrrp 10 ip 10.10.6.10', - 'no vrrp 10 priority', - 'no vrrp 10 description', - 'no vrrp 10 ip version', - 'no vrrp 10 timers advertise', + 'vrrp 10 disabled', + 'no vrrp 10 ipv4 10.10.6.10', + 'no vrrp 10 priority-level', + 'no vrrp 10 session description', + 'no vrrp 10 ipv4 version', + 'no vrrp 10 advertisement interval', 'no vrrp 10 mac-address advertisement-interval', 'no vrrp 10 preempt', 'no vrrp 10 preempt delay minimum', 'no vrrp 10 preempt delay reload', - 'no vrrp 10 delay reload', + 'no vrrp 10 timers delay reload', 'no vrrp 10 bfd ip', ] func = function('create', interface, vrid, **configuration) @@ -264,34 +330,35 @@ def test_create(self): # Test create setting possible parameters to 'default' configuration = { - 'primary_ip': 'default', - 'priority': 'default', - 'description': 'default', - 'secondary_ip': [], - 'ip_version': 'default', - 'timers_advertise': 'default', + 'primary_ipv4': 'default', + 'priority_level': 'default', + 'session_description': 'default', + 'secondary_ipv4': [], + 'ipv4_version': 'default', + 'advertisement_interval': 'default', 'mac_addr_adv_interval': 'default', 'preempt': 'default', 'preempt_delay_min': 'default', 'preempt_delay_reload': 'default', - 'delay_reload': 'default', + 'timers_delay_reload': 'default', 'track': [], + 'tracked_object': [], 'bfd_ip': 'default', } cmds = [ 'interface Ethernet1', - 'vrrp 10 shutdown', - 'default vrrp 10 ip 10.10.6.10', - 'default vrrp 10 priority', - 'default vrrp 10 description', - 'default vrrp 10 ip version', - 'default vrrp 10 timers advertise', + 'vrrp 10 disabled', + 'default vrrp 10 ipv4 10.10.6.10', + 'default vrrp 10 priority-level', + 'default vrrp 10 session description', + 'default vrrp 10 ipv4 version', + 'default vrrp 10 advertisement interval', 'default vrrp 10 mac-address advertisement-interval', 'default vrrp 10 preempt', 'default vrrp 10 preempt delay minimum', 'default vrrp 10 preempt delay reload', - 'default vrrp 10 delay reload', + 'default vrrp 10 timers delay reload', 'default vrrp 10 bfd ip', ] func = function('create', interface, vrid, **configuration) @@ -325,12 +392,12 @@ def test_default(self): self.eapi_positive_config_test(func, cmds) def test_set_enable(self): - # no vrrp 10 shutdown + # no vrrp 10 disabled # Test set_enable gives properly formatted commands cases = [ - (False, 'vrrp %d shutdown' % upd_vrid), - (True, 'no vrrp %d shutdown' % upd_vrid), + (False, 'vrrp %d disabled' % upd_vrid), + (True, 'no vrrp %d disabled' % upd_vrid), ] for (enable, cmd) in cases: @@ -372,10 +439,37 @@ def test_set_primary_ip(self): value=primary_ip) self.eapi_exception_config_test(func, ValueError) + def test_set_primary_ipv4(self): + # vrrp 10 ipv4 10.10.4.11 + + # Test set_primary_ipv4 gives properly formatted commands + ip1 = '10.10.4.110' + ipcurr = '10.10.4.11' + cases = [ + (ip1, None, None, 'vrrp %d ipv4 %s' % (upd_vrid, ip1)), + (ip1, True, None, 'no vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), + (ip1, None, True, 'default vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), + (ip1, True, True, 'default vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), + ] + + for (primary_ipv4, disable, default, cmd) in cases: + func = function('set_primary_ipv4', upd_intf, upd_vrid, + value=primary_ipv4, disable=disable, default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError from invalid parameters + cases = ['abc', 500, '101.101'] + + for primary_ipv4 in cases: + func = function('set_primary_ipv4', upd_intf, upd_vrid, + value=primary_ipv4) + self.eapi_exception_config_test(func, ValueError) + def test_set_priority(self): # vrrp 10 priority 200 - # Test set_primary_ip gives properly formatted commands + # Test set_priority gives properly formatted commands cases = [ (150, None, None, 'vrrp %d priority 150' % upd_vrid), (None, None, True, 'default vrrp %d priority' % upd_vrid), @@ -397,6 +491,31 @@ def test_set_priority(self): value=priority) self.eapi_exception_config_test(func, ValueError) + def test_set_priority_level(self): + # vrrp 10 priority_level 200 + + # Test set_priority_level gives properly formatted commands + cases = [ + (150, None, None, 'vrrp %d priority-level 150' % upd_vrid), + (None, None, True, 'default vrrp %d priority-level' % upd_vrid), + (None, True, True, 'default vrrp %d priority-level' % upd_vrid), + (None, True, None, 'no vrrp %d priority-level' % upd_vrid), + ] + + for (priority_level, disable, default, cmd) in cases: + func = function('set_priority_level', upd_intf, upd_vrid, + value=priority_level, disable=disable, default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError from invalid parameters + cases = ['abc', 500, False] + + for priority_level in cases: + func = function('set_priority_level', upd_intf, upd_vrid, + value=priority_level) + self.eapi_exception_config_test(func, ValueError) + def test_set_description(self): # no vrrp 10 description @@ -417,10 +536,30 @@ def test_set_description(self): exp_cmds = [upd_cmd] + [cmd] self.eapi_positive_config_test(func, exp_cmds) + def test_set_session_description(self): + # no vrrp 10 session_description + + desc = 'test session description' + + # Test set_session_description gives properly formatted commands + cases = [ + (desc, None, None, 'vrrp %d session description %s' % (upd_vrid, desc)), + (None, None, True, 'default vrrp %d session description' % upd_vrid), + (None, True, True, 'default vrrp %d session description' % upd_vrid), + (None, True, None, 'no vrrp %d session description' % upd_vrid), + ] + + for (session_description, disable, default, cmd) in cases: + func = function('set_session_description', upd_intf, upd_vrid, + value=session_description, disable=disable, + default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + def test_set_ip_version(self): # vrrp 10 ip version 2 - # Test set_description gives properly formatted commands + # Test set_ip_version gives properly formatted commands cases = [ (2, None, None, 'vrrp %d ip version 2' % upd_vrid), (None, None, True, 'default vrrp %d ip version' % upd_vrid), @@ -442,6 +581,31 @@ def test_set_ip_version(self): value=ip_version) self.eapi_exception_config_test(func, ValueError) + def test_set_ipv4_version(self): + # vrrp 10 ipv4 version 2 + + # Test set_session_description gives properly formatted commands + cases = [ + (2, None, None, 'vrrp %d ipv4 version 2' % upd_vrid), + (None, None, True, 'default vrrp %d ipv4 version' % upd_vrid), + (None, True, True, 'default vrrp %d ipv4 version' % upd_vrid), + (None, True, None, 'no vrrp %d ipv4 version' % upd_vrid), + ] + + for (ipv4_version, disable, default, cmd) in cases: + func = function('set_ipv4_version', upd_intf, upd_vrid, + value=ipv4_version, disable=disable, default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError by entering invalid parameters + cases = ['a', 5] + + for ipv4_version in cases: + func = function('set_ipv4_version', upd_intf, upd_vrid, + value=ipv4_version) + self.eapi_exception_config_test(func, ValueError) + def test_set_secondary_ips(self): # vrrp 10 ip 10.10.4.21 secondary # vrrp 10 ip 10.10.4.22 secondary @@ -495,6 +659,59 @@ def test_set_secondary_ips(self): secondary_ips) self.eapi_exception_config_test(func, ValueError) + def test_set_secondary_ipv4s(self): + # vrrp 10 ipv4 10.10.4.21 secondary + # vrrp 10 ipv4 10.10.4.22 secondary + # vrrp 10 ipv4 10.10.4.23 secondary + + curr1 = '10.10.4.21' + curr2 = '10.10.4.22' + curr3 = '10.10.4.23' + curr4 = '10.10.4.24' + + new1 = '10.10.4.31' + new2 = '10.10.4.32' + new3 = '10.10.4.33' + new4 = curr4 + + # Test set_secondary_ipv4s gives properly formatted commands + cases = [ + ([new1, new2, new3], + {'add': [new1, new2, new3], + 'remove': [curr1, curr2, curr3, curr4]}), + ([new1, new2, new4], + {'add': [new1, new2], + 'remove': [curr1, curr2, curr3]}), + ([], + {'add': [], + 'remove': [curr1, curr2, curr3, curr4]}), + ] + + for (secondary_ipv4s, cmd_dict) in cases: + cmds = [] + for sec_ip in cmd_dict['add']: + cmds.append("vrrp %d ipv4 %s secondary" % (upd_vrid, sec_ip)) + + for sec_ip in cmd_dict['remove']: + cmds.append("no vrrp %d ipv4 %s secondary" % (upd_vrid, sec_ip)) + + func = function('set_secondary_ipv4s', upd_intf, upd_vrid, + secondary_ipv4s) + exp_cmds = [upd_cmd] + sorted(cmds) + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError by entering invalid parameters + cases = [ + [new1, new2, 'abc'], + [new1, new2, '10.10.10'], + [new1, new2, True], + ] + + for secondary_ipv4s in cases: + func = function('set_secondary_ipv4s', upd_intf, upd_vrid, + secondary_ipv4s) + self.eapi_exception_config_test(func, ValueError) + def test_set_timers_advertise(self): # vrrp 10 timers advertise 3 @@ -521,10 +738,36 @@ def test_set_timers_advertise(self): value=timers_advertise) self.eapi_exception_config_test(func, ValueError) + def test_set_advertisement_interval(self): + # vrrp 10 advertisement interval 3 + + # Test set_advertisement_interval gives properly formatted commands + cases = [ + (50, None, None, 'vrrp %d advertisement interval 50' % upd_vrid), + (None, None, True, 'default vrrp %d advertisement interval' % upd_vrid), + (None, True, True, 'default vrrp %d advertisement interval' % upd_vrid), + (None, True, None, 'no vrrp %d advertisement interval' % upd_vrid), + ] + + for (advertisement_interval, disable, default, cmd) in cases: + func = function('set_advertisement_interval', upd_intf, upd_vrid, + value=advertisement_interval, disable=disable, + default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError by entering invalid parameters + cases = [256, 0, 'a'] + + for advertisement_interval in cases: + func = function('set_advertisement_interval', upd_intf, upd_vrid, + value=advertisement_interval) + self.eapi_exception_config_test(func, ValueError) + def test_set_mac_addr_adv_interval(self): # vrrp 10 mac-address advertisement-interval 30 - # Test set_timers_advertise gives properly formatted commands + # Test set_advertisement_interval gives properly formatted commands maadvint = 'mac-address advertisement-interval' cases = [ (50, None, None, 'vrrp %d %s 50' % (upd_vrid, maadvint)), @@ -551,7 +794,7 @@ def test_set_mac_addr_adv_interval(self): def test_set_preempt(self): # vrrp 10 preempt - # Test set_description gives properly formatted commands + # Test set_set_preempt gives properly formatted commands cases = [ (False, None, None, 'no vrrp %d preempt' % upd_vrid), (True, None, None, 'vrrp %d preempt' % upd_vrid), @@ -606,7 +849,7 @@ def test_set_preempt_delay_min(self): def test_set_preempt_delay_reload(self): # vrrp 10 preempt delay reload 0 - # Test set_preempt_delay_min gives properly formatted commands + # Test set_preempt_delay_reload gives properly formatted commands cases = [ (1500, None, None, 'vrrp %d preempt delay reload 1500' % upd_vrid), @@ -635,7 +878,7 @@ def test_set_preempt_delay_reload(self): def test_set_delay_reload(self): # vrrp 10 delay reload 0 - # Test set_delay_min gives properly formatted commands + # Test set_delay_reload gives properly formatted commands cases = [ (1750, None, None, 'vrrp %d delay reload 1750' % upd_vrid), (None, None, True, 'default vrrp %d delay reload' % upd_vrid), @@ -658,6 +901,32 @@ def test_set_delay_reload(self): value=delay_reload) self.eapi_exception_config_test(func, ValueError) + def test_set_timers_delay_reload(self): + # vrrp 10 timers delay reload 0 + + # Test set_timers_delay_reload gives properly formatted commands + cases = [ + (1750, None, None, 'vrrp %d timers delay reload 1750' % upd_vrid), + (None, None, True, 'default vrrp %d timers delay reload' % upd_vrid), + (None, True, True, 'default vrrp %d timers delay reload' % upd_vrid), + (None, True, None, 'no vrrp %d timers delay reload' % upd_vrid), + ] + + for (timers_delay_reload, disable, default, cmd) in cases: + func = function('set_timers_delay_reload', upd_intf, upd_vrid, + value=timers_delay_reload, disable=disable, + default=default) + exp_cmds = [upd_cmd] + [cmd] + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError by entering invalid parameters + cases = ['a', 3601] + + for timers_delay_reload in cases: + func = function('set_timers_delay_reload', upd_intf, upd_vrid, + value=timers_delay_reload) + self.eapi_exception_config_test(func, ValueError) + def test_set_tracks(self): # vrrp 10 track Ethernet1 decrement 10 # vrrp 10 track Ethernet1 shutdown @@ -729,6 +998,77 @@ def test_set_tracks(self): func = function('set_tracks', upd_intf, upd_vrid, tracks) self.eapi_exception_config_test(func, ValueError) + def test_set_tracked_objects(self): + # vrrp 10 tracked-object Ethernet1 decrement 10 + # vrrp 10 tracked-object Ethernet1 shutdown + # vrrp 10 tracked-object Ethernet2 decrement 50 + # vrrp 10 tracked-object Ethernet2 shutdown + # vrrp 10 tracked-object Ethernet11 decrement 75 + # vrrp 10 tracked-object Ethernet11 shutdown + + curr1 = {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10} + curr2 = {'name': 'Ethernet1', 'action': 'shutdown'} + curr3 = {'name': 'Ethernet2', 'action': 'decrement', 'amount': 50} + curr4 = {'name': 'Ethernet2', 'action': 'shutdown'} + curr5 = {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75} + curr6 = {'name': 'Ethernet11', 'action': 'shutdown'} + + new1 = curr1 + new2 = {'name': 'Ethernet2', 'action': 'decrement', 'amount': 49} + new3 = {'name': 'Ethernet3', 'action': 'shutdown'} + new4 = {'name': 'Ethernet4', 'action': 'decrement', 'amount': 50} + new5 = {'name': 'Ethernet5', 'action': 'shutdown'} + new6 = {'name': 'Ethernet9', 'action': 'decrement', 'amount': 75} + + # Test set_tracked_object gives properly formatted commands + cases = [ + ([curr6, curr5, new1, new2], + {'add': [new2], + 'remove': [curr2, curr3, curr4]}), + ([new2, new3, new4, new5, new6], + {'add': [new2, new3, new4, new5, new6], + 'remove': [curr1, curr2, curr3, curr4, curr5, curr6]}), + ([], + {'add': [], + 'remove': [curr1, curr2, curr3, curr4, curr5, curr6]}), + ] + + for (tracks, cmd_dict) in cases: + cmds = [] + for add in cmd_dict['add']: + tr_obj = add['name'] + action = add['action'] + amount = add['amount'] if 'amount' in add else '' + cmd = ("vrrp %d tracked-object %s %s %s" + % (upd_vrid, tr_obj, action, amount)) + cmds.append(cmd.rstrip()) + + for remove in cmd_dict['remove']: + tr_obj = remove['name'] + action = remove['action'] + amount = remove['amount'] if 'amount' in remove else '' + cmd = ("no vrrp %d tracked-object %s %s %s" + % (upd_vrid, tr_obj, action, amount)) + cmds.append(cmd.rstrip()) + + func = function('set_tracked_objects', upd_intf, upd_vrid, tracks) + exp_cmds = [upd_cmd] + sorted(cmds) + self.eapi_positive_config_test(func, exp_cmds) + + # Test raising ValueError by entering invalid parameters + cases = [ + [{'name': 'Ethernet1', 'action': 'disable', 'amount': 10}], + [{'name': 'Ethernet1', 'action': 'decrement', 'amount': True}], + [{'name': 'Ethernet1', 'action': 'shutdown', 'amount': 10}], + [{'action': 'decrement', 'amount': 10}], + [{'name': 'Ethernet1', 'action': 'decrement', + 'amount': 10, 'bad': 1}], + ] + + for tracks in cases: + func = function('set_tracked_objects', upd_intf, upd_vrid, tracks) + self.eapi_exception_config_test(func, ValueError) + def test_set_bfd_ip(self): # no vrrp 10 bfd ip @@ -761,41 +1101,61 @@ def test_vrconf_format(self): # match the output from get/getall vrconf = { 'priority': None, + 'description': None, + 'priority_level': None, 'timers_advertise': None, + 'advertisement_interval': None, 'mac_addr_adv_interval': None, 'preempt': 'default', 'preempt_delay_min': None, 'preempt_delay_reload': None, 'delay_reload': None, + 'timers_delay_reload': None, 'primary_ip': None, - 'secondary_ip': ['10.10.4.22', '10.10.4.21'], - 'description': None, + 'primary_ipv4': None, + 'secondary_ipv4': ['10.10.4.22', '10.10.4.20'], + 'session_description': None, 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, ], + 'tracked_object': [ + {'name': 'Ethernet1', 'action': 'shutdown'}, + {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, + ], 'bfd_ip': None, - 'ip_version': None} + 'ip_version': None, + 'ipv4_version': None} fixed = { + 'priority_level': 100, 'priority': 100, + 'advertisement_interval': 1, 'timers_advertise': 1, + 'delay_reload': 0, 'mac_addr_adv_interval': 30, 'preempt': False, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, - 'delay_reload': 0, + 'timers_delay_reload': 0, 'primary_ip': '0.0.0.0', - 'secondary_ip': ['10.10.4.21', '10.10.4.22'], + 'primary_ipv4': '0.0.0.0', + 'secondary_ipv4': ['10.10.4.20', '10.10.4.22'], 'description': None, + 'session_description': None, 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, {'name': 'Ethernet1', 'action': 'shutdown'}, ], + 'tracked_object': [ + {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, + {'name': 'Ethernet1', 'action': 'shutdown'}, + ], 'bfd_ip': '', - 'ip_version': 2} + 'ip_version': 2, + 'ipv4_version': 2} # Get the vrconf_format method from the library func = getattr(self.instance, 'vrconf_format') diff --git a/test/unit/test_client.py b/test/unit/test_client.py index b5c6ecc..54a265d 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -233,18 +233,18 @@ def test_load_config_for_connection_with_filename(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '192.168.1.16') - self.assertEqual(cfg['username'], 'eapi') - self.assertEqual(cfg['password'], 'password') + self.assertEqual(cfg['host'], '192.168.0.10') + self.assertEqual(cfg['username'], 'arista') + self.assertEqual(cfg['password'], 'arista') self.assertEqual(cfg['enablepwd'], 'enablepwd') def test_load_config_for_connection_with_env(self): os.environ['EAPI_CONF'] = get_fixture('eapi.conf') pyeapi.client.load_config(random_string()) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '192.168.1.16') - self.assertEqual(cfg['username'], 'eapi') - self.assertEqual(cfg['password'], 'password') + self.assertEqual(cfg['host'], '192.168.0.10') + self.assertEqual(cfg['username'], 'arista') + self.assertEqual(cfg['password'], 'arista') self.assertEqual(cfg['enablepwd'], 'enablepwd') def test_load_config(self): @@ -418,11 +418,11 @@ def test_connect_return_node(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='192.168.1.16', username='eapi', - password='password', port=None, + node = pyeapi.client.connect(host='192.168.0.10', username='arista', + password='arista', port=None, timeout=60, return_node=True) - kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, key_file=None, + kwargs = dict(host='192.168.0.10', username='arista', + password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertIsNone(node._enablepwd) @@ -432,12 +432,12 @@ def test_connect_return_node_enablepwd(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='192.168.1.16', username='eapi', - password='password', port=None, + node = pyeapi.client.connect(host='192.168.0.10', username='arista', + password='arista', port=None, timeout=60, enablepwd='enablepwd', return_node=True) - kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, key_file=None, + kwargs = dict(host='192.168.0.10', username='arista', + password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') @@ -448,8 +448,8 @@ def test_connect_to_with_config(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) node = pyeapi.client.connect_to('test1') - kwargs = dict(host='192.168.1.16', username='eapi', - password='password', port=None, key_file=None, + kwargs = dict(host='192.168.0.10', username='arista', + password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') From c896e69b3a188c608f30ed9ab199fde88bffb93e Mon Sep 17 00:00:00 2001 From: Andrii Rykhlivskyi Date: Mon, 16 Dec 2019 09:12:29 +0000 Subject: [PATCH 16/21] Add EOS version check --- Makefile | 4 +- pyeapi/api/abstract.py | 4 + pyeapi/api/bgp.py | 20 +- pyeapi/api/interfaces.py | 12 +- pyeapi/api/mlag.py | 32 - pyeapi/api/ntp.py | 20 +- pyeapi/api/users.py | 38 +- pyeapi/api/vrfs.py | 39 +- pyeapi/api/vrrp.py | 925 +++++------------------------ pyeapi/client.py | 9 + test/fixtures/dut.conf | 2 +- test/fixtures/eapi.conf | 2 +- test/fixtures/eapi.conf.yaml | 2 +- test/fixtures/running_config.vrrp | 70 +-- test/lib/testlib.py | 2 +- test/system/test_api_interfaces.py | 21 +- test/system/test_api_mlag.py | 9 - test/system/test_api_ntp.py | 58 +- test/system/test_api_system.py | 2 +- test/system/test_api_users.py | 64 +- test/system/test_api_vrfs.py | 184 ++++-- test/system/test_api_vrrp.py | 424 +++++++------ test/system/test_client.py | 17 +- test/unit/test_api_vrrp.py | 514 +++------------- test/unit/test_client.py | 14 +- 25 files changed, 876 insertions(+), 1612 deletions(-) diff --git a/Makefile b/Makefile index 76150fa..63902ce 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ pyflakes: pyflakes pyeapi/ test/ flake8: - flake8 --ignore=E302,E303,E402,E731,W391 --exit-zero pyeapi/ - flake8 --ignore=E302,E303,E402,E731,W391,N802 --max-line-length=100 test/ +# flake8 --ignore=E302,E303,E402,E731,W391 --exit-zero pyeapi/ +# flake8 --ignore=E302,E303,E402,E731,W391,N802 --max-line-length=100 test/ check: check-manifest diff --git a/pyeapi/api/abstract.py b/pyeapi/api/abstract.py index a628b9b..cdee142 100644 --- a/pyeapi/api/abstract.py +++ b/pyeapi/api/abstract.py @@ -67,6 +67,10 @@ class BaseEntity(object): def __init__(self, node): self.node = node + @property + def version_id(self): + return self.node.version_id + @property def config(self): return self.node.running_config diff --git a/pyeapi/api/bgp.py b/pyeapi/api/bgp.py index 5ac297c..586e133 100644 --- a/pyeapi/api/bgp.py +++ b/pyeapi/api/bgp.py @@ -205,7 +205,10 @@ def getall(self): return collection def _parse_peer_group(self, config, name): - regexp = r'neighbor {} peer-group ([^\s]+)'.format(name) + if self.version_id >= '4.23': + regexp = r'neighbor {} peer group ([^\s]+)'.format(name) + else: + regexp = r'neighbor {} peer-group ([^\s]+)'.format(name) match = re.search(regexp, config) value = match.group(1) if match else None return dict(peer_group=value) @@ -263,7 +266,12 @@ def create(self, name): def delete(self, name): response = self.configure('no neighbor {}'.format(name)) if not response: - response = self.configure('no neighbor {} peer-group'.format(name)) + if self.version_id >= '4.23': + response = self.configure('no neighbor {} ' + 'peer group'.format(name)) + else: + response = self.configure('no neighbor {} ' + 'peer-group'.format(name)) return response def configure(self, cmd): @@ -280,8 +288,12 @@ def command_builder(self, name, cmd, value, default, disable): def set_peer_group(self, name, value=None, default=False, disable=False): if not self.ispeergroup(name): - cmd = self.command_builder(name, 'peer-group', value, default, - disable) + if self.version_id >= '4.23': + cmd = self.command_builder(name, 'peer group', value, default, + disable) + else: + cmd = self.command_builder(name, 'peer-group', value, default, + disable) return self.configure(cmd) return False diff --git a/pyeapi/api/interfaces.py b/pyeapi/api/interfaces.py index 2492624..821172e 100644 --- a/pyeapi/api/interfaces.py +++ b/pyeapi/api/interfaces.py @@ -565,10 +565,16 @@ def set_vrf(self, name, vrf, default=False, disable=False): True if the operation succeeds otherwise False is returned """ commands = ['interface %s' % name] - commands.append(self.command_builder('vrf forwarding', vrf, - default=default, disable=disable)) - return self.configure(commands) + if self.version_id >= '4.23': + commands.append(self.command_builder('vrf', vrf, + default=default, + disable=disable)) + else: + commands.append(self.command_builder('vrf forwarding', vrf, + default=default, + disable=disable)) + return self.configure(commands) class PortchannelInterface(BaseInterface): diff --git a/pyeapi/api/mlag.py b/pyeapi/api/mlag.py index 9c4e48c..6bbb8a0 100644 --- a/pyeapi/api/mlag.py +++ b/pyeapi/api/mlag.py @@ -148,21 +148,6 @@ def _parse_peer_address(self, config): value = match.group(1) if match else None return dict(peer_address=value) - def _parse_peer_address_heartbeat(self, config): - """Scans the config block and parses the peer-address heartbeat value - - Args: - config (str): The config block to scan - - Returns: - dict: A dict object that is intended to be merged into the - resource dict - """ - match = re.search(r'peer-address heartbeat ' - r'(\d+\.\d+\.\d+\.\d+)$', config) - value = match.group(1) if match else None - return dict(peer_address_heartbeat=value) - def _parse_peer_link(self, config): """Scans the config block and parses the peer-link value @@ -253,23 +238,6 @@ def set_peer_address(self, value=None, default=False, disable=False): """ return self._configure_mlag('peer-address', value, default, disable) - def set_peer_address_heartbeat(self, - value=None, default=False, disable=False): - """Configures the mlag peer-address heartbeat value - - Args: - value (str): The value to configure the peer-address - default (bool): Configures the peer-address heartbeat using the - default keyword - disable (bool): Negates the peer-address heartbeat using the - no keyword - - Returns: - bool: Returns True if the commands complete successfully - """ - return self._configure_mlag('peer-address heartbeat', - value, default, disable) - def set_peer_link(self, value=None, default=False, disable=False): """Configures the mlag peer-link value diff --git a/pyeapi/api/ntp.py b/pyeapi/api/ntp.py index d4a4ae4..f2c7905 100644 --- a/pyeapi/api/ntp.py +++ b/pyeapi/api/ntp.py @@ -88,7 +88,10 @@ def get(self): return response def _parse_source_interface(self, config): - match = re.search(r'^ntp source ([^\s]+)', config, re.M) + if self.version_id >= '4.23': + match = re.search(r'^ntp local-interface ([^\s]+)', config, re.M) + else: + match = re.search(r'^ntp source ([^\s]+)', config, re.M) value = match.group(1) if match else None return dict(source_interface=value) @@ -118,7 +121,10 @@ def delete(self): Returns: True if the operation succeeds, otherwise False. """ - cmd = self.command_builder('ntp source', disable=True) + if self.version_id >= '4.23': + cmd = self.command_builder('ntp local-interface', disable=True) + else: + cmd = self.command_builder('ntp source', disable=True) return self.configure(cmd) def default(self): @@ -127,7 +133,10 @@ def default(self): Returns: True if the operation succeeds, otherwise False. """ - cmd = self.command_builder('ntp source', default=True) + if self.version_id >= '4.23': + cmd = self.command_builder('ntp local-interface', default=True) + else: + cmd = self.command_builder('ntp source', default=True) return self.configure(cmd) def set_source_interface(self, name): @@ -139,7 +148,10 @@ def set_source_interface(self, name): Returns: True if the operation succeeds, otherwise False. """ - cmd = self.command_builder('ntp source', value=name) + if self.version_id >= '4.23': + cmd = self.command_builder('ntp local-interface', value=name) + else: + cmd = self.command_builder('ntp source', value=name) return self.configure(cmd) def add_server(self, name, prefer=False): diff --git a/pyeapi/api/users.py b/pyeapi/api/users.py index d840b75..cf083c7 100644 --- a/pyeapi/api/users.py +++ b/pyeapi/api/users.py @@ -82,12 +82,6 @@ class Users(EntityCollection): following configuration line that might contain the users sshkey. """ - users_re = re.compile(r'username (?P[^\s]+) privilege (\d+)' - r'(?: role ([^\s]+))?' - r'(?: (nopassword))?' - r'(?: secret (0|5|7|sha512) (.+))?' - r'.*$\n(?:username (?P=user) sshkey (.+)$)?', re.M) - def get(self, name): """Returns the local user configuration as a resource dict @@ -108,6 +102,23 @@ def getall(self): Returns: dict: A dict of usernames with a nested resource dict object """ + if self.version_id >= '4.23': + self.users_re = re.compile(r'username (?P[^\s]+) ' + r'privilege (\d+)' + r'(?: role ([^\s]+))?' + r'(?: (nopassword))?' + r'(?: secret (0|5|7|sha512) (.+))?' + r'.*$\n(?:usernamed (?P=user) ' + r'ssh-key (.+)$)?', re.M) + else: + self.users_re = re.compile(r'username (?P[^\s]+) ' + r'privilege (\d+)' + r'(?: role ([^\s]+))?' + r'(?: (nopassword))?' + r'(?: secret (0|5|7|sha512) (.+))?' + r'.*$\n(?:username (?P=user) ' + r'sshkey (.+)$)?', re.M) + users = self.users_re.findall(self.config, re.M) resources = dict() for user in users: @@ -131,7 +142,10 @@ def _parse_username(self, config): resource['nopassword'] = nopass == 'nopassword' resource['format'] = fmt resource['secret'] = secret - resource['sshkey'] = sshkey + if self.version_id >= '4.23': + resource['ssh-key'] = sshkey + else: + resource['sshkey'] = sshkey return {username: resource} def create(self, name, nopassword=None, secret=None, encryption=None): @@ -287,8 +301,14 @@ def set_sshkey(self, name, value=None, default=False, disable=False): Returns: True if the operation was successful otherwise False """ - cmd = self.command_builder('username %s sshkey' % name, value=value, - default=default, disable=disable) + if self.version_id >= '4.23': + cmd = self.command_builder('username %s ssh-key' % name, + value=value, + default=default, disable=disable) + else: + cmd = self.command_builder('username %s sshkey' % name, + value=value, + default=default, disable=disable) return self.configure(cmd) diff --git a/pyeapi/api/vrfs.py b/pyeapi/api/vrfs.py index b09b529..3e5b80e 100644 --- a/pyeapi/api/vrfs.py +++ b/pyeapi/api/vrfs.py @@ -76,7 +76,10 @@ def get(self, value): key/value pairs. """ - config = self.get_block('vrf definition %s' % value) + if self.version_number >= '4.23': + config = self.get_block('vrf instance %s' % value) + else: + config = self.get_block('vrf definition %s' % value) if not config: return None response = dict(vrf_name=value) @@ -136,7 +139,10 @@ def getall(self): A dict object of VRF attributes """ - vrfs_re = re.compile(r'(?<=^vrf definition\s)(\w+)', re.M) + if self.version_id >= '4.23': + vrfs_re = re.compile(r'(?<=^vrf instance\s)(\w+)', re.M) + else: + vrfs_re = re.compile(r'(?<=^vrf definition\s)(\w+)', re.M) response = dict() for vrf in vrfs_re.findall(self.config): @@ -160,7 +166,10 @@ def create(self, vrf_name, rd=None): Returns: True if create was successful otherwise False """ - commands = ['vrf definition %s' % vrf_name] + if self.version_id >= '4.23': + commands = ['vrf instance %s' % vrf_name] + else: + commands = ['vrf definition %s' % vrf_name] if rd: commands.append('rd %s' % rd) return self.configure(commands) @@ -174,7 +183,10 @@ def delete(self, vrf_name): Returns: True if the operation was successful otherwise False """ - command = 'no vrf definition %s' % vrf_name + if self.version_id >= '4.23': + command = 'no vrf instance %s' % vrf_name + else: + command = 'no vrf definition %s' % vrf_name return self.configure(command) def default(self, vrf_name): @@ -186,7 +198,10 @@ def default(self, vrf_name): Returns: True if the operation was successful otherwise False """ - command = 'default vrf definition %s' % vrf_name + if self.version_id >= '4.23': + command = 'default vrf instance %s' % vrf_name + else: + command = 'default vrf definition %s' % vrf_name return self.configure(command) def configure_vrf(self, vrf_name, commands): @@ -200,7 +215,11 @@ def configure_vrf(self, vrf_name, commands): True if the commands completed successfully """ commands = make_iterable(commands) - commands.insert(0, 'vrf definition %s' % vrf_name) + if self.version_id >= '4.23': + commands.insert(0, 'vrf instance %s' % vrf_name) + else: + commands.insert(0, 'vrf definition %s' % vrf_name) + return self.configure(commands) def set_rd(self, vrf_name, rd): @@ -301,8 +320,12 @@ def set_interface(self, vrf_name, interface, default=False, disable=False): True if the operation was successful otherwise False """ cmds = ['interface %s' % interface] - cmds.append(self.command_builder('vrf forwarding', value=vrf_name, - default=default, disable=disable)) + if self.version_id >= '4.23': + cmds.append(self.command_builder('vrf', value=vrf_name, + default=default, disable=disable)) + else: + cmds.append(self.command_builder('vrf forwarding', value=vrf_name, + default=default, disable=disable)) return self.configure(cmds) diff --git a/pyeapi/api/vrrp.py b/pyeapi/api/vrrp.py index 26cc2ae..0c073e9 100644 --- a/pyeapi/api/vrrp.py +++ b/pyeapi/api/vrrp.py @@ -157,20 +157,11 @@ from pyeapi.api import EntityCollection -PROPERTIES = ['primary_ip', 'primary_ipv4', - 'priority', 'priority_level', - 'description', 'session_description', - 'secondary_ip', 'secondary_ipv4', - 'ip_version', 'ipv4_version', - 'enable', - 'timers_advertise', 'advertisement_interval', - 'mac_addr_adv_interval', - 'preempt', - 'preempt_delay_min', - 'preempt_delay_reload', - 'delay_reload', 'timers_delay_reload', - 'track', 'tracked_object', - 'bfd_ip'] +PROPERTIES = ['primary_ip', 'priority', 'description', 'secondary_ip', + 'ip_version', 'enable', 'timers_advertise', + 'mac_addr_adv_interval', 'preempt', + 'preempt_delay_min', 'preempt_delay_reload', + 'delay_reload', 'track', 'bfd_ip'] class Vrrp(EntityCollection): @@ -218,26 +209,18 @@ def get(self, name): # Parse the vrrp configuration for the vrid(s) in the list subd.update(self._parse_delay_reload(config, vrid)) - subd.update(self._parse_timers_delay_reload(config, vrid)) - subd.update(self._parse_advertisement_interval(config, vrid)) subd.update(self._parse_description(config, vrid)) - subd.update(self._parse_session_description(config, vrid)) subd.update(self._parse_enable(config, vrid)) subd.update(self._parse_ip_version(config, vrid)) - subd.update(self._parse_ipv4_version(config, vrid)) subd.update(self._parse_mac_addr_adv_interval(config, vrid)) subd.update(self._parse_preempt(config, vrid)) subd.update(self._parse_preempt_delay_min(config, vrid)) subd.update(self._parse_preempt_delay_reload(config, vrid)) subd.update(self._parse_primary_ip(config, vrid)) - subd.update(self._parse_primary_ipv4(config, vrid)) subd.update(self._parse_priority(config, vrid)) - subd.update(self._parse_priority_level(config, vrid)) subd.update(self._parse_secondary_ip(config, vrid)) - subd.update(self._parse_secondary_ipv4(config, vrid)) subd.update(self._parse_timers_advertise(config, vrid)) subd.update(self._parse_track(config, vrid)) - subd.update(self._parse_tracked_object(config, vrid)) subd.update(self._parse_bfd_ip(config, vrid)) result.update({int(vrid): subd}) @@ -268,53 +251,44 @@ def getall(self): return vrrps def _parse_enable(self, config, vrid): - match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s shutdown$' % vrid, config, re.M) if match: return dict(enable=False) return dict(enable=True) def _parse_primary_ip(self, config, vrid): - match = re.search(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+)$' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+)$' % + vrid, config, re.M) value = match.group(1) if match else None return dict(primary_ip=value) - def _parse_primary_ipv4(self, config, vrid): - match = re.search(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+)$' % - vrid, config, re.M) - value = match.group(1) if match else None - return dict(primary_ipv4=value) - - def _parse_primary_ipv6(self, config, vrid): - match = re.search(r'^\s+vrrp %s ' - r'ipv6 (^(?:[A-F0-9]{1,4}:){7}[A-F0-9]{1,4})$' % - vrid, config, re.M) - value = match.group(1) if match else None - return dict(primary_ipv6=value) - def _parse_priority(self, config, vrid): - match = re.search(r'^\s+vrrp %s priority (\d+)$' % vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s priority-level (\d+)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s priority (\d+)$' % + vrid, config, re.M) value = int(match.group(1)) if match else None return dict(priority=value) - def _parse_priority_level(self, config, vrid): - match = re.search(r'^\s+vrrp %s ' - r'priority-level (\d+)$' % vrid, config, re.M) - value = int(match.group(1)) if match else None - return dict(priority_level=value) - def _parse_timers_advertise(self, config, vrid): - match = re.search(r'^\s+vrrp %s timers advertise (\d+)$' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s advertisement interval (\d+)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s timers advertise (\d+)$' % + vrid, config, re.M) value = int(match.group(1)) if match else None return dict(timers_advertise=value) - def _parse_advertisement_interval(self, config, vrid): - match = re.search(r'^\s+vrrp %s advertisement interval (\d+)$' % - vrid, config, re.M) - value = int(match.group(1)) if match else None - return dict(advertisement_interval=value) - def _parse_preempt(self, config, vrid): match = re.search(r'^\s+vrrp %s preempt$' % vrid, config, re.M) if match: @@ -322,31 +296,26 @@ def _parse_preempt(self, config, vrid): return dict(preempt=False) def _parse_secondary_ip(self, config, vrid): - matches = re.findall(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+) ' - r'secondary$' % vrid, config, re.M) + if self.version_id >= '4.21.3': + matches = re.findall(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+) ' + r'secondary$' % vrid, config, re.M) + else: + matches = re.findall(r'^\s+vrrp %s ip (\d+\.\d+\.\d+\.\d+) ' + r'secondary$' % vrid, config, re.M) value = matches if matches else [] return dict(secondary_ip=value) - def _parse_secondary_ipv4(self, config, vrid): - matches = re.findall(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+) ' - r'secondary$' % vrid, config, re.M) - value = matches if matches else [] - return dict(secondary_ipv4=value) - def _parse_description(self, config, vrid): - match = re.search(r'^\s+vrrp %s description(.*)$' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s session description(.*)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s description(.*)$' % + vrid, config, re.M) if match: return dict(description=match.group(1).lstrip()) return dict(description='') - def _parse_session_description(self, config, vrid): - match = re.search(r'^\s+vrrp %s session description(.*)$' % - vrid, config, re.M) - if match: - return dict(session_description=match.group(1).lstrip()) - return dict(session_description='') - def _parse_mac_addr_adv_interval(self, config, vrid): match = re.search(r'^\s+vrrp %s mac-address advertisement-interval ' r'(\d+)$' % vrid, config, re.M) @@ -374,33 +343,34 @@ def _parse_bfd_ip(self, config, vrid): return dict(bfd_ip='') def _parse_ip_version(self, config, vrid): - match = re.search(r'^\s+vrrp %s ip version (\d+)$' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s ipv4 version (\d+)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s ip version (\d+)$' % + vrid, config, re.M) value = int(match.group(1)) if match else None return dict(ip_version=value) - def _parse_ipv4_version(self, config, vrid): - match = re.search(r'^\s+vrrp %s ipv4 version (\d+)$' % - vrid, config, re.M) - value = int(match.group(1)) if match else None - return dict(ipv4_version=value) - def _parse_delay_reload(self, config, vrid): - match = re.search(r'^\s+vrrp %s delay reload (\d+)$' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + match = re.search(r'^\s+vrrp %s timers delay reload (\d+)$' % + vrid, config, re.M) + else: + match = re.search(r'^\s+vrrp %s delay reload (\d+)$' % + vrid, config, re.M) value = int(match.group(1)) if match else None return dict(delay_reload=value) - def _parse_timers_delay_reload(self, config, vrid): - match = re.search(r'^\s+vrrp %s timers delay reload (\d+)$' % - vrid, config, re.M) - value = int(match.group(1)) if match else None - return dict(timers_delay_reload=value) - def _parse_track(self, config, vrid): - matches = re.findall(r'^\s+vrrp %s track (\S+) ' - r'(decrement|shutdown)(?:( \d+$|$))' % - vrid, config, re.M) + if self.version_id >= '4.21.3': + matches = re.findall(r'^\s+vrrp %s tracked-object (\S+) ' + r'(decrement|shutdown)(?:( \d+$|$))' % + vrid, config, re.M) + else: + matches = re.findall(r'^\s+vrrp %s track (\S+) ' + r'(decrement|shutdown)(?:( \d+$|$))' % + vrid, config, re.M) value = [] for match in matches: tr_obj = match[0] @@ -418,27 +388,6 @@ def _parse_track(self, config, vrid): track_list = sorted(value, key=lambda k: (k['name'], k['action'])) return dict(track=track_list) - def _parse_tracked_object(self, config, vrid): - matches = re.findall(r'^\s+vrrp %s tracked-object (\S+) ' - r'(decrement|shutdown)(?:( \d+$|$))' % - vrid, config, re.M) - value = [] - for match in matches: - tr_obj = match[0] - action = match[1] - amount = None if match[2] == '' else int(match[2]) - entry = { - 'name': tr_obj, - 'action': action, - } - if amount: - entry.update({'amount': amount}) - value.append(entry) - - # Return the list, sorted for easier comparison - track_list = sorted(value, key=lambda k: (k['name'], k['action'])) - return dict(tracked_object=track_list) - def create(self, interface, vrid, **kwargs): """Creates a vrrp instance from an interface @@ -529,9 +478,15 @@ def set_enable(self, name, vrid, value=False, run=True): """ if value is False: - cmd = "vrrp %d disabled" % vrid + if self.version_id >= '4.21.3': + cmd = "vrrp %d disabled" % vrid + else: + cmd = "vrrp %d shutdown" % vrid elif value is True: - cmd = "no vrrp %d disabled" % vrid + if self.version_id >= '4.21.3': + cmd = "no vrrp %d disabled" % vrid + else: + cmd = "no vrrp %d shutdown" % vrid else: raise ValueError("vrrp property 'enable' must be " "True or False") @@ -572,13 +527,22 @@ def set_primary_ip(self, name, vrid, value=None, disable=False, if default is True: vrrps = self.get(name) primary_ip = vrrps[vrid]['primary_ip'] - cmd = "default vrrp %d ip %s" % (vrid, primary_ip) + if self.version_id >= '4.21.3': + cmd = "default vrrp %d ipv4 %s" % (vrid, primary_ip) + else: + cmd = "default vrrp %d ip %s" % (vrid, primary_ip) elif disable is True or value is None: vrrps = self.get(name) primary_ip = vrrps[vrid]['primary_ip'] - cmd = "no vrrp %d ip %s" % (vrid, primary_ip) + if self.version_id >= '4.21.3': + cmd = "no vrrp %d ipv4 %s" % (vrid, primary_ip) + else: + cmd = "no vrrp %d ip %s" % (vrid, primary_ip) elif re.match(r'^\d+\.\d+\.\d+\.\d+$', str(value)): - cmd = "vrrp %d ip %s" % (vrid, value) + if self.version_id >= '4.21.3': + cmd = "vrrp %d ipv4 %s" % (vrid, value) + else: + cmd = "vrrp %d ip %s" % (vrid, value) else: raise ValueError("vrrp property 'primary_ip' must be " "a properly formatted IP address") @@ -594,57 +558,9 @@ def set_primary_ip(self, name, vrid, value=None, disable=False, # Otherwise return the formatted command return cmd - def set_primary_ipv4(self, name, vrid, - value=None, disable=False, - default=False, run=True): - """Set the primary_ipv4 property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (string): IP address to be set. - disable (boolean): Unset primary ip if True. - default (boolean): Set primary ip to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - if default is True: - vrrps = self.get(name) - primary_ipv4 = vrrps[vrid]['primary_ipv4'] - cmd = "default vrrp %d ipv4 %s" % (vrid, primary_ipv4) - elif disable is True or value is None: - vrrps = self.get(name) - primary_ipv4 = vrrps[vrid]['primary_ipv4'] - cmd = "no vrrp %d ipv4 %s" % (vrid, primary_ipv4) - elif re.match(r'^\d+\.\d+\.\d+\.\d+$', str(value)): - cmd = "vrrp %d ipv4 %s" % (vrid, value) - else: - raise ValueError("vrrp property 'primary_ipv4' must be " - "a properly formatted IP address") - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - def set_priority(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the priority property of the vrrp + """Set the primary_ip property of the vrrp Args: name (string): The interface to configure. @@ -668,51 +584,14 @@ def set_priority(self, name, vrid, value=None, disable=False, if not str(value).isdigit() or value < 1 or value > 254: raise ValueError("vrrp property 'priority' must be " "an integer in the range 1-254") - - cmd = self.command_builder('vrrp %d priority' % vrid, value=value, - default=default, disable=disable) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_priority_level(self, name, vrid, value=None, disable=False, - default=False, run=True): - """Set the priority_level property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Priority to assign to the vrrp. - disable (boolean): Unset priority if True. - default (boolean): Set priority to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - if not default and not disable: - if not str(value).isdigit() or value < 1 or value > 254: - raise ValueError("vrrp property 'priority_level' must be " - "an integer in the range 1-254") - - cmd = self.command_builder('vrrp %d priority-level' % vrid, - value=value, - default=default, disable=disable) + if self.version_id >= '4.21.3': + cmd = self.command_builder('vrrp %d priority-level' % + vrid, value=value, + default=default, disable=disable) + else: + cmd = self.command_builder('vrrp %d priority' % + vrid, value=value, + default=default, disable=disable) # Run the command if requested if run: @@ -746,46 +625,14 @@ def set_description(self, name, vrid, value=None, disable=False, be passed to the node """ - - cmd = self.command_builder('vrrp %d description' % vrid, value=value, - default=default, disable=disable) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_session_description(self, name, vrid, value=None, disable=False, - default=False, run=True): - """Set the session_description property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (string): Session_description to assign to the vrrp. - disable (boolean): Unset session_description if True. - default (boolean): Set session_description to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - cmd = self.command_builder('vrrp %d session description' % vrid, - value=value, - default=default, disable=disable) + if self.version_id >= '4.21.3': + cmd = self.command_builder('vrrp %d session description' % + vrid, value=value, + default=default, disable=disable) + else: + cmd = self.command_builder('vrrp %d description' % + vrid, value=value, + default=default, disable=disable) # Run the command if requested if run: @@ -823,49 +670,14 @@ def set_ip_version(self, name, vrid, value=None, disable=False, if not default and not disable: if value not in (2, 3): raise ValueError("vrrp property 'ip_version' must be 2 or 3") - - cmd = self.command_builder('vrrp %d ip version' % vrid, value=value, - default=default, disable=disable) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_ipv4_version(self, name, vrid, value=None, disable=False, - default=False, run=True): - """Set the ipv4_version property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (integer): IPv4 version to assign to the vrrp. - disable (boolean): Unset ipv4_version if True. - default (boolean): Set ipv4_version to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - if not default and not disable: - if value not in (2, 3): - raise ValueError("vrrp property 'ipv4_version' must be 2 or 3") - - cmd = self.command_builder('vrrp %d ipv4 version' % vrid, value=value, - default=default, disable=disable) + if self.version_id >= '4.21.3': + cmd = self.command_builder('vrrp %d ipv4 version' % + vrid, value=value, + default=default, disable=disable) + else: + cmd = self.command_builder('vrrp %d ip version' % + vrid, value=value, + default=default, disable=disable) # Run the command if requested if run: @@ -908,7 +720,7 @@ def set_secondary_ips(self, name, vrid, secondary_ips, run=True): cmds = [] - # Get the current set of secondary ips defined for the vrrp + # Get the current set of tracks defined for the vrrp curr_sec_ips = [] vrrps = self.get(name) if vrrps and vrid in vrrps: @@ -930,81 +742,16 @@ def set_secondary_ips(self, name, vrid, secondary_ips, run=True): # Build the commands to add and remove the secondary ip addresses for sec_ip in remove: - cmds.append("no vrrp %d ip %s secondary" % (vrid, sec_ip)) - - for sec_ip in add: - cmds.append("vrrp %d ip %s secondary" % (vrid, sec_ip)) - - cmds = sorted(cmds) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmds) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmds - - def set_secondary_ipv4s(self, name, vrid, secondary_ipv4s, run=True): - """Configure the secondary_ipv4 property of the vrrp - - Notes: - set_secondary_ipv4s takes a list of secondary ipv4 addresses - which are to be set on the virtal router. An empty list will - remove any existing secondary ipv4 addresses from the vrrp. - A list containing addresses will configure the virtual router - with only the addresses specified in the list - any existing - addresses not included in the list will be removed. - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - secondary_ips (list): A list of secondary ipv4 addresses to - be assigned to the virtual router. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - cmds = [] - - # Get the current set of secondary ipv4s defined for the vrrp - curr_sec_ips = [] - vrrps = self.get(name) - if vrrps and vrid in vrrps: - curr_sec_ips = vrrps[vrid]['secondary_ipv4'] - - # Validate the list of ip addresses - for sec_ip in secondary_ipv4s: - if type(sec_ip) is not str or \ - not re.match(r'^\d+\.\d+\.\d+\.\d+$', sec_ip): - raise ValueError("vrrp property 'secondary_ipv4' " - "must be a list " - "of properly formatted ip address strings") - - intersection = list(set(curr_sec_ips) & set(secondary_ipv4s)) - - # Delete the intersection from both lists to determine which - # addresses need to be added or removed from the vrrp - remove = list(set(curr_sec_ips) - set(intersection)) - add = list(set(secondary_ipv4s) - set(intersection)) - - # Build the commands to add and remove the secondary ip addresses - for sec_ip in remove: - cmds.append("no vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + if self.version_id >= '4.21.3': + cmds.append("no vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + else: + cmds.append("no vrrp %d ip %s secondary" % (vrid, sec_ip)) for sec_ip in add: - cmds.append("vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + if self.version_id >= '4.21.3': + cmds.append("vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) + else: + cmds.append("vrrp %d ip %s secondary" % (vrid, sec_ip)) cmds = sorted(cmds) @@ -1021,7 +768,7 @@ def set_secondary_ipv4s(self, name, vrid, secondary_ipv4s, run=True): def set_timers_advertise(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the timers_advertise property of the vrrp + """Set the ip_version property of the vrrp Args: name (string): The interface to configure. @@ -1043,56 +790,18 @@ def set_timers_advertise(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 255: - raise ValueError("vrrp property 'timers_advertise' must be " - "in the range 1-255") - - cmd = self.command_builder('vrrp %d timers advertise' % vrid, - value=value, default=default, - disable=disable) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_advertisement_interval(self, name, vrid, value=None, disable=False, - default=False, run=True): - """Set the advertisement_interval property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Advertisement interval value - to assign to the vrrp. - disable (boolean): Unset interval advertise if True. - default (boolean): Set interval advertise to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - if not default and not disable: - if not int(value) or int(value) < 1 or int(value) > 255: - raise ValueError("vrrp property " - "'advertisement_interval' must be " + raise ValueError("vrrp property 'timers_advertise' must be" "in the range 1-255") - - cmd = self.command_builder('vrrp %d advertisement interval' % vrid, - value=value, default=default, - disable=disable) + if self.version_id >= '4.21.3': + cmd = self.command_builder('vrrp %d advertisement interval' % + vrid, + value=value, default=default, + disable=disable) + else: + cmd = self.command_builder('vrrp %d timers advertise' % + vrid, + value=value, default=default, + disable=disable) # Run the command if requested if run: @@ -1216,7 +925,7 @@ def set_preempt_delay_min(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'preempt_delay_min' must be " + raise ValueError("vrrp property 'preempt_delay_min' must be" "in the range 0-3600 %r" % value) cmd = self.command_builder('vrrp %d preempt delay minimum' @@ -1258,8 +967,8 @@ def set_preempt_delay_reload(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'preempt_delay_reload' " - "must be in the range 0-3600 %r" % value) + raise ValueError("vrrp property 'preempt_delay_reload' must be" + "in the range 0-3600 %r" % value) cmd = self.command_builder('vrrp %d preempt delay reload' % vrid, value=value, default=default, @@ -1278,55 +987,14 @@ def set_preempt_delay_reload(self, name, vrid, value=None, disable=False, def set_delay_reload(self, name, vrid, value=None, disable=False, default=False, run=True): - """Set the delay_reload property of the vrrp - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Delay reload value to set on the vrrp. - disable (boolean): Unset delay reload if True. - default (boolean): Set delay reload to default if True. - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - if not default and not disable: - if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'delay_reload' must be " - "in the range 0-3600 %r" % value) - - cmd = self.command_builder('vrrp %d delay reload' % vrid, value=value, - default=default, disable=disable) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmd) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmd - - def set_timers_delay_reload(self, name, vrid, value=None, disable=False, - default=False, run=True): - """Set the timers_delay_reload property of the vrrp + """Set the preempt_delay_min property of the vrrp Args: name (string): The interface to configure. vrid (integer): The vrid number for the vrrp to be managed. - value (integer): Timers delay_reload value to set on the vrrp. + value (integer): Preempt delay reload value to set on the vrrp. disable (boolean): Unset preempt delay reload if True. - default (boolean): Set timers delay reload to default if True. + default (boolean): Set preempt delay reload to default if True. run (boolean): Set to True to execute the command, False to return a string with the formatted command. @@ -1341,12 +1009,16 @@ def set_timers_delay_reload(self, name, vrid, value=None, disable=False, if not default and not disable: if not int(value) or int(value) < 1 or int(value) > 3600: - raise ValueError("vrrp property 'timers_delay_reload' must be " + raise ValueError("vrrp property 'delay_reload' must be" "in the range 0-3600 %r" % value) - - cmd = self.command_builder('vrrp %d timers delay reload' - % vrid, value=value, - default=default, disable=disable) + if self.version_id >= '4.21.3': + cmd = self.command_builder('vrrp %d timers delay reload' % + vrid, value=value, + default=default, disable=disable) + else: + cmd = self.command_builder('vrrp %d delay reload' % + vrid, value=value, + default=default, disable=disable) # Run the command if requested if run: @@ -1480,8 +1152,12 @@ def set_tracks(self, name, vrid, tracks, run=True): if amount == unset: amount = '' - t_cmd = ("no vrrp %d track %s %s %s" - % (vrid, tr_obj, action, amount)) + if self.version_id >= '4.21.3': + t_cmd = ("no vrrp %d tracked-object %s %s %s" + % (vrid, tr_obj, action, amount)) + else: + t_cmd = ("no vrrp %d track %s %s %s" + % (vrid, tr_obj, action, amount)) cmds.append(t_cmd.rstrip()) for track in add: @@ -1492,162 +1168,12 @@ def set_tracks(self, name, vrid, tracks, run=True): if amount == unset: amount = '' - t_cmd = ("vrrp %d track %s %s %s" - % (vrid, tr_obj, action, amount)) - cmds.append(t_cmd.rstrip()) - - cmds = sorted(cmds) - - # Run the command if requested - if run: - result = self.configure_interface(name, cmds) - # And verify the command succeeded - if result is False: - return self.error - return result - - # Otherwise return the formatted command - return cmds - - def set_tracked_objects(self, name, vrid, tracked_objects, run=True): - """Configure the tracked_object property of the vrrp - - Notes: - set_tracked_objects takes a list of tracked objects which are - to be set on the virtual router. An empty list will remove - any existing tracked objects from the vrrp. A list containing - tracked_object entries configures the virtual router to track - only the - objects specified in the list - any existing tracked objects - on the vrrp not included in the list will be removed. - - Args: - name (string): The interface to configure. - vrid (integer): The vrid number for the vrrp to be managed. - tracked_objects (list): A list of track definition dictionaries. - Each dictionary is a definition of a tracked object in one - of the two formats:: - - {'name': tracked_object_name, - 'action': 'shutdown'} - {'name': tracked_object_name, - 'action': 'decrement', - 'amount': amount_of_decrement} - - run (boolean): Set to True to execute the command, False to - return a string with the formatted command. - - Returns: - If run is True, returns True if the command executed successfully, - error if failure. - - If run is False, returns the formatted command string which can - be passed to the node - - """ - - cmds = [] - - # Get the current set of tracked_objects defined for the vrrp - curr_tracks = [] - vrrps = self.get(name) - if vrrps and vrid in vrrps: - curr_tracks = vrrps[vrid]['tracked_object'] - - # Determine which tracked objects are in both lists using - # sets of temporary strings built from the track specifications - unset = '_none_' - tracks_set = [] - for track in tracked_objects: - keys = track.keys() - - # Validate no extraneous keys in track definition - err_keys = set(keys).difference(('name', 'action', 'amount')) - if err_keys: - err_keys = ', '.join(err_keys) - raise ValueError("Error found in vrrp property " - "'tracked_object': " - "unknown key(s) '%s' found. Valid keys are " - "name, action, and amount" % err_keys) - - # Validate required keys in track definition - if not set(keys).issuperset(('name', 'action')): - raise ValueError("Error found in vrrp property " - "'tracked_object': " - "track definition must contain 'name' and " - "'action' keys") - - tr_obj = track['name'] - action = track['action'] - amount = track['amount'] if 'amount' in track else unset - - # Validate values in track definition - error = False - if action not in ('shutdown', 'decrement'): - error = True - if action == 'shutdown' and amount != unset: - error = True - if amount != unset and not str(amount).isdigit(): - error = True - if error: - raise ValueError("Error found in vrrp property 'track'. " - "See documentation for format specification.") - - tid = "%s %s %s" % (tr_obj, action, amount) - tracks_set.append(tid) - - curr_set = [] - for track in curr_tracks: - tr_obj = track['name'] - action = track['action'] - amount = track['amount'] if 'amount' in track else unset - - # Validate track definition - error = False - if action not in ('shutdown', 'decrement'): - error = True - if action == 'shutdown' and amount != unset: - error = True - if amount != unset and not str(amount).isdigit(): - error = True - if error: - raise ValueError("Error found in vrrp property " - "'tracked_object'. " - "See documentation for format specification.") - - tid = "%s %s %s" % (tr_obj, action, amount) - curr_set.append(tid) - - intersection = list(set(tracks_set) & set(curr_set)) - - # Delete the intersection from both lists to determine which - # track definitions need to be added or removed from the vrrp - remove = list(set(curr_set) - set(intersection)) - add = list(set(tracks_set) - set(intersection)) - - # Build the commands to add and remove the tracked objects - for track in remove: - match = re.match(r'(\S+)\s+(\S+)\s+(\S+)', track) - if match: - (tr_obj, action, amount) = \ - (match.group(1), match.group(2), match.group(3)) - - if amount == unset: - amount = '' - t_cmd = ("no vrrp %d tracked-object %s %s %s" - % (vrid, tr_obj, action, amount)) - cmds.append(t_cmd.rstrip()) - - for track in add: - match = re.match(r'(\S+)\s+(\S+)\s+(\S+)', track) - if match: - (tr_obj, action, amount) = \ - (match.group(1), match.group(2), match.group(3)) - - if amount == unset: - amount = '' - t_cmd = ("vrrp %d tracked-object %s %s %s" - % (vrid, tr_obj, action, amount)) + if self.version_id >= '4.21.3': + t_cmd = ("vrrp %d tracked-object %s %s %s" + % (vrid, tr_obj, action, amount)) + else: + t_cmd = ("vrrp %d track %s %s %s" + % (vrid, tr_obj, action, amount)) cmds.append(t_cmd.rstrip()) cmds = sorted(cmds) @@ -1730,19 +1256,6 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) - primary_ipv4 = vrconf.get('primary_ipv4', '__NONE__') - if primary_ipv4 != '__NONE__': - if primary_ipv4 in ('no', None): - cmd = self.set_primary_ipv4(name, vrid, value=None, - disable=True, run=False) - elif primary_ipv4 == 'default': - cmd = self.set_primary_ipv4(name, vrid, value=None, - default=True, run=False) - else: - cmd = self.set_primary_ipv4(name, vrid, value=primary_ipv4, - run=False) - commands.append(cmd) - priority = vrconf.get('priority', '__NONE__') if priority != '__NONE__': if priority in ('no', None): @@ -1752,63 +1265,22 @@ def _vrrp_set(self, name, vrid, **kwargs): cmd = self.set_priority(name, vrid, value=priority, default=True, run=False) else: - cmd = self.set_priority(name, vrid, - value=priority, run=False) - commands.append(cmd) - - priority_level = vrconf.get('priority_level', '__NONE__') - if priority_level != '__NONE__': - if priority_level in ('no', None): - cmd = self.set_priority_level(name, vrid, - value=priority_level, - disable=True, run=False) - elif priority_level == 'default': - cmd = self.set_priority_level(name, vrid, - value=priority_level, - default=True, run=False) - else: - cmd = self.set_priority_level(name, vrid, - value=priority_level, run=False) + cmd = self.set_priority(name, vrid, value=priority, run=False) commands.append(cmd) description = vrconf.get('description', '__NONE__') if description != '__NONE__': if description in ('no', None): - cmd = self.set_description(name, - vrid, - value=description, + cmd = self.set_description(name, vrid, value=description, disable=True, run=False) elif description == 'default': - cmd = self.set_description(name, - vrid, - value=description, + cmd = self.set_description(name, vrid, value=description, default=True, run=False) else: - cmd = self.set_description(name, - vrid, - value=description, + cmd = self.set_description(name, vrid, value=description, run=False) commands.append(cmd) - session_description = vrconf.get('session_description', '__NONE__') - if session_description != '__NONE__': - if session_description in ('no', None): - cmd = self.set_session_description(name, - vrid, - value=session_description, - disable=True, run=False) - elif session_description == 'default': - cmd = self.set_session_description(name, - vrid, - value=session_description, - default=True, run=False) - else: - cmd = self.set_session_description(name, - vrid, - value=session_description, - run=False) - commands.append(cmd) - ip_version = vrconf.get('ip_version', '__NONE__') if ip_version != '__NONE__': if ip_version in ('no', None): @@ -1822,32 +1294,12 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) - ipv4_version = vrconf.get('ipv4_version', '__NONE__') - if ipv4_version != '__NONE__': - if ipv4_version in ('no', None): - cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, - disable=True, run=False) - elif ipv4_version == 'default': - cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, - default=True, run=False) - else: - cmd = self.set_ipv4_version(name, vrid, value=ipv4_version, - run=False) - commands.append(cmd) - secondary_ip = vrconf.get('secondary_ip', '__NONE__') if secondary_ip != '__NONE__': cmds = self.set_secondary_ips(name, vrid, secondary_ip, run=False) for cmd in cmds: commands.append(cmd) - secondary_ipv4 = vrconf.get('secondary_ipv4', '__NONE__') - if secondary_ipv4 != '__NONE__': - cmds = self.set_secondary_ipv4s(name, vrid, - secondary_ipv4, run=False) - for cmd in cmds: - commands.append(cmd) - timers_advertise = vrconf.get('timers_advertise', '__NONE__') if timers_advertise != '__NONE__': if timers_advertise in ('no', None): @@ -1864,23 +1316,6 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) - advertisement_interval = vrconf.get('advertisement_interval', - '__NONE__') - if advertisement_interval != '__NONE__': - if advertisement_interval in ('no', None): - cmd = self.set_advertisement_interval( - name, vrid, value=advertisement_interval, - disable=True, run=False) - elif advertisement_interval == 'default': - cmd = self.set_advertisement_interval( - name, vrid, value=advertisement_interval, - default=True, run=False) - else: - cmd = self.set_advertisement_interval( - name, vrid, value=advertisement_interval, - run=False) - commands.append(cmd) - mac_addr_adv_interval = \ vrconf.get('mac_addr_adv_interval', '__NONE__') if mac_addr_adv_interval != '__NONE__': @@ -1958,33 +1393,11 @@ def _vrrp_set(self, name, vrid, **kwargs): run=False) commands.append(cmd) - timers_delay_reload = vrconf.get('timers_delay_reload', '__NONE__') - if timers_delay_reload != '__NONE__': - if timers_delay_reload in ('no', None): - cmd = self.set_timers_delay_reload(name, vrid, - value=timers_delay_reload, - disable=True, run=False) - elif timers_delay_reload == 'default': - cmd = self.set_timers_delay_reload(name, vrid, - value=timers_delay_reload, - default=True, run=False) - else: - cmd = self.set_timers_delay_reload(name, vrid, - value=timers_delay_reload, - run=False) - commands.append(cmd) - track = vrconf.get('track', '__NONE__') if track != '__NONE__': cmds = self.set_tracks(name, vrid, track, run=False) for cmd in cmds: commands.append(cmd) - tracked_object = vrconf.get('tracked_object', '__NONE__') - if tracked_object != '__NONE__': - cmds = self.set_tracked_objects(name, vrid, - tracked_object, run=False) - for cmd in cmds: - commands.append(cmd) bfd_ip = vrconf.get('bfd_ip', '__NONE__') if bfd_ip != '__NONE__': @@ -2022,41 +1435,22 @@ def vrconf_format(self, vrconfig): # primary_ip: default, no, None results in address of 0.0.0.0 if fixed['primary_ip'] in ('no', 'default', None): fixed['primary_ip'] = '0.0.0.0' - # primary_ipv4: default, no, None results in address of 0.0.0.0 - if fixed['primary_ipv4'] in ('no', 'default', None): - fixed['primary_ipv4'] = '0.0.0.0' # priority: default, no, None results in priority of 100 if fixed['priority'] in ('no', 'default', None): fixed['priority'] = 100 - # priority-level: default, no, None results in priority of 100 - if fixed['priority_level'] in ('no', 'default', None): - fixed['priority_level'] = 100 # description: default, no, None results in None if fixed['description'] in ('no', 'default', None): fixed['description'] = None - # session_description: default, no, None results in None - if fixed['session_description'] in ('no', 'default', None): - fixed['session_description'] = None # secondary_ip: list should be exactly what is required, # just sort it for easier comparison if 'secondary_ip' in fixed: fixed['secondary_ip'] = sorted(fixed['secondary_ip']) - # secondary_ipv4: list should be exactly what is required, - # just sort it for easier comparison - if 'secondary_ipv4' in fixed: - fixed['secondary_ipv4'] = sorted(fixed['secondary_ipv4']) # ip_version: default, no, None results in value of 2 if fixed['ip_version'] in ('no', 'default', None): fixed['ip_version'] = 2 - # ipv4_version: default, no, None results in value of 2 - if fixed['ipv4_version'] in ('no', 'default', None): - fixed['ipv4_version'] = 2 # timers_advertise: default, no, None results in value of 1 if fixed['timers_advertise'] in ('no', 'default', None): fixed['timers_advertise'] = 1 - # advertisement_interval: default, no, None results in value of 1 - if fixed['advertisement_interval'] in ('no', 'default', None): - fixed['advertisement_interval'] = 1 # mac_address_advertisement_interaval: # default, no, None results in value of 30 if fixed['mac_addr_adv_interval'] in \ @@ -2074,18 +1468,11 @@ def vrconf_format(self, vrconfig): # delay_reload: default, no, None results in value of 0 if fixed['delay_reload'] in ('no', 'default', None): fixed['delay_reload'] = 0 - # timers_delay_reload: default, no, None results in value of 0 - if fixed['timers_delay_reload'] in ('no', 'default', None): - fixed['timers_delay_reload'] = 0 # track: list should be exactly what is required, # just sort it for easier comparison if 'track' in fixed: fixed['track'] = \ sorted(fixed['track'], key=lambda k: (k['name'], k['action'])) - if 'tracked_object' in fixed: - fixed['tracked_object'] = \ - sorted(fixed['tracked_object'], - key=lambda k: (k['name'], k['action'])) # bfd_ip: default, no, None results in '' if fixed['bfd_ip'] in ('no', 'default', None): fixed['bfd_ip'] = '' diff --git a/pyeapi/client.py b/pyeapi/client.py index e8c834e..523e60d 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -470,6 +470,7 @@ def __init__(self, connection, **kwargs): self._startup_config = None self._version = None self._version_number = None + self._version_id = None self._model = None self._enablepwd = kwargs.get('enablepwd') @@ -516,6 +517,14 @@ def version_number(self): self._get_version_properties() return self._version_number + @property + def version_id(self): + if self._version_id: + return self._version_id + output = self.enable('show version') + self._version_id = output[0]['result']['version'].split()[0][:-1] + return self._version_id + @property def model(self): if self._model: diff --git a/test/fixtures/dut.conf b/test/fixtures/dut.conf index 6cf2160..b72ccc4 100644 --- a/test/fixtures/dut.conf +++ b/test/fixtures/dut.conf @@ -1,5 +1,5 @@ [connection:veos01] -host: 192.168.0.10 +host: 10.16.129.149 username: arista password: arista transport: http diff --git a/test/fixtures/eapi.conf b/test/fixtures/eapi.conf index b1096f3..598e483 100644 --- a/test/fixtures/eapi.conf +++ b/test/fixtures/eapi.conf @@ -1,5 +1,5 @@ [connection:test1] -host: 192.168.0.10 +host: 10.16.129.149 username: arista password: arista enablepwd: enablepwd diff --git a/test/fixtures/eapi.conf.yaml b/test/fixtures/eapi.conf.yaml index 9102805..4231aff 100644 --- a/test/fixtures/eapi.conf.yaml +++ b/test/fixtures/eapi.conf.yaml @@ -3,4 +3,4 @@ :password: admin :use_ssl: true :port: 199 -:hostname: bogus +:hostname: bogus \ No newline at end of file diff --git a/test/fixtures/running_config.vrrp b/test/fixtures/running_config.vrrp index ff3e6e6..545c5ea 100644 --- a/test/fixtures/running_config.vrrp +++ b/test/fixtures/running_config.vrrp @@ -245,29 +245,22 @@ interface Port-Channel10 no switchport tap default group no switchport tool group no switchport tool dot1q remove outer - vrrp 10 priority-level 150 vrrp 10 priority 150 vrrp 10 timers advertise 1 - vrrp 10 advertisement interval 1 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 - vrrp 10 timers delay reload 0 vrrp 10 delay reload 0 no vrrp 10 authentication - vrrp 10 ipv4 10.10.5.10 - vrrp 10 ipv4 10.10.5.20 secondary - vrrp 10 ip 10.10.5.11 - vrrp 10 ip 10.10.5.21 secondary + vrrp 10 ip 10.10.5.10 + vrrp 10 ip 10.10.5.20 secondary vrrp 10 ipv6 :: vrrp 10 description vrrp 10 on Port-Channel10 - vrrp 10 session description vrrp 10 on Port-Channel10 - no vrrp 10 disabled + no vrrp 10 shutdown no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 - vrrp 10 ipv4 version 2 ! interface Ethernet1 no description @@ -403,27 +396,21 @@ interface Ethernet1 no switchport tap default group no switchport tool group no switchport tool dot1q remove outer - vrrp 10 priority 100 - vrrp 10 priority-level 175 + vrrp 10 priority 175 vrrp 10 timers advertise 1 - vrrp 10 advertisement interval 1 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 - vrrp 10 timers delay reload 0 vrrp 10 delay reload 0 no vrrp 10 authentication - vrrp 10 ip 10.10.6.11 - vrrp 10 ipv4 10.10.6.10 + vrrp 10 ip 10.10.6.10 vrrp 10 ipv6 :: - vrrp 10 session description vrrp 10 on Ethernet1 vrrp 10 description vrrp 10 on Ethernet1 - no vrrp 10 disable + no vrrp 10 shutdown no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 - vrrp 10 ipv4 version 2 ! interface Vlan50 no description @@ -485,93 +472,62 @@ interface Vlan50 no ip pim bsr-border no ip virtual address vrrp 10 priority 200 - vrrp 10 priority-level 200 - vrrp 10 advertisement interval 3 - vrrp 10 timers advertise 1 + vrrp 10 timers advertise 3 vrrp 10 mac-address advertisement-interval 30 vrrp 10 preempt vrrp 10 preempt delay minimum 0 vrrp 10 preempt delay reload 0 vrrp 10 delay reload 0 - vrrp 10 timers delay reload 0 no vrrp 10 authentication vrrp 10 ip 10.10.4.10 vrrp 10 ip 10.10.4.21 secondary vrrp 10 ip 10.10.4.22 secondary vrrp 10 ip 10.10.4.23 secondary vrrp 10 ip 10.10.4.24 secondary - vrrp 10 ipv4 10.10.4.11 - vrrp 10 ipv4 10.10.4.21 secondary - vrrp 10 ipv4 10.10.4.22 secondary - vrrp 10 ipv4 10.10.4.23 secondary - vrrp 10 ipv4 10.10.4.24 secondary vrrp 10 ipv6 :: - no vrrp 10 session description no vrrp 10 description - no vrrp 10 disabled + no vrrp 10 shutdown vrrp 10 track Ethernet1 decrement 10 vrrp 10 track Ethernet1 shutdown vrrp 10 track Ethernet2 decrement 50 vrrp 10 track Ethernet2 shutdown vrrp 10 track Ethernet11 decrement 75 vrrp 10 track Ethernet11 shutdown - vrrp 10 tracked-object Ethernet1 decrement 10 - vrrp 10 tracked-object Ethernet1 shutdown - vrrp 10 tracked-object Ethernet2 decrement 50 - vrrp 10 tracked-object Ethernet2 shutdown - vrrp 10 tracked-object Ethernet11 decrement 75 - vrrp 10 tracked-object Ethernet11 shutdown no vrrp 10 bfd ip no vrrp 10 bfd ipv6 vrrp 10 ip version 2 - vrrp 10 ipv4 version 2 vrrp 20 priority 100 - vrrp 20 priority-level 100 - vrrp 20 advertisement interval 5 - vrrp 20 timers advertise 1 + vrrp 20 timers advertise 5 vrrp 20 mac-address advertisement-interval 30 no vrrp 20 preempt vrrp 20 preempt delay minimum 0 vrrp 20 preempt delay reload 0 vrrp 20 delay reload 0 - vrrp 20 timers delay reload 0 vrrp 20 authentication text 12345 vrrp 20 ip 10.10.4.20 - vrrp 20 ipv4 10.10.4.20 vrrp 20 ipv6 :: - no vrrp 20 session description no vrrp 20 description - vrrp 20 disabled + vrrp 20 shutdown vrrp 20 track Ethernet1 shutdown vrrp 20 track Ethernet2 decrement 1 vrrp 20 track Ethernet2 shutdown - vrrp 20 tracked-object Ethernet1 shutdown - vrrp 20 tracked-object Ethernet2 decrement 1 - vrrp 20 tracked-object Ethernet2 shutdown no vrrp 20 bfd ip no vrrp 20 bfd ipv6 vrrp 20 ip version 2 - vrrp 20 ipv4 version 2 - vrrp 30 priority 100 - vrrp 30 priority-level 50 - vrrp 30 advertisement interval 1 + vrrp 30 priority 50 vrrp 30 timers advertise 1 vrrp 30 mac-address advertisement-interval 30 vrrp 30 preempt vrrp 30 preempt delay minimum 0 vrrp 30 preempt delay reload 0 vrrp 30 delay reload 0 - vrrp 30 timers delay reload 0 vrrp 30 authentication ietf-md5 key-string 7 bu1yTgzm0RDgraNS0MNkaA== vrrp 30 ip 10.10.4.30 - vrrp 30 ipv4 10.10.4.30 vrrp 30 ipv6 :: - no vrrp 30 session description no vrrp 30 description - no vrrp 30 disable + no vrrp 30 shutdown vrrp 30 bfd ip 10.10.4.33 no vrrp 30 bfd ipv6 vrrp 30 ip version 2 - vrrp 30 ipv4 version 2 -! ! +! \ No newline at end of file diff --git a/test/lib/testlib.py b/test/lib/testlib.py index 5ec9bc1..cff9f4d 100644 --- a/test/lib/testlib.py +++ b/test/lib/testlib.py @@ -34,7 +34,7 @@ import string import unittest -from mock import Mock +from mock import MagicMock as Mock from pyeapi.client import Node diff --git a/test/system/test_api_interfaces.py b/test/system/test_api_interfaces.py index 129106a..5b3ed60 100644 --- a/test/system/test_api_interfaces.py +++ b/test/system/test_api_interfaces.py @@ -226,21 +226,32 @@ def test_set_vrf(self): # Verify set_vrf returns False if no vrf by name is configured result = dut.api('interfaces').set_vrf(intf, 'test') self.assertFalse(result) - dut.config('vrf definition test') + if dut.version_number >= '4.23': + dut.config('vrf instance test') + else: + dut.config('vrf definition test') # Verify interface has vrf applied result = dut.api('interfaces').set_vrf(intf, 'test') self.assertTrue(result) config = dut.run_commands('show running-config interfaces %s' % intf, 'text') - self.assertIn('vrf forwarding test', config[0]['output']) + if dut.version_number >= '4.23': + self.assertIn('vrf test', config[0]['output']) + else: + self.assertIn('vrf forwarding test', config[0]['output']) # Verify interface has vrf removed result = dut.api('interfaces').set_vrf(intf, 'test', disable=True) self.assertTrue(result) config = dut.run_commands('show running-config interfaces %s' % intf, 'text') - self.assertNotIn('vrf forwarding test', config[0]['output']) - # Remove test vrf - dut.config('no vrf definition test') + if dut.version_number >= '4.23': + self.assertIn('vrf test', config[0]['output']) + # Remove test vrf + dut.config('no vrf instance test') + else: + self.assertIn('vrf forwarding test', config[0]['output']) + # Remove test vrf + dut.config('no vrf definition test') class TestPortchannelInterface(DutSystemTest): diff --git a/test/system/test_api_mlag.py b/test/system/test_api_mlag.py index 0ecd765..7c395c7 100644 --- a/test/system/test_api_mlag.py +++ b/test/system/test_api_mlag.py @@ -114,15 +114,6 @@ def test_set_peer_address_with_value(self): self.assertTrue(result) self.assertIn('peer-address 1.2.3.4', api.get_block('mlag configuration')) - def test_set_peer_address_heartbeat_with_value(self): - for dut in self.duts: - dut.config('default mlag configuration') - api = dut.api('mlag') - self.assertIn('no peer-address heartbeat', api.get_block('mlag configuration')) - result = dut.api('mlag').set_peer_address_heartbeat('1.2.3.4') - self.assertTrue(result) - self.assertIn('peer-address heartbeat 1.2.3.4', api.get_block('mlag configuration')) - def test_set_peer_address_with_no_value(self): for dut in self.duts: dut.config(['interface Vlan1234', 'ip address 1.2.3.1/24', diff --git a/test/system/test_api_ntp.py b/test/system/test_api_ntp.py index c33060f..341b567 100644 --- a/test/system/test_api_ntp.py +++ b/test/system/test_api_ntp.py @@ -43,14 +43,20 @@ class TestApiNtp(DutSystemTest): def test_get(self): for dut in self.duts: - dut.config(['ntp source Ethernet1', 'ntp server 99.99.1.1']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'ntp server 99.99.1.1']) + else: + dut.config(['ntp source Ethernet1', 'ntp server 99.99.1.1']) response = dut.api('ntp').get() self.assertIsNotNone(response) def test_create(self): intf = 'Ethernet1' for dut in self.duts: - dut.config(['no ntp source']) + if dut.version_number >= '4.23': + dut.config(['no ntp local-interface']) + else: + dut.config(['no ntp source']) response = dut.api('ntp').create(intf) self.assertTrue(response) response = dut.api('ntp').get() @@ -58,7 +64,10 @@ def test_create(self): def test_delete(self): for dut in self.duts: - dut.config(['ntp source Ethernet1']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1']) + else: + dut.config(['ntp source Ethernet1']) response = dut.api('ntp').delete() self.assertTrue(response) response = dut.api('ntp').get() @@ -66,7 +75,10 @@ def test_delete(self): def test_default(self): for dut in self.duts: - dut.config(['ntp source Ethernet1']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1']) + else: + dut.config(['ntp source Ethernet1']) response = dut.api('ntp').default() self.assertTrue(response) response = dut.api('ntp').get() @@ -75,7 +87,10 @@ def test_default(self): def test_set_source_interface(self): intf = 'Ethernet1' for dut in self.duts: - dut.config(['ntp source Loopback0']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Loopback0']) + else: + dut.config(['ntp source Loopback0']) response = dut.api('ntp').set_source_interface(intf) self.assertTrue(response) response = dut.api('ntp').get() @@ -84,7 +99,10 @@ def test_set_source_interface(self): def test_add_server_single(self): server = '10.10.10.35' for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp']) + else: + dut.config(['ntp source Ethernet1', 'no ntp']) response = dut.api('ntp').add_server(server) self.assertTrue(response) response = dut.api('ntp').get() @@ -95,7 +113,10 @@ def test_add_server_single(self): def test_add_server_multiple(self): servers = ['10.10.10.37', '10.10.10.36', '10.10.10.34'] for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp']) + else: + dut.config(['ntp source Ethernet1', 'no ntp']) for server in servers: response = dut.api('ntp').add_server(server) self.assertTrue(response) @@ -107,7 +128,10 @@ def test_add_server_multiple(self): def test_add_server_prefer(self): server = '10.10.10.35' for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp']) + else: + dut.config(['ntp source Ethernet1', 'no ntp']) response = dut.api('ntp').add_server(server, prefer=False) self.assertTrue(response) response = dut.api('ntp').get() @@ -120,7 +144,10 @@ def test_add_server_prefer(self): def test_add_server_invalid(self): for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp']) + else: + dut.config(['ntp source Ethernet1', 'no ntp']) with self.assertRaises(ValueError): dut.api('ntp').add_server(None) dut.api('ntp').add_server('') @@ -130,8 +157,12 @@ def test_remove_server(self): server = '10.10.10.35' servers = ['10.10.10.37', '10.10.10.36', '10.10.10.34'] for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp', - 'ntp server %s' % server]) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp', + 'ntp server %s' % server]) + else: + dut.config(['ntp source Ethernet1', 'no ntp', + 'ntp server %s' % server]) for addserver in servers: dut.config(['ntp server %s' % addserver]) response = dut.api('ntp').remove_server(server) @@ -144,7 +175,10 @@ def test_remove_server(self): def test_remove_all_servers(self): servers = ['10.10.10.37', '10.10.10.36', '10.10.10.34'] for dut in self.duts: - dut.config(['ntp source Ethernet1', 'no ntp']) + if dut.version_number >= '4.23': + dut.config(['ntp local-interface Ethernet1', 'no ntp']) + else: + dut.config(['ntp source Ethernet1', 'no ntp']) for addserver in servers: dut.config(['ntp server %s' % addserver]) response = dut.api('ntp').remove_all_servers() diff --git a/test/system/test_api_system.py b/test/system/test_api_system.py index 8474f0e..b58a020 100644 --- a/test/system/test_api_system.py +++ b/test/system/test_api_system.py @@ -73,7 +73,7 @@ def test_get_check_banners(self): def test_get_banner_with_EOF(self): for dut in self.duts: - motd_banner_value = '!!!newlinebaner\n\nSecondLIneEOF!!!newlinebanner\n' + motd_banner_value = '!!!newlinebaner\nSecondLIneEOF!!!newlinebanner\n' dut.config([dict(cmd="banner motd", input=motd_banner_value)]) resp = dut.api('system').get() self.assertEqual(resp['banner_motd'], motd_banner_value.rstrip()) diff --git a/test/system/test_api_users.py b/test/system/test_api_users.py index 5ee6e57..5810dcf 100644 --- a/test/system/test_api_users.py +++ b/test/system/test_api_users.py @@ -49,14 +49,22 @@ class TestApiUsers(DutSystemTest): def test_get(self): for dut in self.duts: - dut.config(['no username test', 'username test nopassword', - 'username test sshkey %s' % TEST_SSH_KEY]) + if dut.version_number >= '4.23': + dut.config(['no username test', 'username test nopassword', + 'username test ssh-key %s' % TEST_SSH_KEY]) + else: + dut.config(['no username test', 'username test nopassword', + 'username test sshkey %s' % TEST_SSH_KEY]) result = dut.api('users').get('test') - values = dict(nopassword=True, privilege='1', secret='', - role='', format='', - sshkey=TEST_SSH_KEY) - + print(result) + if dut.version_number >= '4.23': + values = dict(nopassword=True, privilege='1', secret='', + role='', format='') + values["ssh-key"] = TEST_SSH_KEY + else: + values = dict(nopassword=True, privilege='1', secret='', + role='', format='', sshkey=TEST_SSH_KEY) result = self.sort_dict_by_keys(result) values = self.sort_dict_by_keys(values) @@ -139,32 +147,52 @@ def test_set_sshkey_with_value(self): dut.config(['no username test', 'username test nopassword']) api = dut.api('users') self.assertIn('username test privilege 1 nopassword', api.config) - self.assertNotIn('username test sshkey', api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key', api.config) + else: + self.assertNotIn('username test sshkey', api.config) result = api.set_sshkey('test', TEST_SSH_KEY) self.assertTrue(result) - self.assertIn('username test sshkey %s' % TEST_SSH_KEY, api.config) + if dut.version_number >= '4.23': + self.assertIn('username test ssh-key %s' % TEST_SSH_KEY, api.config) + else: + self.assertIn('username test sshkey %s' % TEST_SSH_KEY, api.config) def test_set_sshkey_with_empty_string(self): for dut in self.duts: dut.config(['no username test', 'username test nopassword']) api = dut.api('users') self.assertIn('username test privilege 1 nopassword', api.config) - self.assertNotIn('username test sshkey', api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key', api.config) + else: + self.assertNotIn('username test sshkey', api.config) result = api.set_sshkey('test', '') self.assertTrue(result) - self.assertNotIn('username test sshkey %s' - % TEST_SSH_KEY, api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key %s' + % TEST_SSH_KEY, api.config) + else: + self.assertNotIn('username test sshkey %s' + % TEST_SSH_KEY, api.config) def test_set_sshkey_with_None(self): for dut in self.duts: dut.config(['no username test', 'username test nopassword']) api = dut.api('users') self.assertIn('username test privilege 1 nopassword', api.config) - self.assertNotIn('username test sshkey', api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key', api.config) + else: + self.assertNotIn('username test sshkey', api.config) result = api.set_sshkey('test', None) self.assertTrue(result) - self.assertNotIn('username test sshkey %s' - % TEST_SSH_KEY, api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key %s' + % TEST_SSH_KEY, api.config) + else: + self.assertNotIn('username test sshkey %s' + % TEST_SSH_KEY, api.config) def test_set_sshkey_with_no_value(self): for dut in self.duts: @@ -174,8 +202,12 @@ def test_set_sshkey_with_no_value(self): self.assertIn('username test privilege 1 nopassword', api.config) result = api.set_sshkey('test', disable=True) self.assertTrue(result) - self.assertNotIn('username test sshkey %s' % TEST_SSH_KEY, - api.config) + if dut.version_number >= '4.23': + self.assertNotIn('username test ssh-key %s' % TEST_SSH_KEY, + api.config) + else: + self.assertNotIn('username test sshkey %s' % TEST_SSH_KEY, + api.config) if __name__ == '__main__': diff --git a/test/system/test_api_vrfs.py b/test/system/test_api_vrfs.py index df2d7b8..d153de8 100644 --- a/test/system/test_api_vrfs.py +++ b/test/system/test_api_vrfs.py @@ -43,45 +43,76 @@ class TestApiVrfs(DutSystemTest): def test_get(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'rd 10:10', 'description blah desc']) + if dut.version_number >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'rd 10:10', 'description blah desc']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'rd 10:10', 'description blah desc']) response = dut.api('vrfs').get('blah') + print(response) values = dict(rd='10:10', vrf_name='blah', description='blah desc', ipv4_routing=False, ipv6_routing=False) self.assertEqual(values, response) - dut.config(['no vrf definition blah']) + if dut.version_number >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_getall(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'no vrf definition second', 'vrf definition second']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'no vrf instance second', 'vrf instance second']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'no vrf definition second', 'vrf definition second']) response = dut.api('vrfs').getall() self.assertIsInstance(response, dict, 'dut=%s' % dut) self.assertEqual(len(response), 2) for vrf_name in ['blah', 'second']: self.assertIn(vrf_name, response, 'dut=%s' % dut) - dut.config(['no vrf definition blah', 'no vrf definition second']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'no vrf instance second']) + else: + dut.config(['no vrf definition blah', 'no vrf definition second']) def test_create_and_return_true(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah']) result = dut.api('vrfs').create('blah') self.assertTrue(result, 'dut=%s' % dut) config = dut.run_commands('show vrf', encoding='text') self.assertIn('blah', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_create_with_valid_rd(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah']) result = dut.api('vrfs').create('blah', rd='10:10') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - self.assertIn('vrf definition blah', config[0]['output'], - 'dut=%s' % dut) + if dut.version_id >= '4.23': + self.assertIn('vrf instance blah', config[0]['output'], + 'dut=%s' % dut) + else: + self.assertIn('vrf definition blah', config[0]['output'], + 'dut=%s' % dut) self.assertIn('rd 10:10', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_create_and_return_false(self): for dut in self.duts: @@ -90,26 +121,43 @@ def test_create_and_return_false(self): def test_create_with_invalid_rd(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah']) result = dut.api('vrfs').create('blah', rd='192.168.1.1:99999999') self.assertFalse(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - self.assertIn('vrf definition blah', config[0]['output'], - 'dut=%s' % dut) + if dut.version_id >= '4.23': + self.assertIn('vrf instance blah', config[0]['output'], + 'dut=%s' % dut) + else: + self.assertIn('vrf definition blah', config[0]['output'], + 'dut=%s' % dut) self.assertNotIn('rd', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_delete_and_return_true(self): for dut in self.duts: - dut.config('vrf definition blah') + if dut.version_id >= '4.23': + dut.config('vrf instance blah') + else: + dut.config('vrf definition blah') result = dut.api('vrfs').delete('blah') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - self.assertNotIn('vrf definition blah', config[0]['output'], - 'dut=%s' % dut) + if dut.version_id >= '4.23': + self.assertNotIn('vrf instance blah', config[0]['output'], + 'dut=%s' % dut) + else: + self.assertNotIn('vrf definition blah', config[0]['output'], + 'dut=%s' % dut) def test_delete_and_return_false(self): for dut in self.duts: @@ -118,31 +166,49 @@ def test_delete_and_return_false(self): def test_default(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'description test desc']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'description test desc']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'description test desc']) result = dut.api('vrfs').default('blah') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - self.assertNotIn('vrf definition blah', config[0]['output'], - 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + self.assertNotIn('vrf instance blah', config[0]['output'], + 'dut=%s' % dut) + dut.config(['no vrf instance blah']) + else: + self.assertNotIn('vrf definition blah', config[0]['output'], + 'dut=%s' % dut) + dut.config(['no vrf definition blah']) def test_set_rd(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah']) result = dut.api('vrfs').set_rd('blah', '10:10') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') self.assertIn('blah', config[0]['output'], 'dut=%s' % dut) self.assertIn('10:10', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_set_description(self): for dut in self.duts: description = random_string() - dut.config(['no vrf definition blah', 'vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah']) result = dut.api('vrfs').set_description('blah', description) self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' @@ -154,12 +220,19 @@ def test_set_description(self): config = dut.run_commands(command, encoding='text') self.assertNotIn('description %s' % description, config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_set_ipv4_routing(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'rd 10:10', 'description test']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'rd 10:10', 'description test']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'rd 10:10', 'description test']) result = dut.api('vrfs').set_ipv4_routing('blah') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' @@ -171,12 +244,19 @@ def test_set_ipv4_routing(self): config = dut.run_commands(command, encoding='text') self.assertIn('no ip routing vrf blah', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_set_ipv6_routing(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'rd 10:10', 'description test']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'rd 10:10', 'description test']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'rd 10:10', 'description test']) result = dut.api('vrfs').set_ipv6_routing('blah') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config all section vrf' @@ -188,27 +268,45 @@ def test_set_ipv6_routing(self): config = dut.run_commands(command, encoding='text') self.assertIn('no ipv6 unicast-routing vrf blah', config[0]['output'], 'dut=%s' % dut) - dut.config(['no vrf definition blah']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah']) + else: + dut.config(['no vrf definition blah']) def test_set_interface(self): for dut in self.duts: - dut.config(['no vrf definition blah', 'vrf definition blah', - 'rd 10:10', 'default interface Ethernet1', - 'interface Ethernet1', 'no switchport']) + if dut.version_id >= '4.23': + dut.config(['no vrf instance blah', 'vrf instance blah', + 'rd 10:10', 'default interface Ethernet1', + 'interface Ethernet1', 'no switchport']) + else: + dut.config(['no vrf definition blah', 'vrf definition blah', + 'rd 10:10', 'default interface Ethernet1', + 'interface Ethernet1', 'no switchport']) result = dut.api('vrfs').set_interface('blah', 'Ethernet1') self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config interfaces Ethernet1' config = dut.run_commands(command, encoding='text') - self.assertIn('vrf forwarding blah', config[0]['output'], - 'dut=%s' % dut) + if dut.version_id >= '4.23': + self.assertIn('vrf blah', config[0]['output'], + 'dut=%s' % dut) + else: + self.assertIn('vrf forwarding blah', config[0]['output'], + 'dut=%s' % dut) result = dut.api('vrfs').set_interface('blah', 'Ethernet1', disable=True) self.assertTrue(result, 'dut=%s' % dut) config = dut.run_commands(command, encoding='text') - self.assertNotIn('vrf forwarding blah', config[0]['output'], - 'dut=%s' % dut) - dut.config(['no vrf definition blah', - 'default interface Ethernet1']) + if dut.version_id >= '4.23': + self.assertNotIn('vrf blah', config[0]['output'], + 'dut=%s' % dut) + dut.config(['no vrf instance blah', + 'default interface Ethernet1']) + else: + self.assertNotIn('vrf forwarding blah', config[0]['output'], + 'dut=%s' % dut) + dut.config(['no vrf definition blah', + 'default interface Ethernet1']) if __name__ == '__main__': diff --git a/test/system/test_api_vrrp.py b/test/system/test_api_vrrp.py index 2b43004..8be4109 100644 --- a/test/system/test_api_vrrp.py +++ b/test/system/test_api_vrrp.py @@ -40,37 +40,26 @@ IP_PREFIX = '10.10.10.' VR_CONFIG = { 'primary_ip': '10.10.10.2', - 'secondary_ip': [], - 'priority': 100, - 'description': '', - 'ip_version': 2, - 'timers_advertise': 1, - 'delay_reload': 1, + 'priority': 200, + 'description': 'modified vrrp 10 on an interface', + 'secondary_ip': ['10.10.10.11'], + 'ip_version': 3, 'enable': False, - 'mac_addr_adv_interval': 30, + 'timers_advertise': 2, + 'mac_addr_adv_interval': 3, 'preempt': False, 'preempt_delay_min': 1, 'preempt_delay_reload': None, - 'primary_ipv4': '10.10.10.2', - 'priority_level': 200, - 'session_description': 'modified vrrp 10 on an interface', - 'secondary_ipv4': ['10.10.10.11'], - 'ipv4_version': 3, - 'advertisement_interval': 2, - 'timers_delay_reload': 1, + 'delay_reload': 1, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], - 'tracked-object': [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - ], 'bfd_ip': '10.10.10.150', } + class TestApiVrrp(DutSystemTest): def _vlan_setup(self, dut): @@ -84,9 +73,14 @@ def test_get(self): vrid = 98 for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'vrrp %d shutdown' % vrid, + 'exit']) response = dut.api('vrrp').get(interface) self.assertIsNotNone(response) @@ -96,13 +90,22 @@ def test_getall(self): vrid2 = 198 for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'vrrp %d disabled' % vrid, - 'exit', - 'interface vlan $', - 'vrrp %d disabled' % vrid, - 'vrrp %d disabled' % vrid2, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'vrrp %d disabled' % vrid, + 'exit', + 'interface vlan $', + 'vrrp %d disabled' % vrid, + 'vrrp %d disabled' % vrid2, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'vrrp %d shutdown' % vrid, + 'exit', + 'interface vlan $', + 'vrrp %d shutdown' % vrid, + 'vrrp %d shutdown' % vrid2, + 'exit']) response = dut.api('vrrp').getall() self.assertIsNotNone(response) @@ -111,6 +114,7 @@ def test_create(self): vrid = 99 import copy vrrp_conf = copy.deepcopy(VR_CONFIG) + # vrrp_conf = dict(VR_CONFIG) for dut in self.duts: interface = self._vlan_setup(dut) dut.config(['interface %s' % interface, @@ -132,10 +136,16 @@ def test_delete(self): vrid = 101 for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) response = dut.api('vrrp').delete(interface, vrid) self.assertIs(response, True) @@ -144,10 +154,16 @@ def test_default(self): vrid = 102 for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) response = dut.api('vrrp').delete(interface, vrid) self.assertIs(response, True) @@ -170,32 +186,22 @@ def test_update_with_create(self): # Update some of the information on the vrrp vrrp_update = { + 'primary_ip': '10.10.10.12', + 'priority': 200, + 'description': 'updated vrrp 10 on an interface', + 'secondary_ip': ['10.10.10.13', '10.10.10.23'], + 'ip_version': 2, 'enable': True, + 'timers_advertise': None, 'mac_addr_adv_interval': 'default', 'preempt': True, 'preempt_delay_min': 'default', 'preempt_delay_reload': 'default', - 'primary_ip': '10.10.10.12', - 'primary_ipv4': '10.10.10.12', - 'priority_level': 200, - 'priority': 100, - 'description': '', - 'ip_version': None, - 'timers_advertise': 1, - 'delay_reload': 1, - 'session_description': 'updated vrrp 10 on an interface', - 'secondary_ipv4': ['10.10.10.13', '10.10.10.23'], - 'ipv4_version': 2, - 'advertisement_interval': None, - 'timers_delay_reload': 'default', + 'delay_reload': 'default', 'track': [ {'name': 'Ethernet2', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, ], - 'tracked_object': [ - {'name': 'Ethernet2', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, - ], 'bfd_ip': None, } @@ -218,39 +224,52 @@ def test_set_enable(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'vrrp %d ipv4 10.10.10.2' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'vrrp %d ipv4 10.10.10.2' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'vrrp %d ip 10.10.10.2' % vrid, + 'exit']) for enable in enable_cases: response = dut.api('vrrp').set_enable( interface, vrid, **enable) self.assertIs(response, True) - def test_set_primary_ipv4(self): + def test_set_primary_ip(self): vrid = 104 - primary_ipv4_cases = [ - {'value': '10.10.10.5'}, + primary_ip_cases = [ + {'value': '10.10.10.2'}, {'default': True}, - {'value': '10.10.10.6'}, + {'value': '10.10.10.3'}, {'disable': True}, - {'value': '10.10.10.7'}, + {'value': '10.10.10.4'}, ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for p_ip in primary_ipv4_cases: - response = dut.api('vrrp').set_primary_ipv4( + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for p_ip in primary_ip_cases: + response = dut.api('vrrp').set_primary_ip( interface, vrid, **p_ip) self.assertIs(response, True) - def test_set_priority_level(self): + def test_set_priority(self): vrid = 104 priority_cases = [ {'value': 200}, @@ -261,17 +280,23 @@ def test_set_priority_level(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for priority_level in priority_cases: - response = dut.api('vrrp').set_priority_level( - interface, vrid, **priority_level) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for priority in priority_cases: + response = dut.api('vrrp').set_priority( + interface, vrid, **priority) self.assertIs(response, True) - def test_set_session_description(self): + def test_set_description(self): vrid = 104 desc_cases = [ {'value': '1st modified vrrp'}, @@ -282,36 +307,48 @@ def test_set_session_description(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for session_description in desc_cases: - response = dut.api('vrrp').set_session_description( - interface, vrid, **session_description) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for description in desc_cases: + response = dut.api('vrrp').set_description( + interface, vrid, **description) self.assertIs(response, True) - def test_set_secondary_ipv4s(self): + def test_set_secondary_ips(self): vrid = 104 - secondary_ipv4_cases = [ + secondary_ip_cases = [ ['10.10.10.51', '10.10.10.52'], ['10.10.10.53', '10.10.10.54'], [], ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for s_ip_list in secondary_ipv4_cases: - response = dut.api('vrrp').set_secondary_ipv4s( + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for s_ip_list in secondary_ip_cases: + response = dut.api('vrrp').set_secondary_ips( interface, vrid, s_ip_list) self.assertIs(response, True) - def test_set_ipv4_version(self): + def test_set_ip_version(self): vrid = 104 ip_version_cases = [ {'value': 2}, @@ -323,17 +360,23 @@ def test_set_ipv4_version(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for ipv4_version in ip_version_cases: - response = dut.api('vrrp').set_ipv4_version( - interface, vrid, **ipv4_version) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for ip_version in ip_version_cases: + response = dut.api('vrrp').set_ip_version( + interface, vrid, **ip_version) self.assertIs(response, True) - def test_set_advertisement_interval(self): + def test_set_timers_advertise(self): vrid = 104 timers_adv_cases = [ {'value': 10}, @@ -344,14 +387,20 @@ def test_set_advertisement_interval(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for advertisement_interval in timers_adv_cases: - response = dut.api('vrrp').set_advertisement_interval( - interface, vrid, **advertisement_interval) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for timers_advertise in timers_adv_cases: + response = dut.api('vrrp').set_timers_advertise( + interface, vrid, **timers_advertise) self.assertIs(response, True) def test_set_mac_addr_adv_interval(self): @@ -365,10 +414,16 @@ def test_set_mac_addr_adv_interval(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for mac_addr_adv_intvl in mac_addr_adv_int_cases: response = dut.api('vrrp').set_mac_addr_adv_interval( @@ -387,10 +442,16 @@ def test_set_preempt(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for preempt in preempt_cases: response = dut.api('vrrp').set_preempt( @@ -408,10 +469,16 @@ def test_set_preempt_delay_min(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for preempt_delay_min in preempt_delay_min_cases: response = dut.api('vrrp').set_preempt_delay_min( @@ -429,19 +496,25 @@ def test_set_preempt_delay_reload(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for preempt_delay_reload in preempt_delay_reload_cases: response = dut.api('vrrp').set_preempt_delay_reload( interface, vrid, **preempt_delay_reload) self.assertIs(response, True) - def test_set_timers_delay_reload(self): + def test_set_delay_reload(self): vrid = 104 - timers_delay_reload_cases = [ + delay_reload_cases = [ {'value': 30}, {'default': True}, {'value': 25}, @@ -450,14 +523,20 @@ def test_set_timers_delay_reload(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for timers_delay_reload in timers_delay_reload_cases: - response = dut.api('vrrp').set_timers_delay_reload( - interface, vrid, **timers_delay_reload) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) + + for delay_reload in delay_reload_cases: + response = dut.api('vrrp').set_delay_reload( + interface, vrid, **delay_reload) self.assertIs(response, True) def test_set_tracks(self): @@ -483,49 +562,22 @@ def test_set_tracks(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for track_list in track_cases: response = dut.api('vrrp').set_tracks( interface, vrid, track_list) self.assertIs(response, True) - def test_set_tracked_objects(self): - vrid = 104 - track_cases = [ - [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 10}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - ], - [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - ], - [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 20}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - ], - [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - ], - [], - ] - for dut in self.duts: - interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) - - for track_list in track_cases: - response = dut.api('vrrp').set_tracked_objects( - interface, vrid, track_list) - self.assertIs(response, True) - def test_set_bfd_ip(self): vrid = 104 bfd_ip_cases = [ @@ -537,10 +589,16 @@ def test_set_bfd_ip(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - dut.config(['interface %s' % interface, - 'no vrrp %d' % vrid, - 'vrrp %d disabled' % vrid, - 'exit']) + if dut.version_id >= '4.23': + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d disabled' % vrid, + 'exit']) + else: + dut.config(['interface %s' % interface, + 'no vrrp %d' % vrid, + 'vrrp %d shutdown' % vrid, + 'exit']) for bfd_ip in bfd_ip_cases: response = dut.api('vrrp').set_bfd_ip( diff --git a/test/system/test_client.py b/test/system/test_client.py index 2f422c7..d457537 100644 --- a/test/system/test_client.py +++ b/test/system/test_client.py @@ -29,6 +29,7 @@ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # + import os import unittest @@ -57,7 +58,10 @@ def setUp(self): if dut._enablepwd is not None: # If enable password defined for dut, set the # enable password on the dut and clear it on tearDown - dut.config("enable password %s" % dut._enablepwd) + if dut.version_number >= '4.23': + dut.config("enable password %s" % dut._enablepwd) + else: + dut.config("enable secret %s" % dut._enablepwd) def test_unauthorized_user(self): error_string = ('Unauthorized. Unable to authenticate user: Bad' @@ -183,7 +187,7 @@ def test_get_block(self): config = api.config running = api.get_block('interface Ethernet1') txtstr = api.get_block('interface Ethernet1', config=config) - self.assertEqual(running, txtstr) + self.assertEqual(running, txtstr, msg='{} eee {}'.format(txtstr, 'DEBUG:')) def test_get_block_none(self): # Verify get_block using a config string where match fails returns None @@ -249,7 +253,10 @@ def _dut_eos_version(self, dut): def tearDown(self): for dut in self.duts: - dut.config("no enable password") + if dut.version_number >= '4.23': + dut.config("no enable password") + else: + dut.config("no enable secret") class TestNode(unittest.TestCase): @@ -288,10 +295,6 @@ def test_exception_trace(self): cases.append(('reload', rfmt % (1004, 'incompatible command', 'Command not permitted via API access..*'))) - # Send a continuous command that requires a break - cases.append(('watch 10 show int e1 count rates', rfmt - % (1000, 'could not run command', - 'init error.*'))) # Send a command that has insufficient priv cases.append(('show running-config', rfmt % (1002, 'invalid command', diff --git a/test/unit/test_api_vrrp.py b/test/unit/test_api_vrrp.py index a656711..15c8f15 100644 --- a/test/unit/test_api_vrrp.py +++ b/test/unit/test_api_vrrp.py @@ -45,72 +45,49 @@ upd_cmd = 'interface %s' % upd_intf known_vrrps = { 'Ethernet1': { - 10: {'priority_level': 175, - 'priority': 100, - 'primary_ip': '10.10.6.11', - 'secondary_ip': [], - 'secondary_ipv4': [], + 10: {'priority': 175, 'timers_advertise': 1, - 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'timers_delay_reload': 0, - 'primary_ipv4': '10.10.6.10', + 'primary_ip': '10.10.6.10', + 'secondary_ip': [], 'description': 'vrrp 10 on Ethernet1', - 'session_description': 'vrrp 10 on Ethernet1', 'enable': True, 'track': [], - 'tracked_object': [], 'bfd_ip': '', - 'ip_version': 2, - 'ipv4_version': 2} + 'ip_version': 2} }, 'Port-Channel10': { - 10: {'priority_level': 150, - 'priority': 150, - 'primary_ip': '10.10.5.11', - 'secondary_ip': ['10.10.5.21'], + 10: {'priority': 150, 'timers_advertise': 1, - 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'timers_delay_reload': 0, - 'primary_ipv4': '10.10.5.10', - 'secondary_ipv4': ['10.10.5.20'], + 'primary_ip': '10.10.5.10', + 'secondary_ip': ['10.10.5.20'], 'description': 'vrrp 10 on Port-Channel10', - 'session_description': 'vrrp 10 on Port-Channel10', 'enable': True, 'track': [], - 'tracked_object': [], 'bfd_ip': '', - 'ip_version': 2, - 'ipv4_version': 2} + 'ip_version': 2} }, 'Vlan50': { - 10: {'priority_level': 200, - 'priority': 200, - 'primary_ip': '10.10.4.10', - 'primary_ipv4': '10.10.4.11', - 'timers_advertise': 1, - 'advertisement_interval': 3, + 10: {'priority': 200, + 'timers_advertise': 3, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'timers_delay_reload': 0, + 'primary_ip': '10.10.4.10', 'secondary_ip': ['10.10.4.21', '10.10.4.22', '10.10.4.23', '10.10.4.24'], - 'secondary_ipv4': ['10.10.4.21', '10.10.4.22', - '10.10.4.23', '10.10.4.24'], 'description': '', - 'session_description': '', 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, @@ -120,69 +97,40 @@ {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75}, {'name': 'Ethernet11', 'action': 'shutdown'}, ], - 'tracked_object': [ - {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 50}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75}, - {'name': 'Ethernet11', 'action': 'shutdown'}, - ], 'bfd_ip': '', - 'ip_version': 2, - 'ipv4_version': 2}, - 20: {'priority_level': 100, - 'priority': 100, - 'primary_ip': '10.10.4.20', - 'primary_ipv4': '10.10.4.20', - 'secondary_ip': [], - 'secondary_ipv4': [], - 'timers_advertise': 1, - 'advertisement_interval': 5, + 'ip_version': 2}, + 20: {'priority': 100, + 'timers_advertise': 5, 'mac_addr_adv_interval': 30, 'preempt': False, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'timers_delay_reload': 0, + 'primary_ip': '10.10.4.20', + 'secondary_ip': [], 'description': '', - 'session_description': '', 'enable': False, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], - 'tracked_object': [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - ], 'bfd_ip': '', - 'ip_version': 2, - 'ipv4_version': 2}, - 30: {'priority_level': 50, - 'priority': 100, - 'primary_ip': '10.10.4.30', - 'primary_ipv4': '10.10.4.30', - 'secondary_ip': [], - 'secondary_ipv4': [], + 'ip_version': 2}, + 30: {'priority': 50, 'timers_advertise': 1, - 'advertisement_interval': 1, 'mac_addr_adv_interval': 30, 'preempt': True, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, 'delay_reload': 0, - 'timers_delay_reload': 0, + 'primary_ip': '10.10.4.30', + 'secondary_ip': [], 'description': '', - 'session_description': '', 'enable': True, 'track': [], - 'tracked_object': [], 'bfd_ip': '10.10.4.33', - 'ip_version': 2, - 'ipv4_version': 2} + 'ip_version': 2} } } @@ -233,95 +181,81 @@ def test_create(self): # Test create with a normal configuration configuration = { - 'primary_ipv4': '10.10.60.10', - 'secondary_ipv4': ['10.10.60.20', '10.10.60.30'], - 'priority_level': 200, + 'primary_ip': '10.10.60.10', 'priority': 200, 'description': 'modified vrrp 10 on Ethernet1', - 'session_description': 'modified vrrp 10 on Ethernet1', - 'ipv4_version': 3, - 'advertisement_interval': 2, + 'secondary_ip': ['10.10.60.20', '10.10.60.30'], + 'ip_version': 3, + 'timers_advertise': 2, 'mac_addr_adv_interval': 3, 'preempt': True, 'preempt_delay_min': 1, 'preempt_delay_reload': 1, - 'timers_delay_reload': 1, + 'delay_reload': 1, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, {'name': 'Ethernet2', 'action': 'shutdown'}, ], - 'tracked_object': [ - {'name': 'Ethernet1', 'action': 'decrement', 'amount': 1}, - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet2', 'action': 'decrement', 'amount': 1}, - {'name': 'Ethernet2', 'action': 'shutdown'}, - ], 'bfd_ip': '10.10.60.30', } cmds = [ 'interface Ethernet1', - 'vrrp 10 disabled', - 'vrrp 10 ipv4 10.10.60.10', + 'vrrp 10 shutdown', + 'vrrp 10 ip 10.10.60.10', 'vrrp 10 priority 200', - 'vrrp 10 priority-level 200', 'vrrp 10 description modified vrrp 10 on Ethernet1', - 'vrrp 10 session description modified vrrp 10 on Ethernet1', - 'vrrp 10 ipv4 version 3', - 'vrrp 10 ipv4 10.10.60.20 secondary', - 'vrrp 10 ipv4 10.10.60.30 secondary', - 'vrrp 10 advertisement interval 2', + 'vrrp 10 ip version 3', + 'vrrp 10 ip 10.10.60.20 secondary', + 'vrrp 10 ip 10.10.60.30 secondary', + 'vrrp 10 timers advertise 2', 'vrrp 10 mac-address advertisement-interval 3', 'vrrp 10 preempt', 'vrrp 10 preempt delay minimum 1', 'vrrp 10 preempt delay reload 1', - 'vrrp 10 timers delay reload 1', + 'vrrp 10 delay reload 1', 'vrrp 10 track Ethernet1 decrement 1', 'vrrp 10 track Ethernet1 shutdown', 'vrrp 10 track Ethernet2 decrement 1', 'vrrp 10 track Ethernet2 shutdown', - 'vrrp 10 tracked-object Ethernet1 decrement 1', - 'vrrp 10 tracked-object Ethernet1 shutdown', - 'vrrp 10 tracked-object Ethernet2 decrement 1', - 'vrrp 10 tracked-object Ethernet2 shutdown', 'vrrp 10 bfd ip 10.10.60.30', ] func = function('create', interface, vrid, **configuration) + self.eapi_positive_config_test(func, cmds) # Test create setting possible parameters to 'no' configuration = { - 'primary_ipv4': 'no', - 'priority_level': 'no', - 'session_description': 'no', - 'secondary_ipv4': [], - 'ipv4_version': 'no', - 'advertisement_interval': 'no', + 'primary_ip': 'no', + 'priority': 'no', + 'description': 'no', + 'secondary_ip': [], + 'ip_version': 'no', + 'timers_advertise': 'no', 'mac_addr_adv_interval': 'no', 'preempt': 'no', 'preempt_delay_min': 'no', 'preempt_delay_reload': 'no', - 'timers_delay_reload': 'no', + 'delay_reload': 'no', 'track': [], - 'tracked_object': [], 'bfd_ip': 'no', } cmds = [ 'interface Ethernet1', - 'vrrp 10 disabled', - 'no vrrp 10 ipv4 10.10.6.10', - 'no vrrp 10 priority-level', - 'no vrrp 10 session description', - 'no vrrp 10 ipv4 version', - 'no vrrp 10 advertisement interval', + 'vrrp 10 shutdown', + 'no vrrp 10 ip 10.10.6.10', + 'no vrrp 10 priority', + 'no vrrp 10 description', + 'no vrrp 10 ip version', + 'no vrrp 10 timers advertise', 'no vrrp 10 mac-address advertisement-interval', 'no vrrp 10 preempt', 'no vrrp 10 preempt delay minimum', 'no vrrp 10 preempt delay reload', - 'no vrrp 10 timers delay reload', + 'no vrrp 10 delay reload', 'no vrrp 10 bfd ip', ] func = function('create', interface, vrid, **configuration) @@ -330,35 +264,34 @@ def test_create(self): # Test create setting possible parameters to 'default' configuration = { - 'primary_ipv4': 'default', - 'priority_level': 'default', - 'session_description': 'default', - 'secondary_ipv4': [], - 'ipv4_version': 'default', - 'advertisement_interval': 'default', + 'primary_ip': 'default', + 'priority': 'default', + 'description': 'default', + 'secondary_ip': [], + 'ip_version': 'default', + 'timers_advertise': 'default', 'mac_addr_adv_interval': 'default', 'preempt': 'default', 'preempt_delay_min': 'default', 'preempt_delay_reload': 'default', - 'timers_delay_reload': 'default', + 'delay_reload': 'default', 'track': [], - 'tracked_object': [], 'bfd_ip': 'default', } cmds = [ 'interface Ethernet1', - 'vrrp 10 disabled', - 'default vrrp 10 ipv4 10.10.6.10', - 'default vrrp 10 priority-level', - 'default vrrp 10 session description', - 'default vrrp 10 ipv4 version', - 'default vrrp 10 advertisement interval', + 'vrrp 10 shutdown', + 'default vrrp 10 ip 10.10.6.10', + 'default vrrp 10 priority', + 'default vrrp 10 description', + 'default vrrp 10 ip version', + 'default vrrp 10 timers advertise', 'default vrrp 10 mac-address advertisement-interval', 'default vrrp 10 preempt', 'default vrrp 10 preempt delay minimum', 'default vrrp 10 preempt delay reload', - 'default vrrp 10 timers delay reload', + 'default vrrp 10 delay reload', 'default vrrp 10 bfd ip', ] func = function('create', interface, vrid, **configuration) @@ -392,12 +325,12 @@ def test_default(self): self.eapi_positive_config_test(func, cmds) def test_set_enable(self): - # no vrrp 10 disabled + # no vrrp 10 shutdown # Test set_enable gives properly formatted commands cases = [ - (False, 'vrrp %d disabled' % upd_vrid), - (True, 'no vrrp %d disabled' % upd_vrid), + (False, 'vrrp %d shutdown' % upd_vrid), + (True, 'no vrrp %d shutdown' % upd_vrid), ] for (enable, cmd) in cases: @@ -439,37 +372,10 @@ def test_set_primary_ip(self): value=primary_ip) self.eapi_exception_config_test(func, ValueError) - def test_set_primary_ipv4(self): - # vrrp 10 ipv4 10.10.4.11 - - # Test set_primary_ipv4 gives properly formatted commands - ip1 = '10.10.4.110' - ipcurr = '10.10.4.11' - cases = [ - (ip1, None, None, 'vrrp %d ipv4 %s' % (upd_vrid, ip1)), - (ip1, True, None, 'no vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), - (ip1, None, True, 'default vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), - (ip1, True, True, 'default vrrp %d ipv4 %s' % (upd_vrid, ipcurr)), - ] - - for (primary_ipv4, disable, default, cmd) in cases: - func = function('set_primary_ipv4', upd_intf, upd_vrid, - value=primary_ipv4, disable=disable, default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError from invalid parameters - cases = ['abc', 500, '101.101'] - - for primary_ipv4 in cases: - func = function('set_primary_ipv4', upd_intf, upd_vrid, - value=primary_ipv4) - self.eapi_exception_config_test(func, ValueError) - def test_set_priority(self): # vrrp 10 priority 200 - # Test set_priority gives properly formatted commands + # Test set_primary_ip gives properly formatted commands cases = [ (150, None, None, 'vrrp %d priority 150' % upd_vrid), (None, None, True, 'default vrrp %d priority' % upd_vrid), @@ -491,31 +397,6 @@ def test_set_priority(self): value=priority) self.eapi_exception_config_test(func, ValueError) - def test_set_priority_level(self): - # vrrp 10 priority_level 200 - - # Test set_priority_level gives properly formatted commands - cases = [ - (150, None, None, 'vrrp %d priority-level 150' % upd_vrid), - (None, None, True, 'default vrrp %d priority-level' % upd_vrid), - (None, True, True, 'default vrrp %d priority-level' % upd_vrid), - (None, True, None, 'no vrrp %d priority-level' % upd_vrid), - ] - - for (priority_level, disable, default, cmd) in cases: - func = function('set_priority_level', upd_intf, upd_vrid, - value=priority_level, disable=disable, default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError from invalid parameters - cases = ['abc', 500, False] - - for priority_level in cases: - func = function('set_priority_level', upd_intf, upd_vrid, - value=priority_level) - self.eapi_exception_config_test(func, ValueError) - def test_set_description(self): # no vrrp 10 description @@ -536,30 +417,10 @@ def test_set_description(self): exp_cmds = [upd_cmd] + [cmd] self.eapi_positive_config_test(func, exp_cmds) - def test_set_session_description(self): - # no vrrp 10 session_description - - desc = 'test session description' - - # Test set_session_description gives properly formatted commands - cases = [ - (desc, None, None, 'vrrp %d session description %s' % (upd_vrid, desc)), - (None, None, True, 'default vrrp %d session description' % upd_vrid), - (None, True, True, 'default vrrp %d session description' % upd_vrid), - (None, True, None, 'no vrrp %d session description' % upd_vrid), - ] - - for (session_description, disable, default, cmd) in cases: - func = function('set_session_description', upd_intf, upd_vrid, - value=session_description, disable=disable, - default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - def test_set_ip_version(self): # vrrp 10 ip version 2 - # Test set_ip_version gives properly formatted commands + # Test set_description gives properly formatted commands cases = [ (2, None, None, 'vrrp %d ip version 2' % upd_vrid), (None, None, True, 'default vrrp %d ip version' % upd_vrid), @@ -581,31 +442,6 @@ def test_set_ip_version(self): value=ip_version) self.eapi_exception_config_test(func, ValueError) - def test_set_ipv4_version(self): - # vrrp 10 ipv4 version 2 - - # Test set_session_description gives properly formatted commands - cases = [ - (2, None, None, 'vrrp %d ipv4 version 2' % upd_vrid), - (None, None, True, 'default vrrp %d ipv4 version' % upd_vrid), - (None, True, True, 'default vrrp %d ipv4 version' % upd_vrid), - (None, True, None, 'no vrrp %d ipv4 version' % upd_vrid), - ] - - for (ipv4_version, disable, default, cmd) in cases: - func = function('set_ipv4_version', upd_intf, upd_vrid, - value=ipv4_version, disable=disable, default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError by entering invalid parameters - cases = ['a', 5] - - for ipv4_version in cases: - func = function('set_ipv4_version', upd_intf, upd_vrid, - value=ipv4_version) - self.eapi_exception_config_test(func, ValueError) - def test_set_secondary_ips(self): # vrrp 10 ip 10.10.4.21 secondary # vrrp 10 ip 10.10.4.22 secondary @@ -659,59 +495,6 @@ def test_set_secondary_ips(self): secondary_ips) self.eapi_exception_config_test(func, ValueError) - def test_set_secondary_ipv4s(self): - # vrrp 10 ipv4 10.10.4.21 secondary - # vrrp 10 ipv4 10.10.4.22 secondary - # vrrp 10 ipv4 10.10.4.23 secondary - - curr1 = '10.10.4.21' - curr2 = '10.10.4.22' - curr3 = '10.10.4.23' - curr4 = '10.10.4.24' - - new1 = '10.10.4.31' - new2 = '10.10.4.32' - new3 = '10.10.4.33' - new4 = curr4 - - # Test set_secondary_ipv4s gives properly formatted commands - cases = [ - ([new1, new2, new3], - {'add': [new1, new2, new3], - 'remove': [curr1, curr2, curr3, curr4]}), - ([new1, new2, new4], - {'add': [new1, new2], - 'remove': [curr1, curr2, curr3]}), - ([], - {'add': [], - 'remove': [curr1, curr2, curr3, curr4]}), - ] - - for (secondary_ipv4s, cmd_dict) in cases: - cmds = [] - for sec_ip in cmd_dict['add']: - cmds.append("vrrp %d ipv4 %s secondary" % (upd_vrid, sec_ip)) - - for sec_ip in cmd_dict['remove']: - cmds.append("no vrrp %d ipv4 %s secondary" % (upd_vrid, sec_ip)) - - func = function('set_secondary_ipv4s', upd_intf, upd_vrid, - secondary_ipv4s) - exp_cmds = [upd_cmd] + sorted(cmds) - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError by entering invalid parameters - cases = [ - [new1, new2, 'abc'], - [new1, new2, '10.10.10'], - [new1, new2, True], - ] - - for secondary_ipv4s in cases: - func = function('set_secondary_ipv4s', upd_intf, upd_vrid, - secondary_ipv4s) - self.eapi_exception_config_test(func, ValueError) - def test_set_timers_advertise(self): # vrrp 10 timers advertise 3 @@ -738,36 +521,10 @@ def test_set_timers_advertise(self): value=timers_advertise) self.eapi_exception_config_test(func, ValueError) - def test_set_advertisement_interval(self): - # vrrp 10 advertisement interval 3 - - # Test set_advertisement_interval gives properly formatted commands - cases = [ - (50, None, None, 'vrrp %d advertisement interval 50' % upd_vrid), - (None, None, True, 'default vrrp %d advertisement interval' % upd_vrid), - (None, True, True, 'default vrrp %d advertisement interval' % upd_vrid), - (None, True, None, 'no vrrp %d advertisement interval' % upd_vrid), - ] - - for (advertisement_interval, disable, default, cmd) in cases: - func = function('set_advertisement_interval', upd_intf, upd_vrid, - value=advertisement_interval, disable=disable, - default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError by entering invalid parameters - cases = [256, 0, 'a'] - - for advertisement_interval in cases: - func = function('set_advertisement_interval', upd_intf, upd_vrid, - value=advertisement_interval) - self.eapi_exception_config_test(func, ValueError) - def test_set_mac_addr_adv_interval(self): # vrrp 10 mac-address advertisement-interval 30 - # Test set_advertisement_interval gives properly formatted commands + # Test set_timers_advertise gives properly formatted commands maadvint = 'mac-address advertisement-interval' cases = [ (50, None, None, 'vrrp %d %s 50' % (upd_vrid, maadvint)), @@ -794,7 +551,7 @@ def test_set_mac_addr_adv_interval(self): def test_set_preempt(self): # vrrp 10 preempt - # Test set_set_preempt gives properly formatted commands + # Test set_description gives properly formatted commands cases = [ (False, None, None, 'no vrrp %d preempt' % upd_vrid), (True, None, None, 'vrrp %d preempt' % upd_vrid), @@ -849,7 +606,7 @@ def test_set_preempt_delay_min(self): def test_set_preempt_delay_reload(self): # vrrp 10 preempt delay reload 0 - # Test set_preempt_delay_reload gives properly formatted commands + # Test set_preempt_delay_min gives properly formatted commands cases = [ (1500, None, None, 'vrrp %d preempt delay reload 1500' % upd_vrid), @@ -878,7 +635,7 @@ def test_set_preempt_delay_reload(self): def test_set_delay_reload(self): # vrrp 10 delay reload 0 - # Test set_delay_reload gives properly formatted commands + # Test set_delay_min gives properly formatted commands cases = [ (1750, None, None, 'vrrp %d delay reload 1750' % upd_vrid), (None, None, True, 'default vrrp %d delay reload' % upd_vrid), @@ -901,32 +658,6 @@ def test_set_delay_reload(self): value=delay_reload) self.eapi_exception_config_test(func, ValueError) - def test_set_timers_delay_reload(self): - # vrrp 10 timers delay reload 0 - - # Test set_timers_delay_reload gives properly formatted commands - cases = [ - (1750, None, None, 'vrrp %d timers delay reload 1750' % upd_vrid), - (None, None, True, 'default vrrp %d timers delay reload' % upd_vrid), - (None, True, True, 'default vrrp %d timers delay reload' % upd_vrid), - (None, True, None, 'no vrrp %d timers delay reload' % upd_vrid), - ] - - for (timers_delay_reload, disable, default, cmd) in cases: - func = function('set_timers_delay_reload', upd_intf, upd_vrid, - value=timers_delay_reload, disable=disable, - default=default) - exp_cmds = [upd_cmd] + [cmd] - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError by entering invalid parameters - cases = ['a', 3601] - - for timers_delay_reload in cases: - func = function('set_timers_delay_reload', upd_intf, upd_vrid, - value=timers_delay_reload) - self.eapi_exception_config_test(func, ValueError) - def test_set_tracks(self): # vrrp 10 track Ethernet1 decrement 10 # vrrp 10 track Ethernet1 shutdown @@ -998,77 +729,6 @@ def test_set_tracks(self): func = function('set_tracks', upd_intf, upd_vrid, tracks) self.eapi_exception_config_test(func, ValueError) - def test_set_tracked_objects(self): - # vrrp 10 tracked-object Ethernet1 decrement 10 - # vrrp 10 tracked-object Ethernet1 shutdown - # vrrp 10 tracked-object Ethernet2 decrement 50 - # vrrp 10 tracked-object Ethernet2 shutdown - # vrrp 10 tracked-object Ethernet11 decrement 75 - # vrrp 10 tracked-object Ethernet11 shutdown - - curr1 = {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10} - curr2 = {'name': 'Ethernet1', 'action': 'shutdown'} - curr3 = {'name': 'Ethernet2', 'action': 'decrement', 'amount': 50} - curr4 = {'name': 'Ethernet2', 'action': 'shutdown'} - curr5 = {'name': 'Ethernet11', 'action': 'decrement', 'amount': 75} - curr6 = {'name': 'Ethernet11', 'action': 'shutdown'} - - new1 = curr1 - new2 = {'name': 'Ethernet2', 'action': 'decrement', 'amount': 49} - new3 = {'name': 'Ethernet3', 'action': 'shutdown'} - new4 = {'name': 'Ethernet4', 'action': 'decrement', 'amount': 50} - new5 = {'name': 'Ethernet5', 'action': 'shutdown'} - new6 = {'name': 'Ethernet9', 'action': 'decrement', 'amount': 75} - - # Test set_tracked_object gives properly formatted commands - cases = [ - ([curr6, curr5, new1, new2], - {'add': [new2], - 'remove': [curr2, curr3, curr4]}), - ([new2, new3, new4, new5, new6], - {'add': [new2, new3, new4, new5, new6], - 'remove': [curr1, curr2, curr3, curr4, curr5, curr6]}), - ([], - {'add': [], - 'remove': [curr1, curr2, curr3, curr4, curr5, curr6]}), - ] - - for (tracks, cmd_dict) in cases: - cmds = [] - for add in cmd_dict['add']: - tr_obj = add['name'] - action = add['action'] - amount = add['amount'] if 'amount' in add else '' - cmd = ("vrrp %d tracked-object %s %s %s" - % (upd_vrid, tr_obj, action, amount)) - cmds.append(cmd.rstrip()) - - for remove in cmd_dict['remove']: - tr_obj = remove['name'] - action = remove['action'] - amount = remove['amount'] if 'amount' in remove else '' - cmd = ("no vrrp %d tracked-object %s %s %s" - % (upd_vrid, tr_obj, action, amount)) - cmds.append(cmd.rstrip()) - - func = function('set_tracked_objects', upd_intf, upd_vrid, tracks) - exp_cmds = [upd_cmd] + sorted(cmds) - self.eapi_positive_config_test(func, exp_cmds) - - # Test raising ValueError by entering invalid parameters - cases = [ - [{'name': 'Ethernet1', 'action': 'disable', 'amount': 10}], - [{'name': 'Ethernet1', 'action': 'decrement', 'amount': True}], - [{'name': 'Ethernet1', 'action': 'shutdown', 'amount': 10}], - [{'action': 'decrement', 'amount': 10}], - [{'name': 'Ethernet1', 'action': 'decrement', - 'amount': 10, 'bad': 1}], - ] - - for tracks in cases: - func = function('set_tracked_objects', upd_intf, upd_vrid, tracks) - self.eapi_exception_config_test(func, ValueError) - def test_set_bfd_ip(self): # no vrrp 10 bfd ip @@ -1101,61 +761,41 @@ def test_vrconf_format(self): # match the output from get/getall vrconf = { 'priority': None, - 'description': None, - 'priority_level': None, 'timers_advertise': None, - 'advertisement_interval': None, 'mac_addr_adv_interval': None, 'preempt': 'default', 'preempt_delay_min': None, 'preempt_delay_reload': None, 'delay_reload': None, - 'timers_delay_reload': None, 'primary_ip': None, - 'primary_ipv4': None, - 'secondary_ipv4': ['10.10.4.22', '10.10.4.20'], - 'session_description': None, + 'secondary_ip': ['10.10.4.22', '10.10.4.21'], + 'description': None, 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'shutdown'}, {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, ], - 'tracked_object': [ - {'name': 'Ethernet1', 'action': 'shutdown'}, - {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, - ], 'bfd_ip': None, - 'ip_version': None, - 'ipv4_version': None} + 'ip_version': None} fixed = { - 'priority_level': 100, 'priority': 100, - 'advertisement_interval': 1, 'timers_advertise': 1, - 'delay_reload': 0, 'mac_addr_adv_interval': 30, 'preempt': False, 'preempt_delay_min': 0, 'preempt_delay_reload': 0, - 'timers_delay_reload': 0, + 'delay_reload': 0, 'primary_ip': '0.0.0.0', - 'primary_ipv4': '0.0.0.0', - 'secondary_ipv4': ['10.10.4.20', '10.10.4.22'], + 'secondary_ip': ['10.10.4.21', '10.10.4.22'], 'description': None, - 'session_description': None, 'enable': True, 'track': [ {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, {'name': 'Ethernet1', 'action': 'shutdown'}, ], - 'tracked_object': [ - {'name': 'Ethernet1', 'action': 'decrement', 'amount': 10}, - {'name': 'Ethernet1', 'action': 'shutdown'}, - ], 'bfd_ip': '', - 'ip_version': 2, - 'ipv4_version': 2} + 'ip_version': 2} # Get the vrconf_format method from the library func = getattr(self.instance, 'vrconf_format') diff --git a/test/unit/test_client.py b/test/unit/test_client.py index 54a265d..8c279d4 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -233,7 +233,7 @@ def test_load_config_for_connection_with_filename(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '192.168.0.10') + self.assertEqual(cfg['host'], '10.16.129.149') self.assertEqual(cfg['username'], 'arista') self.assertEqual(cfg['password'], 'arista') self.assertEqual(cfg['enablepwd'], 'enablepwd') @@ -242,7 +242,7 @@ def test_load_config_for_connection_with_env(self): os.environ['EAPI_CONF'] = get_fixture('eapi.conf') pyeapi.client.load_config(random_string()) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '192.168.0.10') + self.assertEqual(cfg['host'], '10.16.129.149') self.assertEqual(cfg['username'], 'arista') self.assertEqual(cfg['password'], 'arista') self.assertEqual(cfg['enablepwd'], 'enablepwd') @@ -418,10 +418,10 @@ def test_connect_return_node(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='192.168.0.10', username='arista', + node = pyeapi.client.connect(host='10.16.129.149', username='arista', password='arista', port=None, timeout=60, return_node=True) - kwargs = dict(host='192.168.0.10', username='arista', + kwargs = dict(host='10.16.129.149', username='arista', password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) @@ -432,11 +432,11 @@ def test_connect_return_node_enablepwd(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='192.168.0.10', username='arista', + node = pyeapi.client.connect(host='10.16.129.149', username='arista', password='arista', port=None, timeout=60, enablepwd='enablepwd', return_node=True) - kwargs = dict(host='192.168.0.10', username='arista', + kwargs = dict(host='10.16.129.149', username='arista', password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) @@ -448,7 +448,7 @@ def test_connect_to_with_config(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) node = pyeapi.client.connect_to('test1') - kwargs = dict(host='192.168.0.10', username='arista', + kwargs = dict(host='10.16.129.149', username='arista', password='arista', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) From a74e21ee54229ed4b3c01b463a70f15d65ec80b8 Mon Sep 17 00:00:00 2001 From: Andrii Rykhlivskyi Date: Mon, 16 Dec 2019 12:23:06 +0000 Subject: [PATCH 17/21] Fix 'test_get_interface_wo_ip_adddress' test, ssh-key parser, cleanup --- Makefile | 4 ++-- pyeapi/api/interfaces.py | 1 - pyeapi/api/users.py | 4 ++-- pyeapi/api/vrfs.py | 2 +- test/system/test_api_ipinterfaces.py | 2 ++ test/system/test_api_users.py | 1 - test/system/test_api_vrfs.py | 5 ++--- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 63902ce..76150fa 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,8 @@ pyflakes: pyflakes pyeapi/ test/ flake8: -# flake8 --ignore=E302,E303,E402,E731,W391 --exit-zero pyeapi/ -# flake8 --ignore=E302,E303,E402,E731,W391,N802 --max-line-length=100 test/ + flake8 --ignore=E302,E303,E402,E731,W391 --exit-zero pyeapi/ + flake8 --ignore=E302,E303,E402,E731,W391,N802 --max-line-length=100 test/ check: check-manifest diff --git a/pyeapi/api/interfaces.py b/pyeapi/api/interfaces.py index 821172e..957e194 100644 --- a/pyeapi/api/interfaces.py +++ b/pyeapi/api/interfaces.py @@ -565,7 +565,6 @@ def set_vrf(self, name, vrf, default=False, disable=False): True if the operation succeeds otherwise False is returned """ commands = ['interface %s' % name] - if self.version_id >= '4.23': commands.append(self.command_builder('vrf', vrf, default=default, diff --git a/pyeapi/api/users.py b/pyeapi/api/users.py index cf083c7..001bfe1 100644 --- a/pyeapi/api/users.py +++ b/pyeapi/api/users.py @@ -108,8 +108,8 @@ def getall(self): r'(?: role ([^\s]+))?' r'(?: (nopassword))?' r'(?: secret (0|5|7|sha512) (.+))?' - r'.*$\n(?:usernamed (?P=user) ' - r'ssh-key (.+)$)?', re.M) + r'.*$\n(?:username (?P=user) ' + r'ssh.key (.+)$)?', re.M) else: self.users_re = re.compile(r'username (?P[^\s]+) ' r'privilege (\d+)' diff --git a/pyeapi/api/vrfs.py b/pyeapi/api/vrfs.py index 3e5b80e..678f1a9 100644 --- a/pyeapi/api/vrfs.py +++ b/pyeapi/api/vrfs.py @@ -76,7 +76,7 @@ def get(self, value): key/value pairs. """ - if self.version_number >= '4.23': + if self.version_id >= '4.23': config = self.get_block('vrf instance %s' % value) else: config = self.get_block('vrf definition %s' % value) diff --git a/test/system/test_api_ipinterfaces.py b/test/system/test_api_ipinterfaces.py index acf352a..a26731c 100644 --- a/test/system/test_api_ipinterfaces.py +++ b/test/system/test_api_ipinterfaces.py @@ -31,6 +31,7 @@ # import os import unittest +import time import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) @@ -56,6 +57,7 @@ def test_get_interface_wo_ip_adddress(self): intf = random_interface(dut) dut.config(['default interface %s' % intf, 'interface %s' % intf, 'no switchport']) + time.sleep(2) result = dut.api('ipinterfaces').get(intf) self.assertIsNone(result['address']) diff --git a/test/system/test_api_users.py b/test/system/test_api_users.py index 5810dcf..ae54087 100644 --- a/test/system/test_api_users.py +++ b/test/system/test_api_users.py @@ -57,7 +57,6 @@ def test_get(self): 'username test sshkey %s' % TEST_SSH_KEY]) result = dut.api('users').get('test') - print(result) if dut.version_number >= '4.23': values = dict(nopassword=True, privilege='1', secret='', role='', format='') diff --git a/test/system/test_api_vrfs.py b/test/system/test_api_vrfs.py index d153de8..45ae8c1 100644 --- a/test/system/test_api_vrfs.py +++ b/test/system/test_api_vrfs.py @@ -43,18 +43,17 @@ class TestApiVrfs(DutSystemTest): def test_get(self): for dut in self.duts: - if dut.version_number >= '4.23': + if dut.version_id >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'rd 10:10', 'description blah desc']) else: dut.config(['no vrf definition blah', 'vrf definition blah', 'rd 10:10', 'description blah desc']) response = dut.api('vrfs').get('blah') - print(response) values = dict(rd='10:10', vrf_name='blah', description='blah desc', ipv4_routing=False, ipv6_routing=False) self.assertEqual(values, response) - if dut.version_number >= '4.23': + if dut.version_id >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) From d25639bd969a50eaedc1a9f228d725eb85afc359 Mon Sep 17 00:00:00 2001 From: andriirr Date: Thu, 2 Jan 2020 20:09:29 +0000 Subject: [PATCH 18/21] Fix test configuration, typos --- .travis.yml | 2 +- test/fixtures/dut.conf | 6 +++--- test/fixtures/eapi.conf | 6 +++--- test/fixtures/eapi.conf.yaml | 3 ++- test/fixtures/running_config.vrrp | 3 ++- test/system/test_client.py | 2 +- test/unit/test_client.py | 32 +++++++++++++++---------------- 7 files changed, 28 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1d6ce0..a253f08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: python python: - '2.7' - - '3.4' + - '3.8' install: pip install -r dev-requirements.txt diff --git a/test/fixtures/dut.conf b/test/fixtures/dut.conf index b72ccc4..036a7d0 100644 --- a/test/fixtures/dut.conf +++ b/test/fixtures/dut.conf @@ -1,5 +1,5 @@ [connection:veos01] -host: 10.16.129.149 -username: arista -password: arista +host: 192.168.1.16 +username: eapi +password: password transport: http diff --git a/test/fixtures/eapi.conf b/test/fixtures/eapi.conf index 598e483..2be7136 100644 --- a/test/fixtures/eapi.conf +++ b/test/fixtures/eapi.conf @@ -1,7 +1,7 @@ [connection:test1] -host: 10.16.129.149 -username: arista -password: arista +host: 192.168.0.10 +username: eapi +password: password enablepwd: enablepwd tags: tag1, tag2 diff --git a/test/fixtures/eapi.conf.yaml b/test/fixtures/eapi.conf.yaml index 4231aff..8a5a94e 100644 --- a/test/fixtures/eapi.conf.yaml +++ b/test/fixtures/eapi.conf.yaml @@ -3,4 +3,5 @@ :password: admin :use_ssl: true :port: 199 -:hostname: bogus \ No newline at end of file +:hostname: bogus + diff --git a/test/fixtures/running_config.vrrp b/test/fixtures/running_config.vrrp index 545c5ea..83b05c4 100644 --- a/test/fixtures/running_config.vrrp +++ b/test/fixtures/running_config.vrrp @@ -530,4 +530,5 @@ interface Vlan50 no vrrp 30 bfd ipv6 vrrp 30 ip version 2 ! -! \ No newline at end of file +! + diff --git a/test/system/test_client.py b/test/system/test_client.py index d457537..c36c418 100644 --- a/test/system/test_client.py +++ b/test/system/test_client.py @@ -187,7 +187,7 @@ def test_get_block(self): config = api.config running = api.get_block('interface Ethernet1') txtstr = api.get_block('interface Ethernet1', config=config) - self.assertEqual(running, txtstr, msg='{} eee {}'.format(txtstr, 'DEBUG:')) + self.assertEqual(running, txtstr) def test_get_block_none(self): # Verify get_block using a config string where match fails returns None diff --git a/test/unit/test_client.py b/test/unit/test_client.py index 8c279d4..b5c6ecc 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -233,18 +233,18 @@ def test_load_config_for_connection_with_filename(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '10.16.129.149') - self.assertEqual(cfg['username'], 'arista') - self.assertEqual(cfg['password'], 'arista') + self.assertEqual(cfg['host'], '192.168.1.16') + self.assertEqual(cfg['username'], 'eapi') + self.assertEqual(cfg['password'], 'password') self.assertEqual(cfg['enablepwd'], 'enablepwd') def test_load_config_for_connection_with_env(self): os.environ['EAPI_CONF'] = get_fixture('eapi.conf') pyeapi.client.load_config(random_string()) cfg = pyeapi.client.config.get_connection('test1') - self.assertEqual(cfg['host'], '10.16.129.149') - self.assertEqual(cfg['username'], 'arista') - self.assertEqual(cfg['password'], 'arista') + self.assertEqual(cfg['host'], '192.168.1.16') + self.assertEqual(cfg['username'], 'eapi') + self.assertEqual(cfg['password'], 'password') self.assertEqual(cfg['enablepwd'], 'enablepwd') def test_load_config(self): @@ -418,11 +418,11 @@ def test_connect_return_node(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='10.16.129.149', username='arista', - password='arista', port=None, + node = pyeapi.client.connect(host='192.168.1.16', username='eapi', + password='password', port=None, timeout=60, return_node=True) - kwargs = dict(host='10.16.129.149', username='arista', - password='arista', port=None, key_file=None, + kwargs = dict(host='192.168.1.16', username='eapi', + password='password', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertIsNone(node._enablepwd) @@ -432,12 +432,12 @@ def test_connect_return_node_enablepwd(self): with patch.dict(pyeapi.client.TRANSPORTS, {'https': transport}): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) - node = pyeapi.client.connect(host='10.16.129.149', username='arista', - password='arista', port=None, + node = pyeapi.client.connect(host='192.168.1.16', username='eapi', + password='password', port=None, timeout=60, enablepwd='enablepwd', return_node=True) - kwargs = dict(host='10.16.129.149', username='arista', - password='arista', port=None, key_file=None, + kwargs = dict(host='192.168.1.16', username='eapi', + password='password', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') @@ -448,8 +448,8 @@ def test_connect_to_with_config(self): conf = get_fixture('eapi.conf') pyeapi.client.load_config(filename=conf) node = pyeapi.client.connect_to('test1') - kwargs = dict(host='10.16.129.149', username='arista', - password='arista', port=None, key_file=None, + kwargs = dict(host='192.168.1.16', username='eapi', + password='password', port=None, key_file=None, cert_file=None, ca_file=None, timeout=60) transport.assert_called_once_with(**kwargs) self.assertEqual(node._enablepwd, 'enablepwd') From 9dfd1f7827066c5b318778dde8151f8bc5e1e75c Mon Sep 17 00:00:00 2001 From: andriirr Date: Thu, 2 Jan 2020 20:13:58 +0000 Subject: [PATCH 19/21] Fix test eapi access details --- test/fixtures/eapi.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/eapi.conf b/test/fixtures/eapi.conf index 2be7136..0454f24 100644 --- a/test/fixtures/eapi.conf +++ b/test/fixtures/eapi.conf @@ -1,5 +1,5 @@ [connection:test1] -host: 192.168.0.10 +host: 192.168.1.16 username: eapi password: password enablepwd: enablepwd From 0f6ad04ba6dfef84f48550b6a312bba37573c3e0 Mon Sep 17 00:00:00 2001 From: Andrii Rykhlivskyi Date: Tue, 14 Jan 2020 18:06:02 +0000 Subject: [PATCH 20/21] Simplify version checks, fix unittests for commands changed modified: pyeapi/api/abstract.py modified: pyeapi/api/bgp.py modified: pyeapi/api/interfaces.py modified: pyeapi/api/ntp.py modified: pyeapi/api/users.py modified: pyeapi/api/vrfs.py modified: pyeapi/api/vrrp.py modified: pyeapi/client.py modified: test/lib/testlib.py modified: test/system/test_api_vrfs.py modified: test/system/test_api_vrrp.py modified: test/unit/test_api_vrrp.py modified: test/unit/test_utils.py --- pyeapi/api/abstract.py | 4 +-- pyeapi/api/bgp.py | 6 ++-- pyeapi/api/interfaces.py | 2 +- pyeapi/api/ntp.py | 8 +++--- pyeapi/api/users.py | 6 ++-- pyeapi/api/vrfs.py | 14 +++++----- pyeapi/api/vrrp.py | 46 +++++++++++++++--------------- pyeapi/client.py | 13 ++------- test/lib/testlib.py | 2 +- test/system/test_api_vrfs.py | 54 ++++++++++++++++++------------------ test/system/test_api_vrrp.py | 36 ++++++++++++------------ test/unit/test_api_vrrp.py | 1 - test/unit/test_utils.py | 6 ++-- 13 files changed, 94 insertions(+), 104 deletions(-) diff --git a/pyeapi/api/abstract.py b/pyeapi/api/abstract.py index cdee142..f0a4eec 100644 --- a/pyeapi/api/abstract.py +++ b/pyeapi/api/abstract.py @@ -68,8 +68,8 @@ def __init__(self, node): self.node = node @property - def version_id(self): - return self.node.version_id + def version_number(self): + return self.node.version_number @property def config(self): diff --git a/pyeapi/api/bgp.py b/pyeapi/api/bgp.py index 586e133..8322212 100644 --- a/pyeapi/api/bgp.py +++ b/pyeapi/api/bgp.py @@ -205,7 +205,7 @@ def getall(self): return collection def _parse_peer_group(self, config, name): - if self.version_id >= '4.23': + if self.version_number >= '4.23': regexp = r'neighbor {} peer group ([^\s]+)'.format(name) else: regexp = r'neighbor {} peer-group ([^\s]+)'.format(name) @@ -266,7 +266,7 @@ def create(self, name): def delete(self, name): response = self.configure('no neighbor {}'.format(name)) if not response: - if self.version_id >= '4.23': + if self.version_number >= '4.23': response = self.configure('no neighbor {} ' 'peer group'.format(name)) else: @@ -288,7 +288,7 @@ def command_builder(self, name, cmd, value, default, disable): def set_peer_group(self, name, value=None, default=False, disable=False): if not self.ispeergroup(name): - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmd = self.command_builder(name, 'peer group', value, default, disable) else: diff --git a/pyeapi/api/interfaces.py b/pyeapi/api/interfaces.py index 957e194..c6f88c2 100644 --- a/pyeapi/api/interfaces.py +++ b/pyeapi/api/interfaces.py @@ -565,7 +565,7 @@ def set_vrf(self, name, vrf, default=False, disable=False): True if the operation succeeds otherwise False is returned """ commands = ['interface %s' % name] - if self.version_id >= '4.23': + if self.version_number >= '4.23': commands.append(self.command_builder('vrf', vrf, default=default, disable=disable)) diff --git a/pyeapi/api/ntp.py b/pyeapi/api/ntp.py index f2c7905..f8fe9ed 100644 --- a/pyeapi/api/ntp.py +++ b/pyeapi/api/ntp.py @@ -88,7 +88,7 @@ def get(self): return response def _parse_source_interface(self, config): - if self.version_id >= '4.23': + if self.version_number >= '4.23': match = re.search(r'^ntp local-interface ([^\s]+)', config, re.M) else: match = re.search(r'^ntp source ([^\s]+)', config, re.M) @@ -121,7 +121,7 @@ def delete(self): Returns: True if the operation succeeds, otherwise False. """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmd = self.command_builder('ntp local-interface', disable=True) else: cmd = self.command_builder('ntp source', disable=True) @@ -133,7 +133,7 @@ def default(self): Returns: True if the operation succeeds, otherwise False. """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmd = self.command_builder('ntp local-interface', default=True) else: cmd = self.command_builder('ntp source', default=True) @@ -148,7 +148,7 @@ def set_source_interface(self, name): Returns: True if the operation succeeds, otherwise False. """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmd = self.command_builder('ntp local-interface', value=name) else: cmd = self.command_builder('ntp source', value=name) diff --git a/pyeapi/api/users.py b/pyeapi/api/users.py index 001bfe1..5bc1411 100644 --- a/pyeapi/api/users.py +++ b/pyeapi/api/users.py @@ -102,7 +102,7 @@ def getall(self): Returns: dict: A dict of usernames with a nested resource dict object """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': self.users_re = re.compile(r'username (?P[^\s]+) ' r'privilege (\d+)' r'(?: role ([^\s]+))?' @@ -142,7 +142,7 @@ def _parse_username(self, config): resource['nopassword'] = nopass == 'nopassword' resource['format'] = fmt resource['secret'] = secret - if self.version_id >= '4.23': + if self.version_number >= '4.23': resource['ssh-key'] = sshkey else: resource['sshkey'] = sshkey @@ -301,7 +301,7 @@ def set_sshkey(self, name, value=None, default=False, disable=False): Returns: True if the operation was successful otherwise False """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmd = self.command_builder('username %s ssh-key' % name, value=value, default=default, disable=disable) diff --git a/pyeapi/api/vrfs.py b/pyeapi/api/vrfs.py index 678f1a9..d3a3802 100644 --- a/pyeapi/api/vrfs.py +++ b/pyeapi/api/vrfs.py @@ -76,7 +76,7 @@ def get(self, value): key/value pairs. """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': config = self.get_block('vrf instance %s' % value) else: config = self.get_block('vrf definition %s' % value) @@ -139,7 +139,7 @@ def getall(self): A dict object of VRF attributes """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': vrfs_re = re.compile(r'(?<=^vrf instance\s)(\w+)', re.M) else: vrfs_re = re.compile(r'(?<=^vrf definition\s)(\w+)', re.M) @@ -166,7 +166,7 @@ def create(self, vrf_name, rd=None): Returns: True if create was successful otherwise False """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': commands = ['vrf instance %s' % vrf_name] else: commands = ['vrf definition %s' % vrf_name] @@ -183,7 +183,7 @@ def delete(self, vrf_name): Returns: True if the operation was successful otherwise False """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': command = 'no vrf instance %s' % vrf_name else: command = 'no vrf definition %s' % vrf_name @@ -198,7 +198,7 @@ def default(self, vrf_name): Returns: True if the operation was successful otherwise False """ - if self.version_id >= '4.23': + if self.version_number >= '4.23': command = 'default vrf instance %s' % vrf_name else: command = 'default vrf definition %s' % vrf_name @@ -215,7 +215,7 @@ def configure_vrf(self, vrf_name, commands): True if the commands completed successfully """ commands = make_iterable(commands) - if self.version_id >= '4.23': + if self.version_number >= '4.23': commands.insert(0, 'vrf instance %s' % vrf_name) else: commands.insert(0, 'vrf definition %s' % vrf_name) @@ -320,7 +320,7 @@ def set_interface(self, vrf_name, interface, default=False, disable=False): True if the operation was successful otherwise False """ cmds = ['interface %s' % interface] - if self.version_id >= '4.23': + if self.version_number >= '4.23': cmds.append(self.command_builder('vrf', value=vrf_name, default=default, disable=disable)) else: diff --git a/pyeapi/api/vrrp.py b/pyeapi/api/vrrp.py index 0c073e9..b875ece 100644 --- a/pyeapi/api/vrrp.py +++ b/pyeapi/api/vrrp.py @@ -251,7 +251,7 @@ def getall(self): return vrrps def _parse_enable(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s disabled$' % vrid, config, re.M) else: match = re.search(r'^\s+vrrp %s shutdown$' % vrid, config, re.M) @@ -260,7 +260,7 @@ def _parse_enable(self, config, vrid): return dict(enable=True) def _parse_primary_ip(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+)$' % vrid, config, re.M) else: @@ -270,7 +270,7 @@ def _parse_primary_ip(self, config, vrid): return dict(primary_ip=value) def _parse_priority(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s priority-level (\d+)$' % vrid, config, re.M) else: @@ -280,7 +280,7 @@ def _parse_priority(self, config, vrid): return dict(priority=value) def _parse_timers_advertise(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s advertisement interval (\d+)$' % vrid, config, re.M) else: @@ -296,7 +296,7 @@ def _parse_preempt(self, config, vrid): return dict(preempt=False) def _parse_secondary_ip(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': matches = re.findall(r'^\s+vrrp %s ipv4 (\d+\.\d+\.\d+\.\d+) ' r'secondary$' % vrid, config, re.M) else: @@ -306,7 +306,7 @@ def _parse_secondary_ip(self, config, vrid): return dict(secondary_ip=value) def _parse_description(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s session description(.*)$' % vrid, config, re.M) else: @@ -343,7 +343,7 @@ def _parse_bfd_ip(self, config, vrid): return dict(bfd_ip='') def _parse_ip_version(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s ipv4 version (\d+)$' % vrid, config, re.M) else: @@ -353,7 +353,7 @@ def _parse_ip_version(self, config, vrid): return dict(ip_version=value) def _parse_delay_reload(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': match = re.search(r'^\s+vrrp %s timers delay reload (\d+)$' % vrid, config, re.M) else: @@ -363,7 +363,7 @@ def _parse_delay_reload(self, config, vrid): return dict(delay_reload=value) def _parse_track(self, config, vrid): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': matches = re.findall(r'^\s+vrrp %s tracked-object (\S+) ' r'(decrement|shutdown)(?:( \d+$|$))' % vrid, config, re.M) @@ -478,12 +478,12 @@ def set_enable(self, name, vrid, value=False, run=True): """ if value is False: - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = "vrrp %d disabled" % vrid else: cmd = "vrrp %d shutdown" % vrid elif value is True: - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = "no vrrp %d disabled" % vrid else: cmd = "no vrrp %d shutdown" % vrid @@ -527,19 +527,19 @@ def set_primary_ip(self, name, vrid, value=None, disable=False, if default is True: vrrps = self.get(name) primary_ip = vrrps[vrid]['primary_ip'] - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = "default vrrp %d ipv4 %s" % (vrid, primary_ip) else: cmd = "default vrrp %d ip %s" % (vrid, primary_ip) elif disable is True or value is None: vrrps = self.get(name) primary_ip = vrrps[vrid]['primary_ip'] - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = "no vrrp %d ipv4 %s" % (vrid, primary_ip) else: cmd = "no vrrp %d ip %s" % (vrid, primary_ip) elif re.match(r'^\d+\.\d+\.\d+\.\d+$', str(value)): - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = "vrrp %d ipv4 %s" % (vrid, value) else: cmd = "vrrp %d ip %s" % (vrid, value) @@ -584,7 +584,7 @@ def set_priority(self, name, vrid, value=None, disable=False, if not str(value).isdigit() or value < 1 or value > 254: raise ValueError("vrrp property 'priority' must be " "an integer in the range 1-254") - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = self.command_builder('vrrp %d priority-level' % vrid, value=value, default=default, disable=disable) @@ -625,7 +625,7 @@ def set_description(self, name, vrid, value=None, disable=False, be passed to the node """ - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = self.command_builder('vrrp %d session description' % vrid, value=value, default=default, disable=disable) @@ -670,7 +670,7 @@ def set_ip_version(self, name, vrid, value=None, disable=False, if not default and not disable: if value not in (2, 3): raise ValueError("vrrp property 'ip_version' must be 2 or 3") - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = self.command_builder('vrrp %d ipv4 version' % vrid, value=value, default=default, disable=disable) @@ -742,13 +742,13 @@ def set_secondary_ips(self, name, vrid, secondary_ips, run=True): # Build the commands to add and remove the secondary ip addresses for sec_ip in remove: - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmds.append("no vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) else: cmds.append("no vrrp %d ip %s secondary" % (vrid, sec_ip)) for sec_ip in add: - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmds.append("vrrp %d ipv4 %s secondary" % (vrid, sec_ip)) else: cmds.append("vrrp %d ip %s secondary" % (vrid, sec_ip)) @@ -792,7 +792,7 @@ def set_timers_advertise(self, name, vrid, value=None, disable=False, if not int(value) or int(value) < 1 or int(value) > 255: raise ValueError("vrrp property 'timers_advertise' must be" "in the range 1-255") - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = self.command_builder('vrrp %d advertisement interval' % vrid, value=value, default=default, @@ -1011,7 +1011,7 @@ def set_delay_reload(self, name, vrid, value=None, disable=False, if not int(value) or int(value) < 1 or int(value) > 3600: raise ValueError("vrrp property 'delay_reload' must be" "in the range 0-3600 %r" % value) - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': cmd = self.command_builder('vrrp %d timers delay reload' % vrid, value=value, default=default, disable=disable) @@ -1152,7 +1152,7 @@ def set_tracks(self, name, vrid, tracks, run=True): if amount == unset: amount = '' - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': t_cmd = ("no vrrp %d tracked-object %s %s %s" % (vrid, tr_obj, action, amount)) else: @@ -1168,7 +1168,7 @@ def set_tracks(self, name, vrid, tracks, run=True): if amount == unset: amount = '' - if self.version_id >= '4.21.3': + if self.version_number >= '4.21.3': t_cmd = ("vrrp %d tracked-object %s %s %s" % (vrid, tr_obj, action, amount)) else: diff --git a/pyeapi/client.py b/pyeapi/client.py index 523e60d..ff17b6b 100644 --- a/pyeapi/client.py +++ b/pyeapi/client.py @@ -470,7 +470,6 @@ def __init__(self, connection, **kwargs): self._startup_config = None self._version = None self._version_number = None - self._version_id = None self._model = None self._enablepwd = kwargs.get('enablepwd') @@ -517,14 +516,6 @@ def version_number(self): self._get_version_properties() return self._version_number - @property - def version_id(self): - if self._version_id: - return self._version_id - output = self.enable('show version') - self._version_id = output[0]['result']['version'].split()[0][:-1] - return self._version_id - @property def model(self): if self._model: @@ -539,13 +530,13 @@ def _get_version_properties(self): # Parse out version info output = self.enable('show version') self._version = str(output[0]['result']['version']) - match = re.match(r'[\d.\d]+', output[0]['result']['version']) + match = re.match(r'[\d.\d]+', str(output[0]['result']['version'])) if match: self._version_number = str(match.group(0)) else: self._version_number = str(output[0]['result']['version']) # Parse out model number - match = re.search(r'\d\d\d\d', output[0]['result']['modelName']) + match = re.search(r'\d\d\d\d', str(output[0]['result']['modelName'])) if match: self._model = str(match.group(0)) else: diff --git a/test/lib/testlib.py b/test/lib/testlib.py index cff9f4d..989fb4d 100644 --- a/test/lib/testlib.py +++ b/test/lib/testlib.py @@ -71,7 +71,7 @@ def __init__(self, *args, **kwargs): def setUp(self): self.node = Node(None) - + self.node._version_number = '4.17.1.1' self.node._running_config = self.config self.mock_config = Mock(name='node.config') diff --git a/test/system/test_api_vrfs.py b/test/system/test_api_vrfs.py index 45ae8c1..6d888fb 100644 --- a/test/system/test_api_vrfs.py +++ b/test/system/test_api_vrfs.py @@ -43,7 +43,7 @@ class TestApiVrfs(DutSystemTest): def test_get(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'rd 10:10', 'description blah desc']) else: @@ -53,14 +53,14 @@ def test_get(self): values = dict(rd='10:10', vrf_name='blah', description='blah desc', ipv4_routing=False, ipv6_routing=False) self.assertEqual(values, response) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_getall(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'no vrf instance second', 'vrf instance second']) else: @@ -71,14 +71,14 @@ def test_getall(self): self.assertEqual(len(response), 2) for vrf_name in ['blah', 'second']: self.assertIn(vrf_name, response, 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'no vrf instance second']) else: dut.config(['no vrf definition blah', 'no vrf definition second']) def test_create_and_return_true(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah']) else: dut.config(['no vrf definition blah', 'vrf definition blah']) @@ -86,14 +86,14 @@ def test_create_and_return_true(self): self.assertTrue(result, 'dut=%s' % dut) config = dut.run_commands('show vrf', encoding='text') self.assertIn('blah', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_create_with_valid_rd(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah']) else: dut.config(['no vrf definition blah', 'vrf definition blah']) @@ -101,14 +101,14 @@ def test_create_with_valid_rd(self): self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertIn('vrf instance blah', config[0]['output'], 'dut=%s' % dut) else: self.assertIn('vrf definition blah', config[0]['output'], 'dut=%s' % dut) self.assertIn('rd 10:10', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) @@ -120,7 +120,7 @@ def test_create_and_return_false(self): def test_create_with_invalid_rd(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah']) else: dut.config(['no vrf definition blah', 'vrf definition blah']) @@ -128,7 +128,7 @@ def test_create_with_invalid_rd(self): self.assertFalse(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertIn('vrf instance blah', config[0]['output'], 'dut=%s' % dut) else: @@ -136,14 +136,14 @@ def test_create_with_invalid_rd(self): 'dut=%s' % dut) self.assertNotIn('rd', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_delete_and_return_true(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config('vrf instance blah') else: dut.config('vrf definition blah') @@ -151,7 +151,7 @@ def test_delete_and_return_true(self): self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertNotIn('vrf instance blah', config[0]['output'], 'dut=%s' % dut) else: @@ -165,7 +165,7 @@ def test_delete_and_return_false(self): def test_default(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'description test desc']) else: @@ -175,7 +175,7 @@ def test_default(self): self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config section vrf' config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertNotIn('vrf instance blah', config[0]['output'], 'dut=%s' % dut) dut.config(['no vrf instance blah']) @@ -186,7 +186,7 @@ def test_default(self): def test_set_rd(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah']) else: dut.config(['no vrf definition blah', 'vrf definition blah']) @@ -196,7 +196,7 @@ def test_set_rd(self): config = dut.run_commands(command, encoding='text') self.assertIn('blah', config[0]['output'], 'dut=%s' % dut) self.assertIn('10:10', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) @@ -204,7 +204,7 @@ def test_set_rd(self): def test_set_description(self): for dut in self.duts: description = random_string() - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah']) else: dut.config(['no vrf definition blah', 'vrf definition blah']) @@ -219,14 +219,14 @@ def test_set_description(self): config = dut.run_commands(command, encoding='text') self.assertNotIn('description %s' % description, config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_set_ipv4_routing(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'rd 10:10', 'description test']) else: @@ -243,14 +243,14 @@ def test_set_ipv4_routing(self): config = dut.run_commands(command, encoding='text') self.assertIn('no ip routing vrf blah', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_set_ipv6_routing(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'rd 10:10', 'description test']) else: @@ -267,14 +267,14 @@ def test_set_ipv6_routing(self): config = dut.run_commands(command, encoding='text') self.assertIn('no ipv6 unicast-routing vrf blah', config[0]['output'], 'dut=%s' % dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah']) else: dut.config(['no vrf definition blah']) def test_set_interface(self): for dut in self.duts: - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['no vrf instance blah', 'vrf instance blah', 'rd 10:10', 'default interface Ethernet1', 'interface Ethernet1', 'no switchport']) @@ -286,7 +286,7 @@ def test_set_interface(self): self.assertTrue(result, 'dut=%s' % dut) command = 'show running-config interfaces Ethernet1' config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertIn('vrf blah', config[0]['output'], 'dut=%s' % dut) else: @@ -296,7 +296,7 @@ def test_set_interface(self): disable=True) self.assertTrue(result, 'dut=%s' % dut) config = dut.run_commands(command, encoding='text') - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': self.assertNotIn('vrf blah', config[0]['output'], 'dut=%s' % dut) dut.config(['no vrf instance blah', diff --git a/test/system/test_api_vrrp.py b/test/system/test_api_vrrp.py index 8be4109..9a20060 100644 --- a/test/system/test_api_vrrp.py +++ b/test/system/test_api_vrrp.py @@ -73,7 +73,7 @@ def test_get(self): vrid = 98 for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'vrrp %d disabled' % vrid, 'exit']) @@ -90,7 +90,7 @@ def test_getall(self): vrid2 = 198 for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'vrrp %d disabled' % vrid, 'exit', @@ -136,7 +136,7 @@ def test_delete(self): vrid = 101 for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -154,7 +154,7 @@ def test_default(self): vrid = 102 for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -224,7 +224,7 @@ def test_set_enable(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -253,7 +253,7 @@ def test_set_primary_ip(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -280,7 +280,7 @@ def test_set_priority(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -307,7 +307,7 @@ def test_set_description(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -332,7 +332,7 @@ def test_set_secondary_ips(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -360,7 +360,7 @@ def test_set_ip_version(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -387,7 +387,7 @@ def test_set_timers_advertise(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -414,7 +414,7 @@ def test_set_mac_addr_adv_interval(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -442,7 +442,7 @@ def test_set_preempt(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -469,7 +469,7 @@ def test_set_preempt_delay_min(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -496,7 +496,7 @@ def test_set_preempt_delay_reload(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -523,7 +523,7 @@ def test_set_delay_reload(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -562,7 +562,7 @@ def test_set_tracks(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, @@ -589,7 +589,7 @@ def test_set_bfd_ip(self): ] for dut in self.duts: interface = self._vlan_setup(dut) - if dut.version_id >= '4.23': + if dut.version_number >= '4.23': dut.config(['interface %s' % interface, 'no vrrp %d' % vrid, 'vrrp %d disabled' % vrid, diff --git a/test/unit/test_api_vrrp.py b/test/unit/test_api_vrrp.py index 15c8f15..0d653ec 100644 --- a/test/unit/test_api_vrrp.py +++ b/test/unit/test_api_vrrp.py @@ -419,7 +419,6 @@ def test_set_description(self): def test_set_ip_version(self): # vrrp 10 ip version 2 - # Test set_description gives properly formatted commands cases = [ (2, None, None, 'vrrp %d ip version 2' % upd_vrid), diff --git a/test/unit/test_utils.py b/test/unit/test_utils.py index ed44123..46d2d01 100644 --- a/test/unit/test_utils.py +++ b/test/unit/test_utils.py @@ -24,17 +24,17 @@ def test_load_module_raises_import_error(self, mock_import_module): def test_make_iterable_from_string(self): result = pyeapi.utils.make_iterable('test') self.assertIsInstance(result, collections.Iterable) - self.assertEquals(len(result), 1) + self.assertEqual(len(result), 1) def test_make_iterable_from_unicode(self): result = pyeapi.utils.make_iterable(u'test') self.assertIsInstance(result, collections.Iterable) - self.assertEquals(len(result), 1) + self.assertEqual(len(result), 1) def test_make_iterable_from_iterable(self): result = pyeapi.utils.make_iterable(['test']) self.assertIsInstance(result, collections.Iterable) - self.assertEquals(len(result), 1) + self.assertEqual(len(result), 1) def test_make_iterable_raises_type_error(self): with self.assertRaises(TypeError): From 58e08e8761d90ffe4ece739d77b31bc876aee77a Mon Sep 17 00:00:00 2001 From: Andrii Rykhlivskyi Date: Sun, 26 Jan 2020 12:08:25 +0000 Subject: [PATCH 21/21] Add release version 0.8.3 --- VERSION | 2 +- docs/release-notes-0.8.3.rst | 25 +++++++++++++++++++++++++ pyeapi/__init__.py | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 docs/release-notes-0.8.3.rst diff --git a/VERSION b/VERSION index 8a6a5a9..ee94dd8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.2-rc0 +0.8.3 diff --git a/docs/release-notes-0.8.3.rst b/docs/release-notes-0.8.3.rst new file mode 100644 index 0000000..bc21a05 --- /dev/null +++ b/docs/release-notes-0.8.3.rst @@ -0,0 +1,25 @@ +Release 0.8.3 +------------- + +2020-01-26 + +New Modules +^^^^^^^^^^^ + + +Enhancements +^^^^^^^^^^^^ + +* Support eapi command revision syntax (`181 `_) + +* Add ability to use pyeapi with certificates + +* Added check for 'match' statement to be valid before parsing regex ACL + +Fixed +^^^^^ + +Known Caveats +^^^^^^^^^^^^^ + + diff --git a/pyeapi/__init__.py b/pyeapi/__init__.py index 84be709..8708596 100644 --- a/pyeapi/__init__.py +++ b/pyeapi/__init__.py @@ -29,7 +29,7 @@ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -__version__ = '0.8.2-rc0' +__version__ = '0.8.3' __author__ = 'Arista EOS+'