ns2 0.2.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. ns2/__init__.py +0 -0
  2. ns2/core.py +0 -0
  3. ns2/dbus/__init__.py +0 -0
  4. ns2/dbus/dbus.py +13 -0
  5. ns2/lib/__init__.py +0 -0
  6. ns2/lib/accounts.py +130 -0
  7. ns2/lib/commands.py +32 -0
  8. ns2/lib/firewalld.py +167 -0
  9. ns2/lib/introspection/org.fedoraproject.FirewallD1.config.xml +3 -0
  10. ns2/lib/introspection/org.fedoraproject.FirewallD1.xml +763 -0
  11. ns2/lib/introspection/org.freedesktop.NetworkManager.AccessPoint.xml +106 -0
  12. ns2/lib/introspection/org.freedesktop.NetworkManager.AgentManager.xml +43 -0
  13. ns2/lib/introspection/org.freedesktop.NetworkManager.Checkpoint.xml +36 -0
  14. ns2/lib/introspection/org.freedesktop.NetworkManager.Connection.Active.xml +185 -0
  15. ns2/lib/introspection/org.freedesktop.NetworkManager.DHCP4Config.xml +21 -0
  16. ns2/lib/introspection/org.freedesktop.NetworkManager.DHCP6Config.xml +20 -0
  17. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Adsl.xml +21 -0
  18. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bluetooth.xml +36 -0
  19. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bond.xml +40 -0
  20. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Bridge.xml +41 -0
  21. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Dummy.xml +20 -0
  22. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Generic.xml +27 -0
  23. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Hsr.xml +51 -0
  24. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.IPTunnel.xml +107 -0
  25. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Infiniband.xml +31 -0
  26. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Ipvlan.xml +38 -0
  27. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Loopback.xml +8 -0
  28. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Lowpan.xml +27 -0
  29. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Macsec.xml +109 -0
  30. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Macvlan.xml +39 -0
  31. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Modem.xml +62 -0
  32. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.xml +34 -0
  33. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsBridge.xml +21 -0
  34. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsInterface.xml +11 -0
  35. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.OvsPort.xml +21 -0
  36. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Ppp.xml +11 -0
  37. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Statistics.xml +35 -0
  38. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Team.xml +48 -0
  39. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Tun.xml +65 -0
  40. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Veth.xml +18 -0
  41. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vlan.xml +45 -0
  42. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vrf.xml +18 -0
  43. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Vxlan.xml +139 -0
  44. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WiMax.xml +109 -0
  45. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WifiP2P.xml +76 -0
  46. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.WireGuard.xml +38 -0
  47. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wired.xml +53 -0
  48. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wireless.xml +131 -0
  49. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.Wpan.xml +20 -0
  50. ns2/lib/introspection/org.freedesktop.NetworkManager.Device.xml +407 -0
  51. ns2/lib/introspection/org.freedesktop.NetworkManager.DnsManager.xml +40 -0
  52. ns2/lib/introspection/org.freedesktop.NetworkManager.IP4Config.xml +125 -0
  53. ns2/lib/introspection/org.freedesktop.NetworkManager.IP6Config.xml +95 -0
  54. ns2/lib/introspection/org.freedesktop.NetworkManager.PPP.xml +34 -0
  55. ns2/lib/introspection/org.freedesktop.NetworkManager.SecretAgent.xml +94 -0
  56. ns2/lib/introspection/org.freedesktop.NetworkManager.Settings.Connection.xml +224 -0
  57. ns2/lib/introspection/org.freedesktop.NetworkManager.Settings.xml +233 -0
  58. ns2/lib/introspection/org.freedesktop.NetworkManager.VPN.Connection.xml +42 -0
  59. ns2/lib/introspection/org.freedesktop.NetworkManager.VPN.Plugin.xml +204 -0
  60. ns2/lib/introspection/org.freedesktop.NetworkManager.WiMax.Nsp.xml +35 -0
  61. ns2/lib/introspection/org.freedesktop.NetworkManager.WifiP2PPeer.xml +91 -0
  62. ns2/lib/introspection/org.freedesktop.NetworkManager.xml +598 -0
  63. ns2/lib/lib.py +0 -0
  64. ns2/lib/network_delay.py +92 -0
  65. ns2/lib/networking.py +528 -0
  66. ns2/lib/ntl.py +188 -0
  67. ns2/lib/pam_client.py +37 -0
  68. ns2/lib/ping_data_collector.py +37 -0
  69. ns2/lib/snmp.py +511 -0
  70. ns2/lib/socket.py +132 -0
  71. ns2/lib/socket_client.py +62 -0
  72. ns2/lib/systemd.py +151 -0
  73. ns2/lib/test.py +374 -0
  74. ns2/lib/udp_client.py +227 -0
  75. ns2/lib/udp_server.py +167 -0
  76. ns2/snmp/__init__.py +0 -0
  77. ns2/snmp/ns_dbus_service.py +38 -0
  78. ns2/snmp/pam_interface.py +19 -0
  79. ns2/snmp/snmp_interface.py +66 -0
  80. ns2/ui/__init__.py +0 -0
  81. ns2/ui/assets/NOVUS_LOGO.svg +105 -0
  82. ns2/ui/assets/favicon.png +0 -0
  83. ns2/ui/firewalld_page.py +375 -0
  84. ns2/ui/fpga_page.py +24 -0
  85. ns2/ui/login.py +65 -0
  86. ns2/ui/main.py +200 -0
  87. ns2/ui/networking_page.py +406 -0
  88. ns2/ui/ntp.py +105 -0
  89. ns2/ui/root.py +31 -0
  90. ns2/ui/snmp_page.py +353 -0
  91. ns2/ui/terminal.py +65 -0
  92. ns2/ui/tests_page.py +116 -0
  93. ns2/ui/theme.py +25 -0
  94. ns2/utils.py +5 -0
  95. ns2-0.2.6.dist-info/METADATA +78 -0
  96. ns2-0.2.6.dist-info/RECORD +98 -0
  97. ns2-0.2.6.dist-info/WHEEL +4 -0
  98. ns2-0.2.6.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,92 @@
1
+
2
+ import requests
3
+ from bs4 import BeautifulSoup as bs
4
+ from datetime import datetime, timezone
5
+ import numpy as np
6
+ import sys
7
+
8
+ def calculate_last_50_jitter(delays):
9
+ delays = delays[-50:]
10
+ return np.sum(np.abs(np.diff(delays)))/(len(delays)-1)
11
+
12
+ def file_name_to_time(name):
13
+ timestamp_seconds = float(name.split("_")[0])
14
+ return datetime.fromtimestamp(timestamp_seconds, timezone.utc)
15
+
16
+ def get_latest_data(references :list[str]):
17
+
18
+ ts = {}
19
+
20
+ for r in references:
21
+
22
+ ts[r["href"]] = r["href"].split("_")[0]
23
+
24
+ return max(ts, key=ts.get)
25
+
26
+
27
+ def get_files_to_view():
28
+ host = "http://10.1.10.96:8000"
29
+ try:
30
+ rsp = requests.get(host, timeout=0.1)
31
+ soup = bs(rsp.content, "html.parser")
32
+ references = soup.find_all("a", href=True)
33
+ print(references)
34
+ return references
35
+ except Exception as e:
36
+ print(e)
37
+ raise
38
+
39
+
40
+
41
+ def get_data_by_name(name :str):
42
+ host = "http://10.1.10.96:8000"
43
+
44
+ try:
45
+ rsp = requests.get(host+"/"+name)
46
+ except Exception as e:
47
+ print(e)
48
+ sys.exit()
49
+
50
+
51
+
52
+ lines = rsp.content.decode('utf-8').splitlines()
53
+
54
+ ts = []
55
+ delays = []
56
+ for i, line in enumerate(lines):
57
+ if i != 0:
58
+ values = line.split(",")
59
+ ts.append(float(values[0]))
60
+ delays.append(float(values[1]))
61
+
62
+ return file_name_to_time(name), ts, delays
63
+
64
+ def get_network_delay_data_locally():
65
+
66
+ host = "http://10.1.10.96:8000"
67
+
68
+ try:
69
+ rsp = requests.get(host)
70
+ except Exception as e:
71
+ print(e)
72
+ sys.exit()
73
+
74
+ #rsp = requests.get(host)
75
+ soup = bs(rsp.content, "html.parser")
76
+
77
+ references = soup.find_all("a", href=True) #["href"]
78
+ file_name = get_latest_data(references)
79
+ rsp = requests.get(host+"/"+file_name)
80
+
81
+ lines = rsp.content.decode('utf-8').splitlines()
82
+
83
+ ts = []
84
+ delays = []
85
+ for i, line in enumerate(lines):
86
+ if i != 0:
87
+ values = line.split(",")
88
+ ts.append(float(values[0]))
89
+ delays.append(float(values[1]))
90
+
91
+ return file_name_to_time(file_name), ts, delays
92
+
ns2/lib/networking.py ADDED
@@ -0,0 +1,528 @@
1
+
2
+ from dataclasses import asdict, field
3
+ from typing import List, Optional
4
+ from nicegui import ui, app, binding
5
+
6
+ from dbus_next.signature import Variant
7
+ from dbus_next.errors import DBusError
8
+ from dbus_next.aio.proxy_object import ProxyInterface
9
+ from dbus_next.aio import MessageBus
10
+ from dbus_next import Message
11
+
12
+ from ns.lib.firewalld import formatListToString
13
+ from ns.utils import INTROSPECTION_DIR
14
+
15
+ # ====================================================================
16
+ # data classes
17
+ # ====================================================================
18
+
19
+ class ConnectionDetails:
20
+ Id: Optional[str] = ''
21
+ Permissions: Optional[list[str]] = None
22
+ Timestamp: Optional[int] = 0
23
+ Type: Optional[str] = ''
24
+ Uuid: Optional[str] = ''
25
+
26
+ @binding.bindable_dataclass
27
+ class IpAddress:
28
+ Address: Optional[str] = None
29
+ Prefix: Optional[int] = None
30
+
31
+ @binding.bindable_dataclass
32
+ class DnsServer:
33
+ Server: Optional[str] = ''
34
+
35
+ @binding.bindable_dataclass
36
+ class IpRoute:
37
+ Dest: Optional[str] = None
38
+ Prefix: Optional[int] = None
39
+ NextHop: Optional[str] = None
40
+ Metric: Optional[int] = None
41
+
42
+
43
+ @binding.bindable_dataclass
44
+ class Ipv4v6:
45
+ AddressData: Optional[list[IpAddress]] = field(default_factory=list) # used
46
+ #Addresses: Optional[list[list[int]]] = field(default_factory=list) # not used
47
+ #Dns: Optional[list[list[int]]] = field(default_factory=list) # not used
48
+ DnsData: Optional[list[DnsServer]] = field(default_factory=list) # used
49
+ DnsSearch: Optional[list[DnsServer]] = field(default_factory=list) # used
50
+ Gateway: Optional[str] = '' # used
51
+ IgnoreAutoDns: Optional[bool] = False # used
52
+ IgnoreAutoRoutes: Optional[bool] = False # used
53
+ Method: Optional[str] = '' # used
54
+ RouteData: Optional[list[IpRoute]] = field(default_factory=list) # used
55
+ #Routes: Optional[list[list[int]]] = field(default_factory=list) # not used
56
+
57
+
58
+ @binding.bindable_dataclass
59
+ class Settings:
60
+ Connection: Optional[ConnectionDetails] = None
61
+ Ipv4: Optional[Ipv4v6] = None
62
+ Ipv6: Optional[Ipv4v6] = None
63
+ Proxy: Optional[str] = ''
64
+
65
+
66
+ @binding.bindable_dataclass
67
+ class Device:
68
+ Proxy: Optional[ProxyInterface] = None
69
+ Path: Optional[str] = ''
70
+ ActiveConnectionPath: Optional[str] = ''
71
+ HardwareAddress: Optional[str] = ''
72
+ Flags: Optional[int] = None
73
+ Carrier: Optional[str] = ''
74
+ State: Optional[int] = True
75
+ DeviceState: Optional[str] = ''
76
+ Ip4ConfigPath : Optional[str] = ''
77
+ Ip6ConfigPath : Optional[str] = ''
78
+
79
+
80
+ @binding.bindable_dataclass
81
+ class InterfaceData:
82
+ Name: Optional[str] = ''
83
+ HardwareAddress: Optional[str] = ''
84
+ StateString: Optional[str] = ''
85
+ StateNumber: Optional[int] = 0
86
+ Active: Optional[bool] = False
87
+ Status: Optional[str] = ''
88
+ Carrier: Optional[str] = ''
89
+ Ip4: Optional[str] = ''
90
+ Ip6: Optional[str] = ''
91
+ AutoConnect: Optional[bool] = False
92
+ _dev_path: Optional[str] = ''
93
+ _act_con_path: Optional[str] = ''
94
+
95
+
96
+
97
+ # ====================================================================
98
+ # Proxies
99
+ # ====================================================================
100
+ def GetNetworkManager(bus: MessageBus) -> ProxyInterface:
101
+ file_name = 'org.freedesktop.NetworkManager.xml'
102
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
103
+ introspection = f.read()
104
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager', introspection)
105
+ return obj.get_interface('org.freedesktop.NetworkManager')
106
+
107
+
108
+ def GetDevice(bus: MessageBus, path :str) -> ProxyInterface:
109
+ file_name = 'org.freedesktop.NetworkManager.Device.xml'
110
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
111
+ introspection = f.read()
112
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
113
+ return obj.get_interface('org.freedesktop.NetworkManager.Device')
114
+
115
+
116
+ def GetActiveConnection(bus: MessageBus, path :str) -> ProxyInterface:
117
+ file_name = 'org.freedesktop.NetworkManager.Connection.Active.xml'
118
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
119
+ introspection = f.read()
120
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
121
+ return obj.get_interface('org.freedesktop.NetworkManager.Connection.Active')
122
+
123
+
124
+ def GetIp4Config(bus: MessageBus, path :str) -> ProxyInterface:
125
+ file_name = 'org.freedesktop.NetworkManager.IP4Config.xml'
126
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
127
+ introspection = f.read()
128
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
129
+ return obj.get_interface('org.freedesktop.NetworkManager.IP4Config')
130
+
131
+ def GetIp6Config(bus: MessageBus, path :str) -> ProxyInterface:
132
+ file_name = 'org.freedesktop.NetworkManager.IP6Config.xml'
133
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
134
+ introspection = f.read()
135
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
136
+ return obj.get_interface('org.freedesktop.NetworkManager.IP6Config')
137
+
138
+
139
+ def GetSettingsManager(bus: MessageBus, path :str) -> ProxyInterface:
140
+ file_name = 'org.freedesktop.NetworkManager.Settings.xml'
141
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
142
+ introspection = f.read()
143
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
144
+ return obj.get_interface('org.freedesktop.NetworkManager.Settings')
145
+
146
+ def GetConnection(bus: MessageBus, path : str)-> ProxyInterface:
147
+ file_name = 'org.freedesktop.NetworkManager.Settings.Connection.xml'
148
+ with open(str(INTROSPECTION_DIR /file_name), "r") as f:
149
+ introspection = f.read()
150
+ obj = bus.get_proxy_object('org.freedesktop.NetworkManager', path, introspection)
151
+ return obj.get_interface('org.freedesktop.NetworkManager.Settings.Connection')
152
+
153
+
154
+ async def GetConnectionFromDevice(bus: MessageBus, device :ProxyInterface) -> ProxyInterface:
155
+ active_connection_path = await device.get_active_connection()
156
+ if len(active_connection_path) > 1:
157
+ activeConnection = GetActiveConnection(bus, active_connection_path)
158
+ connection_path = await activeConnection.get_connection()
159
+ return GetConnection(bus, connection_path)
160
+
161
+
162
+ # ====================================================================
163
+ # Getters and Setters
164
+ # ====================================================================
165
+
166
+ async def GetInterfaceData(bus: MessageBus, nm: ProxyInterface, iface :str) -> InterfaceData:
167
+ i = InterfaceData()
168
+ i._dev_path = await nm.call_get_device_by_ip_iface(iface)
169
+ dev = GetDevice(bus, i._dev_path)
170
+ i.Name = iface
171
+ i.HardwareAddress = await dev.get_hw_address()
172
+ i.StateNumber = await dev.get_state()
173
+ i.StateString = processDeviceState(i.StateNumber)
174
+ i.Active = True if i.StateNumber == 100 else False
175
+ i.Carrier = processInterfaceFlags(await dev.get_interface_flags())
176
+
177
+ ip4_config_path = await dev.get_ip4_config()
178
+ ip6_config_path = await dev.get_ip6_config()
179
+
180
+ i._act_con_path = await dev.get_active_connection()
181
+
182
+ if len(i._act_con_path) > 1:
183
+ activeConnection = GetActiveConnection(bus, i._act_con_path)
184
+ connection_path = await activeConnection.get_connection()
185
+ connection = GetConnection(bus, connection_path)
186
+ settings = await connection.call_get_settings()
187
+ i.AutoConnect = settings['connection'].get('autoconnect', Variant('b', True)).value
188
+
189
+
190
+ if len(ip4_config_path) > 1:
191
+ ip4Config = GetIp4Config(bus, ip4_config_path)
192
+ ip6Config = GetIp6Config(bus, ip6_config_path)
193
+ ip4AddressData = await ip4Config.get_address_data()
194
+ ip6AddressData = await ip6Config.get_address_data()
195
+ i.Ip4 = addressDataToString(ip4AddressData)
196
+ i.Ip6 = addressDataToString(ip6AddressData)
197
+
198
+ i.Status = combineAddresses(ip4AddressData, ip6AddressData)
199
+
200
+ return i
201
+
202
+
203
+ async def GetSettings(bus: MessageBus, dev: ProxyInterface) -> dict:
204
+ active_connection_path = await dev.get_active_connection()
205
+ if len(active_connection_path) > 1:
206
+ activeConnection = GetActiveConnection(bus, active_connection_path)
207
+ connection_path = await activeConnection.get_connection()
208
+ connection = GetConnection(bus, connection_path)
209
+ connection_settings = await connection.call_get_settings()
210
+ return connection_settings
211
+
212
+
213
+
214
+
215
+
216
+ def GetIp(version: str, settings: dict) -> Ipv4v6:
217
+
218
+ ip = Ipv4v6()
219
+
220
+ ip_settings = settings.get(version)
221
+
222
+ ip_settings: dict
223
+ if ip_settings:
224
+ addrData = ip_settings.get('address-data')
225
+ if addrData:
226
+ for addr in addrData.value:
227
+ a = addr.get('address').value
228
+ p = addr.get('prefix').value
229
+ ip.AddressData.append(IpAddress(a, p))
230
+
231
+ dnsData = ip_settings.get('dns-data')
232
+ if dnsData:
233
+ for dns in dnsData.value:
234
+ ip.DnsData.append(DnsServer(dns))
235
+
236
+ dnsSearch = ip_settings.get('dns-search')
237
+ if dnsSearch:
238
+ for dns in dnsSearch.value:
239
+ ip.DnsSearch.append(DnsServer(dns))
240
+
241
+ gateway = ip_settings.get('gateway')
242
+ if gateway:
243
+ ip.Gateway = gateway.value
244
+
245
+ ignoreAutoDns = ip_settings.get('ignore-auto-dns')
246
+ if ignoreAutoDns:
247
+ ip.IgnoreAutoDns = ignoreAutoDns.value
248
+
249
+
250
+ ignoreAutoRoutes = ip_settings.get('ignore-auto-routes')
251
+ if ignoreAutoRoutes:
252
+ ip.IgnoreAutoRoutes = ignoreAutoRoutes.value
253
+
254
+ method = ip_settings.get('method')
255
+ if method:
256
+ ip.Method = method.value
257
+
258
+
259
+ routeData = ip_settings.get('route-data')
260
+ if routeData:
261
+ for route in routeData.value:
262
+ a = route.get('dest').value
263
+ p = route.get('prefix').value
264
+ n = route.get('next-hop').value
265
+ m = route.get('metric').value
266
+ ip.RouteData.append(IpRoute(a, p, n, m))
267
+
268
+ return ip
269
+
270
+
271
+
272
+ def SetIp(ip: Ipv4v6, version: str, settings :dict) -> dict:
273
+
274
+ #remove depreciated
275
+ settings[version].pop("addresses", None)
276
+ settings[version].pop("dns", None)
277
+ settings[version].pop("routes", None)
278
+
279
+ # address data
280
+ settings[version]['address-data'] = addresses_to_dbus(ip.AddressData)
281
+ # dns data
282
+ settings[version]['dns-data'] = dns_to_dbus(ip.DnsData)
283
+ # dns search
284
+ settings[version]['dns-search'] = dns_to_dbus(ip.DnsSearch)
285
+ # gateway
286
+ settings[version]['gateway'] = Variant('s', ip.Gateway)
287
+ # ignore auto dns
288
+ settings[version]['ignore-auto-dns'] = Variant('b', ( ip.IgnoreAutoDns))
289
+ # ignore auto routes
290
+ settings[version]['ignore-auto-routes'] = Variant('b', ( ip.IgnoreAutoRoutes))
291
+ # method
292
+ settings[version]['method'] = Variant('s', ip.Method)
293
+ #route data
294
+ settings[version]['route-data'] = route_to_dbus(ip.RouteData)
295
+
296
+ return settings
297
+
298
+
299
+
300
+
301
+ def addresses_to_dbus(ip :list[IpAddress]):
302
+ return Variant('aa{sv}', [{'address': Variant('s', i.Address), 'prefix': Variant('u', int(i.Prefix))} for i in ip])
303
+
304
+ def dns_to_dbus(dns :list[DnsServer]):
305
+ return Variant('as', [d.Server for d in dns])
306
+
307
+ def route_to_dbus(route: list[IpRoute]):
308
+ return Variant('aa{sv}', [{'dest': Variant('s', r.Dest),
309
+ 'prefix': Variant('u', int(r.Prefix)),
310
+ 'next-hop': Variant('s', r.NextHop),
311
+ 'metric': Variant('u', int(r.Metric)),
312
+ } for r in route])
313
+
314
+
315
+
316
+ def ApplyModes(version :str, settings :dict) -> dict:
317
+
318
+ if settings[version]['method'].value == 'auto':
319
+ settings[version].pop('gateway', None)
320
+
321
+ if settings[version]['method'].value == 'disabled':
322
+ settings[version].pop('gateway', None)
323
+
324
+ return settings
325
+
326
+
327
+
328
+
329
+
330
+ def addressDataToAddress(addressdata: list[dict]) -> list:
331
+ formatted = []
332
+ for addr in addressdata:
333
+ address = addr.get('address')
334
+ prefix = addr.get('prefix')
335
+ if address and prefix:
336
+ formatted.append(f"{address.value}/{prefix.value}")
337
+ return formatted
338
+
339
+
340
+ def formatAddressString(addresses: list[str]) -> str:
341
+ return ', '.join(addresses) if addresses else ''
342
+
343
+ def formatInterfaceRow(interface :str, addresses: str):
344
+ return {"name": interface, "addresses": addresses}
345
+
346
+
347
+ def addressDataToString(addressData):
348
+ addresses = []
349
+ addresses.extend(addressDataToAddress(addressData))
350
+ if len(addresses) == 0:
351
+ return "disabled"
352
+ return formatAddressString(addresses)
353
+
354
+ def dnsDataToString(dnsData):
355
+ return formatAddressString(dnsData)
356
+
357
+ def processDeviceState(state: int) -> str:
358
+ state_dict = {0: ["UNKNOWN", "the device's state is unknown"],
359
+ 10: ["UNMANAGED", "the device is recognized, but not managed by NetworkManager"],
360
+ 20: ["UNAVAILABLE", "the device is managed by NetworkManager, but is not available for use. Reasons may include the wireless switched off, missing firmware, no ethernet carrier, missing supplicant or modem manager, etc."],
361
+ 30: ["DISCONNECTED", "the device can be activated, but is currently idle and not connected to a network."],
362
+ 40: ["PREPARE", "the device is preparing the connection to the network. This may include operations like changing the MAC address, setting physical link properties, and anything else required to connect to the requested network."],
363
+ 50: ["CONFIG", "the device is connecting to the requested network. This may include operations like associating with the Wi-Fi AP, dialing the modem, connecting to the remote Bluetooth device, etc."],
364
+ 60: ["NEED_AUTH", "the device requires more information to continue connecting to the requested network. This includes secrets like WiFi passphrases, login passwords, PIN codes, etc."],
365
+ 70: ["IP_CONFIG", "the device is requesting IPv4 and/or IPv6 addresses and routing information from the network."],
366
+ 80: ["IP_CHECK", "the device is checking whether further action is required for the requested network connection. This may include checking whether only local network access is available, whether a captive portal is blocking access to the Internet, etc."],
367
+ 90: ["SECONDARIES", "the device is waiting for a secondary connection (like a VPN) which must activated before the device can be activated"],
368
+ 100: ["ACTIVATED", "the device has a network connection, either local or global."],
369
+ 110: ["DEACTIVATING", "a disconnection from the current network connection was requested, and the device is cleaning up resources used for that connection. The network connection may still be valid."],
370
+ 120: ["FAILED", "the device failed to connect to the requested network and is cleaning up the connection request"]}
371
+ nmState = state_dict.get(state, "STATE NOT FOUND")
372
+ return nmState[0]
373
+
374
+
375
+ def processInterfaceFlags(flags: int) -> str:
376
+ NM_DEVICE_INTERFACE_FLAG_NONE= 0 # an alias for numeric zero, no flags set.
377
+ NM_DEVICE_INTERFACE_FLAG_UP= 0x1 # the interface is enabled from the administrative point of view. Corresponds to kernel IFF_UP.
378
+ NM_DEVICE_INTERFACE_FLAG_LOWER_UP= 0x2 # the physical link is up. Corresponds to kernel IFF_LOWER_UP.
379
+ NM_DEVICE_INTERFACE_FLAG_PROMISC= 0x4 # receive all packets. Corresponds to kernel IFF_PROMISC. Since: 1.32.
380
+ NM_DEVICE_INTERFACE_FLAG_CARRIER= 0x10000 # the interface has carrier. In most cases this is equal to the value of @NM_DEVICE_INTERFACE_FLAG_LOWER_UP. However some devices have a non-standard carrier detection mechanism.
381
+ NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED= 0x20000 # the flag to indicate device LLDP status. Since: 1.32.
382
+ """Convert interface flags to detailed status string"""
383
+
384
+ if flags == 0:
385
+ return "Interface disabled (no flags set)"
386
+
387
+ status = []
388
+
389
+ if flags & NM_DEVICE_INTERFACE_FLAG_UP:
390
+ status.append("administratively up")
391
+
392
+ if flags & NM_DEVICE_INTERFACE_FLAG_LOWER_UP:
393
+ status.append("physical link up")
394
+
395
+ if flags & NM_DEVICE_INTERFACE_FLAG_CARRIER:
396
+ status.append("carrier detected")
397
+
398
+ if flags & NM_DEVICE_INTERFACE_FLAG_PROMISC:
399
+ status.append("promiscuous mode")
400
+
401
+ if flags & NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED:
402
+ status.append("LLDP enabled")
403
+
404
+ if not status:
405
+ return f"Unknown flags: 0x{flags:x}"
406
+
407
+ return " | ".join(status)
408
+
409
+
410
+ def combineAddresses(ipv4AddressData, ipv6AddressData) -> str:
411
+
412
+ addresses = []
413
+ addresses.extend(addressDataToAddress(ipv4AddressData))
414
+ addresses.extend(addressDataToAddress(ipv6AddressData))
415
+ return formatAddressString(addresses)
416
+
417
+
418
+
419
+
420
+ async def GetDeviceFromInterface(bus: MessageBus, iface :str) -> Device:
421
+ nm = GetNetworkManager(bus)
422
+ device_path = await nm.call_get_device_by_ip_iface(iface)
423
+ device = GetDevice(bus, device_path)
424
+
425
+ hwaddr = await device.get_hw_address()
426
+ flags = await device.get_interface_flags()
427
+ carrier = processInterfaceFlags(flags)
428
+
429
+ state = await device.get_state()
430
+ deviceState = processDeviceState(state)
431
+ ip4_config_path = await device.get_ip4_config()
432
+ ip4_config_path = await device.get_ip6_config()
433
+ active_connection_path = await device.get_active_connection()
434
+
435
+ myDevice = Device(
436
+ Proxy = device,
437
+ Path = device_path,
438
+ ActiveConnectionPath = active_connection_path,
439
+ HardwareAddress = hwaddr,
440
+ Flags = flags,
441
+ Carrier = carrier,
442
+ State = state,
443
+ DeviceState = deviceState,
444
+ Ip4ConfigPath = ip4_config_path,
445
+ Ip6ConfigPath = ip4_config_path)
446
+
447
+ return myDevice
448
+
449
+
450
+
451
+ def isAutoconnect(settings :dict) -> bool:
452
+ return settings['connection']
453
+
454
+
455
+
456
+ async def GetInterfaces(bus: MessageBus) -> list:
457
+
458
+ interfaces = []
459
+
460
+ nm = GetNetworkManager(bus)
461
+
462
+ devices_paths = await nm.call_get_devices()
463
+
464
+ for p in devices_paths:
465
+ dev = GetDevice(bus, p)
466
+ interfaces.append(await dev.get_interface())
467
+
468
+ return interfaces
469
+
470
+ async def GetInterfacesAndAddresses(bus: MessageBus) -> list:
471
+
472
+ rows = []
473
+
474
+ nm = GetNetworkManager(bus)
475
+
476
+ device_paths = await nm.call_get_devices()
477
+
478
+ for devicePath in device_paths:
479
+
480
+ device = GetDevice(bus, devicePath)
481
+ interface = await device.get_interface()
482
+ hwaddr = await device.get_hw_address()
483
+ state = await device.get_state()
484
+ processDeviceState
485
+ ip4_config_path = await device.get_ip4_config()
486
+ ip6_config_path = await device.get_ip6_config()
487
+ if len(ip4_config_path) > 1:
488
+
489
+ ip4Config = GetIp4Config(bus, ip4_config_path)
490
+ ip6Config = GetIp6Config(bus, ip6_config_path)
491
+
492
+ ip4AddressData = await ip4Config.get_address_data()
493
+ ip6AddressData = await ip6Config.get_address_data()
494
+
495
+ gw = []
496
+ ip4gw = await ip4Config.get_gateway()
497
+ if ip4gw:
498
+ gw.append(ip4gw)
499
+ ip6gw = await ip6Config.get_gateway()
500
+ if ip6gw:
501
+ gw.append(ip4gw)
502
+
503
+
504
+
505
+ rows.append({'name': interface,
506
+ 'addresses': combineAddresses(ip4AddressData, ip6AddressData),
507
+ 'state':processDeviceState(state),
508
+ 'gateway': formatListToString(gw),
509
+ 'hw address': hwaddr})
510
+
511
+ return rows
512
+
513
+
514
+ async def nm_call(bus: MessageBus, member: str, signature:str, body):
515
+
516
+ rsp = await bus.call(
517
+ Message(
518
+ destination='org.freedesktop.NetworkManager',
519
+ path='/org/freedesktop/NetworkManager',
520
+ interface='org.freedesktop.NetworkManager',
521
+ member=member,
522
+ signature=signature,
523
+ body=[body]
524
+ )
525
+ )
526
+
527
+ if rsp.body:
528
+ return rsp.body[0]