]> git.proxmox.com Git - mirror_frr.git/blob - doc/developer/topotests-snippets.rst
pimd, doc: remove dead import check references
[mirror_frr.git] / doc / developer / topotests-snippets.rst
1 .. _topotests-snippets:
2
3 Snippets
4 --------
5
6 This document will describe common snippets of code that are frequently needed
7 to perform some test checks.
8
9 Checking for router / test failures
10 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11
12 The following check uses the topogen API to check for software failure (e.g.
13 zebra 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
25 Checking FRR routers version
26 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27
28 This code snippet is usually run after the topology setup to make sure all
29 routers 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
45 A sample of this snippet in a test can be found `here
46 <ldp-vpls-topo1/test_ldp_vpls_topo1.py>`__.
47
48 Interacting with equipment
49 ^^^^^^^^^^^^^^^^^^^^^^^^^^
50
51 You might want to interact with the topology equipment during the tests and
52 there are different ways to do so.
53
54 Notes:
55
56 1. When using the Topogen API, all the equipment code derives from ``Topogear``
57 (`lib/topogen.py <lib/topogen.py>`__). If you feel brave you can look by
58 yourself how the abstractions that will be mentioned here work.
59
60 2. When not using the ``Topogen`` API there is only one way to interact with
61 the equipment, which is by calling the ``mininet`` API functions directly
62 to spawn commands.
63
64 Interacting with the Linux sandbox
65 """"""""""""""""""""""""""""""""""
66
67 Without ``Topogen``:
68
69 .. code:: py
70
71 global net
72 output = net['r1'].cmd('echo "foobar"')
73 print 'output is: {}'.format(output)
74
75 With ``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
83 Interacting with VTYSH
84 """"""""""""""""""""""
85
86 Without ``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
94 With ``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
119 You might also want to run multiple commands and get only the commands that
120 failed:
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
137 Translating 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
152 ``vtysh_(multi)cmd`` is only available for router types of equipment.
153
154 Invoking mininet CLI
155 ^^^^^^^^^^^^^^^^^^^^
156
157 Without ``Topogen``:
158
159 .. code:: py
160
161 CLI(net)
162
163 With ``Topogen``:
164
165 .. code:: py
166
167 tgen = get_topogen()
168 tgen.mininet_cli()
169
170 Reading files
171 ^^^^^^^^^^^^^
172
173 Loading 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
186 Loading 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
195 Comparing JSON output
196 ^^^^^^^^^^^^^^^^^^^^^
197
198 After obtaining JSON output formatted with Python data structures, you may use
199 it 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
216 latest 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
230 Pausing execution
231 ^^^^^^^^^^^^^^^^^
232
233 Preferably, choose the ``sleep`` function that ``topotest`` provides, as it
234 prints a notice during the test execution to help debug topology test execution
235 time.
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
251 iproute2 Linux commands as JSON
252 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
253
254 ``topotest`` has two helpers implemented that parses the output of ``ip route``
255 commands to JSON. It might simplify your comparison needs by only needing to
256 provide 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