Professional Documents
Culture Documents
1
1.2
1.3
1.4
FAQ 1.5
1.6
1. 1.7
1.7.1
pip 1.7.2
virtualenv, virtualenvwrapper 1.7.3
Python () 1.7.4
1.7.5
2. Python 1.8
Python 1.8.1
Python. iPython 1.8.2
iPython 1.8.2.1
1.8.3
3. Python 1.9
1.9.1
(Strings) 1.9.2
1.9.2.1
1.9.2.2
(List) 1.9.3
1.9.3.1
1.9.3.2
(Dictionary) 1.9.4
1.9.4.1
1.9.4.2
(advanced) 1.9.4.2.1
(Tuple) 1.9.5
2
(Set) 1.9.6
1.9.6.1
1.9.6.2
1.9.6.3
1.9.7
1.9.8
1.9.9
4. 1.10
1.10.1
1.10.2
1.10.3
5. 1.11
if/elif/else 1.11.1
for 1.11.2
for 1.11.2.1
for if 1.11.2.2
enumerate 1.11.2.3
while 1.11.3
break, continue, pass 1.11.4
for/else, while/else 1.11.5
try/except/else/finally 1.11.6
1.11.7
6. 1.12
1.12.1
1.12.2
1.12.3
1.12.4
with 1.12.5
1.12.6
7. 1.13
1.13.1
. 1.13.2
1.13.3
1.13.3.1
3
1.13.3.2
1.13.3.3
1.13.3.4
1.13.3.5
1.13.4
8. 1.14
1.14.1
1.14.2
1.14.3
9. 1.15
re 1.15.1
1.15.2
1.15.3
1.15.4
show ip dhcp snooping
1.15.4.1
1.15.5
10. 1.16
CSV 1.16.1
JSON 1.16.2
YAML 1.16.3
1.16.4
11. 1.17
SQL 1.17.1
SQLite 1.17.2
SQL ( sqlite3 CLI) 1.17.3
CREATE 1.17.3.1
DROP 1.17.3.2
INSERT 1.17.3.3
SELECT 1.17.3.4
WHERE 1.17.3.5
ALTER 1.17.3.6
UPDATE 1.17.3.7
REPLACE 1.17.3.8
4
DELETE 1.17.3.9
ORDER BY 1.17.3.10
sqlite3 1.17.4
SQLite 1.17.4.1
1.17.5
12. 1.18
1.18.1
Pexpect 1.18.2
Telnetlib 1.18.3
Paramiko 1.18.4
Netmiko 1.18.5
netmiko 1.18.5.1
1.18.6
threading 1.18.6.1
multiprocessing 1.18.6.2
1.18.7
13. Jinja 1.19
Jinja 1.19.1
Jinja
1.19.2
Jinja2 1.19.3
1.19.3.1
for 1.19.3.2
if/elif/else 1.19.3.3
1.19.3.4
1.19.3.5
(set) 1.19.3.6
Include 1.19.3.7
1.19.4
1.19.5
14. TextFSM. 1.20
TextFSM 1.20.1
TextFSM 1.20.2
CLI Table 1.20.3
5
1.20.4
15. Ansible 1.21
Ansible 1.21.1
1.21.1.1
Ad-Hoc 1.21.1.2
1.21.1.3
1.21.1.4
playbook 1.21.2
1.21.2.1
1.21.2.2
1.21.3
ios_command 1.21.3.1
ios_facts 1.21.3.2
ios_config 1.21.3.3
lines (commands) 1.21.3.3.1
parents 1.21.3.3.2
1.21.3.3.3
save 1.21.3.3.4
backup 1.21.3.3.5
defaults 1.21.3.3.6
after 1.21.3.3.7
before 1.21.3.3.8
match 1.21.3.3.9
replace 1.21.3.3.10
src 1.21.3.3.11
ntc_ansible 1.21.3.4
Ansible 1.21.4
1.21.5
1.22
1.22.1
subprocess 1.22.1.1
os 1.22.1.2
argparse 1.22.1.3
6
ipaddress 1.22.1.4
1.22.2
sorted 1.22.2.1
lambda 1.22.2.2
zip 1.22.2.3
map 1.22.2.4
filter 1.22.2.5
any all 1.22.2.6
1.23
1.23.1
1.23.2
1.24
Python
:
PyNEng slack
?
, .
, ,
, :
, ,
/ ,
. , , Python,
, .
,
.
, .
.
, CCNA . ,
, , ,
,
.
Python. ,
Python
.
, ,
. ,
.
Cisco. , ,
.
,
/ ,
.
? .
1.
2. Python
3. Python
4.
5.
6.
7.
8.
9.
10.
11.
12.
13. Jinja
14. TextFSM.
15. Ansible
PDF , 600 ,
. 12-15. ,
,
.
. ,
.
, Python
:
Debian Linux
Python 2.7
Python 3.x.
10
: Vagrant VMware.
, .
, , zip
tar.gz.
, , .
, ,
, .
, , , ,
. , , ,
.
, , ,
. , , -
. .
, , ,
.
, , .
zip
tar.gz.
(, 5.2a),
, . ,
, /
.
, , .
. , ,
, , ,
.
, , .
- .
11
stackoverflow . ,
, , , . ,
, . Python ,
, .
,
/ . , , , ,
, , ,
.
.
. .
, .
07.02.2017.
,
. , , .
, ,
, PDF/mobi/epub. , , ,
, .
2-6
.
Gitbook , ,
.
12
PDF/ePub/Mobi
, .
, . ,
.
GitBook .
GitBook .
, - ,
:
, :
13
,
. , ,
, .
, ,
.
, , , :
, :
14
15
1 :
:
,
, Python
, Ansible.
Python.
Ansible,
show .
, Ansible ,
:
, , , alias
,
- Ansible,
Python, 2.
2 : Python
Python , ,
.
, , , ,
. , ,
, .
(
)
- , "
"
16
,
:
, , ,
, , ,
. ,
, ,
. ,
, , .
, , , .
! . , ,
.
, ,
. :
, , .
, , , .
, .
, , - .
,
.
.
2-4 , .
, - . .
.
.
, ,
, .
github .
, .
- - .
, , .
, , ,
Python. , Python
17
. / ,
. -.
18
, .
. ,
. , ,
, .
, ,
.
0
Python
1 Python
2
3
4
5
6
7
8 Jinja Jinja2
9 TextFSM
TextFSM
10 Ansible Ansible
19
FAQ
?
(
)
, ,
. ?
, .
,
.
, ,
, ,
,
,
, -
, , "
". .
,
. , ,
. .
, , ,
. Ansible, , .
python? , Ansible .
, , - .
, ,
, Python.
, Python,
/ , Ansible. ,
, .
20
FAQ
- , Ansible,
:)
, Python
. , ,
. , -
. log-.
Python .
" "?
:
.
-
. , Python.
, -
,
, .
, .
,
, -
, . ,
- .
Python?
python.
python API,
Python
Python .
, -
, - , ,
Python
Python .
Python ,
. , , , ,
, ,
21
FAQ
, , Python GNS3
, , Python
, "" . ,
.
, . ,
.
, . " Python" .
"" .
:)
. ,
. .
. - ,
. .
:)
, ,
python 3.x.
, .
, , ,
python 3. , , python 2.
, , python 3.x.
.
, :) , .
, , . , ,
Ansible. , .
22
FAQ
show.
().
show , 2-3 .
.
, .
Ansible
.
?
, .
, , SDN, .
, :
, , , -,
.
,
.
: show 20
, . , SSH
. ?
, . ,
, ,
.
, , . ,
. , . .
" ". ,
. - . ,
, ,
/ .
23
FAQ
, " "
3 . ,
:)
. , : CLI unix,
.
, - . , :
,
, , -
, , " "
, " ". .
- ?
, , , .
"Python ".
. .
24
, . ,
- .
, , .
. ,
, , .
, :)
.
. ,
. , !
25
1.
Python, , Python
.
Windows, , , Python .
Windows, Anaconda.
IDE Spyder, .
Ansible Linux.
- .
.
IDE , , IDE - :
( Python)
. ,
.
, , IDE
.
IDE Python . ,
PyCharm ( Windows) Spyder.
Linux/Unix. ,
. , , ,
- .
26
, Python, :
Python
. , Python
2.7, .
Windows, , , Ansible
Linux/Unix.
, ,
Ansible.
Debian Linux
vim ( ,
)
Python 2.7
Python 2.7, , .
(vim emacs ):
Linux:
gEdit
nano
Sublime Text
geany
Mac OS
TextMate
TextWrangler
Windows:
Notepad++
,
.
, , , Debian Linux.
.
27
28
pip
pip
Python, ,
pip.
pip - ,
Python Package Index (PyPi).
, Python, pip.
pip:
$ pip --version
pip 1.1 from /usr/lib/python2.7/dist-packages (python 2.7)
, pip . :
29
virtualenv, virtualenvwrapper
virtualenv, virtualenvwrapper
virtualenv - , .
, ,
, 1 1.0, 2
, 3.1
, ,
virtualenvwrapper:
virtualenv.
virtualenvwrapper pip:
, .bashrc
export WORKON_HOME=~/venv
. /usr/local/bin/virtualenvwrapper.sh
WORKON_HOME - . -
, virtualenvwrapper):
virtualenvwrapper.sh
, bash. , :
exec bash
.
stackoverflow.
30
virtualenv, virtualenvwrapper
$ mkvirtualenv PyNEng
New python executable in PyNEng/bin/python
Installing distribute........................done.
Installing pip...............done.
(PyNEng)$
(
). , .
virtualenvwrapper Tab
.
, .
, WORKON_HOME,
PyNEng:
(PyNEng)$ deactivate
$
, workon:
$ workon PyNEng
(PyNEng)$
,
deactivate, workon:
$ workon Test
(Test)$ workon PyNEng
(PyNEng)$
31
virtualenv, virtualenvwrapper
, rmvirtualenv:
$ rmvirtualenv Test
Removing Test...
$
(PyNEng)$ lssitepackages
ANSI.py pexpect-3.3-py2.7.egg-info
ANSI.pyc pickleshare-0.5-py2.7.egg-info
decorator-4.0.4-py2.7.egg-info pickleshare.py
decorator.py pickleshare.pyc
decorator.pyc pip-1.1-py2.7.egg
distribute-0.6.24-py2.7.egg pxssh.py
easy-install.pth pxssh.pyc
fdpexpect.py requests
fdpexpect.pyc requests-2.7.0-py2.7.egg-info
FSM.py screen.py
FSM.pyc screen.pyc
IPython setuptools.pth
ipython-4.0.0-py2.7.egg-info simplegeneric-0.8.1-py2.7.egg-info
ipython_genutils simplegeneric.py
ipython_genutils-0.1.0-py2.7.egg-info simplegeneric.pyc
path.py test_path.py
path.py-8.1.1-py2.7.egg-info test_path.pyc
path.pyc traitlets
pexpect traitlets-4.0.0-py2.7.egg-info
(requirements)
, ,
. ,
, .
Python ( ) .
requirements.txt , (
requirements.txt):
32
virtualenv, virtualenvwrapper
Jinja2==2.8
pexpect==4.0.1
tornado==4.3
...
, ,
,
:
,
,
.
, simplejson.
ipython ( ipython)
simplejson, :
(PyNEng)$ ipython
In [2]: simplejson
simplejson
In [2]: simplejson.
simplejson.Decimal simplejson.decoder
simplejson.JSONDecodeError simplejson.dump
simplejson.JSONDecoder simplejson.dumps
simplejson.JSONEncoder simplejson.encoder
simplejson.JSONEncoderForHTML simplejson.load
simplejson.OrderedDict simplejson.loads
simplejson.absolute_import simplejson.scanner
simplejson.compat simplejson.simple_first
33
virtualenv, virtualenvwrapper
, , ,
:
(PyNEng)$ deactivate
$ ipython
34
Python ()
Python ()
, , Python,
:
$ python
Python 2.7.3 (default, Mar 13 2014, 11:03:55)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
python,
quit() Ctrl+D
35
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
1.1
: .
,
Linux (Debian),
,
Python 2.7
, Python pip
,
/IDE
36
12, .
37
2. Python
Python
:
Python
Python
38
Python
Python
, , , , Python,
, :
Python:
a = 10
b = 5
if a > b:
print "A B"
print " -"
else:
print "B A"
print " "
, .
Python .
, if/else,
.
Python if . if
a > b , ,
if a > b .
else.
Python:
(, if a > b else).
Tab .
, , Tab 4 (,
Tab, 4 )
.
39
Python
2-4 ( 4
)
,
, .
: .
, .
Python.
, . ,
.
Python :
#
a = 10
b = 5 #
#.
, ,
.
,
, :
"""
"""
a = 10
b = 5
, ,
, , -
.
40
Python. iPython
Python. iPython
.
, :
enter ( ,
cisco).
Python : (,
, ) , enter ..
, Python,
.
, , Python iPython
( iPython).
iPython , ,
python.
( ipython ):
Tab ,
"" %history
iPython pip (
):
ipython , pip,
:
apt pip, :
41
Python. iPython
pip ipython :
wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py
apt-get install python-dev
pip install ipython
iPython.
In [1]: 1 + 2
Out[1]: 3
In [2]: 22*45
Out[2]: 990
In [3]: 2**3
Out[3]: 8
iPython :
In - ,
Out - ( )
In Out
iPython
, , ,
... . ,
Enter:
42
Python. iPython
print
print .
,
( ). , ,
, :
, :
, . ,
,
( , .
).
, file4.py ( ):
print 'Hello!',
print 'Hello!'
, ( Hello
, ):
Hello! Hello!
dir
dir() ,
.
43
Python. iPython
, ( ,
):
In [10]: dir(5)
Out[10]:
['__abs__',
'__add__',
'__and__',
...
'bit_length',
'conjugate',
'denominator',
'imag',
'numerator',
'real']
In [11]: dir('hello')
Out[11]:
['__add__',
'__class__',
'__contains__',
...
'startswith',
'strip',
'swapcase',
'title',
'translate',
'upper',
'zfill']
,
, , :
44
Python. iPython
In [12]: dir()
Out[12]:
[ '__builtin__',
'__builtins__',
'__doc__',
'__name__',
'_dh',
...
'_oh',
'_sh',
'exit',
'get_ipython',
'i',
'quit']
a test:
In [13]: a = 'hello'
In [15]: dir()
Out[15]:
...
'a',
'exit',
'get_ipython',
'i',
'quit',
'test']
45
iPython
Magic commands
IPython , .
%.
%history
, %history :
In [1]: a = 10
In [2]: b = 5
In [3]: if a > b:
...: print "A is bigger"
...:
A is bigger
In [4]: %history
a = 10
b = 5
if a > b:
print "A is bigger"
%history
- .
%cpaste
%cpaste
IPython, - ipython,
:
46
iPython
In [1]: a = 10
In [2]: b = 5
In [3]: if a > b:
...: print "A is bigger"
...: else:
...: print "A is less or equal"
...:
A is bigger
In [4]: %hist
a = 10
b = 5
if a > b:
print "A is bigger"
else:
print "A is less or equal"
%hist
In [5]: if a > b:
...: print "A is bigger"
...: else:
...: print "A is less or equal"
...:
File "<ipython-input-8-4d18ff094f5c>", line 3
else:
^
IndentationError: unindent does not match any outer indentation level
If you want to paste code into IPython, try the %paste and %cpaste magic functions.
. IPython
, .
%paste %cpaste -.
%cpaste ( ,
'--'):
In [9]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:if a > b:
: print "A is bigger"
:else:
: print "A is less or equal"
:--
A is bigger
%paste ( Tkinter):
47
iPython
In [10]: %paste
if a > b:
print "A is bigger"
else:
print "A is less or equal"
IPython IPython.
IPython %quickref:
48
iPython
obj?, obj?? : Get help, or more help for object (also works as
?obj, ??obj).
?foo.*abc* : List names in 'foo' containing 'abc' in them.
%magic : Information about IPython's 'magic' % functions.
Magic functions are prefixed by % or %%, and typically take their arguments
without parentheses, quotes or even commas for convenience. Line magics take a
single % and cell magics are prefixed with two %%.
System commands:
History:
_i, _ii, _iii : Previous, next previous, next next previous input
_i4, _ih[2:5] : Input history line 4, lines 2-4
exec _i81 : Execute input history line #81 again
%rep 81 : Edit input history line #81
_, __, ___ : previous, next previous, next next previous output
_dh : Directory history
_oh : Output history
%hist : Command history of current session.
%hist -g foo : Search command history of (almost) all sessions for 'foo'.
%hist -g : Command history of (almost) all sessions.
%hist 1/2-8 : Command history containing lines 2-8 of session 1.
%hist 1/ ~2/ : Command history of session 1 and 2 sessions before current.
49
Python:
(Python
)
,
@, $, %
Python :
In [1]: a = 3
In [2]: b = 'Hello'
In [3]: c, d = 9, 'Test'
In [4]: print a,b,c,d
3 Hello 9 Test
, Python , a , b .
.
id() , :
In [5]: a = b = c = 33
In [6]: id(a)
Out[6]: 31671480
In [7]: id(b)
Out[7]: 31671480
In [8]: id(c)
Out[8]: 31671480
, .
, , a, b c.
, Python , .
-5 256 (). ,
,
.
50
CPython,
.
In [9]: a = 3
In [10]: b = 3
In [11]: id(a)
Out[11]: 4400936168
In [12]: id(b)
Out[12]: 4400936168
In [13]: id(3)
Out[13]: 4400936168
, a , b 3 .
.
, 256:
In [14]: a = 500
In [15]: b = 500
In [16]: id(a)
Out[16]: 140239990503056
In [17]: id(b)
Out[17]: 140239990503032
In [18]: id(500)
Out[18]: 140239990502960
, :
In [19]: a = b = c = 500
51
In [20]: id(a)
Out[20]: 140239990503080
In [21]: id(b)
Out[21]: 140239990503080
In [22]: id(c)
Out[22]: 140239990503080
, a, b c .
Python , :
DB_NAME
db_name
,
get_names
,
CiscoSwitch
52
3. Python
Python
Python :
Numbers ()
Strings ()
Lists ()
Dictionary ()
Tuples ()
Sets ()
Boolean
, ,
:
:
:
:
53
In [1]: 1 + 2
Out[1]: 3
In [2]: 1.0 + 2
Out[2]: 3.0
In [3]: 10 - 4
Out[3]: 6
In [4]: 2**3
Out[4]: 8
int float:
In [5]: 10/3
Out[5]: 3
In [6]: 10/3.0
Out[6]: 3.3333333333333335
In [7]: 10 / float(3)
Out[7]: 3.3333333333333335
In [8]: float(10) / 3
Out[8]: 3.3333333333333335
round :
In [9]: round(10/3.0, 2)
Out[9]: 3.33
In [10]: round(10/3.0, 4)
Out[10]: 3.3333
54
In [11]: 10 % 3
Out[11]: 1
In [13]: 10 < 3
Out[13]: False
In [14]: 10 == 3
Out[14]: False
In [15]: 10 == 10
Out[15]: True
In [16]: 10 <= 10
Out[16]: True
In [17]: 10.0 == 10
Out[17]: True
int() int.
:
In [18]: a = '11'
In [19]: int(a)
Out[19]: 11
, a ,
:
In [20]: int(a, 2)
Out[20]: 3
int float:
In [21]: int(3.333)
Out[21]: 3
In [22]: int(3.9)
Out[22]: 3
55
bin ( ,
):
In [23]: bin(8)
Out[23]: '0b1000'
In [24]: bin(255)
Out[24]: '0b11111111'
, hex() :
In [25]: hex(10)
Out[25]: '0xa'
, , :
, Python math:
In [29]: math.sqrt(9)
Out[29]: 3.0
In [30]: math.sqrt(10)
Out[30]: 3.1622776601683795
In [31]: math.factorial(3)
Out[31]: 6
In [32]: math.pi
Out[32]: 3.141592653589793
56
(Strings)
(Strings)
Python - , .
- , .
In [9]: 'Hello'
Out[9]: 'Hello'
In [10]: "Hello"
Out[10]: 'Hello'
In [12]: tunnel
Out[12]: '\ninterface Tunnel0\n ip address 10.10.10.1 255.255.255.0\n ip mtu 1416\n ip
ospf hello-interval 5\n tunnel source FastEthernet1/0\n tunnel protection ipsec profi
le DMVPN\n'
interface Tunnel0
ip address 10.10.10.1 255.255.255.0
ip mtu 1416
ip ospf hello-interval 5
tunnel source FastEthernet1/0
tunnel protection ipsec profile DMVPN
. :
57
(Strings)
. ,
:
In [18]: intf * 5
Out[18]: 'interfaceinterfaceinterfaceinterfaceinterface'
In [19]: '#' * 40
Out[19]: '########################################'
,
, :
In [21]: string1[0]
Out[21]: 'i'
. , -
, , (
).
In [22]: string1[1]
Out[22]: 'n'
In [23]: string1[-1]
Out[23]: '0'
, ,
( , ):
In [24]: string1[0:9]
Out[24]: 'interface'
In [25]: string1[10:22]
Out[25]: 'FastEthernet'
, :
In [26]: string1[10:]
Out[26]: 'FastEthernet1/0'
58
(Strings)
In [27]: string1[-3:]
Out[27]: '1/0'
In [28]: a = '0123456789'
In [29]: a[::]
Out[29]: '0123456789'
In [30]: a[::-1]
Out[30]: '9876543210'
a[::] a[:] ,
, , , , .
, , a:
In [31]: a[::2]
Out[31]: '02468'
In [32]: a[1::2]
Out[32]: '13579'
59
- , ,
.
( , ), ,
.
, .
In [26]: string1.upper()
Out[26]: 'FASTETHERNET'
In [27]: string1.lower()
Out[27]: 'fastethernet'
In [28]: string1.swapcase()
Out[28]: 'fASTeTHERNET'
In [30]: string2.capitalize()
Out[30]: 'Tunnel 0'
,
. , , -
( ).
- , .
count()
60
count() , ,
:
In [34]: string1.count('hello')
Out[34]: 3
In [35]: string1.count('ello')
Out[35]: 4
In [36]: string1.count('l')
Out[36]: 8
find()
find()
( ):
In [38]: string1.find('Fast')
Out[38]: 10
In [39]: string1[string1.find('Fast')::]
Out[39]: 'FastEthernet0/1'
startswith(), endswith()
( )
( startswith() , endswith() ):
In [41]: string1.startswith('Fast')
Out[41]: True
In [42]: string1.startswith('fast')
Out[42]: False
In [43]: string1.endswith('0/1')
Out[43]: True
In [44]: string1.endswith('0/2')
Out[44]: False
61
replace()
, (
replace() ):
strip()
, . ,
, - ( ). ,
.
, , strip() :
interface FastEthernet0/1
In [49]: string1
Out[49]: '\n\tinterface FastEthernet0/1\n'
In [50]: string1.strip()
Out[50]: 'interface FastEthernet0/1'
strip() .
, , ,
lstrip() rstrip() .
split()
split() , -
( ). , .
.
,
, :
62
In [52]: string1.split()
Out[52]: ['switchport', 'trunk', 'allowed', 'vlan', '10,20,30,100-200']
string1 .
54, strip() , .
strip() , split()
, , .
commands.
, , vlans,
split() . , ,
- . , vlans, VLAN.
split() : ,
, .
show. :
In [59]: sh_ip_int_br.split()
Out[59]: ['FastEthernet0/0', '15.0.15.1', 'YES', 'manual', 'up', 'up']
,
:
63
64
, ,
.
, Python
: .
% ( )
format() ( )
, format ,
% .
format:
%:
%s -
%d - integer
%f - float
.
. ,
, .
,
15 :
65
, .
, :
,
:
In [10]: '{:08b}'.format(10)
Out[10]: '00001010'
zfill:
In [11]: bin(10)[2:].zfill(8)
Out[11]: '00001010'
.
.
66
(List)
(List)
.
Python - ,
.
- , , ,
, :
In [5]: list3[1]
Out[5]: 20
In [6]: list3[1::]
Out[6]: [20, 4.0, 'word']
In [7]: list3[-1]
Out[7]: 'word'
In [8]: list3[::-1]
Out[8]: ['word', 4.0, 20, 1]
, reverse():
In [11]: vlans.reverse()
In [12]: vlans
Out[12]: ['100-200', '30', '20', '15', '10']
, :
67
(List)
In [13]: list3
Out[13]: [1, 20, 4.0, 'word']
In [15]: list3
Out[15]: ['test', 20, 4.0, 'word']
. , ,
:
In [17]: interfaces[0][0]
Out[17]: 'FastEthernet0/0'
In [18]: interfaces[2][0]
Out[18]: 'FastEthernet0/2'
In [19]: interfaces[2][1]
Out[19]: '10.0.2.1'
68
join()
join() ,
join():
In [17]: ','.join(vlans[:-1])
Out[17]: '10,20,30'
append()
append() :
In [19]: vlans.append('300')
In [20]: vlans
Out[20]: ['10', '20', '30', '100-200', '300']
extend()
, .
extend() :
In [23]: vlans.extend(vlans2)
In [24]: vlans
Out[24]: ['10', '20', '30', '100-200', '300', '400', '500']
In [26]: vlans
Out[26]: ['10', '20', '30', '100-200', '300', '400', '500']
69
pop()
pop() , . ,
, :
In [29]: vlans.pop(-1)
Out[29]: '100-200'
In [30]: vlans
Out[30]: ['10', '20', '30']
remove()
remove() .
remove() :
In [32]: vlans.remove('20')
In [33]: vlans
Out[33]: ['10', '30', '100-200']
remove , ,
. , :
In [34]: vlans.remove(-1)
-------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-32-f4ee38810cb7> in <module>()
----> 1 vlans.remove(-1)
index()
70
index() ,
:
In [36]: vlans.index('30')
Out[36]: 2
insert()
insert() :
In [38]: vlans.insert(1,'15')
In [39]: vlans
Out[39]: ['10', '15', '20', '30', '100-200']
71
- , .
list():
In [5]: list2
Out[6]:
['FastEthernet0/0',
'FastEthernet0/1',
'FastEthernet0/2',
'FastEthernet0/3',
'FastEthernet0/4',
'FastEthernet0/5',
'FastEthernet0/6',
'FastEthernet0/7',
'FastEthernet0/8',
'FastEthernet0/9']
72
(Dictionary)
(Dictionary)
- , ( , collections
, OrderedDict).
( , -):
:
, ,
,
, , ,
:
london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'model': '44
51', 'IOS': '15.4'}
london = {
'id': 1,
'name':'London',
'IT_VLAN':320,
'User_VLAN':1010,
'Mngmt_VLAN':99,
'to_name': None,
'to_id': None,
'port':'G1/0/11'
}
, , ,
, , , :
73
(Dictionary)
In [2]: london['name']
Out[2]: 'London1'
In [3]: london['location']
Out[3]: 'London Str'
::
london_co = {
'r1' : {
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'IOS': '15.4',
'IP': '10.255.0.1'
},
'r2' : {
'hostname': 'london_r2',
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'IOS': '15.4',
'IP': '10.255.0.2'
},
'sw1' : {
'hostname': 'london_sw1',
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'IOS': '3.6.XE',
'IP': '10.255.0.101'
}
}
74
(Dictionary)
In [7]: london_co['r1']['IOS']
Out[7]: '15.4'
In [8]: london_co['r1']['model']
Out[8]: '4451'
In [9]: london_co['sw1']['IP']
Out[9]: '10.255.0.101'
75
clear()
clear() :
In [1]: london = {'name': 'London1', 'location': 'London Str', 'vendor': 'Cisco', 'mod
el': '4451', 'IOS': '15.4'}
In [2]: london.clear()
In [3]: london
Out[3]: {}
copy()
copy() .
, :
In [6]: id(london)
Out[6]: 25489072
In [7]: id(london2)
Out[7]: 25489072
In [9]: london2['vendor']
Out[9]: 'Juniper'
london2 , . ,
london, london2,
.
, , copy():
76
In [12]: id(london)
Out[12]: 25524512
In [13]: id(london2)
Out[13]: 25563296
In [15]: london2['vendor']
Out[15]: 'Cisco'
get()
, ,
:
In [17]: london['IOS']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-17-b4fae8480b21> in <module>()
----> 1 london['IOS']
KeyError: 'IOS'
get() , , None .
get() , None :
77
In [25]: london.keys()
Out[25]: ['vendor', 'name', 'location']
In [26]: london.values()
Out[26]: ['Cisco', 'London1', 'London Str']
In [27]: london.items()
Out[27]: [('vendor', 'Cisco'), ('name', 'London1'), ('location', 'London Str')]
del
In [29]: del(london['name'])
In [30]: london
Out[30]: {'location': 'London Str', 'vendor': 'Cisco'}
78
dict .
,
:
In [3]: r1
Out[3]: {'IOS': '15.4', 'model': '4451'}
dict:
In [5]: r1
Out[5]: {'IOS': '15.4', 'model': '4451'}
, , , ,
( ), fromkeys():
In [7]: r1
Out[7]:
{'IOS': None,
'IP': None,
'hostname': None,
'location': None,
'model': None,
'vendor': None}
- .
, :
79
In [18]: d
Out[18]:
{'IOS': None,
'IP': None,
'hostname': None,
'location': None,
'model': None,
'vendor': None}
80
(advanced)
'advanced' , , ,
. , ,
.
In [5]: r1
Out[5]: {'IOS': '15.4', 'model': '4451'}
, ,
, -
.
,
.
zip() , :
In [1]: a = [1,2,3]
In [2]: b = [100,200,300]
In [3]: zip(a,b)
Out[3]: [(1, 100), (2, 200), (3, 300)]
81
In [6]: zip(d_keys,d_values)
Out[6]:
[('hostname', 'london_r1'),
('location', '21 New Globe Walk'),
('vendor', 'Cisco'),
('model', '4451'),
('IOS', '15.4'),
('IP', '10.255.0.1')]
In [7]: dict(zip(d_keys,d_values))
Out[7]:
{'IOS': '15.4',
'IP': '10.255.0.1',
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'}
In [8]: r1 = dict(zip(d_keys,d_values))
In [9]: r1
Out[9]:
{'IOS': '15.4',
'IP': '10.255.0.1',
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'}
, , ,
( )
.
data:
82
In [11]: data = {
....: 'r1': ['london_r1', '21 New Globe Walk', 'Cisco', '4451', '15.4', '10.255.0.1'
],
....: 'r2': ['london_r2', '21 New Globe Walk', 'Cisco', '4451', '15.4', '10.255.0.2'
],
....: 'sw1': ['london_sw1', '21 New Globe Walk', 'Cisco', '3850', '3.6.XE', '10.255
.0.101']
....: }
In [12]: london_co = {}
In [14]: london_co
Out[14]:
{'r1': {'IOS': '15.4',
'IP': '10.255.0.1',
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'},
'r2': {'IOS': '15.4',
'IP': '10.255.0.2',
'hostname': 'london_r2',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'},
'sw1': {'IOS': '3.6.XE',
'IP': '10.255.0.101',
'hostname': 'london_sw1',
'location': '21 New Globe Walk',
'model': '3850',
'vendor': 'Cisco'}}
83
(Tuple)
(Tuple)
.
Python - ,
.
, - , . ,
. .
( ):
In [6]: tuple_keys
Out[6]: ('hostname', 'location', 'vendor', 'model', 'IOS', 'IP')
,
:
In [7]: tuple_keys[0]
Out[7]: 'hostname'
, :
84
(Tuple)
85
(Set)
(Set)
- .
.
Python - ,
.
In [2]: set(vlans)
Out[2]: {10, 20, 30, 40, 100}
86
add()
add() :
In [2]: set1.add(50)
In [3]: set1
Out[3]: {10, 20, 30, 40, 50}
discard()
discard() , ,
:
In [3]: set1
Out[3]: {10, 20, 30, 40, 50}
In [4]: set1.discard(55)
In [5]: set1
Out[5]: {10, 20, 30, 40, 50}
In [6]: set1.discard(50)
In [7]: set1
Out[7]: {10, 20, 30, 40}
clear()
clear() :
In [9]: set1.clear()
In [10]: set1
Out[10]: set()
87
88
,
, .
union()
| :
In [3]: vlans1.union(vlans2)
Out[3]: {10, 20, 30, 50, 100, 101, 102, 200}
intersection()
& :
In [7]: vlans1.intersection(vlans2)
Out[7]: {100}
89
(
, ):
In [1]: set1 = {}
In [2]: type(set1)
Out[2]: dict
In [4]: type(set2)
Out[4]: set
In [6]: set([10,20,30,10,10,30])
Out[6]: {10, 20, 30}
In [8]: set2
Out[8]: {100, 101, 102, 103, 104, 105, 106, 107, 108, 109}
90
Python ,
.
int()
int() - int:
In [1]: int("10")
Out[1]: 10
int
( )
In [2]: int("11111111", 2)
Out[2]: 255
bin()
bin() :
In [3]: bin(10)
Out[3]: '0b1010'
In [4]: bin(255)
Out[4]: '0b11111111'
hex()
:
In [5]: hex(10)
Out[5]: '0xa'
In [6]: hex(255)
Out[6]: '0xff'
list()
91
list() :
In [7]: list("string")
Out[7]: ['s', 't', 'r', 'i', 'n', 'g']
In [8]: list({1,2,3})
Out[8]: [1, 2, 3]
In [9]: list((1,2,3,4))
Out[9]: [1, 2, 3, 4]
set()
set() :
In [10]: set([1,2,3,3,4,4,4,4])
Out[10]: {1, 2, 3, 4}
In [11]: set((1,2,3,3,4,4,4,4))
Out[11]: {1, 2, 3, 4}
,
.
tuple()
tuple() :
In [13]: tuple([1,2,3,4])
Out[13]: (1, 2, 3, 4)
In [14]: tuple({1,2,3,4})
Out[14]: (1, 2, 3, 4)
In [15]: tuple("string")
Out[15]: ('s', 't', 'r', 'i', 'n', 'g')
, .
str()
str() :
92
In [16]: str(10)
Out[16]: '10'
, , VLAN,
, .
join , :
In [18]: ','.join(vlans)
------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-39-d705aed3f1b3> in <module>()
----> 1 ','.join(vlans)
, .
list comprehensions:
93
, :
In [1]: int('a')
------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-42-b3c3f4515dd4> in <module>()
----> 1 int('a')
.
'a'.
, , , , , ,
, ,
.
,
.
isdigit()
Python . ,
, isdigit() :
In [2]: "a".isdigit()
Out[2]: False
In [3]: "a10".isdigit()
Out[3]: False
In [4]: "10".isdigit()
Out[4]: True
isalpha()
94
isalpha() :
In [7]: "a".isalpha()
Out[7]: True
In [8]: "a100".isalpha()
Out[8]: False
isalnum()
isalnum() :
In [11]: "a".isalnum()
Out[1]: True
In [12]: "a10".isalnum()
Out[12]: True
type()
, ,
. , , , ,
.
-, ,
.
type() :
In [13]: type("string")
Out[13]: str
( ):
95
In [15]: type((1,2,3))
Out[15]: tuple
96
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
3.1
ospf_route :
Protocol: OSPF
Prefix: 10.0.24.0/24
AD/Metric: 110/41
Next-Hop: 10.0.13.3
Last update: 3d18h
Outbound Interface: FastEthernet0/0
,
.
97
3.2
MAC XXXX:XXXX:XXXX XXXX.XXXX.XXXX
MAC = "AAAA:BBBB:CCCC"
3.3
CONFIG VLAN ['1', '3', '10', '20', '30', '100'].
3.4
command1 command2 VLAN,
command1 command2. ,
if.
, : [1, 3, 100]
3.5
VLANS - VLAN, ,
VLAN.
VLAN,
.
, if.
3.6
NAT ,
FastEthernet GigabitEthernet.
NAT = "ip nat inside source list ACL interface FastEthernet0/1 overload"
98
3.7
MAC- ( ).
MAC = "AAAA:BBBB:CCCC"
3.8
IP- ( IP)
, :
, :
10
10 1 1 1
00001010 00000001 00000001 00000001
IP = '192.168.3.1'
3.9
.
, num_list, 10 - 4;
word_list, 'ruby' - 6.
( , )
.
: len() .
99
100
4.
, - .
, .
. .
access_template.py :
print '\n'.join(access_template) % 5
, \n ,
VLAN, .
, .
$ python access_template.py
switchport mode access
switchport access vlan 5
switchport nonegotiate
spanning-tree portfast
spanning-tree bpduguard enable
.py .
, windows, , Windows
, .
, , .py.
, " ", Python
.
101
4.
, ,
( access_template_encoding.py):
$ python access_template_encoding.py
File "access_template_encoding.py", line 7
SyntaxError: Non-ASCII character '\xd0' in file access_template_encoding.py on line 7,
but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
,
:
access_template_encoding.py :
102
4.
$ python access_template_encoding.py
access:
switchport mode access
switchport access vlan 5
switchport nonegotiate
spanning-tree portfast
spanning-tree bpduguard enable
, python
, :
( linux)
#!/usr/bin/env python
access_template_exec.py:
#!/usr/bin/env python
print '\n'.join(access_template) % 5
chmod +x access_template_exec.py
$ ./access_template_exec.py
103
(argv)
- . ,
- . , ,
.
Python, sys
- argv.
( access_template_argv.py):
, , .
argv
argv , ,
104
, argv :
, , .
, :
argv[1:] . . ,
, : ['Gi0/7', '4'] .
Python .
:
In [16]: a = 5
In [17]: b = 6
In [18]: c, d = 5, 6
In [19]: c
Out[19]: 5
In [20]: d
Out[20]: 6
, argv:
In [23]: interface
Out[23]: 'Gi0/7'
In [24]: vlan
Out[24]: '4'
, argv . ,
access_template , ,
vlan ( ).
105
, . ,
.
, , ,
.
raw_input() :
, , ,
, -
. .
- , ,
.
, , .
print:
, , raw_print() .
( access_template_raw_input.py):
106
, .
raw_input() , argv . , vlan
$ python access_template_raw_input.py
Enter interface type and number: Gi0/3
Enter VLAN number: 55
------------------------------
interface Gi0/3
switchport mode access
switchport access vlan 55
switchport nonegotiate
spanning-tree portfast
spanning-tree bpduguard enable
raw_input() input()
stackoverflow
107
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
4.1
IP- : 10.1.1.0/24
Network:
10 1 1 0
00001010 00000001 00000001 00000000
Mask:
/24
255 255 255 0
11111111 11111111 11111111 00000000
/.
108
4.1a
, 4.1. , , ,
,
4.1.
( ):
10.0.1.0/24
190.1.0.0/16
10.0.1.1/24 - 10.0.1.0/24
10.0.5.1/30 - 10.0.5.0/30
Network:
10 1 1 0
00001010 00000001 00000001 00000000
Mask:
/24
255 255 255 0
11111111 11111111 11111111 00000000
/.
4.1b
4.1a , /
, .
4.2
if london_co.
(r1, r2 sw1).
( ).
109
$ python task_4_2.py
Enter device name: r1
{'ios': '15.4', 'model': '4451', 'vendor': 'Cisco', 'location': '21 New Globe Walk', '
ip': '10.255.0.1'}
london_co = {
'r1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.1'
},
'r2' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.2'
},
'sw1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'ios': '3.6.XE',
'ip': '10.255.0.101',
'vlans': '10,20,30',
'routing': True
}
}
4.2a
if london_co.
4.2 , , ,
, .
, .
$ python task_4_2a.py
Enter device name: r1
Enter parameter name: ios
15.4
110
london_co = {
'r1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.1'
},
'r2' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.2'
},
'sw1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'ios': '3.6.XE',
'ip': '10.255.0.101',
'vlans': '10,20,30',
'routing': True
}
}
4.2b
if london_co.
4.2a , , ,
.
, .
$ python task_4_2b.py
Enter device name: r1
Enter parameter name (ios,model,vendor,location,ip): ip
10.255.0.1
111
london_co = {
'r1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.1'
},
'r2' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.2'
},
'sw1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'ios': '3.6.XE',
'ip': '10.255.0.101',
'vlans': '10,20,30',
'routing': True
}
}
4.2c
if london_co.
4.2b , , ,
, ' '.
, . .
,
, .
$ python task_4_2c.py
Enter device name: r1
Enter parameter name (ios,model,vendor,location,ip): io
112
london_co = {
'r1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.1'
},
'r2' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.2'
},
'sw1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'ios': '3.6.XE',
'ip': '10.255.0.101',
'vlans': '10,20,30',
'routing': True
}
}
4.2d
if london_co.
4.2c , , ,
.
$ python task_4_2d.py
Enter device name: r1
Enter parameter name (ios,model,vendor,location,ip): IOS
15.4
113
london_co = {
'r1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.1'
},
'r2' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '4451',
'ios': '15.4',
'ip': '10.255.0.2'
},
'sw1' : {
'location': '21 New Globe Walk',
'vendor': 'Cisco',
'model': '3850',
'ios': '3.6.XE',
'ip': '10.255.0.101',
'vlans': '10,20,30',
'routing': True
}
}
4.3
( )
if.
(access/trunk),
: 'Enter interface mode (access/trunk): '
( , Gi0/3)
: 'Enter interface type and number: '
VLAN ( trunk VLAN)
: 'Enter vlan(s): '
, ,
access trunk (
access_template trunk_template).
, interface ,
, VLAN (
VLAN).
114
, .
, access:
$ python task_4_3.py
Enter interface mode (access/trunk): access
Enter interface type and number: Fa0/6
Enter vlan(s): 3
interface Fa0/6
switchport mode access
switchport access vlan 3
switchport nonegotiate
spanning-tree portfast
spanning-tree bpduguard enable
, trunk:
$ python task_4_3.py
Enter interface mode (access/trunk): trunk
Enter interface type and number: Fa0/7
Enter vlan(s): 2,3,4,5
interface Fa0/7
switchport trunk encapsulation dot1q
switchport mode trunk
switchport trunk allowed vlan 2,3,4,5
4.3a
if.
4.3 , ,
, VLAN VLAN:
115
116
5.
Python .
, :
if/elif/else
for
while
for/else while/else, , ,
.
117
if/elif/else
if/elif/else
if/elif/else
.
if , elif else :
if .
if - :
( True), if .
elif . ,
.
elif if, . , "
..."
elif
else , if elif
.
In [1]: a = 9
In [2]: if a == 0:
...: print 'a 0'
...: elif a < 10:
...: print 'a 10'
...: else:
...: print 'a 10'
...:
a 10
if elif , , :
118
if/elif/else
In [7]: 5 > 3
Out[7]: True
In [8]: 5 == 5
Out[8]: True
In [10]: 1 in [ 1, 2, 3 ]
Out[10]: True
In [11]: 0 in [ 1, 2, 3 ]
Out[11]: False
True False
Python:
True ()
False ()
0
None
True False, , .
, ,
:
In [13]: if list_to_test:
....: print " "
....:
119
if/elif/else
In [14]: if len(list_to_test) != 0:
....: print " "
....:
, :
In [3]: 5 > 6
Out[3]: False
In [4]: 5 > 2
Out[4]: True
In [5]: 5 < 2
Out[5]: False
In [6]: 5 == 2
Out[6]: False
In [7]: 5 == 5
Out[7]: True
In [8]: 5 >= 5
Out[8]: True
In [9]: 5 <= 10
Out[9]: True
In [10]: 8 != 10
Out[10]: True
, == .
in
in
(, ):
120
if/elif/else
In [11]: 10 in vlan
Out[11]: True
In [12]: 50 in vlan
Out[12]: False
in :
In [15]: r1 = {
....: 'IOS': '15.4',
....: 'IP': '10.255.0.1',
....: 'hostname': 'london_r1',
....: 'location': '21 New Globe Walk',
....: 'model': '4451',
....: 'vendor': 'Cisco'}
In [16]: 'IOS' in r1
Out[16]: True
In [17]: '4451' in r1
Out[17]: False
121
if/elif/else
In [15]: r1 = {
....: 'IOS': '15.4',
....: 'IP': '10.255.0.1',
....: 'hostname': 'london_r1',
....: 'location': '21 New Globe Walk',
....: 'model': '4451',
....: 'vendor': 'Cisco'}
and
Python and ,
.
,
:
,
:
122
if/elif/else
or
or , and, .
, :
, :
In [31]: '' or [] or {}
Out[31]: {}
or - ,
, :
if/elif/else
check_password.py,
:
123
if/elif/else
if len(password) < 8:
print ' '
elif username in password:
print ' '
else:
print ' %s ' % username
$ python check_password.py
: nata
: nata1234
$ python check_password.py
: nata
: 123nata123
$ python check_password.py
: nata
: 1234
$ python check_password.py
: nata
: 123456789
nata
(Ternary expressions)
, :
s = [1, 2, 3, 4]
result = True if len(s) > 5 else False
124
for
for
for ,
for.
, for:
'''range()''' '''xrange()'''
(, '''sorted()''', '''enumerate()''')
, , , ,
, ,
. , range(10) ,
0 9 () .
xrange() , .
, , , for. -
, , ,
. , ,
.
for :
s
t
r
i
n
g
letter. ,
, .
for () xrange():
125
for
xrange(10).
, ( 10), .
, VLAN,
vlan:
, :
126
for
In [5]: r1 = {
'IOS': '15.4',
'IP': '10.255.0.1',
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'}
- :
items,
, :
items, , :
127
for
In [9]: r1.items()
Out[9]:
[('vendor', 'Cisco'),
('IP', '10.255.0.1'),
('hostname', 'london_r1'),
('IOS', '15.4'),
('location', '21 New Globe Walk'),
('model', '4451')]
iteritems(). items,
, :
In [10]: r1.iteritems()
Out[10]: <dictionary-itemiterator at 0x102daff18>
128
for
for
for .
, commands ,
fast_int:
for fast_int,
commands.
129
for if
for if
for if.
generate_access_port_config.py:
for fast_int['access']
, , intf
interface FastEthernet
for access_template
switchport access vlan, VLAN:
for
access vlan
VLAN,
intf
,
130
for if
$ python generate_access_port_config.py
interface FastEthernet0/12
switchport mode access
switchport access vlan 10
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/14
switchport mode access
switchport access vlan 11
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/16
switchport mode access
switchport access vlan 17
spanning-tree portfast
spanning-tree bpduguard enable
131
enumerate
enumerate()
, for, ,
. , ,
.
, enumerate() .
enumerate() , ,
applet EEM :
132
enumerate
EEM, , ,
action x cli command . , ,
, EEM.
Python, EEM,
( eem.py):
import sys
config = sys.argv[1]
,
, EEM.
with
(r1_config.txt):
en
conf t
no int Gi0/0/0.300
no int Gi0/0/0.301
no int Gi0/0/0.302
int range gi0/0/0-2
channel-group 1 mode active
interface Port-channel1.300
encapsulation dot1Q 300
vrf forwarding Management
ip address 10.16.19.35 255.255.255.248
133
enumerate
, , .
134
enumerate
135
while
while
while Python.
while, if, . ,
while. , if, while
.
while, ,
, .
In [1]: a = 5
, 5.
, while a > 0. , 0,
. ,
.
, , ,
.
a -= 1 . Python
, a = a - 1 .
: a += 1 , a *= 2 , a /= 2 .
, -
a > 0 .
if. , ,
.
136
while
while, ,
, .
check_password_with_while.py:
pass_OK = False
while ,
, ,
.
$ python check_password_with_while.py
: nata
: nata
: natanata
: 123345345345
nata
137
break, continue, pass
break
break :
break
, break
break for while
for:
while:
In [2]: i = 0
In [3]: while i < 10:
...: if i == 5:
...: break
...: else:
...: print i
...: i += 1
...:
0
1
2
3
4
138
break, continue, pass
while True:
if len(password) < 8:
print ' \n'
password = raw_input(' : ' )
elif username in password:
print ' \n'
password = raw_input(' : ' )
else:
print ' %s ' % username
break
continue
continue . , continue
"" .
for:
while:
139
break, continue, pass
In [5]: i = 0
In [6]: while i < 6:
....: i += 1
....: if i == 3:
....: print " 3"
....: continue
....: print " "
....: else:
....: print " : ", i
....:
: 1
: 2
3
: 4
: 5
: 6
pass
pass . .
, pass , .
, , .
.
pass:
140
for/else, while/else
for/else, while/else
for while else.
for/else
for:
else ,
else , break
141
for/else, while/else
while/else
while:
else ,
else , break
In [4]: i = 0
In [5]: while i < 5:
....: print i
....: i += 1
....: else:
....: print ""
....:
0
1
2
3
4
142
for/else, while/else
In [6]: i = 0
143
try/except/else/finally
try/except/else/finally
try/except
, ,
, . , ,
, , .
, Python
.
, ,
. (exceptions).
In [1]: 2/0
-----------------------------------------------------
ZeroDivisionError: integer division or modulo by zero
In [2]: 'test' + 2
-----------------------------------------------------
TypeError: cannot concatenate 'str' and 'int' objects
, : ZeroDivisionError TypeError.
,
.
, , ,
, , TypeError,
.
Python .
, , .
, .
try/except :
144
try/except/else/finally
In [3]: try:
...: 2/0
...: except ZeroDivisionError:
...: print "You can't divide by zero"
...:
You can't divide by zero
try :
, try
try, , except
.
try, - , ,
try
except , ,
except
, , except,
, 'Cool!' try :
In [4]: try:
...: print "Let's divide some numbers"
...: 2/0
...: print 'Cool!'
...: except ZeroDivisionError:
...: print "You can't divide by zero"
...:
Let's divide some numbers
You can't divide by zero
try/except except, ,
.
, divide.py :
try:
a = raw_input(" : ")
b = raw_input(" : ")
print ": ", int(a)/int(b)
except ValueError:
print ", "
except ZeroDivisionError:
print " "
145
try/except/else/finally
$ python divide.py
: 3
: 1
: 3
$ python divide.py
: 5
: 0
:
$ python divide.py
: qewr
: 3
: ,
, ValueError ,
, .
ZeroDivisionError , 0.
ValueError
ZeroDivisionError, ( divide_ver2.py):
try:
a = raw_input(" : ")
b = raw_input(" : ")
print ": ", int(a)/int(b)
except (ValueError, ZeroDivisionError):
print "- ..."
$ python divide_ver2.py
: wer
: 4
: - ...
$ python divide_ver2.py
: 5
: 0
: - ...
146
try/except/else/finally
except .
, .
try/except/else
try/except else. ,
.
, - ,
, else ( divide_ver3.py):
try:
a = raw_input(" : ")
b = raw_input(" : ")
result = int(a)/int(b)
except (ValueError, ZeroDivisionError):
print "- ..."
else:
print " : ", result**2
$ python divide_ver3.py
: 10
: 2
: 25
$ python divide_ver3.py
: werq
: 3
- ...
try/except/finally
finally try.
, , .
, . ,
.
divide_ver4.py finally:
147
try/except/else/finally
try:
a = raw_input(" : ")
b = raw_input(" : ")
result = int(a)/int(b)
except (ValueError, ZeroDivisionError):
print "- ..."
else:
print " : ", result**2
finally:
print " , - ."
$ python divide_ver4.py
: 10
: 2
: 25
, - .
$ python divide_ver4.py
: qwerewr
: 3
- ...
, - .
$ python divide_ver4.py
: 4
: 0
- ...
, - .
148
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
5.1
1. IP- - .
2. IP-.
3. , :
'unicast' - IP- A, B C
'multicast' - IP- D
'local broadcast' - IP- 255.255.255.255
'unassigned' - IP- 0.0.0.0
'unused' -
( ):
A: 1-127
B: 128-191
149
C: 192-223
D: 224-239
5.1a
5.1.
IP-.
, :
4 ,
0 255.
, :
5.1b
5.1a.
, .
5.2
mac MAC- XXXX:XXXX:XXXX.
, Cisco MAC-
XXXX.XXXX.XXXX.
, MAC- cisco
mac_cisco.
: .
mac_cisco = []
5.3
access-.
150
trunk.
, VLAN , ,
.
()
VLAN, :
trunk_template
add, del, only
fast_int = {'access':{'0/12':'10','0/14':'11','0/16':'17','0/17':'150'},
'trunk':{'0/1':['add','10','20'],
'0/2':['only','11','30'],
'0/4':['del','17']} }
151
6.
, ,
, .
( ), :
(, )
, - .
Jinja
Jinja2
, , -
: YAML, JSON, CSV
Python
(
Python)
. ,
Cisco.
. , Python.
152
, .
open()
, , open() :
open():
'file_name.txt' -
, (
)
'r' -
open() file,
, .
r - ( )
r+ -
w -
,
,
w+ -
,
,
a - .
a+ - .
, w+ r+ . ,
w+ , , , r+ - .
153
Python :
read() -
readline() -
readlines() -
, r1.txt:
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!
read()
read() - .
read() :
In [1]: f = open('r1.txt')
In [2]: f.read()
Out[2]: '!\nservice timestamps debug datetime msec localtime show-timezone year\nservi
ce timestamps log datetime msec localtime show-timezone year\nservice password-encrypt
ion\nservice sequence-numbers\n!\nno ip domain lookup\n!\nip ssh version 2\n!\n'
In [3]: f.read()
Out[3]: ''
3 , .
- , read() , . ,
, .
seek() .
readline()
154
readline() :
In [4]: f = open('r1.txt')
In [5]: f.readline()
Out[5]: '!\n'
In [6]: f.readline()
Out[6]: 'service timestamps debug datetime msec localtime show-timezone year\n'
, , file , read... :
In [7]: f = open('r1.txt')
service password-encryption
service sequence-numbers
no ip domain lookup
ip ssh version 2
readlines()
- readlines() . :
155
In [9]: f = open('r1.txt')
In [10]: f.readlines()
Out[10]:
['!\n',
'service timestamps debug datetime msec localtime show-timezone year\n',
'service timestamps log datetime msec localtime show-timezone year\n',
'service password-encryption\n',
'service sequence-numbers\n',
'!\n',
'no ip domain lookup\n',
'!\n',
'ip ssh version 2\n',
'!\n']
, ,
split , \n :
In [11]: f = open('r1.txt')
In [12]: f.read().split('\n')
Out[12]:
['!',
'service timestamps debug datetime msec localtime show-timezone year',
'service timestamps log datetime msec localtime show-timezone year',
'service password-encryption',
'service sequence-numbers',
'!',
'no ip domain lookup',
'!',
'ip ssh version 2',
'!',
'']
, - .
split() , rstrip() ,
:
156
In [13]: f = open('r1.txt')
In [14]: f.read().rstrip().split('\n')
Out[14]:
['!',
'service timestamps debug datetime msec localtime show-timezone year',
'service timestamps log datetime msec localtime show-timezone year',
'service password-encryption',
'service sequence-numbers',
'!',
'no ip domain lookup',
'!',
'ip ssh version 2',
'!']
seek()
, , .
- , , .
.
,
seek , .
In [15]: f = open('r1.txt')
read , :
, seek , (0
):
157
In [18]: f.seek(0)
, , seek , ,
:
158
, ,
:
append -
write -
,
write() -
writelines() -
write()
write , .
, :
r2.txt :
join :
In [4]: cfg_lines_as_string
Out[4]: '!\nservice timestamps debug datetime msec localtime show-timezone year\nservi
ce timestamps log datetime msec localtime show-timezone year\nservice password-encrypt
ion\nservice sequence-numbers\n!\nno ip domain lookup\n!\nip ssh version 2\n!'
159
In [5]: f.write(cfg_lines_as_string)
, :
In [7]: f.close()
ipython cat,
:
writelines()
writelines() , .
cfg_lines :
160
In [10]: f.writelines(cfg_lines)
In [11]: f.close()
, , ,
\n .
-. ,
:
In [13]: cfg_lines2 = []
In [15]: cfg_lines2
Out[15]:
['!\n',
'service timestamps debug datetime msec localtime show-timezone year\n',
'service timestamps log datetime msec localtime show-timezone year\n',
'service password-encryption\n',
'service sequence-numbers\n',
'!\n',
'no ip domain lookup\n',
'!\n',
'ip ssh version 2\n',
list comprehensions:
161
In [17]: cfg_lines3
Out[17]:
['!\n',
'service timestamps debug datetime msec localtime show-timezone year\n',
'service timestamps log datetime msec localtime show-timezone year\n',
'service password-encryption\n',
'service sequence-numbers\n',
'!\n',
'no ip domain lookup\n',
'!\n',
'ip ssh version 2\n',
'!\n']
, ,
:
In [19]: f.writelines(cfg_lines3)
In [20]: f.close()
162
, , ,
with . , . ,
close ,
.
, . , Python
.
.
close()
close . ,
.
, Python flush() . , ,
, ,
.
r1.txt:
file closed ,
. , False :
163
In [3]: f.closed
Out[3]: False
closed :
In [4]: f.close()
In [5]: f.closed
Out[5]: True
, :
try/finally
, :
, ,
, , finally
, ,
:
try/except ,
:
164
In [8]: try:
....: f = open('r3.txt', 'r')
....: except IOError:
....: print 'No such file'
....:
No such file
finally , , :
In [9]: try:
....: f = open('r1.txt', 'r')
....: print f.read()
....: except IOError:
....: print 'No such file'
....: finally:
....: f.close()
....:
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!
In [10]: f.closed
Out[10]: True
165
with
with
with .
Python , ,
- with :
service password-encryption
service sequence-numbers
no ip domain lookup
ip ssh version 2
, with .
, :
for line in f:
print line
, .
, ,
print .
, print
rstrip :
166
with
In [3]: f.closed
Out[3]: True
, , with
, , , :
with .
:
http://stackoverflow.com/questions/3012488/what-is-the-python-with-statement-
designed-for
167
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
6.1
3.1 ospf.txt
:
Protocol: OSPF
Prefix: 10.0.24.0/24
AD/Metric: 110/41
Next-Hop: 10.0.13.3
Last update: 3d18h
Outbound Interface: FastEthernet0/0
,
.
168
6.2
, config_sw1.txt:
, , '!'.
6.2a
6.2.
, ,
ignore.
6.2b
6.2a:
,
config_sw1_cleared.txt
, , ignore.
, '!' .
6.2c
6.2b:
169
, , ,
ignore.
.
config_sw1.txt.
6.3
CAM_table.txt :
, MAC-
, MAC-, ,
:
6.3a
6.3
VLAN
6.3b
6.3a
VLAN.
VLAN.
170
171
7.
- , :
,
,
, , .
,
?
, , , - .
, ,
:
( ) , (
Cisco)
( )
, , .
, , . ,
. , ,
, , .
(
).
, , - , .
,
.
172
7.
173
def
def
,
, , ,
, , ,
docstring
return
, return -
, ,
create_func.py
, .
, , , . -
ACL : ACL ,
, - .
, , .
- , , .
- (), ,
.
, ,
:
174
In [2]: open_file('r1.txt')
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!
In [3]: open_file('ospf.txt')
router ospf 1
router-id 10.0.0.3
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
network 10.0.2.0 0.0.0.255 area 2
network 10.1.1.0 0.0.0.255 area 0
- docstring, .
, . :
In [4]: open_file.__doc__
Out[4]: 'Documentation string'
,
. , , ,
. ,
, . , -
, , .
return
return , , ,
, - .
Python.
open_file, ,
. , , .
, result,
:
175
result None . - ,
. .
, , , ,
, return :
result .
, , - .
, print,
- .
return: ,
return, .
, , "Done" ,
return:
176
177
.
.
Python . ,
, , ,
.
, Python , ,
. ,
, .
Python LEGB, .
, , , Python
( ):
L (local) - ( )
E (enclosing) - ( ,
)
G (global) - ( )
B (built-in) - ( Python)
:
,
,
''
, ,
result:
178
.
In [3]: open_file('r1.txt')
Out[3]: '!\nservice timestamps debug datetime msec localtime show-timezone year\nservi
ce timestamps log datetime msec localtime show-timezone year\nservice password-encrypt
ion\nservice sequence-numbers\n!\nno ip domain lookup\n!\nip ssh version 2\n!\n'
In [4]: result
Out[4]: 'test string'
179
, , , ,
, .
, .
, -
.
, :
- , , .
- (), ,
.
, ,
func_params_args.py
,
:
, delete_exclamation_from_cfg : in_cfg
out_cfg.
in_cfg, ;
out_cfg ,
.
r1.txt (in_cfg):
180
delete_exclamation_from_cfg:
result.txt :
, .
, . , ,
:
In [5]: delete_exclamation_from_cfg('r1.txt')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-66ae381f1c4f> in <module>()
----> 1 delete_exclamation_from_cfg('r1.txt')
181
, ,
, .
, :
(, )
, ,
func_params_types.py
-
. , ,
( )
, cfg_file , ,
delete_exclamation ,
. pass , .
,
result.
182
delete_exclamation True,
.
, False delete_exclamation:
(
)
, :
delete_exclamation True,
,
:
183
In [5]: cfg_to_list('r1.txt')
Out[5]:
['service timestamps debug datetime msec localtime show-timezone year',
'service timestamps log datetime msec localtime show-timezone year',
'service password-encryption',
'service sequence-numbers',
'no ip domain lookup',
'ip ssh version 2']
, , :
184
- , ,
. , ,
- .
, ,
.
, .
, ,
. , , -
.
, ,
func_args_types.py
, :
, ,
( )
185
, ,
, .
cfg_to_list, :
, , :
186
, ,
, .
, :
, ,
delete_exclamation, .
, , ,
.
, cfg_to_list, , delete_exclamation
.
187
, ,
, . , Python
,
. , , .
,
, , .
, ,
. ,
, , , *args
sum_arg :
a
,
,
*args -
188
In [2]: sum_arg(1,10,20,30)
1 (10, 20, 30)
Out[2]: 61
In [3]: sum_arg(1,10)
1 (10,)
Out[3]: 11
In [4]: sum_arg(1)
1 ()
Out[4]: 1
In [7]: sum_arg()
()
Out[7]: 0
, ,
.
, , , , **kwargs ( keyword
arguments).
sum_arg :
a
,
,
189
**kwargs -
In [9]: sum_arg(a=10,b=10,c=20,d=30)
10 {'c': 20, 'b': 10, 'd': 30}
Out[9]: 70
In [10]: sum_arg(b=10,c=20,d=30,a=10)
10 {'c': 20, 'b': 10, 'd': 30}
Out[10]: 70
, , a ,
:
In [11]: sum_arg(10,b=10,c=20,d=30)
10 {'c': 20, 'b': 10, 'd': 30}
Out[11]: 70
In [12]: sum_arg(b=10,c=20,d=30,10)
File "<ipython-input-6-71c121dc2cf7>", line 1
sum_arg(b=10,c=20,d=30,10)
SyntaxError: non-keyword arg after keyword arg
190
Python, *args **kwargs -
.
, . , ,
.
, , ,
. - Python.
, config_interface ( func_args_var_unpacking.py):
mask_bits = int(cidr_mask.split('/')[-1])
bin_mask = '1'*mask_bits + '0'*(32-mask_bits)
dec_mask = '.'.join([ str(int(bin_mask[i:i+8], 2)) for i in [0,8,16,24] ])
intf_name -
ip_address - IP-
cidr_mask - CIDR ( /24 24)
, , .
191
, ,
, .
, interfaces_info,
:
,
, :
: , 1 -
.
, . *
, , :
192
, ,
.
config_to_list:
,
.
ipython %cpaste.
193
In [9]: config_to_list('r1.txt')
Out[9]:
['service timestamps debug datetime msec localtime show-timezone year',
'service timestamps log datetime msec localtime show-timezone year',
'service password-encryption',
'service sequence-numbers',
'no ip domain lookup',
'ip ssh version 2']
cfg , :
config_to_list, :
, , , .
, , , .
** ,
:
194
Python .
195
,
. .
config_to_list ( kwargs_example.py):
ipython %cpaste .
,
.
ipython:
In [1]: config_to_list('r1.txt')
Out[1]:
['service timestamps debug datetime msec localtime show-timezone year',
'service timestamps log datetime msec localtime show-timezone year',
'service password-encryption',
'service sequence-numbers',
'no ip domain lookup',
'ip ssh version 2']
, ,
, .
delete_empty=False :
196
'' clear_cfg_and_write_to_file,
, config_to_list,
.
, , ,
. , clear_cfg_and_write_to_file
, config_to_list.
,
config_to_list:
, Python
, clear_cfg_and_write_to_file :
clear_cfg_and_write_to_file ,
kwargs . kwargs , ,
config_to_list. , kwargs ,
, config_to_list.
197
clear_cfg_and_write_to_file . , ,
, config_to_list ,
clear_cfg_and_write_to_file.
, **kwargs , ,
clear_cfg_and_write_to_file ,
, '' kwargs,
config_to_list.
198
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
7.1
, access-.
access , , access-, :
{'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17,
'FastEthernet0/17':150}
access
access_template.
199
[
'interface FastEthernet0/12',
'switchport mode access',
'switchport access vlan 10',
'switchport nonegotiate',
'spanning-tree portfast',
'spanning-tree bpduguard enable',
'interface FastEthernet0/17',
'switchport mode access',
'switchport access vlan 150',
'switchport nonegotiate',
'spanning-tree portfast',
'spanning-tree bpduguard enable',
...]
access_dict.
def generate_access_config(access):
"""
access - access-,
, :
{ 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17}
access
"""
access_template = ['switchport mode access',
'switchport access vlan',
'switchport nonegotiate',
'spanning-tree portfast',
'spanning-tree bpduguard enable']
access_dict = { 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17,
'FastEthernet0/17':150 }
7.1a
7.1.
, port-
security
200
'psecurity'
False
access_dict,
port-security .
def generate_access_config(access):
"""
access - access-,
, :
{ 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17 }
,
"""
access_dict = { 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17,
'FastEthernet0/17':150 }
7.1b
7.1a.
, ,
:
: , 'FastEthernet0/12'
: , :
201
access_dict,
port-security .
def generate_access_config(access):
"""
access - access-,
, :
{ 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17 }
:
- : , 'FastEthernet0/1'
- : ,
"""
access_dict = { 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17,
'FastEthernet0/17':150 }
7.2
, trunk-.
trunk - trunk-.
202
trunk ( trunk_dict ):
{ 'FastEthernet0/1':[10,20],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
trunk_template.
trunk_dict.
def generate_trunk_config(trunk):
"""
trunk - trunk- .
,
"""
trunk_template = ['switchport trunk encapsulation dot1q',
'switchport mode trunk',
'switchport trunk native vlan 999',
'switchport trunk allowed vlan']
trunk_dict = { 'FastEthernet0/1':[10,20,30],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
7.2a
7.2
, ,
:
: , 'FastEthernet0/1'
: ,
trunk_dict.
203
def generate_trunk_config(trunk):
"""
trunk - trunk-,
, :
{ 'FastEthernet0/1':[10,20],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
:
- : , 'FastEthernet0/1'
- : ,
"""
trunk_template = ['switchport trunk encapsulation dot1q',
'switchport mode trunk',
'switchport trunk native vlan 999',
'switchport trunk allowed vlan']
trunk_dict = { 'FastEthernet0/1':[10,20,30],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
7.3
get_int_vlan_map,
:
access, , access
VLAN:
{'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17}
trunk, ,
VLAN:
{'FastEthernet0/1':[10,20],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17]}
config_sw1.txt
7.3a
204
7.3.
, access- :
interface FastEthernet0/20
switchport mode access
duplex auto
, VLAN 1
, , VLAN 1
{'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/20':1 }
config_sw2.txt
7.4
,
:
( ),
.
,
, ( ).
,
config_sw1.txt
, ,
'!', ignore.
, ignore_command.
205
command - . ,
ignore - .
def config_to_dict(config):
"""
config -
:
- ( ), .
- ,
, (
).
- ,
"""
pass
7.4a
, 7.4.
config_r1.txt
.
, , :
interface Ethernet0/3.100
router bgp 100
config_to_dict .
, . ,
, .
206
2, ,
- ;
3, , -
.
interface Ethernet0/3.100
{'interface Ethernet0/3.100':{
'encapsulation dot1Q 100':[],
'xconnect 10.2.2.2 12100 encapsulation mpls':
['backup peer 10.4.4.4 14100',
'backup delay 1 1']}}
command - . ,
ignore - .
"""
ignore_command = False
def config_to_dict(config):
"""
config -
"""
pass
207
8.
, , :
,
(, - ).
208
Python :
import module
import module as
import module
import module:
In [1]: dir()
Out[1]:
['In',
'Out',
...
'exit',
'get_ipython',
'quit']
In [2]: import os
In [3]: dir()
Out[3]:
['In',
'Out',
...
'exit',
'get_ipython',
'os',
'quit']
, os dir(). ,
.
- os, os.
:
In [4]: os.getlogin()
Out[4]: 'natasha'
209
,
. , getlogin(),
os.
,
. , .
import module as
import module as
( , ):
In [2]: dir()
Out[2]:
['In',
'Out',
...
'exit',
'get_ipython',
'getcwd',
'getlogin',
'quit']
210
In [3]: getlogin()
Out[3]: 'natasha'
In [4]: getcwd()
Out[4]: '/Users/natasha/Desktop/Py_net_eng/code_test'
In [2]: dir()
Out[2]:
['EX_CANTCREAT',
'EX_CONFIG',
...
'wait',
'wait3',
'wait4',
'waitpid',
'walk',
'write']
In [3]: len(dir())
Out[3]: 218
os , .
.
. ,
, - os, .
.
211
.py Python,
.
, for if :
, .
sw_int_templates.py:
sw_data.py:
sw1_fast_int = {
'access':{
'0/12':'10',
'0/14':'11',
'0/16':'17'}}
generate_sw_int_cfg.py:
212
import sw_int_templates
from sw_data import sw1_fast_int
def generate_access_cfg(sw_dict):
result = []
for intf in sw_dict['access']:
result.append('interface FastEthernet' + intf)
for command in sw_int_templates.access_template:
if command.endswith('access vlan'):
result.append(' %s %s' % (command, sw_dict['access'][intf]))
else:
result.append(' %s' % command)
return result
print '\n'.join(generate_access_cfg(sw1_fast_int))
import sw_int_templates -
: sw_int_templates.access_template
from sw_data import sw1_fast_int - sw_data
sw1_fast_int
, sw1_fast_int
$ python generate_sw_int_cfg.py
interface FastEthernet0/12
switchport mode access
switchport access vlan 10
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/14
switchport mode access
switchport access vlan 11
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/16
switchport mode access
switchport access vlan 17
spanning-tree portfast
spanning-tree bpduguard enable
if __name__ == "__main__"
213
, , , ,
, .
, ,
generate_sw_int_cfg.py.
sw_cfg_templates.py :
basic_cfg = """
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
"""
lines_cfg = """
!
line con 0
logging synchronous
history size 100
line vty 0 4
logging synchronous
history size 100
transport input ssh
!
"""
generate_sw_cfg.py sw_cfg_templates.py
:
print basic_cfg
print '\n'.join(generate_access_cfg(sw1_fast_int))
print lines_cfg
, , :
basic_cfg, , lines_cfg.
214
, :
215
$ python generate_sw_cfg.py
interface FastEthernet0/12
switchport mode access
switchport access vlan 10
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/14
switchport mode access
switchport access vlan 11
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/16
switchport mode access
switchport access vlan 17
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/12
switchport mode access
switchport access vlan 10
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/14
switchport mode access
switchport access vlan 11
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/16
switchport mode access
switchport access vlan 17
spanning-tree portfast
spanning-tree bpduguard enable
!
line con 0
logging synchronous
history size 100
line vty 0 4
logging synchronous
history size 100
transport input ssh
!
216
: basic_cfg,
.
- print generate_sw_int_cfg.py:
print '\n'.join(generate_access_cfg(sw1_fast_int))
- , , , .
, , generate_sw_int_cfg.py print,
,
generate_sw_int_cfg.py.
Python , , -
, .
generate_sw_int_cfg2.py:
import sw_int_templates
from sw_data import sw1_fast_int
def generate_access_cfg(sw_dict):
result = []
for intf in sw_dict['access']:
result.append('interface FastEthernet' + intf)
for command in sw_int_templates.access_template:
if command.endswith('access vlan'):
result.append(' %s %s' % (command, sw_dict['access'][intf]))
else:
result.append(' %s' % command)
return result
if __name__ == "__main__":
print '\n'.join(generate_access_cfg(sw1_fast_int))
if __name__ == "__main__":
print '\n'.join(generate_access_cfg(sw1_fast_int))
__name__ ,
"__main__" , .
, .
, if __name__ == "__main__"
.
217
generate_sw_cfg.py :
$ python generate_sw_cfg.py
interface FastEthernet0/12
switchport mode access
switchport access vlan 10
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/14
switchport mode access
switchport access vlan 11
spanning-tree portfast
spanning-tree bpduguard enable
interface FastEthernet0/16
switchport mode access
switchport access vlan 17
spanning-tree portfast
spanning-tree bpduguard enable
!
line con 0
logging synchronous
history size 100
line vty 0 4
logging synchronous
history size 100
transport input ssh
!
print generate_sw_int_cfg2.py .
218
219
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
8.1
my_func.py.
7.1 7.1a
7.2
7.3 7.3a
main.py:
my_func.
main.py
.
get_int_vlan_map
220
( 7.3-7.3a)
, .
, , :
generate_access_config ( 7.1-7.1a)
generate_trunk_config ( 7.2)
, ,
result.txt
( , )
8.2
parse_cdp_neighbors, show
cdp neighbors.
, , .
,
.
, :
sw1_sh_cdp_neighbors.txt
8.2a
, graphviz:
python graphviz:
pip install graphviz
221
parse_cdp_neighbors draw_topology.
, .
, task_8_2a_topology.svg
8.2b
, graphviz:
apt-get install graphviz
python graphviz:
pip install graphviz
sh_cdp_n_sw1.txt
sh_cdp_n_r1.txt
sh_cdp_n_r2.txt
sh_cdp_n_r3.txt
parse_cdp_neighbors draw_topology.
, .
, task_8_2b_topology.svg
222
223
9.
.
,
.
, ,
, show. ,
uptime,
show version,
,
show more. , ,
BGP.
: regex101.com
224
re
re
Python re.
, Python,
re.
,
, re.
.
re:
match() -
search() -
findall() - .
finditer() - .
compile() - .
search()
search() :
,
Match,
None ,
In [1]: import re
Match .
225
re
, span() , ,
:
In [6]: match.span()
Out[6]: (49, 53)
In [7]: line[49:53]
Out[7]: 'dhcp'
group() , :
In [15]: match.group()
Out[15]: 'dhcp'
search() ,
, :
In [18]: match.group()
Out[18]: 'dhcp'
In [19]: match.span()
Out[19]: (5, 9)
findall()
, findall() :
findall() , ,
, Match. ,
search() .
226
re
finditer()
, ,
Match(), finditer() :
In [27]: line2[5:9]
Out[27]: 'dhcp'
In [28]: line2[17:21]
Out[28]: 'dhcp'
start() , end() (
):
compile()
Python ,
. ,
.
227
re
228
. - , ( m
)
^ -
$ -
[abc] -
[^abc] - , ,
a|b - a b
(regex) - . ,
regex* -
regex+ -
regex? -
regex{n} - n
regex{n,m} - n m
regex{n, } - n
\d -
\D -
\s - whitespace (\t\n\r\f\v)
\S - , whitespace
\w -
\W - ,
In [1]: import re
229
, line 3
.0 :
^ . ^F
:
^.a 'Fa':
$ :
, , ,
. :
, ^ ,
, ( , ,
):
'':
230
231
, (greedy).
, , ,
.
In [1]: import re
In [2]: line = '<text line> some text>'
In [3]: match = re.search('<.*>', line)
In [4]: match.group()
Out[4]: '<text line> some text>'
,
, <>.
,
:
In [7]: match.group()
Out[7]: '<text line>'
232
,
, .
() .
, , 1.
,
.
- , whitespaces.
- ( \w ) .
, .
. 0 ,
:
In [10]: match.group(0)
Out[10]: 'FastEthernet0/1 10.0.12.1 YES manual up
up'
In [11]: match.group(1)
Out[11]: 'FastEthernet0/1'
In [12]: match.group(2)
Out[12]: '10.0.12.1'
, ,
groups:
233
In [13]: match.groups()
Out[13]: ('FastEthernet0/1', '10.0.12.1')
, . ,
, , .
, .
(?P<name>regex) :
In [15]: match.group('intf')
Out[15]: 'FastEthernet0/1'
In [16]: match.group('address')
Out[16]: '10.0.12.1'
, groupdict(), ,
- , - , :
In [17]: match.groupdict()
Out[17]: {'address': '10.0.12.1', 'intf': 'FastEthernet0/1'}
, ,
, :
In [19]: match.groupdict()
Out[19]:
{'address': '10.0.12.1',
'intf': 'FastEthernet0/1',
'protocol': 'up',
'status': 'up'}
234
235
show ip dhcp snooping
, :
, ,
:
(?P<mac>.+?) + - 'mac' . ,
, , (
), ,
,
(?P<ip>.*?) + - , .
'ip'
(\d+) + - ( ),
Lease
([\w-]+) + - - ,
236
show ip dhcp snooping
( , dhcp-snooping)
(?P<vlan>\d+) + - 'vlan'.
,
(?P<int>.*$) - 'int'. ,
(
)
, .
,
.
, groupdict :
In [3]: match.groupdict()
Out[3]:
{'int': 'FastEthernet0/1',
'ip': '10.1.10.2',
'mac': '00:09:BB:3D:D6:58',
'vlan': '10'}
, .
, dhcp_snooping.txt
, .
parse_dhcp_snooping.py:
237
show ip dhcp snooping
$ python parse_dhcp_snooping.py
4
1:
int: FastEthernet0/1
ip: 10.1.10.2
mac: 00:09:BB:3D:D6:58
vlan: 10
2:
int: FastEthernet0/10
ip: 10.1.5.2
mac: 00:04:A3:3E:5B:69
vlan: 5
3:
int: FastEthernet0/9
ip: 10.1.5.4
mac: 00:05:B3:7E:9B:60
vlan: 5
4:
int: FastEthernet0/3
ip: 10.1.10.6
mac: 00:09:BC:3F:A6:50
vlan: 10
238
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
9.1
, :
1. , show
2.
,
show,
.
sh ip int br (
sh_ip_int_br.txt). ,
FastEthernet0/1.
239
9.1a
, 0/1 0/3
sh ip int br.
, ,
9.1, sh_ip_int_br.txt.
9.1b
9.1a , , -
, 0/1 0/3, , ,
7 (
).
, ,
9.1, sh_ip_int_br.txt.
9.1c
9.1 9.1a
9.1b sh ip int br sh_ip_int_br_switch.txt.
, ,
0/1 0/3, . ,
0/1 0/3.
9.2
return_match, :
, show
show
, ( ,
, , ).
240
sh ip int br (
sh_ip_int_br.txt). IP- .
, IP- (
, IP-).
, , IP-
, , ,
.
9.3
parse_cfg, ,
.
IP- ,
, :
- IP-
-
, .
config_r1.txt.
, , IP-
, , ,
.
9.3a
parse_cfg 9.3 ,
:
:
: :
IP-
( ):
241
, .
config_r1.txt.
9.3b
parse_cfg 9.3a config_r2.txt.
, e0/1 IP-:
interface Ethernet0/1
ip address 10.255.2.2 255.255.255.0
ip address 10.254.2.2 255.255.255.0 secondary
, parse_cfg, Ethernet0/1
().
parse_cfg 9.3a ,
.
, .
IP-, .
config_r2.txt ,
Ethernet0/1 .
9.4
parse_sh_ip_int_br, ,
show
show ip int br :
Interface
IP-Address
Status
Protocol
: [('FastEthernet0/0',
'10.0.1.1', 'up', 'up'), ('FastEthernet0/1', '10.0.2.1', 'up', 'up'), ('FastEthernet0/2', 'unassigned',
'up', 'up')]
242
, .
sh_ip_int_br_2.txt.
9.4a
convert_to_dict, :
parse_sh_ip_int_br
9.4
(
): [{'interface': 'FastEthernet0/0', 'status': 'up', 'protocol': 'up', 'address': '10.0.1.1'},
{'interface': 'FastEthernet0/1', 'status': 'up', 'protocol': 'up', 'address': '10.0.2.1'}]
sh_ip_int_br_2.txt:
- headers
- , parse_show
.
parse_sh_ip_int_br .
, , 9.4,
parse_show.
243
10.
- - . ,
- .
, :
YAML JSON
CSV
, Python (
, , , Pickle).
IP- ,
,
CSV
Python
JSON. ,
Python, ,
YAML ,
, (IP-
, VLAN )
, YAML Ansible
Python ,
.
, ,
. , .
, PyMOTW Python,
(, Python):
CSV
JSON
244
10.
YAML
245
CSV
CSV
CSV (comma-separated value) -
(, , ).
, - . ,
, .
, ,
, TSV (tab separated values), CSV ,
, .
CSV (sw_data.csv):
hostname,vendor,model,location
sw1,Cisco,3750,London
sw2,Cisco,3850,Liverpool
sw3,Cisco,3650,Liverpool
sw4,Cisco,3650,London
Python csv,
CSV .
csv ( csv_read.py):
import csv
with open('sw_data.csv') as f:
reader = csv.reader(f)
for row in reader:
print row
$ python csv_read.py
['hostname', 'vendor', 'model', 'location']
['sw1', 'Cisco', '3750', 'London']
['sw2', 'Cisco', '3850', 'Liverpool']
['sw3', 'Cisco', '3650', 'Liverpool']
['sw4', 'Cisco', '3650', 'London']
246
CSV
, ,
.
, , -
, - .
DictReader ( csv_read_dict.py):
import csv
with open('sw_data.csv') as f:
reader = csv.DictReader(f)
for row in reader:
print row
$ python csv_read_dict.py
{'model': '3750', 'hostname': 'sw1', 'vendor': 'Cisco', 'location': 'London'}
{'model': '3850', 'hostname': 'sw2', 'vendor': 'Cisco', 'location': 'Liverpool'}
{'model': '3650', 'hostname': 'sw3', 'vendor': 'Cisco', 'location': 'Liverpool'}
{'model': '3650', 'hostname': 'sw4', 'vendor': 'Cisco', 'location': 'London'}
, reader . , reader,
:
, - ,
:
247
CSV
, csv, CSV
( csv_write.py):
import csv
with open('sw_data_new.csv') as f:
print f.read()
, , ,
.
$ python csv_write.py
hostname,vendor,model,location
sw1,Cisco,3750,"London, Best str"
sw2,Cisco,3850,"Liverpool, Better str"
sw3,Cisco,3650,"Liverpool, Better str"
sw4,Cisco,3650,"London, Best str"
: , ,
- .
- , .
, . ,
csv .
, , . , ,
, ,
.
csv . ,
csv , ( csv_write_ver2.py):
248
CSV
import csv
with open('sw_data_new.csv') as f:
print f.read()
$ python csv_write_ver2.py
"hostname","vendor","model","location"
"sw1","Cisco","3750","London, Best str"
"sw2","Cisco","3850","Liverpool, Better str"
"sw3","Cisco","3650","Liverpool, Better str"
"sw4","Cisco","3650","London, Best str"
. , ,
, .
, . ,
,
.
, ; ( sw_data2.csv):
hostname;vendor;model;location
sw1;Cisco;3750;London
sw2;Cisco;3850;Liverpool
sw3;Cisco;3650;Liverpool
sw4;Cisco;3650;London
reader (
csv_read_delimiter.py):
249
CSV
import csv
with open('sw_data2.csv') as f:
reader = csv.reader(f, delimiter=';')
for row in reader:
print row
250
JSON
JSON
JSON (JavaScript Object Notation) -
.
JSON Python.
.
CSV, Python ,
JSON.
sw_templates.json:
{
"access": [
"switchport mode access",
"switchport access vlan",
"switchport nonegotiate",
"spanning-tree portfast",
"spanning-tree bpduguard enable"
],
"trunk": [
"switchport trunk encapsulation dot1q",
"switchport mode trunk",
"switchport trunk native vlan 999",
"switchport trunk allowed vlan"
]
}
, json :
json.load() - Python
json.loads() - JSON
Python
json.load()
Python:
251
JSON
In [3]: templates
Out[3]:
{u'access': [u'switchport mode access',
u'switchport access vlan',
u'switchport nonegotiate',
u'spanning-tree portfast',
u'spanning-tree bpduguard enable'],
u'trunk': [u'switchport trunk encapsulation dot1q',
u'switchport mode trunk',
u'switchport trunk native vlan 999',
u'switchport trunk allowed vlan']}
- . ,
JSON, unicode.
Unicode.
unicode: Unicode HowTo.
json.loads()
JSON Python:
252
JSON
In [6]: templates
Out[6]:
{u'access': [u'switchport mode access',
u'switchport access vlan',
u'switchport nonegotiate',
u'spanning-tree portfast',
u'spanning-tree bpduguard enable'],
u'trunk': [u'switchport trunk encapsulation dot1q',
u'switchport mode trunk',
u'switchport trunk native vlan 999',
u'switchport trunk allowed vlan']}
JSON .
JSON json :
json.dump()
Python :
253
JSON
JSON ,
dump.
json.dumps()
JSON:
json.dumps() ,
JSON.
254
JSON
dump dumps
.
.
, ,
.
, .
, json .
dump ( dumps),
( json_write_ver2.py):
sw_templates.json :
json:
, Python.
- unicode. ,
JSON , .
255
JSON
In [21]: type(templates)
Out[21]: list
JSON - :
, :
256
JSON
257
YAML
YAML
YAML (YAML Ain't Markup Language) -
.
YAML , JSON,
. , Ansible.
YAML
Python, YAML . YAML
.
Python: #
.
YAML .
, - (
). .
258
YAML
vlan: 100
name: IT
YAML . ,
. , -
( YAML).
, , ,
YAML:
, : access trunk. ,
- :
access:
- switchport mode access
- switchport access vlan
- switchport nonegotiate
- spanning-tree portfast
- spanning-tree bpduguard enable
trunk:
- switchport trunk encapsulation dot1q
- switchport mode trunk
- switchport trunk native vlan 999
- switchport trunk allowed vlan
259
YAML
- BS: 1550
IT: 791
id: 11
name: Liverpool
to_id: 1
to_name: LONDON
- BS: 1510
IT: 793
id: 12
name: Bristol
to_id: 1
to_name: LONDON
- BS: 1650
IT: 892
id: 14
name: Coventry
to_id: 2
to_name: Manchester
PyYAML
YAML Python PyYAML.
, :
csv json.
YAML
YAML Python.
info.yaml:
260
YAML
- BS: 1550
IT: 791
id: 11
name: Liverpool
to_id: 1
to_name: LONDON
- BS: 1510
IT: 793
id: 12
name: Bristol
to_id: 1
to_name: LONDON
- BS: 1650
IT: 892
id: 14
name: Coventry
to_id: 2
to_name: Manchester
YAML :
In [3]: templates
Out[3]:
[{'BS': 1550,
'IT': 791,
'id': 11,
'name': 'Liverpool',
'to_id': 1,
'to_name': 'LONDON'},
{'BS': 1510,
'IT': 793,
'id': 12,
'name': 'Bristol',
'to_id': 1,
'to_name': 'LONDON'},
{'BS': 1650,
'IT': 892,
'id': 14,
'name': 'Coventry',
'to_id': 2,
'to_name': 'Manchester'}]
261
YAML
YAML . ,
.
YAML
Python YAML ( yaml_write.py):
import yaml
with open('sw_templates.yaml') as f:
print f.read()
sw_templates.yaml :
access: [switchport mode access, switchport access vlan, switchport nonegotiate, spann
ing-tree
portfast, spanning-tree bpduguard enable]
trunk: [switchport trunk encapsulation dot1q, switchport mode trunk, switchport trunk
native vlan 999, switchport trunk allowed vlan]
, , . .
, ,
default_flow_style=False ( yaml_write_ver2.py):
262
YAML
import yaml
with open('sw_templates.yaml') as f:
print f.read()
sw_templates.yaml :
access:
- switchport mode access
- switchport access vlan
- switchport nonegotiate
- spanning-tree portfast
- spanning-tree bpduguard enable
trunk:
- switchport trunk encapsulation dot1q
- switchport mode trunk
- switchport trunk native vlan 999
- switchport trunk allowed vlan
263
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
10.1
:
sh version
CSV
parse_sh_version:
output sh version
,
:
264
ios - "12.4(5)T"
image - "flash:c2800-advipservicesk9-mz.124-5.T.bin"
uptime - "5 days, 3 hours, 3 minutes"
write_to_csv:
:
, CSV
, :
- ,
-
, CSV
,
.
sh version:
sh_version_r1.txt, sh_version_r2.txt, sh_version_r3.txt
parse_sh_version,
ios, image, uptime
routers_inventory.csv
, glob, ,
sh_vers. print sh_version_files,
.
, (headers), CSV.
import glob
sh_version_files = glob.glob('sh_vers*')
#print sh_version_files
10.2
:
generate_access_config - access-,
access psecurity sw_templates.yaml
generate_trunk_config - trunk-,
265
trunk sw_templates.yaml
generate_mngmt_config - ,
mngmt templates.yaml
generate_ospf_config - ospf, ospf
templates.yaml
generate_alias_config - alias, alias
templates.yaml
generate_switch_config - ,
,
import yaml
access_dict = { 'FastEthernet0/12':10,
'FastEthernet0/14':11,
'FastEthernet0/16':17,
'FastEthernet0/17':150 }
trunk_dict = { 'FastEthernet0/1':[10,20,30],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
,
"""
pass
def generate_trunk_config(trunk):
"""
trunk - trunk-,
, :
{ 'FastEthernet0/1':[10,20],
'FastEthernet0/2':[11,30],
'FastEthernet0/4':[17] }
,
"""
266
pass
def generate_ospf_config(filename):
"""
filename - YAML, ospf.
,
"""
templates = yaml.load(open(filename))
def generate_mngmt_config(filename):
"""
filename - YAML, mngmt.
,
"""
pass
def generate_alias_config(filename):
"""
filename - YAML, alias.
,
"""
pass
,
"""
pass
# :
sw1 = generate_switch_config()
sw2 = generate_switch_config(psecurity=True, alias=True)
sw3 = generate_switch_config(ospf=False)
10.3
parse_sh_cdp_neighbors, show
cdp neighbors.
, , .
267
,
.
, :
sh_cdp_n_sw1.txt
10.3a
parse_sh_cdp_neighbors 10.3,
sh cdp neighbor :
sh_cdp_n_sw1.txt
sh_cdp_n_r1.txt
sh_cdp_n_r2.txt
sh_cdp_n_r3.txt
sh_cdp_n_r4.txt
sh_cdp_n_r5.txt
sh_cdp_n_r6.txt
, parse_sh_cdp_neighbors,
topology topology.yaml.
topology :
parse_sh_cdp_neighbors
10.3b
268
10.3a,
generate_topology_from_cdp.
generate_topology_from_cdp :
list_of_files - sh cdp
neighbor
save_to_file - , ,
- True
topology_filename - , .
, topology.yaml.
, save_to_file True
, .
, 10.3a.
generate_topology_from_cdp :
sh_cdp_n_sw1.txt
sh_cdp_n_r1.txt
sh_cdp_n_r2.txt
sh_cdp_n_r3.txt
sh_cdp_n_r4.txt
sh_cdp_n_r5.txt
sh_cdp_n_r6.txt
topology.yaml.
parse_sh_cdp_neighbors
10.3c
draw_topology draw_network_graph.py
, topology.yaml
, draw_topology.
topology.yaml
, draw_topology.
, .
, task_10_3c_topology.svg
draw_topology.
269
270
11.
- .
() - ,
. - .
( ) - ,
(, , , ),
, .
() - ,
.
() .
( )
, . , ,
, .
271
SQL
SQL
SQL (structured query language) - ,
(, , , ),
, .
SQL :
( ):
DDL
CREATE - , ,
ALTER - ,
DROP -
DML
SELECT -
INSERT -
UPDATE -
DELETE -
DCL
GRANT - /
REVOKE -
TCL
COMMIT Transaction -
ROLLBACK Transaction -
SQL Python
Python :
,
SQL
, SQLite sqlite3
ORM, -
272
SQL
, SQLAlchemy
273
SQLite
SQLite
SQLite SQL-.
SQL- ,
, SQL-,
(, , , ).
, SQLite .
SQLite CLI
SQLite SQLite
. sqlite3 (sqlite3.exe
Windows) SQL.
SQL,
SQL.
SQL,
.
( ) sqlite3
:
$ sqlite3 testDB.db
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>
sqlite3 SQL , , (
dot-).
274
SQLite
, SQLite.
sqlite3, SQL . ;
.
.help -
.databases -
.tables -
sqlite> .help
.backup ?DB? FILE Backup DB (default "main") to FILE
.bail ON|OFF Stop after hitting an error. Default OFF
.databases List names and files of attached databases
...
sqlite> .databases
seq name file
--- -------- ----------------------------------
0 main /home/nata/py_for_ne/db/db_article/testDB.db
275
SQL ( sqlite3 CLI)
SQL,
" sqlite3".
276
CREATE
CREATE
create .
switch, :
sqlite> create table switch (mac text primary key, hostname text, model text, location
text);
switch:
.
, mac . , :
NULL
, MAC- .
, .
:
277
DROP
DROP
drop .
278
INSERT
INSERT
insert .
, ,
.
,
( ):
sqlite> INSERT into switch values ('0000.AAAA.CCCC', 'sw1', 'Cisco 3750', 'London, Gre
en Str');
, ,
:
279
SELECT
SELECT
select .
select * , . ,
: from switch .
, .
.headers ON .
sqlite> .headers ON
sqlite> SELECT * from switch;
mac|hostname|model|location
0000.AAAA.CCCC|sw1|Cisco 3750|London, Green Str
0000.BBBB.CCCC|sw5|Cisco 3850|London, Green Str
, , .
, .
.mode .
.mode column :
, .
.width . , .width 20 .
, ,
.sqliterc ,
.
,
, .sqliterc :
280
SELECT
.headers on
.mode column
281
WHERE
WHERE
WHERE .
, .
, , ,
.
, switch :
, 3750:
where .
like, .
LIKE _ % :
_ -
% - ,
282
WHERE
, model ,
, .
, model :
WHERE :
, WHERE LIKE :
283
ALTER
ALTER
alter :
.
ALTER:
( NULL):
284
UPDATE
UPDATE
update .
, update where,
.
sqlite> UPDATE switch set model = 'Cisco 3850' where hostname = 'sw1';
sqlite> UPDATE switch set mac = '0000.DDDD.DDDD' where hostname = 'sw1';
sqlite> UPDATE switch set mac = '0000.EEEE.EEEE', model = 'Cisco 3750' where hostname
= 'sw1';
285
REPLACE
REPLACE
replace .
replace .
,
replace:
replace :
replace
:
sqlite> create table switch (mac text primary key, hostname text, model text, location
text);
sqlite> INSERT into switch values ('0000.AAAA.CCCC', 'sw1', 'Cisco 3750', 'London, Gre
en Str');
sqlite> INSERT into switch values ('0000.BBBB.CCCC', 'sw2', 'Cisco 3850', 'London, Gre
en Str');
sqlite> INSERT into switch values ('0000.CCCC.CCCC', 'sw3', 'Cisco 3850', 'London, Gre
en Str');
, ,
replace insert:
286
REPLACE
sqlite> replace into switch values ('0000.DDDD.CCCC', 'sw4', 'Cisco 3850', 'London, Gr
een Str');
, , :
sqlite> insert or replace into switch values ('0000.DDDD.CCCC', 'sw5', 'Cisco 3850', '
London, Green Str');
MAC- ,
.
, ,
:
, replace .
287
DELETE
DELETE
delete .
, where.
288
ORDER BY
ORDER BY
- ORDER BY.
, .
, switch
:
,
ASC.
289
sqlite3
sqlite3
SQLite Python sqlite3.
Connection
Connection - . ,
.
import sqlite3
connection = sqlite3.connect('dhcp_snooping.db')
Cursor
, Cursor -
.
connection = sqlite3.connect('dhcp_snooping.db')
cursor = connection.cursor()
SQL
SQL :
execute() - SQL
executemany() - SQL
( )
executescript() - SQL
execute
execute SQL.
290
sqlite3
switch execute:
In [4]: cursor.execute("create table switch (mac text primary key, hostname text, mode
l text, location text)")
Out[4]: <sqlite3.Cursor at 0x1085be880>
SQL -
. SQL
.
, switch data:
In [5]: data = [
...: ('0000.AAAA.CCCC', 'sw1', 'Cisco 3750', 'London, Green Str'),
...: ('0000.BBBB.CCCC', 'sw2', 'Cisco 3780', 'London, Green Str'),
...: ('0000.AAAA.DDDD', 'sw3', 'Cisco 2960', 'London, Green Str'),
...: ('0011.AAAA.CCCC', 'sw4', 'Cisco 3750', 'London, Green Str')]
,
execute.
, execute, .
, (value, ) .
, commit ( ,
commit ):
291
sqlite3
In [8]: connection.commit()
, sqlite3,
switch:
$ sqlite3 sw_inventory.db
executemany
executemany SQL
( ).
executemany, switch
.
, switch data2:
In [9]: data2 = [
...: ('0000.1111.0001', 'sw5', 'Cisco 3750', 'London, Green Str'),
...: ('0000.1111.0002', 'sw6', 'Cisco 3750', 'London, Green Str'),
...: ('0000.1111.0003', 'sw7', 'Cisco 3750', 'London, Green Str'),
...: ('0000.1111.0004', 'sw8', 'Cisco 3750', 'London, Green Str')]
executemany:
In [12]: connection.commit()
commit, :
292
sqlite3
executemany SQL
.
executescript
executescript SQL .
In [16]: cursor.executescript("""
...: create table switches(
...: hostname text primary key,
...: location text
...: );
...:
...: create table dhcp(
...: mac text primary key,
...: ip text,
...: vlan text,
...: interface text,
...: switch text not null references switches(hostname)
...: );
...: """)
Out[16]: <sqlite3.Cursor at 0x10efd67a0>
sqlite3 :
fetch...() -
,
293
sqlite3
fetchone
fetchone .
sw_inventory.db:
In [5]: cursor.fetchone()
Out[5]: (u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
, SQL ,
, fetchone .
, :
.
, None.
, , , :
294
sqlite3
fetchmany
fetchmany .
cursor.fetchmany([size=cursor.arraysize])
size, .
, size cursor.arraysize:
, :
295
sqlite3
,
size, .
fetchall
fetchall :
In [13]: cursor.fetchall()
Out[13]:
[(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str'),
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str'),
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str'),
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0001', u'sw5', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0002', u'sw6', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0003', u'sw7', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0004', u'sw8', u'Cisco 3750', u'London, Green Str')]
- .
, fetchall, , , fetchone,
fetchall :
296
sqlite3
In [15]: cursor.fetchone()
Out[15]: (u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
In [16]: cursor.fetchone()
Out[16]: (u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
In [17]: cursor.fetchall()
Out[17]:
[(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str'),
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0001', u'sw5', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0002', u'sw6', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0003', u'sw7', u'Cisco 3750', u'London, Green Str'),
(u'0000.1111.0004', u'sw8', u'Cisco 3750', u'London, Green Str')]
fetchmany, , .
Cursor
,
. fetch.
execute, . ,
, , , for:
, , :
297
sqlite3
sqlite3
execute Connection.
, . , fetch Connection .
, , execute, ,
fetch .
( create_sw_inventory_ver1.py):
con = sqlite3.connect('sw_inventory2.db')
con.execute("create table switch (mac text primary key, hostname text, model text, loc
ation text)")
con.close()
298
sqlite3
$ python create_sw_inventory_ver1.py
(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str')
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str')
execute, .
switch mac . ,
MAC-, :
In [23]: query = "INSERT into switch values ('0000.AAAA.DDDD', 'sw7', 'Cisco 2960', 'L
ondon, Green Str')"
In [24]: con.execute(query)
---------------------------------------------------------------------------
IntegrityError Traceback (most recent call last)
<ipython-input-56-ad34d83a8a84> in <module>()
----> 1 con.execute(query)
, :
In [25]: try:
...: con.execute(query)
...: except sqlite3.IntegrityError as e:
...: print "Error occured: ", e
...:
Error occured: UNIQUE constraint failed: switch.mac
, sqlite3.IntegrityError,
IntegrityError.
Connection
, (
commit() ), , .
Python Connection, .
, commit . :
299
sqlite3
,
, commit
,
(create_sw_inventory_ver2.py):
con = sqlite3.connect('sw_inventory3.db')
con.execute("create table switch (mac text primary key, hostname text, model text, loc
ation text)")
try:
with con:
query = "INSERT into switch values (?, ?, ?, ?)"
con.executemany(query, data)
except sqlite3.IntegrityError as e:
print "Error occured: ", e
, ,
, .
, ,
MAC- ( create_sw_inventory_ver3.py):
300
sqlite3
con = sqlite3.connect('sw_inventory3.db')
con.execute("create table switch (mac text primary key, hostname text, model text, loc
ation text)")
try:
with con:
query = "INSERT into switch values (?, ?, ?, ?)"
con.executemany(query, data)
except sqlite3.IntegrityError as e:
print "Error occured: ", e
print '-'*30
try:
with con:
query = "INSERT into switch values (?, ?, ?, ?)"
con.executemany(query, data2)
except sqlite3.IntegrityError as e:
print "Error occured: ", e
. ,
, data2 sw7 MAC-
sw3.
301
sqlite3
$ python create_sw_inventory_ver3.py
(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str')
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str')
------------------------------
Error occured: UNIQUE constraint failed: switch.mac
(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str')
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str')
, switch
- . ,
data2.
- , executemany
4 .
- .
, , .
, execute
.
create_sw_inventory_ver4.py:
302
sqlite3
con = sqlite3.connect('sw_inventory3.db')
con.execute("create table switch (mac text primary key, hostname text, model text, loc
ation text)")
try:
with con:
query = "INSERT into switch values (?, ?, ?, ?)"
con.executemany(query, data)
except sqlite3.IntegrityError as e:
print "Error occured: ", e
print '-'*30
( sw7):
303
sqlite3
$ python create_sw_inventory_ver4.py
(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str')
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str')
------------------------------
Error occured: UNIQUE constraint failed: switch.mac
(u'0000.AAAA.CCCC', u'sw1', u'Cisco 3750', u'London, Green Str')
(u'0000.BBBB.CCCC', u'sw2', u'Cisco 3780', u'London, Green Str')
(u'0000.AAAA.DDDD', u'sw3', u'Cisco 2960', u'London, Green Str')
(u'0011.AAAA.CCCC', u'sw4', u'Cisco 3750', u'London, Green Str')
(u'0055.AAAA.CCCC', u'sw5', u'Cisco 3750', u'London, Green Str')
(u'0066.BBBB.CCCC', u'sw6', u'Cisco 3780', u'London, Green Str')
(u'0088.AAAA.CCCC', u'sw8', u'Cisco 3750', u'London, Green Str')
,
, .
304
SQLite
SQLite
show ip dhcp
snooping binding. ,
(interface, IP, MAC, VLAN).
. , ,
.
, IP- ,
, MAC- VLAN,
, , .
, ,
.
dhcp_snooping_schema.sql
:
"". MAC-
. , , MAC-
.
, (
create_sqlite_ver1.py):
305
SQLite
import sqlite3
with
with sqlite3.connect('dhcp_snooping.db') as conn :
dhcp_snooping.db,
Connection
, ,
dhcp_snooping_schema.sql:
dhcp_snooping_schema.sql
schema = f.read() -
conn.executescript(schema) - executescript
SQL,
$ python create_sqlite_ver1.py
Creating schema...
Done
dhcp.
, , sqlite3,
.
(
DB):
306
SQLite
, dhcp_snooping.txt
, , (
create_sqlite3_ver2.py):
import sqlite3
import re
, ,
.
, sh ip dhcp
snooping binding, ,
,
307
SQLite
,
result - ,
,
,
,
query . ,
. ,
execute row,
$ python create_sqlite_ver2.py
Creating schema...
Done
Inserting DHCP Snooping data
, :
, , .
,
dhcp_snooping.db. , , ,
.
create_sqlite_ver3.py:
308
SQLite
import os
import sqlite3
import re
data_filename = 'dhcp_snooping.txt'
db_filename = 'dhcp_snooping.db'
schema_filename = 'dhcp_snooping_schema.sql'
db_exists = os.path.exists(db_filename)
, dhcp_snooping.db
, . ,
dhcp_snooping.db.
. :
$ python create_sqlite_ver3.py
Database exists, assume dhcp table does, too.
( ):
$ rm dhcp_snooping.db
$ python create_sqlite_ver3.py
Creating schema...
Done
Inserting DHCP Snooping data
309
SQLite
,
. :
get_data_ver1.py:
db_filename = 'dhcp_snooping.db'
, , key, value
keys, .
,
conn.row_factory = sqlite3.Row -
,
,
SQL ,
. ,
310
SQLite
, - SQL.
(value,)
:
,
keys
IP 10.1.10.2:
VLAN 10:
, :
, ,
, .
,
, ,
description
get_data_ver2.py:
311
SQLite
db_filename = 'dhcp_snooping.db'
query = query_dict[key]
result = conn.execute(query, (value,))
# description .
# , .
all_rows = [r[0] for r in result.description]
,
.
,
, ,
.
312
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
11.1
create_sqlite_ver3.py , :
create_db.py
:
,
dhcp_snooping_schema.sql, (
)
add_data.py
,
sh ip dhcp snooping binding,
313
.
, . .
( dhcp_snooping_schema.sql):
switches -
dhcp - , switch
hostname switches
, add_data.py :
switches
, switches.yml
sh ip dhcp snooping binding
dhcp
:
sw1_dhcp_snooping.txt, sw2_dhcp_snooping.txt,
sw3_dhcp_snooping.txt
dhcp , switch,
.
, .
11.1a
add_data.py, 11.1, :
,
, ,
11.2
get_data_ver1.py , get_data.py.
.
, . .
, :
key - ,
value -
314
, dhcp
,
dhcp,
,
,
, :
315
$ python get_data.py
dhcp :
----------------------------------------------------------------------
00:09:BB:3D:D6:58 10.1.10.2 10 FastEthernet0/1 sw1
00:04:A3:3E:5B:69 10.1.5.2 5 FastEthernet0/10 sw1
00:05:B3:7E:9B:60 10.1.5.4 5 FastEthernet0/9 sw1
00:07:BC:3F:A6:50 10.1.10.6 10 FastEthernet0/3 sw1
00:09:BC:3F:A6:50 192.168.1.100 100 FastEthernet0/5 sw1
00:A9:BB:3D:D6:58 10.1.10.20 10 FastEthernet0/7 sw2
00:B4:A3:3E:5B:69 10.1.5.20 5 FastEthernet0/5 sw2
00:C5:B3:7E:9B:60 10.1.5.40 5 FastEthernet0/9 sw2
00:A9:BC:3F:A6:50 100.1.1.6 3 FastEthernet0/20 sw3
11.2a
316
get_data.py 11.2
,
. ,
( ).
, :
11.3
. ,
, .
add_data.py , .
.
, , MAC-,
. , MAC-,
.
, - ,
.
, , ,
dhcp.
, , .
, -. active,
.
active :
0 - False. ,
1 - True. ,
, DHCP snooping
, ( ),
(active = 0).
, (active = 1).
317
, , MAC-,
, .
dhcp_snooping_schema.sql
add_data.py ,
active.
.
, . .
SQL,
, sqlite3.
,
dhcp snooping. ,
.
11.4
get_data 11.2 11.2a.
, , ,
, .
=======================================
Inactive values:
----------------------------------------
mac : 00:09:23:34:16:18
vlan : 10
interface : FastEthernet0/4
switch : sw1
----------------------------------------
11.5
318
. , - MAC-
, , .
, , , MAC-
, .
, , .
, , ,
.
last_active , :
YYYY-MM-DD HH:MM:SS .
, , dhcp .
cli sqlite, dhcp_snooping_schema.sql
add_data.py,
, , .
.
import datetime
now = str(datetime.datetime.today().replace(microsecond=0))
#print now
11.5a
11.5, dhcp last_active.
add_data.py, , ,
7 .
, ,
last_active.
datetime.
, , , ,
.
319
now = datetime.today().replace(microsecond=0)
week_ago = now - timedelta(days = 7)
#print now
#print week_ago
#print now > week_ago
#print str(now) > str(week_ago)
11.6
parse_dhcp_snooping.py.
,
.
parse_dhcp_snooping.py .
, ,
, create_db.py, add_data.py get_data.py.
parse_dhcp_snooping.py :
, ,
parse_dhcp_snooping_functions.py
parse_dhcp_snooping.py.
parse_dhcp_snooping.py, :
parse_dhcp_snooping_functions.py
,
.
, ,
argparse. , .
320
, ,
parse_dhcp_snooping_functions.py , ,
, print.
, , (
).
parse_dhcp_snooping_functions.py, ,
parse_dhcp_snooping.py.
sh ip dhcp snooping binding
( )
, ,
.
$ python parse_dhcp_snooping.py -h
usage: parse_dhcp_snooping.py [-h] {create_db,add,get} ...
optional arguments:
-h, --help show this help message and exit
subcommands:
valid subcommands
optional arguments:
-h, --help show this help message and exit
--db DB_FILE db name
-k {mac,ip,vlan,interface,switch}
host key (parameter) to search
-v VALUE value of key
-a show db content
321
positional arguments:
filename file(s) to add to db
optional arguments:
-h, --help show this help message and exit
--db DB_FILE db name
-s add switch data if set, else add normal data
optional arguments:
-h, --help show this help message and exit
-n NAME db filename
-s SCHEMA db schema filename
322
----------------------------------------
323
12.
SSH
Telnet
Python ,
:
4 ,
.
, netmiko.
.
, SSH.
, :
: cisco
: cisco
324
12.
enable: cisco
SSH 2
IP-: 192.168.100.1, 192.168.100.2, 192.168.100.3
325
, ,
.
,
:
,
-
,
.
, , ,
.
, raw_input() , .
, .
getpass
getpass , :
( ) -
.
, :
326
$ export SSH_USER=user
$ export SSH_PASSWORD=userpass
, Python, :
import os
USERNAME = os.environ.get('SSH_USER')
PASSWORD = os.environ.get('SSH_PASSWORD')
327
Pexpect
pexpect
pexpect , :
telnet
ssh
ftp
, pexpect :
pexpect :
-
pexpect (, )
, /
,
, pexpect , .
pexpect :
run()
spawn
pexpect.run()
run() - .
328
Pexpect
pexpect.spawn
spawn .
, .
pexpect.spawn:
t = pexpect.spawn('ssh user@10.1.1.1')
t.expect('Password:')
t.sendline("userpass")
t.expect('>')
pexpect
pexpect
show ( 1_pexpect.py):
329
Pexpect
import pexpect
import getpass
import sys
COMMAND = sys.argv[1]
USER = raw_input("Username: ")
PASSWORD = getpass.getpass()
ENABLE_PASS = getpass.getpass(prompt='Enter enable password: ')
DEVICES_IP = ['192.168.100.1','192.168.100.2','192.168.100.3']
for IP in DEVICES_IP:
print "Connection to device %s" % IP
t = pexpect.spawn('ssh %s@%s' % (USER, IP))
t.expect('Password:')
t.sendline(PASSWORD)
t.expect('>')
t.sendline('enable')
t.expect('Password:')
t.sendline(ENABLE_PASS)
t.expect('#')
t.sendline("terminal length 0")
t.expect('#')
t.sendline(COMMAND)
t.expect('#')
print t.before
, ,
, enable
getpass
ip_list IP- ,
,
spawn SSH ,
, : expect sendline
expect -
sendline - ,
, :
330
Pexpect
before , pexpect
expect
, , expect ,
# , before .
331
Pexpect
shell
Pexpect shell, > , | , * .
In [3]: p.expect(pexpect.EOF)
Out[3]: 0
pexpect.EOF
pexpect.EOF.
,
, spawn.
ls -ls , pexpect .
, .
, expect , :
In [6]: p.expect('nattaur')
---------------------------------------------------------------------------
EOF Traceback (most recent call last)
<ipython-input-9-9c71777698c2> in <module>()
----> 1 p.expect('nattaur')
332
Pexpect
, expect EOF, .
pexpect.expect
333
Pexpect
pexpect.expect .
pexpect.expect:
EOF - EOF
TIMEOUT - timeout ( timeout = 30 )
compiled re
pexpect.expect:
, .
pexpect.expect ,
,
pexpect.expect ,
, 2, EOF
, ,
pexpect
: pexpect.
334
Telnetlib
telnetlib
telnetlib Python.
telnet.
telnetlib pexpect,
.
2_telnetlib.py:
import telnetlib
import time
import getpass
import sys
COMMAND = sys.argv[1]
USER = raw_input("Username: ")
PASSWORD = getpass.getpass()
ENABLE_PASS = getpass.getpass(prompt='Enter enable password: ')
DEVICES_IP = ['192.168.100.1','192.168.100.2','192.168.100.3']
for IP in DEVICES_IP:
print "Connection to device %s" % IP
t = telnetlib.Telnet(IP)
t.read_until("Username:")
t.write(USER + '\n')
t.read_until("Password:")
t.write(PASSWORD + '\n')
t.write("enable\n")
t.read_until("Password:")
t.write(ENABLE_PASS + '\n')
t.write("terminal length 0\n")
t.write(COMMAND + '\n')
time.sleep(5)
output = t.read_very_eager()
print output
335
Telnetlib
, - ,
.
, telnetlib pexpect:
t = telnetlib.Telnet(ip) - Telnet .
, IP-, ,
read_until - expect pexpect.
write -
read_very_eager - ,
336
Telnetlib
R1#terminal length 0
R1#sh ip int br
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.100.1 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.1.10.1 YES manual up up
FastEthernet0/1.20 10.1.20.1 YES manual up up
FastEthernet0/1.30 10.1.30.1 YES manual up up
FastEthernet0/1.40 10.1.40.1 YES manual up up
FastEthernet0/1.50 10.1.50.1 YES manual up up
FastEthernet0/1.60 10.1.60.1 YES manual up up
FastEthernet0/1.70 10.1.70.1 YES manual up up
R1#
Connection to device 192.168.100.2
R2#terminal length 0
R2#sh ip int br
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.100.2 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.2.10.1 YES manual up up
FastEthernet0/1.20 10.2.20.1 YES manual up up
FastEthernet0/1.30 10.2.30.1 YES manual up up
FastEthernet0/1.40 10.2.40.1 YES manual up up
FastEthernet0/1.50 10.2.50.1 YES manual up up
FastEthernet0/1.60 10.2.60.1 YES manual up up
FastEthernet0/1.70 10.2.70.1 YES manual up up
R2#
Connection to device 192.168.100.3
R3#terminal length 0
R3#sh ip int br
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.100.3 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.3.10.1 YES manual up up
FastEthernet0/1.20 10.3.20.1 YES manual up up
FastEthernet0/1.30 10.3.30.1 YES manual up up
FastEthernet0/1.40 10.3.40.1 YES manual up up
FastEthernet0/1.50 10.3.50.1 YES manual up up
FastEthernet0/1.60 10.3.60.1 YES manual up up
FastEthernet0/1.70 10.3.70.1 YES manual up up
R3#
337
Telnetlib
telnetlib. ,
, .
telnetlib: telnetlib
338
Paramiko
paramiko
Paramiko SSHv2 Python. Paramiko
.
.
Paramiko Python,
:
Paramiko ( 3_paramiko.py):
import paramiko
import getpass
import sys
import time
COMMAND = sys.argv[1]
USER = raw_input("Username: ")
PASSWORD = getpass.getpass()
ENABLE_PASS = getpass.getpass(prompt='Enter enable password: ')
DEVICES_IP = ['192.168.100.1','192.168.100.2','192.168.100.3']
for IP in DEVICES_IP:
print "Connection to device %s" % IP
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.send("enable\n")
ssh.send(ENABLE_PASS + '\n')
time.sleep(1)
ssh.send(COMMAND + "\n")
time.sleep(2)
result = ssh.recv(5000)
print result
339
Paramiko
client = paramiko.SSHClient()
SSH-.
.
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
set_missing_host_key_policy - ,
, .
paramiko.AutoAddPolicy() - ,
HostKeys.
client.connect(IP, username=USER, password=PASSWORD, look_for_keys=False,
allow_agent=False)
client.connect - , SSH-
hostname - IP-
username -
password -
look_for_keys - paramiko
. , False
allow_agent - paramiko SSH
. , , ,
/, .
ssh = client.invoke_shell()
.
invoke_shell SSH
.
:
ssh.send -
ssh.recv - .
, .
, , -
time.sleep
- ,
. ,
340
Paramiko
R1>enable
Password:
R1#terminal length 0
R1#
sh ip int br
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.100.1 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.1.10.1 YES manual up up
FastEthernet0/1.20 10.1.20.1 YES manual up up
FastEthernet0/1.30 10.1.30.1 YES manual up up
FastEthernet0/1.40 10.1.40.1 YES manual up up
FastEthernet0/1.50 10.1.50.1 YES manual up up
FastEthernet0/1.60 10.1.60.1 YES manual up up
FastEthernet0/1.70 10.1.70.1 YES manual up up
R1#
Connection to device 192.168.100.2
R2>enable
Password:
R2#terminal length 0
R2#
sh ip int br
FastEthernet0/0 192.168.100.2 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.2.10.1 YES manual up up
FastEthernet0/1.20 10.2.20.1 YES manual up up
FastEthernet0/1.30 10.2.30.1 YES manual up up
FastEthernet0/1.40 10.2.40.1 YES manual up up
FastEthernet0/1.50 10.2.50.1 YES manual up up
FastEthernet0/1.60 10.2.60.1 YES manual up up
FastEthernet0/1.70 10.2.70.1 YES manual up up
R2#
Connection to device 192.168.100.3
R3>enable
Password:
R3#terminal length 0
R3#
sh ip int br
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.100.3 YES NVRAM up up
FastEthernet0/1 unassigned YES NVRAM up up
FastEthernet0/1.10 10.3.10.1 YES manual up up
FastEthernet0/1.20 10.3.20.1 YES manual up up
FastEthernet0/1.30 10.3.30.1 YES manual up up
FastEthernet0/1.40 10.3.40.1 YES manual up up
FastEthernet0/1.50 10.3.50.1 YES manual up up
341
Paramiko
, enable
terminal length.
, paramiko . ,
recv (, ssh.recv(1000) ), paramiko , .
recv , .
, sh ip int br,
recv , print:
ssh.send("enable\n")
ssh.send(ENABLE_PASS + '\n')
time.sleep(1)
ssh.send(COMMAND + "\n")
time.sleep(3)
result = ssh.recv(5000)
print result
Paramiko
, : Paramiko Client
, ( , ,
ssh): Paramiko Channel
342
Netmiko
netmiko
Netmiko , paramiko
.
netmiko :
netmiko ( 4_netmiko.py):
COMMAND = sys.argv[1]
USER = raw_input("Username: ")
PASSWORD = getpass.getpass()
ENABLE_PASS = getpass.getpass(prompt='Enter enable password: ')
DEVICES_IP = ['192.168.100.1','192.168.100.2','192.168.100.3']
for IP in DEVICES_IP:
print "Connection to device %s" % IP
DEVICE_PARAMS = {'device_type': 'cisco_ios',
'ip': IP,
'username':USER,
'password':PASSWORD,
'secret':ENABLE_PASS }
ssh = ConnectHandler(**DEVICE_PARAMS)
ssh.enable()
result = ssh.send_command(COMMAND)
print result
netmiko.
DEVICE_PARAMS - ,
device_type - , netmiko
, Cisco
343
Netmiko
IOS, 'cisco_ios'
ssh = ConnectHandler(**DEVICE_PARAMS) -
, ,
, (
)
ssh.enable() - enable
secret,
DEVICE_PARAMS
result = ssh.send_command(COMMAND) -
344
Netmiko
, sh ip int br.
netmiko ,
.
345
netmiko
Netmiko :
Arista vEOS
Cisco ASA
Cisco IOS
Cisco IOS-XR
Cisco SG300
HP Comware7
HP ProCurve
Juniper Junos
Linux
SSH
ssh = ConnectHandler(**cisco_router)
enable
enable:
346
netmiko
ssh.enable()
enable:
ssh.exit_enable_mode()
netmiko :
send_command -
send_config_set -
send_config_from_file - (
send_config_set )
send_command_timing -
send_command
send_command .
, ,
send_command_expect , 1.0.0
send_command , send_command_expect
:
command_string -
expect_string -
```delay_factor -
347
netmiko
max_loops - ,
(). 500
strip_prompt - .
strip_command -
, .
send_config_set
send_config_set
.
result = ssh.send_config_set(commands)
,
,
. , IOS-XR ,
send_config_from_file
send_config_from_file
.
result = ssh.send_config_from_file("config_ospf.txt")
, send_config_set .
348
netmiko
, netmiko
:
config_mode -
ssh.config_mode()
exit_config_mode -
ssh.exit_config_mode()
check_config_mode - netmiko
( True, False - )
ssh.check_config_mode()
find_prompt -
ssh.find_prompt()
ssh.commit()
disconnect - SSH
Telnet
1.0.0 netmiko Telnet. ,
Cisco IOS .
, Telnet, ,
, 'cisco_ios_telnet':
, , SSH, Telnet. ,
SSH ( 4_netmiko_telnet.py):
349
netmiko
COMMAND = sys.argv[1]
USER = raw_input("Username: ")
PASSWORD = getpass.getpass()
ENABLE_PASS = getpass.getpass(prompt='Enter enable password: ')
DEVICES_IP = ['192.168.100.1','192.168.100.2','192.168.100.3']
for IP in DEVICES_IP:
print "Connection to device %s" % IP
DEVICE_PARAMS = {'device_type': 'cisco_ios_telnet',
'ip': IP,
'username':USER,
'password':PASSWORD,
'secret':ENABLE_PASS,
'verbose': True}
ssh = ConnectHandler(**DEVICE_PARAMS)
ssh.enable()
result = ssh.send_command(COMMAND)
print result
send_command_timing()
find_prompt()
send_config_set()
send_config_from_file()
check_enable_mode()
disconnect()
350
, ,
. , , . ,
.
"" "" . ,
,
.
, :
threading
multiprocessing
.
:
Linux time
Python datetime
, , Windows.
, ,
. , .
time
time Linux . :
real . , 4.7 .
time time
.
351
datetime
- datetime.
Python.
start_time = datetime.now()
#
time.sleep(5)
$ python test.py
0:00:05.004949
Python (CPython)
, . ,
multiprocessing -
.
, :
(process) - , , .
: ,
(thread) - .
, .
Python ( , CPython - )
. ,
.
, , Python
. , CPython GIL (global interpreter lock).
352
GIL Python.
, GIL ,
. , .
- Python, , ,
- -.
, , ,
, .
, . "": ,
, sleep,
- . , , ,
(GIL) .
, ,
, .
, Python .
Telnet/SSH.
, ,
.
, GIL Python,
multiprocessing .
,
, .
.
,
, :
GIL:
GIL ( )
Inside the Python GIL
Python threads and the GIL
GIL, threads, processes:
353
http://stackoverflow.com/questions/3044580/multiprocessing-vs-threading-python
http://stackoverflow.com/questions/18114285/python-what-are-the-differences-
between-the-threading-and-multiprocessing-modul
354
threading
threading
threading :
- :
,
/
/
, :
, sleep
, , ,
, ,
multiprocessing, threading.
threading
netmiko.
threading, , :
SSH
YAML
netmiko_function.py:
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
ssh = ConnectHandler(**device_dict)
ssh.enable()
result = ssh.send_command(command)
print result
355
threading
devices.yaml :
routers:
- device_type: cisco_ios
ip: 192.168.100.1
username: cisco
password: cisco
secret: cisco
- device_type: cisco_ios
ip: 192.168.100.2
username: cisco
password: cisco
secret: cisco
- device_type: cisco_ios
ip: 192.168.100.3
username: cisco
password: cisco
secret: cisco
( ):
356
threading
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
for th in threads:
th.join()
...
real 0m2.229s
user 0m0.408s
sys 0m0.068s
. , ,
.
conn_threads:
threading.Thread - ,
, ,
th.start() -
threads.append(th) -
th.join() -
357
threading
join .
, join . ,
join . ,
join .
, .
,
. , .
Python Queue, .
,
. Queue.Queue() - FIFO .
connect_ssh,
SSH. .
(
netmiko_threading_data.py):
358
threading
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
#
queue.put({ device_dict['ip']: result })
for th in threads:
th.join()
results = []
# results
for t in threads:
results.append(q.get())
return results
, connect_ssh queue.
queue.put() list.append()
queue.get() list.pop(0)
359
threading
threading, . ,
, .
, , .
, , (
netmiko_threading_data_list.py):
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
#
queue.append({ device_dict['ip']: result })
for th in threads:
th.join()
# , , ,
#
#results = []
#for t in threads:
# results.append(q.get())
return q
360
threading
361
multiprocessing
multiprocessing
multiprocessing threading.
, ,
.
. ,
GIL, , ,
/ .
multiprocessing ( netmiko_multiprocessing.py):
362
multiprocessing
import multiprocessing
from netmiko import ConnectHandler
import sys
import yaml
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
for p in processes:
p.join()
results = []
for p in processes:
results.append(queue.get())
return results
, ,
threading. ,
multiprocessing ,
Queue.
, threading
, :
363
multiprocessing
: 5.833s
threading: 2.225s
multiprocessing: 2.365s
multiprocessing . ,
, .
, ,
multiprocessing threading.
364
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
12.1
send_show_command.
SSH ( netmiko) ,
.
devices_list - ,
command - ,
- IP
365
devices.yaml ( )
command
import netmiko
:
- devices_list - ,
- command - ,
:
- - IP
- -
"""
12.2
send_config_commands
SSH ( netmiko) ,
.
devices_list - ,
config_commands - ,
- IP
-
devices.yaml ( )
366
commands
import netmiko
:
- devices_list - ,
- config_commands - ,
:
- - IP
- -
"""
12.2a
send_config_commands 12.2
output,
. ,
.
12.2b
send_config_commands 12.2a 12.2
, :
Invalid input detected, Incomplete command, Ambiguous command
- ,
,
, .
367
12.3
send_commands ( SSH netmiko).
devices_list - ,
show - show ()
filename - , ,
()
config - ,
, ,
.
- IP
-
devices.yaml ( )
:
commands
command
config.txt
368
12.3a
send_commands ,
device_list , , enable.
, enable
. .
devices2.yaml .
12.3b
send_commands ,
SSH, ping (
ping ).
, subprocess.
ping.
, . ,
, IP-
.
send_commands.
369
12.4
threading.
, :
connect_ssh, send_commands
12.3
send_commands,
conn_threads - .
, ,
show
370
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
ssh = ConnectHandler(**device_dict)
ssh.enable()
result = ssh.send_command(command)
print "Connection to device %s" % device_dict['ip']
for th in threads:
th.join()
results = []
for t in threads:
results.append(q.get())
return results
12.5
12.4.
conn_threads , limit,
.
, 2.
, ,
, limit.
371
12.6
multiprocessing.
, :
connect_ssh, send_commands
12.3
send_commands,
conn_processes - .
, ,
show
372
import multiprocessing
from netmiko import ConnectHandler
import sys
import yaml
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
for p in processes:
p.join()
results = []
for p in processes:
results.append(queue.get())
return results
12.7
12.6.
conn_processes ,
limit, .
, 2.
, ,
, limit.
373
374
13. Jinja
Jinja
Jinja2 , Python. Jinja
() Python , ,
.
Jinja2
.
HTML-
Unix/Linux
Jinja2 pip:
Jinja Jinja2 .
Jinja : .
, .
, ,
, Jinja.
Jinja:
hostname {{name}}
!
interface Loopback255
description Management loopback
ip address 10.255.{{id}}.1 255.255.255.255
!
interface GigabitEthernet0/0
description LAN to {{name}} sw1 {{int}}
ip address {{ip}} 255.255.255.0
!
router ospf 10
router-id 10.255.{{id}}.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
375
13. Jinja
Jinja .
, .
,
.
Jinja (
basic_generator.py):
template = Template(u"""
hostname {{name}}
!
interface Loopback255
description Management loopback
ip address 10.255.{{id}}.1 255.255.255.255
!
interface GigabitEthernet0/0
description LAN to {{name}} sw1 {{int}}
ip address {{ip}} 255.255.255.0
!
router ospf 10
router-id 10.255.{{id}}.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
""")
basic_generator.py:
Jinja2 Template
template,
Jinja
liverpool ,
, , ,
liverpool, ,
.
basic_generator.py, :
376
13. Jinja
$ python basic_generator.py
hostname Liverpool
!
interface Loopback255
description Management loopback
ip address 10.255.11.1 255.255.255.255
!
interface GigabitEthernet0/0
description LAN to Liverpool sw1 Gi1/0/17
ip address 10.1.1.10 255.255.255.0
!
router ospf 10
router-id 10.255.11.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
377
Jinja
Jinja2
3 (
1_example):
router_template.py -
routers_info.yml - , ( YAML),
,
router_config_generator.py -
YAML,
router_template.py
378
Jinja
template_r1 = Template(u"""
hostname {{name}}
!
interface Loopback10
description MPLS loopback
ip address 10.10.{{id}}.1 255.255.255.255
!
interface GigabitEthernet0/0
description WAN to {{name}} sw1 G0/1
!
interface GigabitEthernet0/0.1{{id}}1
description MPLS to {{to_name}}
encapsulation dot1Q 1{{id}}1
ip address 10.{{id}}.1.2 255.255.255.252
ip ospf network point-to-point
ip ospf hello-interval 1
ip ospf cost 10
!
interface GigabitEthernet0/1
description LAN {{name}} to sw1 G0/2 !
interface GigabitEthernet0/1.{{IT}}
description PW IT {{name}} - {{to_name}}
encapsulation dot1Q {{IT}}
xconnect 10.10.{{to_id}}.1 {{id}}11 encapsulation mpls
backup peer 10.10.{{to_id}}.2 {{id}}21
backup delay 1 1
!
interface GigabitEthernet0/1.{{BS}}
description PW BS {{name}} - {{to_name}}
encapsulation dot1Q {{BS}}
xconnect 10.10.{{to_id}}.1 {{to_id}}{{id}}11 encapsulation mpls
backup peer 10.10.{{to_id}}.2 {{to_id}}{{id}}21
backup delay 1 1
!
router ospf 10
router-id 10.10.{{id}}.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
!
""")
379
Jinja
ascii utf-8:
reload(sys)
sys.setdefaultencoding('utf-8')
routers_info.yml
- id: 11
name: Liverpool
to_name: LONDON
IT: 791
BS: 1550
to_id: 1
- id: 12
name: Bristol
to_name: LONDON
IT: 793
BS: 1510
to_id: 1
- id: 14
name: Coventry
to_name: Manchester
IT: 892
BS: 1650
to_id: 2
router_config_generator.py
routers = yaml.load(open('routers_info.yml'))
router_config_generator.py:
template_r1
routers_info.yml routers
() routers:
380
Jinja
, ,
name _r1.txt
, Liverpool_r1.txt
with
( )
router_config_generator.py:
$ python router_config_generator.py
Liverpool_r1.txt
Bristol_r1.txt
Coventry_r1.txt
381
Jinja
hostname Liverpool
!
interface Loopback10
description MPLS loopback
ip address 10.10.11.1 255.255.255.255
!
interface GigabitEthernet0/0
description WAN to Liverpool sw1 G0/1
!
interface GigabitEthernet0/0.1111
description MPLS to LONDON
encapsulation dot1Q 1111
ip address 10.11.1.2 255.255.255.252
ip ospf network point-to-point
ip ospf hello-interval 1
ip ospf cost 10
!
interface GigabitEthernet0/1
description LAN Liverpool to sw1 G0/2
!
interface GigabitEthernet0/1.791
description PW IT Liverpool - LONDON
encapsulation dot1Q 791
xconnect 10.10.1.1 1111 encapsulation mpls
backup peer 10.10.1.2 1121
backup delay 1 1
!
interface GigabitEthernet0/1.1550
description PW BS Liverpool - LONDON
encapsulation dot1Q 1550
xconnect 10.10.1.1 11111 encapsulation mpls
backup peer 10.10.1.2 11121
backup delay 1 1
!
router ospf 10
router-id 10.10.11.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
!
382
Jinja
hostname Bristol
!
interface Loopback10
description MPLS loopback
ip address 10.10.12.1 255.255.255.255
!
interface GigabitEthernet0/0
description WAN to Bristol sw1 G0/1
!
interface GigabitEthernet0/0.1121
description MPLS to LONDON
encapsulation dot1Q 1121
ip address 10.12.1.2 255.255.255.252
ip ospf network point-to-point
ip ospf hello-interval 1
ip ospf cost 10
!
interface GigabitEthernet0/1
description LAN Bristol to sw1 G0/2
!
interface GigabitEthernet0/1.793
description PW IT Bristol - LONDON
encapsulation dot1Q 793
xconnect 10.10.1.1 1211 encapsulation mpls
backup peer 10.10.1.2 1221
backup delay 1 1
!
interface GigabitEthernet0/1.1510
description PW BS Bristol - LONDON
encapsulation dot1Q 1510
xconnect 10.10.1.1 11211 encapsulation mpls
backup peer 10.10.1.2 11221
backup delay 1 1
!
router ospf 10
router-id 10.10.12.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
!
383
Jinja
hostname Coventry
!
interface Loopback10
description MPLS loopback
ip address 10.10.14.1 255.255.255.255
!
interface GigabitEthernet0/0
description WAN to Coventry sw1 G0/1
!
interface GigabitEthernet0/0.1141
description MPLS to Manchester
encapsulation dot1Q 1141
ip address 10.14.1.2 255.255.255.252
ip ospf network point-to-point
ip ospf hello-interval 1
ip ospf cost 10
!
interface GigabitEthernet0/1
description LAN Coventry to sw1 G0/2
!
interface GigabitEthernet0/1.892
description PW IT Coventry - Manchester
encapsulation dot1Q 892
xconnect 10.10.2.1 1411 encapsulation mpls
backup peer 10.10.2.2 1421
backup delay 1 1
!
interface GigabitEthernet0/1.1650
description PW BS Coventry - Manchester
encapsulation dot1Q 1650
xconnect 10.10.2.1 21411 encapsulation mpls
backup peer 10.10.2.2 21421
backup delay 1 1
!
router ospf 10
router-id 10.10.14.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
!
384
Jinja
Jinja
Jinja2, .
Jinja. ,
, , .
, (
2_example):
templates/router_template.txt :
385
Jinja
hostname {{name}}
!
interface Loopback10
description MPLS loopback
ip address 10.10.{{id}}.1 255.255.255.255
!
interface GigabitEthernet0/0
description WAN to {{name}} sw1 G0/1
!
interface GigabitEthernet0/0.1{{id}}1
description MPLS to {{to_name}}
encapsulation dot1Q 1{{id}}1
ip address 10.{{id}}.1.2 255.255.255.252
ip ospf network point-to-point
ip ospf hello-interval 1
ip ospf cost 10
!
interface GigabitEthernet0/1
description LAN {{name}} to sw1 G0/2 !
interface GigabitEthernet0/1.{{IT}}
description PW IT {{name}} - {{to_name}}
encapsulation dot1Q {{IT}}
xconnect 10.10.{{to_id}}.1 {{id}}11 encapsulation mpls
backup peer 10.10.{{to_id}}.2 {{id}}21
backup delay 1 1
!
interface GigabitEthernet0/1.{{BS}}
description PW BS {{name}} - {{to_name}}
encapsulation dot1Q {{BS}}
xconnect 10.10.{{to_id}}.1 {{to_id}}{{id}}11 encapsulation mpls
backup peer 10.10.{{to_id}}.2 {{to_id}}{{id}}21
backup delay 1 1
!
router ospf 10
router-id 10.10.{{id}}.1
auto-cost reference-bandwidth 10000
network 10.0.0.0 0.255.255.255 area 0
!
routers_info.yml
386
Jinja
- id: 11
name: Liverpool
to_name: LONDON
IT: 791
BS: 1550
to_id: 1
- id: 12
name: Bristol
to_name: LONDON
IT: 793
BS: 1510
to_id: 1
- id: 14
name: Coventry
to_name: Manchester
IT: 892
BS: 1650
to_id: 2
router_config_generator_ver2.py
routers = yaml.load(open('routers_info.yml'))
router_config_generator.py jinja2:
FileSystemLoader - ,
,
, templates
Environment - :
,
387
Jinja
, templates.
,
:
import os
curr_dir = os.path.dirname(os.path.abspath(__file__))
env = Environment(loader = FileSystemLoader(curr_dir))
get_template() , .
.
388
Jinja2
Jinja2
, Jinja2
. .
Jinja .
Jinja2 :
(if/else)
(for)
- ,
- -
, Jinja .
.
. Jinja2
.
, ,
3_template_syntax/
cfg_gen.py
389
Jinja2
trim_blocks=True - ,
True ( False).
lstrip_blocks=True - True,
( False).
, ,
:
, YAML
390
hostname {{ name }}
interface Loopback0
ip address 10.0.0.{{ id }} 255.255.255.255
,
.
, ,
, , , . ,
, .
templates/variables.txt,
:
hostname {{ name }}
interface Loopback0
ip address 10.0.0.{{ id }} 255.255.255.255
vlan {{ vlans[0] }}
router ospf 1
router-id 10.0.0.{{ id }}
auto-cost reference-bandwidth 10000
network {{ ospf.network }} area {{ ospf['area'] }}
data_files/vars.yml :
id: 3
name: R3
vlans:
- 10
- 20
- 30
ospf:
network: 10.0.1.0 0.0.0.255
area: 0
vlans :
391
vlans ,
( ospf),
, :
ospf.network ospf['network']
interface Loopback0
ip address 10.0.0.3 255.255.255.255
vlan 10
router ospf 1
router-id 10.0.0.3
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
392
for
for
for .
for {% %} . ,
:
templates/for.txt :
hostname {{ name }}
interface Loopback0
ip address 10.0.0.{{ id }} 255.255.255.255
router ospf 1
router-id 10.0.0.{{ id }}
auto-cost reference-bandwidth 10000
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
data_files/for.yml :
id: 3
name: R3
vlans:
10: Marketing
20: Voice
30: Management
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
393
for
for (, ospf),
( vlans). , , .
. ,
,
, collections.OrderedDict.
interface Loopback0
ip address 10.0.0.3 255.255.255.255
vlan 10
name Marketing
vlan 20
name Voice
vlan 30
name Management
router ospf 1
router-id 10.0.0.3
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
network 10.0.2.0 0.0.0.255 area 2
network 10.1.1.0 0.0.0.255 area 0
394
if/elif/else
if/elif/else
if . , if
- ,
.
if {% %} .
:
{% if ospf %}
router ospf 1
router-id 10.0.0.{{ id }}
auto-cost reference-bandwidth 10000
{% endif %}
templates/if.txt:
hostname {{ name }}
interface Loopback0
ip address 10.0.0.{{ id }} 255.255.255.255
{% if ospf %}
router ospf 1
router-id 10.0.0.{{ id }}
auto-cost reference-bandwidth 10000
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
{% endif %}
if ospf , Python:
, True. , ,
False.
, OSPF ,
ospf .
395
if/elif/else
, data_files/if.yml, ospf:
id: 3
name: R3
vlans:
10: Marketing
20: Voice
30: Management
hostname R3
interface Loopback0
ip address 10.0.0.3 255.255.255.255
vlan 10
name Marketing
vlan 20
name Voice
vlan 30
name Management
, data_files/if_ospf.yml:
id: 3
name: R3
vlans:
10: Marketing
20: Voice
30: Management
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
396
if/elif/else
hostname R3
interface Loopback0
ip address 10.0.0.3 255.255.255.255
vlan 10
name Marketing
vlan 20
name Voice
vlan 30
name Management
router ospf 1
router-id 10.0.0.3
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
network 10.0.2.0 0.0.0.255 area 2
network 10.1.1.0 0.0.0.255 area 0
Python, Jinja .
templates/if_vlans.txt:
data_files/if_vlans.yml :
trunks:
Fa0/1:
action: add
vlans: 10,20
Fa0/2:
action: only
vlans: 10,30
Fa0/3:
action: delete
vlans: 10
397
if/elif/else
, action,
.
, :
, if,
for.
templates/if_for.txt , for:
(data_files/if_for.yml):
vlans:
10: Marketing
20: Voice
30: Management
398
if/elif/else
399
Jinja .
(pipe | )
.
, . ,
,
.
Jinja .
. .
, , .
, .
default
default .
, ,
, , default.
templates/filter_default.txt:
router ospf 1
auto-cost reference-bandwidth {{ ref_bw | default(10000) }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
ref_bw , .
, 10000.
(data_files/filter_default.yml):
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
400
, ,
, .
, ,
( , False Python),
boolean=true .
, :
ref_bw: ''
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
, , :
router ospf 1
auto-cost reference-bandwidth {{ ref_bw | default(10000, boolean=true) }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
401
( ):
dictsort
dictsort . ,
. , ,
.
, dictsort , ,
.
templates/filter_dictsort.txt dictsort:
, ,
.
(data_files/filter_dictsort.yml):
402
trunks:
Fa0/1:
action: add
vlans: 10,20
Fa0/2:
action: only
vlans: 10,30
Fa0/3:
action: delete
vlans: 10
( ):
join
join , join Python.
join ,
.
templates/filter_join.txt join:
(data_files/filter_join.yml):
403
trunks:
Fa0/1:
action: add
vlans:
- 10
- 20
Fa0/2:
action: only
vlans:
- 10
- 30
Fa0/3:
action: delete
vlans:
- 10
404
, Jinja .
- .
Jinja .
. .
, , .
defined
defined .
templates/test_defined.txt:
router ospf 1
{% if ref_bw is defined %}
auto-cost reference-bandwidth {{ ref_bw }}
{% else %}
auto-cost reference-bandwidth 10000
{% endif %}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
, default,
, , ,
, .
(data_files/test_defined.yml):
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
405
iterable
iterable .
, ,
.
templates/test_iterable.txt ( ,
):
(data_files/test_iterable.yml):
406
trunks:
Fa0/1:
action: add
vlans:
- 10
- 20
Fa0/2:
action: only
vlans:
- 10
- 30
Fa0/3:
action: delete
vlans: 10
: vlans: 10 . , 10
join . , is
iterable ( false),
else.
- , ,
lstrip_blocks=True ( ).
407
(set)
set
.
, ,
.
, , ,
.
, .
templates/set.txt, set
:
interface {{ intf }}
{% if vlans is iterable %}
{% if action == 'add' %}
switchport trunk allowed vlan add {{ vlans | join(',') }}
{% elif action == 'delete' %}
switchport trunk allowed vlan remove {{ vlans | join(',') }}
{% else %}
switchport trunk allowed vlan {{ vlans | join(',') }}
{% endif %}
{% else %}
{% if action == 'add' %}
switchport trunk allowed vlan add {{ vlans }}
{% elif action == 'delete' %}
switchport trunk allowed vlan remove {{ vlans }}
{% else %}
switchport trunk allowed vlan {{ vlans }}
{% endif %}
{% endif %}
{% endfor %}
. .
408
(set)
(data_files/set.yml):
trunks:
Fa0/1:
action: add
vlans:
- 10
- 20
Fa0/2:
action: only
vlans:
- 10
- 30
Fa0/3:
action: delete
vlans: 10
interface Fa0/1
switchport trunk allowed vlan add 10,20
interface Fa0/2
switchport trunk allowed vlan 10,30
interface Fa0/3
switchport trunk allowed vlan remove 10
409
Include
include
include .
, ,
, , include.
templates/vlans.txt:
templates/ospf.txt:
router ospf 1
auto-cost reference-bandwidth 10000
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
templates/bgp.txt:
{% include 'vlans.txt' %}
{% include 'ospf.txt' %}
, (data_files/switch.yml):
410
Include
vlans:
10: Marketing
20: Voice
30: Management
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
router ospf 1
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
network 10.0.2.0 0.0.0.255 area 2
network 10.1.1.0 0.0.0.255 area 0
, - ospf.txt
vlans.txt, switch.txt.
templates/router.txt:
{% include 'ospf.txt' %}
{% include 'bgp.txt' %}
logging {{ log_server }}
, include, ,
, include .
(data_files/router.yml):
411
Include
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
bgp:
local_as: 100
loopback: lo100
ibgp_neighbors:
- 10.0.0.2
- 10.0.0.3
ebgp_neighbors:
90.1.1.1: 500
80.1.1.1: 600
log_server: 10.1.1.1
logging 10.1.1.1
include, templates/ospf.txt
templates/switch.txt, templates/router.txt, ,
.
412
,
.
- , .
. ,
, (block).
- , ,
.
,
.
templates/base_router.txt:
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
service sequence-numbers
!
no ip domain lookup
!
ip ssh version 2
!
{% block ospf %}
router ospf 1
auto-cost reference-bandwidth 10000
{% endblock %}
!
{% block bgp %}
{% endblock %}
!
{% block alias %}
{% endblock %}
!
line con 0
logging synchronous
history size 100
line vty 0 4
logging synchronous
history size 100
transport input ssh
!
413
, :
{% block ospf %}
router ospf 1
auto-cost reference-bandwidth 10000
{% endblock %}
!
{% block bgp %}
{% endblock %}
!
{% block alias %}
{% endblock %}
. ,
,
- .
templates/hq_router.txt:
{% extends "base_router.txt" %}
{% block ospf %}
{{ super() }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
{% endblock %}
{% block alias %}
alias configure sh do sh
alias exec ospf sh run | s ^router ospf
alias exec bri show ip int bri | exc unass
alias exec id show int desc
alias exec top sh proc cpu sorted | excl 0.00%__0.00%__0.00%
alias exec c conf t
alias exec diff sh archive config differences nvram:startup-config system:running-conf
ig
alias exec desc sh int desc | ex down
{% endblock %}
templates/hq_router.txt :
{% extends "base_router.txt" %}
, hq_router.txt
base_router.txt.
414
. ,
,
.
, ,
, .
.
.
, ospf alias -. ,
ospf :
{% block ospf %}
router ospf 1
auto-cost reference-bandwidth 10000
{% endblock %}
, :
, .
, .
templates/hq_router.txt ospf {{ super() }} :
{% block ospf %}
{{ super() }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
{% endblock %}
{{ super() }}
. ,
.
super .
. ,
, super.
alias alias. ,
- , .
(data_files/hq_router.yml):
415
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
416
, ospf ,
.
417
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
13.1
cfg_gen.py generate_cfg_from_template.
YAML
, .
templates/for.txt data_files/for.yml.
418
13.1a
generate_cfg_from_template:
, templates,
.
, :
templates/for.txt ( )
data_files/for.yml
13.1b
generate_cfg_from_template 13.1 13.1a:
(Environment)
generate_cfg_from_template ,
Environment .
trim_blocks
lstrip_blocks
13.1c
419
YAML
JSON
Python
. :
YAML - yaml_file
JSON - json_file
Python - py_dict
templates/for.txt :
data_files/for.yml
data_files/for.json
data_dict
data_dict = {'vlans': {
10: 'Marketing',
20: 'Voice',
30: 'Management'},
'ospf': [{'network': '10.0.1.0 0.0.0.255', 'area': 0},
{'network': '10.0.2.0 0.0.0.255', 'area': 2},
{'network': '10.1.1.0 0.0.0.255', 'area': 0}],
'id': 3,
'name': 'R3'}
13.1d
generate_cfg_from_template 13.1, 13.1a, 13.1b
13.1c:
,
data
420
, error_message
( ),
None .
templates/for.txt :
data_files/for.yml
data_files/for.json
data_dict
error_message = """
.
.json, .yml, .yaml Python
"""
data_dict = {'vlans': {
10: 'Marketing',
20: 'Voice',
30: 'Management'},
'ospf': [{'network': '10.0.1.0 0.0.0.255', 'area': 0},
{'network': '10.0.2.0 0.0.0.255', 'area': 2},
{'network': '10.1.1.0 0.0.0.255', 'area': 0}],
'id': 3,
'name': 'R3'}
13.2
config_r1.txt, :
templates/cisco_base.txt - , alias
event manager
hostname
templates/alias.txt - alias
templates/eem_int_desc.txt - event manager applet
templates/alias.txt templates/eem_int_desc.txt .
templates/cisco_router_base.txt.
:
templates/cisco_base.txt
templates/alias.txt
templates/eem_int_desc.txt
, .
421
templates/cisco_router_base.txt,
generate_cfg_from_template 13.1-13.1d. .
, router_info
13.3
templates/ospf.txt OSPF
cisco_ospf.txt. , .
. - process
router-id. - router_id
reference-bandwidth. - ref_bw
, OSPF. - ospf_intf
:
name - , Fa0/1, VLan10, Gi0/0
ip - IP- , 10.0.1.1
area -
passive - . : True
False
ospf_intf, :
, :
passive-interface x
, ,
, :
ip ospf hello-interval 1
422
templates/ospf.txt,
data_files/ospf.yml, generate_cfg_from_template 13.1-
13.1d. .
13.3a
templates/ospf.txt ,
,
, .
if/else.
process - 1
ref_bw - 10000
templates/ospf.txt,
data_files/ospf2.yml, generate_cfg_from_template 13.1-
13.1d. .
13.3b
templates/ospf.txt 13.3a ,
,
, ,
.
if/else.
process - 1
ref_bw - 10000
templates/ospf.txt,
data_files/ospf3.yml, generate_cfg_from_template 13.1-
13.1d. .
13.4
templates/add_vlan_to_switch.txt,
VLAN .
423
VLAN VLAN
VLAN access,
VLAN ,
VLAN access,
VLAN:
interface Gi0/1
switchport mode access
switchport access vlan 5
, VLAN :
interface Gi0/10
switchport trunk allowed vlan add 5
,
data_files/add_vlan_to_switch.yaml.
templates/add_vlan_to_switch.txt
data_files/add_vlan_to_switch.yaml, generate_cfg_from_template
13.1-13.1d. .
424
14. TextFSM.
TextFSM
, - ,
show . , ,
. - ,
Python, , .
, , ,
, Python. ,
: TextFSM.
TextFSM Google .
, .
TextFSM , ,
,
. ,
. .
, :
TextFSM, ,
.
traceroute:
, , .
, TextFSM ( traceroute.template):
425
14. TextFSM.
Value ID (\d+)
Value Hop (\d+(\.\d+){3})
Start
^ ${ID} ${Hop} -> Record
: (\d+) -
Value Hop (\d+(\.\d+){3}) - Hop,
IP- : (\d+(\.\d+){3})
Start . , :
, ID
Hop
TextFSM : ${ }
Record , ,
, TextFSM (
)
traceroute TextFSM
(parse_traceroute.py):
import textfsm
traceroute = """
r2#traceroute 90.0.0.9 source 33.0.0.2
traceroute 90.0.0.9 source 33.0.0.2
Type escape sequence to abort.
Tracing the route to 90.0.0.9
VRF info: (vrf in name/id, vrf out name/id)
1 10.0.12.1 1 msec 0 msec 0 msec
2 15.0.0.5 0 msec 5 msec 4 msec
3 57.0.0.7 4 msec 1 msec 4 msec
4 79.0.0.9 4 msec * 1 msec
"""
template = open('traceroute.textfsm')
fsm = textfsm.TextFSM(template)
result = fsm.ParseText(traceroute)
print fsm.header
print result
426
14. TextFSM.
$ python parse_traceroute.py
['ID', 'Hop']
[['1', '10.0.12.1'], ['2', '15.0.0.5'], ['3', '57.0.0.7'], ['4', '79.0.0.9']]
, ,
. , :
IP-.
traceroute - , traceroute
template = open('traceroute.textfsm') - TextFSM
template
fsm = textfsm.TextFSM(template) - ,
TextFSM
result = fsm.ParseText(traceroute) - ,
,
: print fsm.header ,
. ,
traceroute .
TextFSM :
TextFSM (
)
csv
427
TextFSM
TextFSM
TextFSM .
, TextFSM.
. ,
, ,
, ,
, - .
traceroute:
# :
Value ID (\d+)
Value Hop (\d+(\.\d+){3})
# Start
Start
#
^ ${ID} ${Hop} -> Record
.
- .
. TextFSM
.
( ):
Value - , , .
428
TextFSM
option - , .
, , .
:
Filldown - , ,
(
).
, ,
,
, .
Key - ,
Required - , ,
, .
List -
. ,
.
Fillup - Filldown, , ,
. Required.
name - , .
.
regex - , .
, :
(
, )
-
,
^
Start.
, ,
.
, EOF( )
End.
429
TextFSM
Start - .
.
End -
EOF.
EOF - , ,
. :
EOF
^.* -> Record
EOF , .
, , , EOF:
EOF
TextFSM
( ) ,
,
, .
^
^
regex - ,
, $ValueName
${ValueName} ( )
, ,
, $$
430
TextFSM
, :
, ->
, L.R S
L - Line Action - ,
R - Record Action - ,
S - State Action -
,
Next.NoRecord.
Line Actions
Line Actions:
Next - ,
. ,
Continue - , - ,
Record Action
Record Action - , Line
Action. . :
NoRecord - . ,
Record - , . ,
, Filldown, .
Clear - , , Filldown.
Clearall - .
, Line
Record . ,
.
State Transition
, :
:
,
431
TextFSM
,
.
,
. ,
.
Error Action
Error ,
, .
432
TextFSM
TextFSM
TextFSM.
,
parse_output.py. :
:
import sys
import textfsm
from tabulate import tabulate
template = sys.argv[1]
output_file = sys.argv[2]
f = open(template)
output = open(output_file).read()
re_table = textfsm.TextFSM(f)
header = re_table.header
result = re_table.ParseText(output)
tabulate (
, ).
, tabulate,
.
.
.
, TextFSM.
show clock
- sh clock ( output/sh_clock.txt):
433
TextFSM
, :
Value
-
, , ,
. -
+ -
\S - , whitespace
\w -
\d -
, Start,
, ^ , (
templates/sh_clock.template):
Start
^${Time}.* ${Timezone} ${WeekDay} ${Month} ${MonthDay} ${Year} -> Record
434
TextFSM
, , ,
Record. ,
, ,
.
TextFSM , ,
. :
show clock,
, :
1 : 15:10:44
2 : UTC
3 : Sun
4 : Nov
5 : 13
6 : 2016
, Record, ,
, Next.
, . sh
clock, , .
, , .
435
TextFSM
Version :
Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 12.2(55)SE9, RELEASE S
OFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2014 by Cisco Systems, Inc.
Compiled Mon 03-Mar-14 22:53 by prod_rel_team
advertisement version: 2
VTP Management Domain: ''
Native VLAN: 1
Duplex: full
Management address(es):
IP address: 10.1.1.2
-------------------------
Device ID: R1
Entry address(es):
IP address: 10.1.1.1
Platform: Cisco 3825, Capabilities: Router Switch IGMP
Interface: GigabitEthernet1/0/22, Port ID (outgoing port): GigabitEthernet0/0
Holdtime : 156 sec
Version :
Cisco IOS Software, 3800 Software (C3825-ADVENTERPRISEK9-M), Version 12.4(24)T1, RELEA
SE SOFTWARE (fc3)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2009 by Cisco Systems, Inc.
Compiled Fri 19-Jun-09 18:40 by prod_rel_team
advertisement version: 2
VTP Management Domain: ''
Duplex: full
Management address(es):
-------------------------
Device ID: R2
Entry address(es):
IP address: 10.2.2.2
Platform: Cisco 2911, Capabilities: Router Switch IGMP
Interface: GigabitEthernet1/0/21, Port ID (outgoing port): GigabitEthernet0/0
Holdtime : 156 sec
Version :
Cisco IOS Software, 2900 Software (C3825-ADVENTERPRISEK9-M), Version 15.2(2)T1, RELEAS
E SOFTWARE (fc3)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2009 by Cisco Systems, Inc.
Compiled Fri 19-Jun-09 18:40 by prod_rel_team
436
TextFSM
advertisement version: 2
VTP Management Domain: ''
Duplex: full
Management address(es):
LOCAL_HOST -
DEST_HOST -
MGMNT_IP - IP-
PLATFORM -
LOCAL_PORT - ,
REMOTE_PORT -
IOS_VERSION - IOS
( templates/sh_cdp_n_det.template):
Start
^${LOCAL_HOST}[>#].
^Device ID: ${DEST_HOST}
^.*IP address: ${MGMNT_IP}
^Platform: ${PLATFORM},
^Interface: ${LOCAL_PORT}, Port ID \(outgoing port\): ${REMOTE_PORT}
^.*Version ${IOS_VERSION},
, , ,
, , TextFSM
. , , ,
437
TextFSM
, sh_cdp_n_det.txt ,
, .
Record
- , Record. ,
.
Start
^${LOCAL_HOST}[>#].
^Device ID: ${DEST_HOST}
^.*IP address: ${MGMNT_IP}
^Platform: ${PLATFORM},
^Interface: ${LOCAL_PORT}, Port ID \(outgoing port\): ${REMOTE_PORT}
^.*Version ${IOS_VERSION}, -> Record
. , LOCAL_HOST
, .
Filldown
438
TextFSM
, , ,
. , ,
, Filldown LOCAL_HOST:
Start
^${LOCAL_HOST}[>#].
^Device ID: ${DEST_HOST}
^.*IP address: ${MGMNT_IP}
^Platform: ${PLATFORM},
^Interface: ${LOCAL_PORT}, Port ID \(outgoing port\): ${REMOTE_PORT}
^.*Version ${IOS_VERSION}, -> Record
LOCAL_HOST .
- ,
LOCAL_HOST.
Required
, , , . ,
Filldown. , ,
,
Required:
439
TextFSM
Start
^${LOCAL_HOST}[>#].
^Device ID: ${DEST_HOST}
^.*IP address: ${MGMNT_IP}
^Platform: ${PLATFORM},
^Interface: ${LOCAL_PORT}, Port ID \(outgoing port\): ${REMOTE_PORT}
^.*Version ${IOS_VERSION}, -> Record
Start
^${INTF}\s+${ADDR}\s+\w+\s+\w+\s+${STATUS}\s+${PROTO} -> Record
, .
440
TextFSM
( output/sh_ip_int_br.txt):
, ,
, , next-hop
.
441
TextFSM
,
OSPF , O ( , ).
Start
^O +${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop}, -> Record
442
TextFSM
, 10.4.4.4/32. ,
, .
List
List NextHop:
Start
^O +${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop}, -> Record
, NextHop ,
.
, , ,
NextHop, Record.
, ,
. ,
. , :
^O -> Continue.Record
Record , . ,
, ,
.
Continue , , -
. , .
443
TextFSM
,
( ):
^\s+\[${Distance}\/${Metric}\]\svia\s${NextHop},
( templates/sh_ip_route_ospf.template):
Start
^O -> Continue.Record
^O +${Network}${Mask}\s\[${Distance}\/${Metric}\]\svia\s${NextHop},
^\s+\[${Distance}\/${Metric}\]\svia\s${NextHop},
, ,
, .
, :
444
TextFSM
, :
port-channel. , Po1
. , ['Fa0/1', 'Fa0/2', 'Fa0/3']
, , TextFSM
. ,
.
Start
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +${MEMBERS}\( -> Record
CHANNEL -
MEMBERS - , .
- List
445
TextFSM
CHANNEL MEMBERS
--------- ----------
Po1 ['Fa0/1']
Po3 ['Fa0/11']
, .
, , .
, Continue .
, , .
, .
Start
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +\S+ +${MEMBERS}\( -> Record
, MEMBERS
.
CHANNEL MEMBERS
--------- --------------------
Po1 ['Fa0/1', 'Fa0/2']
Po3 ['Fa0/11', 'Fa0/12']
,
. , ,
Record ,
.
Record , , ,
, ,
.
( templates/sh_etherchannel_summary.txt):
446
TextFSM
Start
^\d+.* -> Continue.Record
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +\S+ +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +(\S+ +){2} +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +(\S+ +){3} +${MEMBERS}\( -> Continue
CHANNEL MEMBERS
--------- ----------------------------------------
Po1 ['Fa0/1', 'Fa0/2', 'Fa0/3']
Po3 ['Fa0/11', 'Fa0/12', 'Fa0/13', 'Fa0/14']
, .
, .
sh etherchannel summary (
output/sh_etherchannel_summary2.txt):
447
TextFSM
- ,
.
, (
templates/sh_etherchannel_summary2.txt):
Start
^\d+.* -> Continue.Record
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +\S+ +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +(\S+ +){2} +${MEMBERS}\( -> Continue
^\d+ +${CHANNEL}\(\S+ +[\w-]+ +[\w ]+ +(\S+ +){3} +${MEMBERS}\( -> Continue
^ +${MEMBERS} -> Continue
^ +\S+ +${MEMBERS} -> Continue
^ +(\S+ +){2} +${MEMBERS} -> Continue
^ +(\S+ +){3} +${MEMBERS} -> Continue
CHANNEL MEMBERS
--------- ------------------------------------------------------------
Po1 ['Fa0/1', 'Fa0/2', 'Fa0/3']
Po3 ['Fa0/11', 'Fa0/12', 'Fa0/13', 'Fa0/14', 'Fa0/15', 'Fa0/16']
TextFSM.
Cisco
ntc-ansible.
448
CLI Table
- .
,
, ,
.
TextFSM .
, ,
. TextFSM
index.
-
-
, (
, ):
-
-
, ,
, Hostname, Vendor.
,
.
, show version Cisco HP.
, ,
. ,
, , ,
.
, ,
, [[]]
index:
449
CLI Table
, :
sh((ow)?)? ip int((erface)?)?
br((ief)?)?
, TextFSM ,
, :
sh ip int br
show ip inter bri
CLI table
clitable index.
templates index:
sh_cdp_n_det.template
sh_clock.template
sh_ip_int_br.template
sh_ip_route_ospf.template
index
clitable , terminal,
, TextFSM ( ),
terminal.py. ,
TextFSM. ,
, : print textfsm.__file__
, clitable:
450
CLI Table
clitable -
show ip route ospf. ,
output/sh_ip_route_ospf.txt, :
, ,
, ,
:
,
. , ,
- , index. ,
, sh ip route ospf
.
ParseCmd :
, cli_table, sh ip route
ospf.
cli_table ( , dir(cli_table)):
451
CLI Table
In [6]: cli_table.
cli_table.AddColumn cli_table.NewRow cli_table.index cli_t
able.size
cli_table.AddKeys cli_table.ParseCmd cli_table.index_file cli_t
able.sort
cli_table.Append cli_table.ReadIndex cli_table.next cli_t
able.superkey
cli_table.CsvToTable cli_table.Remove cli_table.raw cli_t
able.synchronised
cli_table.FormattedTable cli_table.Reset cli_table.row cli_t
able.table
cli_table.INDEX cli_table.RowWith cli_table.row_class cli_t
able.template_dir
cli_table.KeyValue cli_table.extend cli_table.row_index
cli_table.LabelValueTable cli_table.header cli_table.separator
, print cli_table , :
FormattedTable :
,
.
cli_table , ,
, :
452
CLI Table
In [9]: data_rows = []
In [11]: data_rows
Out[11]:
[['10.0.24.0', '/24', '110', '20', ['10.0.12.2']],
['10.0.34.0', '/24', '110', '20', ['10.0.13.3']],
['10.2.2.2', '/32', '110', '11', ['10.0.12.2']],
['10.3.3.3', '/32', '110', '11', ['10.0.13.3']],
['10.4.4.4', '/32', '110', '21', ['10.0.13.3', '10.0.12.2', '10.0.14.4']],
['10.5.35.0', '/24', '110', '20', ['10.0.13.3']]]
In [12]: cli_table.header.viewvalues()
Out[12]: dict_values([])
In [13]: header = []
In [14]: header
Out[14]: ['Network', 'Mask', 'Distance', 'Metric', 'NextHop']
, .
( textfsm_clitable.py):
453
CLI Table
output_sh_ip_route_ospf = open('output/sh_ip_route_ospf.txt').read()
cli_table = clitable.CliTable('index', 'templates')
attributes = {'Command': 'show ip route ospf' , 'Vendor': 'Cisco'}
cli_table.ParseCmd(output_sh_ip_route_ospf, attributes)
data_rows = []
header = []
for name in cli_table.header:
header.append(name)
print header
for row in data_rows:
print row
,
. .
454
CLI Table
$ python textfsm_clitable.py
CLI Table output:
Network, Mask, Distance, Metric, NextHop
10.0.24.0, /24, 110, 20, ['10.0.12.2']
10.0.34.0, /24, 110, 20, ['10.0.13.3']
10.2.2.2, /32, 110, 11, ['10.0.12.2']
10.3.3.3, /32, 110, 11, ['10.0.13.3']
10.4.4.4, /32, 110, 21, ['10.0.13.3', '10.0.12.2', '10.0.14.4']
10.5.35.0, /24, 110, 20, ['10.0.13.3']
Formatted Table:
Network Mask Distance Metric NextHop
====================================================================
10.0.24.0 /24 110 20 10.0.12.2
10.0.34.0 /24 110 20 10.0.13.3
10.2.2.2 /32 110 11 10.0.12.2
10.3.3.3 /32 110 11 10.0.13.3
10.4.4.4 /32 110 21 10.0.13.3, 10.0.12.2, 10.0.14.4
10.5.35.0 /24 110 20 10.0.13.3
, TextFSM, ,
,
.
455
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
14.1
, TextFSM, .
parse_output:
:
template - TextFSM ( ,
)
output - show ()
- ( ,
header)
,
456
( , result)
- .
import sys
import textfsm
from tabulate import tabulate
template = sys.argv[1]
output_file = sys.argv[2]
f = open(template)
output = open(output_file).read()
re_table = textfsm.TextFSM(f)
header = re_table.header
result = re_table.ParseText(output)
14.1a
parse_output 14.1 , ,
, , - ,
, . ,
.
14.2
parse_output 14.1.
, ,
.
CSV .
CSV, list_to_csv,
:
:
-
,
, CSV
457
sh ip int br (
).
14.3
TextFSM sh ip dhcp snooping binding.
output/sh_ip_dhcp_snooping.txt.
MacAddress
IpAddress
VLAN
Interface
14.1.
14.4
clitable parse_command_dynamic.
, : :
'Command':
'Vendor': ( , index ,
,
)
, ()
- index
, ()
- templates
()
( 14.1a):
-
-
sh ip int br.
458
output_sh_ip_route_ospf = open('output/sh_ip_route_ospf.txt').read()
cli_table = clitable.CliTable('index', 'templates')
attributes = {'Command': 'show ip route ospf' , 'Vendor': 'Cisco'}
cli_table.ParseCmd(output_sh_ip_route_ospf, attributes)
data_rows = []
header = []
for name in cli_table.header:
header.append(name)
print header
for row in data_rows:
print row
14.4a
14.4:
show_output,
False,
, FormattedTable
( )
14.5
TextFSM
.
, :
show
TextFSM
459
, , :
send_show_command 12.1
parse_command_dynamic 14.4
send_and_parse_command:
parse_command_dynamic
send_show_command.
send_and_parse_command,
, , ,
send_and_parse_command :
send_show_command
:
- IP
-
, , ,
parse_command_dynamic
, , :
- IP
- ( , ,
parse_command_dynamic)
send_show_command devices.yaml,
.
14.6
14.5,
.
, connect_ssh conn_processes (
multiprocessing) parse_command_dynamic 14.4.
send_and_parse_command_parallel:
connect_ssh, conn_processes
parse_command_dynamic
send_and_parse_command_parallel,
460
, , ,
send_and_parse_command_parallel ,
:
- IP
- ( , ,
parse_command_dynamic)
conn_processes devices.yaml,
.
multiprocessing:
461
import multiprocessing
from netmiko import ConnectHandler
import sys
import yaml
COMMAND = sys.argv[1]
devices = yaml.load(open('devices.yaml'))
for p in processes:
p.join()
results = []
for p in processes:
results.append(queue.get())
return results
462
15. Ansible
Ansible
Ansible - . Ansible
, ,
, .
, , Ansible.
, Ansible .
,
CLI.
, Ansible
.
( ).
Ansible ,
. .
, Ansible:
SSH
SSH (
)
:
-
Jinja2
Ansible,
. , , Ansible
- .
Ansible
463
15. Ansible
Ansible ,
.
Ansible ,
.
Ansible -.
, pip:
, Ansible ,
2.2.1.0 -
. , ,
(05.02.2017), .
.
, SSH.
, :
: cisco
: cisco
enable: cisco
SSH 2
IP-:
R1: 192.168.100.1
R2: 192.168.100.2
R3: 192.168.100.3
SW1: 192.168.100.100
,
, Ansible group_vars/all.yml.
464
15. Ansible
465
Ansible
Ansible
Ansible:
SSH
, Python,
,
YAML
( )
Quick start
Ansible . , :
-
Ansible,
ad-hoc -
, ad-hoc , show
466
Ansible
, playbook (
). ad-hoc .
Ansible.
467
- , , Ansible
.
IP- .
.
INI. :
r5.example.com
[cisco-routers]
192.168.255.1
192.168.255.2
192.168.255.3
192.168.255.4
[cisco-edge-routers]
192.168.255.1
192.168.255.2
, - .
, : cisco-routers cisco-edge-routers.
, 192.168.255.1 192.168.255.2
. , ,
.
- cisco-edge-
routers, , -,
, cisco-routers.
, /etc/ansible/hosts .
. ,
ansible, -i <> ,
Ansible.
- SSH,
, ( ).
468
OpenSSH
paramiko.
, SSH:
[cisco-routers]
192.168.255.1:22022
192.168.255.2:22022
192.168.255.3:22022
[cisco-switches]
192.168.254.1
192.168.254.2
,
:
[cisco-routers]
192.168.255.[1-5]
, 192.168.255.1-
192.168.255.5.
Ansible .
:
[cisco-routers]
192.168.255.1
192.168.255.2
192.168.255.3
[cisco-switches]
192.168.254.1
192.168.254.2
[cisco-devices:children]
cisco-routers
cisco-switches
469
Ad-Hoc
Ad Hoc
Ad-hoc - - Ansible
.
, , , - ,
, . - ,
.
, Ansible.
.
myhosts:
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
,
, . Ansible
.
(
, ).
ad-hoc :
cisco-routers - ,
, all
*
Ansible ,
.
-i myhosts - -i
470
Ad-Hoc
raw
SSH ,
Python. ,
raw , ,
Ansible
-a "sh ip int br" - -a
-u cisco - cisco
--ask-pass - ,
, sshpass.
.
sshpass:
471
Ad-Hoc
.
.
/
.
472
Ansible .
Ansible (
):
ANSIBLE_CONFIG ( )
ansible.cfg ( )
.ansible.cfg ( )
/etc/ansible/ansible.cfg
Ansible
( ).
.
, .
myhosts:
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
ansible.cfg:
[defaults]
inventory = ./myhosts
remote_user = cisco
ask_pass = True
[defaults] -
.
, , ,
Ansible
473
Ansible,
.
ad-hoc :
, --ask-pass.
gathering
, Ansible .
- , Ansible.
playbook .
, , setup.
, , setup ,
. Ansible playbook.
( ). ios_facts.
gathering = explicit
host_key_checking
host_key_checking y , SSH.
host_key_checking=False ,
.
, Ansible
.
,
Cisco, .
~/.ssh/known_hosts.
ad-hoc , , :
474
host_key_checking:
[defaults]
inventory = ./myhosts
remote_user = cisco
ask_pass = True
host_key_checking=False
ad-hoc :
475
Ansible ~/.ssh/known_hosts.
.
.
Ansible.
476
477
Ansible
Ansible
( ). , 200
.
, Ansible. , ,
, .
, ad-hoc
(play), playbook.
, , . -
, - , ,
, .
, ad-hoc , raw.
:
playbook (playbook
):
, JSON.
Ansible, , . ,
, ,
.
Ansible :
core - , Anible.
Ansible.
extra - Ansible, ,
Ansible. , ,
.
.
478
Ansible .
.
479
playbook
playbooks
Playbook ( ) ,
- .
playbook:
play - ,
task - . , :
( , )
( )
playbook
Playbook YAML.
playbook
2_playbook_basics
plabook 1_show_commands_with_raw.yml:
480
playbook
---
tasks:
tasks:
playbook (play):
hosts: cisco-routers - cisco-
routers
, , : hosts:
cisco-routers:cisco-switches . ,
, play remote_user. ,
Ansible, play.
gather_facts: false - ,
.
. , gather_facts play
.
tasks: -
() .
.
.
481
playbook
playbook :
playbook:
$ ansible-playbook 1_show_commands_with_raw.yml
482
playbook
, playbook .
ad-hoc , ansible. playbook - ansible-
playbook.
, , , ,
, playbook -v ( ):
$ ansible-playbook 1_show_commands_with_raw.yml -v
483
playbook
, .
(play) (task) , ,
playbook.
, , ,
, hosts. ,
,
.
playbook, - ,
, .
$ ansible-playbook 1_show_commands_with_raw.yml
484
playbook
192.168.100.1.
- Ansible :
, playbook, - , Ansible
, playbook,
retry. ( ,
)
.
1_show_commands_with_raw.retry :
192.168.100.1
, playbook
(). ,
, playbook.
192.168.100.1,
playbook :
Ansible , retry
playbook .
485
playbook
playbook ( , retry):
--limit . ,
playbook, , playbook.
, playbook
192.168.100.1:
Ansible . ,
, ,
.
, . , raw
. playbook ,
changed.
, , , , Linux httpd,
, . ,
, . , .
, .
, ,
.
486
, :
, ,
.
.
playbook
Ansible :
, _
, ( YAML):
R1:
IP: 10.1.1.1/24
DG: 10.1.1.100
R1['IP']
R1.IP
, , ,
( ) Python
Ansible.
playbook
/
, playbook include ( Jinja2)
487
,
playbook
, ,
.
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
[cisco-routers:vars]
ntp_server=192.168.255.100
log_server=10.255.100.1
playbook
playbook. ,
, .
488
---
vars:
ntp_server: 192.168.255.100
log_server: 10.255.100.1
tasks:
Ansible / :
, group_vars,
, , .
, group_vars all,
, .
, host_vars,
, .
, YAML.
: yml, yaml, json
group_vars host_vars ,
playbook. inventory (
).
, Ansible
, myhosts :
489
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
group_vars _
all.yml |
cisco-routers.yml |
cisco-switches.yml _|
|
host_vars _
192.168.100.1 |
192.168.100.2 |
192.168.100.3 |
192.168.100.100 _|
|
myhosts |
group_vars/all.yml ( ,
):
---
cli:
host: "{{ inventory_hostname }}"
username: "cisco"
password: "cisco"
transport: cli
authorize: yes
auth_pass: "cisco"
, , Ansible.
group_vars/all.yml cli.
,
Ansible ( )
490
inventory_hostname - , ,
Ansible .
{{ inventory_hostname }} - .
Jinja
group_vars/cisco-routers.yml
---
log_server: 10.255.100.1
ntp_server: 10.255.100.1
users:
user1: pass1
user2: pass2
user3: pass3
group_vars/cisco-routers.yml , IP-
Log NTP .
, , .
group_vars/cisco-switches.yml
---
vlans:
- 10
- 20
- 30
host_vars/192.168.100.1
---
hostname: london_r1
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.1
ospf_ints:
- 192.168.100.1
- 10.0.0.1
- 10.255.1.1
491
host_vars/192.168.100.2
---
hostname: london_r2
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.2
ospf_ints:
- 192.168.100.2
- 10.0.0.2
- 10.255.2.2
host_vars/192.168.100.3
---
hostname: london_r3
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.3
ospf_ints:
- 192.168.100.3
- 10.0.0.3
- 10.255.3.3
host_vars/192.168.100.100
---
hostname: london_sw1
mgmnt_int: VLAN100
mgmnt_ip: 10.0.0.100
, playbook include (
Jinja2)
,
playbook
{% if book.book_name == "ansible_neteng" %}
. {% else %} Ansible
{% endif %}
492
, . ,
,
Ansible .
( ):
. ,
,
group_vars
host_vars
(play)
, vars_prompt
, vars_files
register
set_facts
include
( )
(task) ( )
, playbook --extra-vars
( )
493
,
, .
raw,
.
verbose
, ,
- verbose.
, , , , ,
.
Ansible.
playbook verbose ( ):
ansible-playbook 1_show_commands_with_raw.yml -v
v , .
playbook v (5
), :
, JSON:
494
changed - ,
rc - return code. ,
-
stderr - , .
, -
stdout -
stdout_lines - ,
register
register .
,
.
---
tasks:
playbook, ,
, .
- , debug.
debug
debug .
, , .
, playbook
2_register_vars.yml debug:
495
---
tasks:
, sh_ip_int_br_result,
stdout_lines. sh_ip_int_br_result.stdout_lines
, .
playbook :
$ ansible-playbook 2_register_vars.yml
496
playbook 3_register_debug_when.yml:
497
---
tasks:
debug , ,
msg.
when ,
when: "'invalid' in sh_ip_int_br_result.stdout" - ,
,
sh_ip_int_br_result.stdout invalid (,
)
, ,
, .
Ansible.
playbook:
$ ansible-playbook 3_register_debug_when.yml
498
skipping - ,
. , when
.
playbook, :
---
tasks:
$ ansible-playbook 3_register_debug_when.yml
499
, , when
, debug.
500
,
raw.
.
, ,
.
, ,
:
API
, CLI
API, , NXOS,
, ,
(, NXOS 60 ).
, CLI, Ansible
:
os_command - show
os_facts -
os_config -
, , . ,
Cisco IOS, :
ios_command
ios_config
ios_facts
Dellos10
Dellos6
Dellos9
EOS
IOS
IOS XR
JUNOS
501
SR OS
VyOS
, Ansible .
, Ansible
, Ansible,
. , ,
Ansible ( 2.2),
, .
, Cisco IOS:
ios_command
ios_config
ios_facts
, ntc-ansible, core
Ansible.
Ansible :
paramiko
SSH - OpenSSH.
local - ,
SSH, SSH ,
.
, Ansible Python , ,
. Python,
CLI, ,
, Ansible.
, playbook,
:
502
gather_facts - ,
connection - , .
local
, (play), :
gather_facts: false
connection: local
---
Ansible ,
-.
,
( ansible.cfg):
[defaults]
gathering = explicit
, Ansible
(, playbook
).
, , .
, , -.
503
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
[cisco-routers:vars]
ansible_connection=local
, , group_vars/all.yml:
---
ansible_connection: local
---
, .
provider
, ,
.
host - IP-
port -
username -
password -
transport - : CLI API. - cli
authorize - (enable, Cisco)
auth_pass -
504
, Ansible - provider.
(task):
tasks:
cli playbook,
provider:
vars:
cli:
host: "{{ inventory_hostname }}"
username: cisco
password: cisco
transport: cli
tasks:
- name: run show version
ios_command:
commands: show version
provider: "{{ cli }}"
, , group_vars.
, ,
group_vars/all.yml:
---
cli:
host: "{{ inventory_hostname }}"
username: cisco
password: cisco
transport: cli
authorize: yes
auth_pass: cisco
playbook ,
playbook:
505
tasks:
- name: run show version
ios_command:
commands: show version
provider: "{{ cli }}"
, Ansible :
ANSIBLE_NET_USERNAME - username
ANSIBLE_NET_PASSWORD - password
ANSIBLE_NET_SSH_KEYFILE - ssh_keyfile
ANSIBLE_NET_AUTHORIZE - authorize
ANSIBLE_NET_AUTH_PASS - auth_pass
provider
(task)
ios_command, ios_facts
ios_config. , playbook ,
(, ).
myhosts:
[cisco-routers]
192.168.100.1
192.168.100.2
192.168.100.3
[cisco-switches]
192.168.100.100
ansible.cfg:
[defaults]
inventory = ./myhosts
remote_user = cisco
ask_pass = True
506
group_vars/all.yml cli,
, provider:
---
cli:
host: "{{ inventory_hostname }}"
username: "cisco"
password: "cisco"
transport: cli
authorize: yes
auth_pass: "cisco"
507
ios_command
ios_command
ios_command - show IOS
.
ios_command
. - ios_config.
, :
SSH,
enable
terminal length 0 , show
, .
---
tasks:
ios_command :
commands - ,
provider -
, group_vars/all.yml
, register
, ios_command.
508
ios_command
playbook:
$ ansible-playbook 1_ios_command.yml
raw, playbook ,
.
509
ios_command
ios_command .
Playbook 2_ios_command.yml :
---
tasks:
,
- , YAML.
playbook ( ):
$ ansible-playbook 2_ios_command.yml
510
ios_command
,
stdout stdout_lines . ,
.
, , ,
:
511
ios_command
. ,
, , .
, , playbook
$ ansible-playbook 2_ios_command.yml
Ansible . - 'Invalid
input'.
Ambiguous command
Incomplete command
512
ios_facts
ios_facts
ios_facts - IOS.
dir
show version
show memory statistics
show interfaces
show ipv6 interface
show lldp
show lldp neighbors detail
show running-config
, Ansible ,
EEM applet,
.
-
, . ,
, .
, gather_subset.
( ,
):
all
hardware
dir
show version
show memory statistics
config
show version
show running-config
interfaces
dir
show version
show interfaces
show ipv6 interface
show lldp
513
ios_facts
- ios_facts:
gather_subset: all
provider: "{{ cli }}"
interfaces:
- ios_facts:
gather_subset:
- interfaces
provider: "{{ cli }}"
, hardware:
- ios_facts:
gather_subset:
- "!hardware"
provider: "{{ cli }}"
Ansible :
ansible_net_all_ipv4_addresses - IPv4
ansible_net_all_ipv6_addresses - IPv6
ansible_net_config - ( Cisco sh run)
ansible_net_filesystems -
ansible_net_gather_subset - (hardware, default,
interfaces, config)
ansible_net_hostname -
ansible_net_image -
ansible_net_interfaces - .
- , -
ansible_net_memfree_mb -
ansible_net_memtotal_mb -
ansible_net_model -
ansible_net_serialnum -
ansible_net_version - IOS
514
ios_facts
---
tasks:
- name: Facts
ios_facts:
gather_subset: all
provider: "{{ cli }}"
$ ansible-playbook 1_ios_facts.yml
, , ,
-v ( ):
$ ansible-playbook 1_ios_facts.yml -v
Using /home/nata/pyneng_course/chapter15/ansible.cfg as config file
515
ios_facts
, Ansible ,
playbook, ..
, debug (playbook
2_ios_facts_debug.yml):
---
tasks:
- name: Facts
ios_facts:
gather_subset: all
provider: "{{ cli }}"
playbook:
$ ansible-playbook 2_ios_facts_debug.yml
516
ios_facts
, verbose,
. ,
, ,
.
copy.
Playbook 3_ios_facts.yml
( all_facts playbook
Create all_facts dir Ansible ):
517
ios_facts
---
tasks:
- name: Facts
ios_facts:
gather_subset: all
provider: "{{ cli }}"
register: ios_facts_result
copy (
Ansible) . , ,
connection: local , .
, copy :
- copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
, , , .
, ios_facts_result,
all_facts/{{inventory_hostname}}_facts.json.
, copy, src,
content.
to_nice_json - Jinja2,
,
Jinja2
518
ios_facts
dest ,
.
playbook:
$ ansible-playbook 3_ios_facts.yml
, all_facts :
192.168.100.1_facts.json
192.168.100.2_facts.json
192.168.100.3_facts.json
all_facts/192.168.100.1_facts.json:
{
"ansible_facts": {
"ansible_net_all_ipv4_addresses": [
"192.168.200.1",
"192.168.100.1",
"10.1.1.1"
],
"ansible_net_all_ipv6_addresses": [],
"ansible_net_config": "Building configuration...\n\nCurrent configuration :
...
519
ios_facts
, ,
,
. , .
playbook, Ansible
,
, ,
changed. , playbook , -
.
playbook ( ):
$ ansible-playbook 3_ios_facts.yml
--diff
Ansible , ,
. ,
.
playbook --diff
:
520
ios_facts
, , ,
.
521
ios_config
ios_config
ios_config - IOS, ,
.
after -
before -
backup - ,
.
backup, playbook
config - , ,
. ,
.
defaults - ,
, . ,
sh run all.
sh run
lines (commands) - , .
,
.
match -
parents - , .
, .
, ,
replace -
save - .
src - ,
. lines ( ,
lines src). ios_template,
.
522
ios_config
lines (commands)
ios_config -
lines.
playbook 1_ios_config_lines.yml:
---
tasks:
cli, group_vars/all.yml.
playbook:
$ ansible-playbook 1_ios_config_lines.yml
Ansible :
523
ios_config
terminal length 0
enable
show running-config - .
, . ,
, :
configure terminal
service password-encryption
end
, ,
. , playbook,
:
$ ansible-playbook 1_ios_config_lines.yml
, .
, , , IOS .
, ,
. ,
.
lines (playbook
1_ios_config_mult_lines.yml):
524
ios_config
---
tasks:
$ ansible-playbook 1_ios_config_mult_lines.yml
525
ios_config
parents
parents ,
.
, :
line vty 0 4
login local
transport input ssh
, playbook 2_ios_config_parents_basic.yml :
---
tasks:
playbook:
$ ansible-playbook 2_ios_config_parents_basic.yml
526
ios_config
,
parents.
, :
policy-map OUT_QOS
class class-default
shape average 100000000 1000000
playbook 2_ios_config_parents_mult.yml :
---
tasks:
527
ios_config
, ios_config.
Playbook 2_ios_config_parents_basic.yml:
---
tasks:
, playbook - , .
, playbook. , 192.168.100.1,
transport input ssh, transport input all.
, playbook verbose:
$ ansible-playbook 2_ios_config_parents_basic.yml -v
528
ios_config
, updates , Ansible
. 192.168.100.1.
, login local , .
updates , .
verbose, . , ,
,
.
---
tasks:
529
ios_config
playbook:
cfg.
debug updates.
updates ,
, when,
.
when: cfg.changed when: cfg.changed == true
$ ansible-playbook 3_ios_config_debug.yml
192.168.100.1 (
transport input ssh transport input all):
$ ansible-playbook 3_ios_config_debug.yml
530
ios_config
,
.
531
ios_config
save
save
. , - no.
no ( false)
yes ( true)
, ( ansible 2.2),
, copy running-config startup-
config, , , . - ,
playbook save yes, :
$ ansible-playbook 4_ios_config_save.yml
, , ios_command.
Playbook 4_ios_config_save.yml:
532
ios_config
---
tasks:
192.168.100.1. ,
transport input all transport input ssh.
playbook:
$ ansible-playbook 4_ios_config_save.yml
533
ios_config
534
ios_config
backup
backup
. backup,
playbook ( ,
).
Playbook 5_ios_config_backup.yml:
---
tasks:
, , playbook (
), backup
:
$ ansible-playbook 5_ios_config_backup.yml -v
535
ios_config
backup ( playbook
):
192.168.100.1_config.2016-12-10@10:42:34
192.168.100.2_config.2016-12-10@10:42:34
192.168.100.3_config.2016-12-10@10:42:34
536
ios_config
defaults
defaults ,
. ,
sh run all.
sh run.
, ,
. , , ,
.
defaults, ,
, playbook, .
, Ansible
. , .
, playbook, (
):
---
tasks:
defaults: yes , ,
ip mtu 1500 (playbook 6_ios_config_defaults.yml):
537
ios_config
---
tasks:
playbook:
$ ansible-playbook 6_ios_config_defaults.yml
538
ios_config
after
after lines (
commands).
, after:
.
,
.
after , ,
.
, no shutdown . ,
lines, ,
playbook.
, no shutdown after,
, ( lines).
---
tasks:
playbook, :
$ ansible-playbook 7_ios_config_after.yml -v
539
ios_config
playbook ( , no shutdown
):
$ ansible-playbook 7_ios_config_after.yml -v
after.
after (playbook
7_ios_config_after_save.yml):
540
ios_config
---
tasks:
playbook ( 192.168.100.1):
$ ansible-playbook 7_ios_config_after_save.yml -v
541
ios_config
before
before lines.
, before:
.
,
.
before , -
lines.
, after, before ,
. , -, lines.
Playbook 8_ios_config_before.yml:
---
tasks:
ACL ,
lines.
playbook :
542
ios_config
$ ansible-playbook 8_ios_config_before.yml -v
playbook ( before ):
$ ansible-playbook 8_ios_config_before.yml -v
543
ios_config
match
match (
):
line - .
strict - ,
exact -
none -
match: line
match: line .
, , lines
. , .
192.168.100.1 ACL:
544
ios_config
---
tasks:
playbook:
$ ansible-playbook 9_ios_config_match_line.yml -v
, updates ACL.
lines , ,
.
545
ios_config
, . , , ,
, .
playbook, ,
, .
match: exact
, .
ACL :
Playbook 9_ios_config_match_exact.yml ( ):
---
tasks:
playbook, :
$ ansible-playbook 9_ios_config_match_exact.yml -v
546
ios_config
ACL :
, , .
---
tasks:
547
ios_config
playbook ,
, .
ACL:
$ ansible-playbook 9_ios_config_match_exact.yml -v
, , :
ACL :
ACL (
match: line),
, permit icmp any any
, playbook ACL ,
lines, , ACL .
, , match: exact :
548
ios_config
---
tasks:
playbook 9_ios_config_match_exact.yml
( ACL ):
$ ansible-playbook 9_ios_config_match_exact.yml -v
549
ios_config
, ACL , lines
.
, match: exact ,
.
playbook ACL:
---
tasks:
ACL :
550
ios_config
, 4 , , , .
, , . match: exact - .
, playbook
lines, ACL:
$ ansible-playbook 9_ios_config_match_exact.yml -v
, match:exact , , -
, , (
). , ,
playbook.
match: strict
match: strict , ,
, , lines, .
parents, lines
parents.
ACL:
551
ios_config
Playbook 9_ios_config_match_strict.yml:
---
tasks:
playbook:
$ ansible-playbook 9_ios_config_match_strict.yml -v
, ACL .
552
ios_config
, match: exact ,
ACL lines.
match: none
match: none :
playbook, , .
playbook 9_ios_config_match_none.yml:
---
tasks:
playbook :
$ ansible-playbook 9_ios_config_match_none.yml -v
553
ios_config
match: none , ,
, .
554
ios_config
replace
replace :
line - ,
.
block - ,
replace: line
replace: line - . ,
, .
, ACL:
playbook 10_ios_config_replace_line.yml:
---
tasks:
555
ios_config
playbook:
$ ansible-playbook 10_ios_config_replace_line.yml -v
ACL:
, ACL (
match: line), , deny ip any any
. , ACL , lines,
, ACL .
replace: block .
replace: block
replace: block lines ( parents),
.
ACL :
Playbook 10_ios_config_replace_block.yml:
556
ios_config
---
tasks:
playbook:
$ ansible-playbook 10_ios_config_replace_block.yml -v
ACL:
557
ios_config
558
ios_config
src
src
, .
lines ( , lines
src). ios_template, .
playbook 11_ios_config_src.yml:
---
tasks:
templates/acl_cfg.txt :
ACL, ,
playbook:
$ ansible-playbook 11_ios_config_src.yml -v
559
ios_config
src ,
. , , Ansible .
ACL:
playbook , ,
:
$ ansible-playbook 11_ios_config_src.yml -v
Jinja2
src Jinja2.
( templates/ospf.j2):
560
ios_config
router ospf 1
router-id {{ mgmnt_ip }}
ispf
auto-cost reference-bandwidth 10000
{% for ip in ospf_ints %}
network {{ ip }} 0.0.0.0 area 0
{% endfor %}
OSPF ,
.
host_vars.
host_vars ( ):
host_vars/192.168.100.1:
---
hostname: london_r1
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.1
ospf_ints:
- 192.168.100.1
- 10.0.0.1
- 10.255.1.1
host_vars/192.168.100.2:
---
hostname: london_r2
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.2
ospf_ints:
- 192.168.100.2
- 10.0.0.2
- 10.255.2.2
host_vars/192.168.100.3:
561
ios_config
---
hostname: london_r3
mgmnt_loopback: 100
mgmnt_ip: 10.0.0.3
ospf_ints:
- 192.168.100.3
- 10.0.0.3
- 10.255.3.3
playbook 11_ios_config_src_jinja.yml:
---
tasks:
Ansible host_vars, .
playbook:
$ ansible-playbook 11_ios_config_src_jinja.yml -v
OSPF:
562
ios_config
router ospf 1
router-id 10.0.0.3
ispf
auto-cost reference-bandwidth 10000
network 10.0.0.3 0.0.0.0 area 0
network 10.255.3.3 0.0.0.0 area 0
network 192.168.100.3 0.0.0.0 area 0
playbook , :
$ ansible-playbook 11_ios_config_src_jinja.yml -v
src :
563
ios_config
backup
config
defaults
save ( save Ansible 2.2 )
564
ntc_ansible
ntc-ansible
ntc-ansible - ,
,
TextFSM.
core Ansible, .
Ansible, .
ansible.cfg:
[defaults]
inventory = ./myhosts
remote_user = cisco
ask_pass = True
library = ./library
, ntc-ansible, library:
[~/pyneng_course/chapter15/library]
$ git clone https://github.com/networktocode/ntc-ansible --recursive
Cloning into 'ntc-ansible'...
remote: Counting objects: 2063, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 2063 (delta 1), reused 0 (delta 0), pack-reused 2058
Receiving objects: 100% (2063/2063), 332.15 KiB | 334.00 KiB/s, done.
Resolving deltas: 100% (1157/1157), done.
Checking connectivity... done.
Submodule 'ntc-templates' (https://github.com/networktocode/ntc-templates) registered
for path 'ntc-templates'
Cloning into 'ntc-templates'...
remote: Counting objects: 902, done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 902 (delta 16), reused 0 (delta 0), pack-reused 868
Receiving objects: 100% (902/902), 161.11 KiB | 0 bytes/s, done.
Resolving deltas: 100% (362/362), done.
Checking connectivity... done.
Submodule path 'ntc-templates': checked out '89c57342b47c9990f0708226fb3f268c6b8c1549'
565
ntc_ansible
,
.
Ansible ,
, ntc-ansible,
show
. ntc_show_command.
ntc_show_command
netmiko (netmiko
) , , show
TextFSM ( ).
, index
.
, ntc-ansible
:
playbook 1_ntc_ansible.yml:
566
ntc_ansible
---
tasks:
- debug: var=result
playbook:
$ ansible-playbook 1_ntc-ansible.yml
567
ntc_ansible
response .
,
library/ntc-ansible/ntc-templates/templates/cisco_ios_show_ip_int_brief.template
( - ):
568
ntc_ansible
Start
^${INTF}\s+${IPADDR}\s+\w+\s+\w+\s+${STATUS}\s+${PROTO} -> Record
, ,
debug, :
- debug: var=result.response[0]
, , ,
ios_facts.
playbook 2_ntc_ansible_save.yml :
---
tasks:
569
ntc_ansible
$ ansible-playbook 2_ntc-ansible_save.yml
, all_facts
. all_facts/192.168.100.1_sh_ip_int_br.json:
570
ntc_ansible
[
{
"intf": "Ethernet0/0",
"ipaddr": "192.168.100.1",
"proto": "up",
"status": "up"
},
{
"intf": "Ethernet0/1",
"ipaddr": "192.168.200.1",
"proto": "up",
"status": "up"
},
{
"intf": "Ethernet0/2",
"ipaddr": "unassigned",
"proto": "down",
"status": "administratively down"
},
{
"intf": "Ethernet0/3",
"ipaddr": "unassigned",
"proto": "up",
"status": "up"
},
{
"intf": "Loopback0",
"ipaddr": "10.1.1.1",
"proto": "up",
"status": "up"
}
]
Jinja2
Cisco IOS ntc-ansible :
571
ntc_ansible
cisco_ios_dir.template
cisco_ios_show_access-list.template
cisco_ios_show_aliases.template
cisco_ios_show_archive.template
cisco_ios_show_capability_feature_routing.template
cisco_ios_show_cdp_neighbors_detail.template
cisco_ios_show_cdp_neighbors.template
cisco_ios_show_clock.template
cisco_ios_show_interfaces_status.template
cisco_ios_show_interfaces.template
cisco_ios_show_interface_transceiver.template
cisco_ios_show_inventory.template
cisco_ios_show_ip_arp.template
cisco_ios_show_ip_bgp_summary.template
cisco_ios_show_ip_bgp.template
cisco_ios_show_ip_int_brief.template
cisco_ios_show_ip_ospf_neighbor.template
cisco_ios_show_ip_route.template
cisco_ios_show_lldp_neighbors.template
cisco_ios_show_mac-address-table.template
cisco_ios_show_processes_cpu.template
cisco_ios_show_snmp_community.template
cisco_ios_show_spanning-tree.template
cisco_ios_show_standby_brief.template
cisco_ios_show_version.template
cisco_ios_show_vlan.template
cisco_ios_show_vtp_status.template
, ntc-ansible :
ls -ls library/ntc-ansible/ntc-templates/templates/
TextFSM .
, , ntc-ansible , index
(library/ntc-ansible/ntc-templates/templates/index):
572
ntc_ansible
index TextFSM.
573
Ansible
Ansible
Ansible,
. Ansible, , ,
.
, ,
, playbook.
, , - , .
Ansible , .
Ansible . ,
, , ,
Ansible , Playbook.
- "Ansible ",
, Ansible .
574
zip tar.gz.
: Vagrant
VMware. , .
,
PyNEng slack.
python//
.
(, 5.2a),
, . ,
, /
.
, ,
.
15.1
playbook, :
sh arp
sh_arp_output
sh_arp_output
playbook .
15.1a
playbook, :
sh arp
sh_arp_output
575
, ,
playbook .
15.1b
playbook, :
sh arp sh ip int br
result
playbook .
15.1c
playbook, :
sh arp sh ip int br
result
sh arp
sh ip int br
playbook .
15.2
playbook, :
(
)
playbook .
15.2a
playbook, :
576
all_facts:
: hostname_intf_facts.yaml
hostname - ,
YAML, ,
playbook .
15.2b
playbook, :
sh ipv6 int br
show_result
show_result, ,
, IPv6 ,
playbook .
15.3
playbook task_15_3.yml .
, , . ,
.
playbook , ,
.
15.4
playbook, :
, , ACL
Playbook. , ACL ,
playbook.
577
ACL
ACL
ACL ACL
ACL
ACL :
playbook R1.
15.4a
playbook 15.4, , ACL
.
, playbook, ACL
, playbook, .
, .
, , ACL:
playbook R1.
15.4b
playbook 15.4a :
, ,
,
,
playbook R1.
15.4c
578
playbook 15.4b , ,
, outside_intf.
R1,
host_vars.
playbook R1.
579
subprocess
os
argparse
ipaddress
580
subprocess
os
argparse
ipaddress
581
subprocess
subprocess
subprocess . ,
// .
subprocess, , , Linux
. , , ,
.
subprocess.call()
call() :
, .
ls :
result ( 0 ,
):
, , ,
( ):
582
subprocess
, md:
, ,
shell:
shell=True , shell.
, :
583
subprocess
call() -
. , , ping,
:
, - IP-.
call() , :
call() ,
, .
subprocess_call.py:
import subprocess
if reply == 0:
print "Alive"
else:
print "Unreachable"
584
subprocess
$ python subprocess_call.py
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=48 time=49.930 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=48 time=48.981 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=48 time=48.360 ms
, , .
,
stdout devnull ( subprocess_call_devnull.py):
import subprocess
import os
if reply == 0:
print "Alive"
else:
print "Unreachable"
$ python subprocess_call_devnull.py
Alive
subprocess.check_output()
check_output() :
, .
( 0),
, ,
check_output() ( subprocess_check_output.py):
585
subprocess
import subprocess
print "Result:"
print reply
( print reply ,
):
$ python subprocess_check_output.py
Result:
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=48 time=49.785 ms
64 bytes from 8.8.8.8: icmp_seq=1 ttl=48 time=57.231 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=48 time=51.071 ms
, , ,
0 ( subprocess_check_output_catch_exception.py):
$ python subprocess_check_output_catch_exception.py
ping: cannot resolve a: Unknown host
Traceback (most recent call last):
File "subprocess_check_output_catch_exception.py", line 3, in <module>
reply = subprocess.check_output(['ping', '-c', '3', '-n', 'a'])
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p
ython2.7/subprocess.py", line 573, in check_output
raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['ping', '-c', '3', '-n', 'a']' returned non-z
ero exit status 68
CalledProcessError .
check_output() ,
0.
, try/except,
(
subprocess_check_output_catch_exception.py):
586
subprocess
import subprocess
try:
reply = subprocess.check_output(['ping', '-c', '3', '-n', 'a'])
except subprocess.CalledProcessError as e:
print "Error occurred"
print "Return code:", e.returncode
$ python subprocess_check_output_catch_exception.py
ping: cannot resolve a: Unknown host
Error occurred
Return code: 68
. , , ,
.
import subprocess
from tempfile import TemporaryFile
def ping_ip(ip_address):
"""
Ping IP address and return tuple:
On success:
* return code = 0
* command output
On failure:
* return code
* error output (stderr)
"""
with TemporaryFile() as temp:
try:
output = subprocess.check_output(['ping', '-c', '3', '-n', ip_address],
stderr=temp)
return 0, output
except subprocess.CalledProcessError as e:
temp.seek(0)
return e.returncode, temp.read()
print ping_ip('8.8.8.8')
print ping_ip('a')
587
subprocess
$ python subprocess_ping_function.py
(0, 'PING 8.8.8.8 (8.8.8.8): 56 data bytes\n64 bytes from 8.8.8.8: icmp_seq=0 ttl=48 t
ime=46.106 ms\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=48 time=46.114 ms\n64 bytes from
8.8.8.8: icmp_seq=2 ttl=48 time=47.390 ms\n\n--- 8.8.8.8 ping statistics ---\n3 packet
s transmitted, 3 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 4
6.106/46.537/47.390/0.603 ms\n')
stackoverflow
tempfile Python ,
. TemporaryFile
, , .
tempfile PyMOTW.
, , IP-
, , :
.
IP-, , ,
multiprocessing, .
subprocess.
PyMOTW
588
os
os
os , ,
.
.
,
PyMOTW.
os :
In [1]: import os
In [2]: os.mkdir('test')
In [3]: ls -ls
total 0
0 drwxr-xr-x 2 nata nata 68 Jan 23 18:58 test/
, . ,
, :
In [4]: os.mkdir('test')
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-4-cbf3b897c095> in <module>()
----> 1 os.mkdir('test')
, os.path.exists :
In [5]: os.path.exists('test')
Out[5]: True
listdir, :
In [7]: os.listdir('.')
Out[7]: ['cover3.png', 'dir2', 'dir3', 'README.txt', 'test']
589
os
os.path.isdir os.path.isfile ,
:
In [9]: dirs
Out[9]: ['dir2', 'dir3', 'test']
In [11]: files
Out[11]: ['cover3.png', 'README.txt']
In [12]: os.path.basename(file)
Out[12]: 'README.md'
In [13]: os.path.dirname(file)
Out[13]: 'Programming/PyNEng/book/16_additional_info'
In [14]: os.path.split(file)
Out[14]: ('Programming/PyNEng/book/16_additional_info', 'README.md')
590
argparse
argparse
argparse - .
, :
,
,
,
argparse .
, .
argparse. ,
,
, Python. , click.
,
( argparse, click docopt).
ping_function.py:
591
argparse
import subprocess
from tempfile import TemporaryFile
import argparse
args = parser.parse_args()
print args
, -a , ip
parser.add_argument('-c', action="store", dest="count", default=2, type=int)
, -c ,
count , , , .
, , 2
args = parser.parse_args() ,
.
592
argparse
, args ,
. , args.ip .
Namespace , parse_args()
IP-:
593
argparse
$ python ping_function.py
Namespace(count=2, ip=None)
Traceback (most recent call last):
File "ping_function.py", line 31, in <module>
rc, message = ping_ip( args.ip, args.count )
File "ping_function.py", line 16, in ping_ip
stderr=temp)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p
ython2.7/subprocess.py", line 566, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p
ython2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/p
ython2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
TypeError: execv() arg 2 must contain only strings
, argparse,
, .
, - argparse, , None .
Namespace(count=2, ip=None) .
, , IP- . argparse
, .
-a : required=True :
, , :
$ python ping_function.py
usage: ping_function.py [-h] -a IP [-c COUNT]
ping_function.py: error: argument -a is required
, .
usage.
, argparse, help:
594
argparse
$ python ping_function.py -h
usage: ping_function.py [-h] -a IP [-c COUNT]
Ping script
optional arguments:
-h, --help show this help message and exit
-a IP
-c COUNT
, , optional
arguments . argparse , , -
IP-, .
ping_function_ver2.py:
595
argparse
import subprocess
from tempfile import TemporaryFile
import argparse
args = parser.parse_args()
print args
, -a , IP-.
host .
.
, required=True dest="ip" .
, , , help.
596
argparse
help :
$ python ping_function_ver2.py -h
usage: ping_function_ver2.py [-h] [-c COUNT] host
Ping script
positional arguments:
host IP or name to ping
optional arguments:
-h, --help show this help message and exit
-c COUNT Number of packets
argparse,
, , argparse,
PyMOTW.
parse_dhcp_snooping.py:
# Default values:
DFLT_DB_NAME = 'dhcp_snooping.db'
DFLT_DB_SCHEMA = 'dhcp_snooping_schema.sql'
def create(args):
print "Creating DB %s with DB schema %s" % (args.name, args.schema)
def add(args):
if args.sw_true:
597
argparse
def get(args):
if args.key and args.value:
print "Geting data from DB: %s" % args.db_file
print "Request data for host(s) with %s %s" % (args.key, args.value)
elif args.key or args.value:
print "Please give two or zero args\n"
else:
print "Showing %s content..." % args.db_file
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(title='subcommands',
description='valid subcommands',
help='description')
if __name__ == '__main__':
args = parser.parse_args()
args.func(args)
598
argparse
, , .
. , ,
.
, . ,
,
.
, , create_db
-n :
, :
add_argument . ,
.
``create_parser.set_defaults( func=create ) , ,
create_parser```, create.
create , , . ,
, :
def create(args):
print "Creating DB %s with DB schema %s" % (args.name, args.schema)
help , :
599
argparse
$ python parse_dhcp_snooping.py -h
usage: parse_dhcp_snooping.py [-h] {create_db,add,get} ...
optional arguments:
-h, --help show this help message and exit
subcommands:
valid subcommands
{create_db,add,get} description
create_db create new db
add add data to db
get get data from db
, , ,
usage:
help:
optional arguments:
-h, --help show this help message and exit
-n db-filename db filename
-s SCHEMA db schema filename
,
argparse.
metavar
create_parser - metavar :
metavar usage
help:
600
argparse
optional arguments:
-h, --help show this help message and exit
-n db-filename db filename
-s SCHEMA db schema filename
-n -s :
-n , usage, help, ,
metavar
-s ,
nargs
add_parser nargs :
nargs ,
. , ,
, filename , nargs.
.
help, , :
positional arguments:
filename file(s) to add to db
optional arguments:
-h, --help show this help message and exit
--db DB_FILE db name
-s add switch data if set, else add normal data
, . , add,
, :
601
argparse
nargs :
N - .
(, 1)
? - 0 1
* -
+ - , , ,
choices
get_parser choices :
get_parser.add_argument('-k', dest="key",
choices=['mac', 'ip', 'vlan', 'interface', 'switch'],
help='host key (parameter) to search')
, ,
. , choices .
, help :
optional arguments:
-h, --help show this help message and exit
--db DB_FILE db name
-k {mac,ip,vlan,interface,switch}
host key (parameter) to search
-v VALUE value of key
-a show db content
, :
602
argparse
, ,
, SQL-. , choices ,
- , .
parse_dhcp_snooping.py,
, .
if __name__ == '__main__':
args = parser.parse_args()
args.func(args)
, , .
( call_pds.py):
args = parser.parse_args()
args.func(args)
help:
$ python call_pds.py -h
usage: call_pds.py [-h] {create_db,add,get} ...
optional arguments:
-h, --help show this help message and exit
subcommands:
valid subcommands
{create_db,add,get} description
create_db create new db
add add data to db
get get data from db
603
argparse
, argparse - .
, parse_args() (
call_pds2.py):
split(), parse_args ,
.
, :
$ python call_pds2.py
Reading info from file(s)
test.txt, test2.txt
604
ipaddress
ipaddress
ipaddress IP-.
Python, :
ipaddress, , , IP-
, unicode.
, unicode ( ):
ipaddress.ip_address(u'1.2.3.4')
ipaddress.ip_address(unicode('1.2.3.4'))
unicode_literals :
unicode_literals Python2
, unicode.
, ipaddress Python3.
unicode.
ipaddress.ip_address()
ipaddress.ip_address() IPv4Address
IPv6Address, .
IPv4 :
605
ipaddress
In [3]: ipv4
Out[3]: IPv4Address(u'10.0.1.1')
In [5]: ipv4.
ipv4.compressed ipv4.is_loopback ipv4.is_unspecified ipv4.version
ipv4.exploded ipv4.is_multicast ipv4.max_prefixlen
ipv4.is_global ipv4.is_private ipv4.packed
ipv4.is_link_local ipv4.is_reserved ipv4.reverse_pointer
is_ :
In [6]: ipv4.is_loopback
Out[6]: False
In [7]: ipv4.is_multicast
Out[7]: False
In [8]: ipv4.is_reserved
Out[8]: False
In [9]: ipv4.is_private
Out[9]: True
, :
606
ipaddress
In [16]: str(ip1)
Out[16]: '10.0.1.1'
In [17]: int(ip1)
Out[17]: 167772417
In [18]: ip1 + 5
Out[18]: IPv4Address(u'10.0.1.6')
In [19]: ip1 - 5
Out[19]: IPv4Address(u'10.0.0.252')
ipaddress.ip_network()
ipaddress.ip_network() ,
(IPv4 IPv6).
IPv4:
, :
607
ipaddress
In [21]: subnet1.broadcast_address
Out[21]: IPv4Address(u'80.0.1.15')
In [22]: subnet1.with_netmask
Out[22]: u'80.0.1.0/255.255.255.240'
In [23]: subnet1.with_hostmask
Out[23]: u'80.0.1.0/0.0.0.15'
In [24]: subnet1.prefixlen
Out[24]: 28
In [25]: subnet1.num_addresses
Out[25]: 16
hosts() , , ,
list:
In [26]: list(subnet1.hosts())
Out[26]:
[IPv4Address(u'80.0.1.1'),
IPv4Address(u'80.0.1.2'),
IPv4Address(u'80.0.1.3'),
IPv4Address(u'80.0.1.4'),
IPv4Address(u'80.0.1.5'),
IPv4Address(u'80.0.1.6'),
IPv4Address(u'80.0.1.7'),
IPv4Address(u'80.0.1.8'),
IPv4Address(u'80.0.1.9'),
IPv4Address(u'80.0.1.10'),
IPv4Address(u'80.0.1.11'),
IPv4Address(u'80.0.1.12'),
IPv4Address(u'80.0.1.13'),
IPv4Address(u'80.0.1.14')]
subnets . ,
:
In [27]: list(subnet1.subnets())
Out[27]: [IPv4Network(u'80.0.1.0/29'), IPv4Network(u'80.0.1.8/29')]
, prefixlen_diff,
:
608
ipaddress
In [28]: list(subnet1.subnets(prefixlen_diff=2))
Out[28]:
[IPv4Network(u'80.0.1.0/30'),
IPv4Network(u'80.0.1.4/30'),
IPv4Network(u'80.0.1.8/30'),
IPv4Network(u'80.0.1.12/30')]
, new_prefix,
:
In [29]: list(subnet1.subnets(new_prefix=30))
Out[29]:
[IPv4Network(u'80.0.1.0/30'),
IPv4Network(u'80.0.1.4/30'),
IPv4Network(u'80.0.1.8/30'),
IPv4Network(u'80.0.1.12/30')]
In [30]: list(subnet1.subnets(new_prefix=29))
Out[30]: [IPv4Network(u'80.0.1.0/29'), IPv4Network(u'80.0.1.8/29')]
IP- :
609
ipaddress
In [32]: subnet1[0]
Out[32]: IPv4Address(u'80.0.1.0')
In [33]: subnet1[5]
Out[33]: IPv4Address(u'80.0.1.5')
IP- :
ipaddress.ip_interface()
ipaddress.ip_interface() IPv4Interface
IPv6Interface, .
IPv4Interface, ,
:
In [37]: int1.ip
Out[37]: IPv4Address(u'10.0.1.1')
In [38]: int1.network
Out[38]: IPv4Network(u'10.0.1.0/24')
In [39]: int1.netmask
Out[39]: IPv4Address(u'255.255.255.0')
, ,
, :
610
ipaddress
In [43]: check_if_ip_is_network(IP1)
Out[43]: False
In [44]: check_if_ip_is_network(IP2)
Out[44]: True
611
format
sorted
lambda
zip
map
filter
all, any
612
sorted
sorted
sorted() - ,
, .
,
.
- sorted .
, , :
In [2]: sorted(list_of_words)
Out[2]: ['', 'dict', 'list', 'one', 'two']
In [4]: sorted(tuple_of_words)
Out[4]: ['', 'dict', 'list', 'one', 'two']
In [6]: sorted(set_of_words)
Out[6]: ['', 'dict', 'list', 'one', 'two']
In [8]: sorted(string_to_sort)
Out[8]: [' ', 'g', 'g', 'i', 'l', 'n', 'n', 'o', 'r', 's', 't']
sorted , :
613
sorted
In [9]: dict_for_sort = {
...: 'id': 1,
...: 'name':'London',
...: 'IT_VLAN':320,
...: 'User_VLAN':1010,
...: 'Mngmt_VLAN':99,
...: 'to_name': None,
...: 'to_id': None,
...: 'port':'G1/0/11'
...: }
In [10]: sorted(dict_for_sort)
Out[10]:
['IT_VLAN',
'Mngmt_VLAN',
'User_VLAN',
'id',
'name',
'port',
'to_id',
'to_name']
reverse
reverse .
.
reverse, :
In [12]: sorted(list_of_words)
Out[12]: ['', 'dict', 'list', 'one', 'two']
key
key .
key ,
.
, :
614
sorted
, :
In [16]: dict_for_sort = {
...: 'id': 1,
...: 'name':'London',
...: 'IT_VLAN':320,
...: 'User_VLAN':1010,
...: 'Mngmt_VLAN':99,
...: 'to_name': None,
...: 'to_id': None,
...: 'port':'G1/0/11'
...: }
, .
lambda.
, key,
, . lambda
operator.
,
, :
615
sorted
616
lambda
lambda
Python lambda - ,
.
lambda:
In [2]: sum_arg(1,2)
Out[2]: 3
lanbda:
In [4]: sum_arg(1,2)
Out[4]: 3
, lambda return,
,
.
lambda ,
.
, sorted lambda
:
617
lambda
618
zip
zip
zip():
zip() , n- n-
,
,
,
zip:
In [1]: a = [1,2,3]
In [2]: b = [100,200,300]
In [3]: zip(a,b)
Out[3]: [(1, 100), (2, 200), (3, 300)]
zip() :
In [4]: a = [1,2,3,4,5]
In [5]: b = [10,20,30,40,50]
In [6]: c = [100,200,300]
In [7]: zip(a,b,c)
Out[7]: [(1, 10, 100), (2, 20, 200), (3, 30, 300)]
zip :
619
zip
In [9]: zip(d_keys,d_values)
Out[9]:
[('hostname', 'london_r1'),
('location', '21 New Globe Walk'),
('vendor', 'Cisco'),
('model', '4451'),
('IOS', '15.4'),
('IP', '10.255.0.1')]
In [10]: dict(zip(d_keys,d_values))
Out[10]:
{'IOS': '15.4',
'IP': '10.255.0.1',
'hostname': 'london_r1',
'location': '21 New Globe Walk',
'model': '4451',
'vendor': 'Cisco'}
In [11]: r1 = dict(zip(d_keys,d_values))
620
map
map
map
.
, map .
:
map lambda:
, map(), ,
:
621
filter
filter
filter() ,
, True.
, , :
In [1]: list_of_strings = ['one', 'two', 'list', '', 'dict', '100', '1', '50']
, :
, :
In [4]: filter(lambda x: not x%2, [10, 111, 102, 213, 314, 515])
Out[4]: [10, 102, 314]
, :
622
any all
all
all() True, ( ).
In [3]: all([])
Out[3]: True
, all IP-
:
In [4]: IP = '10.0.1.1'
any
any() True, (
).
In [9]: any([])
Out[9]: False
623
any all
624
, . ,
.
, ,
, , . , , - ,
.
Python,
. , (,
) , . ,
.
Python
Packet Pushers Show 176 Intro To Python & Automation For Network Engineers
Packet Pushers Show 198 Kirk Byers On Network Automation With Python & Ansible
Packet Pushers Show 270: Design & Build 9: Automation With Python And Netmiko
PQ Show 99: Netmiko & NAPALM For Network Automation
Network automation tools with Jason Edelman on Sofware Gone Wild
(python + network)
Kirk Byers
Jason Edelman
Matt Oswalt
Michael Kashin
Henry lsner
Mat Wood
(python +
network)
625
, ,
, ,
.
626
.
, . , ,
.
Python
Python:
A Byte of Python
Python 101
Learn Python the Hard Way
Python:
Python
regex101
SQLite:
SQLite tutorial
Telnet, SSH
:
627
Netmiko Library
Automate SSH connections with netmiko
Network Automation Using Python: BGP Configuration
Jinja2
:
TextFSM
:
, TextFSM:
ntc-ansible
TextFSM ( ntc-ansible):
ntc-templates
Ansible
Ansible :
http://docs.ansible.com/ansible/
628
Ansible:
Ansible
, :
https://sysadmincasts.com/episodes/43-19-minutes-with-ansible-part-1-4
Ansible:
https://github.com/ansible/ansible-examples
Playbook
https://github.com/ansible/ansible-examples/tree/master/language_features
https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template.html
https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p2.html
https://pynet.twb-tech.com/blog/ansible/ansible-cfg-template-p3.html
http://jedelman.com/home/ansible-for-networking/
http://jedelman.com/home/network-automation-with-ansible-dynamically-configuring-
interface-descriptions/
http://www.packetgeek.net/2015/08/using-ansible-to-push-cisco-ios-configurations/
. :
http://networkop.github.io/blog/2015/06/24/ansible-intro/
http://networkop.github.io/blog/2015/07/03/parser-modules/
http://networkop.github.io/blog/2015/07/10/test-verification/
http://networkop.github.io/blog/2015/07/17/tdd-quickstart/
http://networkop.github.io/blog/2015/08/14/automating-legacy-networks/
http://networkop.github.io/blog/2015/08/26/automating-network-build-p1/
629
http://networkop.github.io/blog/2015/09/03/automating-bgp-config/
http://networkop.github.io/blog/2015/11/13/automating-flexvpn-config/
, :
re
YAML
CSV
JSON
sqlite3
Telnetlib
Pexpect
Paramiko
Netmiko
threading
multiprocessing
Jinja2
TextFSM
Ansible
630
Python
Python ,
.
CodeEval
HackerRank
Python + network
.
, . ,
, ,
.
,
. , , Python ,
, API,
. , .
Scapy
CiscoConfParse
631
NAPALM
NOC Project
Requests
NetworkX
Twisted
AutoNetKit
632
xgu.ru .
xgu.ru GitBook.
xgu.ru
Python ,
,
, .
xgu.ru, .
"DevOps". ,
,
.
Delphi , ,
.
"" , .
.
.
.
.
.
python.
, ,
. ,
, -
.
,
. .
633
- . ,
, (
:) ), ,
. python
, -
.
, .
634