Skip to content

Commit d6bd855

Browse files
committed
iproute2: updated docs
1 parent 4e9bffc commit d6bd855

File tree

2 files changed

+193
-48
lines changed

2 files changed

+193
-48
lines changed

doc/source/modules.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ Interface
178178
:undoc-members:
179179
:exclude-members: get_module_class
180180

181+
IProute2
182+
~~~~~~~~~
183+
184+
.. autoclass:: testinfra.modules.iproute2.IProute2
185+
:members:
186+
:undoc-members:
187+
181188

182189
Iptables
183190
~~~~~~~~~

testinfra/modules/iproute2.py

Lines changed: 186 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,27 @@
1919
class IProute2(InstanceModule):
2020
"""Test network configuration via iproute2 commands
2121
22-
Optional arguments:
23-
- family: force iproute2 tools to use a specific protocol family
24-
- namespace: execute iproute2 tools inside the provided namespace
22+
Currently supported:
23+
24+
* ip-address
25+
* ip-link
26+
* ip-route
27+
* ip-rule
28+
* ip-vrf
29+
* ip-tunnel
30+
* ip-netns
31+
* bridge vlan
32+
* bridge link
33+
* bridge fdb
34+
* bridge mdb
35+
36+
Optional module-level arguments can also be provided to contro; execution:
37+
38+
* family: force iproute2 tools to use a specific protocol family
39+
>>> host.iproute2(family="inet").addresses()
40+
41+
* namespace: execute iproute2 tools inside the provided namespace
42+
>>> host.iproute2(namespace="test").addresses()
2543
2644
"""
2745

@@ -42,17 +60,68 @@ def _ip(self):
4260
ip_cmd = f"{ip_cmd} -f {self.family}"
4361
return ip_cmd
4462

63+
@functools.cached_property
64+
def _bridge(self):
65+
bridge_cmd = self.find_command("bridge")
66+
if self.namespace is not None:
67+
bridge_cmd = f"{bridge_cmd} -n {self.namespace}"
68+
return bridge_cmd
69+
4570
@property
4671
def exists(self):
72+
"""Returns True if ip -V succeeds
73+
74+
>>> host.iproute2.exists
75+
True
76+
77+
"""
4778
return self.run_test("{} -V".format(self._ip)).rc == 0
4879

49-
def addresses(self, address=None, ifname=None, local=None):
50-
"""Return the addresses associated with interfaces
80+
@property
81+
def bridge_exists(self):
82+
"""Returns True if bridge -V succeeds
83+
84+
>>> host.iproute2.bridge_exists
85+
True
5186
52-
Optionally, results can be filtered by:
53-
- address
54-
- ifname
55-
- local
87+
"""
88+
return self.run_test("{} -V".format(self._bridge)).rc == 0
89+
90+
def addresses(self, address=None, ifname=None, local=None):
91+
"""Returns the addresses associated with interfaces
92+
93+
>>> host.iproute2.addresses()
94+
[{'ifindex': 1,
95+
'ifname': 'lo',
96+
'flags': ['LOOPBACK', 'UP', 'LOWER_UP'],
97+
'mtu': 65536,
98+
'qdisc': 'noqueue',
99+
'operstate': 'UNKNOWN',
100+
'group': 'default',
101+
'txqlen': 1000,
102+
'link_type': 'loopback',
103+
'address': '00:00:00:00:00:00',
104+
'broadcast': '00:00:00:00:00:00',
105+
'addr_info': [{'family': 'inet',
106+
'local': '127.0.0.1',
107+
'prefixlen': 8,
108+
'scope': 'host',
109+
'label': 'lo',
110+
'valid_life_time': 4294967295,
111+
'preferred_life_time': 4294967295},
112+
{'family': 'inet6',
113+
'local': '::1',
114+
'prefixlen': 128,
115+
'scope': 'host',
116+
'noprefixroute': True,
117+
'valid_life_time': 4294967295,
118+
'preferred_life_time': 4294967295}]}]
119+
120+
Optionally, results can be filtered with the following selectors:
121+
122+
* address
123+
* ifname
124+
* local
56125
57126
"""
58127
cmd = f"{self._ip} --json address show"
@@ -74,26 +143,56 @@ def addresses(self, address=None, ifname=None, local=None):
74143
return o
75144

76145
def links(self):
77-
"""Return links and their state"""
146+
"""Returns links and their state.
147+
148+
>>> host.iproute2.links()
149+
[{'ifindex': 1,
150+
'ifname': 'lo',
151+
'flags': ['LOOPBACK', 'UP', 'LOWER_UP'],
152+
'mtu': 65536,
153+
'qdisc': 'noqueue',
154+
'operstate': 'UNKNOWN',
155+
'linkmode': 'DEFAULT',
156+
'group': 'default',
157+
'txqlen': 1000,
158+
'link_type': 'loopback',
159+
'address': '00:00:00:00:00:00',
160+
'broadcast': '00:00:00:00:00:00'}]
161+
162+
"""
78163
cmd = f"{self._ip} --json link show"
79164
out = self.check_output(cmd)
80165
return json.loads(out)
81166

82167
def routes(
83168
self, table="all", device=None, scope=None, proto=None, src=None, metric=None
84169
):
85-
"""Returns the routes installed
86-
87-
Optionally, routes returned can be filtered with the following
88-
selectors. This can be useful in busy routing tables.
89-
90-
Selectors:
91-
- table
92-
- device (maps to ip-route's 'dev' selector)
93-
- scope
94-
- proto
95-
- src
96-
- metric
170+
"""Returns the routes installed in *all* routing tables.
171+
172+
>>> host.iproute2.routes()
173+
[{'dst': '169.254.0.0/16',
174+
'dev': 'wlp4s0',
175+
'scope': 'link',
176+
'metric': 1000,
177+
'flags': []},
178+
{'type': 'multicast',
179+
'dst': 'ff00::/8',
180+
'dev': 'wlp4s0',
181+
'table': 'local',
182+
'protocol': 'kernel',
183+
'metric': 256,
184+
'flags': [],
185+
'pref': 'medium'}]
186+
187+
Optionally, routes returned can be filtered with the following
188+
selectors. This can be useful in busy routing tables.
189+
190+
* table
191+
* device (maps to ip-route's 'dev' selector)
192+
* scope
193+
* proto
194+
* src
195+
* metric
97196
98197
"""
99198
cmd = f"{self._ip} --json route show "
@@ -129,23 +228,28 @@ def rules(
129228
sport=None,
130229
dport=None,
131230
):
132-
"""Returns the rules our routing policy consists of
133-
134-
Optionally, rules returned can be filtered with the following
135-
selectors. This can be useful in busy rulesets.
136-
137-
Selectors:
138-
- src (maps to ip-rule's 'from' selector)
139-
- to
140-
- tos
141-
- fwmark
142-
- iif
143-
- oif
144-
- pref
145-
- uidrange
146-
- ipproto
147-
- sport
148-
- dport
231+
"""Returns the rules our routing policy consists of.
232+
233+
>>> host.iproute2.rules()
234+
[{'priority': 0, 'src': 'all', 'table': 'local'},
235+
{'priority': 32765, 'src': '1.2.3.4', 'table': '123'},
236+
{'priority': 32766, 'src': 'all', 'table': 'main'},
237+
{'priority': 32767, 'src': 'all', 'table': 'default'}]
238+
239+
Optionally, rules returned can be filtered with the following
240+
selectors. This can be useful in busy rulesets.
241+
242+
* src (maps to ip-rule's 'from' selector)
243+
* to
244+
* tos
245+
* fwmark
246+
* iif
247+
* oif
248+
* pref
249+
* uidrange
250+
* ipproto
251+
* sport
252+
* dport
149253
150254
"""
151255
cmd = f"{self._ip} --json rule show "
@@ -191,11 +295,16 @@ def rules(
191295
def tunnels(self, ifname=None):
192296
"""Returns all configured tunnels
193297
194-
Optionally, tunnels returned can be filtered with the interface name.
195-
This can be faster in busy tunnel installations.
298+
>>> host.iproute2.tunnels()
299+
[{'ifname': 'test1',
300+
'mode': 'ip/ip',
301+
'remote': '127.0.0.2',
302+
'local': '0.0.0.0'}]
303+
304+
Optionally, tunnels returned can be filtered with the interface name.
305+
This can be faster in busy tunnel installations.
196306
197-
Selectors:
198-
- ifname
307+
* ifname
199308
200309
"""
201310
cmd = f"{self._ip} --json tunnel show "
@@ -215,33 +324,62 @@ def vrfs(self):
215324
return json.loads(out)
216325

217326
def netns(self):
218-
"""Returns all configured network namespaces"""
327+
"""Returns all configured network namespaces
328+
329+
>>> host.iproute2.netns()
330+
[{'name': 'test'}]
331+
"""
332+
219333
cmd = f"{self._ip} --json netns show"
220334
out = self.check_output(cmd)
221335
if not out: # ip netns returns null instead of [] in json mode
222336
return json.loads("[]\n")
223337
return json.loads(out)
224338

225339
def bridge_vlan(self):
226-
"""Returns all configured vlans"""
340+
"""Returns all configured vlans
341+
342+
>>> host.iproute2.bridge_vlan()
343+
[]
344+
"""
345+
227346
cmd = f"{self._bridge} -json vlan show"
228347
out = self.check_output(cmd)
229348
return json.loads(out)
230349

231350
def bridge_fdb(self):
232-
"""Returns all configured fdb entries"""
351+
"""Returns all configured fdb entries
352+
353+
>>> host.iproute2.bridge_fdb()
354+
[{'mac': '33:33:00:00:00:01',
355+
'ifname': 'enp0s31f6',
356+
'flags': ['self'],
357+
'state': 'permanent'}]
358+
"""
359+
233360
cmd = f"{self._bridge} -json fdb show"
234361
out = self.check_output(cmd)
235362
return json.loads(out)
236363

237364
def bridge_mdb(self):
238-
"""Returns all configured mdb entries"""
365+
"""Returns all configured mdb entries
366+
367+
>>> host.iproute2.bridge_mdb()
368+
[{'mdb': [], 'router': {}}]
369+
370+
"""
371+
239372
cmd = f"{self._bridge} -json mdb show"
240373
out = self.check_output(cmd)
241374
return json.loads(out)
242375

243376
def bridge_link(self):
244-
"""Returns all configured links"""
377+
"""Returns all configured links
378+
379+
>>> host.iproute2.bridge_link()
380+
[]
381+
"""
382+
245383
cmd = f"{self._bridge} -json link show"
246384
out = self.check_output(cmd)
247385
return json.loads(out)

0 commit comments

Comments
 (0)