Skip to content

Commit 7bcbb02

Browse files
committed
Pull request #1: SOFT-8495
Merge in NCA/pysros from ~RICCARDOV/pysros:SOFT-8495 to master * commit 'fb4f3a679005ca4f7202d4acd3fa97e7c0e23feb': Replacing dependency_links which does not work with tox Add copyright Add packaging and QA Remove redundant variable Correct setup.py Add setup, requirements and decorator Create command line script Initial Commit
2 parents b360571 + fb4f3a6 commit 7bcbb02

File tree

8 files changed

+264
-0
lines changed

8 files changed

+264
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# pySROS
2+
Python library to interact with Nokia SROS napalm driver.
3+
4+
## License
5+
6+
Copyright 2021 LINX
7+
8+
Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0

configuration/config.yml.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
username: xxx
2+
password: xxx

pylintrc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[MASTER]
2+
extension-pkg-whitelist=lxml
3+
4+
[MESSAGES CONTROL]
5+
disable=fixme,
6+
no-value-for-parameter,
7+
too-few-public-methods,
8+
not-callable,
9+
no-name-in-module,
10+
argument-differ,
11+
missing-module-docstring
12+
13+
[BASIC]
14+
good-names=e,i,j,k
15+
# Enabling two chars variables
16+
argument-rgx=(([a-z_][a-z0-9_]{1,})|(_[a-z0-9_]*)|(__[a-z][a-z0-9_]+__))$
17+
attr-rgx=(([a-z_][a-z0-9_]{1,})|(_[a-z0-9_]*)|(__[a-z][a-z0-9_]+__))$
18+
variable-rgx=(([a-z_][a-z0-9_]{1,})|(_[a-z0-9_]*)|(__[a-z][a-z0-9_]+__))$
19+
20+
[TYPECHECK]
21+
ignored-classes=optparse.Values,thread._local,_thread._local,linxapi.LinxClient
22+
23+
[REPORTS]
24+
reports=yes

pysros/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copyright (c) 2021 London Internet Exchange Ltd.
2+
3+
__version__ = "0.0.1"

pysros/command_line.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Copyright (c) 2021 London Internet Exchange Ltd.
2+
3+
import argparse
4+
import logging
5+
import textwrap
6+
import time
7+
8+
import napalm # pylint: disable=import-error
9+
import yaml # pylint: disable=import-error
10+
11+
logging.basicConfig()
12+
# logging.getLogger('').setLevel(logging.DEBUG)
13+
14+
15+
def time_func(func):
16+
""" Decorator adding the execution time for the decorated function """
17+
def wrapper():
18+
t1 = time.time()
19+
func()
20+
t2 = time.time()
21+
print(f'Function: "{func.__name__}", completed in: "{t2 - t1}" s')
22+
return wrapper
23+
24+
25+
def parse_and_get_args():
26+
"""
27+
Create arg parser.
28+
Returns: argparse.ArgumentParser
29+
30+
"""
31+
parser = argparse.ArgumentParser(
32+
description='Diff and Replace/Merge configs.',
33+
formatter_class=argparse.RawTextHelpFormatter
34+
)
35+
36+
parser.add_argument(
37+
'config_file_path',
38+
help='Config file with user details like username and password',
39+
)
40+
41+
parser.add_argument(
42+
'hostname',
43+
help='Hostname of the switch',
44+
)
45+
46+
parser.add_argument(
47+
'action',
48+
choices=[
49+
'diff',
50+
'replace',
51+
'merge',
52+
'running'
53+
],
54+
help=textwrap.dedent("""
55+
Please choose one action from below
56+
'diff' Compare Running config with Candidate config.
57+
'replace' Replace Running config with Candidate config.
58+
'merge' Merge Candidate config with Running config.
59+
'running' Get running config from switch and save it to a file.
60+
61+
"""),
62+
)
63+
64+
parser.add_argument(
65+
'-s',
66+
'--save-config-file-path',
67+
dest='save_config_file_path',
68+
default="running.conf",
69+
help=textwrap.dedent("""
70+
File path to save running config in.
71+
If no path is given than file will be saved in current dir
72+
with hostname-action.xml. For example for running config with
73+
hostname foo.bar foo.bar-running.xml will be created.
74+
75+
""")
76+
)
77+
78+
parser.add_argument(
79+
'-f',
80+
'--format',
81+
dest='format',
82+
choices=["xml", "cli"],
83+
default="xml",
84+
help=textwrap.dedent("""
85+
The format in which interact with the Nokia device.
86+
If using a payload its format will overwrite this option.
87+
88+
""")
89+
)
90+
91+
parser.add_argument(
92+
'-c',
93+
'--candidate-file-path',
94+
dest='candidate_file_path',
95+
help='Candidate file path',
96+
)
97+
98+
parser.add_argument(
99+
'-v',
100+
'--verbosity',
101+
action='count',
102+
default=0,
103+
help=textwrap.dedent("""
104+
Set logging verbose level. It accepts a number >= 0.
105+
The default value is 0,
106+
the minimal log besides stack backtrace is given;
107+
Verbose level 1 enables debug level logging for pyocnos;
108+
Verbose level 2 emits ncclient debug level logging as well.
109+
110+
""")
111+
)
112+
113+
args = parser.parse_args()
114+
if any(action in args.action for action in
115+
['diff', 'replace', 'merge']) and not args.candidate_file_path:
116+
parser.error(
117+
"diff, replace and merge action requires -c,"
118+
" --candidate-file-path."
119+
)
120+
return args
121+
122+
123+
@time_func
124+
def main():
125+
""" Main function """
126+
args = parse_and_get_args()
127+
config_path = args.config_file_path
128+
switch_name = args.hostname
129+
operation = args.action
130+
running_conf_path = args.save_config_file_path
131+
candidate_conf_path = args.candidate_file_path
132+
config_format = args.format
133+
134+
with open(config_path) as config_file:
135+
config = yaml.safe_load(config_file)['config']
136+
137+
driver = napalm.get_network_driver('sros')
138+
with driver(hostname=switch_name,
139+
username=config['username'],
140+
timeout=180,
141+
password=config['password']) as device:
142+
if operation == 'running':
143+
# pylint: disable=unexpected-keyword-arg
144+
result = device.get_config(retrieve='running',
145+
optional_args={"format": config_format}
146+
)
147+
with open(running_conf_path, 'w') as running:
148+
running.write(result['running'])
149+
150+
elif operation == 'merge':
151+
device.load_merge_candidate(filename=candidate_conf_path)
152+
device.commit_config()
153+
154+
elif operation == 'replace':
155+
device.load_replace_candidate(filename=candidate_conf_path)
156+
device.commit_config()
157+
158+
elif operation == 'diff':
159+
device.load_replace_candidate(filename=candidate_conf_path)
160+
# pylint: disable=unexpected-keyword-arg
161+
print(device.compare_config(optional_args={"json_format": True}))
162+
163+
164+
if __name__ == '__main__':
165+
main()

setup.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/usr/bin/env python
2+
""" Python simple CLI to interact with Nokia Napalm driver. """
3+
4+
from setuptools import setup, find_packages
5+
6+
version = '0.0.1'
7+
setup(
8+
name='pysros',
9+
version=version,
10+
py_modules=['pysros'],
11+
packages=find_packages(),
12+
install_requires=[
13+
"napalm==3.3.1",
14+
"napalm-sros@git+https://[email protected]/napalm-automation-community/"
15+
"napalm-sros.git",
16+
"PyYAML"
17+
],
18+
include_package_data=True,
19+
description='Python simple CLI to interact with Nokia Napalm Driver',
20+
author='LINX',
21+
author_email='[email protected]',
22+
url='https://github.com/LINXNet/pysros/',
23+
download_url='https://github.com/LINXNet/pysros/tarball/%s' % version,
24+
keywords=['SROS', 'networking'],
25+
classifiers=[
26+
'Programming Language :: Python :: 3'
27+
],
28+
python_requires='~=3.6.6',
29+
entry_points={
30+
'console_scripts': ['pysros=pysros.command_line:main'],
31+
}
32+
)

tests/test_basic_commands.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) 2021 London Internet Exchange Ltd.
2+
3+
def test():
4+
""" test """

tox.ini

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[tox]
2+
envlist = py3-test,py3-lint,py3-flake8
3+
module = pysros
4+
5+
[tox:jenkins]
6+
envlist = py3-test-jenkins,py3-lint-jenkins,py3-flake8
7+
8+
[testenv]
9+
deps=
10+
test: pytest
11+
test: pytest-cov
12+
lint: pylint
13+
flake8: flake8
14+
flake8: flake8-import-order
15+
install_command = pip install --extra-index-url https://dist.linx.net/linx-python {opts} {packages}
16+
whitelist_externals = bash
17+
commands=
18+
test: py.test --cov={envsitepackagesdir}/{[tox]module} --cov-report=xml --cov-report=term-missing --junitxml=test_report_{envname}.xml {posargs}
19+
lint: pylint {[tox]module} tests
20+
# Check that all .py files contain the copyright
21+
lint: bash -c 'for file in $(find {[tox]module} tests -name "*.py" -print); do if ! grep -q "# Copyright (c) [0-9,-]* London Internet Exchange Ltd." $file; then echo "ERROR: Missing copyright in " $file; exit 1; fi; done'
22+
flake8: flake8 {[tox]module} tests --import-order-style=google --application-import-names={[tox]module}
23+
recreate = jenkins: True
24+
25+
[pytest]
26+
junit_family=xunit2

0 commit comments

Comments
 (0)