]>
Commit | Line | Data |
---|---|---|
4501fbca MW |
1 | #!/usr/bin/env python |
2 | ||
3 | # | |
4 | # test_all_protocol_startup.py | |
5 | # Part of NetDEF Topology Tests | |
6 | # | |
7 | # Copyright (c) 2017 by | |
8 | # Network Device Education Foundation, Inc. ("NetDEF") | |
9 | # | |
10 | # Permission to use, copy, modify, and/or distribute this software | |
11 | # for any purpose with or without fee is hereby granted, provided | |
12 | # that the above copyright notice and this permission notice appear | |
13 | # in all copies. | |
14 | # | |
15 | # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES | |
16 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
17 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR | |
18 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY | |
19 | # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
20 | # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | |
21 | # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |
22 | # OF THIS SOFTWARE. | |
23 | # | |
24 | ||
25 | """ | |
26 | test_all_protocol_startup.py: Test of all protocols at same time | |
27 | ||
28 | """ | |
29 | ||
30 | import os | |
31 | import re | |
32 | import sys | |
4501fbca MW |
33 | import pytest |
34 | from time import sleep | |
35 | ||
36 | from mininet.topo import Topo | |
37 | from mininet.net import Mininet | |
38 | from mininet.node import Node, OVSSwitch, Host | |
39 | from mininet.log import setLogLevel, info | |
40 | from mininet.cli import CLI | |
41 | from mininet.link import Intf | |
42 | ||
43 | from functools import partial | |
44 | ||
45 | sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
46 | from lib import topotest | |
47 | ||
48 | fatal_error = "" | |
49 | ||
50 | ||
51 | ##################################################### | |
52 | ## | |
53 | ## Network Topology Definition | |
54 | ## | |
55 | ##################################################### | |
56 | ||
57 | class NetworkTopo(Topo): | |
58 | "All Protocol Startup Test" | |
59 | ||
60 | def build(self, **_opts): | |
61 | ||
62 | # Setup Routers | |
63 | router = {} | |
64 | # | |
65 | # Setup Main Router | |
66 | router[1] = topotest.addRouter(self, 'r1') | |
67 | # | |
68 | ||
69 | # Setup Switches | |
70 | switch = {} | |
71 | # | |
72 | for i in range(0, 10): | |
73 | switch[i] = self.addSwitch('sw%s' % i, cls=topotest.LegacySwitch) | |
74 | self.addLink(switch[i], router[1], intfName2='r1-eth%s' % i ) | |
75 | ||
76 | ||
77 | ##################################################### | |
78 | ## | |
79 | ## Tests starting | |
80 | ## | |
81 | ##################################################### | |
82 | ||
83 | def setup_module(module): | |
84 | global topo, net | |
85 | global fatal_error | |
86 | ||
87 | print("\n\n** %s: Setup Topology" % module.__name__) | |
88 | print("******************************************\n") | |
89 | ||
90 | print("Cleanup old Mininet runs") | |
91 | os.system('sudo mn -c > /dev/null 2>&1') | |
92 | os.system('sudo rm /tmp/r* > /dev/null 2>&1') | |
93 | ||
94 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
95 | topo = NetworkTopo() | |
96 | ||
97 | net = Mininet(controller=None, topo=topo) | |
98 | net.start() | |
99 | ||
100 | if net['r1'].get_routertype() != 'frr': | |
101 | fatal_error = "Test is only implemented for FRR" | |
102 | sys.stderr.write('\n\nTest is only implemented for FRR - Skipping\n\n') | |
103 | pytest.skip(fatal_error) | |
104 | ||
105 | # Starting Routers | |
106 | # | |
107 | # Main router | |
108 | for i in range(1, 2): | |
109 | net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i)) | |
110 | net['r%s' % i].loadConf('ripd', '%s/r%s/ripd.conf' % (thisDir, i)) | |
111 | net['r%s' % i].loadConf('ripngd', '%s/r%s/ripngd.conf' % (thisDir, i)) | |
112 | net['r%s' % i].loadConf('ospfd', '%s/r%s/ospfd.conf' % (thisDir, i)) | |
113 | net['r%s' % i].loadConf('ospf6d', '%s/r%s/ospf6d.conf' % (thisDir, i)) | |
114 | net['r%s' % i].loadConf('isisd', '%s/r%s/isisd.conf' % (thisDir, i)) | |
115 | net['r%s' % i].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir, i)) | |
116 | if net['r%s' % i].daemon_available('ldpd'): | |
117 | # Only test LDPd if it's installed and Kernel >= 4.5 | |
118 | net['r%s' % i].loadConf('ldpd', '%s/r%s/ldpd.conf' % (thisDir, i)) | |
119 | net['r%s' % i].startRouter() | |
120 | ||
121 | # For debugging after starting Quagga/FRR daemons, uncomment the next line | |
122 | # CLI(net) | |
123 | ||
124 | ||
125 | def teardown_module(module): | |
126 | global net | |
127 | ||
128 | print("\n\n** %s: Shutdown Topology" % module.__name__) | |
129 | print("******************************************\n") | |
130 | ||
131 | # End - Shutdown network | |
132 | net.stop() | |
133 | ||
134 | ||
135 | def test_router_running(): | |
136 | global fatal_error | |
137 | global net | |
138 | ||
139 | # Skip if previous fatal error condition is raised | |
140 | if (fatal_error != ""): | |
141 | pytest.skip(fatal_error) | |
142 | ||
143 | print("\n\n** Check if FRR/Quagga is running on each Router node") | |
144 | print("******************************************\n") | |
145 | sleep(5) | |
146 | ||
147 | # Starting Routers | |
148 | for i in range(1, 2): | |
149 | fatal_error = net['r%s' % i].checkRouterRunning() | |
150 | assert fatal_error == "", fatal_error | |
151 | ||
152 | # For debugging after starting FRR/Quagga daemons, uncomment the next line | |
153 | # CLI(net) | |
154 | ||
155 | ||
156 | def test_error_messages_vtysh(): | |
157 | global fatal_error | |
158 | global net | |
159 | ||
160 | # Skip if previous fatal error condition is raised | |
161 | if (fatal_error != ""): | |
162 | pytest.skip(fatal_error) | |
163 | ||
164 | print("\n\n** Check for error messages on VTYSH") | |
165 | print("******************************************\n") | |
166 | ||
167 | failures = 0 | |
168 | for i in range(1, 2): | |
169 | # | |
170 | # First checking Standard Output | |
171 | # | |
172 | ||
173 | # VTYSH output from router | |
174 | vtystdout = net['r%s' % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip() | |
175 | ||
176 | # Fix newlines (make them all the same) | |
177 | vtystdout = ('\n'.join(vtystdout.splitlines()) + '\n').rstrip() | |
178 | # Drop everything starting with "FRRouting X.xx" message | |
179 | vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL) | |
180 | ||
555451fa | 181 | if (vtystdout == ''): |
4501fbca MW |
182 | print("r%s StdOut ok" % i) |
183 | ||
555451fa | 184 | assert vtystdout == '', "Vtysh StdOut Output check failed for router r%s" % i |
798fb593 | 185 | |
4501fbca MW |
186 | # |
187 | # Second checking Standard Error | |
188 | # | |
189 | ||
190 | # VTYSH StdErr output from router | |
191 | vtystderr = net['r%s' % i].cmd('vtysh -c "show version" > /dev/null').rstrip() | |
192 | ||
193 | # Fix newlines (make them all the same) | |
194 | vtystderr = ('\n'.join(vtystderr.splitlines()) + '\n').rstrip() | |
195 | # # Drop everything starting with "FRRouting X.xx" message | |
196 | # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL) | |
197 | ||
555451fa | 198 | if (vtystderr == ''): |
4501fbca MW |
199 | print("r%s StdErr ok" % i) |
200 | ||
555451fa | 201 | assert vtystderr == '', "Vtysh StdErr Output check failed for router r%s" % i |
4501fbca | 202 | |
7e7fc73b MW |
203 | # Make sure that all daemons are running |
204 | for i in range(1, 2): | |
205 | fatal_error = net['r%s' % i].checkRouterRunning() | |
206 | assert fatal_error == "", fatal_error | |
207 | ||
4501fbca MW |
208 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
209 | # CLI(net) | |
210 | ||
211 | ||
212 | def test_error_messages_daemons(): | |
213 | global fatal_error | |
214 | global net | |
215 | ||
216 | # Skip if previous fatal error condition is raised | |
217 | if (fatal_error != ""): | |
218 | pytest.skip(fatal_error) | |
219 | ||
220 | print("\n\n** Check for error messages in daemons") | |
221 | print("******************************************\n") | |
222 | ||
223 | error_logs = "" | |
224 | ||
225 | for i in range(1, 2): | |
226 | log = net['r%s' % i].getStdErr('ripd') | |
227 | if log: | |
228 | error_logs += "r%s RIPd StdErr Output:\n" % i | |
229 | error_logs += log | |
230 | log = net['r%s' % i].getStdErr('ripngd') | |
231 | if log: | |
232 | error_logs += "r%s RIPngd StdErr Output:\n" % i | |
233 | error_logs += log | |
234 | log = net['r%s' % i].getStdErr('ospfd') | |
235 | if log: | |
236 | error_logs += "r%s OSPFd StdErr Output:\n" % i | |
237 | error_logs += log | |
238 | log = net['r%s' % i].getStdErr('ospf6d') | |
239 | if log: | |
240 | error_logs += "r%s OSPF6d StdErr Output:\n" % i | |
241 | error_logs += log | |
242 | log = net['r%s' % i].getStdErr('isisd') | |
243 | # ISIS shows debugging enabled status on StdErr | |
244 | # Remove these messages | |
245 | log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip() | |
246 | if log: | |
247 | error_logs += "r%s ISISd StdErr Output:\n" % i | |
248 | error_logs += log | |
249 | log = net['r%s' % i].getStdErr('bgpd') | |
250 | if log: | |
251 | error_logs += "r%s BGPd StdErr Output:\n" % i | |
252 | error_logs += log | |
253 | if (net['r%s' % i].daemon_available('ldpd')): | |
254 | log = net['r%s' % i].getStdErr('ldpd') | |
255 | if log: | |
256 | error_logs += "r%s LDPd StdErr Output:\n" % i | |
257 | error_logs += log | |
258 | log = net['r%s' % i].getStdErr('zebra') | |
259 | if log: | |
260 | error_logs += "r%s Zebra StdErr Output:\n" | |
261 | error_logs += log | |
262 | ||
263 | if error_logs: | |
264 | sys.stderr.write('Failed check for StdErr Output on daemons:\n%s\n' % error_logs) | |
265 | ||
08fa1af7 MW |
266 | # Ignoring the issue if told to ignore (ie not yet fixed) |
267 | if (error_logs != ""): | |
1026c19a | 268 | if (os.environ.get('bamboo_TOPOTESTS_ISSUE_349') == "IGNORE"): |
08fa1af7 MW |
269 | sys.stderr.write('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349\n') |
270 | pytest.skip('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349') | |
271 | ||
4501fbca MW |
272 | assert error_logs == "", "Daemons report errors to StdErr" |
273 | ||
274 | # For debugging after starting FRR/Quagga daemons, uncomment the next line | |
275 | # CLI(net) | |
276 | ||
277 | ||
278 | def test_converge_protocols(): | |
279 | global fatal_error | |
280 | global net | |
281 | ||
282 | # Skip if previous fatal error condition is raised | |
283 | if (fatal_error != ""): | |
284 | pytest.skip(fatal_error) | |
285 | ||
286 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
287 | ||
288 | print("\n\n** Waiting for protocols convergence") | |
289 | print("******************************************\n") | |
290 | ||
291 | # Not really implemented yet - just sleep 60 secs for now | |
292 | sleep(60) | |
293 | ||
7e7fc73b MW |
294 | # Make sure that all daemons are running |
295 | for i in range(1, 2): | |
296 | fatal_error = net['r%s' % i].checkRouterRunning() | |
297 | assert fatal_error == "", fatal_error | |
298 | ||
4501fbca MW |
299 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
300 | ## CLI(net) | |
301 | ||
302 | ||
303 | def test_rip_status(): | |
304 | global fatal_error | |
305 | global net | |
306 | ||
307 | # Skip if previous fatal error condition is raised | |
308 | if (fatal_error != ""): | |
309 | pytest.skip(fatal_error) | |
310 | ||
311 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
312 | ||
b2764f90 | 313 | print("\n\n** Verifying RIP status") |
4501fbca MW |
314 | print("******************************************\n") |
315 | failures = 0 | |
316 | for i in range(1, 2): | |
317 | refTableFile = '%s/r%s/rip_status.ref' % (thisDir, i) | |
318 | if os.path.isfile(refTableFile): | |
319 | # Read expected result from file | |
320 | expected = open(refTableFile).read().rstrip() | |
321 | # Fix newlines (make them all the same) | |
322 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
323 | ||
324 | # Actual output from router | |
325 | actual = net['r%s' % i].cmd('vtysh -c "show ip rip status" 2> /dev/null').rstrip() | |
326 | # Drop time in next due | |
327 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) | |
328 | # Drop time in last update | |
329 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
330 | # Fix newlines (make them all the same) | |
331 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
332 | ||
333 | # Generate Diff | |
17070436 MW |
334 | diff = topotest.get_textdiff(actual, expected, |
335 | title1="actual IP RIP status", | |
336 | title2="expected IP RIP status") | |
4501fbca MW |
337 | |
338 | # Empty string if it matches, otherwise diff contains unified diff | |
339 | if diff: | |
340 | sys.stderr.write('r%s failed IP RIP status check:\n%s\n' % (i, diff)) | |
341 | failures += 1 | |
342 | else: | |
343 | print("r%s ok" % i) | |
344 | ||
345 | assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff) | |
346 | ||
7e7fc73b MW |
347 | # Make sure that all daemons are running |
348 | for i in range(1, 2): | |
349 | fatal_error = net['r%s' % i].checkRouterRunning() | |
350 | assert fatal_error == "", fatal_error | |
351 | ||
4501fbca MW |
352 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
353 | # CLI(net) | |
354 | ||
355 | ||
356 | def test_ripng_status(): | |
357 | global fatal_error | |
358 | global net | |
359 | ||
360 | # Skip if previous fatal error condition is raised | |
361 | if (fatal_error != ""): | |
362 | pytest.skip(fatal_error) | |
363 | ||
364 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
365 | ||
b2764f90 | 366 | print("\n\n** Verifying RIPng status") |
4501fbca MW |
367 | print("******************************************\n") |
368 | failures = 0 | |
369 | for i in range(1, 2): | |
370 | refTableFile = '%s/r%s/ripng_status.ref' % (thisDir, i) | |
371 | if os.path.isfile(refTableFile): | |
372 | # Read expected result from file | |
373 | expected = open(refTableFile).read().rstrip() | |
374 | # Fix newlines (make them all the same) | |
375 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
376 | ||
377 | # Actual output from router | |
378 | actual = net['r%s' % i].cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null').rstrip() | |
379 | # Mask out Link-Local mac address portion. They are random... | |
380 | actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
381 | # Drop time in next due | |
382 | actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual) | |
383 | # Drop time in last update | |
384 | actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) | |
385 | # Fix newlines (make them all the same) | |
386 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
387 | ||
388 | # Generate Diff | |
17070436 MW |
389 | diff = topotest.get_textdiff(actual, expected, |
390 | title1="actual IPv6 RIPng status", | |
391 | title2="expected IPv6 RIPng status") | |
4501fbca MW |
392 | |
393 | # Empty string if it matches, otherwise diff contains unified diff | |
394 | if diff: | |
395 | sys.stderr.write('r%s failed IPv6 RIPng status check:\n%s\n' % (i, diff)) | |
396 | failures += 1 | |
397 | else: | |
398 | print("r%s ok" % i) | |
399 | ||
400 | assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (i, diff) | |
401 | ||
7e7fc73b MW |
402 | # Make sure that all daemons are running |
403 | for i in range(1, 2): | |
404 | fatal_error = net['r%s' % i].checkRouterRunning() | |
405 | assert fatal_error == "", fatal_error | |
406 | ||
4501fbca MW |
407 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
408 | # CLI(net) | |
409 | ||
410 | ||
411 | def test_ospfv2_interfaces(): | |
412 | global fatal_error | |
413 | global net | |
414 | ||
415 | # Skip if previous fatal error condition is raised | |
416 | if (fatal_error != ""): | |
417 | pytest.skip(fatal_error) | |
418 | ||
419 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
420 | ||
b2764f90 | 421 | print("\n\n** Verifying OSPFv2 interfaces") |
4501fbca MW |
422 | print("******************************************\n") |
423 | failures = 0 | |
424 | for i in range(1, 2): | |
425 | refTableFile = '%s/r%s/show_ip_ospf_interface.ref' % (thisDir, i) | |
426 | if os.path.isfile(refTableFile): | |
427 | # Read expected result from file | |
428 | expected = open(refTableFile).read().rstrip() | |
429 | # Fix newlines (make them all the same) | |
430 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
431 | ||
432 | # Actual output from router | |
433 | actual = net['r%s' % i].cmd('vtysh -c "show ip ospf interface" 2> /dev/null').rstrip() | |
434 | # Mask out Bandwidth portion. They may change.. | |
435 | actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual) | |
436 | # Drop time in next due | |
437 | actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual) | |
985e6d50 MW |
438 | # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both |
439 | actual = re.sub(r"MTU mismatch detection:([a-z]+.*)", r"MTU mismatch detection: \1", actual) | |
4501fbca MW |
440 | # Fix newlines (make them all the same) |
441 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
442 | ||
443 | # Generate Diff | |
17070436 MW |
444 | diff = topotest.get_textdiff(actual, expected, |
445 | title1="actual SHOW IP OSPF INTERFACE", | |
446 | title2="expected SHOW IP OSPF INTERFACE") | |
4501fbca MW |
447 | |
448 | # Empty string if it matches, otherwise diff contains unified diff | |
449 | if diff: | |
450 | sys.stderr.write('r%s failed SHOW IP OSPF INTERFACE check:\n%s\n' % (i, diff)) | |
451 | failures += 1 | |
452 | else: | |
453 | print("r%s ok" % i) | |
454 | ||
08fa1af7 MW |
455 | # Ignoring the issue if told to ignore (ie not yet fixed) |
456 | if (failures != 0): | |
1026c19a | 457 | if (os.environ.get('bamboo_TOPOTESTS_ISSUE_348') == "IGNORE"): |
08fa1af7 MW |
458 | sys.stderr.write('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348\n') |
459 | pytest.skip('Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348') | |
460 | ||
4501fbca MW |
461 | assert failures == 0, "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff) |
462 | ||
7e7fc73b MW |
463 | # Make sure that all daemons are running |
464 | for i in range(1, 2): | |
465 | fatal_error = net['r%s' % i].checkRouterRunning() | |
466 | assert fatal_error == "", fatal_error | |
467 | ||
4501fbca MW |
468 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
469 | # CLI(net) | |
470 | ||
471 | ||
472 | def test_isis_interfaces(): | |
473 | global fatal_error | |
474 | global net | |
475 | ||
476 | # Skip if previous fatal error condition is raised | |
477 | if (fatal_error != ""): | |
478 | pytest.skip(fatal_error) | |
479 | ||
480 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
481 | ||
b2764f90 | 482 | print("\n\n** Verifying ISIS interfaces") |
4501fbca MW |
483 | print("******************************************\n") |
484 | failures = 0 | |
485 | for i in range(1, 2): | |
486 | refTableFile = '%s/r%s/show_isis_interface_detail.ref' % (thisDir, i) | |
487 | if os.path.isfile(refTableFile): | |
488 | # Read expected result from file | |
489 | expected = open(refTableFile).read().rstrip() | |
490 | # Fix newlines (make them all the same) | |
491 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
492 | ||
493 | # Actual output from router | |
494 | actual = net['r%s' % i].cmd('vtysh -c "show isis interface detail" 2> /dev/null').rstrip() | |
495 | # Mask out Link-Local mac address portion. They are random... | |
496 | actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual) | |
497 | # Mask out SNPA mac address portion. They are random... | |
498 | actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual) | |
499 | # Fix newlines (make them all the same) | |
500 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
501 | ||
502 | # Generate Diff | |
17070436 MW |
503 | diff = topotest.get_textdiff(actual, expected, |
504 | title1="actual SHOW ISIS INTERFACE DETAIL", | |
505 | title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL") | |
4501fbca MW |
506 | |
507 | # Empty string if it matches, otherwise diff contains unified diff | |
508 | if diff: | |
509 | sys.stderr.write('r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n' % (i, diff)) | |
510 | failures += 1 | |
511 | else: | |
512 | print("r%s ok" % i) | |
513 | ||
514 | assert failures == 0, "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff) | |
515 | ||
7e7fc73b MW |
516 | # Make sure that all daemons are running |
517 | for i in range(1, 2): | |
518 | fatal_error = net['r%s' % i].checkRouterRunning() | |
519 | assert fatal_error == "", fatal_error | |
520 | ||
4501fbca MW |
521 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
522 | # CLI(net) | |
523 | ||
524 | ||
525 | def test_bgp_summary(): | |
526 | global fatal_error | |
527 | global net | |
528 | ||
529 | # Skip if previous fatal error condition is raised | |
530 | if (fatal_error != ""): | |
531 | pytest.skip(fatal_error) | |
532 | ||
533 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
534 | ||
b2764f90 | 535 | print("\n\n** Verifying BGP Summary") |
4501fbca MW |
536 | print("******************************************\n") |
537 | failures = 0 | |
538 | for i in range(1, 2): | |
08fa1af7 | 539 | refTableFile = '%s/r%s/show_ip_bgp_summary.ref' % (thisDir, i) |
4501fbca MW |
540 | if os.path.isfile(refTableFile): |
541 | # Read expected result from file | |
542 | expected = open(refTableFile).read().rstrip() | |
543 | # Fix newlines (make them all the same) | |
544 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
545 | ||
546 | # Actual output from router | |
08fa1af7 | 547 | actual = net['r%s' % i].cmd('vtysh -c "show ip bgp summary" 2> /dev/null').rstrip() |
4501fbca MW |
548 | # Mask out "using XXiXX bytes" portion. They are random... |
549 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
550 | # Mask out "using XiXXX KiB" portion. They are random... | |
551 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
552 | # |
553 | # Remove extra summaries which exist with newer versions | |
554 | # | |
555 | # Remove summary lines (changed recently) | |
556 | actual = re.sub(r'Total number.*', '', actual) | |
557 | actual = re.sub(r'Displayed.*', '', actual) | |
558 | # Remove IPv4 Unicast Summary (Title only) | |
559 | actual = re.sub(r'IPv4 Unicast Summary:', '', actual) | |
560 | # Remove IPv4 Multicast Summary (all of it) | |
561 | actual = re.sub(r'IPv4 Multicast Summary:', '', actual) | |
562 | actual = re.sub(r'No IPv4 Multicast neighbor is configured', '', actual) | |
563 | # Remove IPv4 VPN Summary (all of it) | |
564 | actual = re.sub(r'IPv4 VPN Summary:', '', actual) | |
565 | actual = re.sub(r'No IPv4 VPN neighbor is configured', '', actual) | |
566 | # Remove IPv4 Encap Summary (all of it) | |
567 | actual = re.sub(r'IPv4 Encap Summary:', '', actual) | |
568 | actual = re.sub(r'No IPv4 Encap neighbor is configured', '', actual) | |
569 | # Remove Unknown Summary (all of it) | |
570 | actual = re.sub(r'Unknown Summary:', '', actual) | |
571 | actual = re.sub(r'No Unknown neighbor is configured', '', actual) | |
8b2e59e9 DS |
572 | |
573 | actual = re.sub(r'IPv4 labeled-unicast Summary:', '', actual) | |
574 | actual = re.sub(r'No IPv4 labeled-unicast neighbor is configured', '', actual) | |
575 | ||
08fa1af7 MW |
576 | # Strip empty lines |
577 | actual = actual.lstrip() | |
578 | actual = actual.rstrip() | |
579 | # | |
4501fbca MW |
580 | # Fix newlines (make them all the same) |
581 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
582 | ||
583 | # Generate Diff | |
17070436 MW |
584 | diff = topotest.get_textdiff(actual, expected, |
585 | title1="actual SHOW IP BGP SUMMARY", | |
586 | title2="expected SHOW IP BGP SUMMARY") | |
4501fbca MW |
587 | |
588 | # Empty string if it matches, otherwise diff contains unified diff | |
589 | if diff: | |
08fa1af7 | 590 | sys.stderr.write('r%s failed SHOW IP BGP SUMMARY check:\n%s\n' % (i, diff)) |
4501fbca MW |
591 | failures += 1 |
592 | else: | |
593 | print("r%s ok" % i) | |
594 | ||
08fa1af7 | 595 | assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (i, diff) |
4501fbca | 596 | |
7e7fc73b MW |
597 | # Make sure that all daemons are running |
598 | for i in range(1, 2): | |
599 | fatal_error = net['r%s' % i].checkRouterRunning() | |
600 | assert fatal_error == "", fatal_error | |
601 | ||
4501fbca MW |
602 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
603 | # CLI(net) | |
604 | ||
605 | ||
606 | def test_bgp_ipv6_summary(): | |
607 | global fatal_error | |
608 | global net | |
609 | ||
610 | # Skip if previous fatal error condition is raised | |
611 | if (fatal_error != ""): | |
612 | pytest.skip(fatal_error) | |
613 | ||
614 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
615 | ||
b2764f90 | 616 | print("\n\n** Verifying BGP IPv6 Summary") |
4501fbca MW |
617 | print("******************************************\n") |
618 | failures = 0 | |
619 | for i in range(1, 2): | |
620 | refTableFile = '%s/r%s/show_bgp_ipv6_summary.ref' % (thisDir, i) | |
621 | if os.path.isfile(refTableFile): | |
622 | # Read expected result from file | |
623 | expected = open(refTableFile).read().rstrip() | |
624 | # Fix newlines (make them all the same) | |
625 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
626 | ||
627 | # Actual output from router | |
628 | actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null').rstrip() | |
629 | # Mask out "using XXiXX bytes" portion. They are random... | |
630 | actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) | |
631 | # Mask out "using XiXXX KiB" portion. They are random... | |
632 | actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) | |
08fa1af7 MW |
633 | # |
634 | # Remove extra summaries which exist with newer versions | |
635 | # | |
636 | # Remove summary lines (changed recently) | |
637 | actual = re.sub(r'Total number.*', '', actual) | |
638 | actual = re.sub(r'Displayed.*', '', actual) | |
639 | # Remove IPv4 Unicast Summary (Title only) | |
640 | actual = re.sub(r'IPv6 Unicast Summary:', '', actual) | |
641 | # Remove IPv4 Multicast Summary (all of it) | |
642 | actual = re.sub(r'IPv6 Multicast Summary:', '', actual) | |
643 | actual = re.sub(r'No IPv6 Multicast neighbor is configured', '', actual) | |
644 | # Remove IPv4 VPN Summary (all of it) | |
645 | actual = re.sub(r'IPv6 VPN Summary:', '', actual) | |
646 | actual = re.sub(r'No IPv6 VPN neighbor is configured', '', actual) | |
647 | # Remove IPv4 Encap Summary (all of it) | |
648 | actual = re.sub(r'IPv6 Encap Summary:', '', actual) | |
649 | actual = re.sub(r'No IPv6 Encap neighbor is configured', '', actual) | |
650 | # Remove Unknown Summary (all of it) | |
651 | actual = re.sub(r'Unknown Summary:', '', actual) | |
652 | actual = re.sub(r'No Unknown neighbor is configured', '', actual) | |
8b2e59e9 DS |
653 | |
654 | # Remove Labeled Unicast Summary (all of it) | |
655 | actual = re.sub(r'IPv6 labeled-unicast Summary:', '', actual) | |
656 | actual = re.sub(r'No IPv6 labeled-unicast neighbor is configured', '', actual) | |
657 | ||
08fa1af7 MW |
658 | # Strip empty lines |
659 | actual = actual.lstrip() | |
660 | actual = actual.rstrip() | |
661 | # | |
4501fbca MW |
662 | # Fix newlines (make them all the same) |
663 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
664 | ||
665 | # Generate Diff | |
17070436 MW |
666 | diff = topotest.get_textdiff(actual, expected, |
667 | title1="actual SHOW BGP IPv6 SUMMARY", | |
668 | title2="expected SHOW BGP IPv6 SUMMARY") | |
4501fbca MW |
669 | |
670 | # Empty string if it matches, otherwise diff contains unified diff | |
671 | if diff: | |
672 | sys.stderr.write('r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n' % (i, diff)) | |
673 | failures += 1 | |
674 | else: | |
675 | print("r%s ok" % i) | |
676 | ||
677 | assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (i, diff) | |
678 | ||
7e7fc73b MW |
679 | # Make sure that all daemons are running |
680 | for i in range(1, 2): | |
681 | fatal_error = net['r%s' % i].checkRouterRunning() | |
682 | assert fatal_error == "", fatal_error | |
683 | ||
4501fbca MW |
684 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
685 | # CLI(net) | |
686 | ||
687 | ||
688 | def test_bgp_ipv4(): | |
689 | global fatal_error | |
690 | global net | |
691 | ||
692 | # Skip if previous fatal error condition is raised | |
693 | if (fatal_error != ""): | |
694 | pytest.skip(fatal_error) | |
695 | ||
696 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
697 | ||
b2764f90 | 698 | print("\n\n** Verifying BGP IPv4") |
4501fbca MW |
699 | print("******************************************\n") |
700 | failures = 0 | |
701 | for i in range(1, 2): | |
702 | refTableFile = '%s/r%s/show_bgp_ipv4.ref' % (thisDir, i) | |
703 | if os.path.isfile(refTableFile): | |
704 | # Read expected result from file | |
705 | expected = open(refTableFile).read().rstrip() | |
706 | # Fix newlines (make them all the same) | |
707 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
708 | ||
709 | # Actual output from router | |
710 | actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip() | |
711 | # Remove summary line (changed recently) | |
712 | actual = re.sub(r'Total number.*', '', actual) | |
713 | actual = re.sub(r'Displayed.*', '', actual) | |
714 | actual = actual.rstrip() | |
715 | # Fix newlines (make them all the same) | |
716 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
717 | ||
718 | # Generate Diff | |
17070436 MW |
719 | diff = topotest.get_textdiff(actual, expected, |
720 | title1="actual SHOW BGP IPv4", | |
721 | title2="expected SHOW BGP IPv4") | |
4501fbca MW |
722 | |
723 | # Empty string if it matches, otherwise diff contains unified diff | |
724 | if diff: | |
725 | sys.stderr.write('r%s failed SHOW BGP IPv4 check:\n%s\n' % (i, diff)) | |
726 | failures += 1 | |
727 | else: | |
728 | print("r%s ok" % i) | |
729 | ||
730 | assert failures == 0, "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, diff) | |
731 | ||
7e7fc73b MW |
732 | # Make sure that all daemons are running |
733 | for i in range(1, 2): | |
734 | fatal_error = net['r%s' % i].checkRouterRunning() | |
735 | assert fatal_error == "", fatal_error | |
736 | ||
4501fbca MW |
737 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
738 | # CLI(net) | |
739 | ||
740 | ||
741 | def test_bgp_ipv6(): | |
742 | global fatal_error | |
743 | global net | |
744 | ||
745 | # Skip if previous fatal error condition is raised | |
746 | if (fatal_error != ""): | |
747 | pytest.skip(fatal_error) | |
748 | ||
749 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
750 | ||
b2764f90 | 751 | print("\n\n** Verifying BGP IPv6") |
4501fbca MW |
752 | print("******************************************\n") |
753 | failures = 0 | |
754 | for i in range(1, 2): | |
755 | refTableFile = '%s/r%s/show_bgp_ipv6.ref' % (thisDir, i) | |
756 | if os.path.isfile(refTableFile): | |
757 | # Read expected result from file | |
758 | expected = open(refTableFile).read().rstrip() | |
759 | # Fix newlines (make them all the same) | |
760 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
761 | ||
762 | # Actual output from router | |
763 | actual = net['r%s' % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip() | |
764 | # Remove summary line (changed recently) | |
765 | actual = re.sub(r'Total number.*', '', actual) | |
766 | actual = re.sub(r'Displayed.*', '', actual) | |
767 | actual = actual.rstrip() | |
768 | # Fix newlines (make them all the same) | |
769 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
770 | ||
771 | # Generate Diff | |
17070436 MW |
772 | diff = topotest.get_textdiff(actual, expected, |
773 | title1="actual SHOW BGP IPv6", | |
774 | title2="expected SHOW BGP IPv6") | |
4501fbca MW |
775 | |
776 | # Empty string if it matches, otherwise diff contains unified diff | |
777 | if diff: | |
778 | sys.stderr.write('r%s failed SHOW BGP IPv6 check:\n%s\n' % (i, diff)) | |
779 | failures += 1 | |
780 | else: | |
781 | print("r%s ok" % i) | |
782 | ||
783 | assert failures == 0, "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, diff) | |
784 | ||
7e7fc73b MW |
785 | # Make sure that all daemons are running |
786 | for i in range(1, 2): | |
787 | fatal_error = net['r%s' % i].checkRouterRunning() | |
788 | assert fatal_error == "", fatal_error | |
789 | ||
4501fbca MW |
790 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
791 | # CLI(net) | |
792 | ||
793 | ||
794 | ||
795 | def test_mpls_interfaces(): | |
796 | global fatal_error | |
797 | global net | |
798 | ||
799 | # Skip if previous fatal error condition is raised | |
800 | if (fatal_error != ""): | |
801 | pytest.skip(fatal_error) | |
802 | ||
803 | # Skip if no LDP installed or old kernel | |
804 | if (net['r1'].daemon_available('ldpd') == False): | |
805 | pytest.skip("No MPLS or kernel < 4.5") | |
806 | ||
807 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
808 | ||
b2764f90 | 809 | print("\n\n** Verifying MPLS Interfaces") |
4501fbca MW |
810 | print("******************************************\n") |
811 | failures = 0 | |
812 | for i in range(1, 2): | |
813 | refTableFile = '%s/r%s/show_mpls_ldp_interface.ref' % (thisDir, i) | |
814 | if os.path.isfile(refTableFile): | |
815 | # Read expected result from file | |
816 | expected = open(refTableFile).read().rstrip() | |
817 | # Fix newlines (make them all the same) | |
818 | expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) | |
819 | ||
820 | # Actual output from router | |
821 | actual = net['r%s' % i].cmd('vtysh -c "show mpls ldp interface" 2> /dev/null').rstrip() | |
822 | # Mask out Timer in Uptime | |
823 | actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual) | |
824 | # Fix newlines (make them all the same) | |
825 | actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) | |
826 | ||
827 | # Generate Diff | |
17070436 MW |
828 | diff = topotest.get_textdiff(actual, expected, |
829 | title1="actual MPLS LDP interface status", | |
830 | title2="expected MPLS LDP interface status") | |
4501fbca MW |
831 | |
832 | # Empty string if it matches, otherwise diff contains unified diff | |
833 | if diff: | |
834 | sys.stderr.write('r%s failed MPLS LDP Interface status Check:\n%s\n' % (i, diff)) | |
835 | failures += 1 | |
836 | else: | |
837 | print("r%s ok" % i) | |
838 | ||
839 | if failures>0: | |
840 | fatal_error = "MPLS LDP Interface status failed" | |
841 | ||
842 | assert failures == 0, "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff) | |
843 | ||
7e7fc73b MW |
844 | # Make sure that all daemons are running |
845 | for i in range(1, 2): | |
846 | fatal_error = net['r%s' % i].checkRouterRunning() | |
847 | assert fatal_error == "", fatal_error | |
848 | ||
4501fbca MW |
849 | # For debugging after starting FRR/Quagga daemons, uncomment the next line |
850 | # CLI(net) | |
851 | ||
852 | ||
853 | def test_shutdown_check_stderr(): | |
854 | global fatal_error | |
855 | global net | |
856 | ||
857 | # Skip if previous fatal error condition is raised | |
858 | if (fatal_error != ""): | |
859 | pytest.skip(fatal_error) | |
860 | ||
b2764f90 | 861 | print("\n\n** Verifying unexpected STDERR output from daemons") |
4501fbca MW |
862 | print("******************************************\n") |
863 | ||
864 | if os.environ.get('TOPOTESTS_CHECK_STDERR') is None: | |
50c40bde MW |
865 | print("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n") |
866 | pytest.skip('Skipping test for Stderr output') | |
4501fbca MW |
867 | |
868 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
869 | ||
50c40bde MW |
870 | print("thisDir=" + thisDir) |
871 | ||
4501fbca MW |
872 | net['r1'].stopRouter() |
873 | ||
874 | log = net['r1'].getStdErr('ripd') | |
8e957dbb MW |
875 | if log: |
876 | print("\nRIPd StdErr Log:\n" + log) | |
4501fbca | 877 | log = net['r1'].getStdErr('ripngd') |
8e957dbb MW |
878 | if log: |
879 | print("\nRIPngd StdErr Log:\n" + log) | |
4501fbca | 880 | log = net['r1'].getStdErr('ospfd') |
8e957dbb MW |
881 | if log: |
882 | print("\nOSPFd StdErr Log:\n" + log) | |
4501fbca | 883 | log = net['r1'].getStdErr('ospf6d') |
8e957dbb MW |
884 | if log: |
885 | print("\nOSPF6d StdErr Log:\n" + log) | |
4501fbca | 886 | log = net['r1'].getStdErr('isisd') |
8e957dbb MW |
887 | if log: |
888 | print("\nISISd StdErr Log:\n" + log) | |
4501fbca | 889 | log = net['r1'].getStdErr('bgpd') |
8e957dbb MW |
890 | if log: |
891 | print("\nBGPd StdErr Log:\n" + log) | |
4501fbca MW |
892 | if (net['r1'].daemon_available('ldpd')): |
893 | log = net['r1'].getStdErr('ldpd') | |
8e957dbb MW |
894 | if log: |
895 | print("\nLDPd StdErr Log:\n" + log) | |
4501fbca | 896 | log = net['r1'].getStdErr('zebra') |
8e957dbb MW |
897 | if log: |
898 | print("\nZebra StdErr Log:\n" + log) | |
4501fbca MW |
899 | |
900 | ||
50c40bde MW |
901 | def test_shutdown_check_memleak(): |
902 | global fatal_error | |
903 | global net | |
904 | ||
905 | # Skip if previous fatal error condition is raised | |
906 | if (fatal_error != ""): | |
907 | pytest.skip(fatal_error) | |
908 | ||
909 | if os.environ.get('TOPOTESTS_CHECK_MEMLEAK') is None: | |
910 | print("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n") | |
911 | pytest.skip('Skipping test for memory leaks') | |
912 | ||
913 | thisDir = os.path.dirname(os.path.realpath(__file__)) | |
914 | ||
915 | for i in range(1, 2): | |
916 | net['r%s' % i].stopRouter() | |
917 | net['r%s' % i].report_memory_leaks(os.environ.get('TOPOTESTS_CHECK_MEMLEAK'), os.path.basename(__file__)) | |
918 | ||
919 | ||
4501fbca MW |
920 | if __name__ == '__main__': |
921 | ||
922 | setLogLevel('info') | |
923 | # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli | |
924 | # retval = pytest.main(["-s", "--tb=no"]) | |
925 | retval = pytest.main(["-s"]) | |
926 | sys.exit(retval) |