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,60 @@ 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
+ if ap .get_ssid ():
196
+ res ["ssid" ] = ap .get_ssid ().get_data ().decode (errors = "surrogateescape" )
197
+ res ["frequency" ] = ap .get_frequency ()
198
+ res ["mode" ] = self ._flags_to_str (ap .get_mode ())
199
+ res ["max-bitrate" ] = ap .get_max_bitrate ()
200
+ res ["strength" ] = ap .get_strength ()
194
201
195
202
return res
196
203
197
204
def get_state (self ):
198
205
state = {}
199
206
200
207
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
208
+ device [" capabilities" ] = self ._flags_to_str (self ._nm_dev .get_capabilities ())
209
+ device [" device-type" ] = self ._flags_to_str (self ._nm_dev .get_device_type ())
210
+ device [" state" ] = self ._flags_to_str (self ._nm_dev .get_state ())
211
+ device [" state-reason" ] = self ._flags_to_str (self ._nm_dev .get_state_reason ())
212
+ device [" hw-address" ] = self ._nm_dev .get_hw_address ()
213
+ device [" driver" ] = self ._nm_dev .get_driver ()
214
+ device [" udi" ] = self ._nm_dev .get_udi ()
215
+ device [" mtu" ] = self ._nm_dev .get_mtu ()
216
+ device [" vendor" ] = self ._nm_dev .get_vendor ()
217
+ device [" product" ] = self ._nm_dev .get_product ()
218
+ state [" device" ] = device
212
219
213
220
for name , ip_cfg in (
214
- ( ' ip4-config' , self ._nm_dev .get_ip4_config ()),
215
- ( ' ip6-config' , self ._nm_dev .get_ip6_config ()),
216
- ):
221
+ ( " ip4-config" , self ._nm_dev .get_ip4_config ()),
222
+ ( " ip6-config" , self ._nm_dev .get_ip6_config ()),
223
+ ):
217
224
if ip_cfg is None :
218
225
continue
219
226
cfg = {}
220
- cfg [' addresses' ] = []
227
+ cfg [" addresses" ] = []
221
228
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 ()
229
+ cfg [" addresses" ].append (f"{ address .get_address ()} /{ address .get_prefix ()} " )
230
+ cfg [" gateway" ] = ip_cfg .get_gateway ()
224
231
state [name ] = cfg
225
232
226
233
try :
227
234
ap = self ._nm_dev .get_active_access_point ()
228
235
except AttributeError :
229
236
ap = None
230
237
if ap :
231
- state [' active-access-point' ] = self ._accesspoint_to_dict (ap )
238
+ state [" active-access-point" ] = self ._accesspoint_to_dict (ap )
232
239
233
240
return state
234
241
235
242
def request_scan (self ):
236
243
future = Future ()
244
+
237
245
def cb (dev , res , error ):
238
246
assert error is None
239
247
try :
@@ -251,7 +259,7 @@ def cb(dev, res, error):
251
259
future .wait () # we must wait, but don't need to return it here
252
260
253
261
def get_access_points (self , scan ):
254
- if scan is None : # automatically scan if needed
262
+ if scan is None : # automatically scan if needed
255
263
age = NM .utils_get_timestamp_msec () - self ._nm_dev .get_last_scan ()
256
264
scan = bool (age > 30_000 )
257
265
@@ -275,80 +283,93 @@ def get_dhcpd_leases(self):
275
283
with open (f"/var/lib/NetworkManager/dnsmasq-{ self ._interface } .leases" ) as f :
276
284
for line in f :
277
285
line = line .strip ().split ()
278
- if line [3 ] == '*' :
286
+ if line [3 ] == "*" :
279
287
line [3 ] = None
280
- if line [4 ] == '*' :
288
+ if line [4 ] == "*" :
281
289
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
- })
290
+ leases .append (
291
+ {
292
+ "expire" : int (line [0 ]),
293
+ "mac" : line [1 ],
294
+ "ip" : line [2 ],
295
+ "hostname" : line [3 ],
296
+ "id" : line [4 ],
297
+ }
298
+ )
289
299
return leases
290
300
291
- if getattr (NM .Client , '__gtype__' , None ):
301
+
302
+ if getattr (NM .Client , "__gtype__" , None ):
292
303
# hide this from sphinx autodoc
293
304
bl = BackgroundLoop ()
294
305
bl .start ()
295
306
nm = bl .block_on (NM .Client .new , None )
296
307
297
308
_nmdevs = {}
298
309
310
+
299
311
def _get_nmdev (interface ):
300
312
if interface not in _nmdevs :
301
313
_nmdevs [interface ] = NMDev (interface )
302
314
return _nmdevs [interface ]
303
315
316
+
304
317
def handle_configure (interface , settings ):
305
318
nmdev = _get_nmdev (interface )
306
319
return nmdev .configure (settings )
307
320
321
+
308
322
def handle_wait_state (interface , expected , timeout = 60 ):
309
323
nmdev = _get_nmdev (interface )
310
324
return nmdev .wait_state (expected , timeout )
311
325
326
+
312
327
def handle_disable (interface ):
313
328
nmdev = _get_nmdev (interface )
314
329
return nmdev .disable ()
315
330
331
+
316
332
def handle_get_active_settings (interface ):
317
333
nmdev = _get_nmdev (interface )
318
334
return nmdev .get_active_settings ()
319
335
336
+
320
337
def handle_get_settings (interface ):
321
338
nmdev = _get_nmdev (interface )
322
339
return nmdev .get_settings ()
323
340
341
+
324
342
def handle_get_state (interface ):
325
343
nmdev = _get_nmdev (interface )
326
344
return nmdev .get_state ()
327
345
346
+
328
347
def handle_get_dhcpd_leases (interface ):
329
348
nmdev = _get_nmdev (interface )
330
349
return nmdev .get_dhcpd_leases ()
331
350
351
+
332
352
def handle_request_scan (interface ):
333
353
nmdev = _get_nmdev (interface )
334
354
return nmdev .request_scan ()
335
355
356
+
336
357
def handle_get_access_points (interface , scan = None ):
337
358
nmdev = _get_nmdev (interface )
338
359
return nmdev .get_access_points (scan )
339
360
340
361
341
362
methods = {
342
363
# 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 ,
364
+ " configure" : handle_configure ,
365
+ " wait_state" : handle_wait_state ,
366
+ " disable" : handle_disable ,
367
+ " get_active_settings" : handle_get_active_settings ,
368
+ " get_settings" : handle_get_settings ,
369
+ " get_state" : handle_get_state ,
349
370
# dhcpd
350
- ' get_dhcpd_leases' : handle_get_dhcpd_leases ,
371
+ " get_dhcpd_leases" : handle_get_dhcpd_leases ,
351
372
# wireless
352
- ' request_scan' : handle_request_scan ,
353
- ' get_access_points' : handle_get_access_points ,
373
+ " request_scan" : handle_request_scan ,
374
+ " get_access_points" : handle_get_access_points ,
354
375
}
0 commit comments