13
13
import functools
14
14
import json
15
15
16
- from testinfra .modules .base import InstanceModule
16
+ from testinfra .modules .base import Module
17
17
18
18
19
- class IProute2 (InstanceModule ):
20
- """Test network configuration via iproute2 commands
19
+ class IProute2 (Module ):
20
+ """Tests network configuration via iproute2 commands
21
21
22
22
Currently supported:
23
23
@@ -33,12 +33,14 @@ class IProute2(InstanceModule):
33
33
* bridge fdb
34
34
* bridge mdb
35
35
36
- Optional module-level arguments can also be provided to contro; execution:
36
+ Optional module-level arguments can also be provided to control execution:
37
+
38
+ * **family**: force iproute2 tools to use a specific protocol family
37
39
38
- * family: force iproute2 tools to use a specific protocol family
39
40
>>> host.iproute2(family="inet").addresses()
40
41
41
- * namespace: execute iproute2 tools inside the provided namespace
42
+ * **namespace**: execute iproute2 tools inside the provided namespace
43
+
42
44
>>> host.iproute2(namespace="test").addresses()
43
45
44
46
"""
@@ -51,6 +53,221 @@ def __init__(self, family=None, namespace=None):
51
53
def __repr__ (self ):
52
54
return "<ip>"
53
55
56
+ @classmethod
57
+ def get_module_class (cls , host ):
58
+ if host .system_info .type == "linux" :
59
+ return LinuxIProute2
60
+ raise NotImplementedError
61
+
62
+ @property
63
+ def exists (self ):
64
+ """Returns True if ip -V succeeds
65
+
66
+ >>> host.iproute2.exists
67
+ True
68
+
69
+ """
70
+
71
+ @property
72
+ def bridge_exists (self ):
73
+ """Returns True if bridge -V succeeds
74
+
75
+ >>> host.iproute2.bridge_exists
76
+ True
77
+
78
+ """
79
+
80
+ def addresses (self , address = None , ifname = None , local = None ):
81
+ """Returns the addresses associated with interfaces
82
+
83
+ >>> host.iproute2.addresses()
84
+ [{'ifindex': 1,
85
+ 'ifname': 'lo',
86
+ 'flags': ['LOOPBACK', 'UP', 'LOWER_UP'],
87
+ 'mtu': 65536,
88
+ 'qdisc': 'noqueue',
89
+ 'operstate': 'UNKNOWN',
90
+ 'group': 'default',
91
+ 'txqlen': 1000,
92
+ 'link_type': 'loopback',
93
+ 'address': '00:00:00:00:00:00',
94
+ 'broadcast': '00:00:00:00:00:00',
95
+ 'addr_info': [{'family': 'inet',
96
+ 'local': '127.0.0.1',
97
+ 'prefixlen': 8,
98
+ 'scope': 'host',
99
+ 'label': 'lo',
100
+ 'valid_life_time': 4294967295,
101
+ 'preferred_life_time': 4294967295},
102
+ {'family': 'inet6',
103
+ 'local': '::1',
104
+ 'prefixlen': 128,
105
+ 'scope': 'host',
106
+ 'noprefixroute': True,
107
+ 'valid_life_time': 4294967295,
108
+ 'preferred_life_time': 4294967295}]}]
109
+
110
+ Optionally, results can be filtered with the following selectors:
111
+
112
+ * address
113
+ * ifname
114
+ * local
115
+
116
+ """
117
+
118
+ def links (self ):
119
+ """Returns links and their state.
120
+
121
+ >>> host.iproute2.links()
122
+ [{'ifindex': 1,
123
+ 'ifname': 'lo',
124
+ 'flags': ['LOOPBACK', 'UP', 'LOWER_UP'],
125
+ 'mtu': 65536,
126
+ 'qdisc': 'noqueue',
127
+ 'operstate': 'UNKNOWN',
128
+ 'linkmode': 'DEFAULT',
129
+ 'group': 'default',
130
+ 'txqlen': 1000,
131
+ 'link_type': 'loopback',
132
+ 'address': '00:00:00:00:00:00',
133
+ 'broadcast': '00:00:00:00:00:00'}]
134
+
135
+ """
136
+
137
+ def routes (
138
+ self , table = "all" , device = None , scope = None , proto = None , src = None , metric = None
139
+ ):
140
+ """Returns the routes installed in *all* routing tables.
141
+
142
+ >>> host.iproute2.routes()
143
+ [{'dst': '169.254.0.0/16',
144
+ 'dev': 'wlp4s0',
145
+ 'scope': 'link',
146
+ 'metric': 1000,
147
+ 'flags': []},
148
+ {'type': 'multicast',
149
+ 'dst': 'ff00::/8',
150
+ 'dev': 'wlp4s0',
151
+ 'table': 'local',
152
+ 'protocol': 'kernel',
153
+ 'metric': 256,
154
+ 'flags': [],
155
+ 'pref': 'medium'}]
156
+
157
+ Optionally, routes returned can be filtered with the following
158
+ selectors. This can be useful in busy routing tables.
159
+
160
+ * table
161
+ * device (maps to ip-route's 'dev' selector)
162
+ * scope
163
+ * proto
164
+ * src
165
+ * metric
166
+
167
+ """
168
+
169
+ def rules (
170
+ self ,
171
+ src = None ,
172
+ to = None ,
173
+ tos = None ,
174
+ fwmark = None ,
175
+ iif = None ,
176
+ oif = None ,
177
+ pref = None ,
178
+ uidrange = None ,
179
+ ipproto = None ,
180
+ sport = None ,
181
+ dport = None ,
182
+ ):
183
+ """Returns the rules our routing policy consists of.
184
+
185
+ >>> host.iproute2.rules()
186
+ [{'priority': 0, 'src': 'all', 'table': 'local'},
187
+ {'priority': 32765, 'src': '1.2.3.4', 'table': '123'},
188
+ {'priority': 32766, 'src': 'all', 'table': 'main'},
189
+ {'priority': 32767, 'src': 'all', 'table': 'default'}]
190
+
191
+ Optionally, rules returned can be filtered with the following
192
+ selectors. This can be useful in busy rulesets.
193
+
194
+ * src (maps to ip-rule's 'from' selector)
195
+ * to
196
+ * tos
197
+ * fwmark
198
+ * iif
199
+ * oif
200
+ * pref
201
+ * uidrange
202
+ * ipproto
203
+ * sport
204
+ * dport
205
+
206
+ """
207
+
208
+ def tunnels (self , ifname = None ):
209
+ """Returns all configured tunnels
210
+
211
+ >>> host.iproute2.tunnels()
212
+ [{'ifname': 'test1',
213
+ 'mode': 'ip/ip',
214
+ 'remote': '127.0.0.2',
215
+ 'local': '0.0.0.0'}]
216
+
217
+ Optionally, tunnels returned can be filtered with the interface name.
218
+ This can be faster in busy tunnel installations.
219
+
220
+ * ifname
221
+
222
+ """
223
+
224
+ def vrfs (self ):
225
+ """Returns all configured vrfs"""
226
+ cmd = f"{ self ._ip } --json vrf show"
227
+ out = self .check_output (cmd )
228
+ return json .loads (out )
229
+
230
+ def netns (self ):
231
+ """Returns all configured network namespaces
232
+
233
+ >>> host.iproute2.netns()
234
+ [{'name': 'test'}]
235
+ """
236
+
237
+ def bridge_vlan (self ):
238
+ """Returns all configured vlans
239
+
240
+ >>> host.iproute2.bridge_vlan()
241
+ []
242
+ """
243
+
244
+ def bridge_fdb (self ):
245
+ """Returns all configured fdb entries
246
+
247
+ >>> host.iproute2.bridge_fdb()
248
+ [{'mac': '33:33:00:00:00:01',
249
+ 'ifname': 'enp0s31f6',
250
+ 'flags': ['self'],
251
+ 'state': 'permanent'}]
252
+ """
253
+
254
+ def bridge_mdb (self ):
255
+ """Returns all configured mdb entries
256
+
257
+ >>> host.iproute2.bridge_mdb()
258
+ [{'mdb': [], 'router': {}}]
259
+
260
+ """
261
+
262
+ def bridge_link (self ):
263
+ """Returns all configured links
264
+
265
+ >>> host.iproute2.bridge_link()
266
+ []
267
+ """
268
+
269
+
270
+ class LinuxIProute2 (IProute2 ):
54
271
@functools .cached_property
55
272
def _ip (self ):
56
273
ip_cmd = self .find_command ("ip" )
@@ -326,9 +543,9 @@ def vrfs(self):
326
543
def netns (self ):
327
544
"""Returns all configured network namespaces
328
545
329
- >>> host.iproute2.netns()
330
- [{'name': 'test'}]
331
- """
546
+ >>> host.iproute2.netns()
547
+ [{'name': 'test'}]
548
+ """
332
549
333
550
cmd = f"{ self ._ip } --json netns show"
334
551
out = self .check_output (cmd )
@@ -339,9 +556,9 @@ def netns(self):
339
556
def bridge_vlan (self ):
340
557
"""Returns all configured vlans
341
558
342
- >>> host.iproute2.bridge_vlan()
343
- []
344
- """
559
+ >>> host.iproute2.bridge_vlan()
560
+ []
561
+ """
345
562
346
563
cmd = f"{ self ._bridge } -json vlan show"
347
564
out = self .check_output (cmd )
@@ -350,11 +567,11 @@ def bridge_vlan(self):
350
567
def bridge_fdb (self ):
351
568
"""Returns all configured fdb entries
352
569
353
- >>> host.iproute2.bridge_fdb()
354
- [{'mac': '33:33:00:00:00:01',
355
- 'ifname': 'enp0s31f6',
356
- 'flags': ['self'],
357
- 'state': 'permanent'}]
570
+ >>> host.iproute2.bridge_fdb()
571
+ [{'mac': '33:33:00:00:00:01',
572
+ 'ifname': 'enp0s31f6',
573
+ 'flags': ['self'],
574
+ 'state': 'permanent'}]
358
575
"""
359
576
360
577
cmd = f"{ self ._bridge } -json fdb show"
@@ -364,10 +581,10 @@ def bridge_fdb(self):
364
581
def bridge_mdb (self ):
365
582
"""Returns all configured mdb entries
366
583
367
- >>> host.iproute2.bridge_mdb()
368
- [{'mdb': [], 'router': {}}]
584
+ >>> host.iproute2.bridge_mdb()
585
+ [{'mdb': [], 'router': {}}]
369
586
370
- """
587
+ """
371
588
372
589
cmd = f"{ self ._bridge } -json mdb show"
373
590
out = self .check_output (cmd )
@@ -376,9 +593,9 @@ def bridge_mdb(self):
376
593
def bridge_link (self ):
377
594
"""Returns all configured links
378
595
379
- >>> host.iproute2.bridge_link()
380
- []
381
- """
596
+ >>> host.iproute2.bridge_link()
597
+ []
598
+ """
382
599
383
600
cmd = f"{ self ._bridge } -json link show"
384
601
out = self .check_output (cmd )
0 commit comments