From 0a76cd899d9ced3b14c01595465ac0cc6e6295fc Mon Sep 17 00:00:00 2001 From: Mircea Ulinic Date: Tue, 23 Jul 2019 14:09:43 +0100 Subject: [PATCH] Relese a1 --- napalm_iosxr_grpc/xrgrpc.py | 75 +++++++++++++++++++++++-------------- setup.py | 13 +++++-- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/napalm_iosxr_grpc/xrgrpc.py b/napalm_iosxr_grpc/xrgrpc.py index 4ccb14a..7917989 100644 --- a/napalm_iosxr_grpc/xrgrpc.py +++ b/napalm_iosxr_grpc/xrgrpc.py @@ -11,11 +11,12 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. -""" +''' gRPC-based NAPALM driver for IOS-XR. -""" +''' from __future__ import unicode_literals +import json import logging import napalm.base.helpers @@ -26,17 +27,21 @@ ConnectionException, CommandErrorException, SessionLockedException, + CommandTimeoutException ) +import grpc.framework.interfaces.face.face from iosxr_grpc.cisco_grpc_client import CiscoGRPCClient +log = logging.getLogger(__name__) + class gRPCXRDriver(NetworkDriver): - """ + ''' gRPCXRDriver driver class. - """ + ''' def __init__(self, hostname, username, password, timeout=60, optional_args=None): - """Constructor.""" + '''Constructor.''' self.device = None self.hostname = hostname self.username = username @@ -45,29 +50,22 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None) self.optional_args = {} if optional_args: self.optional_args = optional_args - self.port = self.optional_args.get("port", 57777) - self.tls_key = self.optional_args.get("tls_key") - self.tls_server_name = self.optional_args.get("tls_server_name") + self.port = self.optional_args.get('port', 57777) + self.tls_key = self.optional_args.get('tls_key') + self.tls_server_name = self.optional_args.get('tls_server_name') - def open(self): - """Establish connection with the network device.""" - log.debug("Establishing the connection over gRPC as %s@%s:%d", self.username, self.hostname, self.port) - self.driver = CiscoGRPCClient( - self.hostname, - self.port, - self.timeout, - self.username, - self.password - ) - raise_err = None - raise_class = ConnectionException - err, result = self.driver.showcmdtextoutput("show clock") + def _execute(self, method, *args, **kwargs): + fmt = kwargs.pop('format', 'json') + try: + err, result = getattr(self.driver, method)(*args, **kwargs) + except grpc.framework.interfaces.face.face.ExpirationError as timeout_err: + raise CommandTimeoutException(timeout_err) if err: err_obj = {} try: - err_obj = ast.literal_eval(err) - except (SyntaxError, ValueError) as parse_err: - log.error('Unable to parse the error return from %s', err, exc_info=True) + err_obj = json.loads(err) + except (json.decoder.JSONDecodeError, TypeError) as parse_err: + log.error('Unable to parse the error from %s', err, exc_info=True) raise_class = None if 'cisco-grpc:errors' in err_obj and 'error' in err_obj['cisco-grpc:errors']: err_msg = err_obj['cisco-grpc:errors']['error'][0] @@ -79,11 +77,32 @@ def open(self): raise_err.error_severity = err_msg['error-severity'] log.error(err_msg['error-message']) raise(raise_err) + if fmt == 'text': + return result + try: + ret = json.loads(result) + except (json.decoder.JSONDecodeError, TypeError) as decode_err: + log.error('Unable to process the return %s', result, exc_info=True) + raise + return ret - def get_facts(self): - """Collecting facts from the device.""" + def open(self): + '''Establish connection with the network device.''' + log.debug('Establishing the connection over gRPC as %s@%s:%d', self.username, self.hostname, self.port) + self.driver = CiscoGRPCClient( + self.hostname, + self.port, + self.timeout, + self.username, + self.password + ) + log.debug('Executing "show clock" to check the connection') + result = self._execute('showcmdtextoutput', 'show clock', format='text') + def get_facts(self): + '''Collecting facts from the device.''' + pass def close(self): - """Disconnect.""" - log.debug("Disconnecting from %s", self.hostname) + '''Disconnect.''' + log.debug('Disconnecting from %s', self.hostname) diff --git a/setup.py b/setup.py index bb8ed23..094d864 100644 --- a/setup.py +++ b/setup.py @@ -7,15 +7,22 @@ reqs = [r for r in fs.read().splitlines() if (len(r) > 0 and not r.startswith("#"))] setup( - name="napalm-mos", - version="2.4.1", - packages=find_packages(), + name="napalm-iosxr-grpc", + version="0.0.1a1", + packages=find_packages(exclude=("test*",)), author="Mircea Ulinic", author_email="ping@mirceaulinic.net", description="Network Automation and Programmability Abstraction Layer with Multivendor support", classifiers=[ "Topic :: Utilities", "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", "Operating System :: POSIX :: Linux", "Operating System :: MacOS", ],