]> git.proxmox.com Git - mirror_frr.git/blame - doc/developer/topotests-snippets.rst
doc: fix typo RFC7572 to RFC7752
[mirror_frr.git] / doc / developer / topotests-snippets.rst
CommitLineData
370c8e07
QY
1.. _topotests-snippets:
2
3Snippets
4--------
5
6This document will describe common snippets of code that are frequently needed
7to perform some test checks.
8
9Checking for router / test failures
10^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11
12The following check uses the topogen API to check for software failure (e.g.
13zebra died) and/or for errors manually set by ``Topogen.set_error()``.
14
15.. code:: py
16
17 # Get the topology reference
18 tgen = get_topogen()
19
20 # Check for errors in the topology
21 if tgen.routers_have_failure():
22 # Skip the test with the topology errors as reason
23 pytest.skip(tgen.errors)
24
25Checking FRR routers version
26^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27
28This code snippet is usually run after the topology setup to make sure all
29routers instantiated in the topology have the correct software version.
30
31.. code:: py
32
33 # Get the topology reference
34 tgen = get_topogen()
35
36 # Get the router list
37 router_list = tgen.routers()
38
39 # Run the check for all routers
40 for router in router_list.values():
41 if router.has_version('<', '3'):
42 # Set topology error, so the next tests are skipped
43 tgen.set_error('unsupported version')
44
45A sample of this snippet in a test can be found `here
46<ldp-vpls-topo1/test_ldp_vpls_topo1.py>`__.
47
48Interacting with equipment
49^^^^^^^^^^^^^^^^^^^^^^^^^^
50
56f0bea7 51You might want to interact with the topology equipment during the tests and
370c8e07
QY
52there are different ways to do so.
53
54Notes:
55
56f0bea7 561. When using the Topogen API, all the equipment code derives from ``Topogear``
370c8e07 57 (`lib/topogen.py <lib/topogen.py>`__). If you feel brave you can look by
56f0bea7 58 yourself how the abstractions that will be mentioned here work.
370c8e07
QY
59
602. When not using the ``Topogen`` API there is only one way to interact with
56f0bea7 61 the equipment, which is by calling the ``mininet`` API functions directly
370c8e07
QY
62 to spawn commands.
63
64Interacting with the Linux sandbox
65""""""""""""""""""""""""""""""""""
66
67Without ``Topogen``:
68
69.. code:: py
70
71 global net
72 output = net['r1'].cmd('echo "foobar"')
73 print 'output is: {}'.format(output)
74
75With ``Topogen``:
76
77.. code:: py
78
79 tgen = get_topogen()
80 output = tgen.gears['r1'].run('echo "foobar"')
81 print 'output is: {}'.format(output)
82
83Interacting with VTYSH
84""""""""""""""""""""""
85
86Without ``Topogen``:
87
88.. code:: py
89
90 global net
91 output = net['r1'].cmd('vtysh "show ip route" 2>/dev/null')
92 print 'output is: {}'.format(output)
93
94With ``Topogen``:
95
96.. code:: py
97
98 tgen = get_topogen()
99 output = tgen.gears['r1'].vtysh_cmd("show ip route")
100 print 'output is: {}'.format(output)
101
102``Topogen`` also supports sending multiple lines of command:
103
104.. code:: py
105
106 tgen = get_topogen()
107 output = tgen.gears['r1'].vtysh_cmd("""
108 configure terminal
109 router bgp 10
110 bgp router-id 10.0.255.1
111 neighbor 1.2.3.4 remote-as 10
112 !
113 router bgp 11
114 bgp router-id 10.0.255.2
115 !
116 """)
117 print 'output is: {}'.format(output)
118
119You might also want to run multiple commands and get only the commands that
120failed:
121
122.. code:: py
123
124 tgen = get_topogen()
125 output = tgen.gears['r1'].vtysh_multicmd("""
126 configure terminal
127 router bgp 10
128 bgp router-id 10.0.255.1
129 neighbor 1.2.3.4 remote-as 10
130 !
131 router bgp 11
132 bgp router-id 10.0.255.2
133 !
134 """, pretty_output=false)
135 print 'output is: {}'.format(output)
136
137Translating vtysh JSON output into Python structures:
138
139.. code:: py
140
141 tgen = get_topogen()
142 json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
143 output = json.dumps(json_output, indent=4)
144 print 'output is: {}'.format(output)
145
146 # You can also access the data structure as normal. For example:
147 # protocol = json_output['1.1.1.1/32']['protocol']
148 # assert protocol == "ospf", "wrong protocol"
149
150.. note::
151
56f0bea7 152 ``vtysh_(multi)cmd`` is only available for router types of equipment.
370c8e07
QY
153
154Invoking mininet CLI
155^^^^^^^^^^^^^^^^^^^^
156
157Without ``Topogen``:
158
159.. code:: py
160
161 CLI(net)
162
163With ``Topogen``:
164
165.. code:: py
166
167 tgen = get_topogen()
168 tgen.mininet_cli()
169
170Reading files
171^^^^^^^^^^^^^
172
173Loading a normal text file content in the current directory:
174
175.. code:: py
176
177 # If you are using Topogen
178 # CURDIR = CWD
179 #
180 # Otherwise find the directory manually:
181 CURDIR = os.path.dirname(os.path.realpath(__file__))
182
183 file_name = '{}/r1/show_ip_route.txt'.format(CURDIR)
184 file_content = open(file_name).read()
185
186Loading JSON from a file:
187
188.. code:: py
189
190 import json
191
192 file_name = '{}/r1/show_ip_route.json'.format(CURDIR)
193 file_content = json.loads(open(file_name).read())
194
195Comparing JSON output
196^^^^^^^^^^^^^^^^^^^^^
197
56f0bea7 198After obtaining JSON output formatted with Python data structures, you may use
370c8e07
QY
199it to assert a minimalist schema:
200
201.. code:: py
202
203 tgen = get_topogen()
204 json_output = tgen.gears['r1'].vtysh_cmd("show ip route json", isjson=True)
205
206 expect = {
207 '1.1.1.1/32': {
208 'protocol': 'ospf'
209 }
210 }
211
212 assertmsg = "route 1.1.1.1/32 was not learned through OSPF"
213 assert json_cmp(json_output, expect) is None, assertmsg
214
215``json_cmp`` function description (it might be outdated, you can find the
216latest description in the source code at
217:file:`tests/topotests/lib/topotest.py`
218
219.. code:: text
220
221 JSON compare function. Receives two parameters:
222 * `d1`: json value
223 * `d2`: json subset which we expect
224
225 Returns `None` when all keys that `d1` has matches `d2`,
226 otherwise a string containing what failed.
227
228 Note: key absence can be tested by adding a key with value `None`.
229
230Pausing execution
231^^^^^^^^^^^^^^^^^
232
233Preferably, choose the ``sleep`` function that ``topotest`` provides, as it
234prints a notice during the test execution to help debug topology test execution
235time.
236
237.. code:: py
238
239 # Using the topotest sleep
240 from lib import topotest
241
242 topotest.sleep(10, 'waiting 10 seconds for bla')
243 # or just tell it the time:
244 # topotest.sleep(10)
245 # It will print 'Sleeping for 10 seconds'.
246
247 # Or you can also use the Python sleep, but it won't show anything
248 from time import sleep
249 sleep(5)
250
251iproute2 Linux commands as JSON
252^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
253
254``topotest`` has two helpers implemented that parses the output of ``ip route``
255commands to JSON. It might simplify your comparison needs by only needing to
256provide a Python dictionary.
257
258.. code:: py
259
260 from lib import topotest
261
262 tgen = get_topogen()
263 routes = topotest.ip4_route(tgen.gears['r1'])
264 expected = {
265 '10.0.1.0/24': {},
266 '10.0.2.0/24': {
267 'dev': 'r1-eth0'
268 }
269 }
270
271 assertmsg = "failed to find 10.0.1.0/24 and/or 10.0.2.0/24"
272 assert json_cmp(routes, expected) is None, assertmsg