Skip to content

Commit

Permalink
Merge pull request #1132 from balasankarrajaguru/dcs_error_handling
Browse files Browse the repository at this point in the history
DCS error handling
  • Loading branch information
rahkumar651991 committed Sep 9, 2021
2 parents 930970e + cb0aedc commit 7c8a4d6
Show file tree
Hide file tree
Showing 38 changed files with 376 additions and 172 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Pylint

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: [3.7, 3.8]
exclude:
- os: windows-latest
python-version: 3.8

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint
pip install -r requirements.txt
pip install -r development.txt
pip install ntc_templates==1.4.1
pip install textfsm==0.4.1
pip install .
- name: Run black tool
run: |
pip install -U black;
black --check --exclude=docs/* .
- name: Run unit tests
run: |
nosetests -v --with-coverage --cover-package=jnpr.junos --cover-inclusive -a unit
13 changes: 11 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
language: python
matrix:
include:
- python: 2.7
dist: trusty
- python: 3.5
dist: trusty
- python: 3.6
dist: trusty
before_install:
- python3 -m pip install -U pip setuptools setuptools-rust
- python: 3.7
dist: xenial
before_install:
- pip3 install setuptools-rust
- python: 3.8
dist: xenial
- os: windows
language: shell
python: 3.7
before_install:
- choco install python3 --version=3.7.4
- choco install openssl --version=1.1.1.900
- pip install ntc_templates==1.4.1
- pip install textfsm==0.4.1
env:
- PATH=/c/Python37:/c/Python37/Scripts:$PATH
- TRAVIS_PYTHON_VERSION=3.7
- CRYPTOGRAPHY_DONT_BUILD_RUST=1
- INCLUDE='C:\OpenSSL-Win32\include;C:\OpenSSL-win64\include'
- LIB='C:\OpenSSL-Win32\lib;C:\OpenSSL-win64\lib'
addons:
apt:
packages:
Expand All @@ -27,6 +35,7 @@ addons:
- libxslt1-dev

install:
- "set"
- "pip install -r development.txt"
- "pip install -r requirements.txt"
- "pip install ."
Expand Down
20 changes: 4 additions & 16 deletions COPYRIGHT
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@

Copyright (c) 1999-2013, Juniper Networks Inc.
Copyright (c) 1999-2021, Juniper Networks Inc.
2013, Jeremy Schulman

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
License: Apache 2.0

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

* Neither the name of the Juniper Networks nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
THIS SOFTWARE IS PROVIDED BY Juniper Networks Inc. ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
DISCLAIMED. IN NO EVENT SHALL Juniper Networks Inc. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Expand Down
2 changes: 2 additions & 0 deletions development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ nose # http://nose.readthedocs.org/en/latest/
pep8 # https://github.com/jcrocholl/pep8
pyflakes # https://launchpad.net/pyflakes
coveralls # https://coveralls.io/
ntc_templates # user needs to explicitly install this
cryptography==3.2
10 changes: 5 additions & 5 deletions lib/jnpr/junos/cfg/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,22 +196,22 @@ def catalog(self):

@property
def D(self):
""" returns the Device object bound to this resource/manager """
"""returns the Device object bound to this resource/manager"""
return self._junos

@property
def R(self):
""" returns the Device RPC meta object """
"""returns the Device RPC meta object"""
return self._junos.rpc

@property
def M(self):
""" returns the :Resource: manager associated to this resource """
"""returns the :Resource: manager associated to this resource"""
return self._manager

@property
def P(self):
""" returns the parent of the associated Junos object """
"""returns the parent of the associated Junos object"""
return self._parent

# -----------------------------------------------------------------------
Expand Down Expand Up @@ -554,7 +554,7 @@ def __repr__(self):
# ---------------------------------------------------------------------

def __iter__(self):
""" iterate through each Resource in the Manager list """
"""iterate through each Resource in the Manager list"""
for name in self.list:
yield self[name]

Expand Down
2 changes: 1 addition & 1 deletion lib/jnpr/junos/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def _tty_logout(self):
self._tty.logout()

def zeroize(self):
""" perform device ZEROIZE actions """
"""perform device ZEROIZE actions"""
logger.info("zeroize : ZEROIZE device, rebooting")
self._tty.nc.zeroize()
self._skip_logout = True
Expand Down
8 changes: 8 additions & 0 deletions lib/jnpr/junos/dcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from jnpr.junos.device import _Connection
from jnpr.junos.rpcmeta import _RpcMetaExec
from jnpr.junos.factcache import _FactCache
from jnpr.junos import exception as EzErrors
from jnpr.junos import jxml as JXML

from jnpr.junos.decorators import ignoreWarnDecorator
Expand Down Expand Up @@ -144,6 +145,13 @@ def _rpc_reply(self, rpc_cmd_e, *args, **kwargs):
di = self._grpc_types_pb2.DeviceInfo(UUID=self._dev_uuid)
exec = self._grpc_dcs_pb2.GetRequest(command=[rpc_cmd], device_info=di)
res = self._grpc_conn_stub.Get(request=exec, metadata=self._grpc_meta_data)
if res.error_code != self._grpc_types_pb2.NoError:
raise EzErrors.RpcError(
cmd=rpc_cmd,
errs="error-code: '{}' error: '{}'".format(
self._grpc_types_pb2.ErrorCode.Name(res.error_code), res.error
),
)
result = res.result[0].result
reply = RPCReply(result)
errors = reply.errors
Expand Down
4 changes: 4 additions & 0 deletions lib/jnpr/junos/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,12 @@ def wrapper(*args, **kwargs):
restore_value = args[0]._use_filter
args[0]._use_filter = use_filter
try:
if args[0].D != None:
func = args[0].D.transform
result = function(*args, **kwargs)
args[0]._use_filter = restore_value
if args[0].D != None:
args[0].D.transform = func
return result
except Exception:
args[0]._use_filter = restore_value
Expand Down
15 changes: 8 additions & 7 deletions lib/jnpr/junos/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,9 @@ class _Connection(object):
model_dict = {}
with open("/etc/product.conf") as f:
for line in f:
(key, val) = line.strip().split("=")
model_dict[key] = val
if "=" in line:
(key, val) = line.strip().split("=")
model_dict[key] = val

if "model" in model_dict and model_dict["model"] in [
"crpd",
Expand Down Expand Up @@ -246,7 +247,7 @@ def ofacts(self):

@ofacts.setter
def ofacts(self, value):
""" read-only property """
"""read-only property"""
raise RuntimeError("facts is read-only!")

# ------------------------------------------------------------------------
Expand Down Expand Up @@ -339,7 +340,7 @@ def master(self):

@master.setter
def master(self, value):
""" read-only property """
"""read-only property"""
raise RuntimeError("master is read-only!")

# ------------------------------------------------------------------------
Expand Down Expand Up @@ -373,7 +374,7 @@ def uptime(self):

@uptime.setter
def uptime(self, value):
""" read-only property """
"""read-only property"""
raise RuntimeError("uptime is read-only!")

# ------------------------------------------------------------------------
Expand Down Expand Up @@ -438,7 +439,7 @@ def re_name(self):

@re_name.setter
def re_name(self, value):
""" read-only property """
"""read-only property"""
raise RuntimeError("re_name is read-only!")

def _sshconf_lkup(self):
Expand Down Expand Up @@ -874,7 +875,7 @@ def execute(self, rpc_cmd, ignore_warning=False, **kvargs):
or (ver_info.major[0] == 14 and ver_info.major[1] >= 2)
):
try:
return json.loads(rpc_rsp_e.text)
return json.loads(rpc_rsp_e.text, strict=False)
except ValueError as ex:
# when data is {}{.*} types
if str(ex).startswith("Extra data"):
Expand Down
8 changes: 4 additions & 4 deletions lib/jnpr/junos/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,22 +219,22 @@ def __init__(self, dev, msg=None):

@property
def user(self):
""" login user-name """
"""login user-name"""
return self.dev.user

@property
def host(self):
""" login host name/ipaddr """
"""login host name/ipaddr"""
return self.dev.hostname

@property
def port(self):
""" login SSH port """
"""login SSH port"""
return self.dev._port

@property
def msg(self):
""" login SSH port """
"""login SSH port"""
return self._orig

def __repr__(self):
Expand Down
8 changes: 6 additions & 2 deletions lib/jnpr/junos/factcache.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import collections
import warnings
from pprint import pformat

try:
from collections.abc import MutableMapping
except ImportError:
from collections import MutableMapping

import jnpr.junos.facts
from jnpr.junos.facts import __doc__ as facts_doc
import jnpr.junos.exception


class _FactCache(collections.MutableMapping):
class _FactCache(MutableMapping):
"""
A dictionary-like object which performs on-demand fact gathering.
Expand Down
14 changes: 7 additions & 7 deletions lib/jnpr/junos/factory/cfgtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def required_keys(self):

@property
def keys_required(self):
""" True/False - if this Table requires keys """
"""True/False - if this Table requires keys"""
return self.required_keys is not None

# -----------------------------------------------------------------------
Expand Down Expand Up @@ -158,7 +158,7 @@ def _build_config_xml(self, top):
add_field = self._grindfield(lxpath[-1], field_value)
for _add in add_field:
if len(_add.attrib) > 0:
for i in dot.getiterator():
for i in dot.iter():
if i.tag == _add.tag:
i.attrib.update(_add.attrib)
break
Expand Down Expand Up @@ -258,15 +258,15 @@ def _validate_min_max_value(field_name, value, opt):
_validate_min_max_value(field_name, value, opt)

def _grindkey(self, key_xpath, key_value):
""" returns list of XML elements for key values """
"""returns list of XML elements for key values"""
simple = lambda: [E(key_xpath.replace("_", "-"), key_value)]
composite = lambda: [
E(xp.replace("_", "-"), xv) for xp, xv in zip(key_xpath, key_value)
]
return simple() if isinstance(key_xpath, str) else composite()

def _grindxpath(self, key_xpath, key_value):
""" returns xpath elements for key values """
"""returns xpath elements for key values"""
simple = lambda: "[{}='{}']".format(key_xpath.replace("_", "-"), key_value)
composite = lambda: "[{}]".format(
" and ".join(
Expand All @@ -279,7 +279,7 @@ def _grindxpath(self, key_xpath, key_value):
return simple() if isinstance(key_xpath, str) else composite()

def _grindfield(self, xpath, value):
""" returns list of xml elements for field name-value pairs """
"""returns list of xml elements for field name-value pairs"""
lst = []
if isinstance(value, (list, tuple, set)):
for v in value:
Expand Down Expand Up @@ -359,7 +359,7 @@ def _encode_xpath(self, top, lst):
return dot

def _keyspec(self):
""" returns tuple (keyname-xpath, item-xpath) """
"""returns tuple (keyname-xpath, item-xpath)"""
return (self._data_dict.get("key", "name"), self._data_dict[self._type])

def _init_field(self):
Expand All @@ -371,7 +371,7 @@ def _init_field(self):
self.__dict__[fname] = opt["default"] if "default" in opt else None

def _mandatory_check(self):
""" Mandatory checks for set table/view """
"""Mandatory checks for set table/view"""
for key in self.key_field:
value = getattr(self, key)
if value is None:
Expand Down

0 comments on commit 7c8a4d6

Please sign in to comment.