1313import functools
1414import json
1515
16- from testinfra .modules .base import InstanceModule
16+ from testinfra .modules .base import Module
1717
1818
19- class IProute2 (InstanceModule ):
20- """Test network configuration via iproute2 commands
19+ class IProute2 (Module ):
20+ """Tests network configuration via iproute2 commands
2121
2222 Currently supported:
2323
@@ -33,12 +33,14 @@ class IProute2(InstanceModule):
3333 * bridge fdb
3434 * bridge mdb
3535
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
3739
38- * family: force iproute2 tools to use a specific protocol family
3940 >>> host.iproute2(family="inet").addresses()
4041
41- * namespace: execute iproute2 tools inside the provided namespace
42+ * **namespace**: execute iproute2 tools inside the provided namespace
43+
4244 >>> host.iproute2(namespace="test").addresses()
4345
4446 """
@@ -51,6 +53,221 @@ def __init__(self, family=None, namespace=None):
5153 def __repr__ (self ):
5254 return "<ip>"
5355
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 ):
54271 @functools .cached_property
55272 def _ip (self ):
56273 ip_cmd = self .find_command ("ip" )
@@ -326,9 +543,9 @@ def vrfs(self):
326543 def netns (self ):
327544 """Returns all configured network namespaces
328545
329- >>> host.iproute2.netns()
330- [{'name': 'test'}]
331- """
546+ >>> host.iproute2.netns()
547+ [{'name': 'test'}]
548+ """
332549
333550 cmd = f"{ self ._ip } --json netns show"
334551 out = self .check_output (cmd )
@@ -339,9 +556,9 @@ def netns(self):
339556 def bridge_vlan (self ):
340557 """Returns all configured vlans
341558
342- >>> host.iproute2.bridge_vlan()
343- []
344- """
559+ >>> host.iproute2.bridge_vlan()
560+ []
561+ """
345562
346563 cmd = f"{ self ._bridge } -json vlan show"
347564 out = self .check_output (cmd )
@@ -350,11 +567,11 @@ def bridge_vlan(self):
350567 def bridge_fdb (self ):
351568 """Returns all configured fdb entries
352569
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'}]
358575 """
359576
360577 cmd = f"{ self ._bridge } -json fdb show"
@@ -364,10 +581,10 @@ def bridge_fdb(self):
364581 def bridge_mdb (self ):
365582 """Returns all configured mdb entries
366583
367- >>> host.iproute2.bridge_mdb()
368- [{'mdb': [], 'router': {}}]
584+ >>> host.iproute2.bridge_mdb()
585+ [{'mdb': [], 'router': {}}]
369586
370- """
587+ """
371588
372589 cmd = f"{ self ._bridge } -json mdb show"
373590 out = self .check_output (cmd )
@@ -376,9 +593,9 @@ def bridge_mdb(self):
376593 def bridge_link (self ):
377594 """Returns all configured links
378595
379- >>> host.iproute2.bridge_link()
380- []
381- """
596+ >>> host.iproute2.bridge_link()
597+ []
598+ """
382599
383600 cmd = f"{ self ._bridge } -json link show"
384601 out = self .check_output (cmd )
0 commit comments