4
4
from time import monotonic , sleep
5
5
6
6
import gi
7
- gi .require_version ('NM' , '1.0' )
7
+
8
+ gi .require_version ("NM" , "1.0" )
8
9
from gi .repository import GLib , NM
9
10
10
11
# ensure all wrapper objects for Settings types are created
11
12
for _name in dir (NM ):
12
- if _name .startswith (' Setting' ):
13
+ if _name .startswith (" Setting" ):
13
14
getattr (NM , _name )
14
15
16
+
15
17
class Future :
16
18
def __init__ (self ):
17
19
self ._event = threading .Event ()
@@ -38,6 +40,7 @@ def run(self):
38
40
GLib .MainLoop (None ).run ()
39
41
except Exception :
40
42
import traceback
43
+
41
44
traceback .print_exc (file = sys .stderr )
42
45
sys .exit (1 )
43
46
@@ -53,13 +56,11 @@ def cb(data):
53
56
done .wait ()
54
57
return result [0 ]
55
58
59
+
56
60
def address_from_str (s ):
57
- assert '/' in s , "IP address must be in the form address/prefix"
58
- (addr , prefix ) = s .split ('/' , 1 )
59
- return NM .IPAddress .new (
60
- socket .AF_INET6 if ':' in addr else socket .AF_INET ,
61
- addr ,
62
- int (prefix ))
61
+ assert "/" in s , "IP address must be in the form address/prefix"
62
+ (addr , prefix ) = s .split ("/" , 1 )
63
+ return NM .IPAddress .new (socket .AF_INET6 if ":" in addr else socket .AF_INET , addr , int (prefix ))
63
64
64
65
65
66
def connection_from_dict (data ):
@@ -71,13 +72,13 @@ def connection_from_dict(data):
71
72
if not v :
72
73
continue
73
74
74
- if k == ' mac-address' :
75
- v = ':' .join (f"{ x :02X} " for x in v )
76
- elif k == ' ssid' :
75
+ if k == " mac-address" :
76
+ v = ":" .join (f"{ x :02X} " for x in v )
77
+ elif k == " ssid" :
77
78
if isinstance (v , str ):
78
79
v = v .encode ()
79
80
v = GLib .Bytes (v )
80
- elif k == ' addresses' :
81
+ elif k == " addresses" :
81
82
# setting addresses via the property doesn't seem to work
82
83
for x in v :
83
84
setting .add_address (address_from_str (x ))
@@ -92,13 +93,15 @@ def connection_from_dict(data):
92
93
con .add_setting (setting )
93
94
return con
94
95
96
+
95
97
class NMDev :
96
98
def __init__ (self , interface ):
97
99
self ._interface = interface
98
- self ._nm_dev = nm .get_device_by_iface (interface ) # pylint: disable=possibly-used-before-assignment
100
+ self ._nm_dev = nm .get_device_by_iface (interface ) # pylint: disable=possibly-used-before-assignment
99
101
100
102
def _delete_connection (self , con ):
101
103
future = Future ()
104
+
102
105
def cb (con , res , error ):
103
106
assert error is None
104
107
try :
@@ -114,7 +117,7 @@ def cb(con, res, error):
114
117
)
115
118
116
119
def get_settings (self ):
117
- lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
120
+ lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
118
121
if lg_con :
119
122
return dict (lg_con .to_dbus (NM .ConnectionSerializationFlags .ALL ))
120
123
@@ -125,26 +128,29 @@ def get_active_settings(self):
125
128
return dict (con .to_dbus (NM .ConnectionSerializationFlags .ALL ))
126
129
127
130
def configure (self , data ):
128
- lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
131
+ lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
129
132
if lg_con :
130
133
self ._delete_connection (lg_con )
131
- data ['connection' ].update ({
132
- 'id' : f"labgrid-{ self ._interface } " ,
133
- 'autoconnect' : False ,
134
- 'interface-name' : self ._interface ,
135
- })
134
+ data ["connection" ].update (
135
+ {
136
+ "id" : f"labgrid-{ self ._interface } " ,
137
+ "autoconnect" : False ,
138
+ "interface-name" : self ._interface ,
139
+ }
140
+ )
136
141
con = connection_from_dict (data )
137
142
138
143
future = Future ()
144
+
139
145
def cb (dev , res , error ):
140
146
assert error is None
141
147
try :
142
- res = nm .add_and_activate_connection_finish (res ) # pylint: disable=possibly-used-before-assignment
148
+ res = nm .add_and_activate_connection_finish (res ) # pylint: disable=possibly-used-before-assignment
143
149
future .set (res )
144
150
except Exception as e :
145
151
future .set (e )
146
152
147
- nm .add_and_activate_connection_async ( # pylint: disable=possibly-used-before-assignment
153
+ nm .add_and_activate_connection_async ( # pylint: disable=possibly-used-before-assignment
148
154
con ,
149
155
self ._nm_dev ,
150
156
None , # specific_object
@@ -172,7 +178,7 @@ def wait_state(self, expected, timeout):
172
178
)
173
179
174
180
def disable (self ):
175
- lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
181
+ lg_con = nm .get_connection_by_id (f"labgrid-{ self ._interface } " ) # pylint: disable=possibly-used-before-assignment
176
182
if lg_con :
177
183
self ._delete_connection (lg_con )
178
184
@@ -182,58 +188,59 @@ def _flags_to_str(self, flags):
182
188
def _accesspoint_to_dict (self , ap ):
183
189
res = {}
184
190
185
- res [' flags' ] = self ._flags_to_str (ap .get_flags ())
186
- res [' wpa-flags' ] = self ._flags_to_str (ap .get_wpa_flags ())
187
- res [' rsn-flags' ] = self ._flags_to_str (ap .get_rsn_flags ())
188
- res [' bssid' ] = ap .get_bssid ()
189
- res [' ssid' ] = ap .get_ssid ().get_data ().decode (errors = ' surrogateescape' )
190
- res [' frequency' ] = ap .get_frequency ()
191
- res [' mode' ] = self ._flags_to_str (ap .get_mode ())
192
- res [' max-bitrate' ] = ap .get_max_bitrate ()
193
- res [' strength' ] = ap .get_strength ()
191
+ res [" flags" ] = self ._flags_to_str (ap .get_flags ())
192
+ res [" wpa-flags" ] = self ._flags_to_str (ap .get_wpa_flags ())
193
+ res [" rsn-flags" ] = self ._flags_to_str (ap .get_rsn_flags ())
194
+ res [" bssid" ] = ap .get_bssid ()
195
+ res [" ssid" ] = ap .get_ssid ().get_data ().decode (errors = " surrogateescape" )
196
+ res [" frequency" ] = ap .get_frequency ()
197
+ res [" mode" ] = self ._flags_to_str (ap .get_mode ())
198
+ res [" max-bitrate" ] = ap .get_max_bitrate ()
199
+ res [" strength" ] = ap .get_strength ()
194
200
195
201
return res
196
202
197
203
def get_state (self ):
198
204
state = {}
199
205
200
206
device = {}
201
- device [' capabilities' ] = self ._flags_to_str (self ._nm_dev .get_capabilities ())
202
- device [' device-type' ] = self ._flags_to_str (self ._nm_dev .get_device_type ())
203
- device [' state' ] = self ._flags_to_str (self ._nm_dev .get_state ())
204
- device [' state-reason' ] = self ._flags_to_str (self ._nm_dev .get_state_reason ())
205
- device [' hw-address' ] = self ._nm_dev .get_hw_address ()
206
- device [' driver' ] = self ._nm_dev .get_driver ()
207
- device [' udi' ] = self ._nm_dev .get_udi ()
208
- device [' mtu' ] = self ._nm_dev .get_mtu ()
209
- device [' vendor' ] = self ._nm_dev .get_vendor ()
210
- device [' product' ] = self ._nm_dev .get_product ()
211
- state [' device' ] = device
207
+ device [" capabilities" ] = self ._flags_to_str (self ._nm_dev .get_capabilities ())
208
+ device [" device-type" ] = self ._flags_to_str (self ._nm_dev .get_device_type ())
209
+ device [" state" ] = self ._flags_to_str (self ._nm_dev .get_state ())
210
+ device [" state-reason" ] = self ._flags_to_str (self ._nm_dev .get_state_reason ())
211
+ device [" hw-address" ] = self ._nm_dev .get_hw_address ()
212
+ device [" driver" ] = self ._nm_dev .get_driver ()
213
+ device [" udi" ] = self ._nm_dev .get_udi ()
214
+ device [" mtu" ] = self ._nm_dev .get_mtu ()
215
+ device [" vendor" ] = self ._nm_dev .get_vendor ()
216
+ device [" product" ] = self ._nm_dev .get_product ()
217
+ state [" device" ] = device
212
218
213
219
for name , ip_cfg in (
214
- ( ' ip4-config' , self ._nm_dev .get_ip4_config ()),
215
- ( ' ip6-config' , self ._nm_dev .get_ip6_config ()),
216
- ):
220
+ ( " ip4-config" , self ._nm_dev .get_ip4_config ()),
221
+ ( " ip6-config" , self ._nm_dev .get_ip6_config ()),
222
+ ):
217
223
if ip_cfg is None :
218
224
continue
219
225
cfg = {}
220
- cfg [' addresses' ] = []
226
+ cfg [" addresses" ] = []
221
227
for address in ip_cfg .get_addresses ():
222
- cfg [' addresses' ].append (f"{ address .get_address ()} /{ address .get_prefix ()} " )
223
- cfg [' gateway' ] = ip_cfg .get_gateway ()
228
+ cfg [" addresses" ].append (f"{ address .get_address ()} /{ address .get_prefix ()} " )
229
+ cfg [" gateway" ] = ip_cfg .get_gateway ()
224
230
state [name ] = cfg
225
231
226
232
try :
227
233
ap = self ._nm_dev .get_active_access_point ()
228
234
except AttributeError :
229
235
ap = None
230
236
if ap :
231
- state [' active-access-point' ] = self ._accesspoint_to_dict (ap )
237
+ state [" active-access-point" ] = self ._accesspoint_to_dict (ap )
232
238
233
239
return state
234
240
235
241
def request_scan (self ):
236
242
future = Future ()
243
+
237
244
def cb (dev , res , error ):
238
245
assert error is None
239
246
try :
@@ -251,7 +258,7 @@ def cb(dev, res, error):
251
258
future .wait () # we must wait, but don't need to return it here
252
259
253
260
def get_access_points (self , scan ):
254
- if scan is None : # automatically scan if needed
261
+ if scan is None : # automatically scan if needed
255
262
age = NM .utils_get_timestamp_msec () - self ._nm_dev .get_last_scan ()
256
263
scan = bool (age > 30_000 )
257
264
@@ -275,80 +282,93 @@ def get_dhcpd_leases(self):
275
282
with open (f"/var/lib/NetworkManager/dnsmasq-{ self ._interface } .leases" ) as f :
276
283
for line in f :
277
284
line = line .strip ().split ()
278
- if line [3 ] == '*' :
285
+ if line [3 ] == "*" :
279
286
line [3 ] = None
280
- if line [4 ] == '*' :
287
+ if line [4 ] == "*" :
281
288
line [4 ] = None
282
- leases .append ({
283
- 'expire' : int (line [0 ]),
284
- 'mac' : line [1 ],
285
- 'ip' : line [2 ],
286
- 'hostname' : line [3 ],
287
- 'id' : line [4 ],
288
- })
289
+ leases .append (
290
+ {
291
+ "expire" : int (line [0 ]),
292
+ "mac" : line [1 ],
293
+ "ip" : line [2 ],
294
+ "hostname" : line [3 ],
295
+ "id" : line [4 ],
296
+ }
297
+ )
289
298
return leases
290
299
291
- if getattr (NM .Client , '__gtype__' , None ):
300
+
301
+ if getattr (NM .Client , "__gtype__" , None ):
292
302
# hide this from sphinx autodoc
293
303
bl = BackgroundLoop ()
294
304
bl .start ()
295
305
nm = bl .block_on (NM .Client .new , None )
296
306
297
307
_nmdevs = {}
298
308
309
+
299
310
def _get_nmdev (interface ):
300
311
if interface not in _nmdevs :
301
312
_nmdevs [interface ] = NMDev (interface )
302
313
return _nmdevs [interface ]
303
314
315
+
304
316
def handle_configure (interface , settings ):
305
317
nmdev = _get_nmdev (interface )
306
318
return nmdev .configure (settings )
307
319
320
+
308
321
def handle_wait_state (interface , expected , timeout = 60 ):
309
322
nmdev = _get_nmdev (interface )
310
323
return nmdev .wait_state (expected , timeout )
311
324
325
+
312
326
def handle_disable (interface ):
313
327
nmdev = _get_nmdev (interface )
314
328
return nmdev .disable ()
315
329
330
+
316
331
def handle_get_active_settings (interface ):
317
332
nmdev = _get_nmdev (interface )
318
333
return nmdev .get_active_settings ()
319
334
335
+
320
336
def handle_get_settings (interface ):
321
337
nmdev = _get_nmdev (interface )
322
338
return nmdev .get_settings ()
323
339
340
+
324
341
def handle_get_state (interface ):
325
342
nmdev = _get_nmdev (interface )
326
343
return nmdev .get_state ()
327
344
345
+
328
346
def handle_get_dhcpd_leases (interface ):
329
347
nmdev = _get_nmdev (interface )
330
348
return nmdev .get_dhcpd_leases ()
331
349
350
+
332
351
def handle_request_scan (interface ):
333
352
nmdev = _get_nmdev (interface )
334
353
return nmdev .request_scan ()
335
354
355
+
336
356
def handle_get_access_points (interface , scan = None ):
337
357
nmdev = _get_nmdev (interface )
338
358
return nmdev .get_access_points (scan )
339
359
340
360
341
361
methods = {
342
362
# basic
343
- ' configure' : handle_configure ,
344
- ' wait_state' : handle_wait_state ,
345
- ' disable' : handle_disable ,
346
- ' get_active_settings' : handle_get_active_settings ,
347
- ' get_settings' : handle_get_settings ,
348
- ' get_state' : handle_get_state ,
363
+ " configure" : handle_configure ,
364
+ " wait_state" : handle_wait_state ,
365
+ " disable" : handle_disable ,
366
+ " get_active_settings" : handle_get_active_settings ,
367
+ " get_settings" : handle_get_settings ,
368
+ " get_state" : handle_get_state ,
349
369
# dhcpd
350
- ' get_dhcpd_leases' : handle_get_dhcpd_leases ,
370
+ " get_dhcpd_leases" : handle_get_dhcpd_leases ,
351
371
# wireless
352
- ' request_scan' : handle_request_scan ,
353
- ' get_access_points' : handle_get_access_points ,
372
+ " request_scan" : handle_request_scan ,
373
+ " get_access_points" : handle_get_access_points ,
354
374
}
0 commit comments