[Python-modules-commits] [pyiosxr] 01/03: Imported Upstream version 0.14
Vincent Bernat
bernat at moszumanska.debian.org
Sat May 28 15:29:45 UTC 2016
This is an automated email from the git hooks/post-receive script.
bernat pushed a commit to branch master
in repository pyiosxr.
commit 39a7c8dad65c2a0a2f07848429c7246ff18edbf5
Author: Vincent Bernat <bernat at debian.org>
Date: Sat May 28 17:25:06 2016 +0200
Imported Upstream version 0.14
---
MANIFEST.in | 1 +
PKG-INFO | 12 +
pyIOSXR.egg-info/PKG-INFO | 12 +
pyIOSXR.egg-info/SOURCES.txt | 13 +
pyIOSXR.egg-info/dependency_links.txt | 1 +
pyIOSXR.egg-info/requires.txt | 1 +
pyIOSXR.egg-info/top_level.txt | 1 +
pyIOSXR/__init__.py | 15 ++
pyIOSXR/exceptions.py | 31 +++
pyIOSXR/iosxr.py | 338 ++++++++++++++++++++++++
requirements.txt | 1 +
setup.cfg | 8 +
setup.py | 42 +++
test/test.py | 467 ++++++++++++++++++++++++++++++++++
14 files changed, 943 insertions(+)
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..f9bd145
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+include requirements.txt
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..93eaa0b
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 1.1
+Name: pyIOSXR
+Version: 0.14
+Summary: Python API to interact with network devices running IOS-XR
+Home-page: https://github.com/fooelisa/pyiosxr/
+Author: Elisa Jasinska
+Author-email: elisa at bigwaveit.org
+License: UNKNOWN
+Download-URL: https://github.com/fooelisa/pyiosxr/tarball/0.14
+Description: UNKNOWN
+Keywords: IOS-XR,IOSXR,Cisco,networking
+Platform: UNKNOWN
diff --git a/pyIOSXR.egg-info/PKG-INFO b/pyIOSXR.egg-info/PKG-INFO
new file mode 100644
index 0000000..93eaa0b
--- /dev/null
+++ b/pyIOSXR.egg-info/PKG-INFO
@@ -0,0 +1,12 @@
+Metadata-Version: 1.1
+Name: pyIOSXR
+Version: 0.14
+Summary: Python API to interact with network devices running IOS-XR
+Home-page: https://github.com/fooelisa/pyiosxr/
+Author: Elisa Jasinska
+Author-email: elisa at bigwaveit.org
+License: UNKNOWN
+Download-URL: https://github.com/fooelisa/pyiosxr/tarball/0.14
+Description: UNKNOWN
+Keywords: IOS-XR,IOSXR,Cisco,networking
+Platform: UNKNOWN
diff --git a/pyIOSXR.egg-info/SOURCES.txt b/pyIOSXR.egg-info/SOURCES.txt
new file mode 100644
index 0000000..a29ed30
--- /dev/null
+++ b/pyIOSXR.egg-info/SOURCES.txt
@@ -0,0 +1,13 @@
+MANIFEST.in
+requirements.txt
+setup.cfg
+setup.py
+pyIOSXR/__init__.py
+pyIOSXR/exceptions.py
+pyIOSXR/iosxr.py
+pyIOSXR.egg-info/PKG-INFO
+pyIOSXR.egg-info/SOURCES.txt
+pyIOSXR.egg-info/dependency_links.txt
+pyIOSXR.egg-info/requires.txt
+pyIOSXR.egg-info/top_level.txt
+test/test.py
\ No newline at end of file
diff --git a/pyIOSXR.egg-info/dependency_links.txt b/pyIOSXR.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pyIOSXR.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/pyIOSXR.egg-info/requires.txt b/pyIOSXR.egg-info/requires.txt
new file mode 100644
index 0000000..808fb07
--- /dev/null
+++ b/pyIOSXR.egg-info/requires.txt
@@ -0,0 +1 @@
+pexpect
diff --git a/pyIOSXR.egg-info/top_level.txt b/pyIOSXR.egg-info/top_level.txt
new file mode 100644
index 0000000..ba20151
--- /dev/null
+++ b/pyIOSXR.egg-info/top_level.txt
@@ -0,0 +1 @@
+pyIOSXR
diff --git a/pyIOSXR/__init__.py b/pyIOSXR/__init__.py
new file mode 100644
index 0000000..0c5f704
--- /dev/null
+++ b/pyIOSXR/__init__.py
@@ -0,0 +1,15 @@
+# Copyright 2015 Netflix. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from iosxr import IOSXR
diff --git a/pyIOSXR/exceptions.py b/pyIOSXR/exceptions.py
new file mode 100644
index 0000000..d19abf5
--- /dev/null
+++ b/pyIOSXR/exceptions.py
@@ -0,0 +1,31 @@
+# Copyright 2015 Netflix. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+class UnknownError(Exception):
+ pass
+
+class InvalidInputError(Exception):
+ pass
+
+class XMLCLIError(Exception):
+ pass
+
+class TimeoutError(Exception):
+ pass
+
+class EOFError(Exception):
+ pass
+
+class IteratorIDError(Exception):
+ pass
diff --git a/pyIOSXR/iosxr.py b/pyIOSXR/iosxr.py
new file mode 100644
index 0000000..4bfd3a9
--- /dev/null
+++ b/pyIOSXR/iosxr.py
@@ -0,0 +1,338 @@
+# Copyright 2015 Netflix. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+import re
+import sys
+import difflib
+import pexpect
+from exceptions import XMLCLIError, InvalidInputError, TimeoutError, EOFError, IteratorIDError
+
+import xml.etree.ElementTree as ET
+
+
+# Build and execute xml requests.
+def __execute_rpc__(device, rpc_command, timeout):
+ rpc_command = '<?xml version="1.0" encoding="UTF-8"?><Request MajorVersion="1" MinorVersion="0">'+rpc_command+'</Request>'
+ try:
+ device.sendline(rpc_command)
+ index = device.expect_exact(["</Response>","ERROR: 0xa240fe00"], timeout = timeout)
+ if index == 1:
+ raise XMLCLIError('The XML document is not well-formed')
+ except pexpect.TIMEOUT as e:
+ raise TimeoutError("pexpect timeout error")
+ except pexpect.EOF as e:
+ raise EOFError("pexpect EOF error")
+
+ #remove leading XML-agent prompt
+ response_assembled = device.before+device.match
+ response = re.sub('^[^<]*', '', response_assembled)
+
+ root = ET.fromstring(response)
+ if 'IteratorID' in root.attrib:
+ raise IteratorIDError("Non supported IteratorID in Response object. \
+Turn iteration off on your XML agent by configuring 'xml agent [tty | ssl] iteration off'. \
+For more information refer to http://www.cisco.com/c/en/us/td/docs/ios_xr_sw/iosxr_r4-1/xml/programming/guide/xl41apidoc.pdf, \
+7-99.Turn iteration off on your XML agent.")
+
+ childs = [x.tag for x in list(root)]
+
+ result_summary = root.find('ResultSummary')
+
+ if result_summary is not None and int(result_summary.get('ErrorCount', 0)) > 0:
+
+ if 'CLI' in childs:
+ error_msg = root.find('CLI').get('ErrorMsg') or ''
+ elif 'Commit' in childs:
+ error_msg = root.find('Commit').get('ErrorMsg') or ''
+ else:
+ error_msg = root.get('ErrorMsg') or ''
+
+ error_msg += '\nOriginal call was: %s' % rpc_command
+ raise XMLCLIError(error_msg)
+
+ if 'CLI' in childs:
+ cli_childs = [x.tag for x in list(root.find('CLI'))]
+ if 'Configuration' in cli_childs:
+ output = root.find('CLI').find('Configuration').text
+ if output is None:
+ output = ''
+ elif 'Invalid input detected' in output:
+ raise InvalidInputError('Invalid input entered:\n%s' % output)
+
+ return root
+
+# Ecexute show commands not in config context.
+def __execute_show__(device, show_command, timeout):
+ rpc_command = '<CLI><Exec>'+show_command+'</Exec></CLI>'
+ response = __execute_rpc__(device, rpc_command, timeout)
+ return response.find('CLI').find('Exec').text.lstrip()
+
+# Ecexute show commands not in config context.
+def __execute_config_show__(device, show_command, timeout):
+ rpc_command = '<CLI><Configuration>'+show_command+'</Configuration></CLI>'
+ response = __execute_rpc__(device, rpc_command, timeout)
+ return response.find('CLI').find('Configuration').text.lstrip()
+
+
+class IOSXR:
+
+ def __init__(self, hostname, username, password, port=22, timeout=60, logfile=None, lock=True):
+ """
+ A device running IOS-XR.
+
+ :param hostname: (str) IP or FQDN of the device you want to connect to
+ :param username: (str) Username
+ :param password: (str) Password
+ :param port: (int) SSH Port (default: 22)
+ :param timeout: (int) Timeout (default: 60 sec)
+ :param logfile: File-like object to save device communication to or None to disable logging
+ :param lock: (bool) Auto-lock config upon open() if set to True, connect without locking if False (default: True)
+ """
+ self.hostname = str(hostname)
+ self.username = str(username)
+ self.password = str(password)
+ self.port = int(port)
+ self.timeout = int(timeout)
+ self.logfile = logfile
+ self.lock_on_connect = lock
+ self.locked = False
+
+ def __getattr__(self, item):
+ """
+ Ok, David came up with this kind of dynamic method. It takes
+ calls with show commands encoded in the name. I'll replacs the
+ underscores for spaces and issues the show command... pretty neat!
+
+ non keyword params for show command:
+ all non keyword arguments is added to the command to allow dynamic parameters:
+ eks: .show_interface("GigabitEthernet0/0/0/0")
+
+ keyword params for show command:
+ config=True/False : set True to run show command in config mode
+ eks: .show_configuration_merge(config=True)
+
+ """
+ def wrapper(*args, **kwargs):
+ cmd = item.replace('_', ' ')
+ for arg in args:
+ cmd += " %s" % arg
+
+ if kwargs.get("config"):
+ response = __execute_config_show__(self.device, cmd, self.timeout)
+ else:
+ response = __execute_show__(self.device, cmd, self.timeout)
+
+ match = re.search(".*(!! IOS XR Configuration.*)</Exec>",response,re.DOTALL)
+
+ if match is not None:
+ response = match.group(1)
+ return response
+
+ if item.startswith('show'):
+ return wrapper
+ else:
+ raise AttributeError("type object '%s' has no attribute '%s'" % (self.__class__.__name__, item))
+
+ def make_rpc_call(self, rpc_command):
+ """
+ Allow a user to query a device directly using XML-requests
+ """
+ result = __execute_rpc__(self.device, rpc_command, self.timeout)
+ return ET.tostring(result)
+
+ def open(self):
+ """
+ Opens a connection to an IOS-XR device.
+ """
+ device = pexpect.spawn('ssh -o ConnectTimeout={} -p {} {}@{}'.format(self.timeout, self.port, self.username, self.hostname), logfile=self.logfile)
+ try:
+ index = device.expect(['\(yes\/no\)\?', 'password:', '#', pexpect.EOF], timeout = self.timeout)
+ if index == 0:
+ device.sendline('yes')
+ index = device.expect(['\(yes\/no\)\?', 'password:', '#', pexpect.EOF], timeout = self.timeout)
+ if index == 1:
+ device.sendline(self.password)
+ elif index == 3:
+ pass
+ if index != 2:
+ device.expect('#', timeout = self.timeout)
+ device.sendline('xml')
+ index = device.expect(['XML>', 'ERROR: 0x24319600'], timeout = self.timeout)
+ if index == 1:
+ raise XMLCLIError('XML TTY agent has not been started. Please configure \'xml agent tty\'.')
+ except pexpect.TIMEOUT as e:
+ raise TimeoutError("pexpect timeout error")
+ except pexpect.EOF as e:
+ raise EOFError("pexpect EOF error")
+ self.device = device
+ if self.lock_on_connect:
+ self.lock()
+
+ def close(self):
+ """
+ Closes the connection to the IOS-XR device.
+ """
+ if self.lock_on_connect or self.locked:
+ self.unlock()
+ self.device.close()
+
+ def lock(self):
+ """
+ Locks the IOS-XR device config.
+ """
+ if not self.locked:
+ rpc_command = '<Lock/>'
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
+ self.locked = True
+
+ def unlock(self):
+ """
+ Unlocks the IOS-XR device config.
+ """
+ if self.locked:
+ rpc_command = '<Unlock/>'
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
+ self.locked = False
+
+ def load_candidate_config(self, filename=None, config=None):
+ """
+ Populates the attribute candidate_config with the desired
+ configuration and loads it into the router. You can populate it from
+ a file or from a string. If you send both a filename and a string
+ containing the configuration, the file takes precedence.
+
+ :param filename: Path to the file containing the desired
+ configuration. By default is None.
+ :param config: String containing the desired configuration.
+ """
+ configuration = ''
+
+ if filename is None:
+ configuration = config
+ else:
+ with open(filename) as f:
+ configuration = f.read()
+
+ rpc_command = '<CLI><Configuration>'+configuration+'</Configuration></CLI>'
+
+ try:
+ __execute_rpc__(self.device, rpc_command, self.timeout)
+ except InvalidInputError as e:
+ self.discard_config()
+ raise InvalidInputError(e.message)
+
+ def get_candidate_config(self, merge=False, formal=False):
+ """
+ Retrieve the configuration loaded as candidate config in your configuration session
+
+ :param merge: Merge candidate config with running config to return
+ the complete configuration including all changed
+ :param formal: Return configuration in IOS-XR formal config format
+ """
+ command="show configuration"
+ if merge:
+ command+=" merge"
+ if formal:
+ command+=" formal"
+ response = __execute_config_show__(self.device, command, self.timeout)
+
+ match = re.search(".*(!! IOS XR Configuration.*)$",response,re.DOTALL)
+ if match is not None:
+ response = match.group(1)
+
+ return response
+
+ def compare_config(self):
+ """
+ Compares executed candidate config with the running config and
+ returns a diff, assuming the loaded config will be merged with the
+ existing one.
+
+ :return: Config diff.
+ """
+ show_merge = __execute_config_show__(self.device, 'show configuration merge', self.timeout)
+ show_run = __execute_config_show__(self.device, 'show running-config', self.timeout)
+
+ diff = difflib.unified_diff(show_run.splitlines(1)[2:-2],show_merge.splitlines(1)[2:-2],n=0)
+ diff = ''.join([x.replace('\r', '') for x in diff])
+ return diff
+
+ def compare_replace_config(self):
+ """
+ Compares executed candidate config with the running config and
+ returns a diff, assuming the entire config will be replaced.
+
+ :return: Config diff.
+ """
+ diff = __execute_config_show__(self.device, 'show configuration changes diff', self.timeout)
+
+ return ''.join(diff.splitlines(1)[2:-2])
+
+ def commit_config(self, label=None, comment=None, confirmed=None):
+ """
+ Commits the candidate config to the device, by merging it with the
+ existing one.
+
+ :param label: Commit comment, displayed in the commit entry on the device.
+ :param comment: Commit label, displayed instead of the commit ID on the device.
+ :param confirmed: Commit with auto-rollback if new commit is not made in 30 to 300 sec
+ """
+ rpc_command = '<Commit'
+ if label:
+ rpc_command += ' Label="%s"' % label
+ if comment:
+ rpc_command += ' Comment="%s"' % comment
+ if confirmed:
+ if 30 <= int(confirmed) <= 300:
+ rpc_command += ' Confirmed="%d"' % int(confirmed)
+ else: raise InvalidInputError('confirmed needs to be between 30 and 300')
+ rpc_command += '/>'
+
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
+
+ def commit_replace_config(self, label=None, comment=None, confirmed=None):
+ """
+ Commits the candidate config to the device, by replacing the existing
+ one.
+
+ :param comment: User comment saved on this commit on the device
+ :param label: User label saved on this commit on the device
+ :param confirmed: Commit with auto-rollback if new commit is not made in 30 to 300 sec
+ """
+ rpc_command = '<Commit Replace="true"'
+ if label:
+ rpc_command += ' Label="%s"' % label
+ if comment:
+ rpc_command += ' Comment="%s"' % comment
+ if confirmed:
+ if 30 <= int(confirmed) <= 300:
+ rpc_command += ' Confirmed="%d"' % int(confirmed)
+ else: raise InvalidInputError('confirmed needs to be between 30 and 300')
+ rpc_command += '/>'
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
+
+ def discard_config(self):
+ """
+ Clears uncommited changes in the current session.
+ """
+ rpc_command = '<Clear/>'
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
+
+ def rollback(self):
+ """
+ Used after a commit, the configuration will be reverted to the
+ previous committed state.
+ """
+ rpc_command = '<Unlock/><Rollback><Previous>1</Previous></Rollback><Lock/>'
+ response = __execute_rpc__(self.device, rpc_command, self.timeout)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..808fb07
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+pexpect
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..8c9157d
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,8 @@
+[metadata]
+description-file = README.md
+
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..e674e3a
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,42 @@
+# Copyright 2015 Netflix. All rights reserved.
+#
+# The contents of this file are licensed under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+from setuptools import setup, find_packages
+from pip.req import parse_requirements
+import uuid
+
+# parse_requirements() returns generator of pip.req.InstallRequirement objects
+install_reqs = parse_requirements('requirements.txt', session=uuid.uuid1())
+
+# reqs is a list of requirement
+# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
+reqs = [str(ir.req) for ir in install_reqs]
+
+version = '0.14'
+
+setup(
+ name='pyIOSXR',
+ version=version,
+ py_modules=['pyIOSXR'],
+ packages=find_packages(),
+ install_requires=reqs,
+ include_package_data=True,
+ description = 'Python API to interact with network devices running IOS-XR',
+ author = 'Elisa Jasinska',
+ author_email = 'elisa at bigwaveit.org',
+ url = 'https://github.com/fooelisa/pyiosxr/', # use the URL to the github repo
+ download_url = 'https://github.com/fooelisa/pyiosxr/tarball/%s' % version,
+ keywords = ['IOS-XR', 'IOSXR', 'Cisco', 'networking'],
+ classifiers = [],
+)
diff --git a/test/test.py b/test/test.py
new file mode 100755
index 0000000..bfbff9f
--- /dev/null
+++ b/test/test.py
@@ -0,0 +1,467 @@
+#!/usr/bin/env python
+
+import sys
+import mock
+import unittest
+import xml.etree.ElementTree as ET
+
+import pexpect
+from pyIOSXR import IOSXR
+from pyIOSXR.exceptions import XMLCLIError, InvalidInputError, TimeoutError, EOFError, IteratorIDError
+
+
+## XXX TODO
+
+# def __execute_rpc__(device, rpc_command, timeout):
+# def __execute_show__(device, show_command, timeout):
+# def __execute_config_show__(device, show_command, timeout):
+
+# test class IOSXR
+# def __getattr__(self, item):
+
+## XXX
+
+
+# def __init__(self, hostname, username, password, port=22, timeout=60, logfile=None, lock=True):
+
+class TestInit(unittest.TestCase):
+
+ def test_init(self):
+ '''
+ Test pyiosxr class init
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd'))
+
+ def test_init_no_lock(self):
+ '''
+ Test pyiosxr class init - woithout locking
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd', lock=False))
+
+ def test_init_log_stdout(self):
+ '''
+ Test pyiosxr class init - log to stdout
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd', logfile=sys.stdout))
+
+ def test_init_log_file(self):
+ '''
+ Test pyiosxr class init - log to file
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd', logfile='filehandle'))
+
+ def test_init_port(self):
+ '''
+ Test pyiosxr class init - pass port number
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22))
+
+ def test_init_timeout(self):
+ '''
+ Test pyiosxr class init - pass timeout
+ Should return True
+ '''
+ self.assertTrue(IOSXR(hostname='hostname', username='ejasinska', password='passwd', timeout=120))
+
+
+# def open(self):
+
+class TestOpen(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn')
+ @mock.patch('pyIOSXR.iosxr.IOSXR.lock')
+ def test_open(self, mock_lock, mock_spawn):
+ '''
+ Test pyiosxr class open
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ self.assertIsNone(device.open())
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn')
+ def test_open_no_lock(self, mock_spawn):
+ '''
+ Test pyiosxr class open - without lock
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ self.assertIsNone(device.open())
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ def test_open_ssh_key_yes(self, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class open - with ssh key warning
+ Should return Nona
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ mock_expect.return_value = 0
+ self.assertIsNone(device.open())
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ def test_open_no_passwd(self, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class open - pexpect.EOF
+ Should return Nona
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ mock_expect.return_value = 3
+ self.assertIsNone(device.open())
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ def test_open_TimeoutError(self, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class open - raising pexpect.TIMEOUT
+ Should return TimeoutError
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ mock_spawn.return_value = None
+ mock_expect.side_effect = pexpect.TIMEOUT('error')
+ self.assertRaises(TimeoutError, device.open)
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ def test_open_EOFError(self, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class open - raising pexpect.EOF
+ Should return EOFError
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ mock_spawn.return_value = None
+ mock_expect.side_effect = pexpect.EOF('error')
+ self.assertRaises(EOFError, device.open)
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ def test_open_XMLCLIError(self, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class open - error as if XML not enabled on device: ERROR: 0x24319600
+ Should return XMLCLIError
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ mock_spawn.return_value = None
+ # expect returns 1 to raise XMLCLIError
+ mock_expect.return_value = 1
+ self.assertRaises(XMLCLIError, device.open)
+
+
+# def close(self):
+
+class TestClose(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.close')
+ def test_close(self, mock_close, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class close
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.close())
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.close')
+ @mock.patch('pyIOSXR.iosxr.IOSXR.lock')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_close_locked(self, mock_rpc, mock_lock, mock_close, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class close with lock
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.close())
+
+
+# def lock(self):
+
+class TestLock(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_lock(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class lock
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.lock())
+
+
+# def unlock(self):
+
+class TestUnlock(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.IOSXR.lock')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_unlock(self, mock_rpc, mock_lock, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class unlock
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=True)
+ mock_spawn.return_value = None
+ device.open()
+ device.locked = True
+ self.assertIsNone(device.unlock())
+
+
+# def discard_config(self):
+
+class TestDiscardConfig(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_discard_config(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class discard_config
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.discard_config())
+
+
+# def rollback(self):
+
+class TestRollback(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_rollback(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class rollback
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.rollback())
+
+
+# def make_rpc_call(self, rpc_command):
+
+class TestMakeRpcCall(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_make_rpc_call(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class make_rpc_call
+ Should return True
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ mock_rpc.return_value = ET.fromstring('<xml></xml>')
+ device.open()
+ self.assertTrue(device.make_rpc_call("<Get><Operational><LLDP><NodeTable></NodeTable></LLDP></Operational></Get>"))
+
+
+# def load_candidate_config(self, filename=None, config=None):
+
+class TestLoadCandidateConfig(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_load_candidate_config_file(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class load_candidate_config
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.load_candidate_config(filename='test/config.txt'))
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_load_candidate_config(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class load_candidate_config
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.load_candidate_config(config='config'))
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.IOSXR.discard_config')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_load_candidate_config_InvalidInputError(self, mock_rpc, mock_discard, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class load_candidate_config
+ Should return InvalidInputError
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ mock_rpc.side_effect = InvalidInputError('error')
+ device.open()
+ self.assertRaises(InvalidInputError, device.load_candidate_config, config='config')
+
+
+# def get_candidate_config(self, merge=False, formal=False):
+
+class TestGetCandidateConfig(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_config_show__')
+ def test_get_candidate_config(self, mock_config, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class get_candidate_config
+ Should return True
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ mock_config.return_value = '!! IOS XR Configuration'
+ self.assertTrue(device.get_candidate_config(merge=True, formal=True))
+
+
+# def compare_config(self):
+
+class TestCompareConfig(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_config_show__')
+ def test_compare_config(self, mock_config, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class compare_config
+ Should return True
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ mock_config.return_value = ''
+ self.assertEqual('', device.compare_config())
+
+
+# def compare_replace_config(self):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_config_show__')
+ def test_compare_replace_config(self, mock_config, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class compare_replace_config
+ Should return True
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ mock_config.return_value = ''
+ self.assertEqual('', device.compare_replace_config())
+
+
+# def commit_config(self, label=None, comment=None, confirmed=None):
+
+class TestCommitConfig(unittest.TestCase):
+
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.__init__')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.expect')
+ @mock.patch('pyIOSXR.iosxr.pexpect.spawn.sendline')
+ @mock.patch('pyIOSXR.iosxr.__execute_rpc__')
+ def test_commit_config(self, mock_rpc, mock_sendline, mock_expect, mock_spawn):
+ '''
+ Test pyiosxr class commit_config
+ Should return None
+ '''
+ device = IOSXR(hostname='hostname', username='ejasinska', password='passwd', port=22, timeout=60, logfile=None, lock=False)
+ mock_spawn.return_value = None
+ device.open()
+ self.assertIsNone(device.commit_config(label='label', comment='comment', confirmed=30))
+
... 50 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pyiosxr.git
More information about the Python-modules-commits
mailing list