From 9af30d9e4e0a6114372cfe668e150ac48747c5ec Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 9 Apr 2022 14:23:08 +0200 Subject: [PATCH 01/80] Update example add-wifi-psk-connection-async.py Add -u UUID parameter and make it usable from other examples: - Pass the UUID to the function so it can be passed from another caller. - Return the DBus path of the created connection to the caller. - Use getLogger().info() instead of print() to allow to customize if we want the output of the local function shown when importing. --- .../async/add-wifi-psk-connection-async.py | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/async/add-wifi-psk-connection-async.py index 6703d5e..37f3eea 100755 --- a/examples/async/add-wifi-psk-connection-async.py +++ b/examples/async/add-wifi-psk-connection-async.py @@ -3,7 +3,7 @@ # # Example to create a new WiFi-PSK network connection profile: # -# $ add-wifi-psk-connection.py --help +# $ examples/async/add-wifi-psk-connection-async.py --help # usage: add-wifi-psk-connection.py [-h] [-c CONN_ID] [-s SSID] [-p PSK] # [-i INTERFACE_NAME] [-a] [--save] # @@ -12,6 +12,7 @@ # optional arguments: # -h, --help show this help message and exit # -c CONN_ID Connection Id +# -u UUID Connection UUID # -s SSID WiFi SSID # -p PSK WiFi PSK # -i INTERFACE_NAME WiFi device @@ -45,27 +46,32 @@ import asyncio import functools +import logging import pprint import sdbus -import uuid +from uuid import uuid4 from argparse import ArgumentParser, Namespace from sdbus_async.networkmanager import NetworkManagerSettings from sdbus_async.networkmanager import NetworkManagerConnectionProperties -async def add_wifi_psk_connection_profile_async(args: Namespace) -> None: - """Add a temporary (not yet saved) network connection profile""" +async def add_wifi_psk_connection_profile_async(args: Namespace) -> str: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info # If we add many connections passing the same id, things get messy. Check: if await NetworkManagerSettings().get_connections_by_id(args.conn_id): print(f'Connection "{args.conn_id}" exists, remove it first') print(f'Run: nmcli connection delete "{args.conn_id}"') - return + return "" properties: NetworkManagerConnectionProperties = { "connection": { "id": ("s", args.conn_id), - "uuid": ("s", str(uuid.uuid4())), + "uuid": ("s", str(args.uuid)), "type": ("s", "802-11-wireless"), "autoconnect": ("b", args.auto), }, @@ -87,23 +93,23 @@ async def add_wifi_psk_connection_profile_async(args: Namespace) -> None: if args.interface_name: properties["connection"]["interface-name"] = ("s", args.interface_name) - networkmanager_settings = NetworkManagerSettings() - if args.save: - await networkmanager_settings.add_connection(properties) - print("New connection profile created and saved, show it with:") - else: - await networkmanager_settings.add_connection_unsaved(properties) - print("New unsaved connection profile created, show it with:") - - print(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') - print("Settings used:") - functools.partial(pprint.pprint, sort_dicts=False)(properties) + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(properties) + created = "created and saved" if args.save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) p = ArgumentParser(description="Optional arguments have example values:") conn_id = "MyConnectionExample" p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") p.add_argument("-s", dest="ssid", default="CafeSSID", help="WiFi SSID") p.add_argument("-p", dest="psk", default="Coffee!!", help="WiFi PSK") p.add_argument("-i", dest="interface_name", default="", help="WiFi device") @@ -111,4 +117,6 @@ async def add_wifi_psk_connection_profile_async(args: Namespace) -> None: p.add_argument("--save", dest="save", action="store_true", help="Save") args = p.parse_args() sdbus.set_default_bus(sdbus.sd_bus_open_system()) - asyncio.run(add_wifi_psk_connection_profile_async(args)) + connection_dpath = asyncio.run(add_wifi_psk_connection_profile_async(args)) + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") From 097b5b9c92f05896918b501fcc4512d747476196 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 9 Apr 2022 19:02:51 +0200 Subject: [PATCH 02/80] Update example add-wifi-psk-connection.py (same change like for add-wifi-psk-connection-async.py): Add -u UUID parameter and make it usable from other examples: - Pass the UUID to the function so it can be passed from another caller. - Return the DBus path of the created connection to the caller. - Use getLogger().info() instead of print() to allow to customize if we want the output of the local function shown when importing. --- examples/block/add-wifi-psk-connection.py | 43 ++++++++++++++--------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/examples/block/add-wifi-psk-connection.py b/examples/block/add-wifi-psk-connection.py index e80e2de..df821bd 100755 --- a/examples/block/add-wifi-psk-connection.py +++ b/examples/block/add-wifi-psk-connection.py @@ -3,7 +3,7 @@ # # Example to create a new WiFi-PSK network connection profile: # -# $ add-wifi-psk-connection.py --help +# $ examples/block/add-wifi-psk-connection.py --help # usage: add-wifi-psk-connection.py [-h] [-c CONN_ID] [-s SSID] [-p PSK] # [-i INTERFACE_NAME] [-a] [--save] # @@ -12,6 +12,7 @@ # optional arguments: # -h, --help show this help message and exit # -c CONN_ID Connection Id +# -u UUID Connection UUID # -s SSID WiFi SSID # -p PSK WiFi PSK # -i INTERFACE_NAME WiFi device @@ -44,27 +45,32 @@ # -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) import functools +import logging import pprint import sdbus -import uuid +from uuid import uuid4 from argparse import ArgumentParser, Namespace from sdbus_block.networkmanager import NetworkManagerSettings from sdbus_block.networkmanager import NetworkManagerConnectionProperties -def add_wifi_psk_connection_profile(args: Namespace) -> None: - """Add a temporary (not yet saved) network connection profile""" +def add_wifi_psk_connection_profile(args: Namespace) -> str: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info # If we add many connections passing the same id, things get messy. Check: if NetworkManagerSettings().get_connections_by_id(args.conn_id): print(f'Connection "{args.conn_id}" exists, remove it first') print(f'Run: nmcli connection delete "{args.conn_id}"') - return + return "" properties: NetworkManagerConnectionProperties = { "connection": { "id": ("s", args.conn_id), - "uuid": ("s", str(uuid.uuid4())), + "uuid": ("s", str(args.uuid)), "type": ("s", "802-11-wireless"), "autoconnect": ("b", args.auto), }, @@ -86,22 +92,23 @@ def add_wifi_psk_connection_profile(args: Namespace) -> None: if args.interface_name: properties["connection"]["interface-name"] = ("s", args.interface_name) - if args.save: - NetworkManagerSettings().add_connection(properties) - print("New connection profile created and saved, show it with:") - else: - NetworkManagerSettings().add_connection_unsaved(properties) - print("New unsaved connection profile created, show it with:") - - print(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') - print("Settings used:") - functools.partial(pprint.pprint, sort_dicts=False)(properties) + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = addconnection(properties) + created = "created and saved" if args.save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) p = ArgumentParser(description="Optional arguments have example values:") conn_id = "MyConnectionExample" p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") p.add_argument("-s", dest="ssid", default="CafeSSID", help="WiFi SSID") p.add_argument("-p", dest="psk", default="Coffee!!", help="WiFi PSK") p.add_argument("-i", dest="interface_name", default="", help="WiFi device") @@ -109,4 +116,6 @@ def add_wifi_psk_connection_profile(args: Namespace) -> None: p.add_argument("--save", dest="save", action="store_true", help="Save") args = p.parse_args() sdbus.set_default_bus(sdbus.sd_bus_open_system()) - add_wifi_psk_connection_profile(args) + connection_dpath = add_wifi_psk_connection_profile(args) + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") From b14b7ee1ce761930e4edc690951245d09f4a3bd3 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 9 Apr 2022 20:51:46 +0200 Subject: [PATCH 03/80] add-eth-connection.py example: Update like add-wifi-psk-connection Add -u UUID parameter and make it usable from other examples: - Pass the UUID to the function so it can be passed from another caller. - Return the DBus path of the created connection to the caller. - Use getLogger().info() instead of print() to allow to customize if we want the output of the local function shown when importing. While at it, add the not yet existing async version of it as well. --- examples/async/add-eth-connection-async.py | 108 +++++++++++++++++++++ examples/block/add-eth-connection.py | 60 +++++++----- 2 files changed, 144 insertions(+), 24 deletions(-) create mode 100755 examples/async/add-eth-connection-async.py mode change 100644 => 100755 examples/block/add-eth-connection.py diff --git a/examples/async/add-eth-connection-async.py b/examples/async/add-eth-connection-async.py new file mode 100755 index 0000000..f7be36f --- /dev/null +++ b/examples/async/add-eth-connection-async.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new Ethernet network connection profile: +# +# examples/block/add-eth-connection-async.py --help +# usage: add-eth-connection-async.py [-h] [-c CONN_ID] [-u UUID] [-4 IP4] +# [-i INTERFACE_NAME] [-g GW] [-a] [--save] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -i INTERFACE_NAME ethX device +# -4 IP4 IP4/prefix +# -g GW gw/metric +# -a autoconnect +# --save Save +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html + +import asyncio +import sdbus +import functools +import logging +import pprint +import sys +from uuid import uuid4 +from argparse import ArgumentParser, Namespace +from sdbus_async.networkmanager import NetworkManagerSettings +from sdbus_async.networkmanager import NetworkManagerConnectionProperties + + +async def add_ethernet_connection_async(args: Namespace) -> str: + """Add a (by default) temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info + + # If we add many connections using the same id, things get messy. Check: + if await NetworkManagerSettings().get_connections_by_id(args.conn_id): + info(f'Connections using ID "{args.conn_id}" exist, remove them:') + info(f'Run: nmcli connection delete "{args.conn_id}"') + return "" + + ipaddr, prefix = args.ip4.split("/") + properties: NetworkManagerConnectionProperties = { + "connection": { + "id": ("s", args.conn_id), + "uuid": ("s", str(args.uuid)), + "type": ("s", "802-3-ethernet"), + "autoconnect": ("b", args.auto), + }, + "ipv4": { + "method": ("s", "manual"), + "address-data": ( + "aa{sv}", + [ + { + "address": ("s", ipaddr), + "prefix": ("u", int(prefix)), + }, + ], + ), + }, + "ipv6": {"method": ("s", "disabled")}, + } + if args.interface_name: + properties["connection"]["interface-name"] = ("s", args.interface_name) + if len(sys.argv) == 1 or args.gw != "192.0.2.1/4000": + default_gateway, route_metric = args.gw.split("/") + properties["ipv4"]["gateway"] = ("s", default_gateway) + properties["ipv4"]["route-metric"] = ("u", int(route_metric)) + + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(properties) + created = "created and saved" if args.save else "created" + + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("-i", dest="interface_name", default="", help="ethX device") + p.add_argument("-4", dest="ip4", default="192.0.2.8/24", help="IP4/prefix") + p.add_argument("-g", dest="gw", default="192.0.2.1/4000", help="gw/metric") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := asyncio.run(add_ethernet_connection_async(args)): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/block/add-eth-connection.py b/examples/block/add-eth-connection.py old mode 100644 new mode 100755 index c8828af..b692890 --- a/examples/block/add-eth-connection.py +++ b/examples/block/add-eth-connection.py @@ -3,15 +3,16 @@ # # Example to create a new Ethernet network connection profile: # -# add-eth-connection.py --help -# usage: add-eth-connection.py [-h] [-c CONN_ID] [-i INTERFACE_NAME] [-4 IP4] -# [-g GW] [-a] [--save] +# examples/block/add-eth-connection.py --help +# usage: add-eth-connection.py [-h] [-c CONN_ID] [-u UUID] [-i INTERFACE_NAME] +# [-4 IP4] [-g GW] [-a] [--save] # # Optional arguments have example values: # # optional arguments: # -h, --help show this help message and exit # -c CONN_ID Connection Id +# -u UUID Connection UUID # -i INTERFACE_NAME ethX device # -4 IP4 IP4/prefix # -g GW gw/metric @@ -23,28 +24,33 @@ import sdbus import functools +import logging import pprint import sys -import uuid +from uuid import uuid4 from argparse import ArgumentParser, Namespace from sdbus_block.networkmanager import NetworkManagerSettings from sdbus_block.networkmanager import NetworkManagerConnectionProperties -def add_ethernet_connection_profile(args: Namespace) -> None: - """Add a temporary (not yet saved) network connection profile""" +def add_ethernet_connection(args: Namespace) -> str: + """Add a (by default) temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info # If we add many connections using the same id, things get messy. Check: if NetworkManagerSettings().get_connections_by_id(args.conn_id): - print(f'Connections using ID "{args.conn_id}" exist, remove them:') - print(f'Run: nmcli connection delete "{args.conn_id}"') - return + info(f'Connections using ID "{args.conn_id}" exist, remove them:') + info(f'Run: nmcli connection delete "{args.conn_id}"') + return "" ipaddr, prefix = args.ip4.split("/") - profile: NetworkManagerConnectionProperties = { + properties: NetworkManagerConnectionProperties = { "connection": { "id": ("s", args.conn_id), - "uuid": ("s", str(uuid.uuid4())), + "uuid": ("s", str(args.uuid)), "type": ("s", "802-3-ethernet"), "autoconnect": ("b", args.auto), }, @@ -63,28 +69,30 @@ def add_ethernet_connection_profile(args: Namespace) -> None: "ipv6": {"method": ("s", "disabled")}, } if args.interface_name: - profile["connection"]["interface-name"] = ("s", args.interface_name) + properties["connection"]["interface-name"] = ("s", args.interface_name) if len(sys.argv) == 1 or args.gw != "192.0.2.1/4000": default_gateway, route_metric = args.gw.split("/") - profile["ipv4"]["gateway"] = ("s", default_gateway) - profile["ipv4"]["route-metric"] = ("u", int(route_metric)) + properties["ipv4"]["gateway"] = ("s", default_gateway) + properties["ipv4"]["route-metric"] = ("u", int(route_metric)) - if args.save: - NetworkManagerSettings().add_connection(profile) - print("New connection profile created and saved, show it with:") - else: - NetworkManagerSettings().add_connection_unsaved(profile) - print("New unsaved connection profile created, show it with:") + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = addconnection(properties) + created = "created and saved" if args.save else "created" - print(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') - print("Settings used:") - functools.partial(pprint.pprint, sort_dicts=False)(profile) + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) p = ArgumentParser(description="Optional arguments have example values:") conn_id = "MyConnectionExample" p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") p.add_argument("-i", dest="interface_name", default="", help="ethX device") p.add_argument("-4", dest="ip4", default="192.0.2.8/24", help="IP4/prefix") p.add_argument("-g", dest="gw", default="192.0.2.1/4000", help="gw/metric") @@ -92,4 +100,8 @@ def add_ethernet_connection_profile(args: Namespace) -> None: p.add_argument("--save", dest="save", action="store_true", help="Save") args = p.parse_args() sdbus.set_default_bus(sdbus.sd_bus_open_system()) - add_ethernet_connection_profile(args) + if connection_dpath := add_ethernet_connection(args): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") From 7e320428038a437ec0b27383c38f419945036d5f Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 9 Apr 2022 21:06:56 +0200 Subject: [PATCH 04/80] add-wifi-psk-connection example check return value of example Check the return value of the example function before declaring success. (And the function name had to be shortened to still fit into 79 columns) --- examples/async/add-wifi-psk-connection-async.py | 10 ++++++---- examples/block/add-wifi-psk-connection.py | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/async/add-wifi-psk-connection-async.py index 37f3eea..9782b0a 100755 --- a/examples/async/add-wifi-psk-connection-async.py +++ b/examples/async/add-wifi-psk-connection-async.py @@ -55,7 +55,7 @@ from sdbus_async.networkmanager import NetworkManagerConnectionProperties -async def add_wifi_psk_connection_profile_async(args: Namespace) -> str: +async def add_wifi_psk_connection_async(args: Namespace) -> str: """Add a temporary (not yet saved) network connection profile :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid :return: dbus connection path of the created connection profile @@ -117,6 +117,8 @@ async def add_wifi_psk_connection_profile_async(args: Namespace) -> str: p.add_argument("--save", dest="save", action="store_true", help="Save") args = p.parse_args() sdbus.set_default_bus(sdbus.sd_bus_open_system()) - connection_dpath = asyncio.run(add_wifi_psk_connection_profile_async(args)) - print(f"Path of the new connection: {connection_dpath}") - print(f"UUID of the new connection: {args.uuid}") + if connection_dpath := asyncio.run(add_wifi_psk_connection_async(args)): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/block/add-wifi-psk-connection.py b/examples/block/add-wifi-psk-connection.py index df821bd..77b06bf 100755 --- a/examples/block/add-wifi-psk-connection.py +++ b/examples/block/add-wifi-psk-connection.py @@ -54,7 +54,7 @@ from sdbus_block.networkmanager import NetworkManagerConnectionProperties -def add_wifi_psk_connection_profile(args: Namespace) -> str: +def add_wifi_psk_connection(args: Namespace) -> str: """Add a temporary (not yet saved) network connection profile :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid :return: dbus connection path of the created connection profile @@ -116,6 +116,8 @@ def add_wifi_psk_connection_profile(args: Namespace) -> str: p.add_argument("--save", dest="save", action="store_true", help="Save") args = p.parse_args() sdbus.set_default_bus(sdbus.sd_bus_open_system()) - connection_dpath = add_wifi_psk_connection_profile(args) - print(f"Path of the new connection: {connection_dpath}") - print(f"UUID of the new connection: {args.uuid}") + if connection_dpath := add_wifi_psk_connection(args): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") From 5bfa62749acf42f93726bba9c37b750e6c04e1ad Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sat, 9 Apr 2022 23:54:19 +0200 Subject: [PATCH 05/80] Add delete-connection-by-uuid examples(sync/async) Demonstrate finding a connection by a known UUID by using get_connection_by_uuid() and demonstrate deleting it as well. Use the `add-wifi-psk-connection` example to create a temporary WiFI connection with a given UUID. --- .../async/add-wifi-psk-connection-async.py | 9 ++-- .../async/delete-connection-by-uuid-async.py | 46 +++++++++++++++++++ examples/block/add-wifi-psk-connection.py | 9 ++-- examples/block/delete-connection-by-uuid.py | 45 ++++++++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100755 examples/async/delete-connection-by-uuid-async.py create mode 100755 examples/block/delete-connection-by-uuid.py diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/async/add-wifi-psk-connection-async.py index 37f3eea..789d29b 100755 --- a/examples/async/add-wifi-psk-connection-async.py +++ b/examples/async/add-wifi-psk-connection-async.py @@ -73,7 +73,7 @@ async def add_wifi_psk_connection_profile_async(args: Namespace) -> str: "id": ("s", args.conn_id), "uuid": ("s", str(args.uuid)), "type": ("s", "802-11-wireless"), - "autoconnect": ("b", args.auto), + "autoconnect": ("b", bool(hasattr(args, "auto") and args.auto)), }, "802-11-wireless": { "mode": ("s", "infrastructure"), @@ -90,13 +90,14 @@ async def add_wifi_psk_connection_profile_async(args: Namespace) -> str: } # To bind the new connection to a specific interface, use this: - if args.interface_name: + if hasattr(args, "interface_name") and args.interface_name: properties["connection"]["interface-name"] = ("s", args.interface_name) s = NetworkManagerSettings() - addconnection = s.add_connection if args.save else s.add_connection_unsaved + save = bool(hasattr(args, "save") and args.save) + addconnection = s.add_connection if save else s.add_connection_unsaved connection_settings_dbus_path = await addconnection(properties) - created = "created and saved" if args.save else "created" + created = "created and saved" if save else "created" info(f"New unsaved connection profile {created}, show it with:") info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') info("Settings used:") diff --git a/examples/async/delete-connection-by-uuid-async.py b/examples/async/delete-connection-by-uuid-async.py new file mode 100755 index 0000000..eff7706 --- /dev/null +++ b/examples/async/delete-connection-by-uuid-async.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Update a property of a connection profile, looked up by connection id +# +# The IPv4 settings of connections profiles are documented here: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# +import asyncio +import logging +import sdbus +from uuid import uuid4 +from argparse import Namespace +from sdbus_async.networkmanager import NetworkManagerSettings +from sdbus_async.networkmanager import NetworkConnectionSettings + + +async def delete_connection_by_uuid(uuid: str) -> bool: + """Find and delete the connection identified by the given UUID""" + settings_manager = NetworkManagerSettings() + connection_path = await settings_manager.get_connection_by_uuid(uuid) + if not connection_path: + logging.getLogger().fatal(f"Connection {uuid} for deletion not found") + return False + connection_settings = NetworkConnectionSettings(connection_path) + await connection_settings.delete() + return True + + +async def create_and_delete_wifi_psk_connection_async(args: Namespace) -> bool: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + add_wifi_psk_connection = __import__("add-wifi-psk-connection-async") + if not await add_wifi_psk_connection.add_wifi_psk_connection_async(args): + return False + return await delete_connection_by_uuid(str(args.uuid)) + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.WARNING) + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = Namespace(conn_id="Example", uuid=uuid4(), ssid="S", psk="Password") + if asyncio.run(create_and_delete_wifi_psk_connection_async(args)): + print(f"Succeeded in creating and deleting connection {args.uuid}") diff --git a/examples/block/add-wifi-psk-connection.py b/examples/block/add-wifi-psk-connection.py index df821bd..51781df 100755 --- a/examples/block/add-wifi-psk-connection.py +++ b/examples/block/add-wifi-psk-connection.py @@ -72,7 +72,7 @@ def add_wifi_psk_connection_profile(args: Namespace) -> str: "id": ("s", args.conn_id), "uuid": ("s", str(args.uuid)), "type": ("s", "802-11-wireless"), - "autoconnect": ("b", args.auto), + "autoconnect": ("b", bool(hasattr(args, "auto") and args.auto)), }, "802-11-wireless": { "mode": ("s", "infrastructure"), @@ -89,13 +89,14 @@ def add_wifi_psk_connection_profile(args: Namespace) -> str: } # To bind the new connection to a specific interface, use this: - if args.interface_name: + if hasattr(args, "interface_name") and args.interface_name: properties["connection"]["interface-name"] = ("s", args.interface_name) s = NetworkManagerSettings() - addconnection = s.add_connection if args.save else s.add_connection_unsaved + save = bool(hasattr(args, "save") and args.save) + addconnection = s.add_connection if save else s.add_connection_unsaved connection_settings_dbus_path = addconnection(properties) - created = "created and saved" if args.save else "created" + created = "created and saved" if save else "created" info(f"New unsaved connection profile {created}, show it with:") info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') info("Settings used:") diff --git a/examples/block/delete-connection-by-uuid.py b/examples/block/delete-connection-by-uuid.py new file mode 100755 index 0000000..8bc3583 --- /dev/null +++ b/examples/block/delete-connection-by-uuid.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Update a property of a connection profile, looked up by connection id +# +# The IPv4 settings of connections profiles are documented here: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# +import logging +import sdbus +from uuid import uuid4 +from argparse import Namespace +from sdbus_block.networkmanager import NetworkManagerSettings +from sdbus_block.networkmanager import NetworkConnectionSettings + + +def delete_connection_by_uuid(uuid: str) -> bool: + """Find and delete the connection identified by the given UUID""" + settings_manager = NetworkManagerSettings() + connection_path = settings_manager.get_connection_by_uuid(uuid) + if not connection_path: + logging.getLogger().fatal(f"Connection {uuid} for deletion not found") + return False + connection_settings = NetworkConnectionSettings(connection_path) + connection_settings.delete() + return True + + +def create_and_delete_wifi_psk_connection_(args: Namespace) -> bool: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + add_wifi_psk_connection = __import__("add-wifi-psk-connection") + if not add_wifi_psk_connection.add_wifi_psk_connection(args): + return False + return delete_connection_by_uuid(str(args.uuid)) + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.WARNING) + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = Namespace(conn_id="Example", uuid=uuid4(), ssid="S", psk="Password") + if create_and_delete_wifi_psk_connection_(args): + print(f"Succeeded in creating and deleting connection {args.uuid}") From d2a4010333857bdf5f6088c355b78ed0fbead1c6 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 29 May 2022 15:58:55 +0300 Subject: [PATCH 06/80] Make settings generator script accept custom XML path --- tools/generate-settings-dataclasses.py | 330 +++++++++++++------------ 1 file changed, 177 insertions(+), 153 deletions(-) diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 90022a5..3885d53 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -1,9 +1,11 @@ #!/usr/bin/env python # SPDX-License-Identifier: LGPL-2.1-or-later import collections -from typing import Any, Dict, List, OrderedDict, Optional, Tuple -import xml.etree.ElementTree as ElementTree import textwrap +import xml.etree.ElementTree as ElementTree +from argparse import ArgumentParser +from pathlib import Path +from typing import Any, Dict, List, Optional, OrderedDict, Tuple def dbg(msg: Any) -> None: @@ -183,158 +185,180 @@ def find_first_not_none(itr: List[Any]) -> Optional[Any]: return next((i for i in itr if i is not None), None) -############################################################################### -gl_input_files = ["man/nm-settings-docs-dbus.xml"] - -xml_roots = [ElementTree.parse(f).getroot() for f in gl_input_files] -assert all(root.tag == "nm-setting-docs" for root in xml_roots) -settings_roots = [node_to_dict(root, "setting", "name") for root in xml_roots] - -root_node = ElementTree.Element("nm-setting-docs") -# print("") -license = "SPDX-License-Identifier: LGPL-2.1-or-later" -script = "This file was generated by tools/generate-settings-dataclasses.py" -header = f"""# {license}\n# {script}, -# if possible, please make changes by also updating the script. -""" -i = open("sdbus_async/networkmanager/settings/__init__.py", mode="w") -p = open("sdbus_async/networkmanager/settings/profile.py", mode="r") -profile_py = open("sdbus_async/networkmanager/settings/profile.py").read() -start_string = "# start of the generated list of settings classes\n" -start_index = profile_py.index(start_string) + len(start_string) -# end_string = " def to_dbus" -end_string = " # end of the generated list of settings classes\n" -end_index = profile_py.index(end_string) -p = open("sdbus_async/networkmanager/settings/profile.py", mode="w") -i.write(header) -p.write(profile_py[:start_index]) -classes = [] -for settingname in iter_keys_of_dicts(settings_roots, key_fcn_setting_name): - settings = [d.get(settingname) for d in settings_roots] - properties = [node_to_dict(s, "property", "name") for s in settings] - if properties == [OrderedDict()]: - continue - if settingname in ["tc", "sriov"]: - continue # Not supported by this codegen yet(needs Qdiscs and vfs) - module = settingname.replace('-', '_') - for prefix in ["6", "802_11_", "802_3_"]: - if module.startswith(prefix): - module = module.replace(prefix, "") - break - if settingname.startswith("802-1x"): - module = f"ieee{module}" - temp = module.split('_') + ["Settings"] - classname = temp[0].title() + ''.join(ele.title() for ele in temp[1:]) - if classname.startswith("Ieee"): - classname.replace("Ieee", "IEEE") - i.write(f"from .{module} import {classname}\n") - classes.append(classname) - f = open(f"sdbus_async/networkmanager/settings/{module}.py", mode="w") - f.write(header) - f.write("from __future__ import annotations\n") - f.write("from dataclasses import dataclass, field\n") - f.write("from typing import") - if module in ["bond", "ethernet", "ovs_external_ids", "vpn", "user"]: - f.write(" Dict,") - if module in list_modules: - f.write(" List,") - f.write(" Optional\n") - f.write("from .base import NetworkManagerSettingsMixin\n") - if settingname.startswith("ipv"): - f.write("from .datatypes import AddressData, RouteData\n") - if settingname.startswith("bridge"): - f.write("from .datatypes import Vlans\n") - if settingname.startswith("team"): - f.write("from .datatypes import LinkWatchers\n") - if settingname == "wireguard": - f.write("from .datatypes import WireguardPeers as Peers\n") - f.write("\n\n") - - setting_node = ElementTree.SubElement(root_node, "setting") - if module != "connection": - p.write(f" {module}: Optional[{classname}] = field(\n") - p.write(f" metadata={{'dbus_name': '{settingname}',\n") - p.write(f" 'settings_class': {classname}}},\n") - p.write(" default=None,\n") - p.write(" )\n") - f.write("@dataclass\n") - f.write(f"class {classname}(NetworkManagerSettingsMixin):\n") - setting_node.set("name", settingname) - desc = node_get_attr(settings, "description") - f.write(' """' + desc + '"""\n\n') - # node_set_attr(setting_node, "alias", settings) - for property_name in iter_keys_of_dicts(properties): - properties_attrs = [p.get(property_name) for p in properties] - property_node = ElementTree.SubElement(setting_node, "property") - property_node.set("name", property_name) - t = node_get_attr(properties_attrs, "type") - attribute = property_name.replace('-', '_') - for builtin in ["id", "type"]: - if attribute == builtin: - attribute = f"{module}_{attribute}" - - if not t: - t = "string" - if t.startswith("array of legacy"): +def main(settings_xml_path: Path) -> None: + gl_input_files = [settings_xml_path] + + xml_roots = [ElementTree.parse(f).getroot() for f in gl_input_files] + assert all(root.tag == "nm-setting-docs" for root in xml_roots) + settings_roots = [node_to_dict(root, "setting", "name") + for root in xml_roots] + + root_node = ElementTree.Element("nm-setting-docs") + # print("") + license = "SPDX-License-Identifier: LGPL-2.1-or-later" + script = ("This file was generated by " + "tools/generate-settings-dataclasses.py") + header = f"""# {license}\n# {script}, + # if possible, please make changes by also updating the script. + """ + i = open("sdbus_async/networkmanager/settings/__init__.py", mode="w") + p = open("sdbus_async/networkmanager/settings/profile.py", mode="r") + profile_py = open("sdbus_async/networkmanager/settings/profile.py").read() + start_string = "# start of the generated list of settings classes\n" + start_index = profile_py.index(start_string) + len(start_string) + # end_string = " def to_dbus" + end_string = " # end of the generated list of settings classes\n" + end_index = profile_py.index(end_string) + p = open("sdbus_async/networkmanager/settings/profile.py", mode="w") + i.write(header) + p.write(profile_py[:start_index]) + classes = [] + for settingname in iter_keys_of_dicts(settings_roots, + key_fcn_setting_name): + settings = [d.get(settingname) for d in settings_roots] + properties = [node_to_dict(s, "property", "name") for s in settings] + if properties == [OrderedDict()]: continue - if t not in dbus_name_type_map: - print(f"{settingname}.{property_name}: type '{t}' not found") - ty = t.replace(")", "")[-5:] - if ty in dbus_name_type_map: - t = ty - if t in ["{sv}'"]: - t = "{sv}" - dbustype = dbus_name_type_map[t] - if dbustype == "aa{sv}": - default = node_get_attr(properties_attrs, "default") - inner_cls = ( - property_name.title().replace("-", "").replace("data", "Data") - ) - f.write(f" {attribute}: Optional[List[{inner_cls}]] = field(\n") - f.write(f" metadata={{'dbus_name': '{property_name}',\n") - f.write(f" 'dbus_type': '{dbustype}',\n") - f.write(f" 'dbus_inner_class': {inner_cls}}},\n") - f.write(f" default={str(default).title()},\n )\n") - else: - attribute_type = dbus_type_name_map[dbustype] - optional = module != "bond" - if optional: - f.write(f" {attribute}: Optional[{attribute_type}]") + if settingname in ["tc", "sriov"]: + continue # Not supported by this codegen yet(needs Qdiscs and vfs) + module = settingname.replace('-', '_') + for prefix in ["6", "802_11_", "802_3_"]: + if module.startswith(prefix): + module = module.replace(prefix, "") + break + if settingname.startswith("802-1x"): + module = f"ieee{module}" + temp = module.split('_') + ["Settings"] + classname = temp[0].title() + ''.join(ele.title() for ele in temp[1:]) + if classname.startswith("Ieee"): + classname.replace("Ieee", "IEEE") + i.write(f"from .{module} import {classname}\n") + classes.append(classname) + f = open(f"sdbus_async/networkmanager/settings/{module}.py", mode="w") + f.write(header) + f.write("from __future__ import annotations\n") + f.write("from dataclasses import dataclass, field\n") + f.write("from typing import") + if module in ["bond", "ethernet", "ovs_external_ids", "vpn", "user"]: + f.write(" Dict,") + if module in list_modules: + f.write(" List,") + f.write(" Optional\n") + f.write("from .base import NetworkManagerSettingsMixin\n") + if settingname.startswith("ipv"): + f.write("from .datatypes import AddressData, RouteData\n") + if settingname.startswith("bridge"): + f.write("from .datatypes import Vlans\n") + if settingname.startswith("team"): + f.write("from .datatypes import LinkWatchers\n") + if settingname == "wireguard": + f.write("from .datatypes import WireguardPeers as Peers\n") + f.write("\n\n") + + setting_node = ElementTree.SubElement(root_node, "setting") + if module != "connection": + p.write(f" {module}: Optional[{classname}] = field(\n") + p.write(f" metadata={{'dbus_name': '{settingname}',\n") + p.write(f" 'settings_class': {classname}}},\n") + p.write(" default=None,\n") + p.write(" )\n") + f.write("@dataclass\n") + f.write(f"class {classname}(NetworkManagerSettingsMixin):\n") + setting_node.set("name", settingname) + desc = node_get_attr(settings, "description") + f.write(' """' + desc + '"""\n\n') + # node_set_attr(setting_node, "alias", settings) + for property_name in iter_keys_of_dicts(properties): + properties_attrs = [p.get(property_name) for p in properties] + property_node = ElementTree.SubElement(setting_node, "property") + property_node.set("name", property_name) + t = node_get_attr(properties_attrs, "type") + attribute = property_name.replace('-', '_') + for builtin in ["id", "type"]: + if attribute == builtin: + attribute = f"{module}_{attribute}" + + if not t: + t = "string" + if t.startswith("array of legacy"): + continue + if t not in dbus_name_type_map: + print(f"{settingname}.{property_name}: type '{t}' not found") + ty = t.replace(")", "")[-5:] + if ty in dbus_name_type_map: + t = ty + if t in ["{sv}'"]: + t = "{sv}" + dbustype = dbus_name_type_map[t] + if dbustype == "aa{sv}": + default = node_get_attr(properties_attrs, "default") + inner_cls = ( + property_name.title( + ).replace("-", "").replace("data", "Data") + ) + f.write( + f" {attribute}: Optional[List[{inner_cls}]] = field(\n") + f.write( + f" metadata={{'dbus_name': '{property_name}',\n") + f.write(f" 'dbus_type': '{dbustype}',\n") + f.write( + f" 'dbus_inner_class': {inner_cls}}},\n") + f.write(f" default={str(default).title()},\n )\n") else: - f.write(f" {attribute}: {attribute_type}") - f.write(" = field(\n") - meta = f"'dbus_name': '{property_name}', 'dbus_type':@'{dbustype}'" - line = "metadata={" + meta + "}," - wrapper = textwrap.TextWrapper( - width=80, - initial_indent=" ", - subsequent_indent=" ", - ) - lines = wrapper.wrap(text=line) - for line in lines: - f.write(line.replace(":@", ": ") + '\n') - default = node_get_attr(properties_attrs, "default") - if default in ["{}", "0", "-1"]: - default = "None" - if optional: - f.write(f" default={str(default).title()},\n") - f.write(" )\n") - generate_descriptions_for_attributes = False - if generate_descriptions_for_attributes: - desc = node_get_attr(properties_attrs, "description") + attribute_type = dbus_type_name_map[dbustype] + optional = module != "bond" + if optional: + f.write(f" {attribute}: Optional[{attribute_type}]") + else: + f.write(f" {attribute}: {attribute_type}") + f.write(" = field(\n") + meta = (f"'dbus_name': '{property_name}', " + f"'dbus_type':@'{dbustype}'") + line = "metadata={" + meta + "}," wrapper = textwrap.TextWrapper( - width=74, initial_indent=" ", subsequent_indent=" " + width=80, + initial_indent=" ", + subsequent_indent=" ", ) - lines = wrapper.wrap(text=f'"""{desc}') - if len(lines) == 1: - print(lines[0] + '"""') - else: - for line in lines: - f.write(line) - f.write(' """') - f.write("") -i.write('\n__all__ = (\n') -for cls in classes: - i.write(f" '{cls}',\n") -i.write(")\n") -p.write(profile_py[end_index:]) + lines = wrapper.wrap(text=line) + for line in lines: + f.write(line.replace(":@", ": ") + '\n') + default = node_get_attr(properties_attrs, "default") + if default in ["{}", "0", "-1"]: + default = "None" + if optional: + f.write(f" default={str(default).title()},\n") + f.write(" )\n") + generate_descriptions_for_attributes = False + if generate_descriptions_for_attributes: + desc = node_get_attr(properties_attrs, "description") + wrapper = textwrap.TextWrapper( + width=74, + initial_indent=" ", + subsequent_indent=" ", + ) + lines = wrapper.wrap(text=f'"""{desc}') + if len(lines) == 1: + print(lines[0] + '"""') + else: + for line in lines: + f.write(line) + f.write(' """') + f.write("") + i.write('\n__all__ = (\n') + for cls in classes: + i.write(f" '{cls}',\n") + i.write(")\n") + p.write(profile_py[end_index:]) + + +if __name__ == '__main__': + arg_parser = ArgumentParser() + arg_parser.add_argument( + 'nm_settings_xml', + type=Path, + default=Path('man/nm-settings-docs-dbus.xml'), + ) + args = arg_parser.parse_args() + + main(args.nm_settings_xml) From ab3de2b2dccb2d9cf2e267f57ecaa31644228d78 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 29 May 2022 20:50:23 +0300 Subject: [PATCH 07/80] Start on new settings classes generator based on Jinja2 Old one was very hard to understand. New one works with `tools/generate-docs-nm-settings-docs-gir.py` from NetworkManager source code. However, there are several problems with that script that need upstream to fix it. --- tools/generate-settings-dataclasses-jinja.py | 190 +++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tools/generate-settings-dataclasses-jinja.py diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py new file mode 100644 index 0000000..9d4dac9 --- /dev/null +++ b/tools/generate-settings-dataclasses-jinja.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +from __future__ import annotations +from argparse import ArgumentParser +from pathlib import Path +from xml.etree.ElementTree import parse, Element + +from typing import List, Optional +from jinja2 import Environment +import builtins +import keyword + +dbus_to_python_extra_typing_imports = { + "as": ("List", ), + "au": ("List", ), + "a{ss}": ("Dict", ), + "aa{sv}": ("List", "Tuple", "Any"), + "aau": ("List", ), + "aay": ("List", ) +} + +dbus_to_python_type_map = { + "b": "bool", + "s": "str", + "i": "int", + "u": "int", + "t": "int", + "x": "int", + "y": "int", + "as": "List[str]", + "au": "List[int]", + "ay": "bytes", + "a{ss}": "Dict[str, str]", + "aa{sv}": "List[Tuple[str, Any]]", + "aau": "List[List[int]]", + "aay": "List[bytes]", + # Legacy types: + "a(ayuay)": "array of legacy IPv6 address struct", + "a(ayuayu)": "array of legacy IPv6 route struct", +} + +dbus_name_type_map = { + 'array of array of uint32': 'aau', + 'array of byte array': 'aay', + 'array of legacy IPv6 address struct': 'a(ayuay)', + 'array of legacy IPv6 route struct': 'a(ayuayu)', + 'array of string': 'as', + 'array of uint32': 'au', + 'array of vardict': 'aa{sv}', + "array of 'a{sv}'": 'aa{sv}', # wireguard.peers uses this, fix NM upstream + 'boolean': 'b', + 'byte': 'y', + 'byte array': 'ay', + 'dict of string to string': 'a{ss}', + 'int32': 'i', + 'int64': 'x', + 'string': 's', + 'uint32': 'u', + 'uint64': 't', +} + +python_name_replacements = { + 'type': 'connection_type', + 'id': 'pretty_id', +} + + +def must_replace_name(name: str) -> bool: + return (keyword.iskeyword(name) + or keyword.issoftkeyword(name) + or hasattr(builtins, name)) + + +class NmSettingPropertyIntrospection: + def __init__(self, name: str, + description: str, + name_upper: str, + dbus_type: str, + python_type: str, + parent: NmSettingsIntrospection, + default: Optional[str] = None, + ) -> None: + self.name = name + self.description = description + self.name_upper = name_upper + self.python_name = name_upper.lower() + self.dbus_type = dbus_type + self.python_type = python_type + self.default = default + + if must_replace_name(self.python_name): + self.python_name = (f"{parent.name_upper.lower()}" + f"_{self.python_name}") + + extra_typing = dbus_to_python_extra_typing_imports.get(dbus_type) + if extra_typing is not None: + parent.typing_imports.update(extra_typing) + + +class NmSettingsIntrospection: + def __init__(self, name: str, description: str, name_upper: str, + ) -> None: + self.name = name + self.description = description + self.name_upper = name_upper + self.python_class_name = name.capitalize() + 'Settings' + + self.typing_imports = {'Optional'} + + self.properties: List[NmSettingPropertyIntrospection] = [] + + +def convert_property(node: Element, + parent: NmSettingsIntrospection + ) -> NmSettingPropertyIntrospection: + options = node.attrib + + unconverted_type = options.pop('type') + try: + dbus_type = dbus_name_type_map[unconverted_type] + except KeyError: + dbus_type = dbus_name_type_map[unconverted_type.split('(')[1][:-1]] + + options['dbus_type'] = dbus_type + options['python_type'] = dbus_to_python_type_map[dbus_type] + + return NmSettingPropertyIntrospection(**options, parent=parent) + + +def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: + settings_introspection: List[NmSettingsIntrospection] = [] + for setting_node in root: + setting = NmSettingsIntrospection(**setting_node.attrib) + setting.properties.extend( + (convert_property(x, setting) for x in setting_node) + ) + + settings_introspection.append(setting) + + return settings_introspection + + +setttngs_template_str = """# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import {{ setting.typing_imports|sort|join(', ') }} +from .base import NetworkManagerSettingsMixin + + +@dataclass +class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): + \"""{{ setting.description }}\""" +{% for property in setting.properties %} + {{ property.python_name }}: Optional[{{ property.python_type }}] = field( + metadata={ + 'dbus_name': '{{ property.name }}', + 'dbus_type': '{{ property.dbus_type }}', + }, + default=None, + ){% endfor %} + +""" + +jinja_env = Environment() +settings_template = jinja_env.from_string(setttngs_template_str) + + +def main(settings_xml_path: Path) -> None: + tree = parse(settings_xml_path) + introspection = generate_introspection(tree.getroot()) + + settings_dir = Path('sdbus_async/networkmanager/settings/') + for setting in introspection: + setting_py_file = settings_dir / (setting.name_upper.lower() + '.py') + with open(setting_py_file, mode='w') as f: + f.write(settings_template.render(setting=setting)) + + +if __name__ == '__main__': + arg_parser = ArgumentParser() + arg_parser.add_argument( + 'nm_settings_xml', + type=Path, + default=Path('man/nm-settings-docs-dbus.xml'), + ) + args = arg_parser.parse_args() + + main(args.nm_settings_xml) From 7dd4a75a3c11dd260aea78c47f584d0758d620f9 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 15:58:38 +0200 Subject: [PATCH 08/80] networkmanager/objects.py: Syncronice new helpers from async to block Add missing helper methods from sdbus_async/networkmanager: - get_settings_by_uuid(): - Net a nested settings dict of a connection profile - delete_connection_by_uuid(): Delete a profile identified by the uuid - connection_profile(): Get a ConnectionProfile object containing all settings --- sdbus_block/networkmanager/objects.py | 30 ++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/sdbus_block/networkmanager/objects.py b/sdbus_block/networkmanager/objects.py index d7a47bd..48aa0bd 100644 --- a/sdbus_block/networkmanager/objects.py +++ b/sdbus_block/networkmanager/objects.py @@ -67,6 +67,8 @@ NetworkManagerVPNConnectionInterface, NetworkManagerWifiP2PPeerInterface, ) +from .settings.profile import ConnectionProfile +from .types import NetworkManagerConnectionProperties NETWORK_MANAGER_SERVICE_NAME = 'org.freedesktop.NetworkManager' @@ -158,7 +160,7 @@ def get_connections_by_id(self, connection_id: str) -> List[str]: which use the given connection identifier. :param str connection_id: The connection identifier of the connections, - e.g. "Ethernet connection 1" + e.g. "Wired connection 1" :return: List of connection profile paths using the given identifier. """ connection_paths_with_matching_id = [] @@ -169,6 +171,25 @@ def get_connections_by_id(self, connection_id: str) -> List[str]: connection_paths_with_matching_id.append(connection_path) return connection_paths_with_matching_id + def get_settings_by_uuid( + self, connection_uuid: str + ) -> NetworkManagerConnectionProperties: + """Helper to get a nested settings dict of a connection profile by uuid. + + :param str connection_uuid: The connection uuid of the connection profile + :return: Nested dictionary of all settings of the given connection profile + """ + connection = self.get_connection_by_uuid(connection_uuid) + return NetworkConnectionSettings(connection).get_settings() + + def delete_connection_by_uuid(self, connection_uuid: str) -> None: + """Helper to delete a connection profile identified by the connection uuid. + + :param str connection_uuid: The connection uuid of the connection profile + """ + conn_dbus_path = self.get_connection_by_uuid(connection_uuid) + NetworkConnectionSettings(conn_dbus_path).delete() + class NetworkConnectionSettings( NetworkManagerSettingsConnectionInterface): @@ -192,6 +213,13 @@ def __init__(self, settings_path: str, settings_path, bus) + def connection_profile(self) -> ConnectionProfile: + """Return a ConnectionProfile object containing all profile settings + + :return: Nested dataclass containing all settings of the profile + """ + return ConnectionProfile.from_dbus(self.get_settings()) + class NetworkDeviceGeneric( NetworkManagerDeviceInterface, From cbf0f3261a587c586cfd8a336a15d3c53c830e5a Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 16:04:35 +0200 Subject: [PATCH 09/80] Show the use of NetworkConnectionSettings(path).connection_profile() --- examples/block/list-connections.py | 56 ++++++++++++++++-------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/examples/block/list-connections.py b/examples/block/list-connections.py index 52e1c4d..ea8954a 100755 --- a/examples/block/list-connections.py +++ b/examples/block/list-connections.py @@ -17,39 +17,41 @@ # | ipv6: method: disabled import sdbus from sdbus_block.networkmanager import ( + ConnectionType, NetworkManagerSettings, NetworkConnectionSettings, ) def list_connection_profiles_blocking() -> None: - for connection_path in NetworkManagerSettings().connections: - connection_settings = NetworkConnectionSettings(connection_path) - settings = connection_settings.get_settings() - connection = settings["connection"] - - # Skip connection profiles for bridges and wireless networks - if connection["type"][1] in ("bridge", "802-11-wireless"): - continue - - print("-------------------------------------------------------------") - print("name:", connection["id"][1]) - print("uuid:", connection["uuid"][1]) - print("type:", connection["type"][1]) - if "interface-name" in connection: - print(" interface-name:", connection["interface-name"][1]) - - if "ipv4" in settings: - ipv4 = settings["ipv4"] - print("ipv4: method:", ipv4["method"][1]) - if "address-data" in ipv4: - for a in ipv4["address-data"][1]: - print(f' ipaddr: {a["address"][1]}/{a["prefix"][1]}') - if "route-metric" in ipv4: - print(f' route-metric: {ipv4["route-metric"][1]}') - - if "ipv6" in settings: - print("ipv6: method:", settings["ipv6"]["method"][1]) + """Call print_connection_profile_blocking() for all connection profiles""" + networkmanager_settings = NetworkManagerSettings() + for dbus_connection_path in networkmanager_settings.connections: + print_connection_profile_blocking(dbus_connection_path) + + +def print_connection_profile_blocking(connection_path: str) -> None: + """Show the use of NetworkConnectionSettings(path).connection_profile()""" + profile = NetworkConnectionSettings(connection_path).connection_profile() + print("-------------------------------------------------------------") + print("name:", profile.connection.connection_id) + print("uuid:", profile.connection.uuid) + print("type:", profile.connection.connection_type) + if profile.connection.interface_name: + print(" interface-name:", profile.connection.interface_name) + if profile.ipv4: + print("ipv4: method:", profile.ipv4.method) + if profile.ipv4.address_data: + for address in profile.ipv4.address_data: + print(f' ipaddr: {address.address}/{address.prefix}') + if profile.ipv4.route_metric: + print(f' route-metric: {profile.ipv4.route_metric}') + if profile.ipv6: + print("ipv6: method:", profile.ipv6.method) + if profile.connection.connection_type == ConnectionType.WIFI: + assert profile.wireless + assert profile.wireless.ssid + print("ssid:", profile.wireless.ssid.decode()) if __name__ == "__main__": From 66c44d4f2bbaa07cb835087a8eb87281b8bf4eed Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 18:03:56 +0200 Subject: [PATCH 10/80] Update add-wifi-psk-connection to use ConnectionProfile class Update the example add-wifi-psk-connection-async.py to to use the new ConnectionProfile dataclass for creating the connection and merge other minor cleanups and improvements. --- .../async/add-wifi-psk-connection-async.py | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/async/add-wifi-psk-connection-async.py index 7bfd5f1..4080a54 100755 --- a/examples/async/add-wifi-psk-connection-async.py +++ b/examples/async/add-wifi-psk-connection-async.py @@ -45,14 +45,24 @@ # -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) import asyncio +import binascii import functools import logging -import pprint import sdbus from uuid import uuid4 from argparse import ArgumentParser, Namespace -from sdbus_async.networkmanager import NetworkManagerSettings -from sdbus_async.networkmanager import NetworkManagerConnectionProperties +from passlib.utils.pbkdf2 import pbkdf2 # type: ignore +from pprint import pformat +from sdbus_async.networkmanager import ( + NetworkManagerSettings as SettingsManager, + ConnectionProfile, + ConnectionSettings, + ConnectionType, + Ipv4Settings, + Ipv6Settings, + WirelessSettings, + WirelessSecuritySettings, +) async def add_wifi_psk_connection_async(args: Namespace) -> str: @@ -63,45 +73,44 @@ async def add_wifi_psk_connection_async(args: Namespace) -> str: info = logging.getLogger().info # If we add many connections passing the same id, things get messy. Check: - if await NetworkManagerSettings().get_connections_by_id(args.conn_id): + if await SettingsManager().get_connections_by_id(args.conn_id): print(f'Connection "{args.conn_id}" exists, remove it first') print(f'Run: nmcli connection delete "{args.conn_id}"') return "" - properties: NetworkManagerConnectionProperties = { - "connection": { - "id": ("s", args.conn_id), - "uuid": ("s", str(args.uuid)), - "type": ("s", "802-11-wireless"), - "autoconnect": ("b", bool(hasattr(args, "auto") and args.auto)), - }, - "802-11-wireless": { - "mode": ("s", "infrastructure"), - "security": ("s", "802-11-wireless-security"), - "ssid": ("ay", args.ssid.encode("utf-8")), - }, - "802-11-wireless-security": { - "key-mgmt": ("s", "wpa-psk"), - "auth-alg": ("s", "open"), - "psk": ("s", args.psk), - }, - "ipv4": {"method": ("s", "auto")}, - "ipv6": {"method": ("s", "auto")}, - } + if args.key_mgmt == "wpa-psk" and len(args.password) < 64: + # Hash the password into a psk hash to not store it in clear form: + pw = pbkdf2(args.password.encode(), args.ssid.encode(), 4096, 32) + args.password = binascii.hexlify(pw).decode("utf-8") + + profile = ConnectionProfile( + connection=ConnectionSettings( + connection_id=args.conn_id, + uuid=str(args.uuid), + connection_type=ConnectionType.WIFI.value, + autoconnect=bool(hasattr(args, "auto") and args.auto), + ), + ipv4=Ipv4Settings(method="auto"), + ipv6=Ipv6Settings(method="auto"), + wireless=WirelessSettings(ssid=args.ssid.encode("utf-8")), + wireless_security=WirelessSecuritySettings( + key_mgmt=args.key_mgmt, auth_alg="open", psk=args.password + ), + ) # To bind the new connection to a specific interface, use this: if hasattr(args, "interface_name") and args.interface_name: - properties["connection"]["interface-name"] = ("s", args.interface_name) + profile.connection.interface_name = args.interface_name - s = NetworkManagerSettings() + s = SettingsManager() save = bool(hasattr(args, "save") and args.save) addconnection = s.add_connection if save else s.add_connection_unsaved - connection_settings_dbus_path = await addconnection(properties) + connection_settings_dbus_path = await addconnection(profile.to_dbus()) created = "created and saved" if save else "created" info(f"New unsaved connection profile {created}, show it with:") info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') info("Settings used:") - info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + info(functools.partial(pformat, sort_dicts=False)(profile.to_settings_dict())) return connection_settings_dbus_path @@ -112,7 +121,8 @@ async def add_wifi_psk_connection_async(args: Namespace) -> str: p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") p.add_argument("-s", dest="ssid", default="CafeSSID", help="WiFi SSID") - p.add_argument("-p", dest="psk", default="Coffee!!", help="WiFi PSK") + p.add_argument("-k", dest="key_mgmt", default="wpa-psk", help="key-mgmt") + p.add_argument("-p", dest="password", default="Coffee!!", help="WiFi PSK") p.add_argument("-i", dest="interface_name", default="", help="WiFi device") p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") p.add_argument("--save", dest="save", action="store_true", help="Save") From 1fe6c83c415099bceb9c051f967ee7db2c95540b Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 18:25:35 +0200 Subject: [PATCH 11/80] Examples: Use NetworkManagerSettings().delete_connection_by_uuid(uuid) --- .../async/delete-connection-by-uuid-async.py | 15 +++++---------- examples/block/delete-connection-by-uuid.py | 19 +++++++------------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/examples/async/delete-connection-by-uuid-async.py b/examples/async/delete-connection-by-uuid-async.py index eff7706..ac1ee3d 100755 --- a/examples/async/delete-connection-by-uuid-async.py +++ b/examples/async/delete-connection-by-uuid-async.py @@ -1,10 +1,7 @@ #!/usr/bin/env python # SPDX-License-Identifier: LGPL-2.1-or-later # -# Update a property of a connection profile, looked up by connection id -# -# The IPv4 settings of connections profiles are documented here: -# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# Create and delete a connection profile using the unique connection uuid # import asyncio import logging @@ -12,18 +9,16 @@ from uuid import uuid4 from argparse import Namespace from sdbus_async.networkmanager import NetworkManagerSettings -from sdbus_async.networkmanager import NetworkConnectionSettings +from sdbus_async.networkmanager import NmSettingsInvalidConnectionError async def delete_connection_by_uuid(uuid: str) -> bool: """Find and delete the connection identified by the given UUID""" - settings_manager = NetworkManagerSettings() - connection_path = await settings_manager.get_connection_by_uuid(uuid) - if not connection_path: + try: + await NetworkManagerSettings().delete_connection_by_uuid(uuid) + except NmSettingsInvalidConnectionError: logging.getLogger().fatal(f"Connection {uuid} for deletion not found") return False - connection_settings = NetworkConnectionSettings(connection_path) - await connection_settings.delete() return True diff --git a/examples/block/delete-connection-by-uuid.py b/examples/block/delete-connection-by-uuid.py index 8bc3583..2b42509 100755 --- a/examples/block/delete-connection-by-uuid.py +++ b/examples/block/delete-connection-by-uuid.py @@ -1,32 +1,27 @@ #!/usr/bin/env python # SPDX-License-Identifier: LGPL-2.1-or-later # -# Update a property of a connection profile, looked up by connection id -# -# The IPv4 settings of connections profiles are documented here: -# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# Create and delete a connection profile using the unique connection uuid # import logging import sdbus from uuid import uuid4 from argparse import Namespace from sdbus_block.networkmanager import NetworkManagerSettings -from sdbus_block.networkmanager import NetworkConnectionSettings +from sdbus_block.networkmanager import NmSettingsInvalidConnectionError def delete_connection_by_uuid(uuid: str) -> bool: """Find and delete the connection identified by the given UUID""" - settings_manager = NetworkManagerSettings() - connection_path = settings_manager.get_connection_by_uuid(uuid) - if not connection_path: + try: + NetworkManagerSettings().delete_connection_by_uuid(uuid) + except NmSettingsInvalidConnectionError: logging.getLogger().fatal(f"Connection {uuid} for deletion not found") return False - connection_settings = NetworkConnectionSettings(connection_path) - connection_settings.delete() return True -def create_and_delete_wifi_psk_connection_(args: Namespace) -> bool: +def create_and_delete_wifi_psk_connection_async(args: Namespace) -> bool: """Add a temporary (not yet saved) network connection profile :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid :return: dbus connection path of the created connection profile @@ -41,5 +36,5 @@ def create_and_delete_wifi_psk_connection_(args: Namespace) -> bool: logging.basicConfig(format="%(message)s", level=logging.WARNING) sdbus.set_default_bus(sdbus.sd_bus_open_system()) args = Namespace(conn_id="Example", uuid=uuid4(), ssid="S", psk="Password") - if create_and_delete_wifi_psk_connection_(args): + if create_and_delete_wifi_psk_connection_async(args): print(f"Succeeded in creating and deleting connection {args.uuid}") From d26e95b2606fe3503be82fa401e8b0ba315ff09a Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 19:23:14 +0200 Subject: [PATCH 12/80] Add docstrings to the new helper functions from #35 PR #35 also added docstrings to the new helpers in sdbus_block, now add the same also to sdbus_async/networkmanager/objects.py --- sdbus_async/networkmanager/objects.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sdbus_async/networkmanager/objects.py b/sdbus_async/networkmanager/objects.py index 0c643fc..f643b38 100644 --- a/sdbus_async/networkmanager/objects.py +++ b/sdbus_async/networkmanager/objects.py @@ -181,12 +181,21 @@ async def get_connections_by_id(self, connection_id: str) -> List[str]: async def get_settings_by_uuid( self, connection_uuid: str ) -> NetworkManagerConnectionProperties: + """Helper to get a nested settings dict of a connection profile by uuid. + + :param str connection_uuid: The connection uuid of the connection profile + :return: Nested dictionary of all settings of the given connection profile + """ connection = await self.get_connection_by_uuid(connection_uuid) connection_manager = NetworkConnectionSettings(connection) connection_settings = await connection_manager.get_settings() return connection_settings async def delete_connection_by_uuid(self, connection_uuid: str) -> None: + """Helper to delete a connection profile identified by the connection uuid. + + :param str connection_uuid: The connection uuid of the connection profile + """ conn_dbus_path = await self.get_connection_by_uuid(connection_uuid) connection_settings_manager = NetworkConnectionSettings(conn_dbus_path) await connection_settings_manager.delete() @@ -216,6 +225,10 @@ def __init__(self, settings_path: str, bus) async def connection_profile(self) -> ConnectionProfile: + """Return a ConnectionProfile object containing all profile settings + + :return: Nested dataclass containing all settings of the profile + """ return ConnectionProfile.from_dbus(await self.get_settings()) From 86f78a00bf4ba65be9931337b16f80ae8132f268 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 29 Jun 2022 16:39:57 +0200 Subject: [PATCH 13/80] enums.py: Fix ConnectionType and show it's use. ConnectionType gives a 1:1 map from a DeviceType.name to a profile.connection.connection_type value, which can be used to find usable connections for a given DeviceType. Fix ConnectionType (added very recently, not yet released) to not use ConnectionType.WIRED for an Ethernet connection but ConnectionType.ETHERNET, which matches DeviceType.ETHERNET. Since ConnectionType is new, the fix is safe to apply now. Demonstrate it's use in the netdevinfo examples like shown in PR #36 with conn_type = getattr(ConnectionType, dev_type). --- examples/async/netdevinfo-async.py | 56 ++++++++++++++++++- examples/block/netdevinfo.py | 86 +++++++++++++++++++++++------ sdbus_async/networkmanager/enums.py | 7 ++- 3 files changed, 128 insertions(+), 21 deletions(-) diff --git a/examples/async/netdevinfo-async.py b/examples/async/netdevinfo-async.py index 8f3a6ff..9d798de 100755 --- a/examples/async/netdevinfo-async.py +++ b/examples/async/netdevinfo-async.py @@ -10,7 +10,10 @@ import asyncio import sdbus from sdbus_async.networkmanager import ( + ConnectionType, + NetworkConnectionSettings, NetworkManager, + NetworkManagerSettings, NetworkDeviceGeneric, IPv4Config, DeviceType, @@ -18,10 +21,46 @@ WiFiOperationMode, AccessPoint, ) -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Optional, Tuple NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] +async def get_most_recent_connection_id(ifname, dev_type) -> Optional[str]: + """Return the most-recently used connection_id for this device + + Besides getting the currently active connection, this will succeed + in getting the most recent connection when a device is not connected + at the moment this function is executed. + + It uses getattr(ConnectionType, dev_type) to get the connection_type + used for connection_profiles for this DeviceType. + + With a slight modification, this could return the most recent connections + of the given device, ordered by the time of the last use of them. + """ + settings_service = NetworkManagerSettings() + connection_paths: List[str] = await settings_service.connections + conns = {} + for connection_path in connection_paths: + connection_manager = NetworkConnectionSettings(connection_path) + connection = (await connection_manager.connection_profile()).connection + # Filter connection profiles matching the connection type for the device: + if connection.connection_type != getattr(ConnectionType, dev_type): + continue + # If the interface_name of a connection profiles is set, it must match: + if connection.interface_name and connection.interface_name != ifname: + continue + # If connection.timestamp is not set, it was never active. Set it to 0: + if not connection.timestamp: + connection.timestamp = 0 + # Record the connection_ids of the matches, and timestamp is the key: + conns[connection.timestamp] = connection.connection_id + if not len(conns): + return None + # Returns the connection_id of the highest timestamp which was found: + return conns.get(max(conns.keys())) + + async def list_networkdevice_details_async() -> None: nm = NetworkManager() devices_paths = await nm.get_devices() @@ -31,11 +70,19 @@ async def list_networkdevice_details_async() -> None: device_ip4_conf_path: str = await generic_device.ip4_config if device_ip4_conf_path == "/": continue + if not await generic_device.managed: + continue + dev_type = DeviceType(await generic_device.device_type).name + if dev_type == DeviceType.BRIDGE.name: + continue + dev_name = await generic_device.interface ip4_conf = IPv4Config(device_ip4_conf_path) gateway: str = await ip4_conf.gateway - print("Device: ", await generic_device.interface) + print("Type: ", dev_type.title()) + print("Name: ", dev_name) + if gateway: print("Gateway:", gateway) @@ -47,7 +94,7 @@ async def list_networkdevice_details_async() -> None: for dns in nameservers: print("DNS: ", dns["address"][1]) - if await generic_device.device_type == DeviceType.WIFI: + if dev_type == DeviceType.WIFI.name: wifi = NetworkDeviceWireless(device_path) print("Wifi: ", WiFiOperationMode(await wifi.mode).name.title()) ap = AccessPoint(await wifi.active_access_point) @@ -56,6 +103,9 @@ async def list_networkdevice_details_async() -> None: print("SSID: ", ssid.decode("utf-8", "ignore")) if await ap.strength: print("Signal: ", await ap.strength) + connection_id = await get_most_recent_connection_id(dev_name, dev_type) + if connection_id: + print("Profile:", connection_id) print("") diff --git a/examples/block/netdevinfo.py b/examples/block/netdevinfo.py index 5004067..e53ed6a 100755 --- a/examples/block/netdevinfo.py +++ b/examples/block/netdevinfo.py @@ -9,7 +9,10 @@ # https://networkmanager.dev/docs/api/latest/ref-dbus-devices.html import sdbus from sdbus_block.networkmanager import ( + ConnectionType, + NetworkConnectionSettings, NetworkManager, + NetworkManagerSettings, NetworkDeviceGeneric, IPv4Config, DeviceType, @@ -17,38 +20,89 @@ WiFiOperationMode, AccessPoint, ) +from typing import Any, Dict, List, Optional, Tuple +NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] + + +def get_most_recent_connection_id(ifname, dev_type) -> Optional[str]: + """Return the most-recently used connection_id for this device + + Besides getting the currently active connection, this will succeed + in getting the most recent connection when a device is not connected + at the moment this function is executed. + + It uses getattr(ConnectionType, dev_type) to get the connection_type + used for connection_profiles for this DeviceType. + + With a slight modification, this could return the most recent connections + of the given device, ordered by the time of the last use of them. + """ + settings_service = NetworkManagerSettings() + connection_paths: List[str] = settings_service.connections + conns = {} + for connection_path in connection_paths: + connection_manager = NetworkConnectionSettings(connection_path) + connection = connection_manager.connection_profile().connection + # Filter connection profiles matching the connection type for the device: + if connection.connection_type != getattr(ConnectionType, dev_type): + continue + # If the interface_name of a connection profiles is set, it must match: + if connection.interface_name and connection.interface_name != ifname: + continue + # If connection.timestamp is not set, it was never active. Set it to 0: + if not connection.timestamp: + connection.timestamp = 0 + # Record the connection_ids of the matches, and timestamp is the key: + conns[connection.timestamp] = connection.connection_id + if not len(conns): + return None + # Returns the connection_id of the highest timestamp which was found: + return conns.get(max(conns.keys())) def list_networkdevice_details_blocking() -> None: - nm = NetworkManager() - devices_paths = nm.get_devices() - for device_path in devices_paths: + for device_path in NetworkManager().get_devices(): generic_device = NetworkDeviceGeneric(device_path) - device_ip4_conf_path = generic_device.ip4_config + device_ip4_conf_path: str = generic_device.ip4_config if device_ip4_conf_path == "/": continue + if not generic_device.managed: + continue + dev_type = DeviceType(generic_device.device_type).name + if dev_type == DeviceType.BRIDGE.name: + continue + dev_name = generic_device.interface ip4_conf = IPv4Config(device_ip4_conf_path) + gateway: str = ip4_conf.gateway + + print("Type: ", dev_type.title()) + print("Name: ", dev_name) - print("Device: ", generic_device.interface) - if ip4_conf.gateway: - print("Gateway:", ip4_conf.gateway) + if gateway: + print("Gateway:", gateway) - for ip4addr in ip4_conf.address_data: - print(f'Address: {ip4addr["address"][1]}/{ip4addr["prefix"][1]}') + address_data: NetworkManagerAddressData = ip4_conf.address_data + for inetaddr in address_data: + print(f'Address: {inetaddr["address"][1]}/{inetaddr["prefix"][1]}') - for dns in ip4_conf.nameserver_data: + nameservers: NetworkManagerAddressData = ip4_conf.nameserver_data + for dns in nameservers: print("DNS: ", dns["address"][1]) - if generic_device.device_type == DeviceType.WIFI: - wifidevice = NetworkDeviceWireless(device_path) - print("Wifi: ", WiFiOperationMode(wifidevice.mode).name.title()) - ap = AccessPoint(wifidevice.active_access_point) - if ap.ssid: - print("SSID: ", ap.ssid.decode("utf-8", "ignore")) + if dev_type == DeviceType.WIFI.name: + wifi = NetworkDeviceWireless(device_path) + print("Wifi: ", WiFiOperationMode(wifi.mode).name.title()) + ap = AccessPoint(wifi.active_access_point) + ssid: bytes = ap.ssid + if ssid: + print("SSID: ", ssid.decode("utf-8", "ignore")) if ap.strength: print("Signal: ", ap.strength) + connection_id = get_most_recent_connection_id(dev_name, dev_type) + if connection_id: + print("Profile:", connection_id) print("") diff --git a/sdbus_async/networkmanager/enums.py b/sdbus_async/networkmanager/enums.py index 5a4ca10..03765f6 100644 --- a/sdbus_async/networkmanager/enums.py +++ b/sdbus_async/networkmanager/enums.py @@ -489,6 +489,9 @@ class DeviceStateReason(IntEnum): # sed 's/#define //;s/_SETTING_NAME//;s/ /=/' >.setting_defines # grep -f .connection_is_type .setting_defines | # sed 's/NM_SETTING_/ /;s/6L/SIXL/;/GENERIC/d;s/=/ = /' +# Manual edit: This resulted in WIRED instead of ETHERNET, but +# ETHERNET is the name used for DeviceType, so use ETHERNET instead to +# be able to lookup connection profiles for Ethernet using DeviceType. # # One src/core/nm-device-*.c can support more than one ConnectionType, # thus there are more ConnectionTypes than DeviceTypes: @@ -503,6 +506,7 @@ class ConnectionType(str, Enum): * BRIDGE * CDMA * DUMMY + * ETHERNET * GSM * INFINIBAND * IP_TUNNEL @@ -522,7 +526,6 @@ class ConnectionType(str, Enum): * VRF * VXLAN * WIFI_P2P - * WIRED * WIREGUARD * WIFI * WPAN @@ -533,6 +536,7 @@ class ConnectionType(str, Enum): BRIDGE = "bridge" CDMA = "cdma" DUMMY = "dummy" + ETHERNET = "802-3-ethernet" GSM = "gsm" INFINIBAND = "infiniband" IP_TUNNEL = "ip-tunnel" @@ -552,7 +556,6 @@ class ConnectionType(str, Enum): VRF = "vrf" VXLAN = "vxlan" WIFI_P2P = "wifi-p2p" - WIRED = "802-3-ethernet" WIREGUARD = "wireguard" WIFI = "802-11-wireless" WPAN = "wpan" From 3f4b4b55cf5c149d65096c79e74f4bde6a5d326b Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 3 Jul 2022 14:56:19 +0200 Subject: [PATCH 14/80] tools/generate-settings-dataclasses.py: Generate attr docstrings(1/2) Prepare to generate docstrings for the attributes of settings_classes. Even though they are not parsed by python itself, they can be used to generate documentation for the settings dataclasses. To not require manual edits after code generation, it was needed to implement sorting of required attributes like connection_id, -type and uuid before other attributes. The new functions for this are derived from the existing sort function for the settings_classes where we need the connection as first attribute of the profile because likewise, it is not an optional attribute. The switch to enable generating the attribute docstrings is deferred to the next commit, to make reviewing this change above (which does not change the established code) and the minor change below easier: There is a minor change in the established code but only regarding sdbus_async/networkmanager/settings/bond.py whose attributes are not actually required and should be optional. Making them required was a quick hack around some issue I don't recall the exact details of, and should be adressed at its source anyway. This is the only code change as result of running the updated tool, and the next commit will enable the switch to generate the docstrings. To aid in understanding and (in the future, reworking) the code for use in the new upcoming generator based on Jinja2, this also adds a few comments and docstrings for navigating the code. I guess this may help be a step towards adressing PR #31, for documenting new Settings helpers classes. --- sdbus_async/networkmanager/settings/bond.py | 6 +- tools/generate-settings-dataclasses.py | 77 +++++++++++++++++---- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/sdbus_async/networkmanager/settings/bond.py b/sdbus_async/networkmanager/settings/bond.py index 701dba9..d98bede 100644 --- a/sdbus_async/networkmanager/settings/bond.py +++ b/sdbus_async/networkmanager/settings/bond.py @@ -11,9 +11,11 @@ class BondSettings(NetworkManagerSettingsMixin): """Bonding Settings""" - interface_name: str = field( + interface_name: Optional[str] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + default=None, ) - options: Dict[str, str] = field( + options: Optional[Dict[str, str]] = field( metadata={'dbus_name': 'options', 'dbus_type': 'a{ss}'}, + default={'Mode': 'Balance-Rr'}, ) diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 3885d53..bd380b8 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# Based on NetworkManager-1.39.2/tools/generate-docs-nm-settings-docs-merge.py # SPDX-License-Identifier: LGPL-2.1-or-later import collections import textwrap @@ -57,6 +58,7 @@ def write(msg: Any) -> None: ############################################################################### +# Order of the connection types(settings_classes) in the profile dataclass: _setting_name_order = [ "connection", "ipv4", @@ -112,6 +114,7 @@ def write(msg: Any) -> None: "wpan", ] +# List of modules for which we must generate an import of typing.List list_modules = [ "bridge", "bridge_port", @@ -134,8 +137,29 @@ def write(msg: Any) -> None: "wireless_security", ] +# Order of special properties which must be first because they are not optional +_property_name_order = [ + "connection.id", + "connection.type", + "connection.uuid", +] + +def _property_name_order_idx(name: str) -> int: + """Return the sort index for the given connection setting property""" + try: + return _property_name_order.index(name) + except ValueError: + # Properties not in _property_name_order are sorted last and then by their name + return len(_property_name_order) + + +def key_fcn_property_name(n1: str) -> Tuple[int, str]: + """key function for sorted(), used to sort connection properties""" + return (_property_name_order_idx(n1), n1) + def _setting_name_order_idx(name: str) -> int: + """Return the sort index for the given connection type(settings_class)""" try: return _setting_name_order.index(name) except ValueError: @@ -143,13 +167,20 @@ def _setting_name_order_idx(name: str) -> int: def key_fcn_setting_name(n1: str) -> Tuple[int, str]: + """key function for sorted(), used to sort the settings_classes(connection types)""" return (_setting_name_order_idx(n1), n1) def iter_keys_of_dicts( - dicts: List[Dict[str, Any]], key: Optional[Any] = None + dicts: List[Dict[str, Any]], key: Optional[Any] = None, prefix: Optional[str] = "" ) -> List[str]: - keys = {k for d in dicts for k in d.keys()} + """Return a sorted list of settings_classes or connection properties + + To support sorting the required properites of settings_classes first, + the settingsname can be passed ad prefix argument to let the key function + return the correct sort index for the given settingsname property. + """ + keys = {f'{prefix}{k}' for d in dicts for k in d.keys()} return sorted(keys, key=key) @@ -185,6 +216,8 @@ def find_first_not_none(itr: List[Any]) -> Optional[Any]: return next((i for i in itr if i is not None), None) +# The code quality of this function is poor(Sourcery says 5%), needs refactoring, +# also see the rework in tools/generate-settings-dataclasses-jinja.py def main(settings_xml_path: Path) -> None: gl_input_files = [settings_xml_path] @@ -194,25 +227,30 @@ def main(settings_xml_path: Path) -> None: for root in xml_roots] root_node = ElementTree.Element("nm-setting-docs") - # print("") + + # Generate the file header license = "SPDX-License-Identifier: LGPL-2.1-or-later" script = ("This file was generated by " "tools/generate-settings-dataclasses.py") header = f"""# {license}\n# {script}, - # if possible, please make changes by also updating the script. - """ +# if possible, please make changes by also updating the script.\n""" i = open("sdbus_async/networkmanager/settings/__init__.py", mode="w") p = open("sdbus_async/networkmanager/settings/profile.py", mode="r") profile_py = open("sdbus_async/networkmanager/settings/profile.py").read() + + # define start and end markers for generating part of settings/profile.py: start_string = "# start of the generated list of settings classes\n" start_index = profile_py.index(start_string) + len(start_string) - # end_string = " def to_dbus" end_string = " # end of the generated list of settings classes\n" end_index = profile_py.index(end_string) p = open("sdbus_async/networkmanager/settings/profile.py", mode="w") + + # write the file headers i.write(header) p.write(profile_py[:start_index]) classes = [] + + # generate the connection type settings classes: for settingname in iter_keys_of_dicts(settings_roots, key_fcn_setting_name): settings = [d.get(settingname) for d in settings_roots] @@ -235,6 +273,8 @@ def main(settings_xml_path: Path) -> None: i.write(f"from .{module} import {classname}\n") classes.append(classname) f = open(f"sdbus_async/networkmanager/settings/{module}.py", mode="w") + + # Generate module type headers with the needed import statements f.write(header) f.write("from __future__ import annotations\n") f.write("from dataclasses import dataclass, field\n") @@ -255,6 +295,7 @@ def main(settings_xml_path: Path) -> None: f.write("from .datatypes import WireguardPeers as Peers\n") f.write("\n\n") + # Generate the settings_class and it's entry in profile.py: setting_node = ElementTree.SubElement(root_node, "setting") if module != "connection": p.write(f" {module}: Optional[{classname}] = field(\n") @@ -265,10 +306,15 @@ def main(settings_xml_path: Path) -> None: f.write("@dataclass\n") f.write(f"class {classname}(NetworkManagerSettingsMixin):\n") setting_node.set("name", settingname) + + # generate the docstring of the new settings_class desc = node_get_attr(settings, "description") f.write(' """' + desc + '"""\n\n') - # node_set_attr(setting_node, "alias", settings) - for property_name in iter_keys_of_dicts(properties): + + # Generate the attributes of the settings_class for this profile type: + + for property in iter_keys_of_dicts(properties, key_fcn_property_name, f'{settingname}.'): + property_name = property[len(settingname)+1:] properties_attrs = [p.get(property_name) for p in properties] property_node = ElementTree.SubElement(setting_node, "property") property_node.set("name", property_name) @@ -306,7 +352,7 @@ def main(settings_xml_path: Path) -> None: f.write(f" default={str(default).title()},\n )\n") else: attribute_type = dbus_type_name_map[dbustype] - optional = module != "bond" + optional = property not in _property_name_order if optional: f.write(f" {attribute}: Optional[{attribute_type}]") else: @@ -329,21 +375,26 @@ def main(settings_xml_path: Path) -> None: if optional: f.write(f" default={str(default).title()},\n") f.write(" )\n") + + # Generate docstrings for attributes: Not stored by python, + # but is parsed for generating documentation and be red by + # developers when they lookup the attribute declaration: generate_descriptions_for_attributes = False if generate_descriptions_for_attributes: desc = node_get_attr(properties_attrs, "description") wrapper = textwrap.TextWrapper( - width=74, + width=82, initial_indent=" ", subsequent_indent=" ", ) - lines = wrapper.wrap(text=f'"""{desc}') + lines = wrapper.wrap(text=f'"""{desc}"""') if len(lines) == 1: print(lines[0] + '"""') else: for line in lines: - f.write(line) - f.write(' """') + f.write(f'{line}\n') + # If the closing """ shall be on a new line, use: + # f.write(' """\n') f.write("") i.write('\n__all__ = (\n') for cls in classes: From ad53e9bad4196cedb9225fd376e91904bdc31c09 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 3 Jul 2022 15:23:03 +0200 Subject: [PATCH 15/80] tools/generate-settings-dataclasses.py: Generate attr docstrings(2/2) --- tools/generate-settings-dataclasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index bd380b8..6c2c0be 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -379,7 +379,7 @@ def main(settings_xml_path: Path) -> None: # Generate docstrings for attributes: Not stored by python, # but is parsed for generating documentation and be red by # developers when they lookup the attribute declaration: - generate_descriptions_for_attributes = False + generate_descriptions_for_attributes = True if generate_descriptions_for_attributes: desc = node_get_attr(properties_attrs, "description") wrapper = textwrap.TextWrapper( From 90754dbe7e02e073240f9c5375e96a07722eaeb7 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 3 Jul 2022 15:25:14 +0200 Subject: [PATCH 16/80] sdbus_async/networkmanager/settings: Add generated attr docstrings --- .../networkmanager/settings/bluetooth.py | 2 + sdbus_async/networkmanager/settings/bond.py | 6 + .../networkmanager/settings/bond_port.py | 2 + sdbus_async/networkmanager/settings/bridge.py | 52 ++++ .../networkmanager/settings/bridge_port.py | 4 + sdbus_async/networkmanager/settings/cdma.py | 11 + .../networkmanager/settings/connection.py | 156 ++++++++++++ sdbus_async/networkmanager/settings/dcb.py | 48 ++++ .../networkmanager/settings/ethernet.py | 100 ++++++++ sdbus_async/networkmanager/settings/gsm.py | 40 ++++ .../networkmanager/settings/hostname.py | 27 +++ .../networkmanager/settings/ieee802_1x.py | 210 ++++++++++++++++ .../networkmanager/settings/infiniband.py | 11 + .../networkmanager/settings/ip_tunnel.py | 30 +++ sdbus_async/networkmanager/settings/ipv4.py | 212 ++++++++++++++++ sdbus_async/networkmanager/settings/ipv6.py | 226 ++++++++++++++++++ sdbus_async/networkmanager/settings/lowpan.py | 2 + sdbus_async/networkmanager/settings/macsec.py | 14 ++ .../networkmanager/settings/macvlan.py | 6 + sdbus_async/networkmanager/settings/match.py | 36 +++ .../networkmanager/settings/olpc_mesh.py | 3 + .../networkmanager/settings/ovs_dpdk.py | 3 + .../networkmanager/settings/ovs_interface.py | 2 + .../networkmanager/settings/ovs_patch.py | 2 + .../networkmanager/settings/ovs_port.py | 2 + sdbus_async/networkmanager/settings/ppp.py | 31 +++ sdbus_async/networkmanager/settings/pppoe.py | 8 + sdbus_async/networkmanager/settings/proxy.py | 2 + sdbus_async/networkmanager/settings/serial.py | 7 + sdbus_async/networkmanager/settings/team.py | 9 + .../networkmanager/settings/team_port.py | 6 + sdbus_async/networkmanager/settings/tun.py | 14 ++ sdbus_async/networkmanager/settings/user.py | 4 + sdbus_async/networkmanager/settings/veth.py | 2 + sdbus_async/networkmanager/settings/vlan.py | 24 ++ sdbus_async/networkmanager/settings/vpn.py | 19 ++ sdbus_async/networkmanager/settings/vxlan.py | 15 ++ .../networkmanager/settings/wifi_p2p.py | 10 + sdbus_async/networkmanager/settings/wimax.py | 5 + .../networkmanager/settings/wireguard.py | 30 +++ .../networkmanager/settings/wireless.py | 113 +++++++++ .../settings/wireless_security.py | 71 ++++++ sdbus_async/networkmanager/settings/wpan.py | 6 + 43 files changed, 1583 insertions(+) diff --git a/sdbus_async/networkmanager/settings/bluetooth.py b/sdbus_async/networkmanager/settings/bluetooth.py index c678604..d63671d 100644 --- a/sdbus_async/networkmanager/settings/bluetooth.py +++ b/sdbus_async/networkmanager/settings/bluetooth.py @@ -19,3 +19,5 @@ class BluetoothSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'type', 'dbus_type': 's'}, default=None, ) + """Either "dun" for Dial-Up Networking connections or "panu" for Personal Area + Networking connections to devices supporting the NAP profile.""" diff --git a/sdbus_async/networkmanager/settings/bond.py b/sdbus_async/networkmanager/settings/bond.py index d98bede..e7a206a 100644 --- a/sdbus_async/networkmanager/settings/bond.py +++ b/sdbus_async/networkmanager/settings/bond.py @@ -15,7 +15,13 @@ class BondSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, default=None, ) + """Deprecated in favor of connection.interface-name, but can be used for + backward-compatibility with older daemons, to set the bond's interface + name.""" options: Optional[Dict[str, str]] = field( metadata={'dbus_name': 'options', 'dbus_type': 'a{ss}'}, default={'Mode': 'Balance-Rr'}, ) + """Dictionary of key/value pairs of bonding options. Both keys and values + must be strings. Option names must contain only alphanumeric characters (ie, + [a-zA-Z0-9]).""" diff --git a/sdbus_async/networkmanager/settings/bond_port.py b/sdbus_async/networkmanager/settings/bond_port.py index 357cb3f..1c022ea 100644 --- a/sdbus_async/networkmanager/settings/bond_port.py +++ b/sdbus_async/networkmanager/settings/bond_port.py @@ -15,3 +15,5 @@ class BondPortSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'queue-id', 'dbus_type': 'u'}, default=None, ) + """The queue ID of this bond port. The maximum value of queue ID is the number + of TX queues currently active in device.""" diff --git a/sdbus_async/networkmanager/settings/bridge.py b/sdbus_async/networkmanager/settings/bridge.py index c1a7101..638088d 100644 --- a/sdbus_async/networkmanager/settings/bridge.py +++ b/sdbus_async/networkmanager/settings/bridge.py @@ -24,10 +24,19 @@ class BridgeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'group-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, The MAC address of the multicast group this bridge uses for + STP. The address must be a link-local address in standard Ethernet MAC address + format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If + not specified the default value is 01:80:C2:00:00:00.""" group_forward_mask: Optional[int] = field( metadata={'dbus_name': 'group-forward-mask', 'dbus_type': 'u'}, default=None, ) + """A mask of group addresses to forward. Usually, group addresses in the range + from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to + standards. This property is a mask of 16 bits, each corresponding to a group + address in that range that must be forwarded. The mask can't have bits 0, 1 or + 2 set because they are used for STP, MAC pause frames and LACP.""" hello_time: Optional[int] = field( metadata={'dbus_name': 'hello-time', 'dbus_type': 'u'}, default=2, @@ -36,10 +45,19 @@ class BridgeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, default=None, ) + """Deprecated in favor of connection.interface-name, but can be used for + backward-compatibility with older daemons, to set the bridge's interface + name.""" mac_address: Optional[bytes] = field( metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, the MAC address of bridge. When creating a new bridge, this + MAC address will be set. If this field is left unspecified, the + "ethernet.cloned-mac-address" is referred instead to generate the initial MAC + address. Note that setting "ethernet.cloned-mac-address" anyway overwrites the + MAC address of the bridge later while activating the bridge. Hence, this + property is deprecated. Deprecated: 1""" max_age: Optional[int] = field( metadata={'dbus_name': 'max-age', 'dbus_type': 'u'}, default=20, @@ -52,45 +70,68 @@ class BridgeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'multicast-last-member-count', 'dbus_type': 'u'}, default=2, ) + """Set the number of queries the bridge will send before stopping forwarding a + multicast group after a "leave" message has been received.""" multicast_last_member_interval: Optional[int] = field( metadata={'dbus_name': 'multicast-last-member-interval', 'dbus_type': 't'}, default=100, ) + """Set interval (in deciseconds) between queries to find remaining members of + a group, after a "leave" message is received.""" multicast_membership_interval: Optional[int] = field( metadata={'dbus_name': 'multicast-membership-interval', 'dbus_type': 't'}, default=26000, ) + """Set delay (in deciseconds) after which the bridge will leave a group, if no + membership reports for this group are received.""" multicast_querier: Optional[bool] = field( metadata={'dbus_name': 'multicast-querier', 'dbus_type': 'b'}, default=False, ) + """Enable or disable sending of multicast queries by the bridge. If not + specified the option is disabled.""" multicast_querier_interval: Optional[int] = field( metadata={'dbus_name': 'multicast-querier-interval', 'dbus_type': 't'}, default=25500, ) + """If no queries are seen after this delay (in deciseconds) has passed, the + bridge will start to send its own queries.""" multicast_query_interval: Optional[int] = field( metadata={'dbus_name': 'multicast-query-interval', 'dbus_type': 't'}, default=12500, ) + """Interval (in deciseconds) between queries sent by the bridge after the end + of the startup phase.""" multicast_query_response_interval: Optional[int] = field( metadata={'dbus_name': 'multicast-query-response-interval', 'dbus_type': 't'}, default=1000, ) + """Set the Max Response Time/Max Response Delay (in deciseconds) for IGMP/MLD + queries sent by the bridge.""" multicast_query_use_ifaddr: Optional[bool] = field( metadata={'dbus_name': 'multicast-query-use-ifaddr', 'dbus_type': 'b'}, default=False, ) + """If enabled the bridge's own IP address is used as the source address for + IGMP queries otherwise the default of 0.0.0.0 is used.""" multicast_router: Optional[str] = field( metadata={'dbus_name': 'multicast-router', 'dbus_type': 's'}, default=None, ) + """Sets bridge's multicast router. Multicast-snooping must be enabled for this + option to work. Supported values are: 'auto', 'disabled', 'enabled' to which + kernel assigns the numbers 1, 0, and 2, respectively. If not specified the + default value is 'auto' (1).""" multicast_snooping: Optional[bool] = field( metadata={'dbus_name': 'multicast-snooping', 'dbus_type': 'b'}, default=True, ) + """Controls whether IGMP snooping is enabled for this bridge. Note that if + snooping was automatically disabled due to hash collisions, the system may + refuse to enable the feature until the collisions are resolved.""" multicast_startup_query_count: Optional[int] = field( metadata={'dbus_name': 'multicast-startup-query-count', 'dbus_type': 'u'}, @@ -101,18 +142,27 @@ class BridgeSettings(NetworkManagerSettingsMixin): 'dbus_type': 't'}, default=3125, ) + """Sets the time (in deciseconds) between queries sent out at startup to + determine membership information.""" priority: Optional[int] = field( metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, default=32768, ) + """Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower + values are "better"; the lowest priority bridge will be elected the root + bridge.""" stp: Optional[bool] = field( metadata={'dbus_name': 'stp', 'dbus_type': 'b'}, default=True, ) + """Controls whether Spanning Tree Protocol (STP) is enabled for this + bridge.""" vlan_default_pvid: Optional[int] = field( metadata={'dbus_name': 'vlan-default-pvid', 'dbus_type': 'u'}, default=1, ) + """The default PVID for the ports of the bridge, that is the VLAN id assigned + to incoming untagged frames.""" vlan_filtering: Optional[bool] = field( metadata={'dbus_name': 'vlan-filtering', 'dbus_type': 'b'}, default=False, @@ -121,6 +171,8 @@ class BridgeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'vlan-protocol', 'dbus_type': 's'}, default=None, ) + """If specified, the protocol used for VLAN filtering. Supported values are: + '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.""" vlan_stats_enabled: Optional[bool] = field( metadata={'dbus_name': 'vlan-stats-enabled', 'dbus_type': 'b'}, default=False, diff --git a/sdbus_async/networkmanager/settings/bridge_port.py b/sdbus_async/networkmanager/settings/bridge_port.py index 56b6e96..a549378 100644 --- a/sdbus_async/networkmanager/settings/bridge_port.py +++ b/sdbus_async/networkmanager/settings/bridge_port.py @@ -16,10 +16,14 @@ class BridgePortSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'hairpin-mode', 'dbus_type': 'b'}, default=False, ) + """Enables or disables "hairpin mode" for the port, which allows frames to be + sent back out through the port the frame was received on.""" path_cost: Optional[int] = field( metadata={'dbus_name': 'path-cost', 'dbus_type': 'u'}, default=100, ) + """The Spanning Tree Protocol (STP) port cost for destinations via this + port.""" priority: Optional[int] = field( metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, default=32, diff --git a/sdbus_async/networkmanager/settings/cdma.py b/sdbus_async/networkmanager/settings/cdma.py index 92156fa..ab518f4 100644 --- a/sdbus_async/networkmanager/settings/cdma.py +++ b/sdbus_async/networkmanager/settings/cdma.py @@ -15,14 +15,22 @@ class CdmaSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple frames.""" number: Optional[str] = field( metadata={'dbus_name': 'number', 'dbus_type': 's'}, default=None, ) + """The number to dial to establish the connection to the CDMA-based mobile + broadband network, if any. If not specified, the default number (#777) is + used when required.""" password: Optional[str] = field( metadata={'dbus_name': 'password', 'dbus_type': 's'}, default=None, ) + """The password used to authenticate with the network, if required. Many + providers do not require a password, or accept any password. But if a + password is required, it is specified here.""" password_flags: Optional[int] = field( metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, default=None, @@ -31,3 +39,6 @@ class CdmaSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'username', 'dbus_type': 's'}, default=None, ) + """The username used to authenticate with the network, if required. Many + providers do not require a username, or accept any username. But if a + username is required, it is specified here.""" diff --git a/sdbus_async/networkmanager/settings/connection.py b/sdbus_async/networkmanager/settings/connection.py index 5d04617..38ed3a8 100644 --- a/sdbus_async/networkmanager/settings/connection.py +++ b/sdbus_async/networkmanager/settings/connection.py @@ -14,44 +14,108 @@ class ConnectionSettings(NetworkManagerSettingsMixin): connection_id: str = field( metadata={'dbus_name': 'id', 'dbus_type': 's'}, ) + """A human readable unique identifier for the connection, like "Work Wi-Fi" or + "T-Mobile 3G".""" connection_type: str = field( metadata={'dbus_name': 'type', 'dbus_type': 's'}, ) + """Base type of the connection. For hardware-dependent connections, should + contain the setting name of the hardware-type specific setting (ie, + "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non- + hardware dependent connections like VPN or otherwise, should contain the + setting name of that setting type (ie, "vpn" or "bridge", etc).""" uuid: str = field( metadata={'dbus_name': 'uuid', 'dbus_type': 's'}, ) + """A universally unique identifier for the connection, for example generated + with libuuid. It should be assigned when the connection is created, and never + changed as long as the connection still applies to the same network. For + example, it should not be changed when the "id" property or NMSettingIP4Config + changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband + network provider, or "type" property changes. The UUID must be in the format + "2815492f-7e56-435e-b2e9-246bd7cdc664" (ie, contains only hexadecimal + characters and "-").""" auth_retries: Optional[int] = field( metadata={'dbus_name': 'auth-retries', 'dbus_type': 'i'}, default=None, ) + """The number of retries for the authentication. Zero means to try + indefinitely; -1 means to use a global default. If the global default is not + set, the authentication retries for 3 times before failing the connection. + Currently, this only applies to 802-1x authentication.""" autoconnect: Optional[bool] = field( metadata={'dbus_name': 'autoconnect', 'dbus_type': 'b'}, default=True, ) + """Whether or not the connection should be automatically connected by + NetworkManager when the resources for the connection are available. TRUE to + automatically activate the connection, FALSE to require manual intervention to + activate the connection. Autoconnect happens when the circumstances are + suitable. That means for example that the device is currently managed and not + active. Autoconnect thus never replaces or competes with an already active + profile. Note that autoconnect is not implemented for VPN profiles. See + "secondaries" as an alternative to automatically connect VPN profiles.""" autoconnect_priority: Optional[int] = field( metadata={'dbus_name': 'autoconnect-priority', 'dbus_type': 'i'}, default=None, ) + """The autoconnect priority in range -999 to 999. If the connection is set to + autoconnect, connections with higher priority will be preferred. The higher + number means higher priority. Defaults to 0. Note that this property only + matters if there are more than one candidate profile to select for + autoconnect. In case of equal priority, the profile used most recently is + chosen.""" autoconnect_retries: Optional[int] = field( metadata={'dbus_name': 'autoconnect-retries', 'dbus_type': 'i'}, default=None, ) + """The number of times a connection should be tried when autoactivating before + giving up. Zero means forever, -1 means the global default (4 times if not + overridden). Setting this to 1 means to try activation only once before + blocking autoconnect. Note that after a timeout, NetworkManager will try to + autoconnect again.""" autoconnect_slaves: Optional[int] = field( metadata={'dbus_name': 'autoconnect-slaves', 'dbus_type': 'i'}, default=None, ) + """Whether or not slaves of this connection should be automatically brought up + when NetworkManager activates this connection. This only has a real effect for + master connections. The properties "autoconnect", "autoconnect-priority" and + "autoconnect-retries" are unrelated to this setting. The permitted values are: + 0: leave slave connections untouched, 1: activate all the slave connections + with this connection, -1: default. If -1 (default) is set, global + connection.autoconnect-slaves is read to determine the real value. If it is + default as well, this fallbacks to 0.""" dns_over_tls: Optional[int] = field( metadata={'dbus_name': 'dns-over-tls', 'dbus_type': 'i'}, default=None, ) + """Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls + is a technology which uses TLS to encrypt dns traffic. The permitted values + are: "yes" (2) use DNSOverTls and disabled fallback, "opportunistic" (1) use + DNSOverTls but allow fallback to unencrypted resolution, "no" (0) don't ever + use DNSOverTls. If unspecified "default" depends on the plugin used. Systemd- + resolved uses global setting. This feature requires a plugin which supports + DNSOverTls. Otherwise, the setting has no effect. One such plugin is dns- + systemd-resolved.""" gateway_ping_timeout: Optional[int] = field( metadata={'dbus_name': 'gateway-ping-timeout', 'dbus_type': 'u'}, default=None, ) + """If greater than zero, delay success of IP addressing until either the + timeout is reached, or an IP gateway replies to a ping.""" interface_name: Optional[str] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, default=None, ) + """The name of the network interface this connection is bound to. If not set, + then the connection can be attached to any interface of the appropriate type + (subject to restrictions imposed by other settings). For software devices this + specifies the name of the created device. For connection types where interface + names cannot easily be made persistent (e.g. mobile broadband or USB + Ethernet), this property should not be used. Setting this property restricts + the interfaces a connection can be used with, and if interface names change or + are reordered the connection may be applied to the wrong interface.""" lldp: Optional[int] = field( metadata={'dbus_name': 'lldp', 'dbus_type': 'i'}, default=None, @@ -60,6 +124,16 @@ class ConnectionSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'llmnr', 'dbus_type': 'i'}, default=None, ) + """Whether Link-Local Multicast Name Resolution (LLMNR) is enabled for the + connection. LLMNR is a protocol based on the Domain Name System (DNS) packet + format that allows both IPv4 and IPv6 hosts to perform name resolution for + hosts on the same local link. The permitted values are: "yes" (2) register + hostname and resolving for the connection, "no" (0) disable LLMNR for the + interface, "resolve" (1) do not register hostname but allow resolving of LLMNR + host names If unspecified, "default" ultimately depends on the DNS plugin + (which for systemd-resolved currently means "yes"). This feature requires a + plugin which supports LLMNR. Otherwise, the setting has no effect. One such + plugin is dns-systemd-resolved.""" master: Optional[str] = field( metadata={'dbus_name': 'master', 'dbus_type': 's'}, default=None, @@ -68,47 +142,129 @@ class ConnectionSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mdns', 'dbus_type': 'i'}, default=None, ) + """Whether mDNS is enabled for the connection. The permitted values are: "yes" + (2) register hostname and resolving for the connection, "no" (0) disable mDNS + for the interface, "resolve" (1) do not register hostname but allow resolving + of mDNS host names and "default" (-1) to allow lookup of a global default in + NetworkManager.conf. If unspecified, "default" ultimately depends on the DNS + plugin (which for systemd-resolved currently means "no"). This feature + requires a plugin which supports mDNS. Otherwise, the setting has no effect. + One such plugin is dns-systemd-resolved.""" metered: Optional[int] = field( metadata={'dbus_name': 'metered', 'dbus_type': 'i'}, default=None, ) + """Whether the connection is metered. When updating this property on a + currently activated connection, the change takes effect immediately.""" mud_url: Optional[str] = field( metadata={'dbus_name': 'mud-url', 'dbus_type': 's'}, default=None, ) + """If configured, set to a Manufacturer Usage Description (MUD) URL that + points to manufacturer-recommended network policies for IoT devices. It is + transmitted as a DHCPv4 or DHCPv6 option. The value must be a valid URL + starting with "https://". The special value "none" is allowed to indicate that + no MUD URL is used. If the per-profile value is unspecified (the default), a + global connection default gets consulted. If still unspecified, the ultimate + default is "none".""" multi_connect: Optional[int] = field( metadata={'dbus_name': 'multi-connect', 'dbus_type': 'i'}, default=None, ) + """Specifies whether the profile can be active multiple times at a particular + moment. The value is of type NMConnectionMultiConnect.""" permissions: Optional[List[str]] = field( metadata={'dbus_name': 'permissions', 'dbus_type': 'as'}, default=None, ) + """An array of strings defining what access a given user has to this + connection. If this is NULL or empty, all users are allowed to access this + connection; otherwise users are allowed if and only if they are in this list. + When this is not empty, the connection can be active only when one of the + specified users is logged into an active session. Each entry is of the form + "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". At this time only the + "user" [type] is allowed. Any other values are ignored and reserved for + future use. [id] is the username that this permission refers to, which may + not contain the ":" character. Any [reserved] information present must be + ignored and is reserved for future use. All of [type], [id], and [reserved] + must be valid UTF-8.""" read_only: Optional[bool] = field( metadata={'dbus_name': 'read-only', 'dbus_type': 'b'}, default=False, ) + """FALSE if the connection can be modified using the provided settings + service's D-Bus interface with the right privileges, or TRUE if the connection + is read-only and cannot be modified.""" secondaries: Optional[List[str]] = field( metadata={'dbus_name': 'secondaries', 'dbus_type': 'as'}, default=None, ) + """List of connection UUIDs that should be activated when the base connection + itself is activated. Currently, only VPN connections are supported.""" slave_type: Optional[str] = field( metadata={'dbus_name': 'slave-type', 'dbus_type': 's'}, default=None, ) + """Setting name of the device type of this slave's master connection (eg, + "bond"), or NULL if this connection is not a slave.""" stable_id: Optional[str] = field( metadata={'dbus_name': 'stable-id', 'dbus_type': 's'}, default=None, ) + """This represents the identity of the connection used for various purposes. + It allows to configure multiple profiles to share the identity. Also, the + stable-id can contain placeholders that are substituted dynamically and + deterministically depending on the context. The stable-id is used for + generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable- + privacy. It is also used to seed the generated cloned MAC address for + ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is + also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to + derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that + depending on the context where it is used, other parameters are also seeded + into the generation algorithm. For example, a per-host key is commonly also + included, so that different systems end up generating different IDs. Or with + ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that + different interfaces yield different addresses. The per-host key is the + identity of your machine and stored in /var/lib/NetworkManager/secret-key. The + '$' character is treated special to perform dynamic substitutions at runtime. + Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", "${BOOT}", + "${RANDOM}". These effectively create unique IDs per-connection, per-device, + per-boot, or every time. Note that "${DEVICE}" corresponds to the interface + name of the device and "${MAC}" is the permanent MAC address of the device. + Any unrecognized patterns following '$' are treated verbatim, however are + reserved for future use. You are thus advised to avoid '$' or escape it as + "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a + unique id for this connection that changes with every reboot and differs + depending on the interface where the profile activates. If the value is unset, + a global connection default is consulted. If the value is still unset, the + default is similar to "${CONNECTION}" and uses a unique, fixed ID for the + connection.""" timestamp: Optional[int] = field( metadata={'dbus_name': 'timestamp', 'dbus_type': 't'}, default=None, ) + """The time, in seconds since the Unix Epoch, that the connection was last + _successfully_ fully activated. NetworkManager updates the connection + timestamp periodically when the connection is active to ensure that an active + connection has the latest timestamp. The property is only meant for reading + (changes to this property will not be preserved).""" wait_device_timeout: Optional[int] = field( metadata={'dbus_name': 'wait-device-timeout', 'dbus_type': 'i'}, default=None, ) + """Timeout in milliseconds to wait for device at startup. During boot, devices + may take a while to be detected by the driver. This property will cause to + delay NetworkManager-wait-online.service and nm-online to give the device a + chance to appear. This works by waiting for the given timeout until a + compatible device for the profile is available and managed. The value 0 means + no wait time. The default value is -1, which currently has the same meaning as + no wait time.""" zone: Optional[str] = field( metadata={'dbus_name': 'zone', 'dbus_type': 's'}, default=None, ) + """The trust level of a the connection. Free form case-insensitive string + (for example "Home", "Work", "Public"). NULL or unspecified zone means the + connection will be placed in the default zone as defined by the firewall. When + updating this property on a currently activated connection, the change takes + effect immediately.""" diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index 95c4cc1..7af0b7f 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -15,59 +15,107 @@ class DcbSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'app-fcoe-flags', 'dbus_type': 'i'}, default=None, ) + """Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may be + any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" app_fcoe_mode: Optional[str] = field( metadata={'dbus_name': 'app-fcoe-mode', 'dbus_type': 's'}, default=None, ) + """The FCoE controller mode; either "fabric" or "vn2vn". Since 1.34, NULL is + the default and means "fabric". Before 1.34, NULL was rejected as invalid and + the default was "fabric".""" app_fcoe_priority: Optional[int] = field( metadata={'dbus_name': 'app-fcoe-priority', 'dbus_type': 'i'}, default=None, ) + """The highest User Priority (0 - 7) which FCoE frames should use, or -1 for + default priority. Only used when the "app-fcoe-flags" property includes the + NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" app_fip_flags: Optional[int] = field( metadata={'dbus_name': 'app-fip-flags', 'dbus_type': 'i'}, default=None, ) + """Specifies the NMSettingDcbFlags for the DCB FIP application. Flags may be + any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" app_fip_priority: Optional[int] = field( metadata={'dbus_name': 'app-fip-priority', 'dbus_type': 'i'}, default=None, ) + """The highest User Priority (0 - 7) which FIP frames should use, or -1 for + default priority. Only used when the "app-fip-flags" property includes the + NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" app_iscsi_flags: Optional[int] = field( metadata={'dbus_name': 'app-iscsi-flags', 'dbus_type': 'i'}, default=None, ) + """Specifies the NMSettingDcbFlags for the DCB iSCSI application. Flags may + be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" app_iscsi_priority: Optional[int] = field( metadata={'dbus_name': 'app-iscsi-priority', 'dbus_type': 'i'}, default=None, ) + """The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for + default priority. Only used when the "app-iscsi-flags" property includes the + NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" priority_bandwidth: Optional[List[int]] = field( metadata={'dbus_name': 'priority-bandwidth', 'dbus_type': 'au'}, default=None, ) + """An array of 8 uint values, where the array index corresponds to the User + Priority (0 - 7) and the value indicates the percentage of bandwidth of the + priority's assigned group that the priority may use. The sum of all + percentages for priorities which belong to the same group must total 100 + percents.""" priority_flow_control: Optional[List[int]] = field( metadata={'dbus_name': 'priority-flow-control', 'dbus_type': 'au'}, default=None, ) + """An array of 8 boolean values, where the array index corresponds to the User + Priority (0 - 7) and the value indicates whether or not the corresponding + priority should transmit priority pause.""" priority_flow_control_flags: Optional[int] = field( metadata={'dbus_name': 'priority-flow-control-flags', 'dbus_type': 'i'}, default=None, ) + """Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags + may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" priority_group_bandwidth: Optional[List[int]] = field( metadata={'dbus_name': 'priority-group-bandwidth', 'dbus_type': 'au'}, default=None, ) + """An array of 8 uint values, where the array index corresponds to the + Priority Group ID (0 - 7) and the value indicates the percentage of link + bandwidth allocated to that group. Allowed values are 0 - 100, and the sum of + all values must total 100 percents.""" priority_group_flags: Optional[int] = field( metadata={'dbus_name': 'priority-group-flags', 'dbus_type': 'i'}, default=None, ) + """Specifies the NMSettingDcbFlags for DCB Priority Groups. Flags may be any + combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE + (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" priority_group_id: Optional[List[int]] = field( metadata={'dbus_name': 'priority-group-id', 'dbus_type': 'au'}, default=None, ) + """An array of 8 uint values, where the array index corresponds to the User + Priority (0 - 7) and the value indicates the Priority Group ID. Allowed + Priority Group ID values are 0 - 7 or 15 for the unrestricted group.""" priority_strict_bandwidth: Optional[List[int]] = field( metadata={'dbus_name': 'priority-strict-bandwidth', 'dbus_type': 'au'}, default=None, ) + """An array of 8 boolean values, where the array index corresponds to the User + Priority (0 - 7) and the value indicates whether or not the priority may use + all of the bandwidth allocated to its assigned group.""" priority_traffic_class: Optional[List[int]] = field( metadata={'dbus_name': 'priority-traffic-class', 'dbus_type': 'au'}, default=None, ) + """An array of 8 uint values, where the array index corresponds to the User + Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which + the priority is mapped.""" diff --git a/sdbus_async/networkmanager/settings/ethernet.py b/sdbus_async/networkmanager/settings/ethernet.py index 07901b9..8b244cd 100644 --- a/sdbus_async/networkmanager/settings/ethernet.py +++ b/sdbus_async/networkmanager/settings/ethernet.py @@ -15,63 +15,163 @@ class EthernetSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'accept-all-mac-addresses', 'dbus_type': 'i'}, default=None, ) + """When TRUE, setup the interface to accept packets for all MAC addresses. + This is enabling the kernel interface flag IFF_PROMISC. When FALSE, the + interface will only accept the packets with the interface destination mac + address or broadcast.""" assigned_mac_address: Optional[str] = field( metadata={'dbus_name': 'assigned-mac-address', 'dbus_type': 's'}, default=None, ) + """The new field for the cloned MAC address. It can be either a hardware + address in ASCII representation, or one of the special values "preserve", + "permanent", "random" or "stable". This field replaces the deprecated "cloned- + mac-address" on D-Bus, which can only contain explicit hardware addresses. + Note that this property only exists in D-Bus API. libnm and nmcli continue to + call this property "cloned-mac-address".""" auto_negotiate: Optional[bool] = field( metadata={'dbus_name': 'auto-negotiate', 'dbus_type': 'b'}, default=False, ) + """When TRUE, enforce auto-negotiation of speed and duplex mode. If "speed" + and "duplex" properties are both specified, only that single mode will be + advertised and accepted during the link auto-negotiation process: this works + only for BASE-T 802.3 specifications and is useful for enforcing gigabits + modes, as in these cases link negotiation is mandatory. When FALSE, "speed" + and "duplex" properties should be both set or link configuration will be + skipped.""" cloned_mac_address: Optional[bytes] = field( metadata={'dbus_name': 'cloned-mac-address', 'dbus_type': 'ay'}, default=None, ) + """This D-Bus field is deprecated in favor of "assigned-mac-address" which is + more flexible and allows specifying special variants like "random". For libnm + and nmcli, this field is called "cloned-mac-address".""" duplex: Optional[str] = field( metadata={'dbus_name': 'duplex', 'dbus_type': 's'}, default=None, ) + """When a value is set, either "half" or "full", configures the device to use + the specified duplex mode. If "auto-negotiate" is "yes" the specified duplex + mode will be the only one advertised during link negotiation: this works only + for BASE-T 802.3 specifications and is useful for enforcing gigabits modes, as + in these cases link negotiation is mandatory. If the value is unset (the + default), the link configuration will be either skipped (if "auto-negotiate" + is "no", the default) or will be auto-negotiated (if "auto-negotiate" is + "yes") and the local device will advertise all the supported duplex modes. + Must be set together with the "speed" property if specified. Before specifying + a duplex mode be sure your device supports it.""" generate_mac_address_mask: Optional[str] = field( metadata={'dbus_name': 'generate-mac-address-mask', 'dbus_type': 's'}, default=None, ) + """With "cloned-mac-address" setting "random" or "stable", by default all bits + of the MAC address are scrambled and a locally-administered, unicast MAC + address is created. This property allows to specify that certain bits are + fixed. Note that the least significant bit of the first MAC address will + always be unset to create a unicast MAC address. If the property is NULL, it + is eligible to be overwritten by a default connection setting. If the value is + still NULL or an empty string, the default is to create a locally- + administered, unicast MAC address. If the value contains one MAC address, this + address is used as mask. The set bits of the mask are to be filled with the + current MAC address of the device, while the unset bits are subject to + randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the + current MAC address and only randomize the lower 3 bytes using the "random" or + "stable" algorithm. If the value contains one additional MAC address after the + mask, this address is used instead of the current MAC address to fill the bits + that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 + 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the + lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" + will create a fully scrambled globally-administered, burned-in MAC address. If + the value contains more than one additional MAC addresses, one of them is + chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 + 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally + or globally administered.""" mac_address: Optional[bytes] = field( metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, this connection will only apply to the Ethernet device whose + permanent MAC address matches. This property does not change the MAC address + of the device (i.e. MAC spoofing).""" mac_address_blacklist: Optional[List[str]] = field( metadata={'dbus_name': 'mac-address-blacklist', 'dbus_type': 'as'}, default=None, ) + """If specified, this connection will never apply to the Ethernet device whose + permanent MAC address matches an address in the list. Each MAC address is in + the standard hex-digits-and-colons notation (00:11:22:33:44:55).""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple Ethernet frames.""" port: Optional[str] = field( metadata={'dbus_name': 'port', 'dbus_type': 's'}, default=None, ) + """Specific port type to use if the device supports multiple attachment + methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit Interface), "bnc" + (Thin Ethernet) or "mii" (Media Independent Interface). If the device supports + only one port type, this setting is ignored.""" s390_nettype: Optional[str] = field( metadata={'dbus_name': 's390-nettype', 'dbus_type': 's'}, default=None, ) + """s390 network device type; one of "qeth", "lcs", or "ctc", representing the + different types of virtual network devices available on s390 systems.""" s390_options: Optional[Dict[str, str]] = field( metadata={'dbus_name': 's390-options', 'dbus_type': 'a{ss}'}, default=None, ) + """Dictionary of key/value pairs of s390-specific device options. Both keys + and values must be strings. Allowed keys include "portno", "layer2", + "portname", "protocol", among others. Key names must contain only + alphanumeric characters (ie, [a-zA-Z0-9]). Currently, NetworkManager itself + does nothing with this information. However, s390utils ships a udev rule which + parses this information and applies it to the interface.""" s390_subchannels: Optional[List[str]] = field( metadata={'dbus_name': 's390-subchannels', 'dbus_type': 'as'}, default=None, ) + """Identifies specific subchannels that this network device uses for + communication with z/VM or s390 host. Like the "mac-address" property for + non-z/VM devices, this property can be used to ensure this connection only + applies to the network device that uses these subchannels. The list should + contain exactly 3 strings, and each string may only be composed of hexadecimal + characters and the period (.) character.""" speed: Optional[int] = field( metadata={'dbus_name': 'speed', 'dbus_type': 'u'}, default=None, ) + """When a value greater than 0 is set, configures the device to use the + specified speed. If "auto-negotiate" is "yes" the specified speed will be the + only one advertised during link negotiation: this works only for BASE-T 802.3 + specifications and is useful for enforcing gigabit speeds, as in this case + link negotiation is mandatory. If the value is unset (0, the default), the + link configuration will be either skipped (if "auto-negotiate" is "no", the + default) or will be auto-negotiated (if "auto-negotiate" is "yes") and the + local device will advertise all the supported speeds. In Mbit/s, ie 100 == + 100Mbit/s. Must be set together with the "duplex" property when non-zero. + Before specifying a speed value be sure your device supports it.""" wake_on_lan: Optional[int] = field( metadata={'dbus_name': 'wake-on-lan', 'dbus_type': 'u'}, default=1, ) + """The NMSettingWiredWakeOnLan options to enable. Not all devices support all + options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), + NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), + NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), + NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), + NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC + (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to + use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to + disable management of Wake-on-LAN in NetworkManager).""" wake_on_lan_password: Optional[str] = field( metadata={'dbus_name': 'wake-on-lan-password', 'dbus_type': 's'}, default=None, ) + """If specified, the password used with magic-packet-based Wake-on-LAN, + represented as an Ethernet MAC address. If NULL, no password will be + required.""" diff --git a/sdbus_async/networkmanager/settings/gsm.py b/sdbus_async/networkmanager/settings/gsm.py index 13b96d2..6353163 100644 --- a/sdbus_async/networkmanager/settings/gsm.py +++ b/sdbus_async/networkmanager/settings/gsm.py @@ -15,34 +15,60 @@ class GsmSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'apn', 'dbus_type': 's'}, default=None, ) + """The GPRS Access Point Name specifying the APN used when establishing a data + session with the GSM-based network. The APN often determines how the user + will be billed for their network usage and whether the user has access to the + Internet or just a provider-specific walled-garden, so it is important to use + the correct APN for the user's mobile broadband plan. The APN may only be + composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.""" auto_config: Optional[bool] = field( metadata={'dbus_name': 'auto-config', 'dbus_type': 'b'}, default=False, ) + """When TRUE, the settings such as APN, username, or password will default to + values that match the network the modem will register to in the Mobile + Broadband Provider database.""" device_id: Optional[str] = field( metadata={'dbus_name': 'device-id', 'dbus_type': 's'}, default=None, ) + """The device unique identifier (as given by the WWAN management service) + which this connection applies to. If given, the connection will only apply to + the specified device.""" home_only: Optional[bool] = field( metadata={'dbus_name': 'home-only', 'dbus_type': 'b'}, default=False, ) + """When TRUE, only connections to the home network will be allowed. + Connections to roaming networks will not be made.""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple frames.""" network_id: Optional[str] = field( metadata={'dbus_name': 'network-id', 'dbus_type': 's'}, default=None, ) + """The Network ID (GSM LAI format, ie MCC-MNC) to force specific network + registration. If the Network ID is specified, NetworkManager will attempt to + force the device to register only on the specified network. This can be used + to ensure that the device does not roam when direct roaming control of the + device is not otherwise possible.""" number: Optional[str] = field( metadata={'dbus_name': 'number', 'dbus_type': 's'}, default=None, ) + """Legacy setting that used to help establishing PPP data sessions for GSM- + based modems. Deprecated: 1""" password: Optional[str] = field( metadata={'dbus_name': 'password', 'dbus_type': 's'}, default=None, ) + """The password used to authenticate with the network, if required. Many + providers do not require a password, or accept any password. But if a + password is required, it is specified here.""" password_flags: Optional[int] = field( metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, default=None, @@ -51,6 +77,9 @@ class GsmSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'pin', 'dbus_type': 's'}, default=None, ) + """If the SIM is locked with a PIN it must be unlocked before any other + operations are requested. Specify the PIN here to allow operation of the + device.""" pin_flags: Optional[int] = field( metadata={'dbus_name': 'pin-flags', 'dbus_type': 'i'}, default=None, @@ -59,11 +88,22 @@ class GsmSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'sim-id', 'dbus_type': 's'}, default=None, ) + """The SIM card unique identifier (as given by the WWAN management service) + which this connection applies to. If given, the connection will apply to any + device also allowed by "device-id" which contains a SIM card matching the + given identifier.""" sim_operator_id: Optional[str] = field( metadata={'dbus_name': 'sim-operator-id', 'dbus_type': 's'}, default=None, ) + """A MCC/MNC string like "310260" or "21601" identifying the specific mobile + network operator which this connection applies to. If given, the connection + will apply to any device also allowed by "device-id" and "sim-id" which + contains a SIM card provisioned by the given operator.""" username: Optional[str] = field( metadata={'dbus_name': 'username', 'dbus_type': 's'}, default=None, ) + """The username used to authenticate with the network, if required. Many + providers do not require a username, or accept any username. But if a + username is required, it is specified here.""" diff --git a/sdbus_async/networkmanager/settings/hostname.py b/sdbus_async/networkmanager/settings/hostname.py index d8ad4ce..a60d20d 100644 --- a/sdbus_async/networkmanager/settings/hostname.py +++ b/sdbus_async/networkmanager/settings/hostname.py @@ -15,15 +15,42 @@ class HostnameSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'from-dhcp', 'dbus_type': 'i'}, default=None, ) + """Whether the system hostname can be determined from DHCP on this connection. + When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is + used. If the property doesn't have a value in the global configuration, + NetworkManager assumes the value to be NM_TERNARY_TRUE (1).""" from_dns_lookup: Optional[int] = field( metadata={'dbus_name': 'from-dns-lookup', 'dbus_type': 'i'}, default=None, ) + """Whether the system hostname can be determined from reverse DNS lookup of + addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from + global configuration is used. If the property doesn't have a value in the + global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE + (1).""" only_from_default: Optional[int] = field( metadata={'dbus_name': 'only-from-default', 'dbus_type': 'i'}, default=None, ) + """If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname + via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device + has the default route for the given address family (IPv4/IPv6). If set to + NM_TERNARY_FALSE (0), the hostname can be set from this device even if it + doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value + from global configuration is used. If the property doesn't have a value in the + global configuration, NetworkManager assumes the value to be NM_TERNARY_FALSE + (0).""" priority: Optional[int] = field( metadata={'dbus_name': 'priority', 'dbus_type': 'i'}, default=None, ) + """The relative priority of this connection to determine the system hostname. + A lower numerical value is better (higher priority). A connection with higher + priority is considered before connections with lower priority. If the value is + zero, it can be overridden by a global value from NetworkManager + configuration. If the property doesn't have a value in the global + configuration, the value is assumed to be 100. Negative values have the + special effect of excluding other connections with a greater numerical + priority value; so in presence of at least one negative priority, only + connections with the lowest priority value will be used to determine the + hostname.""" diff --git a/sdbus_async/networkmanager/settings/ieee802_1x.py b/sdbus_async/networkmanager/settings/ieee802_1x.py index 38b4513..a0b36c4 100644 --- a/sdbus_async/networkmanager/settings/ieee802_1x.py +++ b/sdbus_async/networkmanager/settings/ieee802_1x.py @@ -15,22 +15,44 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'altsubject-matches', 'dbus_type': 'as'}, default=None, ) + """List of strings to be matched against the altSubjectName of the certificate + presented by the authentication server. If the list is empty, no verification + of the server certificate's altSubjectName is performed.""" anonymous_identity: Optional[str] = field( metadata={'dbus_name': 'anonymous-identity', 'dbus_type': 's'}, default=None, ) + """Anonymous identity string for EAP authentication methods. Used as the + unencrypted identity with EAP types that support different tunneled identity + like EAP-TTLS.""" auth_timeout: Optional[int] = field( metadata={'dbus_name': 'auth-timeout', 'dbus_type': 'i'}, default=None, ) + """A timeout for the authentication. Zero means the global default; if the + global default is not set, the authentication timeout is 25 seconds.""" ca_cert: Optional[bytes] = field( metadata={'dbus_name': 'ca-cert', 'dbus_type': 'ay'}, default=None, ) + """Contains the CA certificate if used by the EAP method specified in the + "eap" property. Certificate data is specified using a "scheme"; three are + currently supported: blob, path and pkcs#11 URL. When using the blob scheme + this property should be set to the certificate's DER encoded data. When using + the path scheme, this property should be set to the full UTF-8 encoded path of + the certificate, prefixed with the string "file://" and ending with a + terminating NUL byte. This property can be unset even if the EAP method + supports CA certificates, but this allows man-in-the-middle attacks and is NOT + recommended. Note that enabling NMSetting8021x:system-ca-certs will override + this setting to use the built-in path, if the built-in path is not a + directory.""" ca_cert_password: Optional[str] = field( metadata={'dbus_name': 'ca-cert-password', 'dbus_type': 's'}, default=None, ) + """The password used to access the CA certificate stored in "ca-cert" + property. Only makes sense if the certificate is stored on a PKCS#11 token + that requires a login.""" ca_cert_password_flags: Optional[int] = field( metadata={'dbus_name': 'ca-cert-password-flags', 'dbus_type': 'i'}, default=None, @@ -39,14 +61,29 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'ca-path', 'dbus_type': 's'}, default=None, ) + """UTF-8 encoded path to a directory containing PEM or DER formatted + certificates to be added to the verification chain in addition to the + certificate specified in the "ca-cert" property. If NMSetting8021x:system-ca- + certs is enabled and the built-in CA path is an existing directory, then this + setting is ignored.""" client_cert: Optional[bytes] = field( metadata={'dbus_name': 'client-cert', 'dbus_type': 'ay'}, default=None, ) + """Contains the client certificate if used by the EAP method specified in the + "eap" property. Certificate data is specified using a "scheme"; two are + currently supported: blob and path. When using the blob scheme (which is + backwards compatible with NM 0.7.x) this property should be set to the + certificate's DER encoded data. When using the path scheme, this property + should be set to the full UTF-8 encoded path of the certificate, prefixed with + the string "file://" and ending with a terminating NUL byte.""" client_cert_password: Optional[str] = field( metadata={'dbus_name': 'client-cert-password', 'dbus_type': 's'}, default=None, ) + """The password used to access the client certificate stored in "client-cert" + property. Only makes sense if the certificate is stored on a PKCS#11 token + that requires a login.""" client_cert_password_flags: Optional[int] = field( metadata={'dbus_name': 'client-cert-password-flags', 'dbus_type': 'i'}, default=None, @@ -55,22 +92,45 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'domain-match', 'dbus_type': 's'}, default=None, ) + """Constraint for server domain name. If set, this list of FQDNs is used as a + match requirement for dNSName element(s) of the certificate presented by the + authentication server. If a matching dNSName is found, this constraint is + met. If no dNSName values are present, this constraint is matched against + SubjectName CN using the same comparison. Multiple valid FQDNs can be passed + as a ";" delimited list.""" domain_suffix_match: Optional[str] = field( metadata={'dbus_name': 'domain-suffix-match', 'dbus_type': 's'}, default=None, ) + """Constraint for server domain name. If set, this FQDN is used as a suffix + match requirement for dNSName element(s) of the certificate presented by the + authentication server. If a matching dNSName is found, this constraint is + met. If no dNSName values are present, this constraint is matched against + SubjectName CN using same suffix match comparison. Since version 1.24, + multiple valid FQDNs can be passed as a ";" delimited list.""" eap: Optional[List[str]] = field( metadata={'dbus_name': 'eap', 'dbus_type': 'as'}, default=None, ) + """The allowed EAP method to be used when authenticating to the network with + 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and + "fast". Each method requires different configuration using the properties of + this setting; refer to wpa_supplicant documentation for the allowed + combinations.""" identity: Optional[str] = field( metadata={'dbus_name': 'identity', 'dbus_type': 's'}, default=None, ) + """Identity string for EAP authentication methods. Often the user's user or + login name.""" optional: Optional[bool] = field( metadata={'dbus_name': 'optional', 'dbus_type': 'b'}, default=False, ) + """Whether the 802.1X authentication is optional. If TRUE, the activation will + continue even after a timeout or an authentication failure. Setting the + property to TRUE is currently allowed only for Ethernet connections. If set to + FALSE, the activation can continue only after a successful authentication.""" pac_file: Optional[str] = field( metadata={'dbus_name': 'pac-file', 'dbus_type': 's'}, default=None, @@ -79,6 +139,9 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'password', 'dbus_type': 's'}, default=None, ) + """UTF-8 encoded password used for EAP authentication methods. If both the + "password" property and the "password-raw" property are specified, "password" + is preferred.""" password_flags: Optional[int] = field( metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, default=None, @@ -87,6 +150,10 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'password-raw', 'dbus_type': 'ay'}, default=None, ) + """Password used for EAP authentication methods, given as a byte array to + allow passwords in other encodings than UTF-8 to be used. If both the + "password" property and the "password-raw" property are specified, "password" + is preferred.""" password_raw_flags: Optional[int] = field( metadata={'dbus_name': 'password-raw-flags', 'dbus_type': 'i'}, default=None, @@ -95,38 +162,89 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'phase1-auth-flags', 'dbus_type': 'u'}, default=None, ) + """Specifies authentication flags to use in "phase 1" outer authentication + using NMSetting8021xAuthFlags options. The individual TLS versions can be + explicitly disabled. If a certain TLS disable flag is not set, it is up to the + supplicant to allow or forbid it. The TLS options map to tls_disable_tlsv1_x + settings. See the wpa_supplicant documentation for more details.""" phase1_fast_provisioning: Optional[str] = field( metadata={'dbus_name': 'phase1-fast-provisioning', 'dbus_type': 's'}, default=None, ) + """Enables or disables in-line provisioning of EAP-FAST credentials when FAST + is specified as the EAP method in the "eap" property. Recognized values are + "0" (disabled), "1" (allow unauthenticated provisioning), "2" (allow + authenticated provisioning), and "3" (allow both authenticated and + unauthenticated provisioning). See the wpa_supplicant documentation for more + details.""" phase1_peaplabel: Optional[str] = field( metadata={'dbus_name': 'phase1-peaplabel', 'dbus_type': 's'}, default=None, ) + """Forces use of the new PEAP label during key derivation. Some RADIUS + servers may require forcing the new PEAP label to interoperate with PEAPv1. + Set to "1" to force use of the new PEAP label. See the wpa_supplicant + documentation for more details.""" phase1_peapver: Optional[str] = field( metadata={'dbus_name': 'phase1-peapver', 'dbus_type': 's'}, default=None, ) + """Forces which PEAP version is used when PEAP is set as the EAP method in the + "eap" property. When unset, the version reported by the server will be used. + Sometimes when using older RADIUS servers, it is necessary to force the client + to use a particular PEAP version. To do so, this property may be set to "0" + or "1" to force that specific PEAP version.""" phase2_altsubject_matches: Optional[List[str]] = field( metadata={'dbus_name': 'phase2-altsubject-matches', 'dbus_type': 'as'}, default=None, ) + """List of strings to be matched against the altSubjectName of the certificate + presented by the authentication server during the inner "phase 2" + authentication. If the list is empty, no verification of the server + certificate's altSubjectName is performed.""" phase2_auth: Optional[str] = field( metadata={'dbus_name': 'phase2-auth', 'dbus_type': 's'}, default=None, ) + """Specifies the allowed "phase 2" inner authentication method when an EAP + method that uses an inner TLS tunnel is specified in the "eap" property. For + TTLS this property selects one of the supported non-EAP inner methods: "pap", + "chap", "mschap", "mschapv2" while "phase2-autheap" selects an EAP inner + method. For PEAP this selects an inner EAP method, one of: "gtc", "otp", + "md5" and "tls". Each "phase 2" inner method requires specific parameters for + successful authentication; see the wpa_supplicant documentation for more + details. Both "phase2-auth" and "phase2-autheap" cannot be specified.""" phase2_autheap: Optional[str] = field( metadata={'dbus_name': 'phase2-autheap', 'dbus_type': 's'}, default=None, ) + """Specifies the allowed "phase 2" inner EAP-based authentication method when + TTLS is specified in the "eap" property. Recognized EAP-based "phase 2" + methods are "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner + method requires specific parameters for successful authentication; see the + wpa_supplicant documentation for more details.""" phase2_ca_cert: Optional[bytes] = field( metadata={'dbus_name': 'phase2-ca-cert', 'dbus_type': 'ay'}, default=None, ) + """Contains the "phase 2" CA certificate if used by the EAP method specified + in the "phase2-auth" or "phase2-autheap" properties. Certificate data is + specified using a "scheme"; three are currently supported: blob, path and + pkcs#11 URL. When using the blob scheme this property should be set to the + certificate's DER encoded data. When using the path scheme, this property + should be set to the full UTF-8 encoded path of the certificate, prefixed with + the string "file://" and ending with a terminating NUL byte. This property can + be unset even if the EAP method supports CA certificates, but this allows man- + in-the-middle attacks and is NOT recommended. Note that enabling + NMSetting8021x:system-ca-certs will override this setting to use the built-in + path, if the built-in path is not a directory.""" phase2_ca_cert_password: Optional[str] = field( metadata={'dbus_name': 'phase2-ca-cert-password', 'dbus_type': 's'}, default=None, ) + """The password used to access the "phase2" CA certificate stored in + "phase2-ca-cert" property. Only makes sense if the certificate is stored on a + PKCS#11 token that requires a login.""" phase2_ca_cert_password_flags: Optional[int] = field( metadata={'dbus_name': 'phase2-ca-cert-password-flags', 'dbus_type': 'i'}, @@ -136,44 +254,102 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'phase2-ca-path', 'dbus_type': 's'}, default=None, ) + """UTF-8 encoded path to a directory containing PEM or DER formatted + certificates to be added to the verification chain in addition to the + certificate specified in the "phase2-ca-cert" property. If + NMSetting8021x:system-ca-certs is enabled and the built-in CA path is an + existing directory, then this setting is ignored.""" phase2_client_cert: Optional[bytes] = field( metadata={'dbus_name': 'phase2-client-cert', 'dbus_type': 'ay'}, default=None, ) + """Contains the "phase 2" client certificate if used by the EAP method + specified in the "phase2-auth" or "phase2-autheap" properties. Certificate + data is specified using a "scheme"; two are currently supported: blob and + path. When using the blob scheme (which is backwards compatible with NM 0.7.x) + this property should be set to the certificate's DER encoded data. When using + the path scheme, this property should be set to the full UTF-8 encoded path of + the certificate, prefixed with the string "file://" and ending with a + terminating NUL byte. This property can be unset even if the EAP method + supports CA certificates, but this allows man-in-the-middle attacks and is NOT + recommended.""" phase2_client_cert_password: Optional[str] = field( metadata={'dbus_name': 'phase2-client-cert-password', 'dbus_type': 's'}, default=None, ) + """The password used to access the "phase2" client certificate stored in + "phase2-client-cert" property. Only makes sense if the certificate is stored + on a PKCS#11 token that requires a login.""" phase2_client_cert_password_flags: Optional[int] = field( metadata={'dbus_name': 'phase2-client-cert-password-flags', 'dbus_type': 'i'}, default=None, ) + """Flags indicating how to handle the "phase2-client-cert-password" + property.""" phase2_domain_match: Optional[str] = field( metadata={'dbus_name': 'phase2-domain-match', 'dbus_type': 's'}, default=None, ) + """Constraint for server domain name. If set, this list of FQDNs is used as a + match requirement for dNSName element(s) of the certificate presented by the + authentication server during the inner "phase 2" authentication. If a matching + dNSName is found, this constraint is met. If no dNSName values are present, + this constraint is matched against SubjectName CN using the same comparison. + Multiple valid FQDNs can be passed as a ";" delimited list.""" phase2_domain_suffix_match: Optional[str] = field( metadata={'dbus_name': 'phase2-domain-suffix-match', 'dbus_type': 's'}, default=None, ) + """Constraint for server domain name. If set, this FQDN is used as a suffix + match requirement for dNSName element(s) of the certificate presented by the + authentication server during the inner "phase 2" authentication. If a + matching dNSName is found, this constraint is met. If no dNSName values are + present, this constraint is matched against SubjectName CN using same suffix + match comparison. Since version 1.24, multiple valid FQDNs can be passed as a + ";" delimited list.""" phase2_private_key: Optional[bytes] = field( metadata={'dbus_name': 'phase2-private-key', 'dbus_type': 'ay'}, default=None, ) + """Contains the "phase 2" inner private key when the "phase2-auth" or + "phase2-autheap" property is set to "tls". Key data is specified using a + "scheme"; two are currently supported: blob and path. When using the blob + scheme and private keys, this property should be set to the key's encrypted + PEM encoded data. When using private keys with the path scheme, this property + should be set to the full UTF-8 encoded path of the key, prefixed with the + string "file://" and ending with a terminating NUL byte. When using PKCS#12 + format private keys and the blob scheme, this property should be set to the + PKCS#12 data and the "phase2-private-key-password" property must be set to + password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 + files and the path scheme, this property should be set to the full UTF-8 + encoded path of the key, prefixed with the string "file://" and ending with a + terminating NUL byte, and as with the blob scheme the "phase2-private-key- + password" property must be set to the password used to decode the PKCS#12 + private key and certificate.""" phase2_private_key_password: Optional[str] = field( metadata={'dbus_name': 'phase2-private-key-password', 'dbus_type': 's'}, default=None, ) + """The password used to decrypt the "phase 2" private key specified in the + "phase2-private-key" property when the private key either uses the path + scheme, or is a PKCS#12 format key.""" phase2_private_key_password_flags: Optional[int] = field( metadata={'dbus_name': 'phase2-private-key-password-flags', 'dbus_type': 'i'}, default=None, ) + """Flags indicating how to handle the "phase2-private-key-password" + property.""" phase2_subject_match: Optional[str] = field( metadata={'dbus_name': 'phase2-subject-match', 'dbus_type': 's'}, default=None, ) + """Substring to be matched against the subject of the certificate presented by + the authentication server during the inner "phase 2" authentication. When + unset, no verification of the authentication server certificate's subject is + performed. This property provides little security, if any, and its use is + deprecated in favor of NMSetting8021x:phase2-domain-suffix-match.""" pin: Optional[str] = field( metadata={'dbus_name': 'pin', 'dbus_type': 's'}, default=None, @@ -186,10 +362,31 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'private-key', 'dbus_type': 'ay'}, default=None, ) + """Contains the private key when the "eap" property is set to "tls". Key data + is specified using a "scheme"; two are currently supported: blob and path. + When using the blob scheme and private keys, this property should be set to + the key's encrypted PEM encoded data. When using private keys with the path + scheme, this property should be set to the full UTF-8 encoded path of the key, + prefixed with the string "file://" and ending with a terminating NUL byte. + When using PKCS#12 format private keys and the blob scheme, this property + should be set to the PKCS#12 data and the "private-key-password" property must + be set to password used to decrypt the PKCS#12 certificate and key. When using + PKCS#12 files and the path scheme, this property should be set to the full + UTF-8 encoded path of the key, prefixed with the string "file://" and ending + with a terminating NUL byte, and as with the blob scheme the "private-key- + password" property must be set to the password used to decode the PKCS#12 + private key and certificate. WARNING: "private-key" is not a "secret" + property, and thus unencrypted private key data using the BLOB scheme may be + readable by unprivileged users. Private keys should always be encrypted with + a private key password to prevent unauthorized access to unencrypted private + key data.""" private_key_password: Optional[str] = field( metadata={'dbus_name': 'private-key-password', 'dbus_type': 's'}, default=None, ) + """The password used to decrypt the private key specified in the "private-key" + property when the private key either uses the path scheme, or if the private + key is a PKCS#12 format key.""" private_key_password_flags: Optional[int] = field( metadata={'dbus_name': 'private-key-password-flags', 'dbus_type': 'i'}, default=None, @@ -198,7 +395,20 @@ class Ieee8021XSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'subject-match', 'dbus_type': 's'}, default=None, ) + """Substring to be matched against the subject of the certificate presented by + the authentication server. When unset, no verification of the authentication + server certificate's subject is performed. This property provides little + security, if any, and its use is deprecated in favor of NMSetting8021x:domain- + suffix-match.""" system_ca_certs: Optional[bool] = field( metadata={'dbus_name': 'system-ca-certs', 'dbus_type': 'b'}, default=False, ) + """When TRUE, overrides the "ca-path" and "phase2-ca-path" properties using + the system CA directory specified at configure time with the --system-ca-path + switch. The certificates in this directory are added to the verification + chain in addition to any certificates specified by the "ca-cert" and + "phase2-ca-cert" properties. If the path provided with --system-ca-path is + rather a file name (bundle of trusted CA certificates), it overrides "ca-cert" + and "phase2-ca-cert" properties instead (sets ca_cert/ca_cert2 options for + wpa_supplicant).""" diff --git a/sdbus_async/networkmanager/settings/infiniband.py b/sdbus_async/networkmanager/settings/infiniband.py index 0cc31bc..2317cf8 100644 --- a/sdbus_async/networkmanager/settings/infiniband.py +++ b/sdbus_async/networkmanager/settings/infiniband.py @@ -15,18 +15,29 @@ class InfinibandSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, this connection will only apply to the IPoIB device whose + permanent MAC address matches. This property does not change the MAC address + of the device (i.e. MAC spoofing).""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple frames.""" p_key: Optional[int] = field( metadata={'dbus_name': 'p-key', 'dbus_type': 'i'}, default=None, ) + """The InfiniBand P_Key to use for this device. A value of -1 means to use the + default P_Key (aka "the P_Key at index 0"). Otherwise, it is a 16-bit unsigned + integer, whose high bit is set if it is a "full membership" P_Key.""" parent: Optional[str] = field( metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """The interface name of the parent device of this device. Normally NULL, but + if the "p_key" property is set, then you must specify the base device by + setting either this property or "mac-address".""" transport_mode: Optional[str] = field( metadata={'dbus_name': 'transport-mode', 'dbus_type': 's'}, default=None, diff --git a/sdbus_async/networkmanager/settings/ip_tunnel.py b/sdbus_async/networkmanager/settings/ip_tunnel.py index 48e81ec..45a05d7 100644 --- a/sdbus_async/networkmanager/settings/ip_tunnel.py +++ b/sdbus_async/networkmanager/settings/ip_tunnel.py @@ -15,38 +15,62 @@ class IpTunnelSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'encapsulation-limit', 'dbus_type': 'u'}, default=None, ) + """How many additional levels of encapsulation are permitted to be prepended + to packets. This property applies only to IPv6 tunnels.""" flags: Optional[int] = field( metadata={'dbus_name': 'flags', 'dbus_type': 'u'}, default=None, ) + """Tunnel flags. Currently, the following values are supported: + NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS (0x2), + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV + (0x8), NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only for IPv6 + tunnels.""" flow_label: Optional[int] = field( metadata={'dbus_name': 'flow-label', 'dbus_type': 'u'}, default=None, ) + """The flow label to assign to tunnel packets. This property applies only to + IPv6 tunnels.""" input_key: Optional[str] = field( metadata={'dbus_name': 'input-key', 'dbus_type': 's'}, default=None, ) + """The key used for tunnel input packets; the property is valid only for + certain tunnel modes (GRE, IP6GRE). If empty, no key is used.""" local: Optional[str] = field( metadata={'dbus_name': 'local', 'dbus_type': 's'}, default=None, ) + """The local endpoint of the tunnel; the value can be empty, otherwise it must + contain an IPv4 or IPv6 address.""" mode: Optional[int] = field( metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, default=None, ) + """The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or + NM_IP_TUNNEL_MODE_GRE (2).""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple fragments.""" output_key: Optional[str] = field( metadata={'dbus_name': 'output-key', 'dbus_type': 's'}, default=None, ) + """The key used for tunnel output packets; the property is valid only for + certain tunnel modes (GRE, IP6GRE). If empty, no key is used.""" parent: Optional[str] = field( metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name or parent connection UUID the + new device will be bound to so that tunneled packets will only be routed via + that interface.""" path_mtu_discovery: Optional[bool] = field( metadata={'dbus_name': 'path-mtu-discovery', 'dbus_type': 'b'}, default=True, @@ -55,11 +79,17 @@ class IpTunnelSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'remote', 'dbus_type': 's'}, default=None, ) + """The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 + address.""" tos: Optional[int] = field( metadata={'dbus_name': 'tos', 'dbus_type': 'u'}, default=None, ) + """The type of service (IPv4) or traffic class (IPv6) field to be set on + tunneled packets.""" ttl: Optional[int] = field( metadata={'dbus_name': 'ttl', 'dbus_type': 'u'}, default=None, ) + """The TTL to assign to tunneled packets. 0 is a special value meaning that + packets inherit the TTL value.""" diff --git a/sdbus_async/networkmanager/settings/ipv4.py b/sdbus_async/networkmanager/settings/ipv4.py index 5a383a3..3093d42 100644 --- a/sdbus_async/networkmanager/settings/ipv4.py +++ b/sdbus_async/networkmanager/settings/ipv4.py @@ -22,47 +22,132 @@ class Ipv4Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'addresses', 'dbus_type': 'aau'}, default=None, ) + """Deprecated in favor of the 'address-data' and 'gateway' properties, but + this can be used for backward-compatibility with older daemons. Note that if + you send this property the daemon will ignore 'address-data' and 'gateway'. + Array of IPv4 address structures. Each IPv4 address structure is composed of + 3 32-bit values; the first being the IPv4 address (network byte order), the + second the prefix (1 - 32), and last the IPv4 gateway (network byte order). + The gateway may be left as 0 if no gateway exists for that subnet.""" dad_timeout: Optional[int] = field( metadata={'dbus_name': 'dad-timeout', 'dbus_type': 'i'}, default=None, ) + """Timeout in milliseconds used to check for the presence of duplicate IP + addresses on the network. If an address conflict is detected, the activation + will fail. A zero value means that no duplicate address detection is + performed, -1 means the default value (either configuration ipvx.dad-timeout + override or zero). A value greater than zero is a timeout in milliseconds. + The property is currently implemented only for IPv4.""" dhcp_client_id: Optional[str] = field( metadata={'dbus_name': 'dhcp-client-id', 'dbus_type': 's'}, default=None, ) + """A string sent to the DHCP server to identify the local machine which the + DHCP server may use to customize the DHCP lease and options. When the property + is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which + case the first byte is assumed to be the 'type' field as per RFC 2132 section + 9.14 and the remaining bytes may be an hardware address (e.g. + '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC + address). If the property is not a hex string it is considered as a non- + hardware-address client ID and the 'type' field is set to 0. The special + values "mac" and "perm-mac" are supported, which use the current or permanent + MAC address of the device to generate a client identifier with type ethernet + (01). Currently, these options only work for ethernet type of links. The + special value "ipv6-duid" uses the DUID from "ipv6.dhcp-duid" property as an + RFC4361-compliant client identifier. As IAID it uses "ipv4.dhcp-iaid" and + falls back to "ipv6.dhcp-iaid" if unset. The special value "duid" generates a + RFC4361-compliant client identifier based on "ipv4.dhcp-iaid" and uses a DUID + generated by hashing /etc/machine-id. The special value "stable" is supported + to generate a type 0 client identifier based on the stable-id (see + connection.stable-id) and a per-host key. If you set the stable-id, you may + want to include the "${DEVICE}" or "${MAC}" specifier to get a per-device key. + If unset, a globally configured default is used. If still unset, the default + depends on the DHCP plugin.""" dhcp_fqdn: Optional[str] = field( metadata={'dbus_name': 'dhcp-fqdn', 'dbus_type': 's'}, default=None, ) + """If the "dhcp-send-hostname" property is TRUE, then the specified FQDN will + be sent to the DHCP server when acquiring a lease. This property and "dhcp- + hostname" are mutually exclusive and cannot be set at the same time.""" dhcp_hostname: Optional[str] = field( metadata={'dbus_name': 'dhcp-hostname', 'dbus_type': 's'}, default=None, ) + """If the "dhcp-send-hostname" property is TRUE, then the specified name will + be sent to the DHCP server when acquiring a lease. This property and "dhcp- + fqdn" are mutually exclusive and cannot be set at the same time.""" dhcp_hostname_flags: Optional[int] = field( metadata={'dbus_name': 'dhcp-hostname-flags', 'dbus_type': 'u'}, default=None, ) + """Flags for the DHCP hostname and FQDN. Currently, this property only + includes flags to control the FQDN flags set in the DHCP FQDN option. + Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will + contain no flag. Otherwise, if no FQDN flag is set and + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN + flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is + set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is + looked up in NetworkManager configuration. If that value is unset or also + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above + are sent in the DHCP requests.""" dhcp_iaid: Optional[str] = field( metadata={'dbus_name': 'dhcp-iaid', 'dbus_type': 's'}, default=None, ) + """A string containing the "Identity Association Identifier" (IAID) used by + the DHCP client. The property is a 32-bit decimal value or a special value + among "mac", "perm-mac", "ifname" and "stable". When set to "mac" (or "perm- + mac"), the last 4 bytes of the current (or permanent) MAC address are used as + IAID. When set to "ifname", the IAID is computed by hashing the interface + name. The special value "stable" can be used to generate an IAID based on the + stable-id (see connection.stable-id), a per-host key and the interface name. + When the property is unset, the value from global configuration is used; if no + global default is set then the IAID is assumed to be "ifname". Note that at + the moment this property is ignored for IPv6 by dhclient, which always derives + the IAID from the MAC address.""" dhcp_reject_servers: Optional[List[str]] = field( metadata={'dbus_name': 'dhcp-reject-servers', 'dbus_type': 'as'}, default=None, ) + """Array of servers from which DHCP offers must be rejected. This property is + useful to avoid getting a lease from misconfigured or rogue servers. For + DHCPv4, each element must be an IPv4 address, optionally followed by a slash + and a prefix length (e.g. "192.168.122.0/24"). This property is currently not + implemented for DHCPv6.""" dhcp_send_hostname: Optional[bool] = field( metadata={'dbus_name': 'dhcp-send-hostname', 'dbus_type': 'b'}, default=True, ) + """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some + DHCP servers use this hostname to update DNS databases, essentially providing + a static hostname for the computer. If the "dhcp-hostname" property is NULL + and this property is TRUE, the current persistent hostname of the computer is + sent.""" dhcp_timeout: Optional[int] = field( metadata={'dbus_name': 'dhcp-timeout', 'dbus_type': 'i'}, default=None, ) + """A timeout for a DHCP transaction in seconds. If zero (the default), a + globally configured default is used. If still unspecified, a device specific + timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for + infinity.""" dhcp_vendor_class_identifier: Optional[str] = field( metadata={'dbus_name': 'dhcp-vendor-class-identifier', 'dbus_type': 's'}, default=None, ) + """The Vendor Class Identifier DHCP option (60). Special characters in the + data string may be escaped using C-style escapes, nevertheless this property + cannot contain nul bytes. If the per-profile value is unspecified (the + default), a global connection default gets consulted. If still unspecified, + the DHCP option is not sent to the server. Since 1.28""" dns: Optional[List[int]] = field( metadata={'dbus_name': 'dns', 'dbus_type': 'au'}, default=None, @@ -71,42 +156,139 @@ class Ipv4Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'dns-options', 'dbus_type': 'as'}, default=None, ) + """Array of DNS options as described in man 5 resolv.conf. NULL means that the + options are unset and left at the default. In this case NetworkManager will + use default options. This is distinct from an empty list of properties. The + currently supported options are "attempts", "debug", "edns0", "inet6", + "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", + "no-reload", "no-tld-query", "rotate", "single-request", "single-request- + reopen", "timeout", "trust-ad", "use-vc". The "trust-ad" setting is only + honored if the profile contributes name servers to resolv.conf, and if all + contributing profiles have "trust-ad" enabled. When using a caching DNS plugin + (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust- + ad" are automatically added.""" dns_priority: Optional[int] = field( metadata={'dbus_name': 'dns-priority', 'dbus_type': 'i'}, default=None, ) + """DNS servers priority. The relative priority for DNS servers specified by + this setting. A lower numerical value is better (higher priority). Negative + values have the special effect of excluding other configurations with a + greater numerical priority value; so in presence of at least one negative + priority, only DNS servers from connections with the lowest priority value + will be used. To avoid all DNS leaks, set the priority of the profile that + should be used to the most negative value of all active connections profiles. + Zero selects a globally configured default value. If the latter is missing or + zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other + connections. Note that the priority is to order DNS settings for multiple + active connections. It does not disambiguate multiple DNS servers within the + same connection profile. When multiple devices have configurations with the + same priority, VPNs will be considered first, then devices with the best + (lowest metric) default route and then all other devices. When using + dns=default, servers with higher priority will be on top of resolv.conf. To + prioritize a given server over another one within the same connection, just + specify them in the desired order. Note that commonly the resolver tries name + servers in /etc/resolv.conf in the order listed, proceeding with the next + server in the list on failure. See for example the "rotate" option of the dns- + options setting. If there are any negative DNS priorities, then only name + servers from the devices with that lowest priority will be considered. When + using a DNS resolver that supports Conditional Forwarding or Split DNS (with + dns=dnsmasq or dns=systemd-resolved settings), each connection is used to + query domains in its search list. The search domains determine which name + servers to ask, and the DNS priority is used to prioritize name servers based + on the domain. Queries for domains not present in any search list are routed + through connections having the '~.' special wildcard domain, which is added + automatically to connections with the default route (or can be added + manually). When multiple connections specify the same domain, the one with + the best priority (lowest numerical value) wins. If a sub domain is + configured on another interface it will be accepted regardless the priority, + unless parent domain on the other interface has a negative priority, which + causes the sub domain to be shadowed. With Split DNS one can avoid undesired + DNS leaks by properly configuring DNS priorities and the search domains, so + that only name servers of the desired interface are configured.""" dns_search: Optional[List[str]] = field( metadata={'dbus_name': 'dns-search', 'dbus_type': 'as'}, default=None, ) + """Array of DNS search domains. Domains starting with a tilde ('~') are + considered 'routing' domains and are used only to decide the interface over + which a query must be forwarded; they are not used to complete unqualified + host names. When using a DNS plugin that supports Conditional Forwarding or + Split DNS, then the search domains specify which name servers to query. This + makes the behavior different from running with plain /etc/resolv.conf. For + more information see also the dns-priority setting.""" gateway: Optional[str] = field( metadata={'dbus_name': 'gateway', 'dbus_type': 's'}, default=None, ) + """The gateway associated with this configuration. This is only meaningful if + "addresses" is also set. The gateway's main purpose is to control the next hop + of the standard default route on the device. Hence, the gateway property + conflicts with "never-default" and will be automatically dropped if the IP + configuration is set to never-default. As an alternative to set the gateway, + configure a static default route with /0 as prefix length.""" ignore_auto_dns: Optional[bool] = field( metadata={'dbus_name': 'ignore-auto-dns', 'dbus_type': 'b'}, default=False, ) + """When "method" is set to "auto" and this property to TRUE, automatically + configured name servers and search domains are ignored and only name servers + and search domains specified in the "dns" and "dns-search" properties, if any, + are used.""" ignore_auto_routes: Optional[bool] = field( metadata={'dbus_name': 'ignore-auto-routes', 'dbus_type': 'b'}, default=False, ) + """When "method" is set to "auto" and this property to TRUE, automatically + configured routes are ignored and only routes specified in the "routes" + property, if any, are used.""" may_fail: Optional[bool] = field( metadata={'dbus_name': 'may-fail', 'dbus_type': 'b'}, default=True, ) + """If TRUE, allow overall network configuration to proceed even if the + configuration specified by this property times out. Note that at least one IP + configuration must succeed or overall network configuration will still fail. + For example, in IPv6-only networks, setting this property to TRUE on the + NMSettingIP4Config allows the overall network configuration to succeed if IPv4 + configuration fails but IPv6 configuration completes successfully.""" method: Optional[str] = field( metadata={'dbus_name': 'method', 'dbus_type': 's'}, default=None, ) + """IP configuration method. NMSettingIP4Config and NMSettingIP6Config both + support "disabled", "auto", "manual", and "link-local". See the subclass- + specific documentation for other values. In general, for the "auto" method, + properties such as "dns" and "routes" specify information that is added on to + the information returned from automatic configuration. The "ignore-auto- + routes" and "ignore-auto-dns" properties modify this behavior. For methods + that imply no upstream network, such as "shared" or "link-local", these + properties must be empty. For IPv4 method "shared", the IP subnet can be + configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is + chosen. Note that the shared method must be configured on the interface which + shares the internet to a subnet, not on the uplink which is shared.""" never_default: Optional[bool] = field( metadata={'dbus_name': 'never-default', 'dbus_type': 'b'}, default=False, ) + """If TRUE, this connection will never be the default connection for this IP + type, meaning it will never be assigned the default route by + NetworkManager.""" required_timeout: Optional[int] = field( metadata={'dbus_name': 'required-timeout', 'dbus_type': 'i'}, default=None, ) + """The minimum time interval in milliseconds for which dynamic IP + configuration should be tried before the connection succeeds. This property is + useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. + Normally the connection succeeds as soon as one of the two address families + completes; by setting a required timeout for e.g. IPv4, one can ensure that + even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for + IPv4 before the connection becomes active. Note that if "may-fail" is FALSE + for the same address family, this property has no effect as NetworkManager + needs to wait for the full DHCP timeout. A zero value means that no required + timeout is present, -1 means the default value (either configuration + ipvx.required-timeout override or zero).""" route_data: Optional[List[RouteData]] = field( metadata={'dbus_name': 'route-data', 'dbus_type': 'aa{sv}', @@ -117,11 +299,41 @@ class Ipv4Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'route-metric', 'dbus_type': 'x'}, default=None, ) + """The default metric for routes that don't explicitly specify a metric. The + default value -1 means that the metric is chosen automatically based on the + device type. The metric applies to dynamic routes, manual (static) routes that + don't have an explicit metric setting, address prefix routes, and the default + route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 + (user default). Hence, setting this property to zero effectively mean setting + it to 1024. For IPv4, zero is a regular value for the metric.""" route_table: Optional[int] = field( metadata={'dbus_name': 'route-table', 'dbus_type': 'u'}, default=None, ) + """Enable policy routing (source routing) and set the routing table used when + adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, + SLAAC, default-routes and static routes. But note that static routes can + individually overwrite the setting by explicitly specifying a non-zero routing + table. If the table setting is left at zero, it is eligible to be overwritten + via global configuration. If the property is zero even after applying the + global configuration value, policy routing is disabled for the address family + of this connection. Policy routing disabled means that NetworkManager will add + all routes to the main table (except static routes that explicitly configure a + different table). Additionally, NetworkManager will not delete any extraneous + routes from tables except the main table. This is to preserve backward + compatibility for users who manage routing tables outside of + NetworkManager.""" routes: Optional[List[List[int]]] = field( metadata={'dbus_name': 'routes', 'dbus_type': 'aau'}, default=None, ) + """Deprecated in favor of the 'route-data' property, but this can be used for + backward-compatibility with older daemons. Note that if you send this property + the daemon will ignore 'route-data'. Array of IPv4 route structures. Each + IPv4 route structure is composed of 4 32-bit values; the first being the + destination IPv4 network or address (network byte order), the second the + destination network or address prefix (1 - 32), the third being the next-hop + (network byte order) if any, and the fourth being the route metric. If the + metric is 0, NM will choose an appropriate default metric for the device. + (There is no way to explicitly specify an actual metric of 0 with this + property.)""" diff --git a/sdbus_async/networkmanager/settings/ipv6.py b/sdbus_async/networkmanager/settings/ipv6.py index 1456d78..e9f2d79 100644 --- a/sdbus_async/networkmanager/settings/ipv6.py +++ b/sdbus_async/networkmanager/settings/ipv6.py @@ -16,6 +16,24 @@ class Ipv6Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'addr-gen-mode', 'dbus_type': 'i'}, default=1, ) + """Configure method for creating the address for use with RFC4862 IPv6 + Stateless Address Autoconfiguration. The permitted values are: + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set + to EUI64, the addresses will be generated using the interface tokens derived + from hardware address. This makes the host part of the address to stay + constant, making it possible to track host's presence when it changes + networks. The address changes when the interface hardware is replaced. The + value of stable-privacy enables use of cryptographically secure hash of a + secret host-specific key along with the connection's stable-id and the network + address as specified by RFC7217. This makes it impossible to use the address + track host's presence, and makes the address stable when the network interface + hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals + enabling stable-privacy. For keyfile plugin, the absence of the setting on + disk means EUI64 so that the property doesn't change on upgrade from older + versions. Note that this setting is distinct from the Privacy Extensions as + configured by "ip6-privacy" property and it does not affect the temporary + addresses configured with this option.""" address_data: Optional[List[AddressData]] = field( metadata={'dbus_name': 'address-data', 'dbus_type': 'aa{sv}', @@ -26,34 +44,107 @@ class Ipv6Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'dad-timeout', 'dbus_type': 'i'}, default=None, ) + """Timeout in milliseconds used to check for the presence of duplicate IP + addresses on the network. If an address conflict is detected, the activation + will fail. A zero value means that no duplicate address detection is + performed, -1 means the default value (either configuration ipvx.dad-timeout + override or zero). A value greater than zero is a timeout in milliseconds. + The property is currently implemented only for IPv4.""" dhcp_duid: Optional[str] = field( metadata={'dbus_name': 'dhcp-duid', 'dbus_type': 's'}, default=None, ) + """A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp + client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in + the Client Identifier option. If the property is a hex string ('aa:bb:cc') it + is interpreted as a binary DUID and filled as an opaque value in the Client + Identifier option. The special value "lease" will retrieve the DUID previously + used from the lease file belonging to the connection. If no DUID is found and + "dhclient" is the configured dhcp client, the DUID is searched in the system- + wide dhclient lease file. If still no DUID is found, or another dhcp client is + used, a global and permanent DUID-UUID (RFC 6355) will be generated based on + the machine-id. The special values "llt" and "ll" will generate a DUID of type + LLT or LL (see RFC 3315) based on the current MAC address of the device. In + order to try providing a stable DUID-LLT, the time field will contain a + constant timestamp that is used globally (for all profiles) and persisted to + disk. The special values "stable-llt", "stable-ll" and "stable-uuid" will + generate a DUID of the corresponding type, derived from the connection's + stable-id and a per-host unique key. You may want to include the "${DEVICE}" + or "${MAC}" specifier in the stable-id, in case this profile gets activated on + multiple devices. So, the link-layer address of "stable-ll" and "stable-llt" + will be a generated address derived from the stable id. The DUID-LLT time + value in the "stable-llt" option will be picked among a static timespan of + three years (the upper bound of the interval is the same constant timestamp + used in "llt"). When the property is unset, the global value provided for + "ipv6.dhcp-duid" is used. If no global value is provided, the default "lease" + value is assumed.""" dhcp_hostname: Optional[str] = field( metadata={'dbus_name': 'dhcp-hostname', 'dbus_type': 's'}, default=None, ) + """If the "dhcp-send-hostname" property is TRUE, then the specified name will + be sent to the DHCP server when acquiring a lease. This property and "dhcp- + fqdn" are mutually exclusive and cannot be set at the same time.""" dhcp_hostname_flags: Optional[int] = field( metadata={'dbus_name': 'dhcp-hostname-flags', 'dbus_type': 'u'}, default=None, ) + """Flags for the DHCP hostname and FQDN. Currently, this property only + includes flags to control the FQDN flags set in the DHCP FQDN option. + Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will + contain no flag. Otherwise, if no FQDN flag is set and + NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN + flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is + set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is + looked up in NetworkManager configuration. If that value is unset or also + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above + are sent in the DHCP requests.""" dhcp_iaid: Optional[str] = field( metadata={'dbus_name': 'dhcp-iaid', 'dbus_type': 's'}, default=None, ) + """A string containing the "Identity Association Identifier" (IAID) used by + the DHCP client. The property is a 32-bit decimal value or a special value + among "mac", "perm-mac", "ifname" and "stable". When set to "mac" (or "perm- + mac"), the last 4 bytes of the current (or permanent) MAC address are used as + IAID. When set to "ifname", the IAID is computed by hashing the interface + name. The special value "stable" can be used to generate an IAID based on the + stable-id (see connection.stable-id), a per-host key and the interface name. + When the property is unset, the value from global configuration is used; if no + global default is set then the IAID is assumed to be "ifname". Note that at + the moment this property is ignored for IPv6 by dhclient, which always derives + the IAID from the MAC address.""" dhcp_reject_servers: Optional[List[str]] = field( metadata={'dbus_name': 'dhcp-reject-servers', 'dbus_type': 'as'}, default=None, ) + """Array of servers from which DHCP offers must be rejected. This property is + useful to avoid getting a lease from misconfigured or rogue servers. For + DHCPv4, each element must be an IPv4 address, optionally followed by a slash + and a prefix length (e.g. "192.168.122.0/24"). This property is currently not + implemented for DHCPv6.""" dhcp_send_hostname: Optional[bool] = field( metadata={'dbus_name': 'dhcp-send-hostname', 'dbus_type': 'b'}, default=True, ) + """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some + DHCP servers use this hostname to update DNS databases, essentially providing + a static hostname for the computer. If the "dhcp-hostname" property is NULL + and this property is TRUE, the current persistent hostname of the computer is + sent.""" dhcp_timeout: Optional[int] = field( metadata={'dbus_name': 'dhcp-timeout', 'dbus_type': 'i'}, default=None, ) + """A timeout for a DHCP transaction in seconds. If zero (the default), a + globally configured default is used. If still unspecified, a device specific + timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for + infinity.""" dns: Optional[List[bytes]] = field( metadata={'dbus_name': 'dns', 'dbus_type': 'aay'}, default=None, @@ -62,50 +153,163 @@ class Ipv6Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'dns-options', 'dbus_type': 'as'}, default=None, ) + """Array of DNS options as described in man 5 resolv.conf. NULL means that the + options are unset and left at the default. In this case NetworkManager will + use default options. This is distinct from an empty list of properties. The + currently supported options are "attempts", "debug", "edns0", "inet6", + "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", + "no-reload", "no-tld-query", "rotate", "single-request", "single-request- + reopen", "timeout", "trust-ad", "use-vc". The "trust-ad" setting is only + honored if the profile contributes name servers to resolv.conf, and if all + contributing profiles have "trust-ad" enabled. When using a caching DNS plugin + (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust- + ad" are automatically added.""" dns_priority: Optional[int] = field( metadata={'dbus_name': 'dns-priority', 'dbus_type': 'i'}, default=None, ) + """DNS servers priority. The relative priority for DNS servers specified by + this setting. A lower numerical value is better (higher priority). Negative + values have the special effect of excluding other configurations with a + greater numerical priority value; so in presence of at least one negative + priority, only DNS servers from connections with the lowest priority value + will be used. To avoid all DNS leaks, set the priority of the profile that + should be used to the most negative value of all active connections profiles. + Zero selects a globally configured default value. If the latter is missing or + zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other + connections. Note that the priority is to order DNS settings for multiple + active connections. It does not disambiguate multiple DNS servers within the + same connection profile. When multiple devices have configurations with the + same priority, VPNs will be considered first, then devices with the best + (lowest metric) default route and then all other devices. When using + dns=default, servers with higher priority will be on top of resolv.conf. To + prioritize a given server over another one within the same connection, just + specify them in the desired order. Note that commonly the resolver tries name + servers in /etc/resolv.conf in the order listed, proceeding with the next + server in the list on failure. See for example the "rotate" option of the dns- + options setting. If there are any negative DNS priorities, then only name + servers from the devices with that lowest priority will be considered. When + using a DNS resolver that supports Conditional Forwarding or Split DNS (with + dns=dnsmasq or dns=systemd-resolved settings), each connection is used to + query domains in its search list. The search domains determine which name + servers to ask, and the DNS priority is used to prioritize name servers based + on the domain. Queries for domains not present in any search list are routed + through connections having the '~.' special wildcard domain, which is added + automatically to connections with the default route (or can be added + manually). When multiple connections specify the same domain, the one with + the best priority (lowest numerical value) wins. If a sub domain is + configured on another interface it will be accepted regardless the priority, + unless parent domain on the other interface has a negative priority, which + causes the sub domain to be shadowed. With Split DNS one can avoid undesired + DNS leaks by properly configuring DNS priorities and the search domains, so + that only name servers of the desired interface are configured.""" dns_search: Optional[List[str]] = field( metadata={'dbus_name': 'dns-search', 'dbus_type': 'as'}, default=None, ) + """Array of DNS search domains. Domains starting with a tilde ('~') are + considered 'routing' domains and are used only to decide the interface over + which a query must be forwarded; they are not used to complete unqualified + host names. When using a DNS plugin that supports Conditional Forwarding or + Split DNS, then the search domains specify which name servers to query. This + makes the behavior different from running with plain /etc/resolv.conf. For + more information see also the dns-priority setting.""" gateway: Optional[str] = field( metadata={'dbus_name': 'gateway', 'dbus_type': 's'}, default=None, ) + """The gateway associated with this configuration. This is only meaningful if + "addresses" is also set. The gateway's main purpose is to control the next hop + of the standard default route on the device. Hence, the gateway property + conflicts with "never-default" and will be automatically dropped if the IP + configuration is set to never-default. As an alternative to set the gateway, + configure a static default route with /0 as prefix length.""" ignore_auto_dns: Optional[bool] = field( metadata={'dbus_name': 'ignore-auto-dns', 'dbus_type': 'b'}, default=False, ) + """When "method" is set to "auto" and this property to TRUE, automatically + configured name servers and search domains are ignored and only name servers + and search domains specified in the "dns" and "dns-search" properties, if any, + are used.""" ignore_auto_routes: Optional[bool] = field( metadata={'dbus_name': 'ignore-auto-routes', 'dbus_type': 'b'}, default=False, ) + """When "method" is set to "auto" and this property to TRUE, automatically + configured routes are ignored and only routes specified in the "routes" + property, if any, are used.""" ip6_privacy: Optional[int] = field( metadata={'dbus_name': 'ip6-privacy', 'dbus_type': 'i'}, default=None, ) + """Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If + enabled, it makes the kernel generate a temporary IPv6 address in addition to + the public one generated from MAC address via modified EUI-64. This enhances + privacy, but could cause problems in some applications, on the other hand. + The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public + address), 2: enabled (prefer temporary addresses). Having a per-connection + setting set to "-1" (unknown) means fallback to global configuration + "ipv6.ip6-privacy". If also global configuration is unspecified or set to + "-1", fallback to read "/proc/sys/net/ipv6/conf/default/use_tempaddr". Note + that this setting is distinct from the Stable Privacy addresses that can be + enabled with the "addr-gen-mode" property's "stable-privacy" setting as + another way of avoiding host tracking with IPv6 addresses.""" may_fail: Optional[bool] = field( metadata={'dbus_name': 'may-fail', 'dbus_type': 'b'}, default=True, ) + """If TRUE, allow overall network configuration to proceed even if the + configuration specified by this property times out. Note that at least one IP + configuration must succeed or overall network configuration will still fail. + For example, in IPv6-only networks, setting this property to TRUE on the + NMSettingIP4Config allows the overall network configuration to succeed if IPv4 + configuration fails but IPv6 configuration completes successfully.""" method: Optional[str] = field( metadata={'dbus_name': 'method', 'dbus_type': 's'}, default=None, ) + """IP configuration method. NMSettingIP4Config and NMSettingIP6Config both + support "disabled", "auto", "manual", and "link-local". See the subclass- + specific documentation for other values. In general, for the "auto" method, + properties such as "dns" and "routes" specify information that is added on to + the information returned from automatic configuration. The "ignore-auto- + routes" and "ignore-auto-dns" properties modify this behavior. For methods + that imply no upstream network, such as "shared" or "link-local", these + properties must be empty. For IPv4 method "shared", the IP subnet can be + configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is + chosen. Note that the shared method must be configured on the interface which + shares the internet to a subnet, not on the uplink which is shared.""" never_default: Optional[bool] = field( metadata={'dbus_name': 'never-default', 'dbus_type': 'b'}, default=False, ) + """If TRUE, this connection will never be the default connection for this IP + type, meaning it will never be assigned the default route by + NetworkManager.""" ra_timeout: Optional[int] = field( metadata={'dbus_name': 'ra-timeout', 'dbus_type': 'i'}, default=None, ) + """A timeout for waiting Router Advertisements in seconds. If zero (the + default), a globally configured default is used. If still unspecified, the + timeout depends on the sysctl settings of the device. Set to 2147483647 + (MAXINT32) for infinity.""" required_timeout: Optional[int] = field( metadata={'dbus_name': 'required-timeout', 'dbus_type': 'i'}, default=None, ) + """The minimum time interval in milliseconds for which dynamic IP + configuration should be tried before the connection succeeds. This property is + useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. + Normally the connection succeeds as soon as one of the two address families + completes; by setting a required timeout for e.g. IPv4, one can ensure that + even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for + IPv4 before the connection becomes active. Note that if "may-fail" is FALSE + for the same address family, this property has no effect as NetworkManager + needs to wait for the full DHCP timeout. A zero value means that no required + timeout is present, -1 means the default value (either configuration + ipvx.required-timeout override or zero).""" route_data: Optional[List[RouteData]] = field( metadata={'dbus_name': 'route-data', 'dbus_type': 'aa{sv}', @@ -116,11 +320,33 @@ class Ipv6Settings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'route-metric', 'dbus_type': 'x'}, default=None, ) + """The default metric for routes that don't explicitly specify a metric. The + default value -1 means that the metric is chosen automatically based on the + device type. The metric applies to dynamic routes, manual (static) routes that + don't have an explicit metric setting, address prefix routes, and the default + route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 + (user default). Hence, setting this property to zero effectively mean setting + it to 1024. For IPv4, zero is a regular value for the metric.""" route_table: Optional[int] = field( metadata={'dbus_name': 'route-table', 'dbus_type': 'u'}, default=None, ) + """Enable policy routing (source routing) and set the routing table used when + adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, + SLAAC, default-routes and static routes. But note that static routes can + individually overwrite the setting by explicitly specifying a non-zero routing + table. If the table setting is left at zero, it is eligible to be overwritten + via global configuration. If the property is zero even after applying the + global configuration value, policy routing is disabled for the address family + of this connection. Policy routing disabled means that NetworkManager will add + all routes to the main table (except static routes that explicitly configure a + different table). Additionally, NetworkManager will not delete any extraneous + routes from tables except the main table. This is to preserve backward + compatibility for users who manage routing tables outside of + NetworkManager.""" token: Optional[str] = field( metadata={'dbus_name': 'token', 'dbus_type': 's'}, default=None, ) + """Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 + tokenized interface identifiers. Useful with eui64 addr-gen-mode.""" diff --git a/sdbus_async/networkmanager/settings/lowpan.py b/sdbus_async/networkmanager/settings/lowpan.py index 0d8bc9f..dfd837c 100644 --- a/sdbus_async/networkmanager/settings/lowpan.py +++ b/sdbus_async/networkmanager/settings/lowpan.py @@ -15,3 +15,5 @@ class LowpanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name or parent connection UUID + from which this 6LowPAN interface should be created.""" diff --git a/sdbus_async/networkmanager/settings/macsec.py b/sdbus_async/networkmanager/settings/macsec.py index 022dda2..2eb7003 100644 --- a/sdbus_async/networkmanager/settings/macsec.py +++ b/sdbus_async/networkmanager/settings/macsec.py @@ -19,6 +19,8 @@ class MacsecSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mka-cak', 'dbus_type': 's'}, default=None, ) + """The pre-shared CAK (Connectivity Association Key) for MACsec Key + Agreement.""" mka_cak_flags: Optional[int] = field( metadata={'dbus_name': 'mka-cak-flags', 'dbus_type': 'i'}, default=None, @@ -27,22 +29,34 @@ class MacsecSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mka-ckn', 'dbus_type': 's'}, default=None, ) + """The pre-shared CKN (Connectivity-association Key Name) for MACsec Key + Agreement.""" mode: Optional[int] = field( metadata={'dbus_name': 'mode', 'dbus_type': 'i'}, default=None, ) + """Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key + Agreement) is obtained.""" parent: Optional[str] = field( metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name or parent connection UUID + from which this MACSEC interface should be created. If this property is not + specified, the connection must contain an "802-3-ethernet" setting with a + "mac-address" property.""" port: Optional[int] = field( metadata={'dbus_name': 'port', 'dbus_type': 'i'}, default=1, ) + """The port component of the SCI (Secure Channel Identifier), between 1 and + 65534.""" send_sci: Optional[bool] = field( metadata={'dbus_name': 'send-sci', 'dbus_type': 'b'}, default=True, ) + """Specifies whether the SCI (Secure Channel Identifier) is included in every + packet.""" validation: Optional[int] = field( metadata={'dbus_name': 'validation', 'dbus_type': 'i'}, default=2, diff --git a/sdbus_async/networkmanager/settings/macvlan.py b/sdbus_async/networkmanager/settings/macvlan.py index f97fb9c..b670c63 100644 --- a/sdbus_async/networkmanager/settings/macvlan.py +++ b/sdbus_async/networkmanager/settings/macvlan.py @@ -15,10 +15,16 @@ class MacvlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, default=None, ) + """The macvlan mode, which specifies the communication mechanism between + multiple macvlans on the same lower device.""" parent: Optional[str] = field( metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name or parent connection UUID + from which this MAC-VLAN interface should be created. If this property is not + specified, the connection must contain an "802-3-ethernet" setting with a + "mac-address" property.""" promiscuous: Optional[bool] = field( metadata={'dbus_name': 'promiscuous', 'dbus_type': 'b'}, default=True, diff --git a/sdbus_async/networkmanager/settings/match.py b/sdbus_async/networkmanager/settings/match.py index 033d73f..c253129 100644 --- a/sdbus_async/networkmanager/settings/match.py +++ b/sdbus_async/networkmanager/settings/match.py @@ -15,15 +15,51 @@ class MatchSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'driver', 'dbus_type': 'as'}, default=None, ) + """A list of driver names to match. Each element is a shell wildcard pattern. + See NMSettingMatch:interface-name for how special characters '|', '&', '!' and + '\\' are used for optional and mandatory matches and inverting the pattern.""" interface_name: Optional[List[str]] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 'as'}, default=None, ) + """A list of interface names to match. Each element is a shell wildcard + pattern. An element can be prefixed with a pipe symbol (|) or an ampersand + (&). The former means that the element is optional and the latter means that + it is mandatory. If there are any optional elements, than the match evaluates + to true if at least one of the optional element matches (logical OR). If there + are any mandatory elements, then they all must match (logical AND). By + default, an element is optional. This means that an element "foo" behaves the + same as "|foo". An element can also be inverted with exclamation mark (!) + between the pipe symbol (or the ampersand) and before the pattern. Note that + "!foo" is a shortcut for the mandatory match "&!foo". Finally, a backslash can + be used at the beginning of the element (after the optional special + characters) to escape the start of the pattern. For example, "&\\!a" is an + mandatory match for literally "!a".""" kernel_command_line: Optional[List[str]] = field( metadata={'dbus_name': 'kernel-command-line', 'dbus_type': 'as'}, default=None, ) + """A list of kernel command line arguments to match. This may be used to check + whether a specific kernel command line option is set (or unset, if prefixed + with the exclamation mark). The argument must either be a single word, or an + assignment (i.e. two words, joined by "="). In the former case the kernel + command line is searched for the word appearing as is, or as left hand side of + an assignment. In the latter case, the exact assignment is looked for with + right and left hand side matching. Wildcard patterns are not supported. See + NMSettingMatch:interface-name for how special characters '|', '&', '!' and + '\\' are used for optional and mandatory matches and inverting the match.""" path: Optional[List[str]] = field( metadata={'dbus_name': 'path', 'dbus_type': 'as'}, default=None, ) + """A list of paths to match against the ID_PATH udev property of devices. + ID_PATH represents the topological persistent path of a device. It typically + contains a subsystem string (pci, usb, platform, etc.) and a subsystem- + specific identifier. For PCI devices the path has the form + "pci-$domain:$bus:$device.$function", where each variable is an hexadecimal + value; for example "pci-0000:0a:00.0". The path of a device can be obtained + with "udevadm info /sys/class/net/$dev | grep ID_PATH=" or by looking at the + "path" property exported by NetworkManager ("nmcli -f general.path device show + $dev"). Each element of the list is a shell wildcard pattern. See + NMSettingMatch:interface-name for how special characters '|', '&', '!' and + '\\' are used for optional and mandatory matches and inverting the pattern.""" diff --git a/sdbus_async/networkmanager/settings/olpc_mesh.py b/sdbus_async/networkmanager/settings/olpc_mesh.py index dc6cf5b..68c69cc 100644 --- a/sdbus_async/networkmanager/settings/olpc_mesh.py +++ b/sdbus_async/networkmanager/settings/olpc_mesh.py @@ -19,6 +19,9 @@ class OlpcMeshSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'dhcp-anycast-address', 'dbus_type': 'ay'}, default=None, ) + """Anycast DHCP MAC address used when requesting an IP address via DHCP. The + specific anycast address used determines which DHCP server class answers the + request. This is currently only implemented by dhclient DHCP plugin.""" ssid: Optional[bytes] = field( metadata={'dbus_name': 'ssid', 'dbus_type': 'ay'}, default=None, diff --git a/sdbus_async/networkmanager/settings/ovs_dpdk.py b/sdbus_async/networkmanager/settings/ovs_dpdk.py index 5e2fab9..27faa6f 100644 --- a/sdbus_async/networkmanager/settings/ovs_dpdk.py +++ b/sdbus_async/networkmanager/settings/ovs_dpdk.py @@ -19,3 +19,6 @@ class OvsDpdkSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'n-rxq', 'dbus_type': 'u'}, default=None, ) + """Open vSwitch DPDK number of rx queues. Defaults to zero which means to + leave the parameter in OVS unspecified and effectively configures one + queue.""" diff --git a/sdbus_async/networkmanager/settings/ovs_interface.py b/sdbus_async/networkmanager/settings/ovs_interface.py index 4c38428..d655cd7 100644 --- a/sdbus_async/networkmanager/settings/ovs_interface.py +++ b/sdbus_async/networkmanager/settings/ovs_interface.py @@ -15,3 +15,5 @@ class OvsInterfaceSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'type', 'dbus_type': 's'}, default=None, ) + """The interface type. Either "internal", "system", "patch", "dpdk", or + empty.""" diff --git a/sdbus_async/networkmanager/settings/ovs_patch.py b/sdbus_async/networkmanager/settings/ovs_patch.py index f01f61c..fba70b9 100644 --- a/sdbus_async/networkmanager/settings/ovs_patch.py +++ b/sdbus_async/networkmanager/settings/ovs_patch.py @@ -15,3 +15,5 @@ class OvsPatchSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'peer', 'dbus_type': 's'}, default=None, ) + """Specifies the name of the interface for the other side of the patch. The + patch on the other side must also set this interface as peer.""" diff --git a/sdbus_async/networkmanager/settings/ovs_port.py b/sdbus_async/networkmanager/settings/ovs_port.py index 13c4b05..1e8744d 100644 --- a/sdbus_async/networkmanager/settings/ovs_port.py +++ b/sdbus_async/networkmanager/settings/ovs_port.py @@ -35,3 +35,5 @@ class OvsPortSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'vlan-mode', 'dbus_type': 's'}, default=None, ) + """The VLAN mode. One of "access", "native-tagged", "native-untagged", "trunk" + or unset.""" diff --git a/sdbus_async/networkmanager/settings/ppp.py b/sdbus_async/networkmanager/settings/ppp.py index dcb15d1..2251a06 100644 --- a/sdbus_async/networkmanager/settings/ppp.py +++ b/sdbus_async/networkmanager/settings/ppp.py @@ -15,30 +15,51 @@ class PppSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'baud', 'dbus_type': 'u'}, default=None, ) + """If non-zero, instruct pppd to set the serial port to the specified + baudrate. This value should normally be left as 0 to automatically choose the + speed.""" crtscts: Optional[bool] = field( metadata={'dbus_name': 'crtscts', 'dbus_type': 'b'}, default=False, ) + """If TRUE, specify that pppd should set the serial port to use hardware flow + control with RTS and CTS signals. This value should normally be set to + FALSE.""" lcp_echo_failure: Optional[int] = field( metadata={'dbus_name': 'lcp-echo-failure', 'dbus_type': 'u'}, default=None, ) + """If non-zero, instruct pppd to presume the connection to the peer has failed + if the specified number of LCP echo-requests go unanswered by the peer. The + "lcp-echo-interval" property must also be set to a non-zero value if this + property is used.""" lcp_echo_interval: Optional[int] = field( metadata={'dbus_name': 'lcp-echo-interval', 'dbus_type': 'u'}, default=None, ) + """If non-zero, instruct pppd to send an LCP echo-request frame to the peer + every n seconds (where n is the specified value). Note that some PPP peers + will respond to echo requests and some will not, and it is not possible to + autodetect this.""" mppe_stateful: Optional[bool] = field( metadata={'dbus_name': 'mppe-stateful', 'dbus_type': 'b'}, default=False, ) + """If TRUE, stateful MPPE is used. See pppd documentation for more + information on stateful MPPE.""" mru: Optional[int] = field( metadata={'dbus_name': 'mru', 'dbus_type': 'u'}, default=None, ) + """If non-zero, instruct pppd to request that the peer send packets no larger + than the specified size. If non-zero, the MRU should be between 128 and + 16384.""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, instruct pppd to send packets no larger than the specified + size.""" no_vj_comp: Optional[bool] = field( metadata={'dbus_name': 'no-vj-comp', 'dbus_type': 'b'}, default=False, @@ -47,6 +68,9 @@ class PppSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'noauth', 'dbus_type': 'b'}, default=True, ) + """If TRUE, do not require the other side (usually the PPP server) to + authenticate itself to the client. If FALSE, require authentication from the + remote side. In almost all cases, this should be TRUE.""" nobsdcomp: Optional[bool] = field( metadata={'dbus_name': 'nobsdcomp', 'dbus_type': 'b'}, default=False, @@ -79,7 +103,14 @@ class PppSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'require-mppe', 'dbus_type': 'b'}, default=False, ) + """If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for + the PPP session. If either 64-bit or 128-bit MPPE is not available the + session will fail. Note that MPPE is not used on mobile broadband + connections.""" require_mppe_128: Optional[bool] = field( metadata={'dbus_name': 'require-mppe-128', 'dbus_type': 'b'}, default=False, ) + """If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be + required for the PPP session, and the "require-mppe" property must also be set + to TRUE. If 128-bit MPPE is not available the session will fail.""" diff --git a/sdbus_async/networkmanager/settings/pppoe.py b/sdbus_async/networkmanager/settings/pppoe.py index e2cbb42..faf9a1f 100644 --- a/sdbus_async/networkmanager/settings/pppoe.py +++ b/sdbus_async/networkmanager/settings/pppoe.py @@ -15,6 +15,10 @@ class PppoeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name on which this PPPoE + connection should be created. If this property is not specified, the + connection is activated on the interface specified in "interface-name" of + NMSettingConnection.""" password: Optional[str] = field( metadata={'dbus_name': 'password', 'dbus_type': 's'}, default=None, @@ -27,6 +31,10 @@ class PppoeSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'service', 'dbus_type': 's'}, default=None, ) + """If specified, instruct PPPoE to only initiate sessions with access + concentrators that provide the specified service. For most providers, this + should be left blank. It is only required if there are multiple access + concentrators or a specific service is known to be required.""" username: Optional[str] = field( metadata={'dbus_name': 'username', 'dbus_type': 's'}, default=None, diff --git a/sdbus_async/networkmanager/settings/proxy.py b/sdbus_async/networkmanager/settings/proxy.py index 5aac8c8..eca2460 100644 --- a/sdbus_async/networkmanager/settings/proxy.py +++ b/sdbus_async/networkmanager/settings/proxy.py @@ -19,6 +19,8 @@ class ProxySettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'method', 'dbus_type': 'i'}, default=None, ) + """Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE + (0)""" pac_script: Optional[str] = field( metadata={'dbus_name': 'pac-script', 'dbus_type': 's'}, default=None, diff --git a/sdbus_async/networkmanager/settings/serial.py b/sdbus_async/networkmanager/settings/serial.py index 5cb2cc1..3e44831 100644 --- a/sdbus_async/networkmanager/settings/serial.py +++ b/sdbus_async/networkmanager/settings/serial.py @@ -15,6 +15,9 @@ class SerialSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'baud', 'dbus_type': 'u'}, default=57600, ) + """Speed to use for communication over the serial port. Note that this value + usually has no effect for mobile broadband modems as they generally ignore + speed settings and use the highest available speed.""" bits: Optional[int] = field( metadata={'dbus_name': 'bits', 'dbus_type': 'u'}, default=8, @@ -23,6 +26,8 @@ class SerialSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'parity', 'dbus_type': 'y'}, default=None, ) + """The connection parity: 69 (ASCII 'E') for even parity, 111 (ASCII 'o') for + odd, 110 (ASCII 'n') for none.""" send_delay: Optional[int] = field( metadata={'dbus_name': 'send-delay', 'dbus_type': 't'}, default=None, @@ -31,3 +36,5 @@ class SerialSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'stopbits', 'dbus_type': 'u'}, default=1, ) + """Number of stop bits for communication on the serial port. Either 1 or 2. + The 1 in "8n1" for example.""" diff --git a/sdbus_async/networkmanager/settings/team.py b/sdbus_async/networkmanager/settings/team.py index 7a43390..5646abf 100644 --- a/sdbus_async/networkmanager/settings/team.py +++ b/sdbus_async/networkmanager/settings/team.py @@ -16,10 +16,17 @@ class TeamSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'config', 'dbus_type': 's'}, default=None, ) + """The JSON configuration for the team network interface. The property should + contain raw JSON configuration data suitable for teamd, because the value is + passed directly to teamd. If not specified, the default configuration is used. + See man teamd.conf for the format details.""" interface_name: Optional[str] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, default=None, ) + """Deprecated in favor of connection.interface-name, but can be used for + backward-compatibility with older daemons, to set the team's interface + name.""" link_watchers: Optional[List[LinkWatchers]] = field( metadata={'dbus_name': 'link-watchers', 'dbus_type': 'aa{sv}', @@ -46,6 +53,8 @@ class TeamSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'runner', 'dbus_type': 's'}, default=None, ) + """Corresponds to the teamd runner.name. Permitted values are: "roundrobin", + "broadcast", "activebackup", "loadbalance", "lacp", "random".""" runner_active: Optional[bool] = field( metadata={'dbus_name': 'runner-active', 'dbus_type': 'b'}, default=True, diff --git a/sdbus_async/networkmanager/settings/team_port.py b/sdbus_async/networkmanager/settings/team_port.py index 453c42f..26f4733 100644 --- a/sdbus_async/networkmanager/settings/team_port.py +++ b/sdbus_async/networkmanager/settings/team_port.py @@ -16,6 +16,10 @@ class TeamPortSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'config', 'dbus_type': 's'}, default=None, ) + """The JSON configuration for the team port. The property should contain raw + JSON configuration data suitable for teamd, because the value is passed + directly to teamd. If not specified, the default configuration is used. See + man teamd.conf for the format details.""" lacp_key: Optional[int] = field( metadata={'dbus_name': 'lacp-key', 'dbus_type': 'i'}, default=None, @@ -38,6 +42,8 @@ class TeamPortSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'queue-id', 'dbus_type': 'i'}, default=None, ) + """Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means + the parameter is skipped from the json config.""" sticky: Optional[bool] = field( metadata={'dbus_name': 'sticky', 'dbus_type': 'b'}, default=False, diff --git a/sdbus_async/networkmanager/settings/tun.py b/sdbus_async/networkmanager/settings/tun.py index ea834e7..af7b6b1 100644 --- a/sdbus_async/networkmanager/settings/tun.py +++ b/sdbus_async/networkmanager/settings/tun.py @@ -15,23 +15,37 @@ class TunSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'group', 'dbus_type': 's'}, default=None, ) + """The group ID which will own the device. If set to NULL everyone will be + able to use the device.""" mode: Optional[int] = field( metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, default=1, ) + """The operating mode of the virtual device. Allowed values are + NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and + NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one.""" multi_queue: Optional[bool] = field( metadata={'dbus_name': 'multi-queue', 'dbus_type': 'b'}, default=False, ) + """If the property is set to TRUE, the interface will support multiple file + descriptors (queues) to parallelize packet sending or receiving. Otherwise, + the interface will only support a single queue.""" owner: Optional[str] = field( metadata={'dbus_name': 'owner', 'dbus_type': 's'}, default=None, ) + """The user ID which will own the device. If set to NULL everyone will be able + to use the device.""" pi: Optional[bool] = field( metadata={'dbus_name': 'pi', 'dbus_type': 'b'}, default=False, ) + """If TRUE the interface will prepend a 4 byte header describing the physical + interface to the packets.""" vnet_hdr: Optional[bool] = field( metadata={'dbus_name': 'vnet-hdr', 'dbus_type': 'b'}, default=False, ) + """If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network + header.""" diff --git a/sdbus_async/networkmanager/settings/user.py b/sdbus_async/networkmanager/settings/user.py index dc223a5..be0c0ee 100644 --- a/sdbus_async/networkmanager/settings/user.py +++ b/sdbus_async/networkmanager/settings/user.py @@ -15,3 +15,7 @@ class UserSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'data', 'dbus_type': 'a{ss}'}, default=None, ) + """A dictionary of key/value pairs with user data. This data is ignored by + NetworkManager and can be used at the users discretion. The keys only support + a strict ascii format, but the values can be arbitrary UTF8 strings up to a + certain length.""" diff --git a/sdbus_async/networkmanager/settings/veth.py b/sdbus_async/networkmanager/settings/veth.py index b263845..8b4bc0d 100644 --- a/sdbus_async/networkmanager/settings/veth.py +++ b/sdbus_async/networkmanager/settings/veth.py @@ -15,3 +15,5 @@ class VethSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'peer', 'dbus_type': 's'}, default=None, ) + """This property specifies the peer interface name of the veth. This property + is mandatory.""" diff --git a/sdbus_async/networkmanager/settings/vlan.py b/sdbus_async/networkmanager/settings/vlan.py index 7e49da0..73af40f 100644 --- a/sdbus_async/networkmanager/settings/vlan.py +++ b/sdbus_async/networkmanager/settings/vlan.py @@ -15,23 +15,47 @@ class VlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'egress-priority-map', 'dbus_type': 'as'}, default=None, ) + """For outgoing packets, a list of mappings from Linux SKB priorities to + 802.1p priorities. The mapping is given in the format "from:to" where both + "from" and "to" are unsigned integers, ie "7:3".""" flags: Optional[int] = field( metadata={'dbus_name': 'flags', 'dbus_type': 'i'}, default=None, ) + """One or more flags which control the behavior and features of the VLAN + interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of + output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), + and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its + master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP + protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, + but it used to be 0. To preserve backward compatibility, the default-value in + the D-Bus API continues to be 0 and a missing property on D-Bus is still + considered as 0.""" vlan_id: Optional[int] = field( metadata={'dbus_name': 'id', 'dbus_type': 'u'}, default=None, ) + """The VLAN identifier that the interface created by this connection should be + assigned. The valid range is from 0 to 4094, without the reserved id 4095.""" ingress_priority_map: Optional[List[str]] = field( metadata={'dbus_name': 'ingress-priority-map', 'dbus_type': 'as'}, default=None, ) + """For incoming packets, a list of mappings from 802.1p priorities to Linux + SKB priorities. The mapping is given in the format "from:to" where both + "from" and "to" are unsigned integers, ie "7:3".""" interface_name: Optional[str] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, default=None, ) + """Deprecated in favor of connection.interface-name, but can be used for + backward-compatibility with older daemons, to set the vlan's interface + name.""" parent: Optional[str] = field( metadata={'dbus_name': 'parent', 'dbus_type': 's'}, default=None, ) + """If given, specifies the parent interface name or parent connection UUID + from which this VLAN interface should be created. If this property is not + specified, the connection must contain an "802-3-ethernet" setting with a + "mac-address" property.""" diff --git a/sdbus_async/networkmanager/settings/vpn.py b/sdbus_async/networkmanager/settings/vpn.py index 19016ea..0e6dc06 100644 --- a/sdbus_async/networkmanager/settings/vpn.py +++ b/sdbus_async/networkmanager/settings/vpn.py @@ -15,23 +15,42 @@ class VpnSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'data', 'dbus_type': 'a{ss}'}, default=None, ) + """Dictionary of key/value pairs of VPN plugin specific data. Both keys and + values must be strings.""" persistent: Optional[bool] = field( metadata={'dbus_name': 'persistent', 'dbus_type': 'b'}, default=False, ) + """If the VPN service supports persistence, and this property is TRUE, the VPN + will attempt to stay connected across link changes and outages, until + explicitly disconnected.""" secrets: Optional[Dict[str, str]] = field( metadata={'dbus_name': 'secrets', 'dbus_type': 'a{ss}'}, default=None, ) + """Dictionary of key/value pairs of VPN plugin specific secrets like passwords + or private keys. Both keys and values must be strings.""" service_type: Optional[str] = field( metadata={'dbus_name': 'service-type', 'dbus_type': 's'}, default=None, ) + """D-Bus service name of the VPN plugin that this setting uses to connect to + its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.""" timeout: Optional[int] = field( metadata={'dbus_name': 'timeout', 'dbus_type': 'u'}, default=None, ) + """Timeout for the VPN service to establish the connection. Some services may + take quite a long time to connect. Value of 0 means a default timeout, which + is 60 seconds (unless overridden by vpn.timeout in configuration file). Values + greater than zero mean timeout in seconds.""" user_name: Optional[str] = field( metadata={'dbus_name': 'user-name', 'dbus_type': 's'}, default=None, ) + """If the VPN connection requires a user name for authentication, that name + should be provided here. If the connection is available to more than one + user, and the VPN requires each user to supply a different name, then leave + this property empty. If this property is empty, NetworkManager will + automatically supply the username of the user which requested the VPN + connection.""" diff --git a/sdbus_async/networkmanager/settings/vxlan.py b/sdbus_async/networkmanager/settings/vxlan.py index e1c2552..617a5a0 100644 --- a/sdbus_async/networkmanager/settings/vxlan.py +++ b/sdbus_async/networkmanager/settings/vxlan.py @@ -19,10 +19,14 @@ class VxlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'destination-port', 'dbus_type': 'u'}, default=8472, ) + """Specifies the UDP destination port to communicate to the remote VXLAN + tunnel endpoint.""" vxlan_id: Optional[int] = field( metadata={'dbus_name': 'id', 'dbus_type': 'u'}, default=None, ) + """Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to + use.""" l2_miss: Optional[bool] = field( metadata={'dbus_name': 'l2-miss', 'dbus_type': 'b'}, default=False, @@ -35,10 +39,14 @@ class VxlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'learning', 'dbus_type': 'b'}, default=True, ) + """Specifies whether unknown source link layer addresses and IP addresses are + entered into the VXLAN device forwarding database.""" limit: Optional[int] = field( metadata={'dbus_name': 'limit', 'dbus_type': 'u'}, default=None, ) + """Specifies the maximum number of FDB entries. A value of zero means that the + kernel will store unlimited entries.""" local: Optional[str] = field( metadata={'dbus_name': 'local', 'dbus_type': 's'}, default=None, @@ -55,6 +63,9 @@ class VxlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'remote', 'dbus_type': 's'}, default=None, ) + """Specifies the unicast destination IP address to use in outgoing packets + when the destination link layer address is not known in the VXLAN device + forwarding database, or the multicast IP address to join.""" rsc: Optional[bool] = field( metadata={'dbus_name': 'rsc', 'dbus_type': 'b'}, default=False, @@ -63,10 +74,14 @@ class VxlanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'source-port-max', 'dbus_type': 'u'}, default=None, ) + """Specifies the maximum UDP source port to communicate to the remote VXLAN + tunnel endpoint.""" source_port_min: Optional[int] = field( metadata={'dbus_name': 'source-port-min', 'dbus_type': 'u'}, default=None, ) + """Specifies the minimum UDP source port to communicate to the remote VXLAN + tunnel endpoint.""" tos: Optional[int] = field( metadata={'dbus_name': 'tos', 'dbus_type': 'u'}, default=None, diff --git a/sdbus_async/networkmanager/settings/wifi_p2p.py b/sdbus_async/networkmanager/settings/wifi_p2p.py index 5c4a644..efe4981 100644 --- a/sdbus_async/networkmanager/settings/wifi_p2p.py +++ b/sdbus_async/networkmanager/settings/wifi_p2p.py @@ -15,11 +15,21 @@ class WifiP2PSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'peer', 'dbus_type': 's'}, default=None, ) + """The P2P device that should be connected to. Currently, this is the only way + to create or join a group.""" wfd_ies: Optional[bytes] = field( metadata={'dbus_name': 'wfd-ies', 'dbus_type': 'ay'}, default=None, ) + """The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display + requires a protocol specific information element to be set in certain Wi-Fi + frames. These can be specified here for the purpose of establishing a + connection. This setting is only useful when implementing a Wi-Fi Display + client.""" wps_method: Optional[int] = field( metadata={'dbus_name': 'wps-method', 'dbus_type': 'u'}, default=None, ) + """Flags indicating which mode of WPS is to be used. There's little point in + changing the default setting as NetworkManager will automatically determine + the best method to use.""" diff --git a/sdbus_async/networkmanager/settings/wimax.py b/sdbus_async/networkmanager/settings/wimax.py index 0e67c8e..35137ea 100644 --- a/sdbus_async/networkmanager/settings/wimax.py +++ b/sdbus_async/networkmanager/settings/wimax.py @@ -15,7 +15,12 @@ class WimaxSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, this connection will only apply to the WiMAX device whose MAC + address matches. This property does not change the MAC address of the device + (known as MAC spoofing). Deprecated: 1""" network_name: Optional[str] = field( metadata={'dbus_name': 'network-name', 'dbus_type': 's'}, default=None, ) + """Network Service Provider (NSP) name of the WiMAX network this connection + should use. Deprecated: 1""" diff --git a/sdbus_async/networkmanager/settings/wireguard.py b/sdbus_async/networkmanager/settings/wireguard.py index 65e845b..55ca7ff 100644 --- a/sdbus_async/networkmanager/settings/wireguard.py +++ b/sdbus_async/networkmanager/settings/wireguard.py @@ -16,10 +16,25 @@ class WireguardSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'fwmark', 'dbus_type': 'u'}, default=None, ) + """The use of fwmark is optional and is by default off. Setting it to 0 + disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. Note that + "ip4-auto-default-route" or "ip6-auto-default-route" enabled, implies to + automatically choose a fwmark.""" ip4_auto_default_route: Optional[int] = field( metadata={'dbus_name': 'ip4-auto-default-route', 'dbus_type': 'i'}, default=None, ) + """Whether to enable special handling of the IPv4 default route. If enabled, + the IPv4 default route from wireguard.peer-routes will be placed to a + dedicated routing-table and two policy routing rules will be added. The fwmark + number is also used as routing-table for the default-route, and if fwmark is + zero, an unused fwmark/table is chosen automatically. This corresponds to what + wg-quick does with Table=auto and what WireGuard calls "Improved Rule-based + Routing". Note that for this automatism to work, you usually don't want to set + ipv4.gateway, because that will result in a conflicting default route. Leaving + this at the default will enable this option automatically if ipv4.never- + default is not set and there are any peers that use a default-route as + allowed-ips.""" ip6_auto_default_route: Optional[int] = field( metadata={'dbus_name': 'ip6-auto-default-route', 'dbus_type': 'i'}, default=None, @@ -28,14 +43,29 @@ class WireguardSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'listen-port', 'dbus_type': 'u'}, default=None, ) + """The listen-port. If listen-port is not specified, the port will be chosen + randomly when the interface comes up.""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple fragments. If zero a default MTU is + used. Note that contrary to wg-quick's MTU setting, this does not take into + account the current routes at the time of activation.""" peer_routes: Optional[bool] = field( metadata={'dbus_name': 'peer-routes', 'dbus_type': 'b'}, default=True, ) + """Whether to automatically add routes for the AllowedIPs ranges of the peers. + If TRUE (the default), NetworkManager will automatically add routes in the + routing tables according to ipv4.route-table and ipv6.route-table. Usually you + want this automatism enabled. If FALSE, no such routes are added + automatically. In this case, the user may want to configure static routes in + ipv4.routes and ipv6.routes, respectively. Note that if the peer's AllowedIPs + is "0.0.0.0/0" or "::/0" and the profile's ipv4.never-default or ipv6.never- + default setting is enabled, the peer route for this peer won't be added + automatically.""" peers: Optional[List[Peers]] = field( metadata={'dbus_name': 'peers', 'dbus_type': 'aa{sv}', diff --git a/sdbus_async/networkmanager/settings/wireless.py b/sdbus_async/networkmanager/settings/wireless.py index 4d5d165..2d7235c 100644 --- a/sdbus_async/networkmanager/settings/wireless.py +++ b/sdbus_async/networkmanager/settings/wireless.py @@ -15,70 +15,168 @@ class WirelessSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'ap-isolation', 'dbus_type': 'i'}, default=None, ) + """Configures AP isolation, which prevents communication between wireless + devices connected to this AP. This property can be set to a value different + from NM_TERNARY_DEFAULT (-1) only when the interface is configured in AP mode. + If set to NM_TERNARY_TRUE (1), devices are not able to communicate with each + other. This increases security because it protects devices against attacks + from other clients in the network. At the same time, it prevents devices to + access resources on the same wireless networks as file shares, printers, etc. + If set to NM_TERNARY_FALSE (0), devices can talk to each other. When set to + NM_TERNARY_DEFAULT (-1), the global default is used; in case the global + default is unspecified it is assumed to be NM_TERNARY_FALSE (0).""" assigned_mac_address: Optional[str] = field( metadata={'dbus_name': 'assigned-mac-address', 'dbus_type': 's'}, default=None, ) + """The new field for the cloned MAC address. It can be either a hardware + address in ASCII representation, or one of the special values "preserve", + "permanent", "random" or "stable". This field replaces the deprecated "cloned- + mac-address" on D-Bus, which can only contain explicit hardware addresses. + Note that this property only exists in D-Bus API. libnm and nmcli continue to + call this property "cloned-mac-address".""" band: Optional[str] = field( metadata={'dbus_name': 'band', 'dbus_type': 's'}, default=None, ) + """802.11 frequency band of the network. One of "a" for 5GHz 802.11a or "bg" + for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the + specific band, i.e. if "a" is specified, the device will not associate with + the same network in the 2.4GHz band even if the network's settings are + compatible. This setting depends on specific driver capability and may not + work with all drivers.""" bssid: Optional[bytes] = field( metadata={'dbus_name': 'bssid', 'dbus_type': 'ay'}, default=None, ) + """If specified, directs the device to only associate with the given access + point. This capability is highly driver dependent and not supported by all + devices. Note: this property does not control the BSSID used when creating an + Ad-Hoc network and is unlikely to in the future.""" channel: Optional[int] = field( metadata={'dbus_name': 'channel', 'dbus_type': 'u'}, default=None, ) + """Wireless channel to use for the Wi-Fi connection. The device will only + join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. + Because channel numbers overlap between bands, this property also requires the + "band" property to be set.""" cloned_mac_address: Optional[bytes] = field( metadata={'dbus_name': 'cloned-mac-address', 'dbus_type': 'ay'}, default=None, ) + """This D-Bus field is deprecated in favor of "assigned-mac-address" which is + more flexible and allows specifying special variants like "random". For libnm + and nmcli, this field is called "cloned-mac-address".""" generate_mac_address_mask: Optional[str] = field( metadata={'dbus_name': 'generate-mac-address-mask', 'dbus_type': 's'}, default=None, ) + """With "cloned-mac-address" setting "random" or "stable", by default all bits + of the MAC address are scrambled and a locally-administered, unicast MAC + address is created. This property allows to specify that certain bits are + fixed. Note that the least significant bit of the first MAC address will + always be unset to create a unicast MAC address. If the property is NULL, it + is eligible to be overwritten by a default connection setting. If the value is + still NULL or an empty string, the default is to create a locally- + administered, unicast MAC address. If the value contains one MAC address, this + address is used as mask. The set bits of the mask are to be filled with the + current MAC address of the device, while the unset bits are subject to + randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the + current MAC address and only randomize the lower 3 bytes using the "random" or + "stable" algorithm. If the value contains one additional MAC address after the + mask, this address is used instead of the current MAC address to fill the bits + that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 + 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the + lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" + will create a fully scrambled globally-administered, burned-in MAC address. If + the value contains more than one additional MAC addresses, one of them is + chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 + 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally + or globally administered.""" hidden: Optional[bool] = field( metadata={'dbus_name': 'hidden', 'dbus_type': 'b'}, default=False, ) + """If TRUE, indicates that the network is a non-broadcasting network that + hides its SSID. This works both in infrastructure and AP mode. In + infrastructure mode, various workarounds are used for a more reliable + discovery of hidden networks, such as probe-scanning the SSID. However, these + workarounds expose inherent insecurities with hidden SSID networks, and thus + hidden SSID networks should be used with caution. In AP mode, the created + network does not broadcast its SSID. Note that marking the network as hidden + may be a privacy issue for you (in infrastructure mode) or client stations (in + AP mode), as the explicit probe-scans are distinctly recognizable on the + air.""" mac_address: Optional[bytes] = field( metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, default=None, ) + """If specified, this connection will only apply to the Wi-Fi device whose + permanent MAC address matches. This property does not change the MAC address + of the device (i.e. MAC spoofing).""" mac_address_blacklist: Optional[List[str]] = field( metadata={'dbus_name': 'mac-address-blacklist', 'dbus_type': 'as'}, default=None, ) + """A list of permanent MAC addresses of Wi-Fi devices to which this connection + should never apply. Each MAC address should be given in the standard hex- + digits-and-colons notation (eg "00:11:22:33:44:55").""" mac_address_randomization: Optional[int] = field( metadata={'dbus_name': 'mac-address-randomization', 'dbus_type': 'u'}, default=None, ) + """One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the + user has set a global default to randomize and the supplicant supports + randomization), NM_SETTING_MAC_RANDOMIZATION_NEVER (1) (never randomize the + MAC address), or NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the + MAC address). This property is deprecated for 'cloned-mac-address'. + Deprecated: 1""" mode: Optional[str] = field( metadata={'dbus_name': 'mode', 'dbus_type': 's'}, default=None, ) + """Wi-Fi network mode; one of "infrastructure", "mesh", "adhoc" or "ap". If + blank, infrastructure is assumed.""" mtu: Optional[int] = field( metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, default=None, ) + """If non-zero, only transmit packets of the specified size or smaller, + breaking larger packets up into multiple Ethernet frames.""" powersave: Optional[int] = field( metadata={'dbus_name': 'powersave', 'dbus_type': 'u'}, default=None, ) + """One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power + saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power saving), + NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch currently configure + setting) or NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally + configured value). All other values are reserved.""" rate: Optional[int] = field( metadata={'dbus_name': 'rate', 'dbus_type': 'u'}, default=None, ) + """If non-zero, directs the device to only use the specified bitrate for + communication with the access point. Units are in Kb/s, ie 5500 = 5.5 Mbit/s. + This property is highly driver dependent and not all devices support setting a + static bitrate.""" security: Optional[str] = field( metadata={'dbus_name': 'security', 'dbus_type': 's'}, default=None, ) + """This property is deprecated, but can be set to the value '802-11-wireless- + security' when a wireless security setting is also present in the connection + dictionary, for compatibility with very old NetworkManager daemons.""" seen_bssids: Optional[List[str]] = field( metadata={'dbus_name': 'seen-bssids', 'dbus_type': 'as'}, default=None, ) + """A list of BSSIDs (each BSSID formatted as a MAC address like + "00:11:22:33:44:55") that have been detected as part of the Wi-Fi network. + NetworkManager internally tracks previously seen BSSIDs. The property is only + meant for reading and reflects the BSSID list of NetworkManager. The changes + you make to this property will not be preserved.""" ssid: Optional[bytes] = field( metadata={'dbus_name': 'ssid', 'dbus_type': 'ay'}, default=None, @@ -87,7 +185,22 @@ class WirelessSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'tx-power', 'dbus_type': 'u'}, default=None, ) + """If non-zero, directs the device to use the specified transmit power. Units + are dBm. This property is highly driver dependent and not all devices support + setting a static transmit power.""" wake_on_wlan: Optional[int] = field( metadata={'dbus_name': 'wake-on-wlan', 'dbus_type': 'u'}, default=1, ) + """The NMSettingWirelessWakeOnWLan options to enable. Not all devices support + all options. May be any combination of NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY + (0x2), NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT (0x4), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC (0x8), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE (0x10), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST (0x20), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE (0x40), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE (0x80), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP (0x100) or the special values + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (0x1) (to use global settings) and + NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (0x8000) (to disable management of + Wake-on-LAN in NetworkManager).""" diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index 926298b..0dbc4cd 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -15,22 +15,47 @@ class WirelessSecuritySettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'auth-alg', 'dbus_type': 's'}, default=None, ) + """When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 + authentication algorithm required by the AP here. One of "open" for Open + System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco + LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" + and "leap-password" properties must be specified.""" fils: Optional[int] = field( metadata={'dbus_name': 'fils', 'dbus_type': 'i'}, default=None, ) + """Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for + the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use + global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable + FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the + supplicant and the access point support it) or + NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not + supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no + global default is set, FILS will be optionally enabled.""" group: Optional[List[str]] = field( metadata={'dbus_name': 'group', 'dbus_type': 'as'}, default=None, ) + """A list of group/broadcast encryption algorithms which prevents connections + to Wi-Fi networks that do not utilize one of the algorithms in the list. For + maximum compatibility leave this property empty. Each list element may be one + of "wep40", "wep104", "tkip", or "ccmp".""" key_mgmt: Optional[str] = field( metadata={'dbus_name': 'key-mgmt', 'dbus_type': 's'}, default=None, ) + """Key management used for the connection. One of "none" (WEP or no password + protection), "ieee8021x" (Dynamic WEP), "owe" (Opportunistic Wireless + Encryption), "wpa-psk" (WPA2 + WPA3 personal), "sae" (WPA3 personal only), + "wpa-eap" (WPA2 + WPA3 enterprise) or "wpa-eap-suite-b-192" (WPA3 enterprise + only). This property must be set for any Wi-Fi connection that uses + security.""" leap_password: Optional[str] = field( metadata={'dbus_name': 'leap-password', 'dbus_type': 's'}, default=None, ) + """The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" + and auth-alg = "leap").""" leap_password_flags: Optional[int] = field( metadata={'dbus_name': 'leap-password-flags', 'dbus_type': 'i'}, default=None, @@ -39,22 +64,44 @@ class WirelessSecuritySettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'leap-username', 'dbus_type': 's'}, default=None, ) + """The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" + and auth-alg = "leap").""" pairwise: Optional[List[str]] = field( metadata={'dbus_name': 'pairwise', 'dbus_type': 'as'}, default=None, ) + """A list of pairwise encryption algorithms which prevents connections to Wi- + Fi networks that do not utilize one of the algorithms in the list. For maximum + compatibility leave this property empty. Each list element may be one of + "tkip" or "ccmp".""" pmf: Optional[int] = field( metadata={'dbus_name': 'pmf', 'dbus_type': 'i'}, default=None, ) + """Indicates whether Protected Management Frames (802.11w) must be enabled for + the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use + global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable + PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the + supplicant and the access point support it) or + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not + supported). When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no + global default is set, PMF will be optionally enabled.""" proto: Optional[List[str]] = field( metadata={'dbus_name': 'proto', 'dbus_type': 'as'}, default=None, ) + """List of strings specifying the allowed WPA protocol versions to use. Each + element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If not + specified, both WPA and RSN connections are allowed.""" psk: Optional[str] = field( metadata={'dbus_name': 'psk', 'dbus_type': 's'}, default=None, ) + """Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII + passphrase of 8 to 63 characters that is (as specified in the 802.11i + standard) hashed to derive the actual key, or the key in form of 64 + hexadecimal character. The WPA3-Personal networks use a passphrase of any + length for SAE authentication.""" psk_flags: Optional[int] = field( metadata={'dbus_name': 'psk-flags', 'dbus_type': 'i'}, default=None, @@ -63,31 +110,55 @@ class WirelessSecuritySettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'wep-key-flags', 'dbus_type': 'i'}, default=None, ) + """Flags indicating how to handle the "wep-key0", "wep-key1", "wep-key2", and + "wep-key3" properties.""" wep_key_type: Optional[int] = field( metadata={'dbus_name': 'wep-key-type', 'dbus_type': 'i'}, default=None, ) + """Controls the interpretation of WEP keys. Allowed values are + NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character + hexadecimal string, or a 5- or 13-character ASCII password; or + NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a + string and will be hashed using the de-facto MD5 method to derive the actual + WEP key.""" wep_key0: Optional[str] = field( metadata={'dbus_name': 'wep-key0', 'dbus_type': 's'}, default=None, ) + """Index 0 WEP key. This is the WEP key used in most networks. See the "wep- + key-type" property for a description of how this key is interpreted.""" wep_key1: Optional[str] = field( metadata={'dbus_name': 'wep-key1', 'dbus_type': 's'}, default=None, ) + """Index 1 WEP key. This WEP index is not used by most networks. See the + "wep-key-type" property for a description of how this key is interpreted.""" wep_key2: Optional[str] = field( metadata={'dbus_name': 'wep-key2', 'dbus_type': 's'}, default=None, ) + """Index 2 WEP key. This WEP index is not used by most networks. See the + "wep-key-type" property for a description of how this key is interpreted.""" wep_key3: Optional[str] = field( metadata={'dbus_name': 'wep-key3', 'dbus_type': 's'}, default=None, ) + """Index 3 WEP key. This WEP index is not used by most networks. See the + "wep-key-type" property for a description of how this key is interpreted.""" wep_tx_keyidx: Optional[int] = field( metadata={'dbus_name': 'wep-tx-keyidx', 'dbus_type': 'u'}, default=None, ) + """When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key + index is used by the AP, put that WEP key index here. Valid values are 0 + (default key) through 3. Note that some consumer access points (like the + Linksys WRT54G) number the keys 1 - 4.""" wps_method: Optional[int] = field( metadata={'dbus_name': 'wps-method', 'dbus_type': 'u'}, default=None, ) + """Flags indicating which mode of WPS is to be used if any. There's little + point in changing the default setting as NetworkManager will automatically + determine whether it's feasible to start WPS enrollment from the Access Point + capabilities. WPS can be disabled by setting this property to a value of 1.""" diff --git a/sdbus_async/networkmanager/settings/wpan.py b/sdbus_async/networkmanager/settings/wpan.py index aa79a0a..1c4fbc2 100644 --- a/sdbus_async/networkmanager/settings/wpan.py +++ b/sdbus_async/networkmanager/settings/wpan.py @@ -15,14 +15,20 @@ class WpanSettings(NetworkManagerSettingsMixin): metadata={'dbus_name': 'channel', 'dbus_type': 'i'}, default=None, ) + """IEEE 802.15.4 channel. A positive integer or -1, meaning "do not set, use + whatever the device is already set to".""" mac_address: Optional[str] = field( metadata={'dbus_name': 'mac-address', 'dbus_type': 's'}, default=None, ) + """If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) + MAC layer device whose permanent MAC address matches.""" page: Optional[int] = field( metadata={'dbus_name': 'page', 'dbus_type': 'i'}, default=None, ) + """IEEE 802.15.4 channel page. A positive integer or -1, meaning "do not set, + use whatever the device is already set to".""" pan_id: Optional[int] = field( metadata={'dbus_name': 'pan-id', 'dbus_type': 'u'}, default=65535, From 45d1f124081fad66328c1ee0005e9306cba408a5 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Mon, 4 Jul 2022 17:54:55 +0200 Subject: [PATCH 17/80] Fix ConnectionType for "gsm" to match DeviceType.MODEM Apply the same kind of fix like in #36 for ETHERNET where we fixed ConnectionType.ETHERNET to match DeviceType.ETHERNET: Use ConnectionType.MODEM to match DeviceType.MODEM for use with getattr() like shown in #36: `getattr(ConnectionType, "MODEM")`. Like with the rename from .WIRED to .ETHERNET in #36, this rename from .GSM to .MODEM is ok because the Enum ConnectionType is new, and wasn't in a release of this library yet. --- sdbus_async/networkmanager/enums.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdbus_async/networkmanager/enums.py b/sdbus_async/networkmanager/enums.py index 03765f6..391d517 100644 --- a/sdbus_async/networkmanager/enums.py +++ b/sdbus_async/networkmanager/enums.py @@ -507,7 +507,7 @@ class ConnectionType(str, Enum): * CDMA * DUMMY * ETHERNET - * GSM + * MODEM * INFINIBAND * IP_TUNNEL * MACSEC @@ -537,7 +537,7 @@ class ConnectionType(str, Enum): CDMA = "cdma" DUMMY = "dummy" ETHERNET = "802-3-ethernet" - GSM = "gsm" + MODEM = "gsm" INFINIBAND = "infiniband" IP_TUNNEL = "ip-tunnel" MACSEC = "macsec" From f2cea60a290f7aec01f94a12a6c2c2c8b11562d5 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 17 Jul 2022 18:57:14 +0200 Subject: [PATCH 18/80] tools/generate-settings-dataclasses.py: Fix bond.py, generate options.rst --- docs/options.rst | 143 ++++++++++++++++++++ sdbus_async/networkmanager/settings/bond.py | 2 +- tools/generate-settings-dataclasses.py | 42 ++++-- 3 files changed, 173 insertions(+), 14 deletions(-) create mode 100644 docs/options.rst diff --git a/docs/options.rst b/docs/options.rst new file mode 100644 index 0000000..3190cb2 --- /dev/null +++ b/docs/options.rst @@ -0,0 +1,143 @@ +Network Manager settings +======================== + +.. autoclass:: sdbus_async.networkmanager.settings.ConnectionSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.Ipv4Settings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.Ipv6Settings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.AdslSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.BluetoothSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.BondSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.BondPortSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.BridgeSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.BridgePortSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.CdmaSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.DcbSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.EthernetSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.GsmSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.HostnameSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.Ieee8021XSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.InfinibandSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.IpTunnelSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.LowpanSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.MacsecSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.MacvlanSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.MatchSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OlpcMeshSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsBridgeSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsDpdkSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsExternalIdsSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsInterfaceSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsPatchSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.OvsPortSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.PppSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.PppoeSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.ProxySettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.SerialSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.TeamSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.TeamPortSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.TunSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.UserSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.VethSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.VlanSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.VpnSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.VrfSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.VxlanSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WifiP2PSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WimaxSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WireguardSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WirelessSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WirelessSecuritySettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.WpanSettings + :members: diff --git a/sdbus_async/networkmanager/settings/bond.py b/sdbus_async/networkmanager/settings/bond.py index e7a206a..748db0a 100644 --- a/sdbus_async/networkmanager/settings/bond.py +++ b/sdbus_async/networkmanager/settings/bond.py @@ -20,7 +20,7 @@ class BondSettings(NetworkManagerSettingsMixin): name.""" options: Optional[Dict[str, str]] = field( metadata={'dbus_name': 'options', 'dbus_type': 'a{ss}'}, - default={'Mode': 'Balance-Rr'}, + default=field(default_factory = lambda: {'mode': 'balance-rr'}), ) """Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 6c2c0be..5425e23 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -2,6 +2,8 @@ # Based on NetworkManager-1.39.2/tools/generate-docs-nm-settings-docs-merge.py # SPDX-License-Identifier: LGPL-2.1-or-later import collections +import io +import os import textwrap import xml.etree.ElementTree as ElementTree from argparse import ArgumentParser @@ -216,9 +218,23 @@ def find_first_not_none(itr: List[Any]) -> Optional[Any]: return next((i for i in itr if i is not None), None) +# Generate docs/options.rst, see: +# https://github.com/python-sdbus/python-sdbus-networkmanager/pull/39#issuecomment-1186522147 +def open_options_rst() -> io.TextIOWrapper: + options_rst = open("docs/options.rst", "w") + options_rst.write("Network Manager settings\n========================\n") + return options_rst + + +def append_sphinx_autoclass(options_rst: io.TextIOWrapper, classname: str) -> None: + classpath = f"sdbus_async.networkmanager.settings.{classname}" + options_rst.write(f"\n.. autoclass:: {classpath}\n :members:\n") + + # The code quality of this function is poor(Sourcery says 5%), needs refactoring, # also see the rework in tools/generate-settings-dataclasses-jinja.py def main(settings_xml_path: Path) -> None: + options_rst = open_options_rst() gl_input_files = [settings_xml_path] xml_roots = [ElementTree.parse(f).getroot() for f in gl_input_files] @@ -226,24 +242,22 @@ def main(settings_xml_path: Path) -> None: settings_roots = [node_to_dict(root, "setting", "name") for root in xml_roots] - root_node = ElementTree.Element("nm-setting-docs") - # Generate the file header license = "SPDX-License-Identifier: LGPL-2.1-or-later" - script = ("This file was generated by " - "tools/generate-settings-dataclasses.py") + script = "This file was generated by tools/generate-settings-dataclasses.py" header = f"""# {license}\n# {script}, # if possible, please make changes by also updating the script.\n""" i = open("sdbus_async/networkmanager/settings/__init__.py", mode="w") - p = open("sdbus_async/networkmanager/settings/profile.py", mode="r") - profile_py = open("sdbus_async/networkmanager/settings/profile.py").read() + profile_path = "sdbus_async/networkmanager/settings/profile.py" + profile_py = open(profile_path).read() # define start and end markers for generating part of settings/profile.py: start_string = "# start of the generated list of settings classes\n" start_index = profile_py.index(start_string) + len(start_string) end_string = " # end of the generated list of settings classes\n" end_index = profile_py.index(end_string) - p = open("sdbus_async/networkmanager/settings/profile.py", mode="w") + profile_path_new = f"{profile_path}.new" + p = open(profile_path_new, mode="w") # write the file headers i.write(header) @@ -296,7 +310,6 @@ def main(settings_xml_path: Path) -> None: f.write("\n\n") # Generate the settings_class and it's entry in profile.py: - setting_node = ElementTree.SubElement(root_node, "setting") if module != "connection": p.write(f" {module}: Optional[{classname}] = field(\n") p.write(f" metadata={{'dbus_name': '{settingname}',\n") @@ -305,7 +318,7 @@ def main(settings_xml_path: Path) -> None: p.write(" )\n") f.write("@dataclass\n") f.write(f"class {classname}(NetworkManagerSettingsMixin):\n") - setting_node.set("name", settingname) + append_sphinx_autoclass(options_rst, classname) # generate the docstring of the new settings_class desc = node_get_attr(settings, "description") @@ -316,8 +329,6 @@ def main(settings_xml_path: Path) -> None: for property in iter_keys_of_dicts(properties, key_fcn_property_name, f'{settingname}.'): property_name = property[len(settingname)+1:] properties_attrs = [p.get(property_name) for p in properties] - property_node = ElementTree.SubElement(setting_node, "property") - property_node.set("name", property_name) t = node_get_attr(properties_attrs, "type") attribute = property_name.replace('-', '_') for builtin in ["id", "type"]: @@ -371,9 +382,13 @@ def main(settings_xml_path: Path) -> None: f.write(line.replace(":@", ": ") + '\n') default = node_get_attr(properties_attrs, "default") if default in ["{}", "0", "-1"]: - default = "None" + default = None if optional: - f.write(f" default={str(default).title()},\n") + if dbustype == "a{ss}" and default: + default = f"field(default_factory = lambda: {default})" + else: + default = str(default).title() # FALSE -> False + f.write(f" default={default},\n") f.write(" )\n") # Generate docstrings for attributes: Not stored by python, @@ -401,6 +416,7 @@ def main(settings_xml_path: Path) -> None: i.write(f" '{cls}',\n") i.write(")\n") p.write(profile_py[end_index:]) + os.rename(profile_path_new, profile_path) if __name__ == '__main__': From 35983683e4b23b5fb3a6b514fb293e8a7bb25e9f Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 17 Jul 2022 18:59:33 +0200 Subject: [PATCH 19/80] tools/generate-settings-dataclasses.py: format with black -l88 Cleans up source formatting of generating complicated code --- tools/generate-settings-dataclasses.py | 32 +++++++++++--------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 5425e23..80d1159 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -146,6 +146,7 @@ def write(msg: Any) -> None: "connection.uuid", ] + def _property_name_order_idx(name: str) -> int: """Return the sort index for the given connection setting property""" try: @@ -206,9 +207,7 @@ def node_get_attr(nodes: List[Optional[Any]], name: str) -> Any: return None -def node_set_attr( - dst_node: Any, name: str, nodes: List[Optional[Any]] -) -> None: +def node_set_attr(dst_node: Any, name: str, nodes: List[Optional[Any]]) -> None: x = node_get_attr(nodes, name) if x: dst_node.set(name, x) @@ -239,8 +238,7 @@ def main(settings_xml_path: Path) -> None: xml_roots = [ElementTree.parse(f).getroot() for f in gl_input_files] assert all(root.tag == "nm-setting-docs" for root in xml_roots) - settings_roots = [node_to_dict(root, "setting", "name") - for root in xml_roots] + settings_roots = [node_to_dict(root, "setting", "name") for root in xml_roots] # Generate the file header license = "SPDX-License-Identifier: LGPL-2.1-or-later" @@ -265,8 +263,7 @@ def main(settings_xml_path: Path) -> None: classes = [] # generate the connection type settings classes: - for settingname in iter_keys_of_dicts(settings_roots, - key_fcn_setting_name): + for settingname in iter_keys_of_dicts(settings_roots, key_fcn_setting_name): settings = [d.get(settingname) for d in settings_roots] properties = [node_to_dict(s, "property", "name") for s in settings] if properties == [OrderedDict()]: @@ -326,8 +323,10 @@ def main(settings_xml_path: Path) -> None: # Generate the attributes of the settings_class for this profile type: - for property in iter_keys_of_dicts(properties, key_fcn_property_name, f'{settingname}.'): - property_name = property[len(settingname)+1:] + for property in iter_keys_of_dicts( + properties, key_fcn_property_name, f'{settingname}.' + ): + property_name = property[len(settingname) + 1 :] properties_attrs = [p.get(property_name) for p in properties] t = node_get_attr(properties_attrs, "type") attribute = property_name.replace('-', '_') @@ -350,16 +349,12 @@ def main(settings_xml_path: Path) -> None: if dbustype == "aa{sv}": default = node_get_attr(properties_attrs, "default") inner_cls = ( - property_name.title( - ).replace("-", "").replace("data", "Data") + property_name.title().replace("-", "").replace("data", "Data") ) - f.write( - f" {attribute}: Optional[List[{inner_cls}]] = field(\n") - f.write( - f" metadata={{'dbus_name': '{property_name}',\n") + f.write(f" {attribute}: Optional[List[{inner_cls}]] = field(\n") + f.write(f" metadata={{'dbus_name': '{property_name}',\n") f.write(f" 'dbus_type': '{dbustype}',\n") - f.write( - f" 'dbus_inner_class': {inner_cls}}},\n") + f.write(f" 'dbus_inner_class': {inner_cls}}},\n") f.write(f" default={str(default).title()},\n )\n") else: attribute_type = dbus_type_name_map[dbustype] @@ -369,8 +364,7 @@ def main(settings_xml_path: Path) -> None: else: f.write(f" {attribute}: {attribute_type}") f.write(" = field(\n") - meta = (f"'dbus_name': '{property_name}', " - f"'dbus_type':@'{dbustype}'") + meta = f"'dbus_name': '{property_name}', " f"'dbus_type':@'{dbustype}'" line = "metadata={" + meta + "}," wrapper = textwrap.TextWrapper( width=80, From f4c693a772498b7023d2b781febcc7cce9120c38 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 17 Jul 2022 23:31:45 +0300 Subject: [PATCH 20/80] docs: Add options docs to index --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index c709bf2..0f6acef 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ of `NetworkManager `_. examples device_interfaces other_interfaces + options enums exceptions From 6d3c8d8f7210ca41dab86ef2a85290719d943e28 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 17 Jul 2022 22:26:49 +0200 Subject: [PATCH 21/80] docs: generate docs/profile_settings.rst intead of options.rst - Use docs/profile_settings.rst instead of docs/options.rst --- docs/index.rst | 2 +- docs/{options.rst => profile_settings.rst} | 5 +++-- tools/generate-settings-dataclasses.py | 17 +++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) rename docs/{options.rst => profile_settings.rst} (98%) diff --git a/docs/index.rst b/docs/index.rst index 0f6acef..6846ede 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,7 +12,7 @@ of `NetworkManager `_. examples device_interfaces other_interfaces - options + profile_settings enums exceptions diff --git a/docs/options.rst b/docs/profile_settings.rst similarity index 98% rename from docs/options.rst rename to docs/profile_settings.rst index 3190cb2..5e6b3f1 100644 --- a/docs/options.rst +++ b/docs/profile_settings.rst @@ -1,5 +1,6 @@ -Network Manager settings -======================== +Connection Profile Settings Helpers +=================================== + .. autoclass:: sdbus_async.networkmanager.settings.ConnectionSettings :members: diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 80d1159..4454d88 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -219,21 +219,22 @@ def find_first_not_none(itr: List[Any]) -> Optional[Any]: # Generate docs/options.rst, see: # https://github.com/python-sdbus/python-sdbus-networkmanager/pull/39#issuecomment-1186522147 -def open_options_rst() -> io.TextIOWrapper: - options_rst = open("docs/options.rst", "w") - options_rst.write("Network Manager settings\n========================\n") - return options_rst +def open_profile_settings_rst() -> io.TextIOWrapper: + profile_settings_rst = open("docs/profile_settings.rst", "w") + profile_settings_rst.write("Connection Profile Settings Helpers\n") + profile_settings_rst.write("===================================\n\n") + return profile_settings_rst -def append_sphinx_autoclass(options_rst: io.TextIOWrapper, classname: str) -> None: +def append_sphinx_autoclass(profile_settings: io.TextIOWrapper, classname: str) -> None: classpath = f"sdbus_async.networkmanager.settings.{classname}" - options_rst.write(f"\n.. autoclass:: {classpath}\n :members:\n") + profile_settings.write(f"\n.. autoclass:: {classpath}\n :members:\n") # The code quality of this function is poor(Sourcery says 5%), needs refactoring, # also see the rework in tools/generate-settings-dataclasses-jinja.py def main(settings_xml_path: Path) -> None: - options_rst = open_options_rst() + profile_settings_rst = open_profile_settings_rst() gl_input_files = [settings_xml_path] xml_roots = [ElementTree.parse(f).getroot() for f in gl_input_files] @@ -315,7 +316,7 @@ def main(settings_xml_path: Path) -> None: p.write(" )\n") f.write("@dataclass\n") f.write(f"class {classname}(NetworkManagerSettingsMixin):\n") - append_sphinx_autoclass(options_rst, classname) + append_sphinx_autoclass(profile_settings_rst, classname) # generate the docstring of the new settings_class desc = node_get_attr(settings, "description") From 4ce0acaf38d2159e0989a31c820889c422d85c02 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Sun, 17 Jul 2022 22:36:38 +0200 Subject: [PATCH 22/80] settings/match.py: Fix warning from sphinx due to "|" in docstring Update tools/generate-settings-dataclasses.py to escape any '|' in docstrings with '\|', fixes this warning from sphinx: docstring of sdbus_async.networkmanager.settings.MatchSettings.interface_name:1: WARNING: Inline substitution_reference start-string without end-string. --- sdbus_async/networkmanager/settings/match.py | 15 ++++++++------- tools/generate-settings-dataclasses.py | 16 +++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/sdbus_async/networkmanager/settings/match.py b/sdbus_async/networkmanager/settings/match.py index c253129..946eff2 100644 --- a/sdbus_async/networkmanager/settings/match.py +++ b/sdbus_async/networkmanager/settings/match.py @@ -16,20 +16,21 @@ class MatchSettings(NetworkManagerSettingsMixin): default=None, ) """A list of driver names to match. Each element is a shell wildcard pattern. - See NMSettingMatch:interface-name for how special characters '|', '&', '!' and - '\\' are used for optional and mandatory matches and inverting the pattern.""" + See NMSettingMatch:interface-name for how special characters '\|', '&', '!' + and '\\' are used for optional and mandatory matches and inverting the + pattern.""" interface_name: Optional[List[str]] = field( metadata={'dbus_name': 'interface-name', 'dbus_type': 'as'}, default=None, ) """A list of interface names to match. Each element is a shell wildcard - pattern. An element can be prefixed with a pipe symbol (|) or an ampersand + pattern. An element can be prefixed with a pipe symbol (\|) or an ampersand (&). The former means that the element is optional and the latter means that it is mandatory. If there are any optional elements, than the match evaluates to true if at least one of the optional element matches (logical OR). If there are any mandatory elements, then they all must match (logical AND). By default, an element is optional. This means that an element "foo" behaves the - same as "|foo". An element can also be inverted with exclamation mark (!) + same as "\|foo". An element can also be inverted with exclamation mark (!) between the pipe symbol (or the ampersand) and before the pattern. Note that "!foo" is a shortcut for the mandatory match "&!foo". Finally, a backslash can be used at the beginning of the element (after the optional special @@ -46,7 +47,7 @@ class MatchSettings(NetworkManagerSettingsMixin): command line is searched for the word appearing as is, or as left hand side of an assignment. In the latter case, the exact assignment is looked for with right and left hand side matching. Wildcard patterns are not supported. See - NMSettingMatch:interface-name for how special characters '|', '&', '!' and + NMSettingMatch:interface-name for how special characters '\|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the match.""" path: Optional[List[str]] = field( metadata={'dbus_name': 'path', 'dbus_type': 'as'}, @@ -58,8 +59,8 @@ class MatchSettings(NetworkManagerSettingsMixin): specific identifier. For PCI devices the path has the form "pci-$domain:$bus:$device.$function", where each variable is an hexadecimal value; for example "pci-0000:0a:00.0". The path of a device can be obtained - with "udevadm info /sys/class/net/$dev | grep ID_PATH=" or by looking at the + with "udevadm info /sys/class/net/$dev \| grep ID_PATH=" or by looking at the "path" property exported by NetworkManager ("nmcli -f general.path device show $dev"). Each element of the list is a shell wildcard pattern. See - NMSettingMatch:interface-name for how special characters '|', '&', '!' and + NMSettingMatch:interface-name for how special characters '\|', '&', '!' and '\\' are used for optional and mandatory matches and inverting the pattern.""" diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 4454d88..3ccef30 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -10,15 +10,6 @@ from pathlib import Path from typing import Any, Dict, List, Optional, OrderedDict, Tuple - -def dbg(msg: Any) -> None: - print(f"{msg}") - - -def write(msg: Any) -> None: - print(f"{msg}") - - dbus_type_name_map = { "b": "bool", "s": "str", @@ -391,13 +382,16 @@ def main(settings_xml_path: Path) -> None: # developers when they lookup the attribute declaration: generate_descriptions_for_attributes = True if generate_descriptions_for_attributes: - desc = node_get_attr(properties_attrs, "description") + attr_description = node_get_attr(properties_attrs, "description") + # Fix warning from sphinx: WARNING: + # Inline substitution_reference start-string without end-string + attr_docstring = attr_description.replace("|", "\|") wrapper = textwrap.TextWrapper( width=82, initial_indent=" ", subsequent_indent=" ", ) - lines = wrapper.wrap(text=f'"""{desc}"""') + lines = wrapper.wrap(text=f'"""{attr_docstring}"""') if len(lines) == 1: print(lines[0] + '"""') else: From 23e5828194bd0febb06942b0e71ea236e8d1ec74 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 25 Jul 2022 15:34:43 +0300 Subject: [PATCH 23/80] Fixed typo in DHCPv6 docstring --- sdbus_async/networkmanager/interfaces_other.py | 2 +- sdbus_block/networkmanager/interfaces_other.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index b5992ab..8e93866 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -320,7 +320,7 @@ class NetworkManagerDHCP6ConfigInterfaceAsync( @dbus_property_async('a{sv}') def options(self) -> Dict[str, Tuple[str, Any]]: - """Options and configurations returned by DHCPv4 server""" + """Options and configurations returned by DHCPv6 server""" raise NotImplementedError diff --git a/sdbus_block/networkmanager/interfaces_other.py b/sdbus_block/networkmanager/interfaces_other.py index 9ed146a..9089c10 100644 --- a/sdbus_block/networkmanager/interfaces_other.py +++ b/sdbus_block/networkmanager/interfaces_other.py @@ -298,7 +298,7 @@ class NetworkManagerDHCP6ConfigInterface( @dbus_property('a{sv}') def options(self) -> Dict[str, Tuple[str, Any]]: - """Options and configurations returned by DHCPv4 server""" + """Options and configurations returned by DHCPv6 server""" raise NotImplementedError From 187c98cbedf0eed810d498059f3991f485523014 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 1 Aug 2022 21:45:49 +0300 Subject: [PATCH 24/80] Fixed blocking version missing settings module --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 5ce16f6..48100e1 100644 --- a/setup.py +++ b/setup.py @@ -54,6 +54,7 @@ packages=['sdbus_async.networkmanager', 'sdbus_async.networkmanager.settings', 'sdbus_block.networkmanager', + 'sdbus_block.networkmanager.settings', ], package_data={ 'sdbus_async.networkmanager': [ From 5e7def297465901fe893edc99e65074db55ac43c Mon Sep 17 00:00:00 2001 From: igo95862 Date: Wed, 3 Aug 2022 23:48:56 +0300 Subject: [PATCH 25/80] readthedocs: Use sdbus version without autodoc bugs until fixes --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4b5d8d0..2fe1ae7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -sdbus>=0.8rc2 +sdbus==0.10.0 From 6f96c6a195ed0ccf5b9c80fbfe59894969887a32 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 14 Aug 2022 16:12:10 +0300 Subject: [PATCH 26/80] readthedocs: Use most recent sdbus version with autodoc fixes --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2fe1ae7..c64eda8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -sdbus==0.10.0 +sdbus>=0.10.2 From d162905ac86ce951d022446614c255ba87822ac8 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 14 Aug 2022 18:24:22 +0300 Subject: [PATCH 27/80] Add upstream documentation link --- docs/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 6846ede..e7c9bfd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,6 +4,11 @@ Network Manager binds for python-sdbus This package contains python-sdbus for D-Bus interface of `NetworkManager `_. +.. note:: + See `upstream documentation for NetworkManager D-Bus API + `_ + for more detailed documentation. + .. toctree:: :maxdepth: 3 :caption: Contents: From 245f975a4f7f07b00317464502f043d0123b91a2 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 5 Nov 2022 18:50:45 +0300 Subject: [PATCH 28/80] Update jinja2 settings generator to work with latest NM settings Also add `--regex-filter` option --- tools/generate-settings-dataclasses-jinja.py | 68 ++++++++++++++++---- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 9d4dac9..7bcf663 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -1,14 +1,28 @@ #!/usr/bin/env python # SPDX-License-Identifier: LGPL-2.1-or-later + +# Gerating nm-settings-docs-dbus.xml from NetworkManager source code +# 1. meson setup \ +# -Dselinux=false \ +# -Dqt=false \ +# -Dintrospection=true \ +# -Ddocs=true \ +# build +# 2. cd build +# 3. ninja man/nm-settings-docs-dbus.xml from __future__ import annotations from argparse import ArgumentParser from pathlib import Path from xml.etree.ElementTree import parse, Element from typing import List, Optional +from re import compile as regex_compile +from re import Pattern from jinja2 import Environment import builtins import keyword +from textwrap import fill + dbus_to_python_extra_typing_imports = { "as": ("List", ), @@ -43,8 +57,11 @@ 'array of array of uint32': 'aau', 'array of byte array': 'aay', 'array of legacy IPv6 address struct': 'a(ayuay)', + 'array of legacy IPv6 address struct (a(ayuay))': 'a(ayuay)', 'array of legacy IPv6 route struct': 'a(ayuayu)', + 'array of legacy IPv6 route struct (a(ayuayu))': 'a(ayuayu)', 'array of string': 'as', + 'array of strings': 'as', 'array of uint32': 'au', 'array of vardict': 'aa{sv}', "array of 'a{sv}'": 'aa{sv}', # wireguard.peers uses this, fix NM upstream @@ -110,12 +127,24 @@ def __init__(self, name: str, description: str, name_upper: str, self.properties: List[NmSettingPropertyIntrospection] = [] +def extract_and_format_option_description(node: Element) -> str: + paragraphs: list[str] = [] + for para in node.iter('para'): + paragraphs.append(fill(para.text, width=72)) + + return '\n\n'.join(paragraphs) + + def convert_property(node: Element, parent: NmSettingsIntrospection - ) -> NmSettingPropertyIntrospection: - options = node.attrib + ) -> Optional[NmSettingPropertyIntrospection]: + options = node.attrib.copy() + + try: + unconverted_type = options.pop('type') + except KeyError: + return None - unconverted_type = options.pop('type') try: dbus_type = dbus_name_type_map[unconverted_type] except KeyError: @@ -123,6 +152,7 @@ def convert_property(node: Element, options['dbus_type'] = dbus_type options['python_type'] = dbus_to_python_type_map[dbus_type] + options['description'] = extract_and_format_option_description(node) return NmSettingPropertyIntrospection(**options, parent=parent) @@ -131,9 +161,11 @@ def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: settings_introspection: List[NmSettingsIntrospection] = [] for setting_node in root: setting = NmSettingsIntrospection(**setting_node.attrib) - setting.properties.extend( - (convert_property(x, setting) for x in setting_node) - ) + + for x in setting_node: + new_property = convert_property(x, setting) + if new_property is not None: + setting.properties.append(new_property) settings_introspection.append(setting) @@ -167,13 +199,22 @@ class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): settings_template = jinja_env.from_string(setttngs_template_str) -def main(settings_xml_path: Path) -> None: +def main( + settings_xml_path: Path, + regex_filter: Optional[Pattern] = None, + ) -> None: tree = parse(settings_xml_path) introspection = generate_introspection(tree.getroot()) settings_dir = Path('sdbus_async/networkmanager/settings/') for setting in introspection: - setting_py_file = settings_dir / (setting.name_upper.lower() + '.py') + setting_sake_name = setting.name_upper.lower() + + if regex_filter is not None: + if not regex_filter.match(setting_sake_name): + continue + + setting_py_file = settings_dir / (setting_sake_name + '.py') with open(setting_py_file, mode='w') as f: f.write(settings_template.render(setting=setting)) @@ -181,10 +222,15 @@ def main(settings_xml_path: Path) -> None: if __name__ == '__main__': arg_parser = ArgumentParser() arg_parser.add_argument( - 'nm_settings_xml', + 'settings_xml_path', type=Path, - default=Path('man/nm-settings-docs-dbus.xml'), + default=Path('./nm-settings-docs-dbus.xml'), ) + arg_parser.add_argument( + '--regex-filter', + type=regex_compile, + ) + args = arg_parser.parse_args() - main(args.nm_settings_xml) + main(**vars(args)) From dda655fc9c8e78a0e495cedaff4da927489bffe4 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 6 Nov 2022 16:26:21 +0300 Subject: [PATCH 29/80] Added support for imports of extra datatypes to jinja2 generator --- tools/generate-settings-dataclasses-jinja.py | 45 ++++++++++++++------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 7bcf663..f071b69 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -11,18 +11,19 @@ # 2. cd build # 3. ninja man/nm-settings-docs-dbus.xml from __future__ import annotations -from argparse import ArgumentParser -from pathlib import Path -from xml.etree.ElementTree import parse, Element -from typing import List, Optional -from re import compile as regex_compile -from re import Pattern -from jinja2 import Environment import builtins import keyword +from argparse import ArgumentParser +from functools import cached_property +from pathlib import Path +from re import Pattern +from re import compile as regex_compile from textwrap import fill +from typing import List, Optional +from xml.etree.ElementTree import Element, parse +from jinja2 import Environment dbus_to_python_extra_typing_imports = { "as": ("List", ), @@ -81,6 +82,14 @@ 'id': 'pretty_id', } +datatypes_extra_imports: dict[str, list[str]] = { + 'wireguard': ['WireguardPeers'], + 'bridge': ['Vlans'], + 'team': ['LinkWatchers'], + 'ip4_config': ['AddressData', 'RouteData'], + 'ip6_config': ['AddressData', 'RouteData'], +} + def must_replace_name(name: str) -> bool: return (keyword.iskeyword(name) @@ -126,6 +135,17 @@ def __init__(self, name: str, description: str, name_upper: str, self.properties: List[NmSettingPropertyIntrospection] = [] + @cached_property + def snake_name(self) -> str: + return self.name_upper.lower() + + @cached_property + def datatypes_imports(self) -> list[str]: + try: + return datatypes_extra_imports[self.snake_name] + except KeyError: + return [] + def extract_and_format_option_description(node: Element) -> str: paragraphs: list[str] = [] @@ -179,7 +199,9 @@ def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: from dataclasses import dataclass, field from typing import {{ setting.typing_imports|sort|join(', ') }} from .base import NetworkManagerSettingsMixin - +{% if setting.datatypes_imports -%} +from .datatypes import {{ setting.datatypes_imports|sort|join(', ') }} +{% endif %} @dataclass class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): @@ -206,15 +228,14 @@ def main( tree = parse(settings_xml_path) introspection = generate_introspection(tree.getroot()) - settings_dir = Path('sdbus_async/networkmanager/settings/') + settings_dir = Path('./sdbus_async/networkmanager/settings/') for setting in introspection: - setting_sake_name = setting.name_upper.lower() if regex_filter is not None: - if not regex_filter.match(setting_sake_name): + if not regex_filter.match(setting.snake_name): continue - setting_py_file = settings_dir / (setting_sake_name + '.py') + setting_py_file = settings_dir / (setting.snake_name + '.py') with open(setting_py_file, mode='w') as f: f.write(settings_template.render(setting=setting)) From 114f42ebee50ecd43c752ed7ea1cf0985308d31a Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 6 Nov 2022 19:40:25 +0300 Subject: [PATCH 30/80] Added datatypes generation to jinja2 generator and new datatypes Qdiscs and Tfilters datatypes are missing documentation to recreate their fields --- .../networkmanager/settings/datatypes.py | 105 ++++++++++++++++++ tools/generate-settings-dataclasses-jinja.py | 46 +++++--- 2 files changed, 137 insertions(+), 14 deletions(-) diff --git a/sdbus_async/networkmanager/settings/datatypes.py b/sdbus_async/networkmanager/settings/datatypes.py index dc9a721..452ea93 100644 --- a/sdbus_async/networkmanager/settings/datatypes.py +++ b/sdbus_async/networkmanager/settings/datatypes.py @@ -121,3 +121,108 @@ class WireguardPeers(NetworkManagerSettingsMixin): allowed_ips: List[str] = field( metadata={'dbus_name': 'allowed-ips', 'dbus_type': 'as'}, ) + + +@dataclass +class RoutingRules(NetworkManagerSettingsMixin): + action: Optional[int] = field( + metadata={'dbus_name': 'action', 'dbus_type': 'y'}, + ) + dport_end: Optional[int] = field( + metadata={'dbus_name': 'dport-end', 'dbus_type': 'q'}, + ) + dport_start: Optional[int] = field( + metadata={'dbus_name': 'dport-start', 'dbus_type': 'q'}, + ) + family: Optional[int] = field( + metadata={'dbus_name': 'family', 'dbus_type': 'i'}, + ) + from_prefix: Optional[str] = field( + metadata={'dbus_name': 'from', 'dbus_type': 's'}, + ) + from_len: Optional[int] = field( + metadata={'dbus_name': 'from-len', 'dbus_type': 'y'}, + ) + fwmark: Optional[int] = field( + metadata={'dbus_name': 'fwmark', 'dbus_type': 'u'}, + ) + fwmask: Optional[int] = field( + metadata={'dbus_name': 'fwmask', 'dbus_type': 'u'}, + ) + iifname: Optional[str] = field( + metadata={'dbus_name': 'iifname', 'dbus_type': 's'}, + ) + invert: Optional[bool] = field( + metadata={'dbus_name': 'invert', 'dbus_type': 'b'}, + ) + ipproto: Optional[str] = field( + metadata={'dbus_name': 'ipproto', 'dbus_type': 's'}, + ) + oifname: Optional[str] = field( + metadata={'dbus_name': 'oifname', 'dbus_type': 's'}, + ) + priority: Optional[int] = field( + metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, + ) + sport_end: Optional[int] = field( + metadata={'dbus_name': 'sport-end', 'dbus_type': 'q'}, + ) + sport_start: Optional[int] = field( + metadata={'dbus_name': 'sport-start', 'dbus_type': 'q'}, + ) + supress_prefixlength: Optional[int] = field( + metadata={'dbus_name': 'supress-prefixlength', 'dbus_type': 'i'}, + ) + table: Optional[int] = field( + metadata={'dbus_name': 'table', 'dbus_type': 'u'}, + ) + to: Optional[str] = field( + metadata={'dbus_name': 'to', 'dbus_type': 's'}, + ) + tos: Optional[int] = field( + metadata={'dbus_name': 'tos', 'dbus_type': 'y'}, + ) + to_len: Optional[int] = field( + metadata={'dbus_name': 'to-len', 'dbus_type': 'y'}, + ) + range_end: Optional[int] = field( + metadata={'dbus_name': 'range-end', 'dbus_type': 'u'}, + ) + range_start: Optional[int] = field( + metadata={'dbus_name': 'range-start', 'dbus_type': 'u'}, + ) + + +@dataclass +class Vfs(NetworkManagerSettingsMixin): + index: str = field( + metadata={'dbus_name': 'index', 'dbus_type': 's'}, + ) + mac: Optional[str] = field( + metadata={'dbus_name': 'mac', 'dbus_type': 's'}, + ) + spoof_check: Optional[str] = field( + metadata={'dbus_name': 'spoof-check', 'dbus_type': 's'}, + ) + trust: Optional[str] = field( + metadata={'dbus_name': 'trust', 'dbus_type': 's'}, + ) + min_tx_rate: Optional[str] = field( + metadata={'dbus_name': 'min-tx-rate', 'dbus_type': 's'}, + ) + max_tx_rate: Optional[str] = field( + metadata={'dbus_name': 'max-tx-rate', 'dbus_type': 's'}, + ) + vlans: Optional[str] = field( + metadata={'dbus_name': 'vlans', 'dbus_type': 's'}, + ) + + +@dataclass +class Qdiscs(NetworkManagerSettingsMixin): + ... + + +@dataclass +class Tfilters(NetworkManagerSettingsMixin): + ... diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index f071b69..9dbbe6d 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -82,12 +82,17 @@ 'id': 'pretty_id', } -datatypes_extra_imports: dict[str, list[str]] = { - 'wireguard': ['WireguardPeers'], - 'bridge': ['Vlans'], - 'team': ['LinkWatchers'], - 'ip4_config': ['AddressData', 'RouteData'], - 'ip6_config': ['AddressData', 'RouteData'], + +array_of_vardicts_python_classes: dict[str, str] = { + 'peers': 'WireguardPeers', + 'vlans': 'Vlans', + 'address-data': 'AddressData', + 'route-data': 'RouteData', + 'routing-rules': 'RoutingRules', + 'vfs': 'Vfs', + 'qdiscs': 'Qdiscs', + 'tfilters': 'Tfilters', + 'link-watchers': 'LinkWatchers', } @@ -102,7 +107,6 @@ def __init__(self, name: str, description: str, name_upper: str, dbus_type: str, - python_type: str, parent: NmSettingsIntrospection, default: Optional[str] = None, ) -> None: @@ -111,7 +115,6 @@ def __init__(self, name: str, self.name_upper = name_upper self.python_name = name_upper.lower() self.dbus_type = dbus_type - self.python_type = python_type self.default = default if must_replace_name(self.python_name): @@ -122,6 +125,17 @@ def __init__(self, name: str, if extra_typing is not None: parent.typing_imports.update(extra_typing) + @cached_property + def python_type(self) -> str: + if self.dbus_type == 'aa{sv}': + return f"List[{array_of_vardicts_python_classes[self.name]}]" + + return dbus_to_python_type_map[self.dbus_type] + + @cached_property + def python_inner_class(self) -> Optional[str]: + return array_of_vardicts_python_classes.get(self.name) + class NmSettingsIntrospection: def __init__(self, name: str, description: str, name_upper: str, @@ -141,10 +155,12 @@ def snake_name(self) -> str: @cached_property def datatypes_imports(self) -> list[str]: - try: - return datatypes_extra_imports[self.snake_name] - except KeyError: - return [] + datatypes_found: list[str] = [] + for x in self.properties: + if (datatype := x.python_inner_class) is not None: + datatypes_found.append(datatype) + + return datatypes_found def extract_and_format_option_description(node: Element) -> str: @@ -171,7 +187,6 @@ def convert_property(node: Element, dbus_type = dbus_name_type_map[unconverted_type.split('(')[1][:-1]] options['dbus_type'] = dbus_type - options['python_type'] = dbus_to_python_type_map[dbus_type] options['description'] = extract_and_format_option_description(node) return NmSettingPropertyIntrospection(**options, parent=parent) @@ -211,6 +226,9 @@ class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): metadata={ 'dbus_name': '{{ property.name }}', 'dbus_type': '{{ property.dbus_type }}', +{%- if property.python_inner_class %} + 'dbus_inner_class': {{ property.python_inner_class }}, +{%- endif %} }, default=None, ){% endfor %} @@ -224,7 +242,7 @@ class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): def main( settings_xml_path: Path, regex_filter: Optional[Pattern] = None, - ) -> None: +) -> None: tree = parse(settings_xml_path) introspection = generate_introspection(tree.getroot()) From 22ed5116fe1620ca3252e6343b8cde3b4533f99b Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 6 Nov 2022 20:24:16 +0300 Subject: [PATCH 31/80] Improved jinja2 generator handling of settings starting with digits --- tools/generate-settings-dataclasses-jinja.py | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 9dbbe6d..0c40be1 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -16,6 +16,7 @@ import keyword from argparse import ArgumentParser from functools import cached_property +from itertools import dropwhile from pathlib import Path from re import Pattern from re import compile as regex_compile @@ -95,6 +96,10 @@ 'link-watchers': 'LinkWatchers', } +setting_name_replacement: dict[str, str] = { + 'x': 'eapol', +} + def must_replace_name(name: str) -> bool: return (keyword.iskeyword(name) @@ -143,15 +148,32 @@ def __init__(self, name: str, description: str, name_upper: str, self.name = name self.description = description self.name_upper = name_upper - self.python_class_name = name.capitalize() + 'Settings' self.typing_imports = {'Optional'} self.properties: List[NmSettingPropertyIntrospection] = [] + @cached_property + def python_class_name(self) -> str: + + camel_case = ''.join( + map(str.title, self.snake_name.split('_')) + ) + + return camel_case + 'Settings' + @cached_property def snake_name(self) -> str: - return self.name_upper.lower() + underscore_name = self.name.replace('-', '_') + + no_first_digits_name = ''.join( + dropwhile( + lambda s: not str.isalpha(s), underscore_name)) + + return setting_name_replacement.get( + no_first_digits_name, + no_first_digits_name, + ) @cached_property def datatypes_imports(self) -> list[str]: From 91c376efcb855d163b328fb58c0bbe52bd519aeb Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 6 Nov 2022 21:22:01 +0300 Subject: [PATCH 32/80] Add description generation for jinja2 generator --- tools/generate-settings-dataclasses-jinja.py | 55 +++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 0c40be1..e1b9ac4 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -167,8 +167,8 @@ def snake_name(self) -> str: underscore_name = self.name.replace('-', '_') no_first_digits_name = ''.join( - dropwhile( - lambda s: not str.isalpha(s), underscore_name)) + dropwhile( + lambda s: not str.isalpha(s), underscore_name)) return setting_name_replacement.get( no_first_digits_name, @@ -185,12 +185,54 @@ def datatypes_imports(self) -> list[str]: return datatypes_found +def extract_docbook_paragraphs(docbook_node: Element) -> List[str]: + return [x.text for x in docbook_node] + + +def extract_description_paragraph(description_node: Element) -> str: + return description_node.text + + def extract_and_format_option_description(node: Element) -> str: + formatted_paragraphs: list[str] = [] paragraphs: list[str] = [] - for para in node.iter('para'): - paragraphs.append(fill(para.text, width=72)) + description = 'Not documented' + + for doc_node in node: + if doc_node.tag == 'description-docbook': + paragraphs.extend(extract_docbook_paragraphs(doc_node)) + elif doc_node.tag == 'description': + description = extract_description_paragraph(doc_node) + elif doc_node.tag == 'deprecated': + ... + elif doc_node.tag == 'deprecated-docbook': + ... + else: + raise ValueError("Unknown doc node", doc_node.tag) + + if paragraphs: + first_para = paragraphs.pop(0) + else: + first_para = description + + formatted_paragraphs.append( + fill( + first_para, + width=72, + subsequent_indent=' ', + ) + ) + for para in paragraphs: + formatted_paragraphs.append( + fill( + para, + width=72, + initial_indent=' ', + subsequent_indent=' ', + ) + ) - return '\n\n'.join(paragraphs) + return '\n\n'.join(formatted_paragraphs) def convert_property(node: Element, @@ -253,7 +295,8 @@ class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): {%- endif %} }, default=None, - ){% endfor %} + ) + ""\"{{property.description}}""\"{% endfor %} """ From ab292dc898345be2db00e38a606b97bd0ed54579 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 6 Nov 2022 21:53:51 +0300 Subject: [PATCH 33/80] Use template directory for jinja2 templates --- tools/generate-settings-dataclasses-jinja.py | 40 +++----------------- tools/jinja_templates/setting.py.jinja2 | 27 +++++++++++++ 2 files changed, 33 insertions(+), 34 deletions(-) create mode 100644 tools/jinja_templates/setting.py.jinja2 diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index e1b9ac4..849934c 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -24,7 +24,7 @@ from typing import List, Optional from xml.etree.ElementTree import Element, parse -from jinja2 import Environment +from jinja2 import Environment, FileSystemLoader dbus_to_python_extra_typing_imports = { "as": ("List", ), @@ -271,43 +271,15 @@ def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: return settings_introspection -setttngs_template_str = """# SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses-jinja.py, -# if possible, please make changes by also updating the script. -from __future__ import annotations -from dataclasses import dataclass, field -from typing import {{ setting.typing_imports|sort|join(', ') }} -from .base import NetworkManagerSettingsMixin -{% if setting.datatypes_imports -%} -from .datatypes import {{ setting.datatypes_imports|sort|join(', ') }} -{% endif %} - -@dataclass -class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): - \"""{{ setting.description }}\""" -{% for property in setting.properties %} - {{ property.python_name }}: Optional[{{ property.python_type }}] = field( - metadata={ - 'dbus_name': '{{ property.name }}', - 'dbus_type': '{{ property.dbus_type }}', -{%- if property.python_inner_class %} - 'dbus_inner_class': {{ property.python_inner_class }}, -{%- endif %} - }, - default=None, - ) - ""\"{{property.description}}""\"{% endfor %} - -""" - -jinja_env = Environment() -settings_template = jinja_env.from_string(setttngs_template_str) - - def main( settings_xml_path: Path, regex_filter: Optional[Pattern] = None, ) -> None: + jinja_env = Environment( + loader=FileSystemLoader(Path('./tools/jinja_templates/')), + ) + settings_template = jinja_env.get_template('setting.py.jinja2') + tree = parse(settings_xml_path) introspection = generate_introspection(tree.getroot()) diff --git a/tools/jinja_templates/setting.py.jinja2 b/tools/jinja_templates/setting.py.jinja2 new file mode 100644 index 0000000..3e3abb0 --- /dev/null +++ b/tools/jinja_templates/setting.py.jinja2 @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import {{ setting.typing_imports|sort|join(', ') }} +from .base import NetworkManagerSettingsMixin +{% if setting.datatypes_imports -%} +from .datatypes import {{ setting.datatypes_imports|sort|join(', ') }} +{% endif %} + +@dataclass +class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): + """{{ setting.description }}""" +{% for property in setting.properties %} + {{ property.python_name }}: Optional[{{ property.python_type }}] = field( + metadata={ + 'dbus_name': '{{ property.name }}', + 'dbus_type': '{{ property.dbus_type }}', +{%- if property.python_inner_class %} + 'dbus_inner_class': {{ property.python_inner_class }}, +{%- endif %} + }, + default=None, + ) + """{{property.description}}"""{% endfor %} + From 90b0b8959315a3d6a499c02c2ceb490c37b961e1 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 15:00:34 +0300 Subject: [PATCH 34/80] Renamed generator regex filter option to `--settings-regex-filter` --- tools/generate-settings-dataclasses-jinja.py | 18 ++- tools/jinja_templates/profile.py.jinja2 | 152 +++++++++++++++++++ 2 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 tools/jinja_templates/profile.py.jinja2 diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 849934c..5cd3c72 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -273,7 +273,7 @@ def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: def main( settings_xml_path: Path, - regex_filter: Optional[Pattern] = None, + settings_regex_filter: Optional[Pattern] = None, ) -> None: jinja_env = Environment( loader=FileSystemLoader(Path('./tools/jinja_templates/')), @@ -281,19 +281,25 @@ def main( settings_template = jinja_env.get_template('setting.py.jinja2') tree = parse(settings_xml_path) - introspection = generate_introspection(tree.getroot()) + all_settings = generate_introspection(tree.getroot()) settings_dir = Path('./sdbus_async/networkmanager/settings/') - for setting in introspection: + for setting in all_settings: - if regex_filter is not None: - if not regex_filter.match(setting.snake_name): + if settings_regex_filter is not None: + if not settings_regex_filter.match(setting.snake_name): continue setting_py_file = settings_dir / (setting.snake_name + '.py') with open(setting_py_file, mode='w') as f: f.write(settings_template.render(setting=setting)) + profile_template = jinja_env.get_template('profile.py.jinja2') + with open(settings_dir / 'profile.py', mode='w') as f: + f.write(profile_template.render( + all_settings=sorted(all_settings, key=lambda x: x.snake_name)) + ) + if __name__ == '__main__': arg_parser = ArgumentParser() @@ -303,7 +309,7 @@ def main( default=Path('./nm-settings-docs-dbus.xml'), ) arg_parser.add_argument( - '--regex-filter', + '--settings-regex-filter', type=regex_compile, ) diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 new file mode 100644 index 0000000..0666798 --- /dev/null +++ b/tools/jinja_templates/profile.py.jinja2 @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations + +from dataclasses import dataclass, field, fields +from typing import Any, Dict, Optional + +from .base import NetworkManagerSettingsMixin +{% for setting in all_settings -%} +from .{{ setting.snake_name }} import {{ setting.python_class_name }} +{% endfor -%} +from ..types import NetworkManagerConnectionProperties, SettingsDict + + +@dataclass +class ConnectionProfile: + """ + Connection profiles + ------------------- + + NetworkManager is based on a concept of connection profiles, most often + referred to just as "connections". Connection profiles provide a network + configuration. When NetworkManager activates a connection profile on a + network device, the configuration will be applied and an active network + connection will be established. Users are free to create as many + connection profiles as they see fit. Thus they are flexible in having + various network configurations for different networking needs: + https://networkmanager.pages.freedesktop.org/NetworkManager/NetworkManager/nm-settings-dbus.html + + Connection profiles are handled by NetworkManager via a settings service + and are exported on D-Bus (/org/freedesktop/NetworkManager/Settings/) + + Definition of a connection profile: + A specific, encapsulated, independent group of settings describing + all the configuration required to connect to a specific network. + + It is referred to by a unique identifier called the UUID. + A connection profile is tied to a one specific device type, + but not necessarily a specific hardware device. + + A connection profile is composed of one or more Settings objects. + + Settings objects + ---------------- + + A group of related key/value pairs describing a specific piece + of a Connection (profile). Keys are also referred to as properties. + """ + # The settings object "connection" is special: It must always be present + # because it contains the UUID and the connection type which are required: + connection: ConnectionSettings = field( + metadata={'dbus_name': 'connection', + 'settings_class': ConnectionSettings}, + ) + # The list of the remaining settings classes was generated by + # tools/generate-settings-dataclasses-jinja.py which generates the + # settings classes themselfes as well. + # If possible, please make changes by also updating the script. + + # start of the generated list of settings classes +{%- for setting in all_settings %} + {{ setting.snake_name }}: Optional[{{ setting.python_class_name }}] = field( + metadata={'dbus_name': '{{ setting.name }}', + 'settings_class': {{ setting.python_class_name }}}, + default=None, + ) +{%- endfor %} + # end of the generated list of settings classes + + def to_dbus(self) -> NetworkManagerConnectionProperties: + new_dict: NetworkManagerConnectionProperties = {} + + for x in fields(self): + value = getattr(self, x.name) + if value is None: + continue + + new_dict[x.metadata['dbus_name']] = value.to_dbus() + + return new_dict + + def to_settings_dict(self, defaults: bool = False) -> SettingsDict: + """Return a simple dictionary using the same key names like the dbus + dict from to_dbus(), but without the dbus signatures returned by it. + + Contrary to dataclasses.asdict(), it provides the orignal dbus keys, + e.g. with numerical prefixes like "802-11-", dashes, and "id"/"type". + + The key names provided are exactly as documented in these tables: + https://networkmanager.dev/docs/api/latest/nm-settings-dbus.html + + param defaults: Whether properies with default values are returned. + """ + new_dict = {} + for x in fields(self): + settings_class = getattr(self, x.name) + if settings_class: + settingsdomain_dict = settings_class.to_settings_dict(defaults) + if settingsdomain_dict != {}: + new_dict[x.metadata['dbus_name']] = settingsdomain_dict + return new_dict + + @property + def dbus_name_to_settings_class(self) -> Dict[str, str]: + return {f.metadata['dbus_name']: f.name + for f in fields(self)} + + @classmethod + def from_dbus(cls, dbus_dict: NetworkManagerConnectionProperties + ) -> ConnectionProfile: + for domain in ("ipv4", "ipv6"): + group = dbus_dict.get(domain, None) + if group: + for key in ("addresses", "routes"): + group.pop(key, None) + try: + unvarianted_options: Dict[str, Any] = { + SETTING_DBUS_NAME_TO_NAME[k]: SETTING_TO_CLASS[k].from_dbus(v) + for k, v in dbus_dict.items()} + except KeyError as e: + print(dbus_dict) + raise e + return cls(**unvarianted_options) + + @classmethod + def from_settings_dict( + cls, settings_dict: SettingsDict + ) -> ConnectionProfile: + """Return a ConnectionProfile created from a simple settings dict + A simple settings dict uses the same keys as from_dbus() and to_dbus() + but without the dbus variable signatures used by NetworkManader.py + + This means a simple settings dict does not use the underscore in keys + like the attributes of this class have to use and use "id" and "type". + """ + unvarianted_options: Dict[str, Any] = { + SETTING_DBUS_NAME_TO_NAME[k]: SETTING_TO_CLASS[k].from_dict(v) + for k, v in settings_dict.items()} + return cls(**unvarianted_options) + + +SETTING_DBUS_NAME_TO_NAME: Dict[str, str] = { + f.metadata['dbus_name']: f.name + for f in fields(ConnectionProfile) +} + +SETTING_TO_CLASS: Dict[str, NetworkManagerSettingsMixin] = { + f.metadata['dbus_name']: f.metadata['settings_class'] + for f in fields(ConnectionProfile) +} + From 6130e930bc65eb0a74bb9c501fcde56571461e68 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 16:16:27 +0300 Subject: [PATCH 35/80] Added __init_.py and profile.py generation to jinja2 generator --- tools/generate-settings-dataclasses-jinja.py | 13 +++++++++---- tools/jinja_templates/__init__.py.jinja2 | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 tools/jinja_templates/__init__.py.jinja2 diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 5cd3c72..e5a4452 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -281,7 +281,10 @@ def main( settings_template = jinja_env.get_template('setting.py.jinja2') tree = parse(settings_xml_path) - all_settings = generate_introspection(tree.getroot()) + all_settings = sorted( + generate_introspection(tree.getroot()), + key=lambda x: x.snake_name, + ) settings_dir = Path('./sdbus_async/networkmanager/settings/') for setting in all_settings: @@ -296,9 +299,11 @@ def main( profile_template = jinja_env.get_template('profile.py.jinja2') with open(settings_dir / 'profile.py', mode='w') as f: - f.write(profile_template.render( - all_settings=sorted(all_settings, key=lambda x: x.snake_name)) - ) + f.write(profile_template.render(all_settings=all_settings)) + + init_template = jinja_env.get_template('__init__.py.jinja2') + with open(settings_dir / '__init__.py', mode='w') as f: + f.write(init_template.render(all_settings=all_settings)) if __name__ == '__main__': diff --git a/tools/jinja_templates/__init__.py.jinja2 b/tools/jinja_templates/__init__.py.jinja2 new file mode 100644 index 0000000..da4b9fe --- /dev/null +++ b/tools/jinja_templates/__init__.py.jinja2 @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations + +{% for setting in all_settings -%} +from .{{ setting.snake_name }} import {{ setting.python_class_name }} +{% endfor %} + +__all__ = ( +{%- for setting in all_settings %} + '{{ setting.python_class_name }}', +{%- endfor %} +) + From 79aec5889945cb9e4d4e1c0bf068ff923834df16 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 16:51:29 +0300 Subject: [PATCH 36/80] Skip legacy types in generated settings --- tools/generate-settings-dataclasses-jinja.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index e5a4452..1c8d595 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -50,9 +50,6 @@ "aa{sv}": "List[Tuple[str, Any]]", "aau": "List[List[int]]", "aay": "List[bytes]", - # Legacy types: - "a(ayuay)": "array of legacy IPv6 address struct", - "a(ayuayu)": "array of legacy IPv6 route struct", } dbus_name_type_map = { @@ -253,7 +250,14 @@ def convert_property(node: Element, options['dbus_type'] = dbus_type options['description'] = extract_and_format_option_description(node) - return NmSettingPropertyIntrospection(**options, parent=parent) + new_property = NmSettingPropertyIntrospection(**options, parent=parent) + + try: + new_property.python_type + except KeyError: + return None + + return new_property def generate_introspection(root: Element) -> List[NmSettingsIntrospection]: From 5c444aeff5f31e9cb771cfa74edaa207ee5a02e0 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 16:59:43 +0300 Subject: [PATCH 37/80] Regenerate all settings with new jinja based generator --- sdbus_async/networkmanager/__init__.py | 50 +- .../networkmanager/settings/__init__.py | 31 +- sdbus_async/networkmanager/settings/adsl.py | 44 +- .../networkmanager/settings/bluetooth.py | 17 +- sdbus_async/networkmanager/settings/bond.py | 22 +- .../networkmanager/settings/bond_port.py | 11 +- sdbus_async/networkmanager/settings/bridge.py | 299 ++++--- .../networkmanager/settings/bridge_port.py | 48 +- sdbus_async/networkmanager/settings/cdma.py | 40 +- .../networkmanager/settings/connection.py | 565 +++++++++----- sdbus_async/networkmanager/settings/dcb.py | 171 ++-- sdbus_async/networkmanager/settings/dummy.py | 13 + sdbus_async/networkmanager/settings/eapol.py | 595 ++++++++++++++ .../networkmanager/settings/ethernet.py | 308 +++++--- .../networkmanager/settings/ethtool.py | 13 + .../networkmanager/settings/generic.py | 13 + sdbus_async/networkmanager/settings/gsm.py | 138 ++-- .../networkmanager/settings/hostname.py | 86 +- .../networkmanager/settings/ieee802_1x.py | 414 ---------- .../networkmanager/settings/infiniband.py | 45 +- .../networkmanager/settings/ip_tunnel.py | 101 ++- sdbus_async/networkmanager/settings/ipv4.py | 680 ++++++++++------ sdbus_async/networkmanager/settings/ipv6.py | 733 ++++++++++++------ sdbus_async/networkmanager/settings/lowpan.py | 7 +- sdbus_async/networkmanager/settings/macsec.py | 68 +- .../networkmanager/settings/macvlan.py | 34 +- sdbus_async/networkmanager/settings/match.py | 108 ++- .../networkmanager/settings/olpc_mesh.py | 27 +- .../networkmanager/settings/ovs_bridge.py | 38 +- .../networkmanager/settings/ovs_dpdk.py | 17 +- .../settings/ovs_external_ids.py | 8 +- .../networkmanager/settings/ovs_interface.py | 19 +- .../networkmanager/settings/ovs_patch.py | 7 +- .../networkmanager/settings/ovs_port.py | 41 +- sdbus_async/networkmanager/settings/ppp.py | 171 ++-- sdbus_async/networkmanager/settings/pppoe.py | 43 +- .../networkmanager/settings/profile.py | 78 +- sdbus_async/networkmanager/settings/proxy.py | 28 +- sdbus_async/networkmanager/settings/serial.py | 48 +- sdbus_async/networkmanager/settings/sriov.py | 79 ++ sdbus_async/networkmanager/settings/tc.py | 47 ++ sdbus_async/networkmanager/settings/team.py | 136 +++- .../networkmanager/settings/team_port.py | 65 +- sdbus_async/networkmanager/settings/tun.py | 56 +- sdbus_async/networkmanager/settings/user.py | 15 +- sdbus_async/networkmanager/settings/veth.py | 11 +- sdbus_async/networkmanager/settings/vlan.py | 73 +- sdbus_async/networkmanager/settings/vpn.py | 74 +- sdbus_async/networkmanager/settings/vrf.py | 8 +- sdbus_async/networkmanager/settings/vxlan.py | 117 ++- .../networkmanager/settings/wifi_p2p.py | 39 +- sdbus_async/networkmanager/settings/wimax.py | 20 +- .../networkmanager/settings/wireguard.py | 130 ++-- .../networkmanager/settings/wireless.py | 340 +++++--- .../settings/wireless_security.py | 247 ++++-- sdbus_async/networkmanager/settings/wpan.py | 45 +- 56 files changed, 4447 insertions(+), 2234 deletions(-) create mode 100644 sdbus_async/networkmanager/settings/dummy.py create mode 100644 sdbus_async/networkmanager/settings/eapol.py create mode 100644 sdbus_async/networkmanager/settings/ethtool.py create mode 100644 sdbus_async/networkmanager/settings/generic.py delete mode 100644 sdbus_async/networkmanager/settings/ieee802_1x.py create mode 100644 sdbus_async/networkmanager/settings/sriov.py create mode 100644 sdbus_async/networkmanager/settings/tc.py diff --git a/sdbus_async/networkmanager/__init__.py b/sdbus_async/networkmanager/__init__.py index 6435006..426e4cd 100644 --- a/sdbus_async/networkmanager/__init__.py +++ b/sdbus_async/networkmanager/__init__.py @@ -194,55 +194,9 @@ NetworkManagerSettings, WiFiP2PPeer, ) -from .settings.adsl import AdslSettings -from .settings.bluetooth import BluetoothSettings -from .settings.bond import BondSettings -from .settings.bond_port import BondPortSettings -from .settings.bridge import BridgeSettings -from .settings.bridge_port import BridgePortSettings -from .settings.cdma import CdmaSettings -from .settings.connection import ConnectionSettings -from .settings.datatypes import AddressData, RouteData, WireguardPeers -from .settings.dcb import DcbSettings -from .settings.ethernet import EthernetSettings -from .settings.gsm import GsmSettings -from .settings.hostname import HostnameSettings -from .settings.ieee802_1x import Ieee8021XSettings -from .settings.infiniband import InfinibandSettings -from .settings.ip_tunnel import IpTunnelSettings -from .settings.ipv4 import Ipv4Settings -from .settings.ipv6 import Ipv6Settings -from .settings.lowpan import LowpanSettings -from .settings.macsec import MacsecSettings -from .settings.macvlan import MacvlanSettings -from .settings.match import MatchSettings -from .settings.olpc_mesh import OlpcMeshSettings -from .settings.ovs_bridge import OvsBridgeSettings -from .settings.ovs_dpdk import OvsDpdkSettings -from .settings.ovs_external_ids import OvsExternalIdsSettings -from .settings.ovs_interface import OvsInterfaceSettings -from .settings.ovs_patch import OvsPatchSettings -from .settings.ovs_port import OvsPortSettings -from .settings.ppp import PppSettings -from .settings.pppoe import PppoeSettings + from .settings.profile import ConnectionProfile -from .settings.proxy import ProxySettings -from .settings.serial import SerialSettings -from .settings.team import TeamSettings -from .settings.team_port import TeamPortSettings -from .settings.tun import TunSettings -from .settings.user import UserSettings -from .settings.veth import VethSettings -from .settings.vlan import VlanSettings -from .settings.vpn import VpnSettings -from .settings.vrf import VrfSettings -from .settings.vxlan import VxlanSettings -from .settings.wifi_p2p import WifiP2PSettings -from .settings.wimax import WimaxSettings -from .settings.wireguard import WireguardSettings -from .settings.wireless import WirelessSettings -from .settings.wireless_security import WirelessSecuritySettings -from .settings.wpan import WpanSettings + from .types import ( NetworkManagerConnectionProperties, NetworkManagerSetting, diff --git a/sdbus_async/networkmanager/settings/__init__.py b/sdbus_async/networkmanager/settings/__init__.py index 67eeb4d..d771e6f 100644 --- a/sdbus_async/networkmanager/settings/__init__.py +++ b/sdbus_async/networkmanager/settings/__init__.py @@ -1,9 +1,8 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. -from .connection import ConnectionSettings -from .ipv4 import Ipv4Settings -from .ipv6 import Ipv6Settings +from __future__ import annotations + from .adsl import AdslSettings from .bluetooth import BluetoothSettings from .bond import BondSettings @@ -11,13 +10,19 @@ from .bridge import BridgeSettings from .bridge_port import BridgePortSettings from .cdma import CdmaSettings +from .connection import ConnectionSettings from .dcb import DcbSettings +from .dummy import DummySettings +from .eapol import EapolSettings from .ethernet import EthernetSettings +from .ethtool import EthtoolSettings +from .generic import GenericSettings from .gsm import GsmSettings from .hostname import HostnameSettings -from .ieee802_1x import Ieee8021XSettings from .infiniband import InfinibandSettings from .ip_tunnel import IpTunnelSettings +from .ipv4 import Ipv4Settings +from .ipv6 import Ipv6Settings from .lowpan import LowpanSettings from .macsec import MacsecSettings from .macvlan import MacvlanSettings @@ -33,6 +38,8 @@ from .pppoe import PppoeSettings from .proxy import ProxySettings from .serial import SerialSettings +from .sriov import SriovSettings +from .tc import TcSettings from .team import TeamSettings from .team_port import TeamPortSettings from .tun import TunSettings @@ -49,10 +56,8 @@ from .wireless_security import WirelessSecuritySettings from .wpan import WpanSettings + __all__ = ( - 'ConnectionSettings', - 'Ipv4Settings', - 'Ipv6Settings', 'AdslSettings', 'BluetoothSettings', 'BondSettings', @@ -60,13 +65,19 @@ 'BridgeSettings', 'BridgePortSettings', 'CdmaSettings', + 'ConnectionSettings', 'DcbSettings', + 'DummySettings', + 'EapolSettings', 'EthernetSettings', + 'EthtoolSettings', + 'GenericSettings', 'GsmSettings', 'HostnameSettings', - 'Ieee8021XSettings', 'InfinibandSettings', 'IpTunnelSettings', + 'Ipv4Settings', + 'Ipv6Settings', 'LowpanSettings', 'MacsecSettings', 'MacvlanSettings', @@ -82,6 +93,8 @@ 'PppoeSettings', 'ProxySettings', 'SerialSettings', + 'SriovSettings', + 'TcSettings', 'TeamSettings', 'TeamPortSettings', 'TunSettings', diff --git a/sdbus_async/networkmanager/settings/adsl.py b/sdbus_async/networkmanager/settings/adsl.py index d4b4c11..7c38341 100644 --- a/sdbus_async/networkmanager/settings/adsl.py +++ b/sdbus_async/networkmanager/settings/adsl.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,30 +12,58 @@ class AdslSettings(NetworkManagerSettingsMixin): """ADSL Settings""" encapsulation: Optional[str] = field( - metadata={'dbus_name': 'encapsulation', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'encapsulation', + 'dbus_type': 's', + }, default=None, ) + """Encapsulation of ADSL connection. Can be "vcmux" or "llc".""" password: Optional[str] = field( - metadata={'dbus_name': 'password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'password', + 'dbus_type': 's', + }, default=None, ) + """Password used to authenticate with the ADSL service.""" password_flags: Optional[int] = field( - metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'password-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "password" property.""" protocol: Optional[str] = field( - metadata={'dbus_name': 'protocol', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'protocol', + 'dbus_type': 's', + }, default=None, ) + """ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm".""" username: Optional[str] = field( - metadata={'dbus_name': 'username', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'username', + 'dbus_type': 's', + }, default=None, ) + """Username used to authenticate with the ADSL service.""" vci: Optional[int] = field( - metadata={'dbus_name': 'vci', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'vci', + 'dbus_type': 'u', + }, default=None, ) + """VCI of ADSL connection""" vpi: Optional[int] = field( - metadata={'dbus_name': 'vpi', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'vpi', + 'dbus_type': 'u', + }, default=None, ) + """VPI of ADSL connection""" diff --git a/sdbus_async/networkmanager/settings/bluetooth.py b/sdbus_async/networkmanager/settings/bluetooth.py index d63671d..f5bb59d 100644 --- a/sdbus_async/networkmanager/settings/bluetooth.py +++ b/sdbus_async/networkmanager/settings/bluetooth.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,12 +12,19 @@ class BluetoothSettings(NetworkManagerSettingsMixin): """Bluetooth Settings""" bdaddr: Optional[bytes] = field( - metadata={'dbus_name': 'bdaddr', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'bdaddr', + 'dbus_type': 'ay', + }, default=None, ) + """The Bluetooth address of the device.""" bluetooth_type: Optional[str] = field( - metadata={'dbus_name': 'type', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'type', + 'dbus_type': 's', + }, default=None, ) - """Either "dun" for Dial-Up Networking connections or "panu" for Personal Area - Networking connections to devices supporting the NAP profile.""" + """Either "dun" for Dial-Up Networking connections or "panu" for Personal + Area Networking connections to devices supporting the NAP profile.""" diff --git a/sdbus_async/networkmanager/settings/bond.py b/sdbus_async/networkmanager/settings/bond.py index 748db0a..1eca116 100644 --- a/sdbus_async/networkmanager/settings/bond.py +++ b/sdbus_async/networkmanager/settings/bond.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,16 +12,22 @@ class BondSettings(NetworkManagerSettingsMixin): """Bonding Settings""" interface_name: Optional[str] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 's', + }, default=None, ) """Deprecated in favor of connection.interface-name, but can be used for - backward-compatibility with older daemons, to set the bond's interface - name.""" + backward-compatibility with older daemons, to set the bond's + interface name.""" options: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 'options', 'dbus_type': 'a{ss}'}, - default=field(default_factory = lambda: {'mode': 'balance-rr'}), + metadata={ + 'dbus_name': 'options', + 'dbus_type': 'a{ss}', + }, + default=None, ) """Dictionary of key/value pairs of bonding options. Both keys and values - must be strings. Option names must contain only alphanumeric characters (ie, - [a-zA-Z0-9]).""" + must be strings. Option names must contain only alphanumeric + characters (ie, [a-zA-Z0-9]).""" diff --git a/sdbus_async/networkmanager/settings/bond_port.py b/sdbus_async/networkmanager/settings/bond_port.py index 1c022ea..80d1806 100644 --- a/sdbus_async/networkmanager/settings/bond_port.py +++ b/sdbus_async/networkmanager/settings/bond_port.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,8 +12,11 @@ class BondPortSettings(NetworkManagerSettingsMixin): """Bond Port Settings""" queue_id: Optional[int] = field( - metadata={'dbus_name': 'queue-id', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'queue-id', + 'dbus_type': 'u', + }, default=None, ) - """The queue ID of this bond port. The maximum value of queue ID is the number - of TX queues currently active in device.""" + """The queue ID of this bond port. The maximum value of queue ID is the + number of TX queues currently active in device.""" diff --git a/sdbus_async/networkmanager/settings/bridge.py b/sdbus_async/networkmanager/settings/bridge.py index 638088d..9cc8836 100644 --- a/sdbus_async/networkmanager/settings/bridge.py +++ b/sdbus_async/networkmanager/settings/bridge.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import Vlans @@ -13,173 +13,280 @@ class BridgeSettings(NetworkManagerSettingsMixin): """Bridging Settings""" ageing_time: Optional[int] = field( - metadata={'dbus_name': 'ageing-time', 'dbus_type': 'u'}, - default=300, + metadata={ + 'dbus_name': 'ageing-time', + 'dbus_type': 'u', + }, + default=None, ) + """The Ethernet MAC address aging time, in seconds.""" forward_delay: Optional[int] = field( - metadata={'dbus_name': 'forward-delay', 'dbus_type': 'u'}, - default=15, + metadata={ + 'dbus_name': 'forward-delay', + 'dbus_type': 'u', + }, + default=None, ) + """The Spanning Tree Protocol (STP) forwarding delay, in seconds.""" group_address: Optional[bytes] = field( - metadata={'dbus_name': 'group-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'group-address', + 'dbus_type': 'ay', + }, default=None, ) - """If specified, The MAC address of the multicast group this bridge uses for - STP. The address must be a link-local address in standard Ethernet MAC address - format, ie an address of the form 01:80:C2:00:00:0X, with X in [0, 4..F]. If - not specified the default value is 01:80:C2:00:00:00.""" + """If specified, The MAC address of the multicast group this bridge uses + for STP. + + The address must be a link-local address in standard Ethernet MAC + address format, ie an address of the form 01:80:C2:00:00:0X, with X + in [0, 4..F]. If not specified the default value is + 01:80:C2:00:00:00.""" group_forward_mask: Optional[int] = field( - metadata={'dbus_name': 'group-forward-mask', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'group-forward-mask', + 'dbus_type': 'u', + }, default=None, ) - """A mask of group addresses to forward. Usually, group addresses in the range - from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded according to - standards. This property is a mask of 16 bits, each corresponding to a group - address in that range that must be forwarded. The mask can't have bits 0, 1 or - 2 set because they are used for STP, MAC pause frames and LACP.""" + """A mask of group addresses to forward. Usually, group addresses in the + range from 01:80:C2:00:00:00 to 01:80:C2:00:00:0F are not forwarded + according to standards. This property is a mask of 16 bits, each + corresponding to a group address in that range that must be + forwarded. The mask can't have bits 0, 1 or 2 set because they are + used for STP, MAC pause frames and LACP.""" hello_time: Optional[int] = field( - metadata={'dbus_name': 'hello-time', 'dbus_type': 'u'}, - default=2, + metadata={ + 'dbus_name': 'hello-time', + 'dbus_type': 'u', + }, + default=None, ) + """The Spanning Tree Protocol (STP) hello time, in seconds.""" interface_name: Optional[str] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 's', + }, default=None, ) """Deprecated in favor of connection.interface-name, but can be used for - backward-compatibility with older daemons, to set the bridge's interface - name.""" + backward-compatibility with older daemons, to set the bridge's + interface name.""" mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 'ay', + }, default=None, ) - """If specified, the MAC address of bridge. When creating a new bridge, this - MAC address will be set. If this field is left unspecified, the - "ethernet.cloned-mac-address" is referred instead to generate the initial MAC - address. Note that setting "ethernet.cloned-mac-address" anyway overwrites the - MAC address of the bridge later while activating the bridge. Hence, this - property is deprecated. Deprecated: 1""" + """If specified, the MAC address of bridge. When creating a new bridge, + this MAC address will be set. + + If this field is left unspecified, the "ethernet.cloned-mac-address" + is referred instead to generate the initial MAC address. Note that + setting "ethernet.cloned-mac-address" anyway overwrites the MAC + address of the bridge later while activating the bridge.""" max_age: Optional[int] = field( - metadata={'dbus_name': 'max-age', 'dbus_type': 'u'}, - default=20, + metadata={ + 'dbus_name': 'max-age', + 'dbus_type': 'u', + }, + default=None, ) + """The Spanning Tree Protocol (STP) maximum message age, in seconds.""" multicast_hash_max: Optional[int] = field( - metadata={'dbus_name': 'multicast-hash-max', 'dbus_type': 'u'}, - default=4096, + metadata={ + 'dbus_name': 'multicast-hash-max', + 'dbus_type': 'u', + }, + default=None, ) + """Set maximum size of multicast hash table (value must be a power of 2).""" multicast_last_member_count: Optional[int] = field( - metadata={'dbus_name': 'multicast-last-member-count', 'dbus_type': 'u'}, - default=2, + metadata={ + 'dbus_name': 'multicast-last-member-count', + 'dbus_type': 'u', + }, + default=None, ) - """Set the number of queries the bridge will send before stopping forwarding a - multicast group after a "leave" message has been received.""" + """Set the number of queries the bridge will send before stopping + forwarding a multicast group after a "leave" message has been + received.""" multicast_last_member_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-last-member-interval', - 'dbus_type': 't'}, - default=100, + metadata={ + 'dbus_name': 'multicast-last-member-interval', + 'dbus_type': 't', + }, + default=None, ) - """Set interval (in deciseconds) between queries to find remaining members of - a group, after a "leave" message is received.""" + """Set interval (in deciseconds) between queries to find remaining members + of a group, after a "leave" message is received.""" multicast_membership_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-membership-interval', - 'dbus_type': 't'}, - default=26000, + metadata={ + 'dbus_name': 'multicast-membership-interval', + 'dbus_type': 't', + }, + default=None, ) - """Set delay (in deciseconds) after which the bridge will leave a group, if no - membership reports for this group are received.""" + """Set delay (in deciseconds) after which the bridge will leave a group, if + no membership reports for this group are received.""" multicast_querier: Optional[bool] = field( - metadata={'dbus_name': 'multicast-querier', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'multicast-querier', + 'dbus_type': 'b', + }, + default=None, ) """Enable or disable sending of multicast queries by the bridge. If not specified the option is disabled.""" multicast_querier_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-querier-interval', 'dbus_type': 't'}, - default=25500, + metadata={ + 'dbus_name': 'multicast-querier-interval', + 'dbus_type': 't', + }, + default=None, ) """If no queries are seen after this delay (in deciseconds) has passed, the bridge will start to send its own queries.""" multicast_query_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-query-interval', 'dbus_type': 't'}, - default=12500, + metadata={ + 'dbus_name': 'multicast-query-interval', + 'dbus_type': 't', + }, + default=None, ) - """Interval (in deciseconds) between queries sent by the bridge after the end - of the startup phase.""" + """Interval (in deciseconds) between queries sent by the bridge after the + end of the startup phase.""" multicast_query_response_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-query-response-interval', - 'dbus_type': 't'}, - default=1000, + metadata={ + 'dbus_name': 'multicast-query-response-interval', + 'dbus_type': 't', + }, + default=None, ) - """Set the Max Response Time/Max Response Delay (in deciseconds) for IGMP/MLD - queries sent by the bridge.""" + """Set the Max Response Time/Max Response Delay (in deciseconds) for + IGMP/MLD queries sent by the bridge.""" multicast_query_use_ifaddr: Optional[bool] = field( - metadata={'dbus_name': 'multicast-query-use-ifaddr', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'multicast-query-use-ifaddr', + 'dbus_type': 'b', + }, + default=None, ) """If enabled the bridge's own IP address is used as the source address for IGMP queries otherwise the default of 0.0.0.0 is used.""" multicast_router: Optional[str] = field( - metadata={'dbus_name': 'multicast-router', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'multicast-router', + 'dbus_type': 's', + }, default=None, ) - """Sets bridge's multicast router. Multicast-snooping must be enabled for this - option to work. Supported values are: 'auto', 'disabled', 'enabled' to which - kernel assigns the numbers 1, 0, and 2, respectively. If not specified the + """Sets bridge's multicast router. Multicast-snooping must be enabled for + this option to work. + + Supported values are: 'auto', 'disabled', 'enabled' to which kernel + assigns the numbers 1, 0, and 2, respectively. If not specified the default value is 'auto' (1).""" multicast_snooping: Optional[bool] = field( - metadata={'dbus_name': 'multicast-snooping', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'multicast-snooping', + 'dbus_type': 'b', + }, + default=None, ) """Controls whether IGMP snooping is enabled for this bridge. Note that if - snooping was automatically disabled due to hash collisions, the system may - refuse to enable the feature until the collisions are resolved.""" + snooping was automatically disabled due to hash collisions, the + system may refuse to enable the feature until the collisions are + resolved.""" multicast_startup_query_count: Optional[int] = field( - metadata={'dbus_name': 'multicast-startup-query-count', - 'dbus_type': 'u'}, - default=2, + metadata={ + 'dbus_name': 'multicast-startup-query-count', + 'dbus_type': 'u', + }, + default=None, ) + """Set the number of IGMP queries to send during startup phase.""" multicast_startup_query_interval: Optional[int] = field( - metadata={'dbus_name': 'multicast-startup-query-interval', - 'dbus_type': 't'}, - default=3125, + metadata={ + 'dbus_name': 'multicast-startup-query-interval', + 'dbus_type': 't', + }, + default=None, ) """Sets the time (in deciseconds) between queries sent out at startup to determine membership information.""" priority: Optional[int] = field( - metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, - default=32768, + metadata={ + 'dbus_name': 'priority', + 'dbus_type': 'u', + }, + default=None, ) """Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower - values are "better"; the lowest priority bridge will be elected the root - bridge.""" + values are "better"; the lowest priority bridge will be elected the + root bridge.""" stp: Optional[bool] = field( - metadata={'dbus_name': 'stp', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'stp', + 'dbus_type': 'b', + }, + default=None, ) """Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.""" vlan_default_pvid: Optional[int] = field( - metadata={'dbus_name': 'vlan-default-pvid', 'dbus_type': 'u'}, - default=1, + metadata={ + 'dbus_name': 'vlan-default-pvid', + 'dbus_type': 'u', + }, + default=None, ) - """The default PVID for the ports of the bridge, that is the VLAN id assigned - to incoming untagged frames.""" + """The default PVID for the ports of the bridge, that is the VLAN id + assigned to incoming untagged frames.""" vlan_filtering: Optional[bool] = field( - metadata={'dbus_name': 'vlan-filtering', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'vlan-filtering', + 'dbus_type': 'b', + }, + default=None, ) + """Control whether VLAN filtering is enabled on the bridge.""" vlan_protocol: Optional[str] = field( - metadata={'dbus_name': 'vlan-protocol', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'vlan-protocol', + 'dbus_type': 's', + }, default=None, ) - """If specified, the protocol used for VLAN filtering. Supported values are: - '802.1Q', '802.1ad'. If not specified the default value is '802.1Q'.""" + """If specified, the protocol used for VLAN filtering. + + Supported values are: '802.1Q', '802.1ad'. If not specified the + default value is '802.1Q'.""" vlan_stats_enabled: Optional[bool] = field( - metadata={'dbus_name': 'vlan-stats-enabled', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'vlan-stats-enabled', + 'dbus_type': 'b', + }, + default=None, ) + """Controls whether per-VLAN stats accounting is enabled.""" vlans: Optional[List[Vlans]] = field( - metadata={'dbus_name': 'vlans', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': Vlans}, + metadata={ + 'dbus_name': 'vlans', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': Vlans, + }, default=None, ) + """Array of bridge VLAN objects. In addition to the VLANs specified here, + the bridge will also have the default-pvid VLAN configured by the + bridge.vlan-default-pvid property. + + In nmcli the VLAN list can be specified with the following syntax: + + $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... + + where $vid is either a single id between 1 and 4094 or a range, + represented as a couple of ids separated by a dash.""" diff --git a/sdbus_async/networkmanager/settings/bridge_port.py b/sdbus_async/networkmanager/settings/bridge_port.py index a549378..1708ec1 100644 --- a/sdbus_async/networkmanager/settings/bridge_port.py +++ b/sdbus_async/networkmanager/settings/bridge_port.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import Vlans @@ -13,24 +13,46 @@ class BridgePortSettings(NetworkManagerSettingsMixin): """Bridge Port Settings""" hairpin_mode: Optional[bool] = field( - metadata={'dbus_name': 'hairpin-mode', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'hairpin-mode', + 'dbus_type': 'b', + }, + default=None, ) - """Enables or disables "hairpin mode" for the port, which allows frames to be - sent back out through the port the frame was received on.""" + """Enables or disables "hairpin mode" for the port, which allows frames to + be sent back out through the port the frame was received on.""" path_cost: Optional[int] = field( - metadata={'dbus_name': 'path-cost', 'dbus_type': 'u'}, - default=100, + metadata={ + 'dbus_name': 'path-cost', + 'dbus_type': 'u', + }, + default=None, ) """The Spanning Tree Protocol (STP) port cost for destinations via this port.""" priority: Optional[int] = field( - metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, - default=32, + metadata={ + 'dbus_name': 'priority', + 'dbus_type': 'u', + }, + default=None, ) + """The Spanning Tree Protocol (STP) priority of this bridge port.""" vlans: Optional[List[Vlans]] = field( - metadata={'dbus_name': 'vlans', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': Vlans}, + metadata={ + 'dbus_name': 'vlans', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': Vlans, + }, default=None, ) + """Array of bridge VLAN objects. In addition to the VLANs specified here, + the port will also have the default-pvid VLAN configured on the + bridge by the bridge.vlan-default-pvid property. + + In nmcli the VLAN list can be specified with the following syntax: + + $vid [pvid] [untagged] [, $vid [pvid] [untagged]]... + + where $vid is either a single id between 1 and 4094 or a range, + represented as a couple of ids separated by a dash.""" diff --git a/sdbus_async/networkmanager/settings/cdma.py b/sdbus_async/networkmanager/settings/cdma.py index ab518f4..40fcc67 100644 --- a/sdbus_async/networkmanager/settings/cdma.py +++ b/sdbus_async/networkmanager/settings/cdma.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,33 +12,49 @@ class CdmaSettings(NetworkManagerSettingsMixin): """CDMA-based Mobile Broadband Settings""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.""" number: Optional[str] = field( - metadata={'dbus_name': 'number', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'number', + 'dbus_type': 's', + }, default=None, ) """The number to dial to establish the connection to the CDMA-based mobile - broadband network, if any. If not specified, the default number (#777) is - used when required.""" + broadband network, if any. If not specified, the default number + (#777) is used when required.""" password: Optional[str] = field( - metadata={'dbus_name': 'password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'password', + 'dbus_type': 's', + }, default=None, ) """The password used to authenticate with the network, if required. Many - providers do not require a password, or accept any password. But if a - password is required, it is specified here.""" + providers do not require a password, or accept any password. But if + a password is required, it is specified here.""" password_flags: Optional[int] = field( - metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'password-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "password" property.""" username: Optional[str] = field( - metadata={'dbus_name': 'username', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'username', + 'dbus_type': 's', + }, default=None, ) """The username used to authenticate with the network, if required. Many - providers do not require a username, or accept any username. But if a - username is required, it is specified here.""" + providers do not require a username, or accept any username. But if + a username is required, it is specified here.""" diff --git a/sdbus_async/networkmanager/settings/connection.py b/sdbus_async/networkmanager/settings/connection.py index 38ed3a8..47416bf 100644 --- a/sdbus_async/networkmanager/settings/connection.py +++ b/sdbus_async/networkmanager/settings/connection.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -11,260 +11,469 @@ class ConnectionSettings(NetworkManagerSettingsMixin): """General Connection Profile Settings""" - connection_id: str = field( - metadata={'dbus_name': 'id', 'dbus_type': 's'}, - ) - """A human readable unique identifier for the connection, like "Work Wi-Fi" or - "T-Mobile 3G".""" - connection_type: str = field( - metadata={'dbus_name': 'type', 'dbus_type': 's'}, - ) - """Base type of the connection. For hardware-dependent connections, should - contain the setting name of the hardware-type specific setting (ie, - "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non- - hardware dependent connections like VPN or otherwise, should contain the - setting name of that setting type (ie, "vpn" or "bridge", etc).""" - uuid: str = field( - metadata={'dbus_name': 'uuid', 'dbus_type': 's'}, - ) - """A universally unique identifier for the connection, for example generated - with libuuid. It should be assigned when the connection is created, and never - changed as long as the connection still applies to the same network. For - example, it should not be changed when the "id" property or NMSettingIP4Config - changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband - network provider, or "type" property changes. The UUID must be in the format - "2815492f-7e56-435e-b2e9-246bd7cdc664" (ie, contains only hexadecimal - characters and "-").""" auth_retries: Optional[int] = field( - metadata={'dbus_name': 'auth-retries', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'auth-retries', + 'dbus_type': 'i', + }, default=None, ) """The number of retries for the authentication. Zero means to try - indefinitely; -1 means to use a global default. If the global default is not - set, the authentication retries for 3 times before failing the connection. + indefinitely; -1 means to use a global default. If the global + default is not set, the authentication retries for 3 times before + failing the connection. + Currently, this only applies to 802-1x authentication.""" autoconnect: Optional[bool] = field( - metadata={'dbus_name': 'autoconnect', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'autoconnect', + 'dbus_type': 'b', + }, + default=None, ) """Whether or not the connection should be automatically connected by - NetworkManager when the resources for the connection are available. TRUE to - automatically activate the connection, FALSE to require manual intervention to - activate the connection. Autoconnect happens when the circumstances are - suitable. That means for example that the device is currently managed and not - active. Autoconnect thus never replaces or competes with an already active - profile. Note that autoconnect is not implemented for VPN profiles. See - "secondaries" as an alternative to automatically connect VPN profiles.""" + NetworkManager when the resources for the connection are available. + TRUE to automatically activate the connection, FALSE to require + manual intervention to activate the connection. + + Autoconnect happens when the circumstances are suitable. That means + for example that the device is currently managed and not active. + Autoconnect thus never replaces or competes with an already active + profile. + + Note that autoconnect is not implemented for VPN profiles. See + "secondaries" as an alternative to automatically connect VPN + profiles. + + If multiple profiles are ready to autoconnect on the same device, + the one with the better "connection.autoconnect-priority" is chosen. + If the priorities are equal, then the most recently connected + profile is activated. If the profiles were not connected earlier or + their "connection.timestamp" is identical, the choice is undefined. + + Depending on "connection.multi-connect", a profile can (auto)connect + only once at a time or multiple times.""" autoconnect_priority: Optional[int] = field( - metadata={'dbus_name': 'autoconnect-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'autoconnect-priority', + 'dbus_type': 'i', + }, default=None, ) - """The autoconnect priority in range -999 to 999. If the connection is set to - autoconnect, connections with higher priority will be preferred. The higher - number means higher priority. Defaults to 0. Note that this property only - matters if there are more than one candidate profile to select for - autoconnect. In case of equal priority, the profile used most recently is - chosen.""" + """The autoconnect priority in range -999 to 999. If the connection is set + to autoconnect, connections with higher priority will be preferred. + The higher number means higher priority. Defaults to 0. Note that + this property only matters if there are more than one candidate + profile to select for autoconnect. In case of equal priority, the + profile used most recently is chosen.""" autoconnect_retries: Optional[int] = field( - metadata={'dbus_name': 'autoconnect-retries', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'autoconnect-retries', + 'dbus_type': 'i', + }, default=None, ) - """The number of times a connection should be tried when autoactivating before - giving up. Zero means forever, -1 means the global default (4 times if not - overridden). Setting this to 1 means to try activation only once before - blocking autoconnect. Note that after a timeout, NetworkManager will try to - autoconnect again.""" + """The number of times a connection should be tried when autoactivating + before giving up. Zero means forever, -1 means the global default (4 + times if not overridden). Setting this to 1 means to try activation + only once before blocking autoconnect. Note that after a timeout, + NetworkManager will try to autoconnect again.""" autoconnect_slaves: Optional[int] = field( - metadata={'dbus_name': 'autoconnect-slaves', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'autoconnect-slaves', + 'dbus_type': 'i', + }, default=None, ) - """Whether or not slaves of this connection should be automatically brought up - when NetworkManager activates this connection. This only has a real effect for - master connections. The properties "autoconnect", "autoconnect-priority" and - "autoconnect-retries" are unrelated to this setting. The permitted values are: - 0: leave slave connections untouched, 1: activate all the slave connections - with this connection, -1: default. If -1 (default) is set, global - connection.autoconnect-slaves is read to determine the real value. If it is - default as well, this fallbacks to 0.""" + """Whether or not slaves of this connection should be automatically brought + up when NetworkManager activates this connection. This only has a + real effect for master connections. The properties "autoconnect", + "autoconnect-priority" and "autoconnect-retries" are unrelated to + this setting. The permitted values are: 0: leave slave connections + untouched, 1: activate all the slave connections with this + connection, -1: default. If -1 (default) is set, global + connection.autoconnect-slaves is read to determine the real value. + If it is default as well, this fallbacks to 0.""" dns_over_tls: Optional[int] = field( - metadata={'dbus_name': 'dns-over-tls', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dns-over-tls', + 'dbus_type': 'i', + }, default=None, ) - """Whether DNSOverTls (dns-over-tls) is enabled for the connection. DNSOverTls - is a technology which uses TLS to encrypt dns traffic. The permitted values - are: "yes" (2) use DNSOverTls and disabled fallback, "opportunistic" (1) use - DNSOverTls but allow fallback to unencrypted resolution, "no" (0) don't ever - use DNSOverTls. If unspecified "default" depends on the plugin used. Systemd- - resolved uses global setting. This feature requires a plugin which supports - DNSOverTls. Otherwise, the setting has no effect. One such plugin is dns- - systemd-resolved.""" + """Whether DNSOverTls (dns-over-tls) is enabled for the connection. + DNSOverTls is a technology which uses TLS to encrypt dns traffic. + + The permitted values are: "yes" (2) use DNSOverTls and disabled + fallback, "opportunistic" (1) use DNSOverTls but allow fallback to + unencrypted resolution, "no" (0) don't ever use DNSOverTls. If + unspecified "default" depends on the plugin used. Systemd-resolved + uses global setting. + + This feature requires a plugin which supports DNSOverTls. Otherwise, + the setting has no effect. One such plugin is dns-systemd-resolved.""" gateway_ping_timeout: Optional[int] = field( - metadata={'dbus_name': 'gateway-ping-timeout', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'gateway-ping-timeout', + 'dbus_type': 'u', + }, default=None, ) """If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping.""" + connection_id: Optional[str] = field( + metadata={ + 'dbus_name': 'id', + 'dbus_type': 's', + }, + default=None, + ) + """A human readable unique identifier for the connection, like "Work Wi-Fi" + or "T-Mobile 3G".""" interface_name: Optional[str] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 's', + }, default=None, ) - """The name of the network interface this connection is bound to. If not set, - then the connection can be attached to any interface of the appropriate type - (subject to restrictions imposed by other settings). For software devices this - specifies the name of the created device. For connection types where interface - names cannot easily be made persistent (e.g. mobile broadband or USB - Ethernet), this property should not be used. Setting this property restricts - the interfaces a connection can be used with, and if interface names change or - are reordered the connection may be applied to the wrong interface.""" + """The name of the network interface this connection is bound to. If not + set, then the connection can be attached to any interface of the + appropriate type (subject to restrictions imposed by other + settings). + + For software devices this specifies the name of the created device. + + For connection types where interface names cannot easily be made + persistent (e.g. mobile broadband or USB Ethernet), this property + should not be used. Setting this property restricts the interfaces a + connection can be used with, and if interface names change or are + reordered the connection may be applied to the wrong interface.""" lldp: Optional[int] = field( - metadata={'dbus_name': 'lldp', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'lldp', + 'dbus_type': 'i', + }, default=None, ) + """Whether LLDP is enabled for the connection.""" llmnr: Optional[int] = field( - metadata={'dbus_name': 'llmnr', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'llmnr', + 'dbus_type': 'i', + }, default=None, ) """Whether Link-Local Multicast Name Resolution (LLMNR) is enabled for the - connection. LLMNR is a protocol based on the Domain Name System (DNS) packet - format that allows both IPv4 and IPv6 hosts to perform name resolution for - hosts on the same local link. The permitted values are: "yes" (2) register - hostname and resolving for the connection, "no" (0) disable LLMNR for the - interface, "resolve" (1) do not register hostname but allow resolving of LLMNR - host names If unspecified, "default" ultimately depends on the DNS plugin - (which for systemd-resolved currently means "yes"). This feature requires a - plugin which supports LLMNR. Otherwise, the setting has no effect. One such - plugin is dns-systemd-resolved.""" + connection. LLMNR is a protocol based on the Domain Name System + (DNS) packet format that allows both IPv4 and IPv6 hosts to perform + name resolution for hosts on the same local link. + + The permitted values are: "yes" (2) register hostname and resolving + for the connection, "no" (0) disable LLMNR for the interface, + "resolve" (1) do not register hostname but allow resolving of LLMNR + host names If unspecified, "default" ultimately depends on the DNS + plugin (which for systemd-resolved currently means "yes"). + + This feature requires a plugin which supports LLMNR. Otherwise, the + setting has no effect. One such plugin is dns-systemd-resolved.""" master: Optional[str] = field( - metadata={'dbus_name': 'master', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'master', + 'dbus_type': 's', + }, default=None, ) + """Interface name of the master device or UUID of the master connection.""" mdns: Optional[int] = field( - metadata={'dbus_name': 'mdns', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'mdns', + 'dbus_type': 'i', + }, default=None, ) - """Whether mDNS is enabled for the connection. The permitted values are: "yes" - (2) register hostname and resolving for the connection, "no" (0) disable mDNS - for the interface, "resolve" (1) do not register hostname but allow resolving - of mDNS host names and "default" (-1) to allow lookup of a global default in - NetworkManager.conf. If unspecified, "default" ultimately depends on the DNS - plugin (which for systemd-resolved currently means "no"). This feature - requires a plugin which supports mDNS. Otherwise, the setting has no effect. - One such plugin is dns-systemd-resolved.""" + """Whether mDNS is enabled for the connection. + + The permitted values are: "yes" (2) register hostname and resolving + for the connection, "no" (0) disable mDNS for the interface, + "resolve" (1) do not register hostname but allow resolving of mDNS + host names and "default" (-1) to allow lookup of a global default in + NetworkManager.conf. If unspecified, "default" ultimately depends on + the DNS plugin (which for systemd-resolved currently means "no"). + + This feature requires a plugin which supports mDNS. Otherwise, the + setting has no effect. One such plugin is dns-systemd-resolved.""" metered: Optional[int] = field( - metadata={'dbus_name': 'metered', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'metered', + 'dbus_type': 'i', + }, default=None, ) - """Whether the connection is metered. When updating this property on a - currently activated connection, the change takes effect immediately.""" + """Whether the connection is metered. + + When updating this property on a currently activated connection, the + change takes effect immediately.""" + mptcp_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'mptcp-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Whether to configure MPTCP endpoints and the address flags. If MPTCP is + enabled in NetworkManager, it will configure the addresses of the + interface as MPTCP endpoints. Note that IPv4 loopback addresses + (127.0.0.0/8), IPv4 link local addresses (169.254.0.0/16), the IPv6 + loopback address (::1), IPv6 link local addresses (fe80::/10), IPv6 + unique local addresses (ULA, fc00::/7) and IPv6 privacy extension + addresses (rfc3041, ipv6.ip6-privacy) will be excluded from being + configured as endpoints. + + If "disabled" (0x1), MPTCP handling for the interface is disabled + and no endpoints are registered. + + The "enabled" (0x2) flag means that MPTCP handling is enabled. This + flag can also be implied from the presence of other flags. + + Even when enabled, MPTCP handling will by default still be disabled + unless "/proc/sys/net/mptcp/enabled" sysctl is on. NetworkManager + does not change the sysctl and this is up to the administrator or + distribution. To configure endpoints even if the sysctl is disabled, + "also-without-sysctl" (0x4) flag can be used. In that case, + NetworkManager doesn't look at the sysctl and configures endpoints + regardless. + + Even when enabled, NetworkManager will only configure MPTCP + endpoints for a certain address family, if there is a unicast + default route (0.0.0.0/0 or ::/0) in the main routing table. The + flag "also-without-default-route" (0x8) can override that. + + When MPTCP handling is enabled then endpoints are configured with + the specified address flags "signal" (0x10), "subflow" (0x20), + "backup" (0x40), "fullmesh" (0x80). See ip-mptcp(8) manual for + additional information about the flags. + + If the flags are zero (0x0), the global connection default from + NetworkManager.conf is honored. If still unspecified, the fallback + is "enabled,subflow". Note that this means that MPTCP is by default + done depending on the "/proc/sys/net/mptcp/enabled" sysctl. + + NetworkManager does not change the MPTCP limits nor enable MPTCP via + "/proc/sys/net/mptcp/enabled". That is a host configuration which + the admin can change via sysctl and ip-mptcp. + + Strict reverse path filtering (rp_filter) breaks many MPTCP use + cases, so when MPTCP handling for IPv4 addresses on the interface is + enabled, NetworkManager would loosen the strict reverse path + filtering (1) to the loose setting (2).""" mud_url: Optional[str] = field( - metadata={'dbus_name': 'mud-url', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'mud-url', + 'dbus_type': 's', + }, default=None, ) """If configured, set to a Manufacturer Usage Description (MUD) URL that - points to manufacturer-recommended network policies for IoT devices. It is - transmitted as a DHCPv4 or DHCPv6 option. The value must be a valid URL - starting with "https://". The special value "none" is allowed to indicate that - no MUD URL is used. If the per-profile value is unspecified (the default), a - global connection default gets consulted. If still unspecified, the ultimate - default is "none".""" + points to manufacturer-recommended network policies for IoT devices. + It is transmitted as a DHCPv4 or DHCPv6 option. The value must be a + valid URL starting with "https://". + + The special value "none" is allowed to indicate that no MUD URL is + used. + + If the per-profile value is unspecified (the default), a global + connection default gets consulted. If still unspecified, the + ultimate default is "none".""" multi_connect: Optional[int] = field( - metadata={'dbus_name': 'multi-connect', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'multi-connect', + 'dbus_type': 'i', + }, default=None, ) - """Specifies whether the profile can be active multiple times at a particular - moment. The value is of type NMConnectionMultiConnect.""" + """Specifies whether the profile can be active multiple times at a + particular moment. The value is of type NMConnectionMultiConnect.""" permissions: Optional[List[str]] = field( - metadata={'dbus_name': 'permissions', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'permissions', + 'dbus_type': 'as', + }, default=None, ) """An array of strings defining what access a given user has to this - connection. If this is NULL or empty, all users are allowed to access this - connection; otherwise users are allowed if and only if they are in this list. - When this is not empty, the connection can be active only when one of the - specified users is logged into an active session. Each entry is of the form - "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". At this time only the - "user" [type] is allowed. Any other values are ignored and reserved for - future use. [id] is the username that this permission refers to, which may - not contain the ":" character. Any [reserved] information present must be - ignored and is reserved for future use. All of [type], [id], and [reserved] - must be valid UTF-8.""" + connection. If this is NULL or empty, all users are allowed to + access this connection; otherwise users are allowed if and only if + they are in this list. When this is not empty, the connection can + be active only when one of the specified users is logged into an + active session. Each entry is of the form "[type]:[id]:[reserved]"; + for example, "user:dcbw:blah". + + At this time only the "user" [type] is allowed. Any other values + are ignored and reserved for future use. [id] is the username that + this permission refers to, which may not contain the ":" character. + Any [reserved] information present must be ignored and is reserved + for future use. All of [type], [id], and [reserved] must be valid + UTF-8.""" read_only: Optional[bool] = field( - metadata={'dbus_name': 'read-only', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'read-only', + 'dbus_type': 'b', + }, + default=None, ) """FALSE if the connection can be modified using the provided settings - service's D-Bus interface with the right privileges, or TRUE if the connection - is read-only and cannot be modified.""" + service's D-Bus interface with the right privileges, or TRUE if the + connection is read-only and cannot be modified.""" secondaries: Optional[List[str]] = field( - metadata={'dbus_name': 'secondaries', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'secondaries', + 'dbus_type': 'as', + }, default=None, ) - """List of connection UUIDs that should be activated when the base connection - itself is activated. Currently, only VPN connections are supported.""" + """List of connection UUIDs that should be activated when the base + connection itself is activated. Currently, only VPN connections are + supported.""" slave_type: Optional[str] = field( - metadata={'dbus_name': 'slave-type', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'slave-type', + 'dbus_type': 's', + }, default=None, ) """Setting name of the device type of this slave's master connection (eg, "bond"), or NULL if this connection is not a slave.""" stable_id: Optional[str] = field( - metadata={'dbus_name': 'stable-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'stable-id', + 'dbus_type': 's', + }, default=None, ) - """This represents the identity of the connection used for various purposes. - It allows to configure multiple profiles to share the identity. Also, the - stable-id can contain placeholders that are substituted dynamically and - deterministically depending on the context. The stable-id is used for - generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable- - privacy. It is also used to seed the generated cloned MAC address for - ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is - also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to - derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that - depending on the context where it is used, other parameters are also seeded - into the generation algorithm. For example, a per-host key is commonly also - included, so that different systems end up generating different IDs. Or with - ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that - different interfaces yield different addresses. The per-host key is the - identity of your machine and stored in /var/lib/NetworkManager/secret-key. The - '$' character is treated special to perform dynamic substitutions at runtime. - Currently, supported are "${CONNECTION}", "${DEVICE}", "${MAC}", "${BOOT}", - "${RANDOM}". These effectively create unique IDs per-connection, per-device, - per-boot, or every time. Note that "${DEVICE}" corresponds to the interface - name of the device and "${MAC}" is the permanent MAC address of the device. - Any unrecognized patterns following '$' are treated verbatim, however are - reserved for future use. You are thus advised to avoid '$' or escape it as - "$$". For example, set it to "${CONNECTION}-${BOOT}-${DEVICE}" to create a - unique id for this connection that changes with every reboot and differs - depending on the interface where the profile activates. If the value is unset, - a global connection default is consulted. If the value is still unset, the - default is similar to "${CONNECTION}" and uses a unique, fixed ID for the - connection.""" + """This represents the identity of the connection used for various + purposes. It allows to configure multiple profiles to share the + identity. Also, the stable-id can contain placeholders that are + substituted dynamically and deterministically depending on the + context. + + The stable-id is used for generating IPv6 stable private addresses + with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the + generated cloned MAC address for ethernet.cloned-mac-address=stable + and wifi.cloned-mac-address=stable. It is also used as DHCP client + identifier with ipv4.dhcp-client-id=stable and to derive the DHCP + DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. + + Note that depending on the context where it is used, other + parameters are also seeded into the generation algorithm. For + example, a per-host key is commonly also included, so that different + systems end up generating different IDs. Or with ipv6.addr-gen- + mode=stable-privacy, also the device's name is included, so that + different interfaces yield different addresses. The per-host key is + the identity of your machine and stored in + /var/lib/NetworkManager/secret_key. See NetworkManager(8) manual + about the secret-key and the host identity. + + The '$' character is treated special to perform dynamic + substitutions at runtime. Currently, supported are "${CONNECTION}", + "${DEVICE}", "${MAC}", "${BOOT}", "${RANDOM}". These effectively + create unique IDs per-connection, per-device, per-boot, or every + time. Note that "${DEVICE}" corresponds to the interface name of the + device and "${MAC}" is the permanent MAC address of the device. Any + unrecognized patterns following '$' are treated verbatim, however + are reserved for future use. You are thus advised to avoid '$' or + escape it as "$$". For example, set it to + "${CONNECTION}-${BOOT}-${DEVICE}" to create a unique id for this + connection that changes with every reboot and differs depending on + the interface where the profile activates. + + If the value is unset, a global connection default is consulted. If + the value is still unset, the default is similar to "${CONNECTION}" + and uses a unique, fixed ID for the connection.""" timestamp: Optional[int] = field( - metadata={'dbus_name': 'timestamp', 'dbus_type': 't'}, + metadata={ + 'dbus_name': 'timestamp', + 'dbus_type': 't', + }, default=None, ) """The time, in seconds since the Unix Epoch, that the connection was last - _successfully_ fully activated. NetworkManager updates the connection - timestamp periodically when the connection is active to ensure that an active - connection has the latest timestamp. The property is only meant for reading - (changes to this property will not be preserved).""" + _successfully_ fully activated. + + NetworkManager updates the connection timestamp periodically when + the connection is active to ensure that an active connection has the + latest timestamp. The property is only meant for reading (changes to + this property will not be preserved).""" + connection_type: Optional[str] = field( + metadata={ + 'dbus_name': 'type', + 'dbus_type': 's', + }, + default=None, + ) + """Base type of the connection. For hardware-dependent connections, should + contain the setting name of the hardware-type specific setting (ie, + "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for + non-hardware dependent connections like VPN or otherwise, should + contain the setting name of that setting type (ie, "vpn" or + "bridge", etc).""" + uuid: Optional[str] = field( + metadata={ + 'dbus_name': 'uuid', + 'dbus_type': 's', + }, + default=None, + ) + """A universally unique identifier for the connection, for example + generated with libuuid. It should be assigned when the connection + is created, and never changed as long as the connection still + applies to the same network. For example, it should not be changed + when the "id" property or NMSettingIP4Config changes, but might need + to be re-created when the Wi-Fi SSID, mobile broadband network + provider, or "type" property changes. + + The UUID must be in the format + "2815492f-7e56-435e-b2e9-246bd7cdc664" (ie, contains only + hexadecimal characters and "-").""" + wait_activation_delay: Optional[int] = field( + metadata={ + 'dbus_name': 'wait-activation-delay', + 'dbus_type': 'i', + }, + default=None, + ) + """Time in milliseconds to wait for connection to be considered activated. + The wait will start after the pre-up dispatcher event. + + The value 0 means no wait time. The default value is -1, which + currently has the same meaning as no wait time.""" wait_device_timeout: Optional[int] = field( - metadata={'dbus_name': 'wait-device-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'wait-device-timeout', + 'dbus_type': 'i', + }, default=None, ) - """Timeout in milliseconds to wait for device at startup. During boot, devices - may take a while to be detected by the driver. This property will cause to - delay NetworkManager-wait-online.service and nm-online to give the device a - chance to appear. This works by waiting for the given timeout until a - compatible device for the profile is available and managed. The value 0 means - no wait time. The default value is -1, which currently has the same meaning as - no wait time.""" + """Timeout in milliseconds to wait for device at startup. During boot, + devices may take a while to be detected by the driver. This property + will cause to delay NetworkManager-wait-online.service and nm-online + to give the device a chance to appear. This works by waiting for the + given timeout until a compatible device for the profile is available + and managed. + + The value 0 means no wait time. The default value is -1, which + currently has the same meaning as no wait time.""" zone: Optional[str] = field( - metadata={'dbus_name': 'zone', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'zone', + 'dbus_type': 's', + }, default=None, ) """The trust level of a the connection. Free form case-insensitive string - (for example "Home", "Work", "Public"). NULL or unspecified zone means the - connection will be placed in the default zone as defined by the firewall. When - updating this property on a currently activated connection, the change takes - effect immediately.""" + (for example "Home", "Work", "Public"). NULL or unspecified zone + means the connection will be placed in the default zone as defined + by the firewall. + + When updating this property on a currently activated connection, the + change takes effect immediately.""" diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index 7af0b7f..609d6a8 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,110 +12,163 @@ class DcbSettings(NetworkManagerSettingsMixin): """Data Center Bridging Settings""" app_fcoe_flags: Optional[int] = field( - metadata={'dbus_name': 'app-fcoe-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-fcoe-flags', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may be - any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), - NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" + """Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may + be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING + (0x4).""" app_fcoe_mode: Optional[str] = field( - metadata={'dbus_name': 'app-fcoe-mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'app-fcoe-mode', + 'dbus_type': 's', + }, default=None, ) - """The FCoE controller mode; either "fabric" or "vn2vn". Since 1.34, NULL is - the default and means "fabric". Before 1.34, NULL was rejected as invalid and - the default was "fabric".""" + """The FCoE controller mode; either "fabric" or "vn2vn". + + Since 1.34, NULL is the default and means "fabric". Before 1.34, + NULL was rejected as invalid and the default was "fabric".""" app_fcoe_priority: Optional[int] = field( - metadata={'dbus_name': 'app-fcoe-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-fcoe-priority', + 'dbus_type': 'i', + }, default=None, ) - """The highest User Priority (0 - 7) which FCoE frames should use, or -1 for - default priority. Only used when the "app-fcoe-flags" property includes the - NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" + """The highest User Priority (0 - 7) which FCoE frames should use, or -1 + for default priority. Only used when the "app-fcoe-flags" property + includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" app_fip_flags: Optional[int] = field( - metadata={'dbus_name': 'app-fip-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-fip-flags', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the NMSettingDcbFlags for the DCB FIP application. Flags may be - any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), - NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" + """Specifies the NMSettingDcbFlags for the DCB FIP application. Flags may + be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING + (0x4).""" app_fip_priority: Optional[int] = field( - metadata={'dbus_name': 'app-fip-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-fip-priority', + 'dbus_type': 'i', + }, default=None, ) """The highest User Priority (0 - 7) which FIP frames should use, or -1 for - default priority. Only used when the "app-fip-flags" property includes the - NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" + default priority. Only used when the "app-fip-flags" property + includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" app_iscsi_flags: Optional[int] = field( - metadata={'dbus_name': 'app-iscsi-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-iscsi-flags', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the NMSettingDcbFlags for the DCB iSCSI application. Flags may - be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), - NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" + """Specifies the NMSettingDcbFlags for the DCB iSCSI application. Flags + may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING + (0x4).""" app_iscsi_priority: Optional[int] = field( - metadata={'dbus_name': 'app-iscsi-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'app-iscsi-priority', + 'dbus_type': 'i', + }, default=None, ) - """The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for - default priority. Only used when the "app-iscsi-flags" property includes the - NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" + """The highest User Priority (0 - 7) which iSCSI frames should use, or -1 + for default priority. Only used when the "app-iscsi-flags" property + includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag.""" priority_bandwidth: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-bandwidth', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-bandwidth', + 'dbus_type': 'au', + }, default=None, ) """An array of 8 uint values, where the array index corresponds to the User - Priority (0 - 7) and the value indicates the percentage of bandwidth of the - priority's assigned group that the priority may use. The sum of all - percentages for priorities which belong to the same group must total 100 - percents.""" + Priority (0 - 7) and the value indicates the percentage of bandwidth + of the priority's assigned group that the priority may use. The sum + of all percentages for priorities which belong to the same group + must total 100 percents.""" priority_flow_control: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-flow-control', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-flow-control', + 'dbus_type': 'au', + }, default=None, ) - """An array of 8 boolean values, where the array index corresponds to the User - Priority (0 - 7) and the value indicates whether or not the corresponding - priority should transmit priority pause.""" + """An array of 8 boolean values, where the array index corresponds to the + User Priority (0 - 7) and the value indicates whether or not the + corresponding priority should transmit priority pause.""" priority_flow_control_flags: Optional[int] = field( - metadata={'dbus_name': 'priority-flow-control-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'priority-flow-control-flags', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags - may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), - NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" + """Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). + Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING + (0x4).""" priority_group_bandwidth: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-group-bandwidth', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-group-bandwidth', + 'dbus_type': 'au', + }, default=None, ) """An array of 8 uint values, where the array index corresponds to the - Priority Group ID (0 - 7) and the value indicates the percentage of link - bandwidth allocated to that group. Allowed values are 0 - 100, and the sum of - all values must total 100 percents.""" + Priority Group ID (0 - 7) and the value indicates the percentage of + link bandwidth allocated to that group. Allowed values are 0 - 100, + and the sum of all values must total 100 percents.""" priority_group_flags: Optional[int] = field( - metadata={'dbus_name': 'priority-group-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'priority-group-flags', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the NMSettingDcbFlags for DCB Priority Groups. Flags may be any - combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE - (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4).""" + """Specifies the NMSettingDcbFlags for DCB Priority Groups. Flags may be + any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), + NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING + (0x4).""" priority_group_id: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-group-id', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-group-id', + 'dbus_type': 'au', + }, default=None, ) """An array of 8 uint values, where the array index corresponds to the User - Priority (0 - 7) and the value indicates the Priority Group ID. Allowed - Priority Group ID values are 0 - 7 or 15 for the unrestricted group.""" + Priority (0 - 7) and the value indicates the Priority Group ID. + Allowed Priority Group ID values are 0 - 7 or 15 for the + unrestricted group.""" priority_strict_bandwidth: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-strict-bandwidth', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-strict-bandwidth', + 'dbus_type': 'au', + }, default=None, ) - """An array of 8 boolean values, where the array index corresponds to the User - Priority (0 - 7) and the value indicates whether or not the priority may use - all of the bandwidth allocated to its assigned group.""" + """An array of 8 boolean values, where the array index corresponds to the + User Priority (0 - 7) and the value indicates whether or not the + priority may use all of the bandwidth allocated to its assigned + group.""" priority_traffic_class: Optional[List[int]] = field( - metadata={'dbus_name': 'priority-traffic-class', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'priority-traffic-class', + 'dbus_type': 'au', + }, default=None, ) """An array of 8 uint values, where the array index corresponds to the User - Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which - the priority is mapped.""" + Priority (0 - 7) and the value indicates the traffic class (0 - 7) + to which the priority is mapped.""" diff --git a/sdbus_async/networkmanager/settings/dummy.py b/sdbus_async/networkmanager/settings/dummy.py new file mode 100644 index 0000000..ef45504 --- /dev/null +++ b/sdbus_async/networkmanager/settings/dummy.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Optional +from .base import NetworkManagerSettingsMixin + + +@dataclass +class DummySettings(NetworkManagerSettingsMixin): + """Dummy Link Settings""" + diff --git a/sdbus_async/networkmanager/settings/eapol.py b/sdbus_async/networkmanager/settings/eapol.py new file mode 100644 index 0000000..e4eb6e4 --- /dev/null +++ b/sdbus_async/networkmanager/settings/eapol.py @@ -0,0 +1,595 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import List, Optional +from .base import NetworkManagerSettingsMixin + + +@dataclass +class EapolSettings(NetworkManagerSettingsMixin): + """IEEE 802.1x Authentication Settings""" + + altsubject_matches: Optional[List[str]] = field( + metadata={ + 'dbus_name': 'altsubject-matches', + 'dbus_type': 'as', + }, + default=None, + ) + """List of strings to be matched against the altSubjectName of the + certificate presented by the authentication server. If the list is + empty, no verification of the server certificate's altSubjectName is + performed.""" + anonymous_identity: Optional[str] = field( + metadata={ + 'dbus_name': 'anonymous-identity', + 'dbus_type': 's', + }, + default=None, + ) + """Anonymous identity string for EAP authentication methods. Used as the + unencrypted identity with EAP types that support different tunneled + identity like EAP-TTLS.""" + auth_timeout: Optional[int] = field( + metadata={ + 'dbus_name': 'auth-timeout', + 'dbus_type': 'i', + }, + default=None, + ) + """A timeout for the authentication. Zero means the global default; if the + global default is not set, the authentication timeout is 25 seconds.""" + ca_cert: Optional[bytes] = field( + metadata={ + 'dbus_name': 'ca-cert', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the CA certificate if used by the EAP method specified in the + "eap" property. + + Certificate data is specified using a "scheme"; three are currently + supported: blob, path and pkcs#11 URL. When using the blob scheme + this property should be set to the certificate's DER encoded data. + When using the path scheme, this property should be set to the full + UTF-8 encoded path of the certificate, prefixed with the string + "file://" and ending with a terminating NUL byte. This property can + be unset even if the EAP method supports CA certificates, but this + allows man-in-the-middle attacks and is NOT recommended. + + Note that enabling NMSetting8021x:system-ca-certs will override this + setting to use the built-in path, if the built-in path is not a + directory.""" + ca_cert_password: Optional[str] = field( + metadata={ + 'dbus_name': 'ca-cert-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to access the CA certificate stored in "ca-cert" + property. Only makes sense if the certificate is stored on a PKCS#11 + token that requires a login.""" + ca_cert_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'ca-cert-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "ca-cert-password" property.""" + ca_path: Optional[str] = field( + metadata={ + 'dbus_name': 'ca-path', + 'dbus_type': 's', + }, + default=None, + ) + """UTF-8 encoded path to a directory containing PEM or DER formatted + certificates to be added to the verification chain in addition to + the certificate specified in the "ca-cert" property. + + If NMSetting8021x:system-ca-certs is enabled and the built-in CA + path is an existing directory, then this setting is ignored.""" + client_cert: Optional[bytes] = field( + metadata={ + 'dbus_name': 'client-cert', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the client certificate if used by the EAP method specified in + the "eap" property. + + Certificate data is specified using a "scheme"; two are currently + supported: blob and path. When using the blob scheme (which is + backwards compatible with NM 0.7.x) this property should be set to + the certificate's DER encoded data. When using the path scheme, this + property should be set to the full UTF-8 encoded path of the + certificate, prefixed with the string "file://" and ending with a + terminating NUL byte.""" + client_cert_password: Optional[str] = field( + metadata={ + 'dbus_name': 'client-cert-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to access the client certificate stored in "client- + cert" property. Only makes sense if the certificate is stored on a + PKCS#11 token that requires a login.""" + client_cert_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'client-cert-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "client-cert-password" property.""" + domain_match: Optional[str] = field( + metadata={ + 'dbus_name': 'domain-match', + 'dbus_type': 's', + }, + default=None, + ) + """Constraint for server domain name. If set, this list of FQDNs is used as + a match requirement for dNSName element(s) of the certificate + presented by the authentication server. If a matching dNSName is + found, this constraint is met. If no dNSName values are present, + this constraint is matched against SubjectName CN using the same + comparison. Multiple valid FQDNs can be passed as a ";" delimited + list.""" + domain_suffix_match: Optional[str] = field( + metadata={ + 'dbus_name': 'domain-suffix-match', + 'dbus_type': 's', + }, + default=None, + ) + """Constraint for server domain name. If set, this FQDN is used as a suffix + match requirement for dNSName element(s) of the certificate + presented by the authentication server. If a matching dNSName is + found, this constraint is met. If no dNSName values are present, + this constraint is matched against SubjectName CN using same suffix + match comparison. Since version 1.24, multiple valid FQDNs can be + passed as a ";" delimited list.""" + eap: Optional[List[str]] = field( + metadata={ + 'dbus_name': 'eap', + 'dbus_type': 'as', + }, + default=None, + ) + """The allowed EAP method to be used when authenticating to the network + with 802.1x. Valid methods are: "leap", "md5", "tls", "peap", + "ttls", "pwd", and "fast". Each method requires different + configuration using the properties of this setting; refer to + wpa_supplicant documentation for the allowed combinations.""" + identity: Optional[str] = field( + metadata={ + 'dbus_name': 'identity', + 'dbus_type': 's', + }, + default=None, + ) + """Identity string for EAP authentication methods. Often the user's user + or login name.""" + optional: Optional[bool] = field( + metadata={ + 'dbus_name': 'optional', + 'dbus_type': 'b', + }, + default=None, + ) + """Whether the 802.1X authentication is optional. If TRUE, the activation + will continue even after a timeout or an authentication failure. + Setting the property to TRUE is currently allowed only for Ethernet + connections. If set to FALSE, the activation can continue only after + a successful authentication.""" + pac_file: Optional[str] = field( + metadata={ + 'dbus_name': 'pac-file', + 'dbus_type': 's', + }, + default=None, + ) + """UTF-8 encoded file path containing PAC for EAP-FAST.""" + password: Optional[str] = field( + metadata={ + 'dbus_name': 'password', + 'dbus_type': 's', + }, + default=None, + ) + """UTF-8 encoded password used for EAP authentication methods. If both the + "password" property and the "password-raw" property are specified, + "password" is preferred.""" + password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "password" property.""" + password_raw: Optional[bytes] = field( + metadata={ + 'dbus_name': 'password-raw', + 'dbus_type': 'ay', + }, + default=None, + ) + """Password used for EAP authentication methods, given as a byte array to + allow passwords in other encodings than UTF-8 to be used. If both + the "password" property and the "password-raw" property are + specified, "password" is preferred.""" + password_raw_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'password-raw-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "password-raw" property.""" + phase1_auth_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'phase1-auth-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Specifies authentication flags to use in "phase 1" outer authentication + using NMSetting8021xAuthFlags options. The individual TLS versions + can be explicitly disabled. TLS time checks can be also disabled. If + a certain TLS disable flag is not set, it is up to the supplicant to + allow or forbid it. The TLS options map to tls_disable_tlsv1_x and + tls_disable_time_checks settings. See the wpa_supplicant + documentation for more details.""" + phase1_fast_provisioning: Optional[str] = field( + metadata={ + 'dbus_name': 'phase1-fast-provisioning', + 'dbus_type': 's', + }, + default=None, + ) + """Enables or disables in-line provisioning of EAP-FAST credentials when + FAST is specified as the EAP method in the "eap" property. + Recognized values are "0" (disabled), "1" (allow unauthenticated + provisioning), "2" (allow authenticated provisioning), and "3" + (allow both authenticated and unauthenticated provisioning). See + the wpa_supplicant documentation for more details.""" + phase1_peaplabel: Optional[str] = field( + metadata={ + 'dbus_name': 'phase1-peaplabel', + 'dbus_type': 's', + }, + default=None, + ) + """Forces use of the new PEAP label during key derivation. Some RADIUS + servers may require forcing the new PEAP label to interoperate with + PEAPv1. Set to "1" to force use of the new PEAP label. See the + wpa_supplicant documentation for more details.""" + phase1_peapver: Optional[str] = field( + metadata={ + 'dbus_name': 'phase1-peapver', + 'dbus_type': 's', + }, + default=None, + ) + """Forces which PEAP version is used when PEAP is set as the EAP method in + the "eap" property. When unset, the version reported by the server + will be used. Sometimes when using older RADIUS servers, it is + necessary to force the client to use a particular PEAP version. To + do so, this property may be set to "0" or "1" to force that specific + PEAP version.""" + phase2_altsubject_matches: Optional[List[str]] = field( + metadata={ + 'dbus_name': 'phase2-altsubject-matches', + 'dbus_type': 'as', + }, + default=None, + ) + """List of strings to be matched against the altSubjectName of the + certificate presented by the authentication server during the inner + "phase 2" authentication. If the list is empty, no verification of + the server certificate's altSubjectName is performed.""" + phase2_auth: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-auth', + 'dbus_type': 's', + }, + default=None, + ) + """Specifies the allowed "phase 2" inner authentication method when an EAP + method that uses an inner TLS tunnel is specified in the "eap" + property. For TTLS this property selects one of the supported non- + EAP inner methods: "pap", "chap", "mschap", "mschapv2" while + "phase2-autheap" selects an EAP inner method. For PEAP this selects + an inner EAP method, one of: "gtc", "otp", "md5" and "tls". Each + "phase 2" inner method requires specific parameters for successful + authentication; see the wpa_supplicant documentation for more + details. Both "phase2-auth" and "phase2-autheap" cannot be + specified.""" + phase2_autheap: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-autheap', + 'dbus_type': 's', + }, + default=None, + ) + """Specifies the allowed "phase 2" inner EAP-based authentication method + when TTLS is specified in the "eap" property. Recognized EAP-based + "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and "tls". + Each "phase 2" inner method requires specific parameters for + successful authentication; see the wpa_supplicant documentation for + more details.""" + phase2_ca_cert: Optional[bytes] = field( + metadata={ + 'dbus_name': 'phase2-ca-cert', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the "phase 2" CA certificate if used by the EAP method + specified in the "phase2-auth" or "phase2-autheap" properties. + + Certificate data is specified using a "scheme"; three are currently + supported: blob, path and pkcs#11 URL. When using the blob scheme + this property should be set to the certificate's DER encoded data. + When using the path scheme, this property should be set to the full + UTF-8 encoded path of the certificate, prefixed with the string + "file://" and ending with a terminating NUL byte. This property can + be unset even if the EAP method supports CA certificates, but this + allows man-in-the-middle attacks and is NOT recommended. + + Note that enabling NMSetting8021x:system-ca-certs will override this + setting to use the built-in path, if the built-in path is not a + directory.""" + phase2_ca_cert_password: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-ca-cert-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to access the "phase2" CA certificate stored in + "phase2-ca-cert" property. Only makes sense if the certificate is + stored on a PKCS#11 token that requires a login.""" + phase2_ca_cert_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'phase2-ca-cert-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "phase2-ca-cert-password" property.""" + phase2_ca_path: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-ca-path', + 'dbus_type': 's', + }, + default=None, + ) + """UTF-8 encoded path to a directory containing PEM or DER formatted + certificates to be added to the verification chain in addition to + the certificate specified in the "phase2-ca-cert" property. + + If NMSetting8021x:system-ca-certs is enabled and the built-in CA + path is an existing directory, then this setting is ignored.""" + phase2_client_cert: Optional[bytes] = field( + metadata={ + 'dbus_name': 'phase2-client-cert', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the "phase 2" client certificate if used by the EAP method + specified in the "phase2-auth" or "phase2-autheap" properties. + + Certificate data is specified using a "scheme"; two are currently + supported: blob and path. When using the blob scheme (which is + backwards compatible with NM 0.7.x) this property should be set to + the certificate's DER encoded data. When using the path scheme, this + property should be set to the full UTF-8 encoded path of the + certificate, prefixed with the string "file://" and ending with a + terminating NUL byte. This property can be unset even if the EAP + method supports CA certificates, but this allows man-in-the-middle + attacks and is NOT recommended.""" + phase2_client_cert_password: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-client-cert-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to access the "phase2" client certificate stored in + "phase2-client-cert" property. Only makes sense if the certificate + is stored on a PKCS#11 token that requires a login.""" + phase2_client_cert_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'phase2-client-cert-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "phase2-client-cert-password" + property.""" + phase2_domain_match: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-domain-match', + 'dbus_type': 's', + }, + default=None, + ) + """Constraint for server domain name. If set, this list of FQDNs is used as + a match requirement for dNSName element(s) of the certificate + presented by the authentication server during the inner "phase 2" + authentication. If a matching dNSName is found, this constraint is + met. If no dNSName values are present, this constraint is matched + against SubjectName CN using the same comparison. Multiple valid + FQDNs can be passed as a ";" delimited list.""" + phase2_domain_suffix_match: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-domain-suffix-match', + 'dbus_type': 's', + }, + default=None, + ) + """Constraint for server domain name. If set, this FQDN is used as a suffix + match requirement for dNSName element(s) of the certificate + presented by the authentication server during the inner "phase 2" + authentication. If a matching dNSName is found, this constraint is + met. If no dNSName values are present, this constraint is matched + against SubjectName CN using same suffix match comparison. Since + version 1.24, multiple valid FQDNs can be passed as a ";" delimited + list.""" + phase2_private_key: Optional[bytes] = field( + metadata={ + 'dbus_name': 'phase2-private-key', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the "phase 2" inner private key when the "phase2-auth" or + "phase2-autheap" property is set to "tls". + + Key data is specified using a "scheme"; two are currently supported: + blob and path. When using the blob scheme and private keys, this + property should be set to the key's encrypted PEM encoded data. When + using private keys with the path scheme, this property should be set + to the full UTF-8 encoded path of the key, prefixed with the string + "file://" and ending with a terminating NUL byte. When using PKCS#12 + format private keys and the blob scheme, this property should be set + to the PKCS#12 data and the "phase2-private-key-password" property + must be set to password used to decrypt the PKCS#12 certificate and + key. When using PKCS#12 files and the path scheme, this property + should be set to the full UTF-8 encoded path of the key, prefixed + with the string "file://" and ending with a terminating NUL byte, + and as with the blob scheme the "phase2-private-key-password" + property must be set to the password used to decode the PKCS#12 + private key and certificate.""" + phase2_private_key_password: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-private-key-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to decrypt the "phase 2" private key specified in the + "phase2-private-key" property when the private key either uses the + path scheme, or is a PKCS#12 format key.""" + phase2_private_key_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'phase2-private-key-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "phase2-private-key-password" + property.""" + phase2_subject_match: Optional[str] = field( + metadata={ + 'dbus_name': 'phase2-subject-match', + 'dbus_type': 's', + }, + default=None, + ) + """Substring to be matched against the subject of the certificate presented + by the authentication server during the inner "phase 2" + authentication. When unset, no verification of the authentication + server certificate's subject is performed. This property provides + little security, if any, and should not be used.""" + pin: Optional[str] = field( + metadata={ + 'dbus_name': 'pin', + 'dbus_type': 's', + }, + default=None, + ) + """PIN used for EAP authentication methods.""" + pin_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'pin-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "pin" property.""" + private_key: Optional[bytes] = field( + metadata={ + 'dbus_name': 'private-key', + 'dbus_type': 'ay', + }, + default=None, + ) + """Contains the private key when the "eap" property is set to "tls". + + Key data is specified using a "scheme"; two are currently supported: + blob and path. When using the blob scheme and private keys, this + property should be set to the key's encrypted PEM encoded data. When + using private keys with the path scheme, this property should be set + to the full UTF-8 encoded path of the key, prefixed with the string + "file://" and ending with a terminating NUL byte. When using PKCS#12 + format private keys and the blob scheme, this property should be set + to the PKCS#12 data and the "private-key-password" property must be + set to password used to decrypt the PKCS#12 certificate and key. + When using PKCS#12 files and the path scheme, this property should + be set to the full UTF-8 encoded path of the key, prefixed with the + string "file://" and ending with a terminating NUL byte, and as with + the blob scheme the "private-key-password" property must be set to + the password used to decode the PKCS#12 private key and certificate. + + WARNING: "private-key" is not a "secret" property, and thus + unencrypted private key data using the BLOB scheme may be readable + by unprivileged users. Private keys should always be encrypted with + a private key password to prevent unauthorized access to unencrypted + private key data.""" + private_key_password: Optional[str] = field( + metadata={ + 'dbus_name': 'private-key-password', + 'dbus_type': 's', + }, + default=None, + ) + """The password used to decrypt the private key specified in the "private- + key" property when the private key either uses the path scheme, or + if the private key is a PKCS#12 format key.""" + private_key_password_flags: Optional[int] = field( + metadata={ + 'dbus_name': 'private-key-password-flags', + 'dbus_type': 'u', + }, + default=None, + ) + """Flags indicating how to handle the "private-key-password" property.""" + subject_match: Optional[str] = field( + metadata={ + 'dbus_name': 'subject-match', + 'dbus_type': 's', + }, + default=None, + ) + """Substring to be matched against the subject of the certificate presented + by the authentication server. When unset, no verification of the + authentication server certificate's subject is performed. This + property provides little security, if any, and should not be used.""" + system_ca_certs: Optional[bool] = field( + metadata={ + 'dbus_name': 'system-ca-certs', + 'dbus_type': 'b', + }, + default=None, + ) + """When TRUE, overrides the "ca-path" and "phase2-ca-path" properties using + the system CA directory specified at configure time with the + --system-ca-path switch. The certificates in this directory are + added to the verification chain in addition to any certificates + specified by the "ca-cert" and "phase2-ca-cert" properties. If the + path provided with --system-ca-path is rather a file name (bundle of + trusted CA certificates), it overrides "ca-cert" and "phase2-ca- + cert" properties instead (sets ca_cert/ca_cert2 options for + wpa_supplicant).""" diff --git a/sdbus_async/networkmanager/settings/ethernet.py b/sdbus_async/networkmanager/settings/ethernet.py index 8b244cd..24f15d9 100644 --- a/sdbus_async/networkmanager/settings/ethernet.py +++ b/sdbus_async/networkmanager/settings/ethernet.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,166 +12,252 @@ class EthernetSettings(NetworkManagerSettingsMixin): """Wired Ethernet Settings""" accept_all_mac_addresses: Optional[int] = field( - metadata={'dbus_name': 'accept-all-mac-addresses', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'accept-all-mac-addresses', + 'dbus_type': 'i', + }, default=None, ) """When TRUE, setup the interface to accept packets for all MAC addresses. - This is enabling the kernel interface flag IFF_PROMISC. When FALSE, the - interface will only accept the packets with the interface destination mac - address or broadcast.""" + This is enabling the kernel interface flag IFF_PROMISC. When FALSE, + the interface will only accept the packets with the interface + destination mac address or broadcast.""" assigned_mac_address: Optional[str] = field( - metadata={'dbus_name': 'assigned-mac-address', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'assigned-mac-address', + 'dbus_type': 's', + }, default=None, ) """The new field for the cloned MAC address. It can be either a hardware - address in ASCII representation, or one of the special values "preserve", - "permanent", "random" or "stable". This field replaces the deprecated "cloned- - mac-address" on D-Bus, which can only contain explicit hardware addresses. - Note that this property only exists in D-Bus API. libnm and nmcli continue to - call this property "cloned-mac-address".""" + address in ASCII representation, or one of the special values + "preserve", "permanent", "random" or "stable". This field replaces + the deprecated "cloned-mac-address" on D-Bus, which can only contain + explicit hardware addresses. Note that this property only exists in + D-Bus API. libnm and nmcli continue to call this property "cloned- + mac-address".""" auto_negotiate: Optional[bool] = field( - metadata={'dbus_name': 'auto-negotiate', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'auto-negotiate', + 'dbus_type': 'b', + }, + default=None, ) """When TRUE, enforce auto-negotiation of speed and duplex mode. If "speed" - and "duplex" properties are both specified, only that single mode will be - advertised and accepted during the link auto-negotiation process: this works - only for BASE-T 802.3 specifications and is useful for enforcing gigabits - modes, as in these cases link negotiation is mandatory. When FALSE, "speed" - and "duplex" properties should be both set or link configuration will be - skipped.""" + and "duplex" properties are both specified, only that single mode + will be advertised and accepted during the link auto-negotiation + process: this works only for BASE-T 802.3 specifications and is + useful for enforcing gigabits modes, as in these cases link + negotiation is mandatory. When FALSE, "speed" and "duplex" + properties should be both set or link configuration will be skipped.""" cloned_mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'cloned-mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'cloned-mac-address', + 'dbus_type': 'ay', + }, default=None, ) - """This D-Bus field is deprecated in favor of "assigned-mac-address" which is - more flexible and allows specifying special variants like "random". For libnm - and nmcli, this field is called "cloned-mac-address".""" + """If specified, request that the device use this MAC address instead. This + is known as MAC cloning or spoofing. + + Beside explicitly specifying a MAC address, the special values + "preserve", "permanent", "random" and "stable" are supported. + "preserve" means not to touch the MAC address on activation. + "permanent" means to use the permanent hardware address if the + device has one (otherwise this is treated as "preserve"). "random" + creates a random MAC address on each connect. "stable" creates a + hashed MAC address based on connection.stable-id and a machine + dependent key. + + If unspecified, the value can be overwritten via global defaults, + see manual of NetworkManager.conf. If still unspecified, it defaults + to "preserve" (older versions of NetworkManager may use a different + default value). + + On D-Bus, this field is expressed as "assigned-mac-address" or the + deprecated "cloned-mac-address".""" duplex: Optional[str] = field( - metadata={'dbus_name': 'duplex', 'dbus_type': 's'}, - default=None, - ) - """When a value is set, either "half" or "full", configures the device to use - the specified duplex mode. If "auto-negotiate" is "yes" the specified duplex - mode will be the only one advertised during link negotiation: this works only - for BASE-T 802.3 specifications and is useful for enforcing gigabits modes, as - in these cases link negotiation is mandatory. If the value is unset (the - default), the link configuration will be either skipped (if "auto-negotiate" - is "no", the default) or will be auto-negotiated (if "auto-negotiate" is - "yes") and the local device will advertise all the supported duplex modes. - Must be set together with the "speed" property if specified. Before specifying - a duplex mode be sure your device supports it.""" + metadata={ + 'dbus_name': 'duplex', + 'dbus_type': 's', + }, + default=None, + ) + """When a value is set, either "half" or "full", configures the device to + use the specified duplex mode. If "auto-negotiate" is "yes" the + specified duplex mode will be the only one advertised during link + negotiation: this works only for BASE-T 802.3 specifications and is + useful for enforcing gigabits modes, as in these cases link + negotiation is mandatory. If the value is unset (the default), the + link configuration will be either skipped (if "auto-negotiate" is + "no", the default) or will be auto-negotiated (if "auto-negotiate" + is "yes") and the local device will advertise all the supported + duplex modes. Must be set together with the "speed" property if + specified. Before specifying a duplex mode be sure your device + supports it.""" generate_mac_address_mask: Optional[str] = field( - metadata={'dbus_name': 'generate-mac-address-mask', 'dbus_type': 's'}, - default=None, - ) - """With "cloned-mac-address" setting "random" or "stable", by default all bits - of the MAC address are scrambled and a locally-administered, unicast MAC - address is created. This property allows to specify that certain bits are - fixed. Note that the least significant bit of the first MAC address will - always be unset to create a unicast MAC address. If the property is NULL, it - is eligible to be overwritten by a default connection setting. If the value is - still NULL or an empty string, the default is to create a locally- - administered, unicast MAC address. If the value contains one MAC address, this - address is used as mask. The set bits of the mask are to be filled with the - current MAC address of the device, while the unset bits are subject to - randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the - current MAC address and only randomize the lower 3 bytes using the "random" or - "stable" algorithm. If the value contains one additional MAC address after the - mask, this address is used instead of the current MAC address to fill the bits - that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 - 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the - lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" - will create a fully scrambled globally-administered, burned-in MAC address. If - the value contains more than one additional MAC addresses, one of them is - chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 - 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally - or globally administered.""" + metadata={ + 'dbus_name': 'generate-mac-address-mask', + 'dbus_type': 's', + }, + default=None, + ) + """With "cloned-mac-address" setting "random" or "stable", by default all + bits of the MAC address are scrambled and a locally-administered, + unicast MAC address is created. This property allows to specify that + certain bits are fixed. Note that the least significant bit of the + first MAC address will always be unset to create a unicast MAC + address. + + If the property is NULL, it is eligible to be overwritten by a + default connection setting. If the value is still NULL or an empty + string, the default is to create a locally-administered, unicast MAC + address. + + If the value contains one MAC address, this address is used as mask. + The set bits of the mask are to be filled with the current MAC + address of the device, while the unset bits are subject to + randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI + of the current MAC address and only randomize the lower 3 bytes + using the "random" or "stable" algorithm. + + If the value contains one additional MAC address after the mask, + this address is used instead of the current MAC address to fill the + bits that shall not be randomized. For example, a value of + "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC + address to 68:F7:28, while the lower bits are randomized. A value of + "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled + globally-administered, burned-in MAC address. + + If the value contains more than one additional MAC addresses, one of + them is chosen randomly. For example, "02:00:00:00:00:00 + 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled + MAC address, randomly locally or globally administered.""" mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 'ay', + }, default=None, ) - """If specified, this connection will only apply to the Ethernet device whose - permanent MAC address matches. This property does not change the MAC address - of the device (i.e. MAC spoofing).""" + """If specified, this connection will only apply to the Ethernet device + whose permanent MAC address matches. This property does not change + the MAC address of the device (i.e. MAC spoofing).""" mac_address_blacklist: Optional[List[str]] = field( - metadata={'dbus_name': 'mac-address-blacklist', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'mac-address-blacklist', + 'dbus_type': 'as', + }, default=None, ) - """If specified, this connection will never apply to the Ethernet device whose - permanent MAC address matches an address in the list. Each MAC address is in - the standard hex-digits-and-colons notation (00:11:22:33:44:55).""" + """If specified, this connection will never apply to the Ethernet device + whose permanent MAC address matches an address in the list. Each + MAC address is in the standard hex-digits-and-colons notation + (00:11:22:33:44:55).""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.""" port: Optional[str] = field( - metadata={'dbus_name': 'port', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'port', + 'dbus_type': 's', + }, default=None, ) """Specific port type to use if the device supports multiple attachment - methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit Interface), "bnc" - (Thin Ethernet) or "mii" (Media Independent Interface). If the device supports - only one port type, this setting is ignored.""" + methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit + Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent + Interface). If the device supports only one port type, this setting + is ignored.""" s390_nettype: Optional[str] = field( - metadata={'dbus_name': 's390-nettype', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 's390-nettype', + 'dbus_type': 's', + }, default=None, ) - """s390 network device type; one of "qeth", "lcs", or "ctc", representing the - different types of virtual network devices available on s390 systems.""" + """s390 network device type; one of "qeth", "lcs", or "ctc", representing + the different types of virtual network devices available on s390 + systems.""" s390_options: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 's390-options', 'dbus_type': 'a{ss}'}, + metadata={ + 'dbus_name': 's390-options', + 'dbus_type': 'a{ss}', + }, default=None, ) - """Dictionary of key/value pairs of s390-specific device options. Both keys - and values must be strings. Allowed keys include "portno", "layer2", - "portname", "protocol", among others. Key names must contain only - alphanumeric characters (ie, [a-zA-Z0-9]). Currently, NetworkManager itself - does nothing with this information. However, s390utils ships a udev rule which - parses this information and applies it to the interface.""" + """Dictionary of key/value pairs of s390-specific device options. Both + keys and values must be strings. Allowed keys include "portno", + "layer2", "portname", "protocol", among others. Key names must + contain only alphanumeric characters (ie, [a-zA-Z0-9]). + + Currently, NetworkManager itself does nothing with this information. + However, s390utils ships a udev rule which parses this information + and applies it to the interface.""" s390_subchannels: Optional[List[str]] = field( - metadata={'dbus_name': 's390-subchannels', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 's390-subchannels', + 'dbus_type': 'as', + }, default=None, ) """Identifies specific subchannels that this network device uses for - communication with z/VM or s390 host. Like the "mac-address" property for - non-z/VM devices, this property can be used to ensure this connection only - applies to the network device that uses these subchannels. The list should - contain exactly 3 strings, and each string may only be composed of hexadecimal - characters and the period (.) character.""" + communication with z/VM or s390 host. Like the "mac-address" + property for non-z/VM devices, this property can be used to ensure + this connection only applies to the network device that uses these + subchannels. The list should contain exactly 3 strings, and each + string may only be composed of hexadecimal characters and the period + (.) character.""" speed: Optional[int] = field( - metadata={'dbus_name': 'speed', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'speed', + 'dbus_type': 'u', + }, default=None, ) """When a value greater than 0 is set, configures the device to use the - specified speed. If "auto-negotiate" is "yes" the specified speed will be the - only one advertised during link negotiation: this works only for BASE-T 802.3 - specifications and is useful for enforcing gigabit speeds, as in this case - link negotiation is mandatory. If the value is unset (0, the default), the - link configuration will be either skipped (if "auto-negotiate" is "no", the - default) or will be auto-negotiated (if "auto-negotiate" is "yes") and the - local device will advertise all the supported speeds. In Mbit/s, ie 100 == - 100Mbit/s. Must be set together with the "duplex" property when non-zero. - Before specifying a speed value be sure your device supports it.""" + specified speed. If "auto-negotiate" is "yes" the specified speed + will be the only one advertised during link negotiation: this works + only for BASE-T 802.3 specifications and is useful for enforcing + gigabit speeds, as in this case link negotiation is mandatory. If + the value is unset (0, the default), the link configuration will be + either skipped (if "auto-negotiate" is "no", the default) or will be + auto-negotiated (if "auto-negotiate" is "yes") and the local device + will advertise all the supported speeds. In Mbit/s, ie 100 == + 100Mbit/s. Must be set together with the "duplex" property when non- + zero. Before specifying a speed value be sure your device supports + it.""" wake_on_lan: Optional[int] = field( - metadata={'dbus_name': 'wake-on-lan', 'dbus_type': 'u'}, - default=1, + metadata={ + 'dbus_name': 'wake-on-lan', + 'dbus_type': 'u', + }, + default=None, ) - """The NMSettingWiredWakeOnLan options to enable. Not all devices support all - options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), + """The NMSettingWiredWakeOnLan options to enable. Not all devices support + all options. May be any combination of + NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), - NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC - (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to - use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to - disable management of Wake-on-LAN in NetworkManager).""" + NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), + NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values + NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) + and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable + management of Wake-on-LAN in NetworkManager).""" wake_on_lan_password: Optional[str] = field( - metadata={'dbus_name': 'wake-on-lan-password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'wake-on-lan-password', + 'dbus_type': 's', + }, default=None, ) """If specified, the password used with magic-packet-based Wake-on-LAN, - represented as an Ethernet MAC address. If NULL, no password will be - required.""" + represented as an Ethernet MAC address. If NULL, no password will + be required.""" diff --git a/sdbus_async/networkmanager/settings/ethtool.py b/sdbus_async/networkmanager/settings/ethtool.py new file mode 100644 index 0000000..739e67d --- /dev/null +++ b/sdbus_async/networkmanager/settings/ethtool.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Optional +from .base import NetworkManagerSettingsMixin + + +@dataclass +class EthtoolSettings(NetworkManagerSettingsMixin): + """Ethtool Ethernet Settings""" + diff --git a/sdbus_async/networkmanager/settings/generic.py b/sdbus_async/networkmanager/settings/generic.py new file mode 100644 index 0000000..b633cd5 --- /dev/null +++ b/sdbus_async/networkmanager/settings/generic.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Optional +from .base import NetworkManagerSettingsMixin + + +@dataclass +class GenericSettings(NetworkManagerSettingsMixin): + """Generic Link Settings""" + diff --git a/sdbus_async/networkmanager/settings/gsm.py b/sdbus_async/networkmanager/settings/gsm.py index 6353163..6c49fb1 100644 --- a/sdbus_async/networkmanager/settings/gsm.py +++ b/sdbus_async/networkmanager/settings/gsm.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,98 +12,144 @@ class GsmSettings(NetworkManagerSettingsMixin): """GSM-based Mobile Broadband Settings""" apn: Optional[str] = field( - metadata={'dbus_name': 'apn', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'apn', + 'dbus_type': 's', + }, default=None, ) - """The GPRS Access Point Name specifying the APN used when establishing a data - session with the GSM-based network. The APN often determines how the user - will be billed for their network usage and whether the user has access to the - Internet or just a provider-specific walled-garden, so it is important to use - the correct APN for the user's mobile broadband plan. The APN may only be - composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.""" + """The GPRS Access Point Name specifying the APN used when establishing a + data session with the GSM-based network. The APN often determines + how the user will be billed for their network usage and whether the + user has access to the Internet or just a provider-specific walled- + garden, so it is important to use the correct APN for the user's + mobile broadband plan. The APN may only be composed of the + characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9.""" auto_config: Optional[bool] = field( - metadata={'dbus_name': 'auto-config', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'auto-config', + 'dbus_type': 'b', + }, + default=None, ) - """When TRUE, the settings such as APN, username, or password will default to - values that match the network the modem will register to in the Mobile - Broadband Provider database.""" + """When TRUE, the settings such as APN, username, or password will default + to values that match the network the modem will register to in the + Mobile Broadband Provider database.""" device_id: Optional[str] = field( - metadata={'dbus_name': 'device-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'device-id', + 'dbus_type': 's', + }, default=None, ) """The device unique identifier (as given by the WWAN management service) - which this connection applies to. If given, the connection will only apply to - the specified device.""" + which this connection applies to. If given, the connection will + only apply to the specified device.""" home_only: Optional[bool] = field( - metadata={'dbus_name': 'home-only', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'home-only', + 'dbus_type': 'b', + }, + default=None, ) """When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made.""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.""" network_id: Optional[str] = field( - metadata={'dbus_name': 'network-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'network-id', + 'dbus_type': 's', + }, default=None, ) """The Network ID (GSM LAI format, ie MCC-MNC) to force specific network - registration. If the Network ID is specified, NetworkManager will attempt to - force the device to register only on the specified network. This can be used - to ensure that the device does not roam when direct roaming control of the - device is not otherwise possible.""" + registration. If the Network ID is specified, NetworkManager will + attempt to force the device to register only on the specified + network. This can be used to ensure that the device does not roam + when direct roaming control of the device is not otherwise possible.""" number: Optional[str] = field( - metadata={'dbus_name': 'number', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'number', + 'dbus_type': 's', + }, default=None, ) """Legacy setting that used to help establishing PPP data sessions for GSM- - based modems. Deprecated: 1""" + based modems.""" password: Optional[str] = field( - metadata={'dbus_name': 'password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'password', + 'dbus_type': 's', + }, default=None, ) """The password used to authenticate with the network, if required. Many - providers do not require a password, or accept any password. But if a - password is required, it is specified here.""" + providers do not require a password, or accept any password. But if + a password is required, it is specified here.""" password_flags: Optional[int] = field( - metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'password-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "password" property.""" pin: Optional[str] = field( - metadata={'dbus_name': 'pin', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'pin', + 'dbus_type': 's', + }, default=None, ) """If the SIM is locked with a PIN it must be unlocked before any other - operations are requested. Specify the PIN here to allow operation of the - device.""" + operations are requested. Specify the PIN here to allow operation + of the device.""" pin_flags: Optional[int] = field( - metadata={'dbus_name': 'pin-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'pin-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "pin" property.""" sim_id: Optional[str] = field( - metadata={'dbus_name': 'sim-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'sim-id', + 'dbus_type': 's', + }, default=None, ) """The SIM card unique identifier (as given by the WWAN management service) - which this connection applies to. If given, the connection will apply to any - device also allowed by "device-id" which contains a SIM card matching the - given identifier.""" + which this connection applies to. If given, the connection will + apply to any device also allowed by "device-id" which contains a SIM + card matching the given identifier.""" sim_operator_id: Optional[str] = field( - metadata={'dbus_name': 'sim-operator-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'sim-operator-id', + 'dbus_type': 's', + }, default=None, ) - """A MCC/MNC string like "310260" or "21601" identifying the specific mobile - network operator which this connection applies to. If given, the connection - will apply to any device also allowed by "device-id" and "sim-id" which - contains a SIM card provisioned by the given operator.""" + """A MCC/MNC string like "310260" or "21601" identifying the specific + mobile network operator which this connection applies to. If given, + the connection will apply to any device also allowed by "device-id" + and "sim-id" which contains a SIM card provisioned by the given + operator.""" username: Optional[str] = field( - metadata={'dbus_name': 'username', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'username', + 'dbus_type': 's', + }, default=None, ) """The username used to authenticate with the network, if required. Many - providers do not require a username, or accept any username. But if a - username is required, it is specified here.""" + providers do not require a username, or accept any username. But if + a username is required, it is specified here.""" diff --git a/sdbus_async/networkmanager/settings/hostname.py b/sdbus_async/networkmanager/settings/hostname.py index a60d20d..f4e8b77 100644 --- a/sdbus_async/networkmanager/settings/hostname.py +++ b/sdbus_async/networkmanager/settings/hostname.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,45 +12,69 @@ class HostnameSettings(NetworkManagerSettingsMixin): """Hostname settings""" from_dhcp: Optional[int] = field( - metadata={'dbus_name': 'from-dhcp', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'from-dhcp', + 'dbus_type': 'i', + }, default=None, ) - """Whether the system hostname can be determined from DHCP on this connection. - When set to NM_TERNARY_DEFAULT (-1), the value from global configuration is - used. If the property doesn't have a value in the global configuration, - NetworkManager assumes the value to be NM_TERNARY_TRUE (1).""" + """Whether the system hostname can be determined from DHCP on this + connection. + + When set to NM_TERNARY_DEFAULT (-1), the value from global + configuration is used. If the property doesn't have a value in the + global configuration, NetworkManager assumes the value to be + NM_TERNARY_TRUE (1).""" from_dns_lookup: Optional[int] = field( - metadata={'dbus_name': 'from-dns-lookup', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'from-dns-lookup', + 'dbus_type': 'i', + }, default=None, ) """Whether the system hostname can be determined from reverse DNS lookup of - addresses on this device. When set to NM_TERNARY_DEFAULT (-1), the value from - global configuration is used. If the property doesn't have a value in the - global configuration, NetworkManager assumes the value to be NM_TERNARY_TRUE - (1).""" + addresses on this device. + + When set to NM_TERNARY_DEFAULT (-1), the value from global + configuration is used. If the property doesn't have a value in the + global configuration, NetworkManager assumes the value to be + NM_TERNARY_TRUE (1).""" only_from_default: Optional[int] = field( - metadata={'dbus_name': 'only-from-default', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'only-from-default', + 'dbus_type': 'i', + }, default=None, ) - """If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the hostname - via DHCPv4/DHCPv6 or reverse DNS lookup on this device only when the device - has the default route for the given address family (IPv4/IPv6). If set to - NM_TERNARY_FALSE (0), the hostname can be set from this device even if it - doesn't have the default route. When set to NM_TERNARY_DEFAULT (-1), the value - from global configuration is used. If the property doesn't have a value in the - global configuration, NetworkManager assumes the value to be NM_TERNARY_FALSE - (0).""" + """If set to NM_TERNARY_TRUE (1), NetworkManager attempts to get the + hostname via DHCPv4/DHCPv6 or reverse DNS lookup on this device only + when the device has the default route for the given address family + (IPv4/IPv6). + + If set to NM_TERNARY_FALSE (0), the hostname can be set from this + device even if it doesn't have the default route. + + When set to NM_TERNARY_DEFAULT (-1), the value from global + configuration is used. If the property doesn't have a value in the + global configuration, NetworkManager assumes the value to be + NM_TERNARY_FALSE (0).""" priority: Optional[int] = field( - metadata={'dbus_name': 'priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'priority', + 'dbus_type': 'i', + }, default=None, ) - """The relative priority of this connection to determine the system hostname. - A lower numerical value is better (higher priority). A connection with higher - priority is considered before connections with lower priority. If the value is - zero, it can be overridden by a global value from NetworkManager - configuration. If the property doesn't have a value in the global - configuration, the value is assumed to be 100. Negative values have the - special effect of excluding other connections with a greater numerical - priority value; so in presence of at least one negative priority, only - connections with the lowest priority value will be used to determine the - hostname.""" + """The relative priority of this connection to determine the system + hostname. A lower numerical value is better (higher priority). A + connection with higher priority is considered before connections + with lower priority. + + If the value is zero, it can be overridden by a global value from + NetworkManager configuration. If the property doesn't have a value + in the global configuration, the value is assumed to be 100. + + Negative values have the special effect of excluding other + connections with a greater numerical priority value; so in presence + of at least one negative priority, only connections with the lowest + priority value will be used to determine the hostname.""" diff --git a/sdbus_async/networkmanager/settings/ieee802_1x.py b/sdbus_async/networkmanager/settings/ieee802_1x.py deleted file mode 100644 index a0b36c4..0000000 --- a/sdbus_async/networkmanager/settings/ieee802_1x.py +++ /dev/null @@ -1,414 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, -# if possible, please make changes by also updating the script. -from __future__ import annotations -from dataclasses import dataclass, field -from typing import List, Optional -from .base import NetworkManagerSettingsMixin - - -@dataclass -class Ieee8021XSettings(NetworkManagerSettingsMixin): - """IEEE 802.1x Authentication Settings""" - - altsubject_matches: Optional[List[str]] = field( - metadata={'dbus_name': 'altsubject-matches', 'dbus_type': 'as'}, - default=None, - ) - """List of strings to be matched against the altSubjectName of the certificate - presented by the authentication server. If the list is empty, no verification - of the server certificate's altSubjectName is performed.""" - anonymous_identity: Optional[str] = field( - metadata={'dbus_name': 'anonymous-identity', 'dbus_type': 's'}, - default=None, - ) - """Anonymous identity string for EAP authentication methods. Used as the - unencrypted identity with EAP types that support different tunneled identity - like EAP-TTLS.""" - auth_timeout: Optional[int] = field( - metadata={'dbus_name': 'auth-timeout', 'dbus_type': 'i'}, - default=None, - ) - """A timeout for the authentication. Zero means the global default; if the - global default is not set, the authentication timeout is 25 seconds.""" - ca_cert: Optional[bytes] = field( - metadata={'dbus_name': 'ca-cert', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the CA certificate if used by the EAP method specified in the - "eap" property. Certificate data is specified using a "scheme"; three are - currently supported: blob, path and pkcs#11 URL. When using the blob scheme - this property should be set to the certificate's DER encoded data. When using - the path scheme, this property should be set to the full UTF-8 encoded path of - the certificate, prefixed with the string "file://" and ending with a - terminating NUL byte. This property can be unset even if the EAP method - supports CA certificates, but this allows man-in-the-middle attacks and is NOT - recommended. Note that enabling NMSetting8021x:system-ca-certs will override - this setting to use the built-in path, if the built-in path is not a - directory.""" - ca_cert_password: Optional[str] = field( - metadata={'dbus_name': 'ca-cert-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to access the CA certificate stored in "ca-cert" - property. Only makes sense if the certificate is stored on a PKCS#11 token - that requires a login.""" - ca_cert_password_flags: Optional[int] = field( - metadata={'dbus_name': 'ca-cert-password-flags', 'dbus_type': 'i'}, - default=None, - ) - ca_path: Optional[str] = field( - metadata={'dbus_name': 'ca-path', 'dbus_type': 's'}, - default=None, - ) - """UTF-8 encoded path to a directory containing PEM or DER formatted - certificates to be added to the verification chain in addition to the - certificate specified in the "ca-cert" property. If NMSetting8021x:system-ca- - certs is enabled and the built-in CA path is an existing directory, then this - setting is ignored.""" - client_cert: Optional[bytes] = field( - metadata={'dbus_name': 'client-cert', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the client certificate if used by the EAP method specified in the - "eap" property. Certificate data is specified using a "scheme"; two are - currently supported: blob and path. When using the blob scheme (which is - backwards compatible with NM 0.7.x) this property should be set to the - certificate's DER encoded data. When using the path scheme, this property - should be set to the full UTF-8 encoded path of the certificate, prefixed with - the string "file://" and ending with a terminating NUL byte.""" - client_cert_password: Optional[str] = field( - metadata={'dbus_name': 'client-cert-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to access the client certificate stored in "client-cert" - property. Only makes sense if the certificate is stored on a PKCS#11 token - that requires a login.""" - client_cert_password_flags: Optional[int] = field( - metadata={'dbus_name': 'client-cert-password-flags', 'dbus_type': 'i'}, - default=None, - ) - domain_match: Optional[str] = field( - metadata={'dbus_name': 'domain-match', 'dbus_type': 's'}, - default=None, - ) - """Constraint for server domain name. If set, this list of FQDNs is used as a - match requirement for dNSName element(s) of the certificate presented by the - authentication server. If a matching dNSName is found, this constraint is - met. If no dNSName values are present, this constraint is matched against - SubjectName CN using the same comparison. Multiple valid FQDNs can be passed - as a ";" delimited list.""" - domain_suffix_match: Optional[str] = field( - metadata={'dbus_name': 'domain-suffix-match', 'dbus_type': 's'}, - default=None, - ) - """Constraint for server domain name. If set, this FQDN is used as a suffix - match requirement for dNSName element(s) of the certificate presented by the - authentication server. If a matching dNSName is found, this constraint is - met. If no dNSName values are present, this constraint is matched against - SubjectName CN using same suffix match comparison. Since version 1.24, - multiple valid FQDNs can be passed as a ";" delimited list.""" - eap: Optional[List[str]] = field( - metadata={'dbus_name': 'eap', 'dbus_type': 'as'}, - default=None, - ) - """The allowed EAP method to be used when authenticating to the network with - 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and - "fast". Each method requires different configuration using the properties of - this setting; refer to wpa_supplicant documentation for the allowed - combinations.""" - identity: Optional[str] = field( - metadata={'dbus_name': 'identity', 'dbus_type': 's'}, - default=None, - ) - """Identity string for EAP authentication methods. Often the user's user or - login name.""" - optional: Optional[bool] = field( - metadata={'dbus_name': 'optional', 'dbus_type': 'b'}, - default=False, - ) - """Whether the 802.1X authentication is optional. If TRUE, the activation will - continue even after a timeout or an authentication failure. Setting the - property to TRUE is currently allowed only for Ethernet connections. If set to - FALSE, the activation can continue only after a successful authentication.""" - pac_file: Optional[str] = field( - metadata={'dbus_name': 'pac-file', 'dbus_type': 's'}, - default=None, - ) - password: Optional[str] = field( - metadata={'dbus_name': 'password', 'dbus_type': 's'}, - default=None, - ) - """UTF-8 encoded password used for EAP authentication methods. If both the - "password" property and the "password-raw" property are specified, "password" - is preferred.""" - password_flags: Optional[int] = field( - metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, - default=None, - ) - password_raw: Optional[bytes] = field( - metadata={'dbus_name': 'password-raw', 'dbus_type': 'ay'}, - default=None, - ) - """Password used for EAP authentication methods, given as a byte array to - allow passwords in other encodings than UTF-8 to be used. If both the - "password" property and the "password-raw" property are specified, "password" - is preferred.""" - password_raw_flags: Optional[int] = field( - metadata={'dbus_name': 'password-raw-flags', 'dbus_type': 'i'}, - default=None, - ) - phase1_auth_flags: Optional[int] = field( - metadata={'dbus_name': 'phase1-auth-flags', 'dbus_type': 'u'}, - default=None, - ) - """Specifies authentication flags to use in "phase 1" outer authentication - using NMSetting8021xAuthFlags options. The individual TLS versions can be - explicitly disabled. If a certain TLS disable flag is not set, it is up to the - supplicant to allow or forbid it. The TLS options map to tls_disable_tlsv1_x - settings. See the wpa_supplicant documentation for more details.""" - phase1_fast_provisioning: Optional[str] = field( - metadata={'dbus_name': 'phase1-fast-provisioning', 'dbus_type': 's'}, - default=None, - ) - """Enables or disables in-line provisioning of EAP-FAST credentials when FAST - is specified as the EAP method in the "eap" property. Recognized values are - "0" (disabled), "1" (allow unauthenticated provisioning), "2" (allow - authenticated provisioning), and "3" (allow both authenticated and - unauthenticated provisioning). See the wpa_supplicant documentation for more - details.""" - phase1_peaplabel: Optional[str] = field( - metadata={'dbus_name': 'phase1-peaplabel', 'dbus_type': 's'}, - default=None, - ) - """Forces use of the new PEAP label during key derivation. Some RADIUS - servers may require forcing the new PEAP label to interoperate with PEAPv1. - Set to "1" to force use of the new PEAP label. See the wpa_supplicant - documentation for more details.""" - phase1_peapver: Optional[str] = field( - metadata={'dbus_name': 'phase1-peapver', 'dbus_type': 's'}, - default=None, - ) - """Forces which PEAP version is used when PEAP is set as the EAP method in the - "eap" property. When unset, the version reported by the server will be used. - Sometimes when using older RADIUS servers, it is necessary to force the client - to use a particular PEAP version. To do so, this property may be set to "0" - or "1" to force that specific PEAP version.""" - phase2_altsubject_matches: Optional[List[str]] = field( - metadata={'dbus_name': 'phase2-altsubject-matches', 'dbus_type': 'as'}, - default=None, - ) - """List of strings to be matched against the altSubjectName of the certificate - presented by the authentication server during the inner "phase 2" - authentication. If the list is empty, no verification of the server - certificate's altSubjectName is performed.""" - phase2_auth: Optional[str] = field( - metadata={'dbus_name': 'phase2-auth', 'dbus_type': 's'}, - default=None, - ) - """Specifies the allowed "phase 2" inner authentication method when an EAP - method that uses an inner TLS tunnel is specified in the "eap" property. For - TTLS this property selects one of the supported non-EAP inner methods: "pap", - "chap", "mschap", "mschapv2" while "phase2-autheap" selects an EAP inner - method. For PEAP this selects an inner EAP method, one of: "gtc", "otp", - "md5" and "tls". Each "phase 2" inner method requires specific parameters for - successful authentication; see the wpa_supplicant documentation for more - details. Both "phase2-auth" and "phase2-autheap" cannot be specified.""" - phase2_autheap: Optional[str] = field( - metadata={'dbus_name': 'phase2-autheap', 'dbus_type': 's'}, - default=None, - ) - """Specifies the allowed "phase 2" inner EAP-based authentication method when - TTLS is specified in the "eap" property. Recognized EAP-based "phase 2" - methods are "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner - method requires specific parameters for successful authentication; see the - wpa_supplicant documentation for more details.""" - phase2_ca_cert: Optional[bytes] = field( - metadata={'dbus_name': 'phase2-ca-cert', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the "phase 2" CA certificate if used by the EAP method specified - in the "phase2-auth" or "phase2-autheap" properties. Certificate data is - specified using a "scheme"; three are currently supported: blob, path and - pkcs#11 URL. When using the blob scheme this property should be set to the - certificate's DER encoded data. When using the path scheme, this property - should be set to the full UTF-8 encoded path of the certificate, prefixed with - the string "file://" and ending with a terminating NUL byte. This property can - be unset even if the EAP method supports CA certificates, but this allows man- - in-the-middle attacks and is NOT recommended. Note that enabling - NMSetting8021x:system-ca-certs will override this setting to use the built-in - path, if the built-in path is not a directory.""" - phase2_ca_cert_password: Optional[str] = field( - metadata={'dbus_name': 'phase2-ca-cert-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to access the "phase2" CA certificate stored in - "phase2-ca-cert" property. Only makes sense if the certificate is stored on a - PKCS#11 token that requires a login.""" - phase2_ca_cert_password_flags: Optional[int] = field( - metadata={'dbus_name': 'phase2-ca-cert-password-flags', - 'dbus_type': 'i'}, - default=None, - ) - phase2_ca_path: Optional[str] = field( - metadata={'dbus_name': 'phase2-ca-path', 'dbus_type': 's'}, - default=None, - ) - """UTF-8 encoded path to a directory containing PEM or DER formatted - certificates to be added to the verification chain in addition to the - certificate specified in the "phase2-ca-cert" property. If - NMSetting8021x:system-ca-certs is enabled and the built-in CA path is an - existing directory, then this setting is ignored.""" - phase2_client_cert: Optional[bytes] = field( - metadata={'dbus_name': 'phase2-client-cert', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the "phase 2" client certificate if used by the EAP method - specified in the "phase2-auth" or "phase2-autheap" properties. Certificate - data is specified using a "scheme"; two are currently supported: blob and - path. When using the blob scheme (which is backwards compatible with NM 0.7.x) - this property should be set to the certificate's DER encoded data. When using - the path scheme, this property should be set to the full UTF-8 encoded path of - the certificate, prefixed with the string "file://" and ending with a - terminating NUL byte. This property can be unset even if the EAP method - supports CA certificates, but this allows man-in-the-middle attacks and is NOT - recommended.""" - phase2_client_cert_password: Optional[str] = field( - metadata={'dbus_name': 'phase2-client-cert-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to access the "phase2" client certificate stored in - "phase2-client-cert" property. Only makes sense if the certificate is stored - on a PKCS#11 token that requires a login.""" - phase2_client_cert_password_flags: Optional[int] = field( - metadata={'dbus_name': 'phase2-client-cert-password-flags', - 'dbus_type': 'i'}, - default=None, - ) - """Flags indicating how to handle the "phase2-client-cert-password" - property.""" - phase2_domain_match: Optional[str] = field( - metadata={'dbus_name': 'phase2-domain-match', 'dbus_type': 's'}, - default=None, - ) - """Constraint for server domain name. If set, this list of FQDNs is used as a - match requirement for dNSName element(s) of the certificate presented by the - authentication server during the inner "phase 2" authentication. If a matching - dNSName is found, this constraint is met. If no dNSName values are present, - this constraint is matched against SubjectName CN using the same comparison. - Multiple valid FQDNs can be passed as a ";" delimited list.""" - phase2_domain_suffix_match: Optional[str] = field( - metadata={'dbus_name': 'phase2-domain-suffix-match', 'dbus_type': 's'}, - default=None, - ) - """Constraint for server domain name. If set, this FQDN is used as a suffix - match requirement for dNSName element(s) of the certificate presented by the - authentication server during the inner "phase 2" authentication. If a - matching dNSName is found, this constraint is met. If no dNSName values are - present, this constraint is matched against SubjectName CN using same suffix - match comparison. Since version 1.24, multiple valid FQDNs can be passed as a - ";" delimited list.""" - phase2_private_key: Optional[bytes] = field( - metadata={'dbus_name': 'phase2-private-key', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the "phase 2" inner private key when the "phase2-auth" or - "phase2-autheap" property is set to "tls". Key data is specified using a - "scheme"; two are currently supported: blob and path. When using the blob - scheme and private keys, this property should be set to the key's encrypted - PEM encoded data. When using private keys with the path scheme, this property - should be set to the full UTF-8 encoded path of the key, prefixed with the - string "file://" and ending with a terminating NUL byte. When using PKCS#12 - format private keys and the blob scheme, this property should be set to the - PKCS#12 data and the "phase2-private-key-password" property must be set to - password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 - files and the path scheme, this property should be set to the full UTF-8 - encoded path of the key, prefixed with the string "file://" and ending with a - terminating NUL byte, and as with the blob scheme the "phase2-private-key- - password" property must be set to the password used to decode the PKCS#12 - private key and certificate.""" - phase2_private_key_password: Optional[str] = field( - metadata={'dbus_name': 'phase2-private-key-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to decrypt the "phase 2" private key specified in the - "phase2-private-key" property when the private key either uses the path - scheme, or is a PKCS#12 format key.""" - phase2_private_key_password_flags: Optional[int] = field( - metadata={'dbus_name': 'phase2-private-key-password-flags', - 'dbus_type': 'i'}, - default=None, - ) - """Flags indicating how to handle the "phase2-private-key-password" - property.""" - phase2_subject_match: Optional[str] = field( - metadata={'dbus_name': 'phase2-subject-match', 'dbus_type': 's'}, - default=None, - ) - """Substring to be matched against the subject of the certificate presented by - the authentication server during the inner "phase 2" authentication. When - unset, no verification of the authentication server certificate's subject is - performed. This property provides little security, if any, and its use is - deprecated in favor of NMSetting8021x:phase2-domain-suffix-match.""" - pin: Optional[str] = field( - metadata={'dbus_name': 'pin', 'dbus_type': 's'}, - default=None, - ) - pin_flags: Optional[int] = field( - metadata={'dbus_name': 'pin-flags', 'dbus_type': 'i'}, - default=None, - ) - private_key: Optional[bytes] = field( - metadata={'dbus_name': 'private-key', 'dbus_type': 'ay'}, - default=None, - ) - """Contains the private key when the "eap" property is set to "tls". Key data - is specified using a "scheme"; two are currently supported: blob and path. - When using the blob scheme and private keys, this property should be set to - the key's encrypted PEM encoded data. When using private keys with the path - scheme, this property should be set to the full UTF-8 encoded path of the key, - prefixed with the string "file://" and ending with a terminating NUL byte. - When using PKCS#12 format private keys and the blob scheme, this property - should be set to the PKCS#12 data and the "private-key-password" property must - be set to password used to decrypt the PKCS#12 certificate and key. When using - PKCS#12 files and the path scheme, this property should be set to the full - UTF-8 encoded path of the key, prefixed with the string "file://" and ending - with a terminating NUL byte, and as with the blob scheme the "private-key- - password" property must be set to the password used to decode the PKCS#12 - private key and certificate. WARNING: "private-key" is not a "secret" - property, and thus unencrypted private key data using the BLOB scheme may be - readable by unprivileged users. Private keys should always be encrypted with - a private key password to prevent unauthorized access to unencrypted private - key data.""" - private_key_password: Optional[str] = field( - metadata={'dbus_name': 'private-key-password', 'dbus_type': 's'}, - default=None, - ) - """The password used to decrypt the private key specified in the "private-key" - property when the private key either uses the path scheme, or if the private - key is a PKCS#12 format key.""" - private_key_password_flags: Optional[int] = field( - metadata={'dbus_name': 'private-key-password-flags', 'dbus_type': 'i'}, - default=None, - ) - subject_match: Optional[str] = field( - metadata={'dbus_name': 'subject-match', 'dbus_type': 's'}, - default=None, - ) - """Substring to be matched against the subject of the certificate presented by - the authentication server. When unset, no verification of the authentication - server certificate's subject is performed. This property provides little - security, if any, and its use is deprecated in favor of NMSetting8021x:domain- - suffix-match.""" - system_ca_certs: Optional[bool] = field( - metadata={'dbus_name': 'system-ca-certs', 'dbus_type': 'b'}, - default=False, - ) - """When TRUE, overrides the "ca-path" and "phase2-ca-path" properties using - the system CA directory specified at configure time with the --system-ca-path - switch. The certificates in this directory are added to the verification - chain in addition to any certificates specified by the "ca-cert" and - "phase2-ca-cert" properties. If the path provided with --system-ca-path is - rather a file name (bundle of trusted CA certificates), it overrides "ca-cert" - and "phase2-ca-cert" properties instead (sets ca_cert/ca_cert2 options for - wpa_supplicant).""" diff --git a/sdbus_async/networkmanager/settings/infiniband.py b/sdbus_async/networkmanager/settings/infiniband.py index 2317cf8..a144095 100644 --- a/sdbus_async/networkmanager/settings/infiniband.py +++ b/sdbus_async/networkmanager/settings/infiniband.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,33 +12,50 @@ class InfinibandSettings(NetworkManagerSettingsMixin): """Infiniband Settings""" mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 'ay', + }, default=None, ) """If specified, this connection will only apply to the IPoIB device whose - permanent MAC address matches. This property does not change the MAC address - of the device (i.e. MAC spoofing).""" + permanent MAC address matches. This property does not change the MAC + address of the device (i.e. MAC spoofing).""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames.""" p_key: Optional[int] = field( - metadata={'dbus_name': 'p-key', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'p-key', + 'dbus_type': 'i', + }, default=None, ) - """The InfiniBand P_Key to use for this device. A value of -1 means to use the - default P_Key (aka "the P_Key at index 0"). Otherwise, it is a 16-bit unsigned - integer, whose high bit is set if it is a "full membership" P_Key.""" + """The InfiniBand P_Key to use for this device. A value of -1 means to use + the default P_Key (aka "the P_Key at index 0"). Otherwise, it is a + 16-bit unsigned integer, whose high bit is set if it is a "full + membership" P_Key.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) - """The interface name of the parent device of this device. Normally NULL, but - if the "p_key" property is set, then you must specify the base device by - setting either this property or "mac-address".""" + """The interface name of the parent device of this device. Normally NULL, + but if the "p_key" property is set, then you must specify the base + device by setting either this property or "mac-address".""" transport_mode: Optional[str] = field( - metadata={'dbus_name': 'transport-mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'transport-mode', + 'dbus_type': 's', + }, default=None, ) + """The IP-over-InfiniBand transport mode. Either "datagram" or "connected".""" diff --git a/sdbus_async/networkmanager/settings/ip_tunnel.py b/sdbus_async/networkmanager/settings/ip_tunnel.py index 45a05d7..da2f0ad 100644 --- a/sdbus_async/networkmanager/settings/ip_tunnel.py +++ b/sdbus_async/networkmanager/settings/ip_tunnel.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,83 +12,124 @@ class IpTunnelSettings(NetworkManagerSettingsMixin): """IP Tunneling Settings""" encapsulation_limit: Optional[int] = field( - metadata={'dbus_name': 'encapsulation-limit', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'encapsulation-limit', + 'dbus_type': 'u', + }, default=None, ) - """How many additional levels of encapsulation are permitted to be prepended - to packets. This property applies only to IPv6 tunnels.""" + """How many additional levels of encapsulation are permitted to be + prepended to packets. This property applies only to IPv6 tunnels.""" flags: Optional[int] = field( - metadata={'dbus_name': 'flags', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'flags', + 'dbus_type': 'u', + }, default=None, ) """Tunnel flags. Currently, the following values are supported: NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT (0x1), NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS (0x2), - NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV - (0x8), NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), - NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only for IPv6 - tunnels.""" + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL (0x4), + NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV (0x8), + NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY (0x10), + NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK (0x20). They are valid only + for IPv6 tunnels.""" flow_label: Optional[int] = field( - metadata={'dbus_name': 'flow-label', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'flow-label', + 'dbus_type': 'u', + }, default=None, ) - """The flow label to assign to tunnel packets. This property applies only to - IPv6 tunnels.""" + """The flow label to assign to tunnel packets. This property applies only + to IPv6 tunnels.""" input_key: Optional[str] = field( - metadata={'dbus_name': 'input-key', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'input-key', + 'dbus_type': 's', + }, default=None, ) """The key used for tunnel input packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.""" local: Optional[str] = field( - metadata={'dbus_name': 'local', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'local', + 'dbus_type': 's', + }, default=None, ) - """The local endpoint of the tunnel; the value can be empty, otherwise it must - contain an IPv4 or IPv6 address.""" + """The local endpoint of the tunnel; the value can be empty, otherwise it + must contain an IPv4 or IPv6 address.""" mode: Optional[int] = field( - metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mode', + 'dbus_type': 'u', + }, default=None, ) """The tunneling mode, for example NM_IP_TUNNEL_MODE_IPIP (1) or NM_IP_TUNNEL_MODE_GRE (2).""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments.""" output_key: Optional[str] = field( - metadata={'dbus_name': 'output-key', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'output-key', + 'dbus_type': 's', + }, default=None, ) """The key used for tunnel output packets; the property is valid only for certain tunnel modes (GRE, IP6GRE). If empty, no key is used.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) - """If given, specifies the parent interface name or parent connection UUID the - new device will be bound to so that tunneled packets will only be routed via - that interface.""" + """If given, specifies the parent interface name or parent connection UUID + the new device will be bound to so that tunneled packets will only + be routed via that interface.""" path_mtu_discovery: Optional[bool] = field( - metadata={'dbus_name': 'path-mtu-discovery', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'path-mtu-discovery', + 'dbus_type': 'b', + }, + default=None, ) + """Whether to enable Path MTU Discovery on this tunnel.""" remote: Optional[str] = field( - metadata={'dbus_name': 'remote', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'remote', + 'dbus_type': 's', + }, default=None, ) - """The remote endpoint of the tunnel; the value must contain an IPv4 or IPv6 - address.""" + """The remote endpoint of the tunnel; the value must contain an IPv4 or + IPv6 address.""" tos: Optional[int] = field( - metadata={'dbus_name': 'tos', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'tos', + 'dbus_type': 'u', + }, default=None, ) """The type of service (IPv4) or traffic class (IPv6) field to be set on tunneled packets.""" ttl: Optional[int] = field( - metadata={'dbus_name': 'ttl', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'ttl', + 'dbus_type': 'u', + }, default=None, ) """The TTL to assign to tunneled packets. 0 is a special value meaning that diff --git a/sdbus_async/networkmanager/settings/ipv4.py b/sdbus_async/networkmanager/settings/ipv4.py index 3093d42..b2b91f2 100644 --- a/sdbus_async/networkmanager/settings/ipv4.py +++ b/sdbus_async/networkmanager/settings/ipv4.py @@ -1,11 +1,11 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin -from .datatypes import AddressData, RouteData +from .datatypes import AddressData, RouteData, RoutingRules @dataclass @@ -13,327 +13,533 @@ class Ipv4Settings(NetworkManagerSettingsMixin): """IPv4 Settings""" address_data: Optional[List[AddressData]] = field( - metadata={'dbus_name': 'address-data', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': AddressData}, + metadata={ + 'dbus_name': 'address-data', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': AddressData, + }, default=None, ) + """Array of IPv4 addresses. Each address dictionary contains at least + 'address' and 'prefix' entries, containing the IP address as a + string, and the prefix length as a uint32. Additional attributes may + also exist on some addresses.""" addresses: Optional[List[List[int]]] = field( - metadata={'dbus_name': 'addresses', 'dbus_type': 'aau'}, + metadata={ + 'dbus_name': 'addresses', + 'dbus_type': 'aau', + }, default=None, ) - """Deprecated in favor of the 'address-data' and 'gateway' properties, but - this can be used for backward-compatibility with older daemons. Note that if - you send this property the daemon will ignore 'address-data' and 'gateway'. - Array of IPv4 address structures. Each IPv4 address structure is composed of - 3 32-bit values; the first being the IPv4 address (network byte order), the - second the prefix (1 - 32), and last the IPv4 gateway (network byte order). - The gateway may be left as 0 if no gateway exists for that subnet.""" + """Array of IP addresses.""" dad_timeout: Optional[int] = field( - metadata={'dbus_name': 'dad-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dad-timeout', + 'dbus_type': 'i', + }, default=None, ) """Timeout in milliseconds used to check for the presence of duplicate IP - addresses on the network. If an address conflict is detected, the activation - will fail. A zero value means that no duplicate address detection is - performed, -1 means the default value (either configuration ipvx.dad-timeout - override or zero). A value greater than zero is a timeout in milliseconds. + addresses on the network. If an address conflict is detected, the + activation will fail. A zero value means that no duplicate address + detection is performed, -1 means the default value (either + configuration ipvx.dad-timeout override or zero). A value greater + than zero is a timeout in milliseconds. + The property is currently implemented only for IPv4.""" dhcp_client_id: Optional[str] = field( - metadata={'dbus_name': 'dhcp-client-id', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-client-id', + 'dbus_type': 's', + }, default=None, ) """A string sent to the DHCP server to identify the local machine which the - DHCP server may use to customize the DHCP lease and options. When the property - is a hex string ('aa:bb:cc') it is interpreted as a binary client ID, in which - case the first byte is assumed to be the 'type' field as per RFC 2132 section - 9.14 and the remaining bytes may be an hardware address (e.g. - '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet ARP type and the rest is a MAC - address). If the property is not a hex string it is considered as a non- - hardware-address client ID and the 'type' field is set to 0. The special - values "mac" and "perm-mac" are supported, which use the current or permanent - MAC address of the device to generate a client identifier with type ethernet - (01). Currently, these options only work for ethernet type of links. The - special value "ipv6-duid" uses the DUID from "ipv6.dhcp-duid" property as an - RFC4361-compliant client identifier. As IAID it uses "ipv4.dhcp-iaid" and - falls back to "ipv6.dhcp-iaid" if unset. The special value "duid" generates a - RFC4361-compliant client identifier based on "ipv4.dhcp-iaid" and uses a DUID - generated by hashing /etc/machine-id. The special value "stable" is supported - to generate a type 0 client identifier based on the stable-id (see - connection.stable-id) and a per-host key. If you set the stable-id, you may - want to include the "${DEVICE}" or "${MAC}" specifier to get a per-device key. - If unset, a globally configured default is used. If still unset, the default - depends on the DHCP plugin.""" + DHCP server may use to customize the DHCP lease and options. When + the property is a hex string ('aa:bb:cc') it is interpreted as a + binary client ID, in which case the first byte is assumed to be the + 'type' field as per RFC 2132 section 9.14 and the remaining bytes + may be an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is + the Ethernet ARP type and the rest is a MAC address). If the + property is not a hex string it is considered as a non-hardware- + address client ID and the 'type' field is set to 0. + + The special values "mac" and "perm-mac" are supported, which use the + current or permanent MAC address of the device to generate a client + identifier with type ethernet (01). Currently, these options only + work for ethernet type of links. + + The special value "ipv6-duid" uses the DUID from "ipv6.dhcp-duid" + property as an RFC4361-compliant client identifier. As IAID it uses + "ipv4.dhcp-iaid" and falls back to "ipv6.dhcp-iaid" if unset. + + The special value "duid" generates a RFC4361-compliant client + identifier based on "ipv4.dhcp-iaid" and uses a DUID generated by + hashing /etc/machine-id. + + The special value "stable" is supported to generate a type 0 client + identifier based on the stable-id (see connection.stable-id) and a + per-host key. If you set the stable-id, you may want to include the + "${DEVICE}" or "${MAC}" specifier to get a per-device key. + + If unset, a globally configured default is used. If still unset, the + default depends on the DHCP plugin.""" dhcp_fqdn: Optional[str] = field( - metadata={'dbus_name': 'dhcp-fqdn', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-fqdn', + 'dbus_type': 's', + }, default=None, ) - """If the "dhcp-send-hostname" property is TRUE, then the specified FQDN will - be sent to the DHCP server when acquiring a lease. This property and "dhcp- - hostname" are mutually exclusive and cannot be set at the same time.""" + """If the "dhcp-send-hostname" property is TRUE, then the specified FQDN + will be sent to the DHCP server when acquiring a lease. This + property and "dhcp-hostname" are mutually exclusive and cannot be + set at the same time.""" dhcp_hostname: Optional[str] = field( - metadata={'dbus_name': 'dhcp-hostname', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-hostname', + 'dbus_type': 's', + }, default=None, ) - """If the "dhcp-send-hostname" property is TRUE, then the specified name will - be sent to the DHCP server when acquiring a lease. This property and "dhcp- - fqdn" are mutually exclusive and cannot be set at the same time.""" + """If the "dhcp-send-hostname" property is TRUE, then the specified name + will be sent to the DHCP server when acquiring a lease. This + property and "dhcp-fqdn" are mutually exclusive and cannot be set at + the same time.""" dhcp_hostname_flags: Optional[int] = field( - metadata={'dbus_name': 'dhcp-hostname-flags', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'dhcp-hostname-flags', + 'dbus_type': 'u', + }, default=None, ) - """Flags for the DHCP hostname and FQDN. Currently, this property only - includes flags to control the FQDN flags set in the DHCP FQDN option. - Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + """Flags for the DHCP hostname and FQDN. + + Currently, this property only includes flags to control the FQDN + flags set in the DHCP FQDN option. Supported FQDN flags are + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and - NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will - contain no flag. Otherwise, if no FQDN flag is set and - NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN - flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is + set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the + DHCP FQDN option will contain no flag. Otherwise, if no FQDN flag is + set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the + standard FQDN flags are set in the request: + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is - set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is - looked up in NetworkManager configuration. If that value is unset or also - NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above - are sent in the DHCP requests.""" + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. + + When this property is set to the default value + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is looked up in + NetworkManager configuration. If that value is unset or also + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags + described above are sent in the DHCP requests.""" dhcp_iaid: Optional[str] = field( - metadata={'dbus_name': 'dhcp-iaid', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-iaid', + 'dbus_type': 's', + }, default=None, ) """A string containing the "Identity Association Identifier" (IAID) used by - the DHCP client. The property is a 32-bit decimal value or a special value - among "mac", "perm-mac", "ifname" and "stable". When set to "mac" (or "perm- - mac"), the last 4 bytes of the current (or permanent) MAC address are used as - IAID. When set to "ifname", the IAID is computed by hashing the interface - name. The special value "stable" can be used to generate an IAID based on the - stable-id (see connection.stable-id), a per-host key and the interface name. - When the property is unset, the value from global configuration is used; if no - global default is set then the IAID is assumed to be "ifname". Note that at - the moment this property is ignored for IPv6 by dhclient, which always derives - the IAID from the MAC address.""" + the DHCP client. The property is a 32-bit decimal value or a special + value among "mac", "perm-mac", "ifname" and "stable". When set to + "mac" (or "perm-mac"), the last 4 bytes of the current (or + permanent) MAC address are used as IAID. When set to "ifname", the + IAID is computed by hashing the interface name. The special value + "stable" can be used to generate an IAID based on the stable-id (see + connection.stable-id), a per-host key and the interface name. When + the property is unset, the value from global configuration is used; + if no global default is set then the IAID is assumed to be "ifname". + Note that at the moment this property is ignored for IPv6 by + dhclient, which always derives the IAID from the MAC address.""" dhcp_reject_servers: Optional[List[str]] = field( - metadata={'dbus_name': 'dhcp-reject-servers', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dhcp-reject-servers', + 'dbus_type': 'as', + }, default=None, ) - """Array of servers from which DHCP offers must be rejected. This property is - useful to avoid getting a lease from misconfigured or rogue servers. For - DHCPv4, each element must be an IPv4 address, optionally followed by a slash - and a prefix length (e.g. "192.168.122.0/24"). This property is currently not - implemented for DHCPv6.""" + """Array of servers from which DHCP offers must be rejected. This property + is useful to avoid getting a lease from misconfigured or rogue + servers. + + For DHCPv4, each element must be an IPv4 address, optionally + followed by a slash and a prefix length (e.g. "192.168.122.0/24"). + + This property is currently not implemented for DHCPv6.""" dhcp_send_hostname: Optional[bool] = field( - metadata={'dbus_name': 'dhcp-send-hostname', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'dhcp-send-hostname', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some - DHCP servers use this hostname to update DNS databases, essentially providing - a static hostname for the computer. If the "dhcp-hostname" property is NULL - and this property is TRUE, the current persistent hostname of the computer is - sent.""" + """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. + Some DHCP servers use this hostname to update DNS databases, + essentially providing a static hostname for the computer. If the + "dhcp-hostname" property is NULL and this property is TRUE, the + current persistent hostname of the computer is sent.""" dhcp_timeout: Optional[int] = field( - metadata={'dbus_name': 'dhcp-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dhcp-timeout', + 'dbus_type': 'i', + }, default=None, ) """A timeout for a DHCP transaction in seconds. If zero (the default), a - globally configured default is used. If still unspecified, a device specific - timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for - infinity.""" + globally configured default is used. If still unspecified, a device + specific timeout is used (usually 45 seconds). + + Set to 2147483647 (MAXINT32) for infinity.""" dhcp_vendor_class_identifier: Optional[str] = field( - metadata={'dbus_name': 'dhcp-vendor-class-identifier', - 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-vendor-class-identifier', + 'dbus_type': 's', + }, default=None, ) """The Vendor Class Identifier DHCP option (60). Special characters in the - data string may be escaped using C-style escapes, nevertheless this property - cannot contain nul bytes. If the per-profile value is unspecified (the - default), a global connection default gets consulted. If still unspecified, - the DHCP option is not sent to the server. Since 1.28""" + data string may be escaped using C-style escapes, nevertheless this + property cannot contain nul bytes. If the per-profile value is + unspecified (the default), a global connection default gets + consulted. If still unspecified, the DHCP option is not sent to the + server. + + Since 1.28""" dns: Optional[List[int]] = field( - metadata={'dbus_name': 'dns', 'dbus_type': 'au'}, + metadata={ + 'dbus_name': 'dns', + 'dbus_type': 'au', + }, default=None, ) + """Array of IP addresses of DNS servers. + + For DoT (DNS over TLS), the SNI server name can be specified by + appending "#example.com" to the IP address of the DNS server. This + currently only has effect when using systemd-resolved.""" + dns_data: Optional[List[str]] = field( + metadata={ + 'dbus_name': 'dns-data', + 'dbus_type': 'as', + }, + default=None, + ) + """Array of DNS name servers. This replaces the deprecated "dns" property. + Each name server can also contain a DoT server name.""" dns_options: Optional[List[str]] = field( - metadata={'dbus_name': 'dns-options', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dns-options', + 'dbus_type': 'as', + }, default=None, ) - """Array of DNS options as described in man 5 resolv.conf. NULL means that the - options are unset and left at the default. In this case NetworkManager will - use default options. This is distinct from an empty list of properties. The - currently supported options are "attempts", "debug", "edns0", "inet6", - "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", - "no-reload", "no-tld-query", "rotate", "single-request", "single-request- - reopen", "timeout", "trust-ad", "use-vc". The "trust-ad" setting is only - honored if the profile contributes name servers to resolv.conf, and if all - contributing profiles have "trust-ad" enabled. When using a caching DNS plugin - (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust- - ad" are automatically added.""" + """Array of DNS options as described in man 5 resolv.conf. + + NULL means that the options are unset and left at the default. In + this case NetworkManager will use default options. This is distinct + from an empty list of properties. + + The currently supported options are "attempts", "debug", "edns0", + "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", + "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single- + request", "single-request-reopen", "timeout", "trust-ad", "use-vc". + + The "trust-ad" setting is only honored if the profile contributes + name servers to resolv.conf, and if all contributing profiles have + "trust-ad" enabled. + + When using a caching DNS plugin (dnsmasq or systemd-resolved in + NetworkManager.conf) then "edns0" and "trust-ad" are automatically + added.""" dns_priority: Optional[int] = field( - metadata={'dbus_name': 'dns-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dns-priority', + 'dbus_type': 'i', + }, default=None, ) - """DNS servers priority. The relative priority for DNS servers specified by - this setting. A lower numerical value is better (higher priority). Negative - values have the special effect of excluding other configurations with a - greater numerical priority value; so in presence of at least one negative - priority, only DNS servers from connections with the lowest priority value - will be used. To avoid all DNS leaks, set the priority of the profile that - should be used to the most negative value of all active connections profiles. - Zero selects a globally configured default value. If the latter is missing or - zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other - connections. Note that the priority is to order DNS settings for multiple - active connections. It does not disambiguate multiple DNS servers within the - same connection profile. When multiple devices have configurations with the - same priority, VPNs will be considered first, then devices with the best - (lowest metric) default route and then all other devices. When using - dns=default, servers with higher priority will be on top of resolv.conf. To - prioritize a given server over another one within the same connection, just - specify them in the desired order. Note that commonly the resolver tries name - servers in /etc/resolv.conf in the order listed, proceeding with the next - server in the list on failure. See for example the "rotate" option of the dns- - options setting. If there are any negative DNS priorities, then only name - servers from the devices with that lowest priority will be considered. When - using a DNS resolver that supports Conditional Forwarding or Split DNS (with - dns=dnsmasq or dns=systemd-resolved settings), each connection is used to - query domains in its search list. The search domains determine which name - servers to ask, and the DNS priority is used to prioritize name servers based - on the domain. Queries for domains not present in any search list are routed - through connections having the '~.' special wildcard domain, which is added + """DNS servers priority. + + The relative priority for DNS servers specified by this setting. A + lower numerical value is better (higher priority). + + Negative values have the special effect of excluding other + configurations with a greater numerical priority value; so in + presence of at least one negative priority, only DNS servers from + connections with the lowest priority value will be used. To avoid + all DNS leaks, set the priority of the profile that should be used + to the most negative value of all active connections profiles. + + Zero selects a globally configured default value. If the latter is + missing or zero too, it defaults to 50 for VPNs (including + WireGuard) and 100 for other connections. + + Note that the priority is to order DNS settings for multiple active + connections. It does not disambiguate multiple DNS servers within + the same connection profile. + + When multiple devices have configurations with the same priority, + VPNs will be considered first, then devices with the best (lowest + metric) default route and then all other devices. + + When using dns=default, servers with higher priority will be on top + of resolv.conf. To prioritize a given server over another one within + the same connection, just specify them in the desired order. Note + that commonly the resolver tries name servers in /etc/resolv.conf in + the order listed, proceeding with the next server in the list on + failure. See for example the "rotate" option of the dns-options + setting. If there are any negative DNS priorities, then only name + servers from the devices with that lowest priority will be + considered. + + When using a DNS resolver that supports Conditional Forwarding or + Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each + connection is used to query domains in its search list. The search + domains determine which name servers to ask, and the DNS priority is + used to prioritize name servers based on the domain. Queries for + domains not present in any search list are routed through + connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added - manually). When multiple connections specify the same domain, the one with - the best priority (lowest numerical value) wins. If a sub domain is - configured on another interface it will be accepted regardless the priority, - unless parent domain on the other interface has a negative priority, which - causes the sub domain to be shadowed. With Split DNS one can avoid undesired - DNS leaks by properly configuring DNS priorities and the search domains, so - that only name servers of the desired interface are configured.""" + manually). When multiple connections specify the same domain, the + one with the best priority (lowest numerical value) wins. If a sub + domain is configured on another interface it will be accepted + regardless the priority, unless parent domain on the other interface + has a negative priority, which causes the sub domain to be shadowed. + With Split DNS one can avoid undesired DNS leaks by properly + configuring DNS priorities and the search domains, so that only name + servers of the desired interface are configured.""" dns_search: Optional[List[str]] = field( - metadata={'dbus_name': 'dns-search', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dns-search', + 'dbus_type': 'as', + }, default=None, ) - """Array of DNS search domains. Domains starting with a tilde ('~') are - considered 'routing' domains and are used only to decide the interface over - which a query must be forwarded; they are not used to complete unqualified - host names. When using a DNS plugin that supports Conditional Forwarding or - Split DNS, then the search domains specify which name servers to query. This - makes the behavior different from running with plain /etc/resolv.conf. For - more information see also the dns-priority setting.""" + """List of DNS search domains. Domains starting with a tilde ('~') are + considered 'routing' domains and are used only to decide the + interface over which a query must be forwarded; they are not used to + complete unqualified host names. + + When using a DNS plugin that supports Conditional Forwarding or + Split DNS, then the search domains specify which name servers to + query. This makes the behavior different from running with plain + /etc/resolv.conf. For more information see also the dns-priority + setting. + + When set on a profile that also enabled DHCP, the DNS search list + received automatically (option 119 for DHCPv4 and option 24 for + DHCPv6) gets merged with the manual list. This can be prevented by + setting "ignore-auto-dns". Note that if no DNS searches are + configured, the fallback will be derived from the domain from DHCP + (option 15).""" gateway: Optional[str] = field( - metadata={'dbus_name': 'gateway', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'gateway', + 'dbus_type': 's', + }, default=None, ) - """The gateway associated with this configuration. This is only meaningful if - "addresses" is also set. The gateway's main purpose is to control the next hop - of the standard default route on the device. Hence, the gateway property - conflicts with "never-default" and will be automatically dropped if the IP - configuration is set to never-default. As an alternative to set the gateway, - configure a static default route with /0 as prefix length.""" + """The gateway associated with this configuration. This is only meaningful + if "addresses" is also set. + + Setting the gateway causes NetworkManager to configure a standard + default route with the gateway as next hop. This is ignored if + "never-default" is set. An alternative is to configure the default + route explicitly with a manual route and /0 as prefix length. + + Note that the gateway usually conflicts with routing that + NetworkManager configures for WireGuard interfaces, so usually it + should not be set in that case. See "ip4-auto-default-route".""" ignore_auto_dns: Optional[bool] = field( - metadata={'dbus_name': 'ignore-auto-dns', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'ignore-auto-dns', + 'dbus_type': 'b', + }, + default=None, ) """When "method" is set to "auto" and this property to TRUE, automatically - configured name servers and search domains are ignored and only name servers - and search domains specified in the "dns" and "dns-search" properties, if any, - are used.""" + configured name servers and search domains are ignored and only name + servers and search domains specified in the "dns" and "dns-search" + properties, if any, are used.""" ignore_auto_routes: Optional[bool] = field( - metadata={'dbus_name': 'ignore-auto-routes', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'ignore-auto-routes', + 'dbus_type': 'b', + }, + default=None, ) """When "method" is set to "auto" and this property to TRUE, automatically - configured routes are ignored and only routes specified in the "routes" - property, if any, are used.""" + configured routes are ignored and only routes specified in the + "routes" property, if any, are used.""" + link_local: Optional[int] = field( + metadata={ + 'dbus_name': 'link-local', + 'dbus_type': 'i', + }, + default=None, + ) + """Enable and disable the IPv4 link-local configuration independently of + the ipv4.method configuration. This allows a link-local address + (169.254.x.y/16) to be obtained in addition to other addresses, such + as those manually configured or obtained from a DHCP server. + + When set to "auto", the value is dependent on "ipv4.method". When + set to "default", it honors the global connection default, before + falling back to "auto". Note that if "ipv4.method" is "disabled", + then link local addressing is always disabled too. The default is + "default". + + Since 1.40""" may_fail: Optional[bool] = field( - metadata={'dbus_name': 'may-fail', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'may-fail', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, allow overall network configuration to proceed even if the - configuration specified by this property times out. Note that at least one IP - configuration must succeed or overall network configuration will still fail. - For example, in IPv6-only networks, setting this property to TRUE on the - NMSettingIP4Config allows the overall network configuration to succeed if IPv4 - configuration fails but IPv6 configuration completes successfully.""" + configuration specified by this property times out. Note that at + least one IP configuration must succeed or overall network + configuration will still fail. For example, in IPv6-only networks, + setting this property to TRUE on the NMSettingIP4Config allows the + overall network configuration to succeed if IPv4 configuration fails + but IPv6 configuration completes successfully.""" method: Optional[str] = field( - metadata={'dbus_name': 'method', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'method', + 'dbus_type': 's', + }, default=None, ) - """IP configuration method. NMSettingIP4Config and NMSettingIP6Config both - support "disabled", "auto", "manual", and "link-local". See the subclass- - specific documentation for other values. In general, for the "auto" method, - properties such as "dns" and "routes" specify information that is added on to - the information returned from automatic configuration. The "ignore-auto- - routes" and "ignore-auto-dns" properties modify this behavior. For methods - that imply no upstream network, such as "shared" or "link-local", these - properties must be empty. For IPv4 method "shared", the IP subnet can be - configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is - chosen. Note that the shared method must be configured on the interface which + """IP configuration method. + + NMSettingIP4Config and NMSettingIP6Config both support "disabled", + "auto", "manual", and "link-local". See the subclass-specific + documentation for other values. + + In general, for the "auto" method, properties such as "dns" and + "routes" specify information that is added on to the information + returned from automatic configuration. The "ignore-auto-routes" and + "ignore-auto-dns" properties modify this behavior. + + For methods that imply no upstream network, such as "shared" or + "link-local", these properties must be empty. + + For IPv4 method "shared", the IP subnet can be configured by adding + one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note + that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.""" never_default: Optional[bool] = field( - metadata={'dbus_name': 'never-default', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'never-default', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE, this connection will never be the default connection for this IP - type, meaning it will never be assigned the default route by + """If TRUE, this connection will never be the default connection for this + IP type, meaning it will never be assigned the default route by NetworkManager.""" required_timeout: Optional[int] = field( - metadata={'dbus_name': 'required-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'required-timeout', + 'dbus_type': 'i', + }, default=None, ) """The minimum time interval in milliseconds for which dynamic IP - configuration should be tried before the connection succeeds. This property is - useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. - Normally the connection succeeds as soon as one of the two address families - completes; by setting a required timeout for e.g. IPv4, one can ensure that - even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for - IPv4 before the connection becomes active. Note that if "may-fail" is FALSE - for the same address family, this property has no effect as NetworkManager - needs to wait for the full DHCP timeout. A zero value means that no required - timeout is present, -1 means the default value (either configuration - ipvx.required-timeout override or zero).""" + configuration should be tried before the connection succeeds. + + This property is useful for example if both IPv4 and IPv6 are + enabled and are allowed to fail. Normally the connection succeeds as + soon as one of the two address families completes; by setting a + required timeout for e.g. IPv4, one can ensure that even if IP6 + succeeds earlier than IPv4, NetworkManager waits some time for IPv4 + before the connection becomes active. + + Note that if "may-fail" is FALSE for the same address family, this + property has no effect as NetworkManager needs to wait for the full + DHCP timeout. + + A zero value means that no required timeout is present, -1 means the + default value (either configuration ipvx.required-timeout override + or zero).""" route_data: Optional[List[RouteData]] = field( - metadata={'dbus_name': 'route-data', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': RouteData}, + metadata={ + 'dbus_name': 'route-data', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': RouteData, + }, default=None, ) + """Array of IPv4 routes. Each route dictionary contains at least 'dest' and + 'prefix' entries, containing the destination IP address as a string, + and the prefix length as a uint32. Most routes will also have a + 'next-hop' entry, containing the next hop IP address as a string. If + the route has a 'metric' entry (containing a uint32), that will be + used as the metric for the route (otherwise NM will pick a default + value appropriate to the device). Additional attributes may also + exist on some routes.""" route_metric: Optional[int] = field( - metadata={'dbus_name': 'route-metric', 'dbus_type': 'x'}, + metadata={ + 'dbus_name': 'route-metric', + 'dbus_type': 'x', + }, default=None, ) - """The default metric for routes that don't explicitly specify a metric. The - default value -1 means that the metric is chosen automatically based on the - device type. The metric applies to dynamic routes, manual (static) routes that - don't have an explicit metric setting, address prefix routes, and the default - route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 - (user default). Hence, setting this property to zero effectively mean setting - it to 1024. For IPv4, zero is a regular value for the metric.""" + """The default metric for routes that don't explicitly specify a metric. + The default value -1 means that the metric is chosen automatically + based on the device type. The metric applies to dynamic routes, + manual (static) routes that don't have an explicit metric setting, + address prefix routes, and the default route. Note that for IPv6, + the kernel accepts zero (0) but coerces it to 1024 (user default). + Hence, setting this property to zero effectively mean setting it to + 1024. For IPv4, zero is a regular value for the metric.""" route_table: Optional[int] = field( - metadata={'dbus_name': 'route-table', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'route-table', + 'dbus_type': 'u', + }, default=None, ) - """Enable policy routing (source routing) and set the routing table used when - adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, - SLAAC, default-routes and static routes. But note that static routes can - individually overwrite the setting by explicitly specifying a non-zero routing - table. If the table setting is left at zero, it is eligible to be overwritten - via global configuration. If the property is zero even after applying the - global configuration value, policy routing is disabled for the address family - of this connection. Policy routing disabled means that NetworkManager will add - all routes to the main table (except static routes that explicitly configure a - different table). Additionally, NetworkManager will not delete any extraneous - routes from tables except the main table. This is to preserve backward - compatibility for users who manage routing tables outside of - NetworkManager.""" + """Enable policy routing (source routing) and set the routing table used + when adding routes. + + This affects all routes, including device-routes, IPv4LL, DHCP, + SLAAC, default-routes and static routes. But note that static routes + can individually overwrite the setting by explicitly specifying a + non-zero routing table. + + If the table setting is left at zero, it is eligible to be + overwritten via global configuration. If the property is zero even + after applying the global configuration value, policy routing is + disabled for the address family of this connection. + + Policy routing disabled means that NetworkManager will add all + routes to the main table (except static routes that explicitly + configure a different table). Additionally, NetworkManager will not + delete any extraneous routes from tables except the main table. This + is to preserve backward compatibility for users who manage routing + tables outside of NetworkManager.""" routes: Optional[List[List[int]]] = field( - metadata={'dbus_name': 'routes', 'dbus_type': 'aau'}, + metadata={ + 'dbus_name': 'routes', + 'dbus_type': 'aau', + }, + default=None, + ) + """Array of IP routes.""" + routing_rules: Optional[List[RoutingRules]] = field( + metadata={ + 'dbus_name': 'routing-rules', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': RoutingRules, + }, default=None, ) - """Deprecated in favor of the 'route-data' property, but this can be used for - backward-compatibility with older daemons. Note that if you send this property - the daemon will ignore 'route-data'. Array of IPv4 route structures. Each - IPv4 route structure is composed of 4 32-bit values; the first being the - destination IPv4 network or address (network byte order), the second the - destination network or address prefix (1 - 32), the third being the next-hop - (network byte order) if any, and the fourth being the route metric. If the - metric is 0, NM will choose an appropriate default metric for the device. - (There is no way to explicitly specify an actual metric of 0 with this - property.)""" + """Array of dictionaries for routing rules. Each routing rule supports the + following options: action (y), dport-end (q), dport-start (q), + family (i), from (s), from-len (y), fwmark (u), fwmask (u), iifname + (s), invert (b), ipproto (s), oifname (s), priority (u), sport-end + (q), sport-start (q), supress-prefixlength (i), table (u), to (s), + tos (y), to-len (y), range-end (u), range-start (u).""" diff --git a/sdbus_async/networkmanager/settings/ipv6.py b/sdbus_async/networkmanager/settings/ipv6.py index e9f2d79..7f69c51 100644 --- a/sdbus_async/networkmanager/settings/ipv6.py +++ b/sdbus_async/networkmanager/settings/ipv6.py @@ -1,11 +1,11 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin -from .datatypes import AddressData, RouteData +from .datatypes import AddressData, RouteData, RoutingRules @dataclass @@ -13,340 +13,577 @@ class Ipv6Settings(NetworkManagerSettingsMixin): """IPv6 Settings""" addr_gen_mode: Optional[int] = field( - metadata={'dbus_name': 'addr-gen-mode', 'dbus_type': 'i'}, - default=1, + metadata={ + 'dbus_name': 'addr-gen-mode', + 'dbus_type': 'i', + }, + default=None, ) """Configure method for creating the address for use with RFC4862 IPv6 Stateless Address Autoconfiguration. The permitted values are: - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0) or - NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). If the property is set - to EUI64, the addresses will be generated using the interface tokens derived - from hardware address. This makes the host part of the address to stay - constant, making it possible to track host's presence when it changes - networks. The address changes when the interface hardware is replaced. The - value of stable-privacy enables use of cryptographically secure hash of a - secret host-specific key along with the connection's stable-id and the network - address as specified by RFC7217. This makes it impossible to use the address - track host's presence, and makes the address stable when the network interface - hardware is replaced. On D-Bus, the absence of an addr-gen-mode setting equals - enabling stable-privacy. For keyfile plugin, the absence of the setting on - disk means EUI64 so that the property doesn't change on upgrade from older - versions. Note that this setting is distinct from the Privacy Extensions as - configured by "ip6-privacy" property and it does not affect the temporary - addresses configured with this option.""" + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 (0), + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY (1). + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT_OR_EUI64 (2) or + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_DEFAULT (3). + + If the property is set to EUI64, the addresses will be generated + using the interface tokens derived from hardware address. This makes + the host part of the address to stay constant, making it possible to + track host's presence when it changes networks. The address changes + when the interface hardware is replaced. + + The value of stable-privacy enables use of cryptographically secure + hash of a secret host-specific key along with the connection's + stable-id and the network address as specified by RFC7217. This + makes it impossible to use the address track host's presence, and + makes the address stable when the network interface hardware is + replaced. + + The special values "default" and "default-or-eui64" will fallback to + the global connection default in as documented in + NetworkManager.conf(5) manual. If the global default is not + specified, the fallback value is "stable-privacy" or "eui64", + respectively. + + For libnm, the property defaults to "default" since 1.40. Previously + it defaulted to "stable-privacy". On D-Bus, the absence of an addr- + gen-mode setting equals "default". For keyfile plugin, the absence + of the setting on disk means "default-or-eui64" so that the property + doesn't change on upgrade from older versions. + + Note that this setting is distinct from the Privacy Extensions as + configured by "ip6-privacy" property and it does not affect the + temporary addresses configured with this option.""" address_data: Optional[List[AddressData]] = field( - metadata={'dbus_name': 'address-data', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': AddressData}, + metadata={ + 'dbus_name': 'address-data', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': AddressData, + }, default=None, ) + """Array of IPv6 addresses. Each address dictionary contains at least + 'address' and 'prefix' entries, containing the IP address as a + string, and the prefix length as a uint32. Additional attributes may + also exist on some addresses.""" dad_timeout: Optional[int] = field( - metadata={'dbus_name': 'dad-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dad-timeout', + 'dbus_type': 'i', + }, default=None, ) """Timeout in milliseconds used to check for the presence of duplicate IP - addresses on the network. If an address conflict is detected, the activation - will fail. A zero value means that no duplicate address detection is - performed, -1 means the default value (either configuration ipvx.dad-timeout - override or zero). A value greater than zero is a timeout in milliseconds. + addresses on the network. If an address conflict is detected, the + activation will fail. A zero value means that no duplicate address + detection is performed, -1 means the default value (either + configuration ipvx.dad-timeout override or zero). A value greater + than zero is a timeout in milliseconds. + The property is currently implemented only for IPv4.""" dhcp_duid: Optional[str] = field( - metadata={'dbus_name': 'dhcp-duid', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-duid', + 'dbus_type': 's', + }, default=None, ) """A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp - client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried in - the Client Identifier option. If the property is a hex string ('aa:bb:cc') it - is interpreted as a binary DUID and filled as an opaque value in the Client - Identifier option. The special value "lease" will retrieve the DUID previously - used from the lease file belonging to the connection. If no DUID is found and - "dhclient" is the configured dhcp client, the DUID is searched in the system- - wide dhclient lease file. If still no DUID is found, or another dhcp client is - used, a global and permanent DUID-UUID (RFC 6355) will be generated based on - the machine-id. The special values "llt" and "ll" will generate a DUID of type - LLT or LL (see RFC 3315) based on the current MAC address of the device. In - order to try providing a stable DUID-LLT, the time field will contain a - constant timestamp that is used globally (for all profiles) and persisted to - disk. The special values "stable-llt", "stable-ll" and "stable-uuid" will - generate a DUID of the corresponding type, derived from the connection's - stable-id and a per-host unique key. You may want to include the "${DEVICE}" - or "${MAC}" specifier in the stable-id, in case this profile gets activated on - multiple devices. So, the link-layer address of "stable-ll" and "stable-llt" - will be a generated address derived from the stable id. The DUID-LLT time - value in the "stable-llt" option will be picked among a static timespan of - three years (the upper bound of the interval is the same constant timestamp - used in "llt"). When the property is unset, the global value provided for - "ipv6.dhcp-duid" is used. If no global value is provided, the default "lease" - value is assumed.""" + client to identify itself to DHCPv6 servers (RFC 3315). The DUID is + carried in the Client Identifier option. If the property is a hex + string ('aa:bb:cc') it is interpreted as a binary DUID and filled as + an opaque value in the Client Identifier option. + + The special value "lease" will retrieve the DUID previously used + from the lease file belonging to the connection. If no DUID is found + and "dhclient" is the configured dhcp client, the DUID is searched + in the system-wide dhclient lease file. If still no DUID is found, + or another dhcp client is used, a global and permanent DUID-UUID + (RFC 6355) will be generated based on the machine-id. + + The special values "llt" and "ll" will generate a DUID of type LLT + or LL (see RFC 3315) based on the current MAC address of the device. + In order to try providing a stable DUID-LLT, the time field will + contain a constant timestamp that is used globally (for all + profiles) and persisted to disk. + + The special values "stable-llt", "stable-ll" and "stable-uuid" will + generate a DUID of the corresponding type, derived from the + connection's stable-id and a per-host unique key. You may want to + include the "${DEVICE}" or "${MAC}" specifier in the stable-id, in + case this profile gets activated on multiple devices. So, the link- + layer address of "stable-ll" and "stable-llt" will be a generated + address derived from the stable id. The DUID-LLT time value in the + "stable-llt" option will be picked among a static timespan of three + years (the upper bound of the interval is the same constant + timestamp used in "llt"). + + When the property is unset, the global value provided for + "ipv6.dhcp-duid" is used. If no global value is provided, the + default "lease" value is assumed.""" dhcp_hostname: Optional[str] = field( - metadata={'dbus_name': 'dhcp-hostname', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-hostname', + 'dbus_type': 's', + }, default=None, ) - """If the "dhcp-send-hostname" property is TRUE, then the specified name will - be sent to the DHCP server when acquiring a lease. This property and "dhcp- - fqdn" are mutually exclusive and cannot be set at the same time.""" + """If the "dhcp-send-hostname" property is TRUE, then the specified name + will be sent to the DHCP server when acquiring a lease. This + property and "dhcp-fqdn" are mutually exclusive and cannot be set at + the same time.""" dhcp_hostname_flags: Optional[int] = field( - metadata={'dbus_name': 'dhcp-hostname-flags', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'dhcp-hostname-flags', + 'dbus_type': 'u', + }, default=None, ) - """Flags for the DHCP hostname and FQDN. Currently, this property only - includes flags to control the FQDN flags set in the DHCP FQDN option. - Supported FQDN flags are NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + """Flags for the DHCP hostname and FQDN. + + Currently, this property only includes flags to control the FQDN + flags set in the DHCP FQDN option. Supported FQDN flags are + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) and - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is set and - NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the DHCP FQDN option will - contain no flag. Otherwise, if no FQDN flag is set and - NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the standard FQDN - flags are set in the request: NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE (0x4). When no FQDN flag is + set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is set, the + DHCP FQDN option will contain no flag. Otherwise, if no FQDN flag is + set and NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS (0x8) is not set, the + standard FQDN flags are set in the request: + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1), NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED (0x2) for IPv4 and - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. When this property is - set to the default value NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is - looked up in NetworkManager configuration. If that value is unset or also - NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags described above - are sent in the DHCP requests.""" + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE (0x1) for IPv6. + + When this property is set to the default value + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), a global default is looked up in + NetworkManager configuration. If that value is unset or also + NM_DHCP_HOSTNAME_FLAG_NONE (0x0), then the standard FQDN flags + described above are sent in the DHCP requests.""" dhcp_iaid: Optional[str] = field( - metadata={'dbus_name': 'dhcp-iaid', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'dhcp-iaid', + 'dbus_type': 's', + }, default=None, ) """A string containing the "Identity Association Identifier" (IAID) used by - the DHCP client. The property is a 32-bit decimal value or a special value - among "mac", "perm-mac", "ifname" and "stable". When set to "mac" (or "perm- - mac"), the last 4 bytes of the current (or permanent) MAC address are used as - IAID. When set to "ifname", the IAID is computed by hashing the interface - name. The special value "stable" can be used to generate an IAID based on the - stable-id (see connection.stable-id), a per-host key and the interface name. - When the property is unset, the value from global configuration is used; if no - global default is set then the IAID is assumed to be "ifname". Note that at - the moment this property is ignored for IPv6 by dhclient, which always derives - the IAID from the MAC address.""" + the DHCP client. The property is a 32-bit decimal value or a special + value among "mac", "perm-mac", "ifname" and "stable". When set to + "mac" (or "perm-mac"), the last 4 bytes of the current (or + permanent) MAC address are used as IAID. When set to "ifname", the + IAID is computed by hashing the interface name. The special value + "stable" can be used to generate an IAID based on the stable-id (see + connection.stable-id), a per-host key and the interface name. When + the property is unset, the value from global configuration is used; + if no global default is set then the IAID is assumed to be "ifname". + Note that at the moment this property is ignored for IPv6 by + dhclient, which always derives the IAID from the MAC address.""" dhcp_reject_servers: Optional[List[str]] = field( - metadata={'dbus_name': 'dhcp-reject-servers', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dhcp-reject-servers', + 'dbus_type': 'as', + }, default=None, ) - """Array of servers from which DHCP offers must be rejected. This property is - useful to avoid getting a lease from misconfigured or rogue servers. For - DHCPv4, each element must be an IPv4 address, optionally followed by a slash - and a prefix length (e.g. "192.168.122.0/24"). This property is currently not - implemented for DHCPv6.""" + """Array of servers from which DHCP offers must be rejected. This property + is useful to avoid getting a lease from misconfigured or rogue + servers. + + For DHCPv4, each element must be an IPv4 address, optionally + followed by a slash and a prefix length (e.g. "192.168.122.0/24"). + + This property is currently not implemented for DHCPv6.""" dhcp_send_hostname: Optional[bool] = field( - metadata={'dbus_name': 'dhcp-send-hostname', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'dhcp-send-hostname', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some - DHCP servers use this hostname to update DNS databases, essentially providing - a static hostname for the computer. If the "dhcp-hostname" property is NULL - and this property is TRUE, the current persistent hostname of the computer is - sent.""" + """If TRUE, a hostname is sent to the DHCP server when acquiring a lease. + Some DHCP servers use this hostname to update DNS databases, + essentially providing a static hostname for the computer. If the + "dhcp-hostname" property is NULL and this property is TRUE, the + current persistent hostname of the computer is sent.""" dhcp_timeout: Optional[int] = field( - metadata={'dbus_name': 'dhcp-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dhcp-timeout', + 'dbus_type': 'i', + }, default=None, ) """A timeout for a DHCP transaction in seconds. If zero (the default), a - globally configured default is used. If still unspecified, a device specific - timeout is used (usually 45 seconds). Set to 2147483647 (MAXINT32) for - infinity.""" + globally configured default is used. If still unspecified, a device + specific timeout is used (usually 45 seconds). + + Set to 2147483647 (MAXINT32) for infinity.""" dns: Optional[List[bytes]] = field( - metadata={'dbus_name': 'dns', 'dbus_type': 'aay'}, + metadata={ + 'dbus_name': 'dns', + 'dbus_type': 'aay', + }, default=None, ) + """Array of IP addresses of DNS servers. + + For DoT (DNS over TLS), the SNI server name can be specified by + appending "#example.com" to the IP address of the DNS server. This + currently only has effect when using systemd-resolved.""" + dns_data: Optional[List[str]] = field( + metadata={ + 'dbus_name': 'dns-data', + 'dbus_type': 'as', + }, + default=None, + ) + """Array of DNS name servers. This replaces the deprecated "dns" property. + Each name server can also contain a DoT server name.""" dns_options: Optional[List[str]] = field( - metadata={'dbus_name': 'dns-options', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dns-options', + 'dbus_type': 'as', + }, default=None, ) - """Array of DNS options as described in man 5 resolv.conf. NULL means that the - options are unset and left at the default. In this case NetworkManager will - use default options. This is distinct from an empty list of properties. The - currently supported options are "attempts", "debug", "edns0", "inet6", - "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", "no-ip6-dotint", - "no-reload", "no-tld-query", "rotate", "single-request", "single-request- - reopen", "timeout", "trust-ad", "use-vc". The "trust-ad" setting is only - honored if the profile contributes name servers to resolv.conf, and if all - contributing profiles have "trust-ad" enabled. When using a caching DNS plugin - (dnsmasq or systemd-resolved in NetworkManager.conf) then "edns0" and "trust- - ad" are automatically added.""" + """Array of DNS options as described in man 5 resolv.conf. + + NULL means that the options are unset and left at the default. In + this case NetworkManager will use default options. This is distinct + from an empty list of properties. + + The currently supported options are "attempts", "debug", "edns0", + "inet6", "ip6-bytestring", "ip6-dotint", "ndots", "no-check-names", + "no-ip6-dotint", "no-reload", "no-tld-query", "rotate", "single- + request", "single-request-reopen", "timeout", "trust-ad", "use-vc". + + The "trust-ad" setting is only honored if the profile contributes + name servers to resolv.conf, and if all contributing profiles have + "trust-ad" enabled. + + When using a caching DNS plugin (dnsmasq or systemd-resolved in + NetworkManager.conf) then "edns0" and "trust-ad" are automatically + added.""" dns_priority: Optional[int] = field( - metadata={'dbus_name': 'dns-priority', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'dns-priority', + 'dbus_type': 'i', + }, default=None, ) - """DNS servers priority. The relative priority for DNS servers specified by - this setting. A lower numerical value is better (higher priority). Negative - values have the special effect of excluding other configurations with a - greater numerical priority value; so in presence of at least one negative - priority, only DNS servers from connections with the lowest priority value - will be used. To avoid all DNS leaks, set the priority of the profile that - should be used to the most negative value of all active connections profiles. - Zero selects a globally configured default value. If the latter is missing or - zero too, it defaults to 50 for VPNs (including WireGuard) and 100 for other - connections. Note that the priority is to order DNS settings for multiple - active connections. It does not disambiguate multiple DNS servers within the - same connection profile. When multiple devices have configurations with the - same priority, VPNs will be considered first, then devices with the best - (lowest metric) default route and then all other devices. When using - dns=default, servers with higher priority will be on top of resolv.conf. To - prioritize a given server over another one within the same connection, just - specify them in the desired order. Note that commonly the resolver tries name - servers in /etc/resolv.conf in the order listed, proceeding with the next - server in the list on failure. See for example the "rotate" option of the dns- - options setting. If there are any negative DNS priorities, then only name - servers from the devices with that lowest priority will be considered. When - using a DNS resolver that supports Conditional Forwarding or Split DNS (with - dns=dnsmasq or dns=systemd-resolved settings), each connection is used to - query domains in its search list. The search domains determine which name - servers to ask, and the DNS priority is used to prioritize name servers based - on the domain. Queries for domains not present in any search list are routed - through connections having the '~.' special wildcard domain, which is added + """DNS servers priority. + + The relative priority for DNS servers specified by this setting. A + lower numerical value is better (higher priority). + + Negative values have the special effect of excluding other + configurations with a greater numerical priority value; so in + presence of at least one negative priority, only DNS servers from + connections with the lowest priority value will be used. To avoid + all DNS leaks, set the priority of the profile that should be used + to the most negative value of all active connections profiles. + + Zero selects a globally configured default value. If the latter is + missing or zero too, it defaults to 50 for VPNs (including + WireGuard) and 100 for other connections. + + Note that the priority is to order DNS settings for multiple active + connections. It does not disambiguate multiple DNS servers within + the same connection profile. + + When multiple devices have configurations with the same priority, + VPNs will be considered first, then devices with the best (lowest + metric) default route and then all other devices. + + When using dns=default, servers with higher priority will be on top + of resolv.conf. To prioritize a given server over another one within + the same connection, just specify them in the desired order. Note + that commonly the resolver tries name servers in /etc/resolv.conf in + the order listed, proceeding with the next server in the list on + failure. See for example the "rotate" option of the dns-options + setting. If there are any negative DNS priorities, then only name + servers from the devices with that lowest priority will be + considered. + + When using a DNS resolver that supports Conditional Forwarding or + Split DNS (with dns=dnsmasq or dns=systemd-resolved settings), each + connection is used to query domains in its search list. The search + domains determine which name servers to ask, and the DNS priority is + used to prioritize name servers based on the domain. Queries for + domains not present in any search list are routed through + connections having the '~.' special wildcard domain, which is added automatically to connections with the default route (or can be added - manually). When multiple connections specify the same domain, the one with - the best priority (lowest numerical value) wins. If a sub domain is - configured on another interface it will be accepted regardless the priority, - unless parent domain on the other interface has a negative priority, which - causes the sub domain to be shadowed. With Split DNS one can avoid undesired - DNS leaks by properly configuring DNS priorities and the search domains, so - that only name servers of the desired interface are configured.""" + manually). When multiple connections specify the same domain, the + one with the best priority (lowest numerical value) wins. If a sub + domain is configured on another interface it will be accepted + regardless the priority, unless parent domain on the other interface + has a negative priority, which causes the sub domain to be shadowed. + With Split DNS one can avoid undesired DNS leaks by properly + configuring DNS priorities and the search domains, so that only name + servers of the desired interface are configured.""" dns_search: Optional[List[str]] = field( - metadata={'dbus_name': 'dns-search', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'dns-search', + 'dbus_type': 'as', + }, default=None, ) - """Array of DNS search domains. Domains starting with a tilde ('~') are - considered 'routing' domains and are used only to decide the interface over - which a query must be forwarded; they are not used to complete unqualified - host names. When using a DNS plugin that supports Conditional Forwarding or - Split DNS, then the search domains specify which name servers to query. This - makes the behavior different from running with plain /etc/resolv.conf. For - more information see also the dns-priority setting.""" + """List of DNS search domains. Domains starting with a tilde ('~') are + considered 'routing' domains and are used only to decide the + interface over which a query must be forwarded; they are not used to + complete unqualified host names. + + When using a DNS plugin that supports Conditional Forwarding or + Split DNS, then the search domains specify which name servers to + query. This makes the behavior different from running with plain + /etc/resolv.conf. For more information see also the dns-priority + setting. + + When set on a profile that also enabled DHCP, the DNS search list + received automatically (option 119 for DHCPv4 and option 24 for + DHCPv6) gets merged with the manual list. This can be prevented by + setting "ignore-auto-dns". Note that if no DNS searches are + configured, the fallback will be derived from the domain from DHCP + (option 15).""" gateway: Optional[str] = field( - metadata={'dbus_name': 'gateway', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'gateway', + 'dbus_type': 's', + }, default=None, ) - """The gateway associated with this configuration. This is only meaningful if - "addresses" is also set. The gateway's main purpose is to control the next hop - of the standard default route on the device. Hence, the gateway property - conflicts with "never-default" and will be automatically dropped if the IP - configuration is set to never-default. As an alternative to set the gateway, - configure a static default route with /0 as prefix length.""" + """The gateway associated with this configuration. This is only meaningful + if "addresses" is also set. + + Setting the gateway causes NetworkManager to configure a standard + default route with the gateway as next hop. This is ignored if + "never-default" is set. An alternative is to configure the default + route explicitly with a manual route and /0 as prefix length. + + Note that the gateway usually conflicts with routing that + NetworkManager configures for WireGuard interfaces, so usually it + should not be set in that case. See "ip4-auto-default-route".""" ignore_auto_dns: Optional[bool] = field( - metadata={'dbus_name': 'ignore-auto-dns', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'ignore-auto-dns', + 'dbus_type': 'b', + }, + default=None, ) """When "method" is set to "auto" and this property to TRUE, automatically - configured name servers and search domains are ignored and only name servers - and search domains specified in the "dns" and "dns-search" properties, if any, - are used.""" + configured name servers and search domains are ignored and only name + servers and search domains specified in the "dns" and "dns-search" + properties, if any, are used.""" ignore_auto_routes: Optional[bool] = field( - metadata={'dbus_name': 'ignore-auto-routes', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'ignore-auto-routes', + 'dbus_type': 'b', + }, + default=None, ) """When "method" is set to "auto" and this property to TRUE, automatically - configured routes are ignored and only routes specified in the "routes" - property, if any, are used.""" + configured routes are ignored and only routes specified in the + "routes" property, if any, are used.""" ip6_privacy: Optional[int] = field( - metadata={'dbus_name': 'ip6-privacy', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'ip6-privacy', + 'dbus_type': 'i', + }, default=None, ) """Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If - enabled, it makes the kernel generate a temporary IPv6 address in addition to - the public one generated from MAC address via modified EUI-64. This enhances - privacy, but could cause problems in some applications, on the other hand. - The permitted values are: -1: unknown, 0: disabled, 1: enabled (prefer public - address), 2: enabled (prefer temporary addresses). Having a per-connection - setting set to "-1" (unknown) means fallback to global configuration - "ipv6.ip6-privacy". If also global configuration is unspecified or set to - "-1", fallback to read "/proc/sys/net/ipv6/conf/default/use_tempaddr". Note - that this setting is distinct from the Stable Privacy addresses that can be - enabled with the "addr-gen-mode" property's "stable-privacy" setting as - another way of avoiding host tracking with IPv6 addresses.""" + enabled, it makes the kernel generate a temporary IPv6 address in + addition to the public one generated from MAC address via modified + EUI-64. This enhances privacy, but could cause problems in some + applications, on the other hand. The permitted values are: -1: + unknown, 0: disabled, 1: enabled (prefer public address), 2: enabled + (prefer temporary addresses). + + Having a per-connection setting set to "-1" (unknown) means fallback + to global configuration "ipv6.ip6-privacy". + + If also global configuration is unspecified or set to "-1", fallback + to read "/proc/sys/net/ipv6/conf/default/use_tempaddr". + + Note that this setting is distinct from the Stable Privacy addresses + that can be enabled with the "addr-gen-mode" property's "stable- + privacy" setting as another way of avoiding host tracking with IPv6 + addresses.""" may_fail: Optional[bool] = field( - metadata={'dbus_name': 'may-fail', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'may-fail', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, allow overall network configuration to proceed even if the - configuration specified by this property times out. Note that at least one IP - configuration must succeed or overall network configuration will still fail. - For example, in IPv6-only networks, setting this property to TRUE on the - NMSettingIP4Config allows the overall network configuration to succeed if IPv4 - configuration fails but IPv6 configuration completes successfully.""" + configuration specified by this property times out. Note that at + least one IP configuration must succeed or overall network + configuration will still fail. For example, in IPv6-only networks, + setting this property to TRUE on the NMSettingIP4Config allows the + overall network configuration to succeed if IPv4 configuration fails + but IPv6 configuration completes successfully.""" method: Optional[str] = field( - metadata={'dbus_name': 'method', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'method', + 'dbus_type': 's', + }, default=None, ) - """IP configuration method. NMSettingIP4Config and NMSettingIP6Config both - support "disabled", "auto", "manual", and "link-local". See the subclass- - specific documentation for other values. In general, for the "auto" method, - properties such as "dns" and "routes" specify information that is added on to - the information returned from automatic configuration. The "ignore-auto- - routes" and "ignore-auto-dns" properties modify this behavior. For methods - that imply no upstream network, such as "shared" or "link-local", these - properties must be empty. For IPv4 method "shared", the IP subnet can be - configured by adding one manual IPv4 address or otherwise 10.42.x.0/24 is - chosen. Note that the shared method must be configured on the interface which + """IP configuration method. + + NMSettingIP4Config and NMSettingIP6Config both support "disabled", + "auto", "manual", and "link-local". See the subclass-specific + documentation for other values. + + In general, for the "auto" method, properties such as "dns" and + "routes" specify information that is added on to the information + returned from automatic configuration. The "ignore-auto-routes" and + "ignore-auto-dns" properties modify this behavior. + + For methods that imply no upstream network, such as "shared" or + "link-local", these properties must be empty. + + For IPv4 method "shared", the IP subnet can be configured by adding + one manual IPv4 address or otherwise 10.42.x.0/24 is chosen. Note + that the shared method must be configured on the interface which shares the internet to a subnet, not on the uplink which is shared.""" + mtu: Optional[int] = field( + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, + default=None, + ) + """Maximum transmission unit size, in bytes. If zero (the default), the MTU + is set automatically from router advertisements or is left equal to + the link-layer MTU. If greater than the link-layer MTU, or greater + than zero but less than the minimum IPv6 MTU of 1280, this value has + no effect.""" never_default: Optional[bool] = field( - metadata={'dbus_name': 'never-default', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'never-default', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE, this connection will never be the default connection for this IP - type, meaning it will never be assigned the default route by + """If TRUE, this connection will never be the default connection for this + IP type, meaning it will never be assigned the default route by NetworkManager.""" ra_timeout: Optional[int] = field( - metadata={'dbus_name': 'ra-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'ra-timeout', + 'dbus_type': 'i', + }, default=None, ) """A timeout for waiting Router Advertisements in seconds. If zero (the - default), a globally configured default is used. If still unspecified, the - timeout depends on the sysctl settings of the device. Set to 2147483647 - (MAXINT32) for infinity.""" + default), a globally configured default is used. If still + unspecified, the timeout depends on the sysctl settings of the + device. + + Set to 2147483647 (MAXINT32) for infinity.""" required_timeout: Optional[int] = field( - metadata={'dbus_name': 'required-timeout', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'required-timeout', + 'dbus_type': 'i', + }, default=None, ) """The minimum time interval in milliseconds for which dynamic IP - configuration should be tried before the connection succeeds. This property is - useful for example if both IPv4 and IPv6 are enabled and are allowed to fail. - Normally the connection succeeds as soon as one of the two address families - completes; by setting a required timeout for e.g. IPv4, one can ensure that - even if IP6 succeeds earlier than IPv4, NetworkManager waits some time for - IPv4 before the connection becomes active. Note that if "may-fail" is FALSE - for the same address family, this property has no effect as NetworkManager - needs to wait for the full DHCP timeout. A zero value means that no required - timeout is present, -1 means the default value (either configuration - ipvx.required-timeout override or zero).""" + configuration should be tried before the connection succeeds. + + This property is useful for example if both IPv4 and IPv6 are + enabled and are allowed to fail. Normally the connection succeeds as + soon as one of the two address families completes; by setting a + required timeout for e.g. IPv4, one can ensure that even if IP6 + succeeds earlier than IPv4, NetworkManager waits some time for IPv4 + before the connection becomes active. + + Note that if "may-fail" is FALSE for the same address family, this + property has no effect as NetworkManager needs to wait for the full + DHCP timeout. + + A zero value means that no required timeout is present, -1 means the + default value (either configuration ipvx.required-timeout override + or zero).""" route_data: Optional[List[RouteData]] = field( - metadata={'dbus_name': 'route-data', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': RouteData}, + metadata={ + 'dbus_name': 'route-data', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': RouteData, + }, default=None, ) + """Array of IPv6 routes. Each route dictionary contains at least 'dest' and + 'prefix' entries, containing the destination IP address as a string, + and the prefix length as a uint32. Most routes will also have a + 'next-hop' entry, containing the next hop IP address as a string. If + the route has a 'metric' entry (containing a uint32), that will be + used as the metric for the route (otherwise NM will pick a default + value appropriate to the device). Additional attributes may also + exist on some routes.""" route_metric: Optional[int] = field( - metadata={'dbus_name': 'route-metric', 'dbus_type': 'x'}, + metadata={ + 'dbus_name': 'route-metric', + 'dbus_type': 'x', + }, default=None, ) - """The default metric for routes that don't explicitly specify a metric. The - default value -1 means that the metric is chosen automatically based on the - device type. The metric applies to dynamic routes, manual (static) routes that - don't have an explicit metric setting, address prefix routes, and the default - route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 - (user default). Hence, setting this property to zero effectively mean setting - it to 1024. For IPv4, zero is a regular value for the metric.""" + """The default metric for routes that don't explicitly specify a metric. + The default value -1 means that the metric is chosen automatically + based on the device type. The metric applies to dynamic routes, + manual (static) routes that don't have an explicit metric setting, + address prefix routes, and the default route. Note that for IPv6, + the kernel accepts zero (0) but coerces it to 1024 (user default). + Hence, setting this property to zero effectively mean setting it to + 1024. For IPv4, zero is a regular value for the metric.""" route_table: Optional[int] = field( - metadata={'dbus_name': 'route-table', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'route-table', + 'dbus_type': 'u', + }, default=None, ) - """Enable policy routing (source routing) and set the routing table used when - adding routes. This affects all routes, including device-routes, IPv4LL, DHCP, - SLAAC, default-routes and static routes. But note that static routes can - individually overwrite the setting by explicitly specifying a non-zero routing - table. If the table setting is left at zero, it is eligible to be overwritten - via global configuration. If the property is zero even after applying the - global configuration value, policy routing is disabled for the address family - of this connection. Policy routing disabled means that NetworkManager will add - all routes to the main table (except static routes that explicitly configure a - different table). Additionally, NetworkManager will not delete any extraneous - routes from tables except the main table. This is to preserve backward - compatibility for users who manage routing tables outside of - NetworkManager.""" + """Enable policy routing (source routing) and set the routing table used + when adding routes. + + This affects all routes, including device-routes, IPv4LL, DHCP, + SLAAC, default-routes and static routes. But note that static routes + can individually overwrite the setting by explicitly specifying a + non-zero routing table. + + If the table setting is left at zero, it is eligible to be + overwritten via global configuration. If the property is zero even + after applying the global configuration value, policy routing is + disabled for the address family of this connection. + + Policy routing disabled means that NetworkManager will add all + routes to the main table (except static routes that explicitly + configure a different table). Additionally, NetworkManager will not + delete any extraneous routes from tables except the main table. This + is to preserve backward compatibility for users who manage routing + tables outside of NetworkManager.""" + routing_rules: Optional[List[RoutingRules]] = field( + metadata={ + 'dbus_name': 'routing-rules', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': RoutingRules, + }, + default=None, + ) + """Array of dictionaries for routing rules. Each routing rule supports the + following options: action (y), dport-end (q), dport-start (q), + family (i), from (s), from-len (y), fwmark (u), fwmask (u), iifname + (s), invert (b), ipproto (s), oifname (s), priority (u), sport-end + (q), sport-start (q), supress-prefixlength (i), table (u), to (s), + tos (y), to-len (y), range-end (u), range-start (u).""" token: Optional[str] = field( - metadata={'dbus_name': 'token', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'token', + 'dbus_type': 's', + }, default=None, ) - """Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 IPv6 - tokenized interface identifiers. Useful with eui64 addr-gen-mode.""" + """Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 + IPv6 tokenized interface identifiers. Useful with eui64 addr-gen- + mode.""" diff --git a/sdbus_async/networkmanager/settings/lowpan.py b/sdbus_async/networkmanager/settings/lowpan.py index dfd837c..ae988ad 100644 --- a/sdbus_async/networkmanager/settings/lowpan.py +++ b/sdbus_async/networkmanager/settings/lowpan.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,7 +12,10 @@ class LowpanSettings(NetworkManagerSettingsMixin): """6LoWPAN Settings""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) """If given, specifies the parent interface name or parent connection UUID diff --git a/sdbus_async/networkmanager/settings/macsec.py b/sdbus_async/networkmanager/settings/macsec.py index 2eb7003..95c40df 100644 --- a/sdbus_async/networkmanager/settings/macsec.py +++ b/sdbus_async/networkmanager/settings/macsec.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,52 +12,82 @@ class MacsecSettings(NetworkManagerSettingsMixin): """MACSec Settings""" encrypt: Optional[bool] = field( - metadata={'dbus_name': 'encrypt', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'encrypt', + 'dbus_type': 'b', + }, + default=None, ) + """Whether the transmitted traffic must be encrypted.""" mka_cak: Optional[str] = field( - metadata={'dbus_name': 'mka-cak', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'mka-cak', + 'dbus_type': 's', + }, default=None, ) """The pre-shared CAK (Connectivity Association Key) for MACsec Key Agreement.""" mka_cak_flags: Optional[int] = field( - metadata={'dbus_name': 'mka-cak-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'mka-cak-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "mka-cak" property.""" mka_ckn: Optional[str] = field( - metadata={'dbus_name': 'mka-ckn', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'mka-ckn', + 'dbus_type': 's', + }, default=None, ) """The pre-shared CKN (Connectivity-association Key Name) for MACsec Key Agreement.""" mode: Optional[int] = field( - metadata={'dbus_name': 'mode', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'mode', + 'dbus_type': 'i', + }, default=None, ) """Specifies how the CAK (Connectivity Association Key) for MKA (MACsec Key Agreement) is obtained.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) """If given, specifies the parent interface name or parent connection UUID - from which this MACSEC interface should be created. If this property is not - specified, the connection must contain an "802-3-ethernet" setting with a - "mac-address" property.""" + from which this MACSEC interface should be created. If this + property is not specified, the connection must contain an + "802-3-ethernet" setting with a "mac-address" property.""" port: Optional[int] = field( - metadata={'dbus_name': 'port', 'dbus_type': 'i'}, - default=1, + metadata={ + 'dbus_name': 'port', + 'dbus_type': 'i', + }, + default=None, ) """The port component of the SCI (Secure Channel Identifier), between 1 and 65534.""" send_sci: Optional[bool] = field( - metadata={'dbus_name': 'send-sci', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'send-sci', + 'dbus_type': 'b', + }, + default=None, ) - """Specifies whether the SCI (Secure Channel Identifier) is included in every - packet.""" + """Specifies whether the SCI (Secure Channel Identifier) is included in + every packet.""" validation: Optional[int] = field( - metadata={'dbus_name': 'validation', 'dbus_type': 'i'}, - default=2, + metadata={ + 'dbus_name': 'validation', + 'dbus_type': 'i', + }, + default=None, ) + """Specifies the validation mode for incoming frames.""" diff --git a/sdbus_async/networkmanager/settings/macvlan.py b/sdbus_async/networkmanager/settings/macvlan.py index b670c63..bd5017f 100644 --- a/sdbus_async/networkmanager/settings/macvlan.py +++ b/sdbus_async/networkmanager/settings/macvlan.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,24 +12,38 @@ class MacvlanSettings(NetworkManagerSettingsMixin): """MAC VLAN Settings""" mode: Optional[int] = field( - metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mode', + 'dbus_type': 'u', + }, default=None, ) """The macvlan mode, which specifies the communication mechanism between multiple macvlans on the same lower device.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) """If given, specifies the parent interface name or parent connection UUID - from which this MAC-VLAN interface should be created. If this property is not - specified, the connection must contain an "802-3-ethernet" setting with a - "mac-address" property.""" + from which this MAC-VLAN interface should be created. If this + property is not specified, the connection must contain an + "802-3-ethernet" setting with a "mac-address" property.""" promiscuous: Optional[bool] = field( - metadata={'dbus_name': 'promiscuous', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'promiscuous', + 'dbus_type': 'b', + }, + default=None, ) + """Whether the interface should be put in promiscuous mode.""" tap: Optional[bool] = field( - metadata={'dbus_name': 'tap', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'tap', + 'dbus_type': 'b', + }, + default=None, ) + """Whether the interface should be a MACVTAP.""" diff --git a/sdbus_async/networkmanager/settings/match.py b/sdbus_async/networkmanager/settings/match.py index 946eff2..048dc6e 100644 --- a/sdbus_async/networkmanager/settings/match.py +++ b/sdbus_async/networkmanager/settings/match.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,55 +12,83 @@ class MatchSettings(NetworkManagerSettingsMixin): """Match settings""" driver: Optional[List[str]] = field( - metadata={'dbus_name': 'driver', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'driver', + 'dbus_type': 'as', + }, default=None, ) - """A list of driver names to match. Each element is a shell wildcard pattern. - See NMSettingMatch:interface-name for how special characters '\|', '&', '!' - and '\\' are used for optional and mandatory matches and inverting the - pattern.""" + """A list of driver names to match. Each element is a shell wildcard + pattern. + + See NMSettingMatch:interface-name for how special characters '|', + '&', '!' and '\\' are used for optional and mandatory matches and + inverting the pattern.""" interface_name: Optional[List[str]] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 'as', + }, default=None, ) """A list of interface names to match. Each element is a shell wildcard - pattern. An element can be prefixed with a pipe symbol (\|) or an ampersand - (&). The former means that the element is optional and the latter means that - it is mandatory. If there are any optional elements, than the match evaluates - to true if at least one of the optional element matches (logical OR). If there - are any mandatory elements, then they all must match (logical AND). By - default, an element is optional. This means that an element "foo" behaves the - same as "\|foo". An element can also be inverted with exclamation mark (!) - between the pipe symbol (or the ampersand) and before the pattern. Note that - "!foo" is a shortcut for the mandatory match "&!foo". Finally, a backslash can - be used at the beginning of the element (after the optional special - characters) to escape the start of the pattern. For example, "&\\!a" is an - mandatory match for literally "!a".""" + pattern. + + An element can be prefixed with a pipe symbol (|) or an ampersand + (&). The former means that the element is optional and the latter + means that it is mandatory. If there are any optional elements, than + the match evaluates to true if at least one of the optional element + matches (logical OR). If there are any mandatory elements, then they + all must match (logical AND). By default, an element is optional. + This means that an element "foo" behaves the same as "|foo". An + element can also be inverted with exclamation mark (!) between the + pipe symbol (or the ampersand) and before the pattern. Note that + "!foo" is a shortcut for the mandatory match "&!foo". Finally, a + backslash can be used at the beginning of the element (after the + optional special characters) to escape the start of the pattern. For + example, "&\\!a" is an mandatory match for literally "!a".""" kernel_command_line: Optional[List[str]] = field( - metadata={'dbus_name': 'kernel-command-line', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'kernel-command-line', + 'dbus_type': 'as', + }, default=None, ) - """A list of kernel command line arguments to match. This may be used to check - whether a specific kernel command line option is set (or unset, if prefixed - with the exclamation mark). The argument must either be a single word, or an - assignment (i.e. two words, joined by "="). In the former case the kernel - command line is searched for the word appearing as is, or as left hand side of - an assignment. In the latter case, the exact assignment is looked for with - right and left hand side matching. Wildcard patterns are not supported. See - NMSettingMatch:interface-name for how special characters '\|', '&', '!' and - '\\' are used for optional and mandatory matches and inverting the match.""" + """A list of kernel command line arguments to match. This may be used to + check whether a specific kernel command line option is set (or + unset, if prefixed with the exclamation mark). The argument must + either be a single word, or an assignment (i.e. two words, joined by + "="). In the former case the kernel command line is searched for the + word appearing as is, or as left hand side of an assignment. In the + latter case, the exact assignment is looked for with right and left + hand side matching. Wildcard patterns are not supported. + + See NMSettingMatch:interface-name for how special characters '|', + '&', '!' and '\\' are used for optional and mandatory matches and + inverting the match.""" path: Optional[List[str]] = field( - metadata={'dbus_name': 'path', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'path', + 'dbus_type': 'as', + }, default=None, ) """A list of paths to match against the ID_PATH udev property of devices. - ID_PATH represents the topological persistent path of a device. It typically - contains a subsystem string (pci, usb, platform, etc.) and a subsystem- - specific identifier. For PCI devices the path has the form - "pci-$domain:$bus:$device.$function", where each variable is an hexadecimal - value; for example "pci-0000:0a:00.0". The path of a device can be obtained - with "udevadm info /sys/class/net/$dev \| grep ID_PATH=" or by looking at the - "path" property exported by NetworkManager ("nmcli -f general.path device show - $dev"). Each element of the list is a shell wildcard pattern. See - NMSettingMatch:interface-name for how special characters '\|', '&', '!' and - '\\' are used for optional and mandatory matches and inverting the pattern.""" + ID_PATH represents the topological persistent path of a device. It + typically contains a subsystem string (pci, usb, platform, etc.) and + a subsystem-specific identifier. + + For PCI devices the path has the form + "pci-$domain:$bus:$device.$function", where each variable is an + hexadecimal value; for example "pci-0000:0a:00.0". + + The path of a device can be obtained with "udevadm info + /sys/class/net/$dev | grep ID_PATH=" or by looking at the "path" + property exported by NetworkManager ("nmcli -f general.path device + show $dev"). + + Each element of the list is a shell wildcard pattern. + + See NMSettingMatch:interface-name for how special characters '|', + '&', '!' and '\\' are used for optional and mandatory matches and + inverting the pattern.""" diff --git a/sdbus_async/networkmanager/settings/olpc_mesh.py b/sdbus_async/networkmanager/settings/olpc_mesh.py index 68c69cc..f4e149c 100644 --- a/sdbus_async/networkmanager/settings/olpc_mesh.py +++ b/sdbus_async/networkmanager/settings/olpc_mesh.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,17 +12,30 @@ class OlpcMeshSettings(NetworkManagerSettingsMixin): """OLPC Wireless Mesh Settings""" channel: Optional[int] = field( - metadata={'dbus_name': 'channel', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'channel', + 'dbus_type': 'u', + }, default=None, ) + """Channel on which the mesh network to join is located.""" dhcp_anycast_address: Optional[bytes] = field( - metadata={'dbus_name': 'dhcp-anycast-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'dhcp-anycast-address', + 'dbus_type': 'ay', + }, default=None, ) - """Anycast DHCP MAC address used when requesting an IP address via DHCP. The - specific anycast address used determines which DHCP server class answers the - request. This is currently only implemented by dhclient DHCP plugin.""" + """Anycast DHCP MAC address used when requesting an IP address via DHCP. + The specific anycast address used determines which DHCP server class + answers the request. + + This is currently only implemented by dhclient DHCP plugin.""" ssid: Optional[bytes] = field( - metadata={'dbus_name': 'ssid', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'ssid', + 'dbus_type': 'ay', + }, default=None, ) + """SSID of the mesh network to join.""" diff --git a/sdbus_async/networkmanager/settings/ovs_bridge.py b/sdbus_async/networkmanager/settings/ovs_bridge.py index 428a1f6..7167450 100644 --- a/sdbus_async/networkmanager/settings/ovs_bridge.py +++ b/sdbus_async/networkmanager/settings/ovs_bridge.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,22 +12,42 @@ class OvsBridgeSettings(NetworkManagerSettingsMixin): """OvsBridge Link Settings""" datapath_type: Optional[str] = field( - metadata={'dbus_name': 'datapath-type', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'datapath-type', + 'dbus_type': 's', + }, default=None, ) + """The data path type. One of "system", "netdev" or empty.""" fail_mode: Optional[str] = field( - metadata={'dbus_name': 'fail-mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'fail-mode', + 'dbus_type': 's', + }, default=None, ) + """The bridge failure mode. One of "secure", "standalone" or empty.""" mcast_snooping_enable: Optional[bool] = field( - metadata={'dbus_name': 'mcast-snooping-enable', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'mcast-snooping-enable', + 'dbus_type': 'b', + }, + default=None, ) + """Enable or disable multicast snooping.""" rstp_enable: Optional[bool] = field( - metadata={'dbus_name': 'rstp-enable', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'rstp-enable', + 'dbus_type': 'b', + }, + default=None, ) + """Enable or disable RSTP.""" stp_enable: Optional[bool] = field( - metadata={'dbus_name': 'stp-enable', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'stp-enable', + 'dbus_type': 'b', + }, + default=None, ) + """Enable or disable STP.""" diff --git a/sdbus_async/networkmanager/settings/ovs_dpdk.py b/sdbus_async/networkmanager/settings/ovs_dpdk.py index 27faa6f..b078909 100644 --- a/sdbus_async/networkmanager/settings/ovs_dpdk.py +++ b/sdbus_async/networkmanager/settings/ovs_dpdk.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,13 +12,20 @@ class OvsDpdkSettings(NetworkManagerSettingsMixin): """OvsDpdk Link Settings""" devargs: Optional[str] = field( - metadata={'dbus_name': 'devargs', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'devargs', + 'dbus_type': 's', + }, default=None, ) + """Open vSwitch DPDK device arguments.""" n_rxq: Optional[int] = field( - metadata={'dbus_name': 'n-rxq', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'n-rxq', + 'dbus_type': 'u', + }, default=None, ) """Open vSwitch DPDK number of rx queues. Defaults to zero which means to - leave the parameter in OVS unspecified and effectively configures one - queue.""" + leave the parameter in OVS unspecified and effectively configures + one queue.""" diff --git a/sdbus_async/networkmanager/settings/ovs_external_ids.py b/sdbus_async/networkmanager/settings/ovs_external_ids.py index 304b4b1..de28638 100644 --- a/sdbus_async/networkmanager/settings/ovs_external_ids.py +++ b/sdbus_async/networkmanager/settings/ovs_external_ids.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,6 +12,10 @@ class OvsExternalIdsSettings(NetworkManagerSettingsMixin): """OVS External IDs Settings""" data: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 'data', 'dbus_type': 'a{ss}'}, + metadata={ + 'dbus_name': 'data', + 'dbus_type': 'a{ss}', + }, default=None, ) + """A dictionary of key/value pairs with exernal-ids for OVS.""" diff --git a/sdbus_async/networkmanager/settings/ovs_interface.py b/sdbus_async/networkmanager/settings/ovs_interface.py index d655cd7..dbe4f29 100644 --- a/sdbus_async/networkmanager/settings/ovs_interface.py +++ b/sdbus_async/networkmanager/settings/ovs_interface.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -11,8 +11,23 @@ class OvsInterfaceSettings(NetworkManagerSettingsMixin): """Open vSwitch Interface Settings""" + ofport_request: Optional[int] = field( + metadata={ + 'dbus_name': 'ofport-request', + 'dbus_type': 'u', + }, + default=None, + ) + """Open vSwitch openflow port number. Defaults to zero which means that + port number will not be specified and it will be chosen randomly by + ovs. OpenFlow ports are the network interfaces for passing packets + between OpenFlow processing and the rest of the network. OpenFlow + switches connect logically to each other via their OpenFlow ports.""" ovs_interface_type: Optional[str] = field( - metadata={'dbus_name': 'type', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'type', + 'dbus_type': 's', + }, default=None, ) """The interface type. Either "internal", "system", "patch", "dpdk", or diff --git a/sdbus_async/networkmanager/settings/ovs_patch.py b/sdbus_async/networkmanager/settings/ovs_patch.py index fba70b9..45cb376 100644 --- a/sdbus_async/networkmanager/settings/ovs_patch.py +++ b/sdbus_async/networkmanager/settings/ovs_patch.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,7 +12,10 @@ class OvsPatchSettings(NetworkManagerSettingsMixin): """OvsPatch Link Settings""" peer: Optional[str] = field( - metadata={'dbus_name': 'peer', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'peer', + 'dbus_type': 's', + }, default=None, ) """Specifies the name of the interface for the other side of the patch. The diff --git a/sdbus_async/networkmanager/settings/ovs_port.py b/sdbus_async/networkmanager/settings/ovs_port.py index 1e8744d..898fd31 100644 --- a/sdbus_async/networkmanager/settings/ovs_port.py +++ b/sdbus_async/networkmanager/settings/ovs_port.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,28 +12,51 @@ class OvsPortSettings(NetworkManagerSettingsMixin): """OvsPort Link Settings""" bond_downdelay: Optional[int] = field( - metadata={'dbus_name': 'bond-downdelay', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'bond-downdelay', + 'dbus_type': 'u', + }, default=None, ) + """The time port must be inactive in order to be considered down.""" bond_mode: Optional[str] = field( - metadata={'dbus_name': 'bond-mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'bond-mode', + 'dbus_type': 's', + }, default=None, ) + """Bonding mode. One of "active-backup", "balance-slb", or "balance-tcp".""" bond_updelay: Optional[int] = field( - metadata={'dbus_name': 'bond-updelay', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'bond-updelay', + 'dbus_type': 'u', + }, default=None, ) + """The time port must be active before it starts forwarding traffic.""" lacp: Optional[str] = field( - metadata={'dbus_name': 'lacp', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'lacp', + 'dbus_type': 's', + }, default=None, ) + """LACP mode. One of "active", "off", or "passive".""" tag: Optional[int] = field( - metadata={'dbus_name': 'tag', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'tag', + 'dbus_type': 'u', + }, default=None, ) + """The VLAN tag in the range 0-4095.""" vlan_mode: Optional[str] = field( - metadata={'dbus_name': 'vlan-mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'vlan-mode', + 'dbus_type': 's', + }, default=None, ) - """The VLAN mode. One of "access", "native-tagged", "native-untagged", "trunk" - or unset.""" + """The VLAN mode. One of "access", "native-tagged", "native-untagged", + "trunk" or unset.""" diff --git a/sdbus_async/networkmanager/settings/ppp.py b/sdbus_async/networkmanager/settings/ppp.py index 2251a06..ab79f66 100644 --- a/sdbus_async/networkmanager/settings/ppp.py +++ b/sdbus_async/networkmanager/settings/ppp.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,105 +12,168 @@ class PppSettings(NetworkManagerSettingsMixin): """Point-to-Point Protocol Settings""" baud: Optional[int] = field( - metadata={'dbus_name': 'baud', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'baud', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, instruct pppd to set the serial port to the specified - baudrate. This value should normally be left as 0 to automatically choose the - speed.""" + baudrate. This value should normally be left as 0 to automatically + choose the speed.""" crtscts: Optional[bool] = field( - metadata={'dbus_name': 'crtscts', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'crtscts', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE, specify that pppd should set the serial port to use hardware flow - control with RTS and CTS signals. This value should normally be set to - FALSE.""" + """If TRUE, specify that pppd should set the serial port to use hardware + flow control with RTS and CTS signals. This value should normally + be set to FALSE.""" lcp_echo_failure: Optional[int] = field( - metadata={'dbus_name': 'lcp-echo-failure', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'lcp-echo-failure', + 'dbus_type': 'u', + }, default=None, ) - """If non-zero, instruct pppd to presume the connection to the peer has failed - if the specified number of LCP echo-requests go unanswered by the peer. The - "lcp-echo-interval" property must also be set to a non-zero value if this - property is used.""" + """If non-zero, instruct pppd to presume the connection to the peer has + failed if the specified number of LCP echo-requests go unanswered by + the peer. The "lcp-echo-interval" property must also be set to a + non-zero value if this property is used.""" lcp_echo_interval: Optional[int] = field( - metadata={'dbus_name': 'lcp-echo-interval', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'lcp-echo-interval', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, instruct pppd to send an LCP echo-request frame to the peer - every n seconds (where n is the specified value). Note that some PPP peers - will respond to echo requests and some will not, and it is not possible to - autodetect this.""" + every n seconds (where n is the specified value). Note that some + PPP peers will respond to echo requests and some will not, and it is + not possible to autodetect this.""" mppe_stateful: Optional[bool] = field( - metadata={'dbus_name': 'mppe-stateful', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'mppe-stateful', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, stateful MPPE is used. See pppd documentation for more information on stateful MPPE.""" mru: Optional[int] = field( - metadata={'dbus_name': 'mru', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mru', + 'dbus_type': 'u', + }, default=None, ) - """If non-zero, instruct pppd to request that the peer send packets no larger - than the specified size. If non-zero, the MRU should be between 128 and - 16384.""" + """If non-zero, instruct pppd to request that the peer send packets no + larger than the specified size. If non-zero, the MRU should be + between 128 and 16384.""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, instruct pppd to send packets no larger than the specified size.""" no_vj_comp: Optional[bool] = field( - metadata={'dbus_name': 'no-vj-comp', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'no-vj-comp', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, Van Jacobsen TCP header compression will not be requested.""" noauth: Optional[bool] = field( - metadata={'dbus_name': 'noauth', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'noauth', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, do not require the other side (usually the PPP server) to - authenticate itself to the client. If FALSE, require authentication from the - remote side. In almost all cases, this should be TRUE.""" + authenticate itself to the client. If FALSE, require authentication + from the remote side. In almost all cases, this should be TRUE.""" nobsdcomp: Optional[bool] = field( - metadata={'dbus_name': 'nobsdcomp', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'nobsdcomp', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, BSD compression will not be requested.""" nodeflate: Optional[bool] = field( - metadata={'dbus_name': 'nodeflate', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'nodeflate', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, "deflate" compression will not be requested.""" refuse_chap: Optional[bool] = field( - metadata={'dbus_name': 'refuse-chap', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'refuse-chap', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, the CHAP authentication method will not be used.""" refuse_eap: Optional[bool] = field( - metadata={'dbus_name': 'refuse-eap', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'refuse-eap', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, the EAP authentication method will not be used.""" refuse_mschap: Optional[bool] = field( - metadata={'dbus_name': 'refuse-mschap', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'refuse-mschap', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, the MSCHAP authentication method will not be used.""" refuse_mschapv2: Optional[bool] = field( - metadata={'dbus_name': 'refuse-mschapv2', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'refuse-mschapv2', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, the MSCHAPv2 authentication method will not be used.""" refuse_pap: Optional[bool] = field( - metadata={'dbus_name': 'refuse-pap', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'refuse-pap', + 'dbus_type': 'b', + }, + default=None, ) + """If TRUE, the PAP authentication method will not be used.""" require_mppe: Optional[bool] = field( - metadata={'dbus_name': 'require-mppe', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'require-mppe', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, MPPE (Microsoft Point-to-Point Encryption) will be required for - the PPP session. If either 64-bit or 128-bit MPPE is not available the - session will fail. Note that MPPE is not used on mobile broadband - connections.""" + the PPP session. If either 64-bit or 128-bit MPPE is not available + the session will fail. Note that MPPE is not used on mobile + broadband connections.""" require_mppe_128: Optional[bool] = field( - metadata={'dbus_name': 'require-mppe-128', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'require-mppe-128', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encryption) will be - required for the PPP session, and the "require-mppe" property must also be set - to TRUE. If 128-bit MPPE is not available the session will fail.""" + required for the PPP session, and the "require-mppe" property must + also be set to TRUE. If 128-bit MPPE is not available the session + will fail.""" diff --git a/sdbus_async/networkmanager/settings/pppoe.py b/sdbus_async/networkmanager/settings/pppoe.py index faf9a1f..3d6c4d7 100644 --- a/sdbus_async/networkmanager/settings/pppoe.py +++ b/sdbus_async/networkmanager/settings/pppoe.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,30 +12,49 @@ class PppoeSettings(NetworkManagerSettingsMixin): """PPP-over-Ethernet Settings""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) """If given, specifies the parent interface name on which this PPPoE - connection should be created. If this property is not specified, the - connection is activated on the interface specified in "interface-name" of - NMSettingConnection.""" + connection should be created. If this property is not specified, + the connection is activated on the interface specified in + "interface-name" of NMSettingConnection.""" password: Optional[str] = field( - metadata={'dbus_name': 'password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'password', + 'dbus_type': 's', + }, default=None, ) + """Password used to authenticate with the PPPoE service.""" password_flags: Optional[int] = field( - metadata={'dbus_name': 'password-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'password-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "password" property.""" service: Optional[str] = field( - metadata={'dbus_name': 'service', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'service', + 'dbus_type': 's', + }, default=None, ) """If specified, instruct PPPoE to only initiate sessions with access - concentrators that provide the specified service. For most providers, this - should be left blank. It is only required if there are multiple access - concentrators or a specific service is known to be required.""" + concentrators that provide the specified service. For most + providers, this should be left blank. It is only required if there + are multiple access concentrators or a specific service is known to + be required.""" username: Optional[str] = field( - metadata={'dbus_name': 'username', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'username', + 'dbus_type': 's', + }, default=None, ) + """Username used to authenticate with the PPPoE service.""" diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index d8bf643..b65c149 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -1,12 +1,12 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field, fields from typing import Any, Dict, Optional from .base import NetworkManagerSettingsMixin -from .connection import ConnectionSettings -from .ipv4 import Ipv4Settings -from .ipv6 import Ipv6Settings from .adsl import AdslSettings from .bluetooth import BluetoothSettings from .bond import BondSettings @@ -14,13 +14,19 @@ from .bridge import BridgeSettings from .bridge_port import BridgePortSettings from .cdma import CdmaSettings +from .connection import ConnectionSettings from .dcb import DcbSettings +from .dummy import DummySettings +from .eapol import EapolSettings from .ethernet import EthernetSettings +from .ethtool import EthtoolSettings +from .generic import GenericSettings from .gsm import GsmSettings from .hostname import HostnameSettings -from .ieee802_1x import Ieee8021XSettings from .infiniband import InfinibandSettings from .ip_tunnel import IpTunnelSettings +from .ipv4 import Ipv4Settings +from .ipv6 import Ipv6Settings from .lowpan import LowpanSettings from .macsec import MacsecSettings from .macvlan import MacvlanSettings @@ -36,6 +42,8 @@ from .pppoe import PppoeSettings from .proxy import ProxySettings from .serial import SerialSettings +from .sriov import SriovSettings +from .tc import TcSettings from .team import TeamSettings from .team_port import TeamPortSettings from .tun import TunSettings @@ -95,21 +103,11 @@ class ConnectionProfile: 'settings_class': ConnectionSettings}, ) # The list of the remaining settings classes was generated by - # tools/generate-settings-dataclasses.py which generates the + # tools/generate-settings-dataclasses-jinja.py which generates the # settings classes themselfes as well. # If possible, please make changes by also updating the script. # start of the generated list of settings classes - ipv4: Optional[Ipv4Settings] = field( - metadata={'dbus_name': 'ipv4', - 'settings_class': Ipv4Settings}, - default=None, - ) - ipv6: Optional[Ipv6Settings] = field( - metadata={'dbus_name': 'ipv6', - 'settings_class': Ipv6Settings}, - default=None, - ) adsl: Optional[AdslSettings] = field( metadata={'dbus_name': 'adsl', 'settings_class': AdslSettings}, @@ -145,16 +143,41 @@ class ConnectionProfile: 'settings_class': CdmaSettings}, default=None, ) + connection: Optional[ConnectionSettings] = field( + metadata={'dbus_name': 'connection', + 'settings_class': ConnectionSettings}, + default=None, + ) dcb: Optional[DcbSettings] = field( metadata={'dbus_name': 'dcb', 'settings_class': DcbSettings}, default=None, ) + dummy: Optional[DummySettings] = field( + metadata={'dbus_name': 'dummy', + 'settings_class': DummySettings}, + default=None, + ) + eapol: Optional[EapolSettings] = field( + metadata={'dbus_name': '802-1x', + 'settings_class': EapolSettings}, + default=None, + ) ethernet: Optional[EthernetSettings] = field( metadata={'dbus_name': '802-3-ethernet', 'settings_class': EthernetSettings}, default=None, ) + ethtool: Optional[EthtoolSettings] = field( + metadata={'dbus_name': 'ethtool', + 'settings_class': EthtoolSettings}, + default=None, + ) + generic: Optional[GenericSettings] = field( + metadata={'dbus_name': 'generic', + 'settings_class': GenericSettings}, + default=None, + ) gsm: Optional[GsmSettings] = field( metadata={'dbus_name': 'gsm', 'settings_class': GsmSettings}, @@ -165,11 +188,6 @@ class ConnectionProfile: 'settings_class': HostnameSettings}, default=None, ) - ieee802_1x: Optional[Ieee8021XSettings] = field( - metadata={'dbus_name': '802-1x', - 'settings_class': Ieee8021XSettings}, - default=None, - ) infiniband: Optional[InfinibandSettings] = field( metadata={'dbus_name': 'infiniband', 'settings_class': InfinibandSettings}, @@ -180,6 +198,16 @@ class ConnectionProfile: 'settings_class': IpTunnelSettings}, default=None, ) + ipv4: Optional[Ipv4Settings] = field( + metadata={'dbus_name': 'ipv4', + 'settings_class': Ipv4Settings}, + default=None, + ) + ipv6: Optional[Ipv6Settings] = field( + metadata={'dbus_name': 'ipv6', + 'settings_class': Ipv6Settings}, + default=None, + ) lowpan: Optional[LowpanSettings] = field( metadata={'dbus_name': '6lowpan', 'settings_class': LowpanSettings}, @@ -255,6 +283,16 @@ class ConnectionProfile: 'settings_class': SerialSettings}, default=None, ) + sriov: Optional[SriovSettings] = field( + metadata={'dbus_name': 'sriov', + 'settings_class': SriovSettings}, + default=None, + ) + tc: Optional[TcSettings] = field( + metadata={'dbus_name': 'tc', + 'settings_class': TcSettings}, + default=None, + ) team: Optional[TeamSettings] = field( metadata={'dbus_name': 'team', 'settings_class': TeamSettings}, diff --git a/sdbus_async/networkmanager/settings/proxy.py b/sdbus_async/networkmanager/settings/proxy.py index eca2460..6cf2c14 100644 --- a/sdbus_async/networkmanager/settings/proxy.py +++ b/sdbus_async/networkmanager/settings/proxy.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,20 +12,36 @@ class ProxySettings(NetworkManagerSettingsMixin): """WWW Proxy Settings""" browser_only: Optional[bool] = field( - metadata={'dbus_name': 'browser-only', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'browser-only', + 'dbus_type': 'b', + }, + default=None, ) + """Whether the proxy configuration is for browser only.""" method: Optional[int] = field( - metadata={'dbus_name': 'method', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'method', + 'dbus_type': 'i', + }, default=None, ) """Method for proxy configuration, Default is NM_SETTING_PROXY_METHOD_NONE (0)""" pac_script: Optional[str] = field( - metadata={'dbus_name': 'pac-script', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'pac-script', + 'dbus_type': 's', + }, default=None, ) + """PAC script for the connection. This is an UTF-8 encoded javascript code + that defines a FindProxyForURL() function.""" pac_url: Optional[str] = field( - metadata={'dbus_name': 'pac-url', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'pac-url', + 'dbus_type': 's', + }, default=None, ) + """PAC URL for obtaining PAC file.""" diff --git a/sdbus_async/networkmanager/settings/serial.py b/sdbus_async/networkmanager/settings/serial.py index 3e44831..7d07d8c 100644 --- a/sdbus_async/networkmanager/settings/serial.py +++ b/sdbus_async/networkmanager/settings/serial.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,29 +12,45 @@ class SerialSettings(NetworkManagerSettingsMixin): """Serial Link Settings""" baud: Optional[int] = field( - metadata={'dbus_name': 'baud', 'dbus_type': 'u'}, - default=57600, + metadata={ + 'dbus_name': 'baud', + 'dbus_type': 'u', + }, + default=None, ) - """Speed to use for communication over the serial port. Note that this value - usually has no effect for mobile broadband modems as they generally ignore - speed settings and use the highest available speed.""" + """Speed to use for communication over the serial port. Note that this + value usually has no effect for mobile broadband modems as they + generally ignore speed settings and use the highest available speed.""" bits: Optional[int] = field( - metadata={'dbus_name': 'bits', 'dbus_type': 'u'}, - default=8, + metadata={ + 'dbus_name': 'bits', + 'dbus_type': 'u', + }, + default=None, ) + """Byte-width of the serial communication. The 8 in "8n1" for example.""" parity: Optional[int] = field( - metadata={'dbus_name': 'parity', 'dbus_type': 'y'}, + metadata={ + 'dbus_name': 'parity', + 'dbus_type': 'y', + }, default=None, ) - """The connection parity: 69 (ASCII 'E') for even parity, 111 (ASCII 'o') for - odd, 110 (ASCII 'n') for none.""" + """Parity setting of the serial port.""" send_delay: Optional[int] = field( - metadata={'dbus_name': 'send-delay', 'dbus_type': 't'}, + metadata={ + 'dbus_name': 'send-delay', + 'dbus_type': 't', + }, default=None, ) + """Time to delay between each byte sent to the modem, in microseconds.""" stopbits: Optional[int] = field( - metadata={'dbus_name': 'stopbits', 'dbus_type': 'u'}, - default=1, + metadata={ + 'dbus_name': 'stopbits', + 'dbus_type': 'u', + }, + default=None, ) - """Number of stop bits for communication on the serial port. Either 1 or 2. - The 1 in "8n1" for example.""" + """Number of stop bits for communication on the serial port. Either 1 or + 2. The 1 in "8n1" for example.""" diff --git a/sdbus_async/networkmanager/settings/sriov.py b/sdbus_async/networkmanager/settings/sriov.py new file mode 100644 index 0000000..5ed5bc1 --- /dev/null +++ b/sdbus_async/networkmanager/settings/sriov.py @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Any, List, Optional, Tuple +from .base import NetworkManagerSettingsMixin +from .datatypes import Vfs + + +@dataclass +class SriovSettings(NetworkManagerSettingsMixin): + """SR-IOV settings""" + + autoprobe_drivers: Optional[int] = field( + metadata={ + 'dbus_name': 'autoprobe-drivers', + 'dbus_type': 'i', + }, + default=None, + ) + """Whether to autoprobe virtual functions by a compatible driver. + + If set to NM_TERNARY_TRUE (1), the kernel will try to bind VFs to a + compatible driver and if this succeeds a new network interface will + be instantiated for each VF. + + If set to NM_TERNARY_FALSE (0), VFs will not be claimed and no + network interfaces will be created for them. + + When set to NM_TERNARY_DEFAULT (-1), the global default is used; in + case the global default is unspecified it is assumed to be + NM_TERNARY_TRUE (1).""" + total_vfs: Optional[int] = field( + metadata={ + 'dbus_name': 'total-vfs', + 'dbus_type': 'u', + }, + default=None, + ) + """The total number of virtual functions to create. + + Note that when the sriov setting is present NetworkManager enforces + the number of virtual functions on the interface (also when it is + zero) during activation and resets it upon deactivation. To prevent + any changes to SR-IOV parameters don't add a sriov setting to the + connection.""" + vfs: Optional[List[Vfs]] = field( + metadata={ + 'dbus_name': 'vfs', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': Vfs, + }, + default=None, + ) + """Array of virtual function descriptors. + + Each VF descriptor is a dictionary mapping attribute names to + GVariant values. The 'index' entry is mandatory for each VF. + + When represented as string a VF is in the form: + + "INDEX [ATTR=VALUE[ ATTR=VALUE]...]". + + for example: + + "2 mac=00:11:22:33:44:55 spoof-check=true". + + Multiple VFs can be specified using a comma as separator. Currently, + the following attributes are supported: mac, spoof-check, trust, + min-tx-rate, max-tx-rate, vlans. + + The "vlans" attribute is represented as a semicolon-separated list + of VLAN descriptors, where each descriptor has the form + + "ID[.PRIORITY[.PROTO]]". + + PROTO can be either 'q' for 802.1Q (the default) or 'ad' for + 802.1ad.""" diff --git a/sdbus_async/networkmanager/settings/tc.py b/sdbus_async/networkmanager/settings/tc.py new file mode 100644 index 0000000..89c6a49 --- /dev/null +++ b/sdbus_async/networkmanager/settings/tc.py @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# This file was generated by tools/generate-settings-dataclasses-jinja.py, +# if possible, please make changes by also updating the script. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Any, List, Optional, Tuple +from .base import NetworkManagerSettingsMixin +from .datatypes import Qdiscs, Tfilters + + +@dataclass +class TcSettings(NetworkManagerSettingsMixin): + """Linux Traffic Control Settings""" + + qdiscs: Optional[List[Qdiscs]] = field( + metadata={ + 'dbus_name': 'qdiscs', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': Qdiscs, + }, + default=None, + ) + """Array of TC queueing disciplines. + + When the "tc" setting is present, qdiscs from this property are + applied upon activation. If the property is empty, all qdiscs are + removed and the device will only have the default qdisc assigned by + kernel according to the "net.core.default_qdisc" sysctl. + + If the "tc" setting is not present, NetworkManager doesn't touch the + qdiscs present on the interface.""" + tfilters: Optional[List[Tfilters]] = field( + metadata={ + 'dbus_name': 'tfilters', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': Tfilters, + }, + default=None, + ) + """Array of TC traffic filters. + + When the "tc" setting is present, filters from this property are + applied upon activation. If the property is empty, NetworkManager + removes all the filters. + + If the "tc" setting is not present, NetworkManager doesn't touch the + filters present on the interface.""" diff --git a/sdbus_async/networkmanager/settings/team.py b/sdbus_async/networkmanager/settings/team.py index 5646abf..023b025 100644 --- a/sdbus_async/networkmanager/settings/team.py +++ b/sdbus_async/networkmanager/settings/team.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import LinkWatchers @@ -13,81 +13,155 @@ class TeamSettings(NetworkManagerSettingsMixin): """Teaming Settings""" config: Optional[str] = field( - metadata={'dbus_name': 'config', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'config', + 'dbus_type': 's', + }, default=None, ) - """The JSON configuration for the team network interface. The property should - contain raw JSON configuration data suitable for teamd, because the value is - passed directly to teamd. If not specified, the default configuration is used. - See man teamd.conf for the format details.""" + """The JSON configuration for the team network interface. The property + should contain raw JSON configuration data suitable for teamd, + because the value is passed directly to teamd. If not specified, the + default configuration is used. See man teamd.conf for the format + details.""" interface_name: Optional[str] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 's', + }, default=None, ) """Deprecated in favor of connection.interface-name, but can be used for - backward-compatibility with older daemons, to set the team's interface - name.""" + backward-compatibility with older daemons, to set the team's + interface name.""" link_watchers: Optional[List[LinkWatchers]] = field( - metadata={'dbus_name': 'link-watchers', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': LinkWatchers}, + metadata={ + 'dbus_name': 'link-watchers', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': LinkWatchers, + }, default=None, ) + """Link watchers configuration for the connection: each link watcher is + defined by a dictionary, whose keys depend upon the selected link + watcher. Available link watchers are 'ethtool', 'nsna_ping' and + 'arp_ping' and it is specified in the dictionary with the key + 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', + 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', + 'target-host'; arp_ping: all the ones in nsna_ping and 'source- + host', 'validate-active', 'validate-inactive', 'send-always'. See + teamd.conf man for more details.""" mcast_rejoin_count: Optional[int] = field( - metadata={'dbus_name': 'mcast-rejoin-count', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'mcast-rejoin-count', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd mcast_rejoin.count.""" mcast_rejoin_interval: Optional[int] = field( - metadata={'dbus_name': 'mcast-rejoin-interval', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'mcast-rejoin-interval', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd mcast_rejoin.interval.""" notify_peers_count: Optional[int] = field( - metadata={'dbus_name': 'notify-peers-count', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'notify-peers-count', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd notify_peers.count.""" notify_peers_interval: Optional[int] = field( - metadata={'dbus_name': 'notify-peers-interval', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'notify-peers-interval', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd notify_peers.interval.""" runner: Optional[str] = field( - metadata={'dbus_name': 'runner', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'runner', + 'dbus_type': 's', + }, default=None, ) - """Corresponds to the teamd runner.name. Permitted values are: "roundrobin", - "broadcast", "activebackup", "loadbalance", "lacp", "random".""" + """Corresponds to the teamd runner.name. Permitted values are: + "roundrobin", "broadcast", "activebackup", "loadbalance", "lacp", + "random".""" runner_active: Optional[bool] = field( - metadata={'dbus_name': 'runner-active', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'runner-active', + 'dbus_type': 'b', + }, + default=None, ) + """Corresponds to the teamd runner.active.""" runner_agg_select_policy: Optional[str] = field( - metadata={'dbus_name': 'runner-agg-select-policy', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'runner-agg-select-policy', + 'dbus_type': 's', + }, default=None, ) + """Corresponds to the teamd runner.agg_select_policy.""" runner_fast_rate: Optional[bool] = field( - metadata={'dbus_name': 'runner-fast-rate', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'runner-fast-rate', + 'dbus_type': 'b', + }, + default=None, ) + """Corresponds to the teamd runner.fast_rate.""" runner_hwaddr_policy: Optional[str] = field( - metadata={'dbus_name': 'runner-hwaddr-policy', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'runner-hwaddr-policy', + 'dbus_type': 's', + }, default=None, ) + """Corresponds to the teamd runner.hwaddr_policy.""" runner_min_ports: Optional[int] = field( - metadata={'dbus_name': 'runner-min-ports', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'runner-min-ports', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd runner.min_ports.""" runner_sys_prio: Optional[int] = field( - metadata={'dbus_name': 'runner-sys-prio', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'runner-sys-prio', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd runner.sys_prio.""" runner_tx_balancer: Optional[str] = field( - metadata={'dbus_name': 'runner-tx-balancer', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'runner-tx-balancer', + 'dbus_type': 's', + }, default=None, ) + """Corresponds to the teamd runner.tx_balancer.name.""" runner_tx_balancer_interval: Optional[int] = field( - metadata={'dbus_name': 'runner-tx-balancer-interval', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'runner-tx-balancer-interval', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd runner.tx_balancer.interval.""" runner_tx_hash: Optional[List[str]] = field( - metadata={'dbus_name': 'runner-tx-hash', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'runner-tx-hash', + 'dbus_type': 'as', + }, default=None, ) + """Corresponds to the teamd runner.tx_hash.""" diff --git a/sdbus_async/networkmanager/settings/team_port.py b/sdbus_async/networkmanager/settings/team_port.py index 26f4733..65fc1b4 100644 --- a/sdbus_async/networkmanager/settings/team_port.py +++ b/sdbus_async/networkmanager/settings/team_port.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import LinkWatchers @@ -13,38 +13,71 @@ class TeamPortSettings(NetworkManagerSettingsMixin): """Team Port Settings""" config: Optional[str] = field( - metadata={'dbus_name': 'config', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'config', + 'dbus_type': 's', + }, default=None, ) - """The JSON configuration for the team port. The property should contain raw - JSON configuration data suitable for teamd, because the value is passed - directly to teamd. If not specified, the default configuration is used. See - man teamd.conf for the format details.""" + """The JSON configuration for the team port. The property should contain + raw JSON configuration data suitable for teamd, because the value is + passed directly to teamd. If not specified, the default + configuration is used. See man teamd.conf for the format details.""" lacp_key: Optional[int] = field( - metadata={'dbus_name': 'lacp-key', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'lacp-key', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd ports.PORTIFNAME.lacp_key.""" lacp_prio: Optional[int] = field( - metadata={'dbus_name': 'lacp-prio', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'lacp-prio', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd ports.PORTIFNAME.lacp_prio.""" link_watchers: Optional[List[LinkWatchers]] = field( - metadata={'dbus_name': 'link-watchers', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': LinkWatchers}, + metadata={ + 'dbus_name': 'link-watchers', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': LinkWatchers, + }, default=None, ) + """Link watchers configuration for the connection: each link watcher is + defined by a dictionary, whose keys depend upon the selected link + watcher. Available link watchers are 'ethtool', 'nsna_ping' and + 'arp_ping' and it is specified in the dictionary with the key + 'name'. Available keys are: ethtool: 'delay-up', 'delay-down', + 'init-wait'; nsna_ping: 'init-wait', 'interval', 'missed-max', + 'target-host'; arp_ping: all the ones in nsna_ping and 'source- + host', 'validate-active', 'validate-inactive', 'send-always'. See + teamd.conf man for more details.""" prio: Optional[int] = field( - metadata={'dbus_name': 'prio', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'prio', + 'dbus_type': 'i', + }, default=None, ) + """Corresponds to the teamd ports.PORTIFNAME.prio.""" queue_id: Optional[int] = field( - metadata={'dbus_name': 'queue-id', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'queue-id', + 'dbus_type': 'i', + }, default=None, ) """Corresponds to the teamd ports.PORTIFNAME.queue_id. When set to -1 means the parameter is skipped from the json config.""" sticky: Optional[bool] = field( - metadata={'dbus_name': 'sticky', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'sticky', + 'dbus_type': 'b', + }, + default=None, ) + """Corresponds to the teamd ports.PORTIFNAME.sticky.""" diff --git a/sdbus_async/networkmanager/settings/tun.py b/sdbus_async/networkmanager/settings/tun.py index af7b6b1..03dee1f 100644 --- a/sdbus_async/networkmanager/settings/tun.py +++ b/sdbus_async/networkmanager/settings/tun.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,40 +12,58 @@ class TunSettings(NetworkManagerSettingsMixin): """Tunnel Settings""" group: Optional[str] = field( - metadata={'dbus_name': 'group', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'group', + 'dbus_type': 's', + }, default=None, ) """The group ID which will own the device. If set to NULL everyone will be able to use the device.""" mode: Optional[int] = field( - metadata={'dbus_name': 'mode', 'dbus_type': 'u'}, - default=1, + metadata={ + 'dbus_name': 'mode', + 'dbus_type': 'u', + }, + default=None, ) """The operating mode of the virtual device. Allowed values are NM_SETTING_TUN_MODE_TUN (1) to create a layer 3 device and NM_SETTING_TUN_MODE_TAP (2) to create an Ethernet-like layer 2 one.""" multi_queue: Optional[bool] = field( - metadata={'dbus_name': 'multi-queue', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'multi-queue', + 'dbus_type': 'b', + }, + default=None, ) """If the property is set to TRUE, the interface will support multiple file - descriptors (queues) to parallelize packet sending or receiving. Otherwise, - the interface will only support a single queue.""" + descriptors (queues) to parallelize packet sending or receiving. + Otherwise, the interface will only support a single queue.""" owner: Optional[str] = field( - metadata={'dbus_name': 'owner', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'owner', + 'dbus_type': 's', + }, default=None, ) - """The user ID which will own the device. If set to NULL everyone will be able - to use the device.""" + """The user ID which will own the device. If set to NULL everyone will be + able to use the device.""" pi: Optional[bool] = field( - metadata={'dbus_name': 'pi', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'pi', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE the interface will prepend a 4 byte header describing the physical - interface to the packets.""" + """If TRUE the interface will prepend a 4 byte header describing the + physical interface to the packets.""" vnet_hdr: Optional[bool] = field( - metadata={'dbus_name': 'vnet-hdr', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'vnet-hdr', + 'dbus_type': 'b', + }, + default=None, ) - """If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio network - header.""" + """If TRUE the IFF_VNET_HDR the tunnel packets will include a virtio + network header.""" diff --git a/sdbus_async/networkmanager/settings/user.py b/sdbus_async/networkmanager/settings/user.py index be0c0ee..2c3835a 100644 --- a/sdbus_async/networkmanager/settings/user.py +++ b/sdbus_async/networkmanager/settings/user.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Dict, List, Optional +from typing import Dict, Optional from .base import NetworkManagerSettingsMixin @@ -12,10 +12,13 @@ class UserSettings(NetworkManagerSettingsMixin): """General User Profile Settings""" data: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 'data', 'dbus_type': 'a{ss}'}, + metadata={ + 'dbus_name': 'data', + 'dbus_type': 'a{ss}', + }, default=None, ) """A dictionary of key/value pairs with user data. This data is ignored by - NetworkManager and can be used at the users discretion. The keys only support - a strict ascii format, but the values can be arbitrary UTF8 strings up to a - certain length.""" + NetworkManager and can be used at the users discretion. The keys + only support a strict ascii format, but the values can be arbitrary + UTF8 strings up to a certain length.""" diff --git a/sdbus_async/networkmanager/settings/veth.py b/sdbus_async/networkmanager/settings/veth.py index 8b4bc0d..166393e 100644 --- a/sdbus_async/networkmanager/settings/veth.py +++ b/sdbus_async/networkmanager/settings/veth.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,8 +12,11 @@ class VethSettings(NetworkManagerSettingsMixin): """Veth Settings""" peer: Optional[str] = field( - metadata={'dbus_name': 'peer', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'peer', + 'dbus_type': 's', + }, default=None, ) - """This property specifies the peer interface name of the veth. This property - is mandatory.""" + """This property specifies the peer interface name of the veth. This + property is mandatory.""" diff --git a/sdbus_async/networkmanager/settings/vlan.py b/sdbus_async/networkmanager/settings/vlan.py index 73af40f..9fe54e2 100644 --- a/sdbus_async/networkmanager/settings/vlan.py +++ b/sdbus_async/networkmanager/settings/vlan.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,50 +12,71 @@ class VlanSettings(NetworkManagerSettingsMixin): """VLAN Settings""" egress_priority_map: Optional[List[str]] = field( - metadata={'dbus_name': 'egress-priority-map', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'egress-priority-map', + 'dbus_type': 'as', + }, default=None, ) """For outgoing packets, a list of mappings from Linux SKB priorities to - 802.1p priorities. The mapping is given in the format "from:to" where both - "from" and "to" are unsigned integers, ie "7:3".""" + 802.1p priorities. The mapping is given in the format "from:to" + where both "from" and "to" are unsigned integers, ie "7:3".""" flags: Optional[int] = field( - metadata={'dbus_name': 'flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'flags', + 'dbus_type': 'u', + }, default=None, ) """One or more flags which control the behavior and features of the VLAN - interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of - output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), - and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its - master device's operating state). NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP - protocol). The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, - but it used to be 0. To preserve backward compatibility, the default-value in - the D-Bus API continues to be 0 and a missing property on D-Bus is still - considered as 0.""" + interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) + (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use + of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose + binding of the interface to its master device's operating state). + NM_VLAN_FLAG_MVRP (0x8) (use of the MVRP protocol). + + The default value of this property is NM_VLAN_FLAG_REORDER_HEADERS, + but it used to be 0. To preserve backward compatibility, the + default-value in the D-Bus API continues to be 0 and a missing + property on D-Bus is still considered as 0.""" vlan_id: Optional[int] = field( - metadata={'dbus_name': 'id', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'id', + 'dbus_type': 'u', + }, default=None, ) - """The VLAN identifier that the interface created by this connection should be - assigned. The valid range is from 0 to 4094, without the reserved id 4095.""" + """The VLAN identifier that the interface created by this connection should + be assigned. The valid range is from 0 to 4094, without the reserved + id 4095.""" ingress_priority_map: Optional[List[str]] = field( - metadata={'dbus_name': 'ingress-priority-map', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'ingress-priority-map', + 'dbus_type': 'as', + }, default=None, ) """For incoming packets, a list of mappings from 802.1p priorities to Linux - SKB priorities. The mapping is given in the format "from:to" where both - "from" and "to" are unsigned integers, ie "7:3".""" + SKB priorities. The mapping is given in the format "from:to" where + both "from" and "to" are unsigned integers, ie "7:3".""" interface_name: Optional[str] = field( - metadata={'dbus_name': 'interface-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'interface-name', + 'dbus_type': 's', + }, default=None, ) """Deprecated in favor of connection.interface-name, but can be used for - backward-compatibility with older daemons, to set the vlan's interface - name.""" + backward-compatibility with older daemons, to set the vlan's + interface name.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) """If given, specifies the parent interface name or parent connection UUID - from which this VLAN interface should be created. If this property is not - specified, the connection must contain an "802-3-ethernet" setting with a - "mac-address" property.""" + from which this VLAN interface should be created. If this property + is not specified, the connection must contain an "802-3-ethernet" + setting with a "mac-address" property.""" diff --git a/sdbus_async/networkmanager/settings/vpn.py b/sdbus_async/networkmanager/settings/vpn.py index 0e6dc06..5089090 100644 --- a/sdbus_async/networkmanager/settings/vpn.py +++ b/sdbus_async/networkmanager/settings/vpn.py @@ -1,9 +1,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Dict, List, Optional +from typing import Dict, Optional from .base import NetworkManagerSettingsMixin @@ -12,45 +12,65 @@ class VpnSettings(NetworkManagerSettingsMixin): """VPN Settings""" data: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 'data', 'dbus_type': 'a{ss}'}, + metadata={ + 'dbus_name': 'data', + 'dbus_type': 'a{ss}', + }, default=None, ) - """Dictionary of key/value pairs of VPN plugin specific data. Both keys and - values must be strings.""" + """Dictionary of key/value pairs of VPN plugin specific data. Both keys + and values must be strings.""" persistent: Optional[bool] = field( - metadata={'dbus_name': 'persistent', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'persistent', + 'dbus_type': 'b', + }, + default=None, ) - """If the VPN service supports persistence, and this property is TRUE, the VPN - will attempt to stay connected across link changes and outages, until - explicitly disconnected.""" + """If the VPN service supports persistence, and this property is TRUE, the + VPN will attempt to stay connected across link changes and outages, + until explicitly disconnected.""" secrets: Optional[Dict[str, str]] = field( - metadata={'dbus_name': 'secrets', 'dbus_type': 'a{ss}'}, + metadata={ + 'dbus_name': 'secrets', + 'dbus_type': 'a{ss}', + }, default=None, ) - """Dictionary of key/value pairs of VPN plugin specific secrets like passwords - or private keys. Both keys and values must be strings.""" + """Dictionary of key/value pairs of VPN plugin specific secrets like + passwords or private keys. Both keys and values must be strings.""" service_type: Optional[str] = field( - metadata={'dbus_name': 'service-type', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'service-type', + 'dbus_type': 's', + }, default=None, ) - """D-Bus service name of the VPN plugin that this setting uses to connect to - its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin.""" + """D-Bus service name of the VPN plugin that this setting uses to connect + to its network. i.e. org.freedesktop.NetworkManager.vpnc for the + vpnc plugin.""" timeout: Optional[int] = field( - metadata={'dbus_name': 'timeout', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'timeout', + 'dbus_type': 'u', + }, default=None, ) - """Timeout for the VPN service to establish the connection. Some services may - take quite a long time to connect. Value of 0 means a default timeout, which - is 60 seconds (unless overridden by vpn.timeout in configuration file). Values - greater than zero mean timeout in seconds.""" + """Timeout for the VPN service to establish the connection. Some services + may take quite a long time to connect. Value of 0 means a default + timeout, which is 60 seconds (unless overridden by vpn.timeout in + configuration file). Values greater than zero mean timeout in + seconds.""" user_name: Optional[str] = field( - metadata={'dbus_name': 'user-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'user-name', + 'dbus_type': 's', + }, default=None, ) """If the VPN connection requires a user name for authentication, that name - should be provided here. If the connection is available to more than one - user, and the VPN requires each user to supply a different name, then leave - this property empty. If this property is empty, NetworkManager will - automatically supply the username of the user which requested the VPN - connection.""" + should be provided here. If the connection is available to more + than one user, and the VPN requires each user to supply a different + name, then leave this property empty. If this property is empty, + NetworkManager will automatically supply the username of the user + which requested the VPN connection.""" diff --git a/sdbus_async/networkmanager/settings/vrf.py b/sdbus_async/networkmanager/settings/vrf.py index f312943..1085bb7 100644 --- a/sdbus_async/networkmanager/settings/vrf.py +++ b/sdbus_async/networkmanager/settings/vrf.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,6 +12,10 @@ class VrfSettings(NetworkManagerSettingsMixin): """VRF settings""" table: Optional[int] = field( - metadata={'dbus_name': 'table', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'table', + 'dbus_type': 'u', + }, default=None, ) + """The routing table for this VRF.""" diff --git a/sdbus_async/networkmanager/settings/vxlan.py b/sdbus_async/networkmanager/settings/vxlan.py index 617a5a0..3cb3314 100644 --- a/sdbus_async/networkmanager/settings/vxlan.py +++ b/sdbus_async/networkmanager/settings/vxlan.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,81 +12,138 @@ class VxlanSettings(NetworkManagerSettingsMixin): """VXLAN Settings""" ageing: Optional[int] = field( - metadata={'dbus_name': 'ageing', 'dbus_type': 'u'}, - default=300, + metadata={ + 'dbus_name': 'ageing', + 'dbus_type': 'u', + }, + default=None, ) + """Specifies the lifetime in seconds of FDB entries learnt by the kernel.""" destination_port: Optional[int] = field( - metadata={'dbus_name': 'destination-port', 'dbus_type': 'u'}, - default=8472, + metadata={ + 'dbus_name': 'destination-port', + 'dbus_type': 'u', + }, + default=None, ) """Specifies the UDP destination port to communicate to the remote VXLAN tunnel endpoint.""" vxlan_id: Optional[int] = field( - metadata={'dbus_name': 'id', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'id', + 'dbus_type': 'u', + }, default=None, ) """Specifies the VXLAN Network Identifier (or VXLAN Segment Identifier) to use.""" l2_miss: Optional[bool] = field( - metadata={'dbus_name': 'l2-miss', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'l2-miss', + 'dbus_type': 'b', + }, + default=None, ) + """Specifies whether netlink LL ADDR miss notifications are generated.""" l3_miss: Optional[bool] = field( - metadata={'dbus_name': 'l3-miss', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'l3-miss', + 'dbus_type': 'b', + }, + default=None, ) + """Specifies whether netlink IP ADDR miss notifications are generated.""" learning: Optional[bool] = field( - metadata={'dbus_name': 'learning', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'learning', + 'dbus_type': 'b', + }, + default=None, ) - """Specifies whether unknown source link layer addresses and IP addresses are - entered into the VXLAN device forwarding database.""" + """Specifies whether unknown source link layer addresses and IP addresses + are entered into the VXLAN device forwarding database.""" limit: Optional[int] = field( - metadata={'dbus_name': 'limit', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'limit', + 'dbus_type': 'u', + }, default=None, ) - """Specifies the maximum number of FDB entries. A value of zero means that the - kernel will store unlimited entries.""" + """Specifies the maximum number of FDB entries. A value of zero means that + the kernel will store unlimited entries.""" local: Optional[str] = field( - metadata={'dbus_name': 'local', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'local', + 'dbus_type': 's', + }, default=None, ) + """If given, specifies the source IP address to use in outgoing packets.""" parent: Optional[str] = field( - metadata={'dbus_name': 'parent', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'parent', + 'dbus_type': 's', + }, default=None, ) + """If given, specifies the parent interface name or parent connection UUID.""" proxy: Optional[bool] = field( - metadata={'dbus_name': 'proxy', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'proxy', + 'dbus_type': 'b', + }, + default=None, ) + """Specifies whether ARP proxy is turned on.""" remote: Optional[str] = field( - metadata={'dbus_name': 'remote', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'remote', + 'dbus_type': 's', + }, default=None, ) """Specifies the unicast destination IP address to use in outgoing packets - when the destination link layer address is not known in the VXLAN device - forwarding database, or the multicast IP address to join.""" + when the destination link layer address is not known in the VXLAN + device forwarding database, or the multicast IP address to join.""" rsc: Optional[bool] = field( - metadata={'dbus_name': 'rsc', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'rsc', + 'dbus_type': 'b', + }, + default=None, ) + """Specifies whether route short circuit is turned on.""" source_port_max: Optional[int] = field( - metadata={'dbus_name': 'source-port-max', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'source-port-max', + 'dbus_type': 'u', + }, default=None, ) """Specifies the maximum UDP source port to communicate to the remote VXLAN tunnel endpoint.""" source_port_min: Optional[int] = field( - metadata={'dbus_name': 'source-port-min', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'source-port-min', + 'dbus_type': 'u', + }, default=None, ) """Specifies the minimum UDP source port to communicate to the remote VXLAN tunnel endpoint.""" tos: Optional[int] = field( - metadata={'dbus_name': 'tos', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'tos', + 'dbus_type': 'u', + }, default=None, ) + """Specifies the TOS value to use in outgoing packets.""" ttl: Optional[int] = field( - metadata={'dbus_name': 'ttl', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'ttl', + 'dbus_type': 'u', + }, default=None, ) + """Specifies the time-to-live value to use in outgoing packets.""" diff --git a/sdbus_async/networkmanager/settings/wifi_p2p.py b/sdbus_async/networkmanager/settings/wifi_p2p.py index efe4981..5d18bd1 100644 --- a/sdbus_async/networkmanager/settings/wifi_p2p.py +++ b/sdbus_async/networkmanager/settings/wifi_p2p.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,24 +12,35 @@ class WifiP2PSettings(NetworkManagerSettingsMixin): """Wi-Fi P2P Settings""" peer: Optional[str] = field( - metadata={'dbus_name': 'peer', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'peer', + 'dbus_type': 's', + }, default=None, ) - """The P2P device that should be connected to. Currently, this is the only way - to create or join a group.""" + """The P2P device that should be connected to. Currently, this is the only + way to create or join a group.""" wfd_ies: Optional[bytes] = field( - metadata={'dbus_name': 'wfd-ies', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'wfd-ies', + 'dbus_type': 'ay', + }, default=None, ) - """The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display - requires a protocol specific information element to be set in certain Wi-Fi - frames. These can be specified here for the purpose of establishing a - connection. This setting is only useful when implementing a Wi-Fi Display - client.""" + """The Wi-Fi Display (WFD) Information Elements (IEs) to set. + + Wi-Fi Display requires a protocol specific information element to be + set in certain Wi-Fi frames. These can be specified here for the + purpose of establishing a connection. This setting is only useful + when implementing a Wi-Fi Display client.""" wps_method: Optional[int] = field( - metadata={'dbus_name': 'wps-method', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'wps-method', + 'dbus_type': 'u', + }, default=None, ) - """Flags indicating which mode of WPS is to be used. There's little point in - changing the default setting as NetworkManager will automatically determine - the best method to use.""" + """Flags indicating which mode of WPS is to be used. + + There's little point in changing the default setting as + NetworkManager will automatically determine the best method to use.""" diff --git a/sdbus_async/networkmanager/settings/wimax.py b/sdbus_async/networkmanager/settings/wimax.py index 35137ea..d498f75 100644 --- a/sdbus_async/networkmanager/settings/wimax.py +++ b/sdbus_async/networkmanager/settings/wimax.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,15 +12,21 @@ class WimaxSettings(NetworkManagerSettingsMixin): """WiMax Settings""" mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 'ay', + }, default=None, ) - """If specified, this connection will only apply to the WiMAX device whose MAC - address matches. This property does not change the MAC address of the device - (known as MAC spoofing). Deprecated: 1""" + """If specified, this connection will only apply to the WiMAX device whose + MAC address matches. This property does not change the MAC address + of the device (known as MAC spoofing).""" network_name: Optional[str] = field( - metadata={'dbus_name': 'network-name', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'network-name', + 'dbus_type': 's', + }, default=None, ) """Network Service Provider (NSP) name of the WiMAX network this connection - should use. Deprecated: 1""" + should use.""" diff --git a/sdbus_async/networkmanager/settings/wireguard.py b/sdbus_async/networkmanager/settings/wireguard.py index 55ca7ff..371c2dc 100644 --- a/sdbus_async/networkmanager/settings/wireguard.py +++ b/sdbus_async/networkmanager/settings/wireguard.py @@ -1,11 +1,11 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin -from .datatypes import WireguardPeers as Peers +from .datatypes import WireguardPeers @dataclass @@ -13,70 +13,112 @@ class WireguardSettings(NetworkManagerSettingsMixin): """WireGuard Settings""" fwmark: Optional[int] = field( - metadata={'dbus_name': 'fwmark', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'fwmark', + 'dbus_type': 'u', + }, default=None, ) """The use of fwmark is optional and is by default off. Setting it to 0 - disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. Note that - "ip4-auto-default-route" or "ip6-auto-default-route" enabled, implies to - automatically choose a fwmark.""" + disables it. Otherwise, it is a 32-bit fwmark for outgoing packets. + + Note that "ip4-auto-default-route" or "ip6-auto-default-route" + enabled, implies to automatically choose a fwmark.""" ip4_auto_default_route: Optional[int] = field( - metadata={'dbus_name': 'ip4-auto-default-route', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'ip4-auto-default-route', + 'dbus_type': 'i', + }, default=None, ) - """Whether to enable special handling of the IPv4 default route. If enabled, - the IPv4 default route from wireguard.peer-routes will be placed to a - dedicated routing-table and two policy routing rules will be added. The fwmark - number is also used as routing-table for the default-route, and if fwmark is - zero, an unused fwmark/table is chosen automatically. This corresponds to what - wg-quick does with Table=auto and what WireGuard calls "Improved Rule-based - Routing". Note that for this automatism to work, you usually don't want to set - ipv4.gateway, because that will result in a conflicting default route. Leaving - this at the default will enable this option automatically if ipv4.never- - default is not set and there are any peers that use a default-route as - allowed-ips.""" + """Whether to enable special handling of the IPv4 default route. If + enabled, the IPv4 default route from wireguard.peer-routes will be + placed to a dedicated routing-table and two policy routing rules + will be added. The fwmark number is also used as routing-table for + the default-route, and if fwmark is zero, an unused fwmark/table is + chosen automatically. This corresponds to what wg-quick does with + Table=auto and what WireGuard calls "Improved Rule-based Routing". + + Note that for this automatism to work, you usually don't want to set + ipv4.gateway, because that will result in a conflicting default + route. + + Leaving this at the default will enable this option automatically if + ipv4.never-default is not set and there are any peers that use a + default-route as allowed-ips. Since this automatism only makes sense + if you also have a peer with an /0 allowed-ips, it is usually not + necessary to enable this explicitly. However, you can disable it if + you want to configure your own routing and rules.""" ip6_auto_default_route: Optional[int] = field( - metadata={'dbus_name': 'ip6-auto-default-route', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'ip6-auto-default-route', + 'dbus_type': 'i', + }, default=None, ) + """Like ip4-auto-default-route, but for the IPv6 default route.""" listen_port: Optional[int] = field( - metadata={'dbus_name': 'listen-port', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'listen-port', + 'dbus_type': 'u', + }, default=None, ) - """The listen-port. If listen-port is not specified, the port will be chosen - randomly when the interface comes up.""" + """The listen-port. If listen-port is not specified, the port will be + chosen randomly when the interface comes up.""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, - breaking larger packets up into multiple fragments. If zero a default MTU is - used. Note that contrary to wg-quick's MTU setting, this does not take into - account the current routes at the time of activation.""" + breaking larger packets up into multiple fragments. + + If zero a default MTU is used. Note that contrary to wg-quick's MTU + setting, this does not take into account the current routes at the + time of activation.""" peer_routes: Optional[bool] = field( - metadata={'dbus_name': 'peer-routes', 'dbus_type': 'b'}, - default=True, + metadata={ + 'dbus_name': 'peer-routes', + 'dbus_type': 'b', + }, + default=None, ) - """Whether to automatically add routes for the AllowedIPs ranges of the peers. - If TRUE (the default), NetworkManager will automatically add routes in the - routing tables according to ipv4.route-table and ipv6.route-table. Usually you - want this automatism enabled. If FALSE, no such routes are added - automatically. In this case, the user may want to configure static routes in - ipv4.routes and ipv6.routes, respectively. Note that if the peer's AllowedIPs - is "0.0.0.0/0" or "::/0" and the profile's ipv4.never-default or ipv6.never- - default setting is enabled, the peer route for this peer won't be added - automatically.""" - peers: Optional[List[Peers]] = field( - metadata={'dbus_name': 'peers', - 'dbus_type': 'aa{sv}', - 'dbus_inner_class': Peers}, + """Whether to automatically add routes for the AllowedIPs ranges of the + peers. If TRUE (the default), NetworkManager will automatically add + routes in the routing tables according to ipv4.route-table and + ipv6.route-table. Usually you want this automatism enabled. If + FALSE, no such routes are added automatically. In this case, the + user may want to configure static routes in ipv4.routes and + ipv6.routes, respectively. + + Note that if the peer's AllowedIPs is "0.0.0.0/0" or "::/0" and the + profile's ipv4.never-default or ipv6.never-default setting is + enabled, the peer route for this peer won't be added automatically.""" + peers: Optional[List[WireguardPeers]] = field( + metadata={ + 'dbus_name': 'peers', + 'dbus_type': 'aa{sv}', + 'dbus_inner_class': WireguardPeers, + }, default=None, ) + """Array of dictionaries for the WireGuard peers.""" private_key: Optional[str] = field( - metadata={'dbus_name': 'private-key', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'private-key', + 'dbus_type': 's', + }, default=None, ) + """The 256 bit private-key in base64 encoding.""" private_key_flags: Optional[int] = field( - metadata={'dbus_name': 'private-key-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'private-key-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "private-key" property.""" diff --git a/sdbus_async/networkmanager/settings/wireless.py b/sdbus_async/networkmanager/settings/wireless.py index 2d7235c..f2cc165 100644 --- a/sdbus_async/networkmanager/settings/wireless.py +++ b/sdbus_async/networkmanager/settings/wireless.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,195 +12,289 @@ class WirelessSettings(NetworkManagerSettingsMixin): """Wi-Fi Settings""" ap_isolation: Optional[int] = field( - metadata={'dbus_name': 'ap-isolation', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'ap-isolation', + 'dbus_type': 'i', + }, default=None, ) """Configures AP isolation, which prevents communication between wireless - devices connected to this AP. This property can be set to a value different - from NM_TERNARY_DEFAULT (-1) only when the interface is configured in AP mode. - If set to NM_TERNARY_TRUE (1), devices are not able to communicate with each - other. This increases security because it protects devices against attacks - from other clients in the network. At the same time, it prevents devices to - access resources on the same wireless networks as file shares, printers, etc. - If set to NM_TERNARY_FALSE (0), devices can talk to each other. When set to - NM_TERNARY_DEFAULT (-1), the global default is used; in case the global - default is unspecified it is assumed to be NM_TERNARY_FALSE (0).""" + devices connected to this AP. This property can be set to a value + different from NM_TERNARY_DEFAULT (-1) only when the interface is + configured in AP mode. + + If set to NM_TERNARY_TRUE (1), devices are not able to communicate + with each other. This increases security because it protects devices + against attacks from other clients in the network. At the same time, + it prevents devices to access resources on the same wireless + networks as file shares, printers, etc. + + If set to NM_TERNARY_FALSE (0), devices can talk to each other. + + When set to NM_TERNARY_DEFAULT (-1), the global default is used; in + case the global default is unspecified it is assumed to be + NM_TERNARY_FALSE (0).""" assigned_mac_address: Optional[str] = field( - metadata={'dbus_name': 'assigned-mac-address', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'assigned-mac-address', + 'dbus_type': 's', + }, default=None, ) """The new field for the cloned MAC address. It can be either a hardware - address in ASCII representation, or one of the special values "preserve", - "permanent", "random" or "stable". This field replaces the deprecated "cloned- - mac-address" on D-Bus, which can only contain explicit hardware addresses. - Note that this property only exists in D-Bus API. libnm and nmcli continue to - call this property "cloned-mac-address".""" + address in ASCII representation, or one of the special values + "preserve", "permanent", "random" or "stable". This field replaces + the deprecated "cloned-mac-address" on D-Bus, which can only contain + explicit hardware addresses. Note that this property only exists in + D-Bus API. libnm and nmcli continue to call this property "cloned- + mac-address".""" band: Optional[str] = field( - metadata={'dbus_name': 'band', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'band', + 'dbus_type': 's', + }, default=None, ) - """802.11 frequency band of the network. One of "a" for 5GHz 802.11a or "bg" - for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the - specific band, i.e. if "a" is specified, the device will not associate with - the same network in the 2.4GHz band even if the network's settings are - compatible. This setting depends on specific driver capability and may not - work with all drivers.""" + """802.11 frequency band of the network. One of "a" for 5GHz 802.11a or + "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi + network to the specific band, i.e. if "a" is specified, the device + will not associate with the same network in the 2.4GHz band even if + the network's settings are compatible. This setting depends on + specific driver capability and may not work with all drivers.""" bssid: Optional[bytes] = field( - metadata={'dbus_name': 'bssid', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'bssid', + 'dbus_type': 'ay', + }, default=None, ) """If specified, directs the device to only associate with the given access - point. This capability is highly driver dependent and not supported by all - devices. Note: this property does not control the BSSID used when creating an - Ad-Hoc network and is unlikely to in the future.""" + point. This capability is highly driver dependent and not supported + by all devices. Note: this property does not control the BSSID used + when creating an Ad-Hoc network and is unlikely to in the future. + + Locking a client profile to a certain BSSID will prevent roaming and + also disable background scanning. That can be useful, if there is + only one access point for the SSID.""" channel: Optional[int] = field( - metadata={'dbus_name': 'channel', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'channel', + 'dbus_type': 'u', + }, default=None, ) """Wireless channel to use for the Wi-Fi connection. The device will only - join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. - Because channel numbers overlap between bands, this property also requires the - "band" property to be set.""" + join (or create for Ad-Hoc networks) a Wi-Fi network on the + specified channel. Because channel numbers overlap between bands, + this property also requires the "band" property to be set.""" cloned_mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'cloned-mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'cloned-mac-address', + 'dbus_type': 'ay', + }, default=None, ) - """This D-Bus field is deprecated in favor of "assigned-mac-address" which is - more flexible and allows specifying special variants like "random". For libnm - and nmcli, this field is called "cloned-mac-address".""" + """If specified, request that the device use this MAC address instead. This + is known as MAC cloning or spoofing. + + Beside explicitly specifying a MAC address, the special values + "preserve", "permanent", "random" and "stable" are supported. + "preserve" means not to touch the MAC address on activation. + "permanent" means to use the permanent hardware address of the + device. "random" creates a random MAC address on each connect. + "stable" creates a hashed MAC address based on connection.stable-id + and a machine dependent key. + + If unspecified, the value can be overwritten via global defaults, + see manual of NetworkManager.conf. If still unspecified, it defaults + to "preserve" (older versions of NetworkManager may use a different + default value). + + On D-Bus, this field is expressed as "assigned-mac-address" or the + deprecated "cloned-mac-address".""" generate_mac_address_mask: Optional[str] = field( - metadata={'dbus_name': 'generate-mac-address-mask', 'dbus_type': 's'}, - default=None, - ) - """With "cloned-mac-address" setting "random" or "stable", by default all bits - of the MAC address are scrambled and a locally-administered, unicast MAC - address is created. This property allows to specify that certain bits are - fixed. Note that the least significant bit of the first MAC address will - always be unset to create a unicast MAC address. If the property is NULL, it - is eligible to be overwritten by a default connection setting. If the value is - still NULL or an empty string, the default is to create a locally- - administered, unicast MAC address. If the value contains one MAC address, this - address is used as mask. The set bits of the mask are to be filled with the - current MAC address of the device, while the unset bits are subject to - randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI of the - current MAC address and only randomize the lower 3 bytes using the "random" or - "stable" algorithm. If the value contains one additional MAC address after the - mask, this address is used instead of the current MAC address to fill the bits - that shall not be randomized. For example, a value of "FE:FF:FF:00:00:00 - 68:F7:28:00:00:00" will set the OUI of the MAC address to 68:F7:28, while the - lower bits are randomized. A value of "02:00:00:00:00:00 00:00:00:00:00:00" - will create a fully scrambled globally-administered, burned-in MAC address. If - the value contains more than one additional MAC addresses, one of them is - chosen randomly. For example, "02:00:00:00:00:00 00:00:00:00:00:00 - 02:00:00:00:00:00" will create a fully scrambled MAC address, randomly locally - or globally administered.""" + metadata={ + 'dbus_name': 'generate-mac-address-mask', + 'dbus_type': 's', + }, + default=None, + ) + """With "cloned-mac-address" setting "random" or "stable", by default all + bits of the MAC address are scrambled and a locally-administered, + unicast MAC address is created. This property allows to specify that + certain bits are fixed. Note that the least significant bit of the + first MAC address will always be unset to create a unicast MAC + address. + + If the property is NULL, it is eligible to be overwritten by a + default connection setting. If the value is still NULL or an empty + string, the default is to create a locally-administered, unicast MAC + address. + + If the value contains one MAC address, this address is used as mask. + The set bits of the mask are to be filled with the current MAC + address of the device, while the unset bits are subject to + randomization. Setting "FE:FF:FF:00:00:00" means to preserve the OUI + of the current MAC address and only randomize the lower 3 bytes + using the "random" or "stable" algorithm. + + If the value contains one additional MAC address after the mask, + this address is used instead of the current MAC address to fill the + bits that shall not be randomized. For example, a value of + "FE:FF:FF:00:00:00 68:F7:28:00:00:00" will set the OUI of the MAC + address to 68:F7:28, while the lower bits are randomized. A value of + "02:00:00:00:00:00 00:00:00:00:00:00" will create a fully scrambled + globally-administered, burned-in MAC address. + + If the value contains more than one additional MAC addresses, one of + them is chosen randomly. For example, "02:00:00:00:00:00 + 00:00:00:00:00:00 02:00:00:00:00:00" will create a fully scrambled + MAC address, randomly locally or globally administered.""" hidden: Optional[bool] = field( - metadata={'dbus_name': 'hidden', 'dbus_type': 'b'}, - default=False, + metadata={ + 'dbus_name': 'hidden', + 'dbus_type': 'b', + }, + default=None, ) """If TRUE, indicates that the network is a non-broadcasting network that - hides its SSID. This works both in infrastructure and AP mode. In - infrastructure mode, various workarounds are used for a more reliable - discovery of hidden networks, such as probe-scanning the SSID. However, these - workarounds expose inherent insecurities with hidden SSID networks, and thus - hidden SSID networks should be used with caution. In AP mode, the created - network does not broadcast its SSID. Note that marking the network as hidden - may be a privacy issue for you (in infrastructure mode) or client stations (in - AP mode), as the explicit probe-scans are distinctly recognizable on the - air.""" + hides its SSID. This works both in infrastructure and AP mode. + + In infrastructure mode, various workarounds are used for a more + reliable discovery of hidden networks, such as probe-scanning the + SSID. However, these workarounds expose inherent insecurities with + hidden SSID networks, and thus hidden SSID networks should be used + with caution. + + In AP mode, the created network does not broadcast its SSID. + + Note that marking the network as hidden may be a privacy issue for + you (in infrastructure mode) or client stations (in AP mode), as the + explicit probe-scans are distinctly recognizable on the air.""" mac_address: Optional[bytes] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 'ay', + }, default=None, ) """If specified, this connection will only apply to the Wi-Fi device whose - permanent MAC address matches. This property does not change the MAC address - of the device (i.e. MAC spoofing).""" + permanent MAC address matches. This property does not change the MAC + address of the device (i.e. MAC spoofing).""" mac_address_blacklist: Optional[List[str]] = field( - metadata={'dbus_name': 'mac-address-blacklist', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'mac-address-blacklist', + 'dbus_type': 'as', + }, default=None, ) - """A list of permanent MAC addresses of Wi-Fi devices to which this connection - should never apply. Each MAC address should be given in the standard hex- - digits-and-colons notation (eg "00:11:22:33:44:55").""" + """A list of permanent MAC addresses of Wi-Fi devices to which this + connection should never apply. Each MAC address should be given in + the standard hex-digits-and-colons notation (eg + "00:11:22:33:44:55").""" mac_address_randomization: Optional[int] = field( - metadata={'dbus_name': 'mac-address-randomization', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mac-address-randomization', + 'dbus_type': 'u', + }, default=None, ) - """One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless the - user has set a global default to randomize and the supplicant supports - randomization), NM_SETTING_MAC_RANDOMIZATION_NEVER (1) (never randomize the - MAC address), or NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the - MAC address). This property is deprecated for 'cloned-mac-address'. - Deprecated: 1""" + """One of NM_SETTING_MAC_RANDOMIZATION_DEFAULT (0) (never randomize unless + the user has set a global default to randomize and the supplicant + supports randomization), NM_SETTING_MAC_RANDOMIZATION_NEVER (1) + (never randomize the MAC address), or + NM_SETTING_MAC_RANDOMIZATION_ALWAYS (2) (always randomize the MAC + address).""" mode: Optional[str] = field( - metadata={'dbus_name': 'mode', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'mode', + 'dbus_type': 's', + }, default=None, ) - """Wi-Fi network mode; one of "infrastructure", "mesh", "adhoc" or "ap". If - blank, infrastructure is assumed.""" + """Wi-Fi network mode; one of "infrastructure", "mesh", "adhoc" or "ap". + If blank, infrastructure is assumed.""" mtu: Optional[int] = field( - metadata={'dbus_name': 'mtu', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'mtu', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames.""" powersave: Optional[int] = field( - metadata={'dbus_name': 'powersave', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'powersave', + 'dbus_type': 'u', + }, default=None, ) """One of NM_SETTING_WIRELESS_POWERSAVE_DISABLE (2) (disable Wi-Fi power - saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi power saving), - NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch currently configure - setting) or NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally + saving), NM_SETTING_WIRELESS_POWERSAVE_ENABLE (3) (enable Wi-Fi + power saving), NM_SETTING_WIRELESS_POWERSAVE_IGNORE (1) (don't touch + currently configure setting) or + NM_SETTING_WIRELESS_POWERSAVE_DEFAULT (0) (use the globally configured value). All other values are reserved.""" rate: Optional[int] = field( - metadata={'dbus_name': 'rate', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'rate', + 'dbus_type': 'u', + }, default=None, ) """If non-zero, directs the device to only use the specified bitrate for - communication with the access point. Units are in Kb/s, ie 5500 = 5.5 Mbit/s. - This property is highly driver dependent and not all devices support setting a - static bitrate.""" - security: Optional[str] = field( - metadata={'dbus_name': 'security', 'dbus_type': 's'}, - default=None, - ) - """This property is deprecated, but can be set to the value '802-11-wireless- - security' when a wireless security setting is also present in the connection - dictionary, for compatibility with very old NetworkManager daemons.""" + communication with the access point. Units are in Kb/s, ie 5500 = + 5.5 Mbit/s. This property is highly driver dependent and not all + devices support setting a static bitrate.""" seen_bssids: Optional[List[str]] = field( - metadata={'dbus_name': 'seen-bssids', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'seen-bssids', + 'dbus_type': 'as', + }, default=None, ) """A list of BSSIDs (each BSSID formatted as a MAC address like - "00:11:22:33:44:55") that have been detected as part of the Wi-Fi network. - NetworkManager internally tracks previously seen BSSIDs. The property is only - meant for reading and reflects the BSSID list of NetworkManager. The changes - you make to this property will not be preserved.""" + "00:11:22:33:44:55") that have been detected as part of the Wi-Fi + network. NetworkManager internally tracks previously seen BSSIDs. + The property is only meant for reading and reflects the BSSID list + of NetworkManager. The changes you make to this property will not be + preserved.""" ssid: Optional[bytes] = field( - metadata={'dbus_name': 'ssid', 'dbus_type': 'ay'}, + metadata={ + 'dbus_name': 'ssid', + 'dbus_type': 'ay', + }, default=None, ) + """SSID of the Wi-Fi network. Must be specified.""" tx_power: Optional[int] = field( - metadata={'dbus_name': 'tx-power', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'tx-power', + 'dbus_type': 'u', + }, default=None, ) - """If non-zero, directs the device to use the specified transmit power. Units - are dBm. This property is highly driver dependent and not all devices support - setting a static transmit power.""" + """If non-zero, directs the device to use the specified transmit power. + Units are dBm. This property is highly driver dependent and not all + devices support setting a static transmit power.""" wake_on_wlan: Optional[int] = field( - metadata={'dbus_name': 'wake-on-wlan', 'dbus_type': 'u'}, - default=1, + metadata={ + 'dbus_name': 'wake-on-wlan', + 'dbus_type': 'u', + }, + default=None, ) - """The NMSettingWirelessWakeOnWLan options to enable. Not all devices support - all options. May be any combination of NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY - (0x2), NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT (0x4), + """The NMSettingWirelessWakeOnWLan options to enable. Not all devices + support all options. May be any combination of + NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY (0x2), + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT (0x4), NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC (0x8), NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE (0x10), NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST (0x20), NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE (0x40), NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE (0x80), NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP (0x100) or the special values - NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (0x1) (to use global settings) and - NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (0x8000) (to disable management of - Wake-on-LAN in NetworkManager).""" + NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (0x1) (to use global + settings) and NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (0x8000) (to + disable management of Wake-on-LAN in NetworkManager).""" diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index 0dbc4cd..7933541 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,153 +12,230 @@ class WirelessSecuritySettings(NetworkManagerSettingsMixin): """Wi-Fi Security Settings""" auth_alg: Optional[str] = field( - metadata={'dbus_name': 'auth-alg', 'dbus_type': 's'}, - default=None, - ) - """When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 - authentication algorithm required by the AP here. One of "open" for Open - System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco - LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" - and "leap-password" properties must be specified.""" + metadata={ + 'dbus_name': 'auth-alg', + 'dbus_type': 's', + }, + default=None, + ) + """When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the + 802.11 authentication algorithm required by the AP here. One of + "open" for Open System, "shared" for Shared Key, or "leap" for Cisco + LEAP. When using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth- + alg = "leap") the "leap-username" and "leap-password" properties + must be specified.""" fils: Optional[int] = field( - metadata={'dbus_name': 'fils', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'fils', + 'dbus_type': 'i', + }, default=None, ) """Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for - the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use - global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable - FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the + the connection. One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT + (0) (use global default value), + NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), + NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or - NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not - supported). When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no - global default is set, FILS will be optionally enabled.""" + NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail + if not supported). When set to + NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default + is set, FILS will be optionally enabled.""" group: Optional[List[str]] = field( - metadata={'dbus_name': 'group', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'group', + 'dbus_type': 'as', + }, default=None, ) - """A list of group/broadcast encryption algorithms which prevents connections - to Wi-Fi networks that do not utilize one of the algorithms in the list. For - maximum compatibility leave this property empty. Each list element may be one - of "wep40", "wep104", "tkip", or "ccmp".""" + """A list of group/broadcast encryption algorithms which prevents + connections to Wi-Fi networks that do not utilize one of the + algorithms in the list. For maximum compatibility leave this + property empty. Each list element may be one of "wep40", "wep104", + "tkip", or "ccmp".""" key_mgmt: Optional[str] = field( - metadata={'dbus_name': 'key-mgmt', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'key-mgmt', + 'dbus_type': 's', + }, default=None, ) - """Key management used for the connection. One of "none" (WEP or no password - protection), "ieee8021x" (Dynamic WEP), "owe" (Opportunistic Wireless - Encryption), "wpa-psk" (WPA2 + WPA3 personal), "sae" (WPA3 personal only), - "wpa-eap" (WPA2 + WPA3 enterprise) or "wpa-eap-suite-b-192" (WPA3 enterprise - only). This property must be set for any Wi-Fi connection that uses + """Key management used for the connection. One of "none" (WEP or no + password protection), "ieee8021x" (Dynamic WEP), "owe" + (Opportunistic Wireless Encryption), "wpa-psk" (WPA2 + WPA3 + personal), "sae" (WPA3 personal only), "wpa-eap" (WPA2 + WPA3 + enterprise) or "wpa-eap-suite-b-192" (WPA3 enterprise only). + + This property must be set for any Wi-Fi connection that uses security.""" leap_password: Optional[str] = field( - metadata={'dbus_name': 'leap-password', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'leap-password', + 'dbus_type': 's', + }, default=None, ) - """The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" - and auth-alg = "leap").""" + """The login password for legacy LEAP connections (ie, key-mgmt = + "ieee8021x" and auth-alg = "leap").""" leap_password_flags: Optional[int] = field( - metadata={'dbus_name': 'leap-password-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'leap-password-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "leap-password" property.""" leap_username: Optional[str] = field( - metadata={'dbus_name': 'leap-username', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'leap-username', + 'dbus_type': 's', + }, default=None, ) - """The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" - and auth-alg = "leap").""" + """The login username for legacy LEAP connections (ie, key-mgmt = + "ieee8021x" and auth-alg = "leap").""" pairwise: Optional[List[str]] = field( - metadata={'dbus_name': 'pairwise', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'pairwise', + 'dbus_type': 'as', + }, default=None, ) - """A list of pairwise encryption algorithms which prevents connections to Wi- - Fi networks that do not utilize one of the algorithms in the list. For maximum - compatibility leave this property empty. Each list element may be one of - "tkip" or "ccmp".""" + """A list of pairwise encryption algorithms which prevents connections to + Wi-Fi networks that do not utilize one of the algorithms in the + list. For maximum compatibility leave this property empty. Each + list element may be one of "tkip" or "ccmp".""" pmf: Optional[int] = field( - metadata={'dbus_name': 'pmf', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'pmf', + 'dbus_type': 'i', + }, default=None, ) - """Indicates whether Protected Management Frames (802.11w) must be enabled for - the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use - global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable - PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the + """Indicates whether Protected Management Frames (802.11w) must be enabled + for the connection. One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT + (0) (use global default value), + NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), + NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or - NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not - supported). When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no - global default is set, PMF will be optionally enabled.""" + NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail + if not supported). When set to + NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default + is set, PMF will be optionally enabled.""" proto: Optional[List[str]] = field( - metadata={'dbus_name': 'proto', 'dbus_type': 'as'}, + metadata={ + 'dbus_name': 'proto', + 'dbus_type': 'as', + }, default=None, ) - """List of strings specifying the allowed WPA protocol versions to use. Each - element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If not - specified, both WPA and RSN connections are allowed.""" + """List of strings specifying the allowed WPA protocol versions to use. + Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). + If not specified, both WPA and RSN connections are allowed.""" psk: Optional[str] = field( - metadata={'dbus_name': 'psk', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'psk', + 'dbus_type': 's', + }, default=None, ) """Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII - passphrase of 8 to 63 characters that is (as specified in the 802.11i - standard) hashed to derive the actual key, or the key in form of 64 - hexadecimal character. The WPA3-Personal networks use a passphrase of any - length for SAE authentication.""" + passphrase of 8 to 63 characters that is (as specified in the + 802.11i standard) hashed to derive the actual key, or the key in + form of 64 hexadecimal character. The WPA3-Personal networks use a + passphrase of any length for SAE authentication.""" psk_flags: Optional[int] = field( - metadata={'dbus_name': 'psk-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'psk-flags', + 'dbus_type': 'u', + }, default=None, ) + """Flags indicating how to handle the "psk" property.""" wep_key_flags: Optional[int] = field( - metadata={'dbus_name': 'wep-key-flags', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'wep-key-flags', + 'dbus_type': 'u', + }, default=None, ) - """Flags indicating how to handle the "wep-key0", "wep-key1", "wep-key2", and - "wep-key3" properties.""" + """Flags indicating how to handle the "wep-key0", "wep-key1", "wep-key2", + and "wep-key3" properties.""" wep_key_type: Optional[int] = field( - metadata={'dbus_name': 'wep-key-type', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'wep-key-type', + 'dbus_type': 'u', + }, default=None, ) """Controls the interpretation of WEP keys. Allowed values are - NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character - hexadecimal string, or a 5- or 13-character ASCII password; or - NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a - string and will be hashed using the de-facto MD5 method to derive the actual - WEP key.""" + NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or + 26-character hexadecimal string, or a 5- or 13-character ASCII + password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the + passphrase is provided as a string and will be hashed using the de- + facto MD5 method to derive the actual WEP key.""" wep_key0: Optional[str] = field( - metadata={'dbus_name': 'wep-key0', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'wep-key0', + 'dbus_type': 's', + }, default=None, ) - """Index 0 WEP key. This is the WEP key used in most networks. See the "wep- - key-type" property for a description of how this key is interpreted.""" + """Index 0 WEP key. This is the WEP key used in most networks. See the + "wep-key-type" property for a description of how this key is + interpreted.""" wep_key1: Optional[str] = field( - metadata={'dbus_name': 'wep-key1', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'wep-key1', + 'dbus_type': 's', + }, default=None, ) """Index 1 WEP key. This WEP index is not used by most networks. See the - "wep-key-type" property for a description of how this key is interpreted.""" + "wep-key-type" property for a description of how this key is + interpreted.""" wep_key2: Optional[str] = field( - metadata={'dbus_name': 'wep-key2', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'wep-key2', + 'dbus_type': 's', + }, default=None, ) """Index 2 WEP key. This WEP index is not used by most networks. See the - "wep-key-type" property for a description of how this key is interpreted.""" + "wep-key-type" property for a description of how this key is + interpreted.""" wep_key3: Optional[str] = field( - metadata={'dbus_name': 'wep-key3', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'wep-key3', + 'dbus_type': 's', + }, default=None, ) """Index 3 WEP key. This WEP index is not used by most networks. See the - "wep-key-type" property for a description of how this key is interpreted.""" + "wep-key-type" property for a description of how this key is + interpreted.""" wep_tx_keyidx: Optional[int] = field( - metadata={'dbus_name': 'wep-tx-keyidx', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'wep-tx-keyidx', + 'dbus_type': 'u', + }, default=None, ) - """When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key - index is used by the AP, put that WEP key index here. Valid values are 0 - (default key) through 3. Note that some consumer access points (like the - Linksys WRT54G) number the keys 1 - 4.""" + """When static WEP is used (ie, key-mgmt = "none") and a non-default WEP + key index is used by the AP, put that WEP key index here. Valid + values are 0 (default key) through 3. Note that some consumer + access points (like the Linksys WRT54G) number the keys 1 - 4.""" wps_method: Optional[int] = field( - metadata={'dbus_name': 'wps-method', 'dbus_type': 'u'}, + metadata={ + 'dbus_name': 'wps-method', + 'dbus_type': 'u', + }, default=None, ) - """Flags indicating which mode of WPS is to be used if any. There's little - point in changing the default setting as NetworkManager will automatically - determine whether it's feasible to start WPS enrollment from the Access Point - capabilities. WPS can be disabled by setting this property to a value of 1.""" + """Flags indicating which mode of WPS is to be used if any. + + There's little point in changing the default setting as + NetworkManager will automatically determine whether it's feasible to + start WPS enrollment from the Access Point capabilities. + + WPS can be disabled by setting this property to a value of 1.""" diff --git a/sdbus_async/networkmanager/settings/wpan.py b/sdbus_async/networkmanager/settings/wpan.py index 1c4fbc2..1c63388 100644 --- a/sdbus_async/networkmanager/settings/wpan.py +++ b/sdbus_async/networkmanager/settings/wpan.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# This file was generated by tools/generate-settings-dataclasses.py, +# This file was generated by tools/generate-settings-dataclasses-jinja.py, # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field @@ -12,28 +12,45 @@ class WpanSettings(NetworkManagerSettingsMixin): """IEEE 802.15.4 (WPAN) MAC Settings""" channel: Optional[int] = field( - metadata={'dbus_name': 'channel', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'channel', + 'dbus_type': 'i', + }, default=None, ) - """IEEE 802.15.4 channel. A positive integer or -1, meaning "do not set, use - whatever the device is already set to".""" + """IEEE 802.15.4 channel. A positive integer or -1, meaning "do not set, + use whatever the device is already set to".""" mac_address: Optional[str] = field( - metadata={'dbus_name': 'mac-address', 'dbus_type': 's'}, + metadata={ + 'dbus_name': 'mac-address', + 'dbus_type': 's', + }, default=None, ) - """If specified, this connection will only apply to the IEEE 802.15.4 (WPAN) - MAC layer device whose permanent MAC address matches.""" + """If specified, this connection will only apply to the IEEE 802.15.4 + (WPAN) MAC layer device whose permanent MAC address matches.""" page: Optional[int] = field( - metadata={'dbus_name': 'page', 'dbus_type': 'i'}, + metadata={ + 'dbus_name': 'page', + 'dbus_type': 'i', + }, default=None, ) - """IEEE 802.15.4 channel page. A positive integer or -1, meaning "do not set, - use whatever the device is already set to".""" + """IEEE 802.15.4 channel page. A positive integer or -1, meaning "do not + set, use whatever the device is already set to".""" pan_id: Optional[int] = field( - metadata={'dbus_name': 'pan-id', 'dbus_type': 'u'}, - default=65535, + metadata={ + 'dbus_name': 'pan-id', + 'dbus_type': 'u', + }, + default=None, ) + """IEEE 802.15.4 Personal Area Network (PAN) identifier.""" short_address: Optional[int] = field( - metadata={'dbus_name': 'short-address', 'dbus_type': 'u'}, - default=65535, + metadata={ + 'dbus_name': 'short-address', + 'dbus_type': 'u', + }, + default=None, ) + """Short IEEE 802.15.4 address to be used within a restricted environment.""" From 7e905b271a94311e92ba7264bb5d5967d8027bf4 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 17:07:09 +0300 Subject: [PATCH 38/80] Added docs to jinja2 generator --- tools/generate-settings-dataclasses-jinja.py | 4 ++++ tools/jinja_templates/profile_settings.rst.jinja2 | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 tools/jinja_templates/profile_settings.rst.jinja2 diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 1c8d595..385786f 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -309,6 +309,10 @@ def main( with open(settings_dir / '__init__.py', mode='w') as f: f.write(init_template.render(all_settings=all_settings)) + docs_template = jinja_env.get_template('profile_settings.rst.jinja2') + with open('./docs/profile_settings.rst', mode='w') as f: + f.write(docs_template.render(all_settings=all_settings)) + if __name__ == '__main__': arg_parser = ArgumentParser() diff --git a/tools/jinja_templates/profile_settings.rst.jinja2 b/tools/jinja_templates/profile_settings.rst.jinja2 new file mode 100644 index 0000000..b545b36 --- /dev/null +++ b/tools/jinja_templates/profile_settings.rst.jinja2 @@ -0,0 +1,8 @@ +Connection Profile Settings Helpers +=================================== + +{% for setting in all_settings -%} +.. autoclass:: sdbus_async.networkmanager.settings.{{ setting.python_class_name }} + :members: + +{% endfor %} From ea21b2a5a3092a8a806dbccca55cc7311f825ac3 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 12 Nov 2022 17:07:42 +0300 Subject: [PATCH 39/80] Regenerate docs/profile_settings.rst with new generator --- docs/profile_settings.rst | 41 ++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/docs/profile_settings.rst b/docs/profile_settings.rst index 5e6b3f1..c2f3873 100644 --- a/docs/profile_settings.rst +++ b/docs/profile_settings.rst @@ -1,16 +1,6 @@ Connection Profile Settings Helpers =================================== - -.. autoclass:: sdbus_async.networkmanager.settings.ConnectionSettings - :members: - -.. autoclass:: sdbus_async.networkmanager.settings.Ipv4Settings - :members: - -.. autoclass:: sdbus_async.networkmanager.settings.Ipv6Settings - :members: - .. autoclass:: sdbus_async.networkmanager.settings.AdslSettings :members: @@ -32,19 +22,31 @@ Connection Profile Settings Helpers .. autoclass:: sdbus_async.networkmanager.settings.CdmaSettings :members: +.. autoclass:: sdbus_async.networkmanager.settings.ConnectionSettings + :members: + .. autoclass:: sdbus_async.networkmanager.settings.DcbSettings :members: +.. autoclass:: sdbus_async.networkmanager.settings.DummySettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.EapolSettings + :members: + .. autoclass:: sdbus_async.networkmanager.settings.EthernetSettings :members: -.. autoclass:: sdbus_async.networkmanager.settings.GsmSettings +.. autoclass:: sdbus_async.networkmanager.settings.EthtoolSettings :members: -.. autoclass:: sdbus_async.networkmanager.settings.HostnameSettings +.. autoclass:: sdbus_async.networkmanager.settings.GenericSettings :members: -.. autoclass:: sdbus_async.networkmanager.settings.Ieee8021XSettings +.. autoclass:: sdbus_async.networkmanager.settings.GsmSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.HostnameSettings :members: .. autoclass:: sdbus_async.networkmanager.settings.InfinibandSettings @@ -53,6 +55,12 @@ Connection Profile Settings Helpers .. autoclass:: sdbus_async.networkmanager.settings.IpTunnelSettings :members: +.. autoclass:: sdbus_async.networkmanager.settings.Ipv4Settings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.Ipv6Settings + :members: + .. autoclass:: sdbus_async.networkmanager.settings.LowpanSettings :members: @@ -98,6 +106,12 @@ Connection Profile Settings Helpers .. autoclass:: sdbus_async.networkmanager.settings.SerialSettings :members: +.. autoclass:: sdbus_async.networkmanager.settings.SriovSettings + :members: + +.. autoclass:: sdbus_async.networkmanager.settings.TcSettings + :members: + .. autoclass:: sdbus_async.networkmanager.settings.TeamSettings :members: @@ -142,3 +156,4 @@ Connection Profile Settings Helpers .. autoclass:: sdbus_async.networkmanager.settings.WpanSettings :members: + From 69874e568446466e3f792076d722de0a236a79f5 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 13 Nov 2022 22:01:17 +0300 Subject: [PATCH 40/80] Fix connection settings being optional ConnectionSettings must always be present in connection profile. --- sdbus_async/networkmanager/settings/profile.py | 12 +++--------- tools/generate-settings-dataclasses-jinja.py | 7 +++++++ tools/jinja_templates/profile.py.jinja2 | 14 ++++++-------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index b65c149..d7af23f 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -96,13 +96,7 @@ class ConnectionProfile: A group of related key/value pairs describing a specific piece of a Connection (profile). Keys are also referred to as properties. """ - # The settings object "connection" is special: It must always be present - # because it contains the UUID and the connection type which are required: - connection: ConnectionSettings = field( - metadata={'dbus_name': 'connection', - 'settings_class': ConnectionSettings}, - ) - # The list of the remaining settings classes was generated by + # The list of the settings classes was generated by # tools/generate-settings-dataclasses-jinja.py which generates the # settings classes themselfes as well. # If possible, please make changes by also updating the script. @@ -143,10 +137,10 @@ class ConnectionProfile: 'settings_class': CdmaSettings}, default=None, ) - connection: Optional[ConnectionSettings] = field( + connection: ConnectionSettings = field( metadata={'dbus_name': 'connection', 'settings_class': ConnectionSettings}, - default=None, + default_factory=ConnectionSettings, ) dcb: Optional[DcbSettings] = field( metadata={'dbus_name': 'dcb', diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 385786f..8bc6e2c 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -181,6 +181,13 @@ def datatypes_imports(self) -> list[str]: return datatypes_found + @cached_property + def is_optional_setting(self) -> bool: + if self.name == 'connection': + return False + + return True + def extract_docbook_paragraphs(docbook_node: Element) -> List[str]: return [x.text for x in docbook_node] diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 index 0666798..6c17831 100644 --- a/tools/jinja_templates/profile.py.jinja2 +++ b/tools/jinja_templates/profile.py.jinja2 @@ -47,23 +47,21 @@ class ConnectionProfile: A group of related key/value pairs describing a specific piece of a Connection (profile). Keys are also referred to as properties. """ - # The settings object "connection" is special: It must always be present - # because it contains the UUID and the connection type which are required: - connection: ConnectionSettings = field( - metadata={'dbus_name': 'connection', - 'settings_class': ConnectionSettings}, - ) - # The list of the remaining settings classes was generated by + # The list of the settings classes was generated by # tools/generate-settings-dataclasses-jinja.py which generates the # settings classes themselfes as well. # If possible, please make changes by also updating the script. # start of the generated list of settings classes {%- for setting in all_settings %} - {{ setting.snake_name }}: Optional[{{ setting.python_class_name }}] = field( + {{ setting.snake_name }}: {%- if setting.is_optional_setting %} Optional[{{ setting.python_class_name }}] {% else %} {{ setting.python_class_name }} {% endif -%} = field( metadata={'dbus_name': '{{ setting.name }}', 'settings_class': {{ setting.python_class_name }}}, +{%- if setting.is_optional_setting %} default=None, +{%- else %} + default_factory={{ setting.python_class_name }}, +{%- endif %} ) {%- endfor %} # end of the generated list of settings classes From 7b900c8ed12b8a69f1de014509cd83c7d04431c5 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 14 Nov 2022 20:58:31 +0300 Subject: [PATCH 41/80] Enable mypy namespace packages --- mypy.ini | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 mypy.ini diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..c19fe76 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,3 @@ +[mypy] +namespace_packages = true + From da54965c21dbca7f3f1cf6de5ba491835e017fcb Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 14 Nov 2022 21:05:55 +0300 Subject: [PATCH 42/80] Import ConnectionProfile to sdbus_async.networkmanager.settings --- sdbus_async/networkmanager/settings/__init__.py | 2 ++ tools/jinja_templates/__init__.py.jinja2 | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sdbus_async/networkmanager/settings/__init__.py b/sdbus_async/networkmanager/settings/__init__.py index d771e6f..3a06b1f 100644 --- a/sdbus_async/networkmanager/settings/__init__.py +++ b/sdbus_async/networkmanager/settings/__init__.py @@ -3,6 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations +from .profile import ConnectionProfile from .adsl import AdslSettings from .bluetooth import BluetoothSettings from .bond import BondSettings @@ -58,6 +59,7 @@ __all__ = ( + 'ConnectionProfile', 'AdslSettings', 'BluetoothSettings', 'BondSettings', diff --git a/tools/jinja_templates/__init__.py.jinja2 b/tools/jinja_templates/__init__.py.jinja2 index da4b9fe..15b9d91 100644 --- a/tools/jinja_templates/__init__.py.jinja2 +++ b/tools/jinja_templates/__init__.py.jinja2 @@ -3,11 +3,13 @@ # if possible, please make changes by also updating the script. from __future__ import annotations +from .profile import ConnectionProfile {% for setting in all_settings -%} from .{{ setting.snake_name }} import {{ setting.python_class_name }} {% endfor %} __all__ = ( + 'ConnectionProfile', {%- for setting in all_settings %} '{{ setting.python_class_name }}', {%- endfor %} From e907667cdb0190a6ed7e2350485210da30421ae3 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 14 Nov 2022 21:25:00 +0300 Subject: [PATCH 43/80] Connection Profiles are now contained in networkmanager.settings They should be explicitly imported from there. This allows better separation between generated and handwritten code. --- .../async/add-wifi-psk-connection-async.py | 4 +- examples/async/netdevinfo-async.py | 2 +- examples/async/update-connection-async.py | 2 +- examples/block/netdevinfo.py | 2 +- sdbus_async/networkmanager/__init__.py | 52 ---------- sdbus_block/networkmanager/__init__.py | 99 ------------------- 6 files changed, 6 insertions(+), 155 deletions(-) diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/async/add-wifi-psk-connection-async.py index 4080a54..fb9022a 100755 --- a/examples/async/add-wifi-psk-connection-async.py +++ b/examples/async/add-wifi-psk-connection-async.py @@ -55,9 +55,11 @@ from pprint import pformat from sdbus_async.networkmanager import ( NetworkManagerSettings as SettingsManager, + ConnectionType, +) +from sdbus_async.networkmanager.settings import ( ConnectionProfile, ConnectionSettings, - ConnectionType, Ipv4Settings, Ipv6Settings, WirelessSettings, diff --git a/examples/async/netdevinfo-async.py b/examples/async/netdevinfo-async.py index 9d798de..c2d4870 100755 --- a/examples/async/netdevinfo-async.py +++ b/examples/async/netdevinfo-async.py @@ -25,7 +25,7 @@ NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] -async def get_most_recent_connection_id(ifname, dev_type) -> Optional[str]: +async def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[str]: """Return the most-recently used connection_id for this device Besides getting the currently active connection, this will succeed diff --git a/examples/async/update-connection-async.py b/examples/async/update-connection-async.py index 2323d07..48e50e5 100755 --- a/examples/async/update-connection-async.py +++ b/examples/async/update-connection-async.py @@ -17,9 +17,9 @@ import asyncio import sdbus from functools import partial -from sdbus_async.networkmanager import ConnectionProfile from sdbus_async.networkmanager import NetworkManagerSettings from sdbus_async.networkmanager import NetworkConnectionSettings +from sdbus_async.networkmanager.settings import ConnectionProfile from pprint import pprint from typing import Any, Dict diff --git a/examples/block/netdevinfo.py b/examples/block/netdevinfo.py index e53ed6a..1f03161 100755 --- a/examples/block/netdevinfo.py +++ b/examples/block/netdevinfo.py @@ -24,7 +24,7 @@ NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] -def get_most_recent_connection_id(ifname, dev_type) -> Optional[str]: +def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[str]: """Return the most-recently used connection_id for this device Besides getting the currently active connection, this will succeed diff --git a/sdbus_async/networkmanager/__init__.py b/sdbus_async/networkmanager/__init__.py index 426e4cd..e49e0e7 100644 --- a/sdbus_async/networkmanager/__init__.py +++ b/sdbus_async/networkmanager/__init__.py @@ -195,8 +195,6 @@ WiFiP2PPeer, ) -from .settings.profile import ConnectionProfile - from .types import ( NetworkManagerConnectionProperties, NetworkManagerSetting, @@ -388,56 +386,6 @@ 'NetworkManagerDnsManager', 'NetworkManagerSettings', 'WiFiP2PPeer', - # .settings - 'AdslSettings', - 'BluetoothSettings', - 'BondSettings', - 'BondPortSettings', - 'BridgeSettings', - 'BridgePortSettings', - 'CdmaSettings', - 'ConnectionSettings', - 'AddressData', 'RouteData', 'WireguardPeers', - 'DcbSettings', - 'EthernetSettings', - 'GsmSettings', - 'HostnameSettings', - 'Ieee8021XSettings', - 'InfinibandSettings', - 'IpTunnelSettings', - 'Ipv4Settings', - 'Ipv6Settings', - 'LowpanSettings', - 'MacsecSettings', - 'MacvlanSettings', - 'MatchSettings', - 'OlpcMeshSettings', - 'OvsBridgeSettings', - 'OvsDpdkSettings', - 'OvsExternalIdsSettings', - 'OvsInterfaceSettings', - 'OvsPatchSettings', - 'OvsPortSettings', - 'PppSettings', - 'PppoeSettings', - 'ConnectionProfile', - 'ProxySettings', - 'SerialSettings', - 'TeamSettings', - 'TeamPortSettings', - 'TunSettings', - 'UserSettings', - 'VethSettings', - 'VlanSettings', - 'VpnSettings', - 'VrfSettings', - 'VxlanSettings', - 'WifiP2PSettings', - 'WimaxSettings', - 'WireguardSettings', - 'WirelessSettings', - 'WirelessSecuritySettings', - 'WpanSettings', # .types 'NetworkManagerConnectionProperties', 'NetworkManagerSetting', diff --git a/sdbus_block/networkmanager/__init__.py b/sdbus_block/networkmanager/__init__.py index bcdfec0..07559b1 100644 --- a/sdbus_block/networkmanager/__init__.py +++ b/sdbus_block/networkmanager/__init__.py @@ -194,55 +194,6 @@ NetworkManagerSettings, WiFiP2PPeer, ) -from .settings.adsl import AdslSettings -from .settings.bluetooth import BluetoothSettings -from .settings.bond import BondSettings -from .settings.bond_port import BondPortSettings -from .settings.bridge import BridgeSettings -from .settings.bridge_port import BridgePortSettings -from .settings.cdma import CdmaSettings -from .settings.connection import ConnectionSettings -from .settings.datatypes import AddressData, RouteData, WireguardPeers -from .settings.dcb import DcbSettings -from .settings.ethernet import EthernetSettings -from .settings.gsm import GsmSettings -from .settings.hostname import HostnameSettings -from .settings.ieee802_1x import Ieee8021XSettings -from .settings.infiniband import InfinibandSettings -from .settings.ip_tunnel import IpTunnelSettings -from .settings.ipv4 import Ipv4Settings -from .settings.ipv6 import Ipv6Settings -from .settings.lowpan import LowpanSettings -from .settings.macsec import MacsecSettings -from .settings.macvlan import MacvlanSettings -from .settings.match import MatchSettings -from .settings.olpc_mesh import OlpcMeshSettings -from .settings.ovs_bridge import OvsBridgeSettings -from .settings.ovs_dpdk import OvsDpdkSettings -from .settings.ovs_external_ids import OvsExternalIdsSettings -from .settings.ovs_interface import OvsInterfaceSettings -from .settings.ovs_patch import OvsPatchSettings -from .settings.ovs_port import OvsPortSettings -from .settings.ppp import PppSettings -from .settings.pppoe import PppoeSettings -from .settings.profile import ConnectionProfile -from .settings.proxy import ProxySettings -from .settings.serial import SerialSettings -from .settings.team import TeamSettings -from .settings.team_port import TeamPortSettings -from .settings.tun import TunSettings -from .settings.user import UserSettings -from .settings.veth import VethSettings -from .settings.vlan import VlanSettings -from .settings.vpn import VpnSettings -from .settings.vrf import VrfSettings -from .settings.vxlan import VxlanSettings -from .settings.wifi_p2p import WifiP2PSettings -from .settings.wimax import WimaxSettings -from .settings.wireguard import WireguardSettings -from .settings.wireless import WirelessSettings -from .settings.wireless_security import WirelessSecuritySettings -from .settings.wpan import WpanSettings from .types import ( NetworkManagerConnectionProperties, NetworkManagerSetting, @@ -434,56 +385,6 @@ 'NetworkManagerDnsManager', 'NetworkManagerSettings', 'WiFiP2PPeer', - # .settings - 'AdslSettings', - 'BluetoothSettings', - 'BondSettings', - 'BondPortSettings', - 'BridgeSettings', - 'BridgePortSettings', - 'CdmaSettings', - 'ConnectionSettings', - 'AddressData', 'RouteData', 'WireguardPeers', - 'DcbSettings', - 'EthernetSettings', - 'GsmSettings', - 'HostnameSettings', - 'Ieee8021XSettings', - 'InfinibandSettings', - 'IpTunnelSettings', - 'Ipv4Settings', - 'Ipv6Settings', - 'LowpanSettings', - 'MacsecSettings', - 'MacvlanSettings', - 'MatchSettings', - 'OlpcMeshSettings', - 'OvsBridgeSettings', - 'OvsDpdkSettings', - 'OvsExternalIdsSettings', - 'OvsInterfaceSettings', - 'OvsPatchSettings', - 'OvsPortSettings', - 'PppSettings', - 'PppoeSettings', - 'ConnectionProfile', - 'ProxySettings', - 'SerialSettings', - 'TeamSettings', - 'TeamPortSettings', - 'TunSettings', - 'UserSettings', - 'VethSettings', - 'VlanSettings', - 'VpnSettings', - 'VrfSettings', - 'VxlanSettings', - 'WifiP2PSettings', - 'WimaxSettings', - 'WireguardSettings', - 'WirelessSettings', - 'WirelessSecuritySettings', - 'WpanSettings', # .types 'NetworkManagerConnectionProperties', 'NetworkManagerSetting', From 05b39c73a4869ea0482065ca7d7f15f57671eecd Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Dec 2022 16:52:41 +0300 Subject: [PATCH 44/80] Export datatypes to networkmanager.settings --- sdbus_async/networkmanager/settings/__init__.py | 17 +++++++++++++++++ tools/jinja_templates/__init__.py.jinja2 | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/sdbus_async/networkmanager/settings/__init__.py b/sdbus_async/networkmanager/settings/__init__.py index 3a06b1f..60b03d0 100644 --- a/sdbus_async/networkmanager/settings/__init__.py +++ b/sdbus_async/networkmanager/settings/__init__.py @@ -57,6 +57,15 @@ from .wireless_security import WirelessSecuritySettings from .wpan import WpanSettings +from .datatypes import ( + AddressData, + RouteData, + LinkWatchers, + Vlans, + WireguardPeers, + RoutingRules, + Vfs, +) __all__ = ( 'ConnectionProfile', @@ -112,4 +121,12 @@ 'WirelessSettings', 'WirelessSecuritySettings', 'WpanSettings', + + 'AddressData', + 'RouteData', + 'LinkWatchers', + 'Vlans', + 'WireguardPeers', + 'RoutingRules', + 'Vfs', ) diff --git a/tools/jinja_templates/__init__.py.jinja2 b/tools/jinja_templates/__init__.py.jinja2 index 15b9d91..b7fc950 100644 --- a/tools/jinja_templates/__init__.py.jinja2 +++ b/tools/jinja_templates/__init__.py.jinja2 @@ -7,11 +7,28 @@ from .profile import ConnectionProfile {% for setting in all_settings -%} from .{{ setting.snake_name }} import {{ setting.python_class_name }} {% endfor %} +from .datatypes import ( + AddressData, + RouteData, + LinkWatchers, + Vlans, + WireguardPeers, + RoutingRules, + Vfs, +) __all__ = ( 'ConnectionProfile', {%- for setting in all_settings %} '{{ setting.python_class_name }}', {%- endfor %} + + 'AddressData', + 'RouteData', + 'LinkWatchers', + 'Vlans', + 'WireguardPeers', + 'RoutingRules', + 'Vfs', ) From dd7f56158ee15532c621df328ec52bbd33188c3c Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Dec 2022 17:36:04 +0300 Subject: [PATCH 45/80] Make None be a default for more settings datatypes fields --- .../networkmanager/settings/datatypes.py | 63 ++++++++++++++----- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/sdbus_async/networkmanager/settings/datatypes.py b/sdbus_async/networkmanager/settings/datatypes.py index 452ea93..278012c 100644 --- a/sdbus_async/networkmanager/settings/datatypes.py +++ b/sdbus_async/networkmanager/settings/datatypes.py @@ -49,43 +49,43 @@ class LinkWatchers(NetworkManagerSettingsMixin): ) delay_up: Optional[int] = field( metadata={'dbus_delay-up': 'delay-up', 'dbus_type': 'u'}, - default=None + default=None, ) delay_down: Optional[int] = field( metadata={'dbus_name': 'delay-down', 'dbus_type': 'u'}, - default=None + default=None, ) init_wait: Optional[int] = field( metadata={'dbus_name': 'init-wait', 'dbus_type': 'u'}, - default=None + default=None, ) interval: Optional[int] = field( metadata={'dbus_name': 'interval', 'dbus_type': 'u'}, - default=None + default=None, ) missed_max: Optional[int] = field( metadata={'dbus_name': 'missed-max', 'dbus_type': 'u'}, - default=None + default=None, ) source_host: Optional[str] = field( metadata={'dbus_name': 'source-host', 'dbus_type': 's'}, - default=None + default=None, ) target_host: Optional[str] = field( metadata={'dbus_name': 'target-host', 'dbus_type': 's'}, - default=None + default=None, ) validate_active: Optional[bool] = field( metadata={'dbus_name': 'validate-active', 'dbus_type': 'b'}, - default=None + default=None, ) validate_inactive: Optional[bool] = field( metadata={'dbus_name': 'validate-inactive', 'dbus_type': 'b'}, - default=None + default=None, ) send_alway: Optional[bool] = field( metadata={'dbus_name': 'send-alway', 'dbus_type': 'b'}, - default=None + default=None, ) @@ -102,24 +102,29 @@ class Vlans(NetworkManagerSettingsMixin): vid_end: int = field( metadata={'dbus_name': 'vid-end', 'dbus_type': 'u'}, ) - pvid: bool = field( + pvid: Optional[bool] = field( metadata={'dbus_name': 'pvid', 'dbus_type': 'b'}, + default=None, ) - untagged: bool = field( + untagged: Optional[bool] = field( metadata={'dbus_name': 'untagged', 'dbus_type': 'b'}, + default=None ) @dataclass class WireguardPeers(NetworkManagerSettingsMixin): - public_key: str = field( + public_key: Optional[str] = field( metadata={'dbus_name': 'public-key', 'dbus_type': 's'}, + default=None, ) - endpoint: int = field( + endpoint: Optional[int] = field( metadata={'dbus_name': 'endpoint', 'dbus_type': 's'}, + default=None, ) - allowed_ips: List[str] = field( + allowed_ips: Optional[List[str]] = field( metadata={'dbus_name': 'allowed-ips', 'dbus_type': 'as'}, + default=None, ) @@ -127,69 +132,91 @@ class WireguardPeers(NetworkManagerSettingsMixin): class RoutingRules(NetworkManagerSettingsMixin): action: Optional[int] = field( metadata={'dbus_name': 'action', 'dbus_type': 'y'}, + default=None, ) dport_end: Optional[int] = field( metadata={'dbus_name': 'dport-end', 'dbus_type': 'q'}, + default=None, ) dport_start: Optional[int] = field( metadata={'dbus_name': 'dport-start', 'dbus_type': 'q'}, + default=None, ) family: Optional[int] = field( metadata={'dbus_name': 'family', 'dbus_type': 'i'}, + default=None, ) from_prefix: Optional[str] = field( metadata={'dbus_name': 'from', 'dbus_type': 's'}, + default=None, ) from_len: Optional[int] = field( metadata={'dbus_name': 'from-len', 'dbus_type': 'y'}, + default=None, ) fwmark: Optional[int] = field( metadata={'dbus_name': 'fwmark', 'dbus_type': 'u'}, + default=None, ) fwmask: Optional[int] = field( metadata={'dbus_name': 'fwmask', 'dbus_type': 'u'}, + default=None, ) iifname: Optional[str] = field( metadata={'dbus_name': 'iifname', 'dbus_type': 's'}, + default=None, ) invert: Optional[bool] = field( metadata={'dbus_name': 'invert', 'dbus_type': 'b'}, + default=None, ) ipproto: Optional[str] = field( metadata={'dbus_name': 'ipproto', 'dbus_type': 's'}, + default=None, ) oifname: Optional[str] = field( metadata={'dbus_name': 'oifname', 'dbus_type': 's'}, + default=None, ) priority: Optional[int] = field( metadata={'dbus_name': 'priority', 'dbus_type': 'u'}, + default=None, ) sport_end: Optional[int] = field( metadata={'dbus_name': 'sport-end', 'dbus_type': 'q'}, + default=None, ) sport_start: Optional[int] = field( metadata={'dbus_name': 'sport-start', 'dbus_type': 'q'}, + default=None, ) supress_prefixlength: Optional[int] = field( metadata={'dbus_name': 'supress-prefixlength', 'dbus_type': 'i'}, + default=None, ) table: Optional[int] = field( metadata={'dbus_name': 'table', 'dbus_type': 'u'}, + default=None, ) to: Optional[str] = field( metadata={'dbus_name': 'to', 'dbus_type': 's'}, + default=None, ) tos: Optional[int] = field( metadata={'dbus_name': 'tos', 'dbus_type': 'y'}, + default=None, ) to_len: Optional[int] = field( metadata={'dbus_name': 'to-len', 'dbus_type': 'y'}, + default=None, ) range_end: Optional[int] = field( metadata={'dbus_name': 'range-end', 'dbus_type': 'u'}, + default=None, ) range_start: Optional[int] = field( metadata={'dbus_name': 'range-start', 'dbus_type': 'u'}, + default=None, ) @@ -200,21 +227,27 @@ class Vfs(NetworkManagerSettingsMixin): ) mac: Optional[str] = field( metadata={'dbus_name': 'mac', 'dbus_type': 's'}, + default=None, ) spoof_check: Optional[str] = field( metadata={'dbus_name': 'spoof-check', 'dbus_type': 's'}, + default=None, ) trust: Optional[str] = field( metadata={'dbus_name': 'trust', 'dbus_type': 's'}, + default=None, ) min_tx_rate: Optional[str] = field( metadata={'dbus_name': 'min-tx-rate', 'dbus_type': 's'}, + default=None, ) max_tx_rate: Optional[str] = field( metadata={'dbus_name': 'max-tx-rate', 'dbus_type': 's'}, + default=None, ) vlans: Optional[str] = field( metadata={'dbus_name': 'vlans', 'dbus_type': 's'}, + default=None, ) From 6439b7d959902650802158143d6a8c47adea5b12 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Dec 2022 18:05:53 +0300 Subject: [PATCH 46/80] Added ConnectionProfile.update method Updates connection profile with the settings from another profile. Similar to dict.update --- .../networkmanager/settings/profile.py | 28 ++++++++ tests/__init__.py | 19 ++++++ tests/test_settings_profile.py | 64 +++++++++++++++++++ tools/jinja_templates/profile.py.jinja2 | 28 ++++++++ 4 files changed, 139 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/test_settings_profile.py diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index d7af23f..5c067f4 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -435,6 +435,34 @@ def from_settings_dict( for k, v in settings_dict.items()} return cls(**unvarianted_options) + def update(self, other: ConnectionProfile) -> None: + """Update this connection profile with the settings from the other. + + Similar to dict.update method. + """ + for f in fields(other): + settings_field_name = f.name + other_settings = getattr(other, settings_field_name) + + if other_settings is None: + continue + + my_settings = getattr(self, settings_field_name) + + if my_settings is None: + setattr(self, settings_field_name, other_settings) + continue + + for setting_field in fields(other_settings): + setting_field_name = setting_field.name + + other_setting = getattr(other_settings, setting_field_name) + + if other_setting is None: + continue + + setattr(my_settings, setting_field_name, other_setting) + SETTING_DBUS_NAME_TO_NAME: Dict[str, str] = { f.metadata['dbus_name']: f.name diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..4b6332c --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# Copyright (C) 2022 igo95862 + +# This file is part of python-sdbus + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/tests/test_settings_profile.py b/tests/test_settings_profile.py new file mode 100644 index 0000000..d39a85c --- /dev/null +++ b/tests/test_settings_profile.py @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# Copyright (C) 2022 igo95862 + +# This file is part of python-sdbus + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +from __future__ import annotations + +from unittest import TestCase +from sdbus_async.networkmanager.settings import ConnectionProfile + +connection_dict = { + 'connection': {'id': 'mlvd-wg', + 'interface-name': 'mlvd-wg', + 'timestamp': 150000, + 'type': 'wireguard', + 'uuid': 'uuid'}, + 'ipv4': {'address-data': [{'address': '10.0.0.1', 'prefix': 32}], + 'dns': [150000], + 'dns-search': ['~'], + 'method': 'manual'}, + 'ipv6': {'addr-gen-mode': 1, + 'address-data': [{'address': 'fc00:1', + 'prefix': 128}], + 'method': 'manual'}, + 'wireguard': { + 'peers': [ + {'allowed-ips': ['::/0', '0.0.0.0/0'], + 'endpoint': '1.1.1.1:51820', + 'public-key': 'public_key'}]}} + +secret_dict = { + 'connection': {}, + 'ipv4': {}, + 'ipv6': {}, + 'proxy': {}, + 'wireguard': { + 'peers': [ + {'public-key': 'public_key'} + ], + 'private-key': 'secret_key'}} + + +class TestSettingsProfile(TestCase): + def test_update(self) -> None: + connection = ConnectionProfile.from_settings_dict(connection_dict) + secrets = ConnectionProfile.from_settings_dict(secret_dict) + + connection.update(secrets) + + self.assertEqual(connection.wireguard.private_key, 'secret_key') diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 index 6c17831..17811a2 100644 --- a/tools/jinja_templates/profile.py.jinja2 +++ b/tools/jinja_templates/profile.py.jinja2 @@ -137,6 +137,34 @@ class ConnectionProfile: for k, v in settings_dict.items()} return cls(**unvarianted_options) + def update(self, other: ConnectionProfile) -> None: + """Update this connection profile with the settings from the other. + + Similar to dict.update method. + """ + for f in fields(other): + settings_field_name = f.name + other_settings = getattr(other, settings_field_name) + + if other_settings is None: + continue + + my_settings = getattr(self, settings_field_name) + + if my_settings is None: + setattr(self, settings_field_name, other_settings) + continue + + for setting_field in fields(other_settings): + setting_field_name = setting_field.name + + other_setting = getattr(other_settings, setting_field_name) + + if other_setting is None: + continue + + setattr(my_settings, setting_field_name, other_setting) + SETTING_DBUS_NAME_TO_NAME: Dict[str, str] = { f.metadata['dbus_name']: f.name From 4cd0cb15fc767cfd590c538f991785d24a26fcc5 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 17 Dec 2022 20:57:39 +0300 Subject: [PATCH 47/80] Added `secret_fields_names` attribute to settings It contains the names of the fields that are secret and must be fetched separately. --- sdbus_async/networkmanager/settings/adsl.py | 3 ++- sdbus_async/networkmanager/settings/base.py | 10 ++++--- sdbus_async/networkmanager/settings/cdma.py | 3 ++- .../networkmanager/settings/connection.py | 3 ++- sdbus_async/networkmanager/settings/dcb.py | 3 ++- sdbus_async/networkmanager/settings/eapol.py | 3 ++- sdbus_async/networkmanager/settings/gsm.py | 3 ++- sdbus_async/networkmanager/settings/ipv4.py | 3 ++- sdbus_async/networkmanager/settings/ipv6.py | 3 ++- sdbus_async/networkmanager/settings/macsec.py | 3 ++- sdbus_async/networkmanager/settings/pppoe.py | 3 ++- .../networkmanager/settings/wireguard.py | 3 ++- .../settings/wireless_security.py | 3 ++- tools/generate-settings-dataclasses-jinja.py | 27 ++++++++++++++++--- tools/jinja_templates/setting.py.jinja2 | 3 +++ 15 files changed, 56 insertions(+), 20 deletions(-) diff --git a/sdbus_async/networkmanager/settings/adsl.py b/sdbus_async/networkmanager/settings/adsl.py index 7c38341..af2a9c5 100644 --- a/sdbus_async/networkmanager/settings/adsl.py +++ b/sdbus_async/networkmanager/settings/adsl.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class AdslSettings(NetworkManagerSettingsMixin): """ADSL Settings""" + secret_fields_names: ClassVar[List[str]] = ['password'] encapsulation: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/base.py b/sdbus_async/networkmanager/settings/base.py index 33ad163..cff4a69 100644 --- a/sdbus_async/networkmanager/settings/base.py +++ b/sdbus_async/networkmanager/settings/base.py @@ -1,14 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later from __future__ import annotations + from dataclasses import fields from functools import lru_cache -from typing import Any, Dict, Type, cast +from typing import Any, ClassVar, Dict, List, Type, cast -from ..types import ( - NetworkManagerSettingsDomain, -) +from ..types import NetworkManagerSettingsDomain class NetworkManagerSettingsMixin: + secret_fields_names: ClassVar[List[str]] = [] + def to_dbus(self) -> NetworkManagerSettingsDomain: """Return a dbus dictionary for NetworkManager to add/update profiles diff --git a/sdbus_async/networkmanager/settings/cdma.py b/sdbus_async/networkmanager/settings/cdma.py index 40fcc67..d3580d3 100644 --- a/sdbus_async/networkmanager/settings/cdma.py +++ b/sdbus_async/networkmanager/settings/cdma.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class CdmaSettings(NetworkManagerSettingsMixin): """CDMA-based Mobile Broadband Settings""" + secret_fields_names: ClassVar[List[str]] = ['password'] mtu: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/connection.py b/sdbus_async/networkmanager/settings/connection.py index 47416bf..711d1b9 100644 --- a/sdbus_async/networkmanager/settings/connection.py +++ b/sdbus_async/networkmanager/settings/connection.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class ConnectionSettings(NetworkManagerSettingsMixin): """General Connection Profile Settings""" + secret_fields_names: ClassVar[List[str]] = ['mptcp'] auth_retries: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index 609d6a8..70e53bb 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class DcbSettings(NetworkManagerSettingsMixin): """Data Center Bridging Settings""" + secret_fields_names: ClassVar[List[str]] = ['app_fcoe', 'app_fip', 'app_iscsi', 'priority_flow_control', 'priority_group'] app_fcoe_flags: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/eapol.py b/sdbus_async/networkmanager/settings/eapol.py index e4eb6e4..fcd5010 100644 --- a/sdbus_async/networkmanager/settings/eapol.py +++ b/sdbus_async/networkmanager/settings/eapol.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class EapolSettings(NetworkManagerSettingsMixin): """IEEE 802.1x Authentication Settings""" + secret_fields_names: ClassVar[List[str]] = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase1_auth', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] altsubject_matches: Optional[List[str]] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/gsm.py b/sdbus_async/networkmanager/settings/gsm.py index 6c49fb1..383ea94 100644 --- a/sdbus_async/networkmanager/settings/gsm.py +++ b/sdbus_async/networkmanager/settings/gsm.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class GsmSettings(NetworkManagerSettingsMixin): """GSM-based Mobile Broadband Settings""" + secret_fields_names: ClassVar[List[str]] = ['password', 'pin'] apn: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv4.py b/sdbus_async/networkmanager/settings/ipv4.py index b2b91f2..00e5ee6 100644 --- a/sdbus_async/networkmanager/settings/ipv4.py +++ b/sdbus_async/networkmanager/settings/ipv4.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, List, Optional, Tuple +from typing import Any, ClassVar, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import AddressData, RouteData, RoutingRules @@ -11,6 +11,7 @@ @dataclass class Ipv4Settings(NetworkManagerSettingsMixin): """IPv4 Settings""" + secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] address_data: Optional[List[AddressData]] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv6.py b/sdbus_async/networkmanager/settings/ipv6.py index 7f69c51..5e2230d 100644 --- a/sdbus_async/networkmanager/settings/ipv6.py +++ b/sdbus_async/networkmanager/settings/ipv6.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, List, Optional, Tuple +from typing import Any, ClassVar, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import AddressData, RouteData, RoutingRules @@ -11,6 +11,7 @@ @dataclass class Ipv6Settings(NetworkManagerSettingsMixin): """IPv6 Settings""" + secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] addr_gen_mode: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/macsec.py b/sdbus_async/networkmanager/settings/macsec.py index 95c40df..884dbc3 100644 --- a/sdbus_async/networkmanager/settings/macsec.py +++ b/sdbus_async/networkmanager/settings/macsec.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class MacsecSettings(NetworkManagerSettingsMixin): """MACSec Settings""" + secret_fields_names: ClassVar[List[str]] = ['mka_cak'] encrypt: Optional[bool] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/pppoe.py b/sdbus_async/networkmanager/settings/pppoe.py index 3d6c4d7..bbfe3e5 100644 --- a/sdbus_async/networkmanager/settings/pppoe.py +++ b/sdbus_async/networkmanager/settings/pppoe.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class PppoeSettings(NetworkManagerSettingsMixin): """PPP-over-Ethernet Settings""" + secret_fields_names: ClassVar[List[str]] = ['password'] parent: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/wireguard.py b/sdbus_async/networkmanager/settings/wireguard.py index 371c2dc..e6b264f 100644 --- a/sdbus_async/networkmanager/settings/wireguard.py +++ b/sdbus_async/networkmanager/settings/wireguard.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, List, Optional, Tuple +from typing import Any, ClassVar, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import WireguardPeers @@ -11,6 +11,7 @@ @dataclass class WireguardSettings(NetworkManagerSettingsMixin): """WireGuard Settings""" + secret_fields_names: ClassVar[List[str]] = ['private_key'] fwmark: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index 7933541..e43fff5 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -3,13 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import List, Optional +from typing import ClassVar, List, Optional from .base import NetworkManagerSettingsMixin @dataclass class WirelessSecuritySettings(NetworkManagerSettingsMixin): """Wi-Fi Security Settings""" + secret_fields_names: ClassVar[List[str]] = ['leap_password', 'psk', 'wep_key'] auth_alg: Optional[str] = field( metadata={ diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index 8bc6e2c..ee557c3 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -21,7 +21,7 @@ from re import Pattern from re import compile as regex_compile from textwrap import fill -from typing import List, Optional +from typing import List, Optional, Set from xml.etree.ElementTree import Element, parse from jinja2 import Environment, FileSystemLoader @@ -125,7 +125,7 @@ def __init__(self, name: str, extra_typing = dbus_to_python_extra_typing_imports.get(dbus_type) if extra_typing is not None: - parent.typing_imports.update(extra_typing) + parent.properties_want_imports.update(extra_typing) @cached_property def python_type(self) -> str: @@ -146,10 +146,19 @@ def __init__(self, name: str, description: str, name_upper: str, self.description = description self.name_upper = name_upper - self.typing_imports = {'Optional'} - + self.properties_want_imports = {'Optional'} self.properties: List[NmSettingPropertyIntrospection] = [] + @cached_property + def typing_imports(self) -> List[str]: + typing_imports: Set[str] = self.properties_want_imports.copy() + + if self.secret_fields: + typing_imports.add('ClassVar') + typing_imports.add('List') + + return typing_imports + @cached_property def python_class_name(self) -> str: @@ -188,6 +197,16 @@ def is_optional_setting(self) -> bool: return True + @cached_property + def secret_fields(self) -> List[str]: + secret_fields: List[str] = [] + + for x in self.properties: + if x.python_name.endswith('_flags') and x.python_type == 'int': + secret_fields.append(x.python_name.removesuffix('_flags')) + + return secret_fields + def extract_docbook_paragraphs(docbook_node: Element) -> List[str]: return [x.text for x in docbook_node] diff --git a/tools/jinja_templates/setting.py.jinja2 b/tools/jinja_templates/setting.py.jinja2 index 3e3abb0..125bc27 100644 --- a/tools/jinja_templates/setting.py.jinja2 +++ b/tools/jinja_templates/setting.py.jinja2 @@ -12,6 +12,9 @@ from .datatypes import {{ setting.datatypes_imports|sort|join(', ') }} @dataclass class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): """{{ setting.description }}""" +{%- if setting.secret_fields %} + secret_fields_names: ClassVar[List[str]] = ['{{ setting.secret_fields|sort|join("', '") }}'] +{%- endif %} {% for property in setting.properties %} {{ property.python_name }}: Optional[{{ property.python_type }}] = field( metadata={ From 07507e8168df6b9564bfccd3c0ce02aa58d3350a Mon Sep 17 00:00:00 2001 From: igo95862 Date: Tue, 20 Dec 2022 20:20:09 +0300 Subject: [PATCH 48/80] Added `secret_name` class var to settings classes Can be used in `get_secrets` method. --- sdbus_async/networkmanager/settings/adsl.py | 1 + sdbus_async/networkmanager/settings/base.py | 1 + sdbus_async/networkmanager/settings/cdma.py | 1 + sdbus_async/networkmanager/settings/connection.py | 1 + sdbus_async/networkmanager/settings/dcb.py | 1 + sdbus_async/networkmanager/settings/eapol.py | 1 + sdbus_async/networkmanager/settings/gsm.py | 1 + sdbus_async/networkmanager/settings/ipv4.py | 1 + sdbus_async/networkmanager/settings/ipv6.py | 1 + sdbus_async/networkmanager/settings/macsec.py | 1 + sdbus_async/networkmanager/settings/pppoe.py | 1 + sdbus_async/networkmanager/settings/wireguard.py | 1 + sdbus_async/networkmanager/settings/wireless_security.py | 1 + tools/jinja_templates/setting.py.jinja2 | 1 + 14 files changed, 14 insertions(+) diff --git a/sdbus_async/networkmanager/settings/adsl.py b/sdbus_async/networkmanager/settings/adsl.py index af2a9c5..9893def 100644 --- a/sdbus_async/networkmanager/settings/adsl.py +++ b/sdbus_async/networkmanager/settings/adsl.py @@ -11,6 +11,7 @@ class AdslSettings(NetworkManagerSettingsMixin): """ADSL Settings""" secret_fields_names: ClassVar[List[str]] = ['password'] + secret_name = 'adsl' encapsulation: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/base.py b/sdbus_async/networkmanager/settings/base.py index cff4a69..80a3262 100644 --- a/sdbus_async/networkmanager/settings/base.py +++ b/sdbus_async/networkmanager/settings/base.py @@ -10,6 +10,7 @@ class NetworkManagerSettingsMixin: secret_fields_names: ClassVar[List[str]] = [] + secret_name: ClassVar[str] = '' def to_dbus(self) -> NetworkManagerSettingsDomain: """Return a dbus dictionary for NetworkManager to add/update profiles diff --git a/sdbus_async/networkmanager/settings/cdma.py b/sdbus_async/networkmanager/settings/cdma.py index d3580d3..4eea623 100644 --- a/sdbus_async/networkmanager/settings/cdma.py +++ b/sdbus_async/networkmanager/settings/cdma.py @@ -11,6 +11,7 @@ class CdmaSettings(NetworkManagerSettingsMixin): """CDMA-based Mobile Broadband Settings""" secret_fields_names: ClassVar[List[str]] = ['password'] + secret_name = 'cdma' mtu: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/connection.py b/sdbus_async/networkmanager/settings/connection.py index 711d1b9..f61dc44 100644 --- a/sdbus_async/networkmanager/settings/connection.py +++ b/sdbus_async/networkmanager/settings/connection.py @@ -11,6 +11,7 @@ class ConnectionSettings(NetworkManagerSettingsMixin): """General Connection Profile Settings""" secret_fields_names: ClassVar[List[str]] = ['mptcp'] + secret_name = 'connection' auth_retries: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index 70e53bb..ab9b63d 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -11,6 +11,7 @@ class DcbSettings(NetworkManagerSettingsMixin): """Data Center Bridging Settings""" secret_fields_names: ClassVar[List[str]] = ['app_fcoe', 'app_fip', 'app_iscsi', 'priority_flow_control', 'priority_group'] + secret_name = 'dcb' app_fcoe_flags: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/eapol.py b/sdbus_async/networkmanager/settings/eapol.py index fcd5010..dfbed5b 100644 --- a/sdbus_async/networkmanager/settings/eapol.py +++ b/sdbus_async/networkmanager/settings/eapol.py @@ -11,6 +11,7 @@ class EapolSettings(NetworkManagerSettingsMixin): """IEEE 802.1x Authentication Settings""" secret_fields_names: ClassVar[List[str]] = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase1_auth', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] + secret_name = '802-1x' altsubject_matches: Optional[List[str]] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/gsm.py b/sdbus_async/networkmanager/settings/gsm.py index 383ea94..bdd4714 100644 --- a/sdbus_async/networkmanager/settings/gsm.py +++ b/sdbus_async/networkmanager/settings/gsm.py @@ -11,6 +11,7 @@ class GsmSettings(NetworkManagerSettingsMixin): """GSM-based Mobile Broadband Settings""" secret_fields_names: ClassVar[List[str]] = ['password', 'pin'] + secret_name = 'gsm' apn: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv4.py b/sdbus_async/networkmanager/settings/ipv4.py index 00e5ee6..d80a8a6 100644 --- a/sdbus_async/networkmanager/settings/ipv4.py +++ b/sdbus_async/networkmanager/settings/ipv4.py @@ -12,6 +12,7 @@ class Ipv4Settings(NetworkManagerSettingsMixin): """IPv4 Settings""" secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] + secret_name = 'ipv4' address_data: Optional[List[AddressData]] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv6.py b/sdbus_async/networkmanager/settings/ipv6.py index 5e2230d..7c2558c 100644 --- a/sdbus_async/networkmanager/settings/ipv6.py +++ b/sdbus_async/networkmanager/settings/ipv6.py @@ -12,6 +12,7 @@ class Ipv6Settings(NetworkManagerSettingsMixin): """IPv6 Settings""" secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] + secret_name = 'ipv6' addr_gen_mode: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/macsec.py b/sdbus_async/networkmanager/settings/macsec.py index 884dbc3..f997aef 100644 --- a/sdbus_async/networkmanager/settings/macsec.py +++ b/sdbus_async/networkmanager/settings/macsec.py @@ -11,6 +11,7 @@ class MacsecSettings(NetworkManagerSettingsMixin): """MACSec Settings""" secret_fields_names: ClassVar[List[str]] = ['mka_cak'] + secret_name = 'macsec' encrypt: Optional[bool] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/pppoe.py b/sdbus_async/networkmanager/settings/pppoe.py index bbfe3e5..8a420aa 100644 --- a/sdbus_async/networkmanager/settings/pppoe.py +++ b/sdbus_async/networkmanager/settings/pppoe.py @@ -11,6 +11,7 @@ class PppoeSettings(NetworkManagerSettingsMixin): """PPP-over-Ethernet Settings""" secret_fields_names: ClassVar[List[str]] = ['password'] + secret_name = 'pppoe' parent: Optional[str] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/wireguard.py b/sdbus_async/networkmanager/settings/wireguard.py index e6b264f..e77526e 100644 --- a/sdbus_async/networkmanager/settings/wireguard.py +++ b/sdbus_async/networkmanager/settings/wireguard.py @@ -12,6 +12,7 @@ class WireguardSettings(NetworkManagerSettingsMixin): """WireGuard Settings""" secret_fields_names: ClassVar[List[str]] = ['private_key'] + secret_name = 'wireguard' fwmark: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index e43fff5..0c7dfac 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -11,6 +11,7 @@ class WirelessSecuritySettings(NetworkManagerSettingsMixin): """Wi-Fi Security Settings""" secret_fields_names: ClassVar[List[str]] = ['leap_password', 'psk', 'wep_key'] + secret_name = '802-11-wireless-security' auth_alg: Optional[str] = field( metadata={ diff --git a/tools/jinja_templates/setting.py.jinja2 b/tools/jinja_templates/setting.py.jinja2 index 125bc27..dcdcb69 100644 --- a/tools/jinja_templates/setting.py.jinja2 +++ b/tools/jinja_templates/setting.py.jinja2 @@ -14,6 +14,7 @@ class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): """{{ setting.description }}""" {%- if setting.secret_fields %} secret_fields_names: ClassVar[List[str]] = ['{{ setting.secret_fields|sort|join("', '") }}'] + secret_name = '{{ setting.name }}' {%- endif %} {% for property in setting.properties %} {{ property.python_name }}: Optional[{{ property.python_type }}] = field( From 82b6f23ccc31e0f5a733bf94abc507082e4df239 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Tue, 20 Dec 2022 21:13:15 +0300 Subject: [PATCH 49/80] Improve secret fields detection. Now the `_flags` fields must have a corresponding field without `_flags` suffix. Fixes several fields which were not secret but mark as is. --- .../networkmanager/settings/connection.py | 4 +--- sdbus_async/networkmanager/settings/dcb.py | 2 +- sdbus_async/networkmanager/settings/eapol.py | 2 +- .../settings/wireless_security.py | 2 +- tools/generate-settings-dataclasses-jinja.py | 18 ++++++++++++------ 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sdbus_async/networkmanager/settings/connection.py b/sdbus_async/networkmanager/settings/connection.py index f61dc44..47416bf 100644 --- a/sdbus_async/networkmanager/settings/connection.py +++ b/sdbus_async/networkmanager/settings/connection.py @@ -3,15 +3,13 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import List, Optional from .base import NetworkManagerSettingsMixin @dataclass class ConnectionSettings(NetworkManagerSettingsMixin): """General Connection Profile Settings""" - secret_fields_names: ClassVar[List[str]] = ['mptcp'] - secret_name = 'connection' auth_retries: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index ab9b63d..94d15fc 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -10,7 +10,7 @@ @dataclass class DcbSettings(NetworkManagerSettingsMixin): """Data Center Bridging Settings""" - secret_fields_names: ClassVar[List[str]] = ['app_fcoe', 'app_fip', 'app_iscsi', 'priority_flow_control', 'priority_group'] + secret_fields_names: ClassVar[List[str]] = ['priority_flow_control'] secret_name = 'dcb' app_fcoe_flags: Optional[int] = field( diff --git a/sdbus_async/networkmanager/settings/eapol.py b/sdbus_async/networkmanager/settings/eapol.py index dfbed5b..02bc3b4 100644 --- a/sdbus_async/networkmanager/settings/eapol.py +++ b/sdbus_async/networkmanager/settings/eapol.py @@ -10,7 +10,7 @@ @dataclass class EapolSettings(NetworkManagerSettingsMixin): """IEEE 802.1x Authentication Settings""" - secret_fields_names: ClassVar[List[str]] = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase1_auth', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] + secret_fields_names: ClassVar[List[str]] = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] secret_name = '802-1x' altsubject_matches: Optional[List[str]] = field( diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index 0c7dfac..8adc810 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -10,7 +10,7 @@ @dataclass class WirelessSecuritySettings(NetworkManagerSettingsMixin): """Wi-Fi Security Settings""" - secret_fields_names: ClassVar[List[str]] = ['leap_password', 'psk', 'wep_key'] + secret_fields_names: ClassVar[List[str]] = ['leap_password', 'psk'] secret_name = '802-11-wireless-security' auth_alg: Optional[str] = field( diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index ee557c3..f804ebc 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -24,7 +24,7 @@ from typing import List, Optional, Set from xml.etree.ElementTree import Element, parse -from jinja2 import Environment, FileSystemLoader +from jinja2 import Environment, FileSystemLoader, StrictUndefined dbus_to_python_extra_typing_imports = { "as": ("List", ), @@ -150,7 +150,7 @@ def __init__(self, name: str, description: str, name_upper: str, self.properties: List[NmSettingPropertyIntrospection] = [] @cached_property - def typing_imports(self) -> List[str]: + def typing_imports(self) -> Set[str]: typing_imports: Set[str] = self.properties_want_imports.copy() if self.secret_fields: @@ -198,14 +198,19 @@ def is_optional_setting(self) -> bool: return True @cached_property - def secret_fields(self) -> List[str]: - secret_fields: List[str] = [] + def secret_fields(self) -> Set[str]: + all_fields: Set[str] = set() + possible_secret_fields: Set[str] = set() for x in self.properties: + if x.python_name.endswith('_flags') and x.python_type == 'int': - secret_fields.append(x.python_name.removesuffix('_flags')) + possible_secret_fields.add( + x.python_name.removesuffix('_flags')) + else: + all_fields.add(x.python_name) - return secret_fields + return all_fields.intersection(possible_secret_fields) def extract_docbook_paragraphs(docbook_node: Element) -> List[str]: @@ -307,6 +312,7 @@ def main( ) -> None: jinja_env = Environment( loader=FileSystemLoader(Path('./tools/jinja_templates/')), + undefined=StrictUndefined, ) settings_template = jinja_env.get_template('setting.py.jinja2') From 59c8a396047c170dcb0c43ed09bfa668cea7749d Mon Sep 17 00:00:00 2001 From: igo95862 Date: Wed, 21 Dec 2022 21:24:39 +0300 Subject: [PATCH 50/80] Improved secret field detection by using description Now checks for "Flags indicating" at the begining of description. --- sdbus_async/networkmanager/settings/dcb.py | 4 +--- sdbus_async/networkmanager/settings/ipv4.py | 4 +--- sdbus_async/networkmanager/settings/ipv6.py | 4 +--- tools/generate-settings-dataclasses-jinja.py | 4 +++- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sdbus_async/networkmanager/settings/dcb.py b/sdbus_async/networkmanager/settings/dcb.py index 94d15fc..609d6a8 100644 --- a/sdbus_async/networkmanager/settings/dcb.py +++ b/sdbus_async/networkmanager/settings/dcb.py @@ -3,15 +3,13 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import List, Optional from .base import NetworkManagerSettingsMixin @dataclass class DcbSettings(NetworkManagerSettingsMixin): """Data Center Bridging Settings""" - secret_fields_names: ClassVar[List[str]] = ['priority_flow_control'] - secret_name = 'dcb' app_fcoe_flags: Optional[int] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv4.py b/sdbus_async/networkmanager/settings/ipv4.py index d80a8a6..b2b91f2 100644 --- a/sdbus_async/networkmanager/settings/ipv4.py +++ b/sdbus_async/networkmanager/settings/ipv4.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, ClassVar, List, Optional, Tuple +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import AddressData, RouteData, RoutingRules @@ -11,8 +11,6 @@ @dataclass class Ipv4Settings(NetworkManagerSettingsMixin): """IPv4 Settings""" - secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] - secret_name = 'ipv4' address_data: Optional[List[AddressData]] = field( metadata={ diff --git a/sdbus_async/networkmanager/settings/ipv6.py b/sdbus_async/networkmanager/settings/ipv6.py index 7c2558c..7f69c51 100644 --- a/sdbus_async/networkmanager/settings/ipv6.py +++ b/sdbus_async/networkmanager/settings/ipv6.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, ClassVar, List, Optional, Tuple +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import AddressData, RouteData, RoutingRules @@ -11,8 +11,6 @@ @dataclass class Ipv6Settings(NetworkManagerSettingsMixin): """IPv6 Settings""" - secret_fields_names: ClassVar[List[str]] = ['dhcp_hostname'] - secret_name = 'ipv6' addr_gen_mode: Optional[int] = field( metadata={ diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index f804ebc..e995a30 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -204,7 +204,9 @@ def secret_fields(self) -> Set[str]: for x in self.properties: - if x.python_name.endswith('_flags') and x.python_type == 'int': + if (x.python_name.endswith('_flags') + and x.python_type == 'int' + and x.description.startswith('Flags indicating')): possible_secret_fields.add( x.python_name.removesuffix('_flags')) else: From dc2f382de258e18f882bb7fb1ead1f14bc25c756 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Wed, 21 Dec 2022 21:41:09 +0300 Subject: [PATCH 51/80] Added `update_secrets_generator` to connection profile Will be used to automatically fetch secrets --- .../networkmanager/settings/profile.py | 29 ++++++++++++++++++- tests/test_settings_profile.py | 16 ++++++++++ tools/jinja_templates/profile.py.jinja2 | 29 ++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index 5c067f4..0049411 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -4,7 +4,7 @@ from __future__ import annotations from dataclasses import dataclass, field, fields -from typing import Any, Dict, Optional +from typing import Any, Dict, Generator, Optional from .base import NetworkManagerSettingsMixin from .adsl import AdslSettings @@ -463,6 +463,33 @@ def update(self, other: ConnectionProfile) -> None: setattr(my_settings, setting_field_name, other_setting) + def update_secrets_generator( + self) -> Generator[str, ConnectionProfile, None]: + for attr_name, value in vars(self).items(): + if value is None: + continue + + if not isinstance(value, NetworkManagerSettingsMixin): + continue + + secret_setting_name = value.secret_name + + if not secret_setting_name: + continue + + secret_profile = yield secret_setting_name + current_setting_secrets = getattr(secret_profile, attr_name) + + for secret_attribute in value.secret_fields_names: + setattr( + value, + secret_attribute, + getattr( + current_setting_secrets, + secret_attribute, + ), + ) + SETTING_DBUS_NAME_TO_NAME: Dict[str, str] = { f.metadata['dbus_name']: f.name diff --git a/tests/test_settings_profile.py b/tests/test_settings_profile.py index d39a85c..8ee6c98 100644 --- a/tests/test_settings_profile.py +++ b/tests/test_settings_profile.py @@ -62,3 +62,19 @@ def test_update(self) -> None: connection.update(secrets) self.assertEqual(connection.wireguard.private_key, 'secret_key') + + def test_update_secrets(self) -> None: + connection = ConnectionProfile.from_settings_dict(connection_dict) + secrets = ConnectionProfile.from_settings_dict(secret_dict) + + connection_secret_update_generator = ( + connection.update_secrets_generator() + ) + + setting_name = next(connection_secret_update_generator) + self.assertEqual(setting_name, 'wireguard') + + with self.assertRaises(StopIteration): + connection_secret_update_generator.send(secrets) + + self.assertEqual(connection.wireguard.private_key, 'secret_key') diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 index 17811a2..6927b2c 100644 --- a/tools/jinja_templates/profile.py.jinja2 +++ b/tools/jinja_templates/profile.py.jinja2 @@ -4,7 +4,7 @@ from __future__ import annotations from dataclasses import dataclass, field, fields -from typing import Any, Dict, Optional +from typing import Any, Dict, Generator, Optional from .base import NetworkManagerSettingsMixin {% for setting in all_settings -%} @@ -165,6 +165,33 @@ class ConnectionProfile: setattr(my_settings, setting_field_name, other_setting) + def update_secrets_generator( + self) -> Generator[str, ConnectionProfile, None]: + for attr_name, value in vars(self).items(): + if value is None: + continue + + if not isinstance(value, NetworkManagerSettingsMixin): + continue + + secret_setting_name = value.secret_name + + if not secret_setting_name: + continue + + secret_profile = yield secret_setting_name + current_setting_secrets = getattr(secret_profile, attr_name) + + for secret_attribute in value.secret_fields_names: + setattr( + value, + secret_attribute, + getattr( + current_setting_secrets, + secret_attribute, + ), + ) + SETTING_DBUS_NAME_TO_NAME: Dict[str, str] = { f.metadata['dbus_name']: f.name From caec60d05d531dae1dd8e615f5b874f953255ab4 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Wed, 21 Dec 2022 22:05:22 +0300 Subject: [PATCH 52/80] Removed unnecessary ClassVar typing for settings --- sdbus_async/networkmanager/settings/adsl.py | 4 ++-- sdbus_async/networkmanager/settings/cdma.py | 4 ++-- sdbus_async/networkmanager/settings/eapol.py | 4 ++-- sdbus_async/networkmanager/settings/gsm.py | 4 ++-- sdbus_async/networkmanager/settings/macsec.py | 4 ++-- sdbus_async/networkmanager/settings/pppoe.py | 4 ++-- sdbus_async/networkmanager/settings/wireguard.py | 4 ++-- sdbus_async/networkmanager/settings/wireless_security.py | 4 ++-- tools/generate-settings-dataclasses-jinja.py | 4 ---- tools/jinja_templates/setting.py.jinja2 | 2 +- 10 files changed, 17 insertions(+), 21 deletions(-) diff --git a/sdbus_async/networkmanager/settings/adsl.py b/sdbus_async/networkmanager/settings/adsl.py index 9893def..5306e03 100644 --- a/sdbus_async/networkmanager/settings/adsl.py +++ b/sdbus_async/networkmanager/settings/adsl.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import Optional from .base import NetworkManagerSettingsMixin @dataclass class AdslSettings(NetworkManagerSettingsMixin): """ADSL Settings""" - secret_fields_names: ClassVar[List[str]] = ['password'] + secret_fields_names = ['password'] secret_name = 'adsl' encapsulation: Optional[str] = field( diff --git a/sdbus_async/networkmanager/settings/cdma.py b/sdbus_async/networkmanager/settings/cdma.py index 4eea623..70c1d28 100644 --- a/sdbus_async/networkmanager/settings/cdma.py +++ b/sdbus_async/networkmanager/settings/cdma.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import Optional from .base import NetworkManagerSettingsMixin @dataclass class CdmaSettings(NetworkManagerSettingsMixin): """CDMA-based Mobile Broadband Settings""" - secret_fields_names: ClassVar[List[str]] = ['password'] + secret_fields_names = ['password'] secret_name = 'cdma' mtu: Optional[int] = field( diff --git a/sdbus_async/networkmanager/settings/eapol.py b/sdbus_async/networkmanager/settings/eapol.py index 02bc3b4..74eb852 100644 --- a/sdbus_async/networkmanager/settings/eapol.py +++ b/sdbus_async/networkmanager/settings/eapol.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import List, Optional from .base import NetworkManagerSettingsMixin @dataclass class EapolSettings(NetworkManagerSettingsMixin): """IEEE 802.1x Authentication Settings""" - secret_fields_names: ClassVar[List[str]] = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] + secret_fields_names = ['ca_cert_password', 'client_cert_password', 'password', 'password_raw', 'phase2_ca_cert_password', 'phase2_client_cert_password', 'phase2_private_key_password', 'pin', 'private_key_password'] secret_name = '802-1x' altsubject_matches: Optional[List[str]] = field( diff --git a/sdbus_async/networkmanager/settings/gsm.py b/sdbus_async/networkmanager/settings/gsm.py index bdd4714..4926d3a 100644 --- a/sdbus_async/networkmanager/settings/gsm.py +++ b/sdbus_async/networkmanager/settings/gsm.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import Optional from .base import NetworkManagerSettingsMixin @dataclass class GsmSettings(NetworkManagerSettingsMixin): """GSM-based Mobile Broadband Settings""" - secret_fields_names: ClassVar[List[str]] = ['password', 'pin'] + secret_fields_names = ['password', 'pin'] secret_name = 'gsm' apn: Optional[str] = field( diff --git a/sdbus_async/networkmanager/settings/macsec.py b/sdbus_async/networkmanager/settings/macsec.py index f997aef..f0dad7c 100644 --- a/sdbus_async/networkmanager/settings/macsec.py +++ b/sdbus_async/networkmanager/settings/macsec.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import Optional from .base import NetworkManagerSettingsMixin @dataclass class MacsecSettings(NetworkManagerSettingsMixin): """MACSec Settings""" - secret_fields_names: ClassVar[List[str]] = ['mka_cak'] + secret_fields_names = ['mka_cak'] secret_name = 'macsec' encrypt: Optional[bool] = field( diff --git a/sdbus_async/networkmanager/settings/pppoe.py b/sdbus_async/networkmanager/settings/pppoe.py index 8a420aa..826b7a9 100644 --- a/sdbus_async/networkmanager/settings/pppoe.py +++ b/sdbus_async/networkmanager/settings/pppoe.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import Optional from .base import NetworkManagerSettingsMixin @dataclass class PppoeSettings(NetworkManagerSettingsMixin): """PPP-over-Ethernet Settings""" - secret_fields_names: ClassVar[List[str]] = ['password'] + secret_fields_names = ['password'] secret_name = 'pppoe' parent: Optional[str] = field( diff --git a/sdbus_async/networkmanager/settings/wireguard.py b/sdbus_async/networkmanager/settings/wireguard.py index e77526e..e1f4c32 100644 --- a/sdbus_async/networkmanager/settings/wireguard.py +++ b/sdbus_async/networkmanager/settings/wireguard.py @@ -3,7 +3,7 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, ClassVar, List, Optional, Tuple +from typing import Any, List, Optional, Tuple from .base import NetworkManagerSettingsMixin from .datatypes import WireguardPeers @@ -11,7 +11,7 @@ @dataclass class WireguardSettings(NetworkManagerSettingsMixin): """WireGuard Settings""" - secret_fields_names: ClassVar[List[str]] = ['private_key'] + secret_fields_names = ['private_key'] secret_name = 'wireguard' fwmark: Optional[int] = field( diff --git a/sdbus_async/networkmanager/settings/wireless_security.py b/sdbus_async/networkmanager/settings/wireless_security.py index 8adc810..2c1dda1 100644 --- a/sdbus_async/networkmanager/settings/wireless_security.py +++ b/sdbus_async/networkmanager/settings/wireless_security.py @@ -3,14 +3,14 @@ # if possible, please make changes by also updating the script. from __future__ import annotations from dataclasses import dataclass, field -from typing import ClassVar, List, Optional +from typing import List, Optional from .base import NetworkManagerSettingsMixin @dataclass class WirelessSecuritySettings(NetworkManagerSettingsMixin): """Wi-Fi Security Settings""" - secret_fields_names: ClassVar[List[str]] = ['leap_password', 'psk'] + secret_fields_names = ['leap_password', 'psk'] secret_name = '802-11-wireless-security' auth_alg: Optional[str] = field( diff --git a/tools/generate-settings-dataclasses-jinja.py b/tools/generate-settings-dataclasses-jinja.py index e995a30..09eca55 100644 --- a/tools/generate-settings-dataclasses-jinja.py +++ b/tools/generate-settings-dataclasses-jinja.py @@ -153,10 +153,6 @@ def __init__(self, name: str, description: str, name_upper: str, def typing_imports(self) -> Set[str]: typing_imports: Set[str] = self.properties_want_imports.copy() - if self.secret_fields: - typing_imports.add('ClassVar') - typing_imports.add('List') - return typing_imports @cached_property diff --git a/tools/jinja_templates/setting.py.jinja2 b/tools/jinja_templates/setting.py.jinja2 index dcdcb69..ec9a4f2 100644 --- a/tools/jinja_templates/setting.py.jinja2 +++ b/tools/jinja_templates/setting.py.jinja2 @@ -13,7 +13,7 @@ from .datatypes import {{ setting.datatypes_imports|sort|join(', ') }} class {{ setting.python_class_name }}(NetworkManagerSettingsMixin): """{{ setting.description }}""" {%- if setting.secret_fields %} - secret_fields_names: ClassVar[List[str]] = ['{{ setting.secret_fields|sort|join("', '") }}'] + secret_fields_names = ['{{ setting.secret_fields|sort|join("', '") }}'] secret_name = '{{ setting.name }}' {%- endif %} {% for property in setting.properties %} From 955190d2b713095b59847ad54dd9ca363b18c8a1 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 24 Dec 2022 20:58:04 +0300 Subject: [PATCH 53/80] Added `get_profile` and `update_profile` to Connection interface `get_profile` returns the profile object and can fetch secrets. `update_profile` updates connection using the profile object --- sdbus_async/networkmanager/__init__.py | 1 - .../networkmanager/interfaces_other.py | 46 +++++++++++++++++++ .../networkmanager/interfaces_other.py | 45 ++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/sdbus_async/networkmanager/__init__.py b/sdbus_async/networkmanager/__init__.py index e49e0e7..1107e8e 100644 --- a/sdbus_async/networkmanager/__init__.py +++ b/sdbus_async/networkmanager/__init__.py @@ -194,7 +194,6 @@ NetworkManagerSettings, WiFiP2PPeer, ) - from .types import ( NetworkManagerConnectionProperties, NetworkManagerSetting, diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index 8e93866..c555414 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -28,6 +28,7 @@ dbus_signal_async, ) +from .settings import ConnectionProfile from .types import NetworkManagerConnectionProperties @@ -613,6 +614,51 @@ def removed(self) -> None: """Signal when connection is removed""" raise NotImplementedError + async def update_profile(self, + profile: ConnectionProfile, + save_to_disk: bool = True) -> None: + """Update connection using the profile dataclass. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param bool save_to_disk: Make changes permanent by saving + updated values to disk. + + By default changes are temporary. (saved only to RAM) + """ + flags = 0 + + if save_to_disk: + flags |= 0x1 + else: + flags |= 0x2 + + await self.update2(profile.to_dbus(), flags, {}) + + async def get_profile(self, + fetch_secrets: bool = True) -> ConnectionProfile: + """Get the connection settings as the profile object. + + :param bool fetch_secrets: Retrieve secret values. (like VPN passwords) + Makes additional calls to NetworkManager. + """ + profile = ConnectionProfile.from_dbus(await self.get_settings()) + + if fetch_secrets: + secrets_name_generator = profile.update_secrets_generator() + try: + secrets_name = next(secrets_name_generator) + while True: + secret_profile = ConnectionProfile.from_dbus( + await self.get_secrets(secrets_name)) + + secrets_name = secrets_name_generator.send(secret_profile) + except StopIteration: + ... + + return profile + class NetworkManagerSettingsInterfaceAsync( DbusInterfaceCommonAsync, diff --git a/sdbus_block/networkmanager/interfaces_other.py b/sdbus_block/networkmanager/interfaces_other.py index 9089c10..ef5e580 100644 --- a/sdbus_block/networkmanager/interfaces_other.py +++ b/sdbus_block/networkmanager/interfaces_other.py @@ -23,6 +23,7 @@ from sdbus import DbusInterfaceCommon, dbus_method, dbus_property +from .settings import ConnectionProfile from .types import NetworkManagerConnectionProperties @@ -581,6 +582,50 @@ def filename(self) -> str: """File that stores connection settings""" raise NotImplementedError + def update_profile(self, + profile: ConnectionProfile, + save_to_disk: bool = True) -> None: + """Update connection using the profile dataclass. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param bool save_to_disk: Make changes permanent by saving + updated values to disk. + + By default changes are temporary. (saved only to RAM) + """ + flags = 0 + + if save_to_disk: + flags |= 0x1 + else: + flags |= 0x2 + + self.update2(profile.to_dbus(), flags, {}) + + def get_profile(self, fetch_secrets: bool = True) -> ConnectionProfile: + """Get the connection settings as the profile object. + + :param bool fetch_secrets: Retrieve secret values. (like VPN passwords) + Makes additional calls to NetworkManager. + """ + profile = ConnectionProfile.from_dbus(self.get_settings()) + + if fetch_secrets: + secrets_name_generator = profile.update_secrets_generator() + try: + secrets_name = next(secrets_name_generator) + while True: + secret_profile = ConnectionProfile.from_dbus( + self.get_secrets(secrets_name)) + + secrets_name = secrets_name_generator.send(secret_profile) + except StopIteration: + ... + + return profile + class NetworkManagerSettingsInterface( DbusInterfaceCommon, From f22b5c3fc49a4c36c74d07401bce30df9e05b349 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 13:20:01 +0300 Subject: [PATCH 54/80] Added `add_connection_profile` to networkmanager settings Adds the connection using the profile object. --- .../networkmanager/interfaces_other.py | 30 +++++++++++++++++++ .../networkmanager/interfaces_other.py | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index c555414..4f2be61 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -779,6 +779,36 @@ def connection_removed(self) -> str: """Signal when connection was removed with the path""" raise NotImplementedError + async def add_connection_profile( + self, + profile: ConnectionProfile, + save_to_disk: bool = False, + ) -> Tuple[str, None]: + """Add new connection using the profile object. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param bool save_to_disk: Make changes permanent by saving + updated values to disk. + + By default changes are temporary. (saved only to RAM) + + :return: Object path of new connection and None + :rtype: Tuple[str, None] + """ + flags = 0 + + if save_to_disk: + flags |= 0x1 + else: + flags |= 0x2 + + return ( + (await self.add_connection2(profile.to_dbus(), flags, {}))[0], + None, + ) + class NetworkManagerVPNPluginInterfaceAsync( DbusInterfaceCommonAsync, diff --git a/sdbus_block/networkmanager/interfaces_other.py b/sdbus_block/networkmanager/interfaces_other.py index ef5e580..7186252 100644 --- a/sdbus_block/networkmanager/interfaces_other.py +++ b/sdbus_block/networkmanager/interfaces_other.py @@ -736,6 +736,36 @@ def can_modify(self) -> bool: """If true adding and modifying connections is supported""" raise NotImplementedError + def add_connection_profile( + self, + profile: ConnectionProfile, + save_to_disk: bool = False, + ) -> Tuple[str, None]: + """Add new connection using the profile object. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param bool save_to_disk: Make changes permanent by saving + updated values to disk. + + By default changes are temporary. (saved only to RAM) + + :return: Object path of new connection and None + :rtype: Tuple[str, None] + """ + flags = 0 + + if save_to_disk: + flags |= 0x1 + else: + flags |= 0x2 + + return ( + (self.add_connection2(profile.to_dbus(), flags, {}))[0], + None, + ) + class NetworkManagerVPNPluginInterface( DbusInterfaceCommon, From 1608d62a9e887eae898a307569ecb62edafc37b9 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 13:23:56 +0300 Subject: [PATCH 55/80] Fix saving to RAM not being default for `update_profile` --- sdbus_async/networkmanager/interfaces_other.py | 8 +++++--- sdbus_block/networkmanager/interfaces_other.py | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index 4f2be61..9c1ed37 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -614,9 +614,11 @@ def removed(self) -> None: """Signal when connection is removed""" raise NotImplementedError - async def update_profile(self, - profile: ConnectionProfile, - save_to_disk: bool = True) -> None: + async def update_profile( + self, + profile: ConnectionProfile, + save_to_disk: bool = False, + ) -> None: """Update connection using the profile dataclass. :param ConnectionProfile profile: Connection profile to update diff --git a/sdbus_block/networkmanager/interfaces_other.py b/sdbus_block/networkmanager/interfaces_other.py index 7186252..718f3a2 100644 --- a/sdbus_block/networkmanager/interfaces_other.py +++ b/sdbus_block/networkmanager/interfaces_other.py @@ -582,9 +582,11 @@ def filename(self) -> str: """File that stores connection settings""" raise NotImplementedError - def update_profile(self, - profile: ConnectionProfile, - save_to_disk: bool = True) -> None: + def update_profile( + self, + profile: ConnectionProfile, + save_to_disk: bool = False, + ) -> None: """Update connection using the profile dataclass. :param ConnectionProfile profile: Connection profile to update From 4bc4bff41f102ab2004239cb6aaba4df7eb3bb19 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 13:35:15 +0300 Subject: [PATCH 56/80] Added `add_and_activate_connection_profile` method Adds and activates the connection using the profile object. --- .../networkmanager/interfaces_other.py | 30 +++++++++++++++++++ .../networkmanager/interfaces_other.py | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index 9c1ed37..2a4c4af 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -1378,3 +1378,33 @@ def device_added(self) -> str: def device_removed(self) -> str: """Signal when device had been removed with path""" raise NotImplementedError + + async def add_and_activate_connection_profile( + self, + profile: ConnectionProfile, + device_path: str = '/', + specific_object: str = '/', + ) -> Tuple[str, str]: + """Adds new connection using the profile object as template. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param str device_path: Object path of device to be activated + using the given connection + + :param str specific_object: The path of a connection-type-specific + object this activation should use. + + This parameter is currently ignored for wired and mobile broadband + connections, and the value of "/" should be used. + + :return: Object path of new connection and path of active connection. + :rtype: Tuple[str, str] + """ + + return await self.add_and_activate_connection( + profile.to_dbus(), + device_path, + specific_object, + ) diff --git a/sdbus_block/networkmanager/interfaces_other.py b/sdbus_block/networkmanager/interfaces_other.py index 718f3a2..a65da27 100644 --- a/sdbus_block/networkmanager/interfaces_other.py +++ b/sdbus_block/networkmanager/interfaces_other.py @@ -1271,3 +1271,33 @@ def connectivity_check_uri(self) -> str: def global_dns_configuration(self) -> Dict[str, Tuple[str, Any]]: """Global DNS connection settings""" raise NotImplementedError + + def add_and_activate_connection_profile( + self, + profile: ConnectionProfile, + device_path: str = '/', + specific_object: str = '/', + ) -> Tuple[str, str]: + """Adds new connection using the profile object as template. + + :param ConnectionProfile profile: Connection profile to update + with. + + :param str device_path: Object path of device to be activated + using the given connection + + :param str specific_object: The path of a connection-type-specific + object this activation should use. + + This parameter is currently ignored for wired and mobile broadband + connections, and the value of "/" should be used. + + :return: Object path of new connection and path of active connection. + :rtype: Tuple[str, str] + """ + + return self.add_and_activate_connection( + profile.to_dbus(), + device_path, + specific_object, + ) From cb3839ac1f199b45b9576e8832e082ca5691c81c Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 14:02:54 +0300 Subject: [PATCH 57/80] Added `get_applied_connection_profile` to device interface Retrieves applied connection as a profile object. --- .../networkmanager/interfaces_devices.py | 21 +++++++++++++++++++ .../networkmanager/interfaces_devices.py | 21 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/sdbus_async/networkmanager/interfaces_devices.py b/sdbus_async/networkmanager/interfaces_devices.py index e8d3924..39995c6 100644 --- a/sdbus_async/networkmanager/interfaces_devices.py +++ b/sdbus_async/networkmanager/interfaces_devices.py @@ -28,6 +28,8 @@ dbus_signal_async, ) +from .settings import ConnectionProfile + class NetworkManagerDeviceBluetoothInterfaceAsync( DbusInterfaceCommonAsync, @@ -1020,6 +1022,25 @@ def state_changed(self) -> Tuple[int, int, int]: """ raise NotImplementedError + async def get_applied_connection_profile( + self + ) -> Tuple[ConnectionProfile, int]: + """Get the currently applied connection on the device. + + .. note:: + + This method cannot fetch secrets. Use + :py:meth:`NetworkManagerSettingsConnectionInterfaceAsync.get_profile` + to acquire profile with secrets. + + :returns: Tuple of profile and version id. + :rtype: Tuple[ConnectionProfile, int] + """ + + connection_vardict, version_id = await self.get_applied_connection(0) + + return ConnectionProfile.from_dbus(connection_vardict), version_id + class NetworkManagerPPPInterfaceAsync( DbusInterfaceCommonAsync, diff --git a/sdbus_block/networkmanager/interfaces_devices.py b/sdbus_block/networkmanager/interfaces_devices.py index 0275bad..570de1f 100644 --- a/sdbus_block/networkmanager/interfaces_devices.py +++ b/sdbus_block/networkmanager/interfaces_devices.py @@ -23,6 +23,8 @@ from sdbus import DbusInterfaceCommon, dbus_method, dbus_property +from .settings import ConnectionProfile + class NetworkManagerDeviceBluetoothInterface( DbusInterfaceCommon, @@ -985,6 +987,25 @@ def hw_address(self) -> str: """Hardware address""" raise NotImplementedError + def get_applied_connection_profile( + self + ) -> Tuple[ConnectionProfile, int]: + """Get the currently applied connection on the device. + + .. note:: + + This method cannot fetch secrets. Use + :py:meth:`NetworkManagerSettingsConnectionInterfaceAsync.get_profile` + to acquire profile with secrets. + + :returns: Tuple of profile and version id. + :rtype: Tuple[ConnectionProfile, int] + """ + + connection_vardict, version_id = self.get_applied_connection(0) + + return ConnectionProfile.from_dbus(connection_vardict), version_id + class NetworkManagerPPPInterface( DbusInterfaceCommon, From b5cc067a4b9b6c4d86720d22e4e81db88b9d1ef6 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 14:13:28 +0300 Subject: [PATCH 58/80] Added `reapply_profile` method to device interface Tries to update device configuration using the profile object. --- sdbus_async/networkmanager/interfaces_devices.py | 16 ++++++++++++++++ sdbus_block/networkmanager/interfaces_devices.py | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/sdbus_async/networkmanager/interfaces_devices.py b/sdbus_async/networkmanager/interfaces_devices.py index 39995c6..cef354c 100644 --- a/sdbus_async/networkmanager/interfaces_devices.py +++ b/sdbus_async/networkmanager/interfaces_devices.py @@ -1041,6 +1041,22 @@ async def get_applied_connection_profile( return ConnectionProfile.from_dbus(connection_vardict), version_id + async def reapply_profile( + self, + profile: ConnectionProfile, + version_id: int = 0, + ) -> None: + """Attempts to update the configuration of a device + without deactivating it. + + :param ConnectionProfile profile: Connection profile to update + with. + :param int version_id: If non-zero, the current version id of + the applied-connection must match. The current version id can be + retrieved via :py:meth:`get_applied_connection_profile`. + """ + await self.reapply(profile.to_dbus(), version_id, 0) + class NetworkManagerPPPInterfaceAsync( DbusInterfaceCommonAsync, diff --git a/sdbus_block/networkmanager/interfaces_devices.py b/sdbus_block/networkmanager/interfaces_devices.py index 570de1f..00aa372 100644 --- a/sdbus_block/networkmanager/interfaces_devices.py +++ b/sdbus_block/networkmanager/interfaces_devices.py @@ -1006,6 +1006,22 @@ def get_applied_connection_profile( return ConnectionProfile.from_dbus(connection_vardict), version_id + def reapply_profile( + self, + profile: ConnectionProfile, + version_id: int = 0, + ) -> None: + """Attempts to update the configuration of a device + without deactivating it. + + :param ConnectionProfile profile: Connection profile to update + with. + :param int version_id: If non-zero, the current version id of + the applied-connection must match. The current version id can be + retrieved via :py:meth:`get_applied_connection_profile`. + """ + self.reapply(profile.to_dbus(), version_id, 0) + class NetworkManagerPPPInterface( DbusInterfaceCommon, From 00468963e91acd08150c73e64793e91e26888186 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 26 Dec 2022 14:18:09 +0300 Subject: [PATCH 59/80] Version 2.0rc1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 48100e1..4ad40d0 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ description=('NetworkManager binds for sdbus.'), long_description=long_description, long_description_content_type='text/markdown', - version='1.2.0', + version='2.0rc1', url='https://github.com/igo95862/python-sdbus', author='igo95862', author_email='igo95862@yandex.ru', From 457949f745db8a45f81ac9e9970e45905c416bdc Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 4 Feb 2023 15:11:39 +0600 Subject: [PATCH 60/80] settings: Skip unknown fields when converting from D-Bus This allows forwards and backwards compatibility. --- sdbus_async/networkmanager/settings/base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sdbus_async/networkmanager/settings/base.py b/sdbus_async/networkmanager/settings/base.py index 80a3262..cc423c7 100644 --- a/sdbus_async/networkmanager/settings/base.py +++ b/sdbus_async/networkmanager/settings/base.py @@ -82,10 +82,15 @@ def from_dbus( ) -> NetworkManagerSettingsMixin: """TODO: Add proper docstring""" reverse_mapping = cls.setting_name_reverse_mapping() - unvarianted_options = { - reverse_mapping[k]: cls._unpack_variant(k, *v) - for k, v in dbus_dict.items() - } + unvarianted_options = {} + for k, v in dbus_dict.items(): + try: + reverse_name = reverse_mapping[k] + except KeyError: + continue + + unvarianted_options[reverse_name] = cls._unpack_variant(k, *v) + return cls(**unvarianted_options) @classmethod From 21fd2940e68e5990f655c8531c7ebbbfb4769cc6 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 23 Apr 2023 20:33:11 +0600 Subject: [PATCH 61/80] Version 2.0rc2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4ad40d0..1b5f520 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ description=('NetworkManager binds for sdbus.'), long_description=long_description, long_description_content_type='text/markdown', - version='2.0rc1', + version='2.0rc2', url='https://github.com/igo95862/python-sdbus', author='igo95862', author_email='igo95862@yandex.ru', From 85d42bcee38a759d7f6ed6bed791ce344b50de70 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 20:52:48 +0600 Subject: [PATCH 62/80] Remove `connection_profile` as it is replaced with `get_profile` `connection_profile` was added early in to the development of settings dataclasses. However, it was incorrectly added to the object class rather than interface. `get_profile` is equivalent and can fetch secrets. No reason to keep duplicated functionality in before it is released to stable version. --- examples/async/list-connections-async.py | 2 +- examples/async/netdevinfo-async.py | 2 +- examples/async/update-connection-async.py | 6 +++--- examples/block/list-connections.py | 4 ++-- examples/block/netdevinfo.py | 2 +- sdbus_async/networkmanager/objects.py | 8 -------- sdbus_block/networkmanager/objects.py | 8 -------- 7 files changed, 8 insertions(+), 24 deletions(-) diff --git a/examples/async/list-connections-async.py b/examples/async/list-connections-async.py index 4b8bfb9..cd39131 100755 --- a/examples/async/list-connections-async.py +++ b/examples/async/list-connections-async.py @@ -36,7 +36,7 @@ async def list_connection_profiles_async() -> None: async def print_connection_profile(connection_path: str) -> None: connectionsettings_service = NetworkConnectionSettings(connection_path) - profile = await connectionsettings_service.connection_profile() + profile = await connectionsettings_service.get_profile() connection = profile.connection print("-------------------------------------------------------------") print("name:", connection.connection_id) diff --git a/examples/async/netdevinfo-async.py b/examples/async/netdevinfo-async.py index c2d4870..f1a1cfe 100755 --- a/examples/async/netdevinfo-async.py +++ b/examples/async/netdevinfo-async.py @@ -43,7 +43,7 @@ async def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[ conns = {} for connection_path in connection_paths: connection_manager = NetworkConnectionSettings(connection_path) - connection = (await connection_manager.connection_profile()).connection + connection = (await connection_manager.get_profile()).connection # Filter connection profiles matching the connection type for the device: if connection.connection_type != getattr(ConnectionType, dev_type): continue diff --git a/examples/async/update-connection-async.py b/examples/async/update-connection-async.py index 48e50e5..192468b 100755 --- a/examples/async/update-connection-async.py +++ b/examples/async/update-connection-async.py @@ -3,7 +3,7 @@ # # Update a property of a connection profile, looked up by connection id # -# This version uses connection_manager.connection_profile().to_settings_dict() +# This version uses connection_manager.get_profile().to_settings_dict() # to retrieve the connection profile from NetworkManager as a settings dict. # # It then updates it dynamically using the given arguments: @@ -34,9 +34,9 @@ async def update_connection_async(args: Dict[str, Any]) -> None: print(f"No connection {id}, create with add-wifi-psk-connection-async") return - # Get the profile settings of the first connecttion with given id + # Get the profile settings of the first connection with given id connection_manager = NetworkConnectionSettings(connection_paths[0]) - existing_connection_profile = await connection_manager.connection_profile() + existing_connection_profile = await connection_manager.get_profile() settings = existing_connection_profile.to_settings_dict() # Update the given setting's property using the given value diff --git a/examples/block/list-connections.py b/examples/block/list-connections.py index ea8954a..f8d262a 100755 --- a/examples/block/list-connections.py +++ b/examples/block/list-connections.py @@ -31,8 +31,8 @@ def list_connection_profiles_blocking() -> None: def print_connection_profile_blocking(connection_path: str) -> None: - """Show the use of NetworkConnectionSettings(path).connection_profile()""" - profile = NetworkConnectionSettings(connection_path).connection_profile() + """Show the use of NetworkConnectionSettings(path).get_profile()""" + profile = NetworkConnectionSettings(connection_path).get_profile() print("-------------------------------------------------------------") print("name:", profile.connection.connection_id) print("uuid:", profile.connection.uuid) diff --git a/examples/block/netdevinfo.py b/examples/block/netdevinfo.py index 1f03161..1dec341 100755 --- a/examples/block/netdevinfo.py +++ b/examples/block/netdevinfo.py @@ -42,7 +42,7 @@ def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[str]: conns = {} for connection_path in connection_paths: connection_manager = NetworkConnectionSettings(connection_path) - connection = connection_manager.connection_profile().connection + connection = connection_manager.get_profile().connection # Filter connection profiles matching the connection type for the device: if connection.connection_type != getattr(ConnectionType, dev_type): continue diff --git a/sdbus_async/networkmanager/objects.py b/sdbus_async/networkmanager/objects.py index f643b38..8417d3c 100644 --- a/sdbus_async/networkmanager/objects.py +++ b/sdbus_async/networkmanager/objects.py @@ -67,7 +67,6 @@ NetworkManagerVPNConnectionInterfaceAsync, NetworkManagerWifiP2PPeerInterfaceAsync, ) -from .settings.profile import ConnectionProfile from .types import NetworkManagerConnectionProperties NETWORK_MANAGER_SERVICE_NAME = 'org.freedesktop.NetworkManager' @@ -224,13 +223,6 @@ def __init__(self, settings_path: str, settings_path, bus) - async def connection_profile(self) -> ConnectionProfile: - """Return a ConnectionProfile object containing all profile settings - - :return: Nested dataclass containing all settings of the profile - """ - return ConnectionProfile.from_dbus(await self.get_settings()) - class NetworkDeviceGeneric( NetworkManagerDeviceInterfaceAsync, diff --git a/sdbus_block/networkmanager/objects.py b/sdbus_block/networkmanager/objects.py index 48aa0bd..44bbb95 100644 --- a/sdbus_block/networkmanager/objects.py +++ b/sdbus_block/networkmanager/objects.py @@ -67,7 +67,6 @@ NetworkManagerVPNConnectionInterface, NetworkManagerWifiP2PPeerInterface, ) -from .settings.profile import ConnectionProfile from .types import NetworkManagerConnectionProperties NETWORK_MANAGER_SERVICE_NAME = 'org.freedesktop.NetworkManager' @@ -213,13 +212,6 @@ def __init__(self, settings_path: str, settings_path, bus) - def connection_profile(self) -> ConnectionProfile: - """Return a ConnectionProfile object containing all profile settings - - :return: Nested dataclass containing all settings of the profile - """ - return ConnectionProfile.from_dbus(self.get_settings()) - class NetworkDeviceGeneric( NetworkManagerDeviceInterface, From b49d9f3346fe910d7b753fb8b8556bffe5e9d20c Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 21:00:43 +0600 Subject: [PATCH 63/80] Make settings dataclasses resilient towards new settings being added Turns out during version 2.0 development new `loopback` settings were added. Since we want to be compatible with many versions of NetworkManager it is good to be able to handle new settings types being added that have not yet been added to binds. --- sdbus_async/networkmanager/settings/profile.py | 17 ++++++++++------- tools/jinja_templates/profile.py.jinja2 | 17 ++++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index 0049411..8c45106 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -410,13 +410,16 @@ def from_dbus(cls, dbus_dict: NetworkManagerConnectionProperties if group: for key in ("addresses", "routes"): group.pop(key, None) - try: - unvarianted_options: Dict[str, Any] = { - SETTING_DBUS_NAME_TO_NAME[k]: SETTING_TO_CLASS[k].from_dbus(v) - for k, v in dbus_dict.items()} - except KeyError as e: - print(dbus_dict) - raise e + + unvarianted_options: Dict[str, Any] = {} + for k, v in dbus_dict.items(): + try: + unvarianted_options[SETTING_DBUS_NAME_TO_NAME[k]] = ( + SETTING_TO_CLASS[k].from_dbus(v) + ) + except KeyError: + ... + return cls(**unvarianted_options) @classmethod diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 index 6927b2c..fe8e5ac 100644 --- a/tools/jinja_templates/profile.py.jinja2 +++ b/tools/jinja_templates/profile.py.jinja2 @@ -112,13 +112,16 @@ class ConnectionProfile: if group: for key in ("addresses", "routes"): group.pop(key, None) - try: - unvarianted_options: Dict[str, Any] = { - SETTING_DBUS_NAME_TO_NAME[k]: SETTING_TO_CLASS[k].from_dbus(v) - for k, v in dbus_dict.items()} - except KeyError as e: - print(dbus_dict) - raise e + + unvarianted_options: Dict[str, Any] = {} + for k, v in dbus_dict.items(): + try: + unvarianted_options[SETTING_DBUS_NAME_TO_NAME[k]] = ( + SETTING_TO_CLASS[k].from_dbus(v) + ) + except KeyError: + ... + return cls(**unvarianted_options) @classmethod From 798fbb12470fdb5f914966343241fbc21e65a7b4 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 21:16:43 +0600 Subject: [PATCH 64/80] Mark `NetworkManagerSettingsMixin` as dataclass for typing Otherwise type checker complains that you can't pass not dataclass to `fields` function. --- sdbus_async/networkmanager/settings/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdbus_async/networkmanager/settings/base.py b/sdbus_async/networkmanager/settings/base.py index cc423c7..5485f7f 100644 --- a/sdbus_async/networkmanager/settings/base.py +++ b/sdbus_async/networkmanager/settings/base.py @@ -1,13 +1,14 @@ # SPDX-License-Identifier: LGPL-2.1-or-later from __future__ import annotations -from dataclasses import fields +from dataclasses import dataclass, fields from functools import lru_cache from typing import Any, ClassVar, Dict, List, Type, cast from ..types import NetworkManagerSettingsDomain +@dataclass class NetworkManagerSettingsMixin: secret_fields_names: ClassVar[List[str]] = [] secret_name: ClassVar[str] = '' From 27f49ccb1bd9163b1f924a405472801378db18d9 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 21:28:02 +0600 Subject: [PATCH 65/80] Typo fixes --- examples/async/update-connection-async.py | 2 +- sdbus_async/networkmanager/exceptions.py | 2 +- sdbus_async/networkmanager/objects.py | 2 +- sdbus_async/networkmanager/settings/base.py | 2 +- sdbus_async/networkmanager/settings/profile.py | 6 +++--- sdbus_async/networkmanager/types.py | 4 ++-- sdbus_block/networkmanager/objects.py | 2 +- tools/generate-settings-dataclasses.py | 2 +- tools/jinja_templates/profile.py.jinja2 | 6 +++--- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/async/update-connection-async.py b/examples/async/update-connection-async.py index 192468b..d838bda 100755 --- a/examples/async/update-connection-async.py +++ b/examples/async/update-connection-async.py @@ -27,7 +27,7 @@ async def update_connection_async(args: Dict[str, Any]) -> None: """Update the settings for [key][entry] of the 1st matching connection""" - # Get the connection path of the connection(s) with the recieved id + # Get the connection path of the connection(s) with the received id fn = NetworkManagerSettings().get_connections_by_id(args["connection_id"]) connection_paths = await fn if not connection_paths: diff --git a/sdbus_async/networkmanager/exceptions.py b/sdbus_async/networkmanager/exceptions.py index 146c531..7c7ab84 100644 --- a/sdbus_async/networkmanager/exceptions.py +++ b/sdbus_async/networkmanager/exceptions.py @@ -72,7 +72,7 @@ class NmAgentManagerUserCanceledError( ) -# Errors returned by Connetion objects. +# Errors returned by Connection objects. class NmConnectionFailedError( DbusFailedError, NetworkManagerBaseError): """Unknown or unspecified error.""" diff --git a/sdbus_async/networkmanager/objects.py b/sdbus_async/networkmanager/objects.py index 8417d3c..2bad5ae 100644 --- a/sdbus_async/networkmanager/objects.py +++ b/sdbus_async/networkmanager/objects.py @@ -73,7 +73,7 @@ class NetworkManager(NetworkManagerInterfaceAsync): - """Network Manger main object + """Network Manager main object Implements :py:class:`NetworkManagerInterfaceAsync` diff --git a/sdbus_async/networkmanager/settings/base.py b/sdbus_async/networkmanager/settings/base.py index 5485f7f..c41b694 100644 --- a/sdbus_async/networkmanager/settings/base.py +++ b/sdbus_async/networkmanager/settings/base.py @@ -42,7 +42,7 @@ def to_settings_dict(self, defaults: bool = False) -> Dict[str, Any]: The key names provided are exactly as documented in these tables: https://networkmanager.dev/docs/api/latest/nm-settings-dbus.html - Contrary to dataclasses.asdict(), it provides the orignal dbus keys, + Contrary to dataclasses.asdict(), it provides the original dbus keys, e.g. with numerical prefixes like "802-11-", dashes, and "id"/"type". In addition, it can be selected if defaults shall be omitted in output, diff --git a/sdbus_async/networkmanager/settings/profile.py b/sdbus_async/networkmanager/settings/profile.py index 8c45106..d997fa6 100644 --- a/sdbus_async/networkmanager/settings/profile.py +++ b/sdbus_async/networkmanager/settings/profile.py @@ -98,7 +98,7 @@ class ConnectionProfile: """ # The list of the settings classes was generated by # tools/generate-settings-dataclasses-jinja.py which generates the - # settings classes themselfes as well. + # settings classes themselves as well. # If possible, please make changes by also updating the script. # start of the generated list of settings classes @@ -380,13 +380,13 @@ def to_settings_dict(self, defaults: bool = False) -> SettingsDict: """Return a simple dictionary using the same key names like the dbus dict from to_dbus(), but without the dbus signatures returned by it. - Contrary to dataclasses.asdict(), it provides the orignal dbus keys, + Contrary to dataclasses.asdict(), it provides the original dbus keys, e.g. with numerical prefixes like "802-11-", dashes, and "id"/"type". The key names provided are exactly as documented in these tables: https://networkmanager.dev/docs/api/latest/nm-settings-dbus.html - param defaults: Whether properies with default values are returned. + param defaults: Whether properties with default values are returned. """ new_dict = {} for x in fields(self): diff --git a/sdbus_async/networkmanager/types.py b/sdbus_async/networkmanager/types.py index fc9c373..a7bd55e 100644 --- a/sdbus_async/networkmanager/types.py +++ b/sdbus_async/networkmanager/types.py @@ -25,8 +25,8 @@ # A settings domain, e.g. ipv4.*, ipv6.*, 802-11-wireless-security.*, etc: NetworkManagerSettingsDomain = Dict[str, NetworkManagerSetting] -# All settings and properites of a connection, e.g. returned by get_settings() +# All settings and properties of a connection, e.g. returned by get_settings() NetworkManagerConnectionProperties = Dict[str, NetworkManagerSettingsDomain] -# All settings and properites of a connection, but without dbus signatures +# All settings and properties of a connection, but without dbus signatures SettingsDict = Dict[str, Dict[str, Any]] diff --git a/sdbus_block/networkmanager/objects.py b/sdbus_block/networkmanager/objects.py index 44bbb95..6031a62 100644 --- a/sdbus_block/networkmanager/objects.py +++ b/sdbus_block/networkmanager/objects.py @@ -73,7 +73,7 @@ class NetworkManager(NetworkManagerInterface): - """Network Manger main object + """Network Manager main object Implements :py:class:`NetworkManagerInterface` diff --git a/tools/generate-settings-dataclasses.py b/tools/generate-settings-dataclasses.py index 3ccef30..d770f76 100755 --- a/tools/generate-settings-dataclasses.py +++ b/tools/generate-settings-dataclasses.py @@ -170,7 +170,7 @@ def iter_keys_of_dicts( ) -> List[str]: """Return a sorted list of settings_classes or connection properties - To support sorting the required properites of settings_classes first, + To support sorting the required properties of settings_classes first, the settingsname can be passed ad prefix argument to let the key function return the correct sort index for the given settingsname property. """ diff --git a/tools/jinja_templates/profile.py.jinja2 b/tools/jinja_templates/profile.py.jinja2 index fe8e5ac..22b0ddd 100644 --- a/tools/jinja_templates/profile.py.jinja2 +++ b/tools/jinja_templates/profile.py.jinja2 @@ -49,7 +49,7 @@ class ConnectionProfile: """ # The list of the settings classes was generated by # tools/generate-settings-dataclasses-jinja.py which generates the - # settings classes themselfes as well. + # settings classes themselves as well. # If possible, please make changes by also updating the script. # start of the generated list of settings classes @@ -82,13 +82,13 @@ class ConnectionProfile: """Return a simple dictionary using the same key names like the dbus dict from to_dbus(), but without the dbus signatures returned by it. - Contrary to dataclasses.asdict(), it provides the orignal dbus keys, + Contrary to dataclasses.asdict(), it provides the original dbus keys, e.g. with numerical prefixes like "802-11-", dashes, and "id"/"type". The key names provided are exactly as documented in these tables: https://networkmanager.dev/docs/api/latest/nm-settings-dbus.html - param defaults: Whether properies with default values are returned. + param defaults: Whether properties with default values are returned. """ new_dict = {} for x in fields(self): From 9b4904f1ff2e08ab96573dc105126bc9df166c8b Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 21:53:00 +0600 Subject: [PATCH 66/80] Example netdevinfo-async: fix edge case when Wi-Fi is not connected Instead of crashing just print "No active access point". NetworkManager indicates that wireless device not connected by returning "/" path. --- examples/async/netdevinfo-async.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/async/netdevinfo-async.py b/examples/async/netdevinfo-async.py index f1a1cfe..e4ef140 100755 --- a/examples/async/netdevinfo-async.py +++ b/examples/async/netdevinfo-async.py @@ -97,12 +97,16 @@ async def list_networkdevice_details_async() -> None: if dev_type == DeviceType.WIFI.name: wifi = NetworkDeviceWireless(device_path) print("Wifi: ", WiFiOperationMode(await wifi.mode).name.title()) - ap = AccessPoint(await wifi.active_access_point) - ssid: bytes = await ap.ssid - if ssid: - print("SSID: ", ssid.decode("utf-8", "ignore")) - if await ap.strength: - print("Signal: ", await ap.strength) + ap_path = await wifi.active_access_point + if ap_path == "/": + print("No active access point") + else: + ap = AccessPoint(ap_path) + ssid: bytes = await ap.ssid + if ssid: + print("SSID: ", ssid.decode("utf-8", "ignore")) + if await ap.strength: + print("Signal: ", await ap.strength) connection_id = await get_most_recent_connection_id(dev_name, dev_type) if connection_id: print("Profile:", connection_id) From 25d67263e3e7d018b7dc980fef0c62d391fe0815 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 3 Jun 2023 21:57:27 +0600 Subject: [PATCH 67/80] Add loopback device type from NetworkManager 1.42 There is actually no methods or properties that it defines. --- docs/device_interfaces.rst | 3 ++ docs/objects.rst | 3 ++ sdbus_async/networkmanager/__init__.py | 4 +++ sdbus_async/networkmanager/enums.py | 4 +++ .../networkmanager/interfaces_devices.py | 7 +++++ sdbus_async/networkmanager/objects.py | 31 +++++++++++++++++++ sdbus_block/networkmanager/__init__.py | 4 +++ .../networkmanager/interfaces_devices.py | 7 +++++ sdbus_block/networkmanager/objects.py | 29 +++++++++++++++++ 9 files changed, 92 insertions(+) diff --git a/docs/device_interfaces.rst b/docs/device_interfaces.rst index ab5f00f..0078390 100644 --- a/docs/device_interfaces.rst +++ b/docs/device_interfaces.rst @@ -77,3 +77,6 @@ Contains interfaces for most types of devices. .. autoclass:: sdbus_async.networkmanager.NetworkManagerPPPInterfaceAsync :members: + +.. autoclass:: sdbus_async.networkmanager.NetworkManagerLoopbackInterfaceAsync + :members: diff --git a/docs/objects.rst b/docs/objects.rst index 75c6da7..e113adb 100644 --- a/docs/objects.rst +++ b/docs/objects.rst @@ -97,6 +97,9 @@ Device objects .. autoclass:: sdbus_async.networkmanager.NetworkDevicePPP :members: +.. autoclass:: sdbus_async.networkmanager.NetworkDeviceLoopback + :members: + Connection configuration objects -------------------------------- diff --git a/sdbus_async/networkmanager/__init__.py b/sdbus_async/networkmanager/__init__.py index 1107e8e..6f81a22 100644 --- a/sdbus_async/networkmanager/__init__.py +++ b/sdbus_async/networkmanager/__init__.py @@ -136,6 +136,7 @@ NetworkManagerDeviceWiredInterfaceAsync, NetworkManagerDeviceWireGuardInterfaceAsync, NetworkManagerDeviceWirelessInterfaceAsync, + NetworkManagerLoopbackInterfaceAsync, NetworkManagerPPPInterfaceAsync, ) from .interfaces_other import ( @@ -171,6 +172,7 @@ NetworkDeviceBridge, NetworkDeviceGeneric, NetworkDeviceIpTunnel, + NetworkDeviceLoopback, NetworkDeviceMacsec, NetworkDeviceMacvlan, NetworkDeviceModem, @@ -330,6 +332,7 @@ 'NetworkManagerDeviceWiredInterfaceAsync', 'NetworkManagerDeviceWireGuardInterfaceAsync', 'NetworkManagerDeviceWirelessInterfaceAsync', + 'NetworkManagerLoopbackInterfaceAsync', 'NetworkManagerPPPInterfaceAsync', # .interfaces_other 'NetworkManagerAccessPointInterfaceAsync', @@ -363,6 +366,7 @@ 'NetworkDeviceBridge', 'NetworkDeviceGeneric', 'NetworkDeviceIpTunnel', + 'NetworkDeviceLoopback', 'NetworkDeviceMacsec', 'NetworkDeviceMacvlan', 'NetworkDeviceModem', diff --git a/sdbus_async/networkmanager/enums.py b/sdbus_async/networkmanager/enums.py index 391d517..e1b09bc 100644 --- a/sdbus_async/networkmanager/enums.py +++ b/sdbus_async/networkmanager/enums.py @@ -529,6 +529,7 @@ class ConnectionType(str, Enum): * WIREGUARD * WIFI * WPAN + * LOOPBACK """ ADSL = "adsl" BLUETOOTH = "bluetooth" @@ -559,6 +560,7 @@ class ConnectionType(str, Enum): WIREGUARD = "wireguard" WIFI = "802-11-wireless" WPAN = "wpan" + LOOPBACK = "loopback" class DeviceType(IntEnum): @@ -596,6 +598,7 @@ class DeviceType(IntEnum): * WIREGUARD * WIFI_P2P * VRF + * LOOPBACK """ UNKNOWN = 0 ETHERNET = 1 @@ -629,6 +632,7 @@ class DeviceType(IntEnum): WIREGUARD = 29 WIFI_P2P = 30 VRF = 31 + LOOPBACK = 32 class DeviceMetered(IntEnum): diff --git a/sdbus_async/networkmanager/interfaces_devices.py b/sdbus_async/networkmanager/interfaces_devices.py index cef354c..a111eea 100644 --- a/sdbus_async/networkmanager/interfaces_devices.py +++ b/sdbus_async/networkmanager/interfaces_devices.py @@ -1112,3 +1112,10 @@ async def set_ifindex( Not documented upstream. """ raise NotImplementedError + + +class NetworkManagerLoopbackInterfaceAsync( + DbusInterfaceCommonAsync, + interface_name='org.freedesktop.NetworkManager.Device.Loopback', +): + ... diff --git a/sdbus_async/networkmanager/objects.py b/sdbus_async/networkmanager/objects.py index 2bad5ae..e03c69a 100644 --- a/sdbus_async/networkmanager/objects.py +++ b/sdbus_async/networkmanager/objects.py @@ -49,6 +49,7 @@ NetworkManagerDeviceWiredInterfaceAsync, NetworkManagerDeviceWireGuardInterfaceAsync, NetworkManagerDeviceWirelessInterfaceAsync, + NetworkManagerLoopbackInterfaceAsync, NetworkManagerPPPInterfaceAsync, ) from .interfaces_other import ( @@ -862,6 +863,36 @@ def __init__(self, device_path: str, bus: Optional[SdBus] = None) -> None: bus) +class NetworkDeviceLoopback( + NetworkManagerDeviceInterfaceAsync, + NetworkManagerDeviceStatisticsInterfaceAsync, + NetworkManagerLoopbackInterfaceAsync, +): + """Loopback device + + Implements :py:class:`NetworkManagerDeviceInterfaceAsync`, \ + :py:class:`NetworkManagerDeviceStatisticsInterfaceAsync` and \ + :py:class:`NetworkManagerLoopbackInterfaceAsync` + """ + + def __init__(self, device_path: str, bus: Optional[SdBus] = None) -> None: + """ + + :param device_path: D-Bus path to device object. \ + Obtained from \ + :py:meth:`NetworkManagerInterface.get_devices` or \ + :py:meth:`NetworkManagerInterface.get_device_by_ip_iface`. + + :param bus: You probably want to set default bus to system bus \ + or pass system bus directly. + """ + super().__init__() + self._connect( + NETWORK_MANAGER_SERVICE_NAME, + device_path, + bus) + + class ActiveConnection(NetworkManagerConnectionActiveInterfaceAsync): """Active connection object diff --git a/sdbus_block/networkmanager/__init__.py b/sdbus_block/networkmanager/__init__.py index 07559b1..dbd8dcf 100644 --- a/sdbus_block/networkmanager/__init__.py +++ b/sdbus_block/networkmanager/__init__.py @@ -136,6 +136,7 @@ NetworkManagerDeviceWiredInterface, NetworkManagerDeviceWireGuardInterface, NetworkManagerDeviceWirelessInterface, + NetworkManagerLoopbackInterface, NetworkManagerPPPInterface, ) from .interfaces_other import ( @@ -171,6 +172,7 @@ NetworkDeviceBridge, NetworkDeviceGeneric, NetworkDeviceIpTunnel, + NetworkDeviceLoopback, NetworkDeviceMacsec, NetworkDeviceMacvlan, NetworkDeviceModem, @@ -330,6 +332,7 @@ 'NetworkManagerDeviceWiredInterface', 'NetworkManagerDeviceWireGuardInterface', 'NetworkManagerDeviceWirelessInterface', + 'NetworkManagerLoopbackInterface', 'NetworkManagerPPPInterface', # .interfaces_other 'NetworkManagerAccessPointInterface', @@ -363,6 +366,7 @@ 'NetworkDeviceBridge', 'NetworkDeviceGeneric', 'NetworkDeviceIpTunnel', + 'NetworkDeviceLoopback', 'NetworkDeviceMacsec', 'NetworkDeviceMacvlan', 'NetworkDeviceModem', diff --git a/sdbus_block/networkmanager/interfaces_devices.py b/sdbus_block/networkmanager/interfaces_devices.py index 00aa372..ea65082 100644 --- a/sdbus_block/networkmanager/interfaces_devices.py +++ b/sdbus_block/networkmanager/interfaces_devices.py @@ -1077,3 +1077,10 @@ def set_ifindex( Not documented upstream. """ raise NotImplementedError + + +class NetworkManagerLoopbackInterface( + DbusInterfaceCommon, + interface_name='org.freedesktop.NetworkManager.Device.Loopback', +): + ... diff --git a/sdbus_block/networkmanager/objects.py b/sdbus_block/networkmanager/objects.py index 6031a62..3d4c68d 100644 --- a/sdbus_block/networkmanager/objects.py +++ b/sdbus_block/networkmanager/objects.py @@ -49,6 +49,7 @@ NetworkManagerDeviceWiredInterface, NetworkManagerDeviceWireGuardInterface, NetworkManagerDeviceWirelessInterface, + NetworkManagerLoopbackInterface, NetworkManagerPPPInterface, ) from .interfaces_other import ( @@ -829,6 +830,34 @@ def __init__(self, device_path: str, bus: Optional[SdBus] = None) -> None: bus) +class NetworkDeviceLoopback( + NetworkManagerDeviceInterface, + NetworkManagerDeviceStatisticsInterface, + NetworkManagerLoopbackInterface): + """Loopback device + + Implements :py:class:`NetworkManagerDeviceInterface`, \ + :py:class:`NetworkManagerDeviceStatisticsInterface` and \ + :py:class:`NetworkManagerLoopbackInterface` + """ + + def __init__(self, device_path: str, bus: Optional[SdBus] = None) -> None: + """ + + :param device_path: D-Bus path to device object. \ + Obtained from \ + :py:meth:`NetworkManagerInterface.get_devices` or \ + :py:meth:`NetworkManagerInterface.get_device_by_ip_iface`. + + :param bus: You probably want to set default bus to system bus \ + or pass system bus directly. + """ + super().__init__( + NETWORK_MANAGER_SERVICE_NAME, + device_path, + bus) + + class ActiveConnection(NetworkManagerConnectionActiveInterface): """Active connection object From 1d511c6d6dbe809deeca0bab5b5e85b6a39b140b Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 4 Jun 2023 16:38:01 +0600 Subject: [PATCH 68/80] Added CHANGELOG with version 2.0.0 changelog --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d507da0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,50 @@ +## 2.0.0 + +### Warning if you used pre-release version + +`connection_profile` of `NetworkConnectionSettings` object has been replaced with +equivalent `get_profile` method which can also fetch the secrets fields. (you can +use `mypy` to check) + +### Breaking changes + +* Renamed certain elements of `ConnectionType` enum to match `DeviceType` enum. + + * `WIRED` -> `ETHERNET` + * `GSM` -> `MODEM` + +### Features + +* Added connection settings dataclasses. + Those dataclasses are found under `networkmanager.settings` sub-package. + They allow for easy and typed reading, modifying and writing connection settings + without dealing with D-Bus variants. + + Thank you @bernhardkaindl for spearheading this feature. + + New methods have been added to existing interfaces that utilize the new dataclasses: + + * `NetworkManagerSettingsConnectionInterface` + + * `get_profile` + * `update_profile` + + * `NetworkManagerSettingsInterface` + + * `add_connection_profile` + + * `NetworkManagerInterfaceAsync` + + * `add_and_activate_connection_profile` + +* Added support for loopback devices from NetworkManager 1.42 + +## 1.1.0 + +### Features + +* Added NetworkManager errors as named exceptions. + +## 1.0.0 + +Initial release. From f1fcc1dbef467e9dc0cbdf25eff51d065020ffcc Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 4 Jun 2023 16:48:06 +0600 Subject: [PATCH 69/80] Version 2.0.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1b5f520..85c82fe 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ description=('NetworkManager binds for sdbus.'), long_description=long_description, long_description_content_type='text/markdown', - version='2.0rc2', + version='2.0.0', url='https://github.com/igo95862/python-sdbus', author='igo95862', author_email='igo95862@yandex.ru', From 76a3c2cc4c7ac07fa220637f89eab2f776daab96 Mon Sep 17 00:00:00 2001 From: andrey-pr Date: Fri, 21 Jul 2023 16:09:39 +0200 Subject: [PATCH 70/80] Added async vpn example (#58) Thank you! --- .../async/add-openvpn-connection-async.py | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100755 examples/async/add-openvpn-connection-async.py diff --git a/examples/async/add-openvpn-connection-async.py b/examples/async/add-openvpn-connection-async.py new file mode 100755 index 0000000..4200ebd --- /dev/null +++ b/examples/async/add-openvpn-connection-async.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new VPN network connection profile. Currently supported only with tls-auth +# +# $ examples/async/add-openvpn-connection-async.py --help +# usage: add-openvpn-connection.py [-h] [-c CONN_ID] [-d DEV] [--remote REMOTE] [--remote-cert-tls] [-a] [--save] +# [--ca, CA_PATH] [--cert, CERT_PATH] [--key, KEY_path] [--ta, TA_PATH] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -f OVPN .ovpn connection file +# -a autoconnect +# --save Save +# --ca Path to CA file +# --cert Path to cert file +# --key Path to key file +# --ta Path to tls-auth file +# +# $ add-vpn-connection.py +# New unsaved connection profile created, show it with: +# nmcli connection show "MyConnectionExample"|grep -v -e -- -e default +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Note: By default, it uses add_connection_unsaved() to add a temporary +# memory-only connection which is not saved to the system-connections folder: +# For reference, see: https://networkmanager.dev/docs/api/latest/spec.html +# -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) + +import asyncio +import functools +import logging +import sdbus +from uuid import uuid4 +from argparse import ArgumentParser +from pprint import pformat +from sdbus_async.networkmanager import ( + NetworkManagerSettings as SettingsManager, + ConnectionType, +) +from sdbus_async.networkmanager.settings import ( + ConnectionProfile, + ConnectionSettings, + Ipv4Settings, + Ipv6Settings, + VpnSettings +) + + +async def add_vpn_connection_async(conn_id: str, + dev: str, + remote: str, + remote_cert_tls: str, + uuid, + auto: bool, + save: bool, + ca: str, + cert: str, + key: str, + ta: str) -> str: + # Add a temporary (not yet saved) network connection profile + # param Namespace args: dev, remote, remote_cert_tls, ca_path, cert_path, key_path, ta_path + # return: dbus connection path of the created connection profile + + info = logging.getLogger().info + + # If we add many connections passing the same id, things get messy. Check: + if await SettingsManager().get_connections_by_id(conn_id): + print(f'Connection "{conn_id}" exists, remove it first') + print(f'Run: nmcli connection delete "{conn_id}"') + return "" + + profile = ConnectionProfile( + connection=ConnectionSettings( + connection_id=conn_id, + uuid=str(uuid), + connection_type=ConnectionType.VPN.value, + autoconnect=bool(auto), + ), + ipv4=Ipv4Settings(method="auto"), + ipv6=Ipv6Settings(method="auto"), + vpn=VpnSettings(data={ + 'ca': ca, + 'cert': cert, + 'cert-pass-flags': '0', + 'connection-type': 'tls', + 'dev': dev, + 'key': key, + 'remote': remote, + 'remote-cert-tls': remote_cert_tls, + 'ta': ta, + 'ta-dir': '1' + }, service_type='org.freedesktop.NetworkManager.openvpn') + ) + + s = SettingsManager() + save = bool(save) + addconnection = s.add_connection if save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(profile.to_dbus()) + created = "created and saved" if save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pformat, sort_dicts=False)(profile.to_settings_dict())) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("--dev", dest="dev", default="tun", help="VPN Dev") + p.add_argument("--remote", dest="remote", default="example.com:443:tcp", help="VPN Remote") + p.add_argument("--remote-cert-tls", dest="remote_cert_tls", default="server", help="VPN Remote cert tls") + p.add_argument("--ca", dest="ca", required=True, help="VPN CA file path") + p.add_argument("--cert", dest="cert", required=True, help="VPN cert file path") + p.add_argument("--key", dest="key", required=True, help="VPN key file path") + p.add_argument("--ta", dest="ta", required=True, help="VPN TA file path") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := asyncio.run(add_vpn_connection_async(**vars(args))): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") From 68485e6e0043cbb4ef75b99aec086d8a0cb44179 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 20 Nov 2023 00:30:48 +0600 Subject: [PATCH 71/80] Update enums in accordance with upstream documentation This begins version 3.0 All enums were revisisted and updated in accordance to NetworkManager documentation. Some enums and their fields were renamed: * `AccessPointCapabilities` -> `WifiAccessPointCapabilities` * `WirelessCapabilities` -> `WifiCapabilities` * `WpaSecurityFlags` -> `WifiAccessPointSecurityFlags` * `P2P_*` -> `PAIR_*` * `BROADCAST_*` -> `GROUP_*` * `AUTH_*` -> `KEY_MGMT_*` * `ConnectionState` -> `ActiveConnectionState` * `ConnectionStateReason` -> `ActiveConnectionStateReason` * `ConnectionFlags` -> `SettingsConnectionFlags` * `ConnectionStateFlags` -> `ActivationStateFlags` * `DeviceCapabilities` -> `DeviceCapabilitiesFlags` * `BluetoothCapabilities` -> `BluetoothCapabilitiesFlags` * `ModemCapabilities` -> `ModemCapabilitiesFlags` * `SecretAgentCapabilities` -> `SecretAgentCapabilitiesFlags` * `VpnState` -> `VpnServiceState` * `VpnFailure` * `LOGIN_FAILURE` -> `LOGIN_FAILED` New enums: * `NetworkManagerCapabilities` * `WimaxNSPNetworkType` * `SecretAgentGetSecretsFlags` * `CheckpointCreateFlags` * `CheckpointRollbackResult` * `SettingsAddConnection2Flags` * `SettingsUpdate2Flags` * `DeviceReapplyFlags` * `NetworkManagerReloadFlags` * `RadioFlags` * `MptcpFlags` * `VpnConnectionState` * `VpnConnectionStateReason` --- CHANGELOG.md | 42 + docs/enums.rst | 83 +- examples/async/device-state-async.py | 6 +- examples/block/device-state.py | 6 +- sdbus_async/networkmanager/__init__.py | 78 +- sdbus_async/networkmanager/enums.py | 1718 +++++++++++------ .../networkmanager/interfaces_devices.py | 46 +- .../networkmanager/interfaces_other.py | 78 +- sdbus_block/networkmanager/__init__.py | 78 +- 9 files changed, 1418 insertions(+), 717 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d507da0..8435887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,45 @@ +## 3.0.0 + +### Breaking changes + +All enums were revisisted and updated in accordance to NetworkManager documentation. + +Some enums and their fields were renamed: + +* `AccessPointCapabilities` -> `WifiAccessPointCapabilities` +* `WirelessCapabilities` -> `WifiCapabilities` +* `WpaSecurityFlags` -> `WifiAccessPointSecurityFlags` + * `P2P_*` -> `PAIR_*` + * `BROADCAST_*` -> `GROUP_*` + * `AUTH_*` -> `KEY_MGMT_*` +* `ConnectionState` -> `ActiveConnectionState` +* `ConnectionStateReason` -> `ActiveConnectionStateReason` +* `ConnectionFlags` -> `SettingsConnectionFlags` +* `ConnectionStateFlags` -> `ActivationStateFlags` +* `DeviceCapabilities` -> `DeviceCapabilitiesFlags` +* `BluetoothCapabilities` -> `BluetoothCapabilitiesFlags` +* `ModemCapabilities` -> `ModemCapabilitiesFlags` +* `SecretAgentCapabilities` -> `SecretAgentCapabilitiesFlags` +* `VpnState` -> `VpnServiceState` +* `VpnFailure` + * `LOGIN_FAILURE` -> `LOGIN_FAILED` + +New enums: + +* `NetworkManagerCapabilities` +* `WimaxNSPNetworkType` +* `SecretAgentGetSecretsFlags` +* `CheckpointCreateFlags` +* `CheckpointRollbackResult` +* `SettingsAddConnection2Flags` +* `SettingsUpdate2Flags` +* `DeviceReapplyFlags` +* `NetworkManagerReloadFlags` +* `RadioFlags` +* `MptcpFlags` +* `VpnConnectionState` +* `VpnConnectionStateReason` + ## 2.0.0 ### Warning if you used pre-release version diff --git a/docs/enums.rst b/docs/enums.rst index 946f685..90a8cc4 100644 --- a/docs/enums.rst +++ b/docs/enums.rst @@ -1,74 +1,43 @@ Enums ================ -.. autoclass:: sdbus_async.networkmanager.AccessPointCapabilities - :members: +Python's Enum quick intro +------------------------- -.. autoclass:: sdbus_async.networkmanager.WpaSecurityFlags - :members: +There are two types of enums. ``IntEnum`` is used for a discrete values +and ``IntFlag`` is used for bit flags. For example, ``DeviceType`` identifies +a single device type as a device cannot be of multiple types. +``WifiCapabilities`` shows a particular Wifi device capabilities which it +can have multiple, for example, supporting both 5GHz and 2.4GHz radio bands. -.. autoclass:: sdbus_async.networkmanager.WiFiOperationMode - :members: +Usually ``IntEnum`` is implied unless the enum's name ends with ``Flag``. -.. autoclass:: sdbus_async.networkmanager.SecretAgentCapabilities - :members: +Example code using enums: -.. autoclass:: sdbus_async.networkmanager.ConnectionState - :members: +.. code-block:: python -.. autoclass:: sdbus_async.networkmanager.ConnectionStateFlags - :members: + from sdbus_async.networkmanager.enums import DeviceType, WifiCapabilities -.. autoclass:: sdbus_async.networkmanager.ConnectionStateReason - :members: + # Get particular device type from an integer + DeviceType(2) == DeviceType.WIFI + # Returns: True -.. autoclass:: sdbus_async.networkmanager.BluetoothCapabilities - :members: + # Check if a specific flag is enabled + WifiCapabilities.FREQ_2GHZ in WifiCapabilities(0x00000400 | 0x00000200) + # Returns: True -.. autoclass:: sdbus_async.networkmanager.IpTunnelMode - :members: + # Iterate over all enabled flags + list(WifiCapabilities(0x00000400 | 0x00000200)) + # Returns: [, ] -.. autoclass:: sdbus_async.networkmanager.ModemCapabilities - :members: +`See Python's standard library documentation for more detailed +tutorial and API reference. `_ -.. autoclass:: sdbus_async.networkmanager.WirelessCapabilities - :members: +NetworkManager's enums +------------------------- -.. autoclass:: sdbus_async.networkmanager.DeviceCapabilities - :members: - -.. autoclass:: sdbus_async.networkmanager.DeviceState - :members: - -.. autoclass:: sdbus_async.networkmanager.DeviceStateReason - :members: - -.. autoclass:: sdbus_async.networkmanager.DeviceType - :members: - -.. autoclass:: sdbus_async.networkmanager.DeviceMetered - :members: - -.. autoclass:: sdbus_async.networkmanager.ConnectivityState - :members: - -.. autoclass:: sdbus_async.networkmanager.DeviceInterfaceFlags - :members: - -.. autoclass:: sdbus_async.networkmanager.ConnectionFlags - :members: - -.. autoclass:: sdbus_async.networkmanager.VpnState - :members: - -.. autoclass:: sdbus_async.networkmanager.VpnFailure - :members: - -.. autoclass:: sdbus_async.networkmanager.NetworkManagerConnectivityState - :members: - -.. autoclass:: sdbus_async.networkmanager.NetworkManagerState - :members: +.. automodule:: sdbus_async.networkmanager.enums + :members: Helper classes ----------------------- diff --git a/examples/async/device-state-async.py b/examples/async/device-state-async.py index d55e36b..558ed3a 100755 --- a/examples/async/device-state-async.py +++ b/examples/async/device-state-async.py @@ -24,7 +24,7 @@ NetworkDeviceGeneric, DeviceState, DeviceType, - DeviceCapabilities as Capabilities, + DeviceCapabilitiesFlags, ActiveConnection, ConnectivityState, ) @@ -46,7 +46,9 @@ async def list_active_hardware_networkdevice_states(only_hw: bool) -> None: generic = NetworkDeviceGeneric(device_path) # Demonstrates an enum to match devices using capabilities: - if only_hw and await generic.capabilities & Capabilities.IS_SOFTWARE: + if only_hw and ( + DeviceCapabilitiesFlags.IS_SOFTWARE + in DeviceCapabilitiesFlags(await generic.capabilities)): continue # Create the strings for the columns using the names of the enums: diff --git a/examples/block/device-state.py b/examples/block/device-state.py index 2070072..138e163 100755 --- a/examples/block/device-state.py +++ b/examples/block/device-state.py @@ -23,7 +23,7 @@ NetworkDeviceGeneric, DeviceState, DeviceType, - DeviceCapabilities as Capabilities, + DeviceCapabilitiesFlags, ActiveConnection, ConnectivityState, ) @@ -45,7 +45,9 @@ def list_active_hardware_networkdevice_states(only_hw: bool) -> None: generic_dev = NetworkDeviceGeneric(device_path) # Demonstrates an enum to match devices using capabilities: - if only_hw and generic_dev.capabilities & Capabilities.IS_SOFTWARE: + if only_hw and ( + DeviceCapabilitiesFlags.IS_SOFTWARE + in DeviceCapabilitiesFlags(generic_dev.capabilities)): continue # Create the strings for the columns using the names of the enums: diff --git a/sdbus_async/networkmanager/__init__.py b/sdbus_async/networkmanager/__init__.py index 6f81a22..81a390c 100644 --- a/sdbus_async/networkmanager/__init__.py +++ b/sdbus_async/networkmanager/__init__.py @@ -20,30 +20,43 @@ from __future__ import annotations from .enums import ( - AccessPointCapabilities, - BluetoothCapabilities, - ConnectionFlags, - ConnectionState, - ConnectionStateFlags, - ConnectionStateReason, + ActivationStateFlags, + ActiveConnectionState, + ActiveConnectionStateReason, + BluetoothCapabilitiesFlags, + CheckpointCreateFlags, + CheckpointRollbackResult, + ConnectionMultiConnect, ConnectionType, ConnectivityState, - DeviceCapabilities, + DeviceCapabilitiesFlags, DeviceInterfaceFlags, DeviceMetered, + DeviceReapplyFlags, DeviceState, DeviceStateReason, DeviceType, IpTunnelMode, - ModemCapabilities, - NetworkManagerConnectivityState, + ModemCapabilitiesFlags, + MptcpFlags, + NetworkManagerCapabilitiesFlags, + NetworkManagerReloadFlags, NetworkManagerState, - SecretAgentCapabilities, + RadioFlags, + SecretAgentCapabilitiesFlags, + SecretAgentGetSecretsFlags, + SettingsAddConnection2Flags, + SettingsConnectionFlags, + SettingsUpdate2Flags, + VpnConnectionState, + VpnConnectionStateReason, VpnFailure, - VpnState, + VpnServiceState, + WifiAccessPointCapabilitiesFlags, + WifiAccessPointSecurityFlags, + WifiCapabilitiesFlags, WiFiOperationMode, - WirelessCapabilities, - WpaSecurityFlags, + WimaxNSPNetworkType, ) from .exceptions import ( NetworkManagerAlreadyAsleepOrAwakeError, @@ -218,30 +231,43 @@ __all__ = ( # .enums - 'AccessPointCapabilities', - 'BluetoothCapabilities', - 'ConnectionFlags', - 'ConnectionState', - 'ConnectionStateFlags', - 'ConnectionStateReason', + 'ActivationStateFlags', + 'ActiveConnectionState', + 'ActiveConnectionStateReason', + 'BluetoothCapabilitiesFlags', + 'CheckpointCreateFlags', + 'CheckpointRollbackResult', + 'ConnectionMultiConnect', 'ConnectionType', 'ConnectivityState', - 'DeviceCapabilities', + 'DeviceCapabilitiesFlags', 'DeviceInterfaceFlags', 'DeviceMetered', + 'DeviceReapplyFlags', 'DeviceState', 'DeviceStateReason', 'DeviceType', 'IpTunnelMode', - 'ModemCapabilities', - 'NetworkManagerConnectivityState', + 'ModemCapabilitiesFlags', + 'MptcpFlags', + 'NetworkManagerCapabilitiesFlags', + 'NetworkManagerReloadFlags', 'NetworkManagerState', - 'SecretAgentCapabilities', + 'RadioFlags', + 'SecretAgentCapabilitiesFlags', + 'SecretAgentGetSecretsFlags', + 'SettingsAddConnection2Flags', + 'SettingsConnectionFlags', + 'SettingsUpdate2Flags', + 'VpnConnectionState', + 'VpnConnectionStateReason', 'VpnFailure', - 'VpnState', + 'VpnServiceState', + 'WifiAccessPointCapabilitiesFlags', + 'WifiAccessPointSecurityFlags', + 'WifiCapabilitiesFlags', 'WiFiOperationMode', - 'WirelessCapabilities', - 'WpaSecurityFlags', + 'WimaxNSPNetworkType', # .exceptions 'NetworkManagerAlreadyAsleepOrAwakeError', 'NetworkManagerAlreadyEnabledOrDisabledError', diff --git a/sdbus_async/networkmanager/enums.py b/sdbus_async/networkmanager/enums.py index e1b09bc..beb1788 100644 --- a/sdbus_async/networkmanager/enums.py +++ b/sdbus_async/networkmanager/enums.py @@ -17,755 +17,1347 @@ # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +"""Enums used by the NetworkManager. + +`Copied from NetworkManager documentation. +`_ +""" from __future__ import annotations from enum import Enum, IntEnum, IntFlag -class AccessPointCapabilities(IntFlag): - """Wi-Fi Access point capabilities +class NetworkManagerCapabilitiesFlags(IntFlag): + """NetworkManager loaded plugins. + + Capabilities are positive numbers. They are part of stable API and + a certain capability number is guaranteed not to change. - Flags: + The range 0x7000 - 0x7FFF of capabilities is guaranteed not to be + used by upstream NetworkManager. It could thus be used for + downstream extensions. - * NONE - * PRIVACY - * WPS - * WPS_BUTTON - * WPS_PIN + Since NetworkManager 1.6. """ - NONE = 0x0 - PRIVACY = 0x1 - WPS = 0x2 - WPS_BUTTON = 0x4 - WPS_PIN = 0x8 - - -class WpaSecurityFlags(IntFlag): - """WPA (WiFi protected Access) encryption and authentication types - - Flags: - - * NONE - * P2P_WEP40 - * P2P_WEP104 - * P2P_TKIP - * P2P_CCMP - * BROADCAST_WEP40 - * BROADCAST_WEP104 - * BROADCAST_TKIP - * BROADCAST_CCMP - * AUTH_PSK - * AUTH_802_1X - * AUTH_SAE - * AUTH_OWE - * AUTH_OWE_TM - * AUTH_EAP_SUITE_B + + TEAM = 0x1 + """Teams can be managed. This means the team device plugin is loaded.""" + OVS = 0x2 + """OpenVSwitch can be managed. This means the OVS device plugin is loaded. + + Since NetworkManager 1.24. """ - NONE = 0x0 - P2P_WEP40 = 0x1 - P2P_WEP104 = 0x2 - P2P_TKIP = 0x4 - P2P_CCMP = 0x8 - BROADCAST_WEP40 = 0x10 - BROADCAST_WEP104 = 0x20 - BROADCAST_TKIP = 0x40 - BROADCAST_CCMP = 0x80 - AUTH_PSK = 0x100 - AUTH_802_1X = 0x200 - AUTH_SAE = 0x400 - AUTH_OWE = 0x800 - AUTH_OWE_TM = 0x1000 - AUTH_EAP_SUITE_B = 0x2000 -class WiFiOperationMode(IntEnum): - """Operation mode of WiFi access point +class NetworkManagerState(IntEnum): + """Indicates the current overall networking state.""" - * UNKNOWN - * ADHOC - * INFRASTRUCTURE - * AP - * MESH - """ UNKNOWN = 0 - ADHOC = 1 - INFRASTRUCTURE = 2 - AP = 3 - MESH = 4 + """Networking state is unknown. + This indicates a daemon error that makes it unable to reasonably assess + the state. In such event the applications are expected to assume Internet + connectivity might be present and not disable controls that require + network access. The graphical shells may hide the network accessibility + indicator altogether since no meaningful status indication can be provided. + """ + ASLEEP = 10 + """Networking is not enabled, the system is being suspended or resumed + from suspend.""" + DISCONNECTED = 20 + """There is no active network connection. -class SecretAgentCapabilities(IntFlag): - """Secret agent capabilities + The graphical shell should indicate no network connectivity and + the applications should not attempt to access the network. + """ + DISCONNECTING = 30 + """Network connections are being cleaned up. - Flags: + The applications should tear down their network sessions. + """ + CONNECTING = 40 + """A network connection is being started. - * NONE - * VPN_HINTS + The graphical shell should indicate the network is being connected + while the applications should still make no attempts to connect + the network. """ - NONE = 0x0 - VPN_HINTS = 0x1 + CONNECTED_LOCAL = 50 + """There is only local IPv4 and/or IPv6 connectivity, but no default route + to access the Internet. + The graphical shell should indicate no network connectivity. + """ + CONNECTED_SITE = 60 + """There is only site-wide IPv4 and/or IPv6 connectivity. -class ConnectionState(IntEnum): - """State of the connection + This means a default route is available, but the Internet + connectivity check (see "Connectivity" property) did not succeed. + The graphical shell should indicate limited network connectivity. + """ + GLOBAL = 70 + """There is global IPv4 and/or IPv6 Internet connectivity. - * UNKNOWN - * ACTIVATING - * ACTIVATED - * DEACTIVATING - * DEACTIVATED + This means the Internet connectivity check succeeded, the graphical shell + should indicate full network connectivity. """ + + +class ConnectivityState(IntEnum): + """System connectivity state.""" + UNKNOWN = 0 - ACTIVATING = 1 - ACTIVATED = 2 - DEACTIVATING = 3 - DEACTIVATED = 4 + """Network connectivity is unknown. + + This means the connectivity checks are disabled (e.g. on server + installations) or has not run yet. The graphical shell should assume + the Internet connection might be available and not present a captive + portal window.""" + NONE = 1 + """The host is not connected to any network. + + There's no active connection that contains a default route to the internet + and thus it makes no sense to even attempt a connectivity check. + The graphical shell should use this state to indicate the network + connection is unavailable.""" + PORTAL = 2 + """The Internet connection is hijacked by a captive portal gateway. + + The graphical shell may open a sandboxed web browser window (because + the captive portals typically attempt a man-in-the-middle attacks against + the https connections) for the purpose of authenticating to a gateway and + retrigger the connectivity check with CheckConnectivity() when the browser + window is dismissed.""" + LIMITED = 3 + """The host is connected to a network, does not appear to be able to reach + the full Internet, but a captive portal has not been detected.""" + FULL = 4 + """The host is connected to a network, and appears to be able to reach the + full Internet.""" + + +class DeviceType(IntEnum): + """Indicate the type of hardware represented by a device object.""" + UNKNOWN = 0 + """Unknown device.""" + ETHERNET = 1 + """A wired ethernet device.""" + WIFI = 2 + """An 802.11 Wi-Fi device.""" + UNUSED1 = 3 + """Not used.""" + UNUSED2 = 4 + """Not used.""" + BLUETOOTH = 5 + """A Bluetooth device supporting PAN or DUN access protocols.""" + OLPC_MESH = 6 + """An OLPC XO mesh networking device.""" + WIMAX = 7 + """An 802.16e Mobile WiMAX broadband device.""" + MODEM = 8 + """A modem supporting analog telephone, CDMA/EVDO, GSM/UMTS, or + LTE network access protocols.""" + INFINIBAND = 9 + """An IP-over-InfiniBand device.""" + BOND = 10 + """A bond master interface.""" + VLAN = 11 + """An 802.1Q VLAN interface.""" + ADSL = 12 + """ADSL modem.""" + BRIDGE = 13 + """A bridge master interface.""" + GENERIC = 14 + """Generic support for unrecognized device types.""" + TEAM = 15 + """A team master interface.""" + TUN = 16 + """A TUN or TAP interface.""" + IP_TUNNEL = 17 + """A IP tunnel interface.""" + MACVLAN = 18 + """A MACVLAN interface.""" + VXLAN = 19 + """A VXLAN interface.""" + VETH = 20 + """A VETH interface.""" + MACSEC = 21 + """A MACsec interface.""" + DUMMY = 22 + """A dummy interface.""" + PPP = 23 + """A PPP interface.""" + OVS_INTERFACE = 24 + """A Open vSwitch interface.""" + OVS_PORT = 25 + """A Open vSwitch port.""" + OVS_BRIDGE = 26 + """A Open vSwitch bridge.""" + WPAN = 27 + """A IEEE 802.15.4 (WPAN) MAC Layer Device.""" + SIXLOWPAN = 28 + """6LoWPAN interfac.e""" + WIREGUARD = 29 + """A WireGuard interface.""" + WIFI_P2P = 30 + """An 802.11 Wi-Fi P2P device. -class ConnectionStateFlags(IntFlag): - """State of connection flags + Since NetworkManager 1.16. + """ + VRF = 31 + """A VRF (Virtual Routing and Forwarding) interface. - Flags: + Since NetworkManager 1.24. + """ + LOOPBACK = 32 + """A loopback interface. - * NONE - * IS_MASTER - * IS_SLAVE - * LAYER2_READY - * IP4_READY - * IP6_READY - * MASTER_HAS_SLAVES - * LIFE_TIME_BOUND_TO_PROFILE_VISIBILITY - * EXTERNAL + Since NetworkManager 1.42. """ - NONE = 0x0 - IS_MASTER = 0x1 - IS_SLAVE = 0x2 - LAYER2_READY = 0x4 - IP4_READY = 0x8 - IP6_READY = 0x10 - MASTER_HAS_SLAVES = 0x20 - LIFE_TIME_BOUND_TO_PROFILE_VISIBILITY = 0x40 - EXTERNAL = 0x80 -class ConnectionStateReason(IntEnum): - """Connection state change reason - - * UNKNOWN - * NONE - * USER_DISCONNECTED - * DEVICE_DISCONNECTED - * SERVICE_STOPPED - * IP_CONFIG_INVALID - * CONNECT_TIMEOUT - * SERVICE_START_TIMEOUT - * SERVICE_START_FAILED - * NO_SECRETS - * LOGIN_FAILED - * CONNECTION_REMOVED - * DEPENDENCY_FAILED - * DEVICE_REALIZE_FAILED - * DEVICE_REMOVED +class DeviceCapabilitiesFlags(IntFlag): + """General device capability flags.""" + + NONE = 0x00000000 + """Device has no special capabilities.""" + SUPPORTED = 0x00000001 + """NetworkManager supports this device.""" + CARRIER_DETECTABLE = 0x00000002 + """This device can indicate carrier status.""" + IS_SOFTWARE = 0x00000004 + """This device is a software device.""" + CAN_SRIOV = 0x00000008 + """This device supports single-root I/O virtualization.""" + + +class WifiCapabilitiesFlags(IntFlag): + """802.11 specific device encryption and authentication flags.""" + + NONE = 0x00000000 + """Device has no encryption/authentication capabilities.""" + CIPHER_WEP40 = 0x00000001 + """Device supports 40/64-bit WEP encryption.""" + CIPHER_WEP104 = 0x00000002 + """Device supports 104/128-bit WEP encryption.""" + CIPHER_TKIP = 0x00000004 + """Device supports TKIP encryption.""" + CIPHER_CCMP = 0x00000008 + """Device supports AES/CCMP encryption.""" + WPA = 0x00000010 + """Device supports WPA1 authentication.""" + WPA2 = 0x00000020 + """Device supports WPA2/RSN authentication.""" + AP = 0x00000040 + """Device supports Access Point mode.""" + ADHOC = 0x00000080 + """Device supports Ad-Hoc mode.""" + FREQ_VALID = 0x00000100 + """Device reports frequency capabilities.""" + FREQ_2GHZ = 0x00000200 + """Device supports 2.4GHz frequencies.""" + FREQ_5GHZ = 0x00000400 + """Device supports 5GHz frequencies.""" + MESH = 0x00001000 + """Device supports acting as a mesh point. + + Since NetworkManager 1.20. + """ + IBSS_WPA2 = 0x2000 + """Device supports WPA2/RSN in an IBSS network. + + Since NetworkManager 1.22. """ - UNKNOWN = 0 - NONE = 1 - USER_DISCONNECTED = 2 - DEVICE_DISCONNECTED = 3 - SERVICE_STOPPED = 4 - IP_CONFIG_INVALID = 5 - CONNECT_TIMEOUT = 6 - SERVICE_START_TIMEOUT = 7 - SERVICE_START_FAILED = 8 - NO_SECRETS = 9 - LOGIN_FAILED = 10 - CONNECTION_REMOVED = 11 - DEPENDENCY_FAILED = 12 - DEVICE_REALIZE_FAILED = 13 - DEVICE_REMOVED = 14 -class BluetoothCapabilities(IntFlag): - """Bluetooth Capabilities +class WifiAccessPointCapabilitiesFlags(IntFlag): + """802.11 access point flags.""" - Flags: + NONE = 0x00000000 + """Access point has no special capabilities.""" + PRIVACY = 0x00000001 + """Access point requires authentication and encryption. - * NONE - * DIAL_UP - * NETWORK_ACCESS_POINT + Usually means WEP. """ - NONE = 0x0 - DIAL_UP = 0x1 - NETWORK_ACCESS_POINT = 0x2 + WPS = 0x00000002 + """Access point supports some WPS method.""" + WPS_BUTTON = 0x00000004 + """Access point supports push-button WPS.""" + WPS_PIN = 0x00000008 + """Access point supports PIN-based WPS.""" -class IpTunnelMode(IntEnum): - """Mode of IP tunnel - - * UNKNOWN - * IP_IP - * GRE - * SIT - * ISATAP - * VTI - * IP6_IP6 - * IP_IP6 - * IP6_GRE - * VTI6 - * GRE_TAP - * IP6_GRE_TAP +class WifiAccessPointSecurityFlags(IntFlag): + """802.11 access point security and authentication flags. + + These flags describe the current security requirements of an access point + as determined from the access point's beacon. """ - UNKNOWN = 0 - IP_IP = 1 - GRE = 2 - SIT = 3 - ISATAP = 4 - VTI = 5 - IP6_IP6 = 6 - IP_IP6 = 7 - IP6_GRE = 8 - VTI6 = 9 - GRE_TAP = 10 - IP6_GRE_TAP = 11 + NONE = 0x00000000 + """The access point has no special security requirements.""" + PAIR_WEP40 = 0x00000001 + """40/64-bit WEP is supported for pairwise/unicast encryption.""" + PAIR_WEP104 = 0x00000002 + """104/128-bit WEP is supported for pairwise/unicast encryption.""" + PAIR_TKIP = 0x00000004 + """TKIP is supported for pairwise/unicast encryption.""" + PAIR_CCMP = 0x00000008 + """AES/CCMP is supported for pairwise/unicast encryption.""" + GROUP_WEP40 = 0x00000010 + """40/64-bit WEP is supported for group/broadcast encryption.""" + GROUP_WEP104 = 0x00000020 + """104/128-bit WEP is supported for group/broadcast encryption.""" + GROUP_TKIP = 0x00000040 + """TKIP is supported for group/broadcast encryption.""" + GROUP_CCMP = 0x00000080 + """AES/CCMP is supported for group/broadcast encryption.""" + KEY_MGMT_PSK = 0x00000100 + """WPA/RSN Pre-Shared Key encryption is supported.""" + KEY_MGMT_802_1X = 0x00000200 + """802.1x authentication and key management is supported.""" + KEY_MGMT_SAE = 0x00000400 + """WPA/RSN Simultaneous Authentication of Equals is supported.""" + KEY_MGMT_OWE = 0x00000800 + """WPA/RSN Opportunistic Wireless Encryption is supported.""" + KEY_MGMT_OWE_TM = 0x00001000 + """WPA/RSN Opportunistic Wireless Encryption transition mode is supported. + + Since NetworkManager 1.26. + """ + KEY_MGMT_EAP_SUITE_B_192 = 0x00002000 + """WPA3 Enterprise Suite-B 192 bit mode is supported. -class ModemCapabilities(IntFlag): - """Modem capabilities flags + Since NetworkManager 1.30. + """ - Flags: - * NONE - * ANALOG_WIRE - * CDMA - * GSM - * LTE +class WiFiOperationMode(IntEnum): + """Indicates the 802.11 mode an access point or device is currently in.""" + + UNKNOWN = 0 + """The device or access point mode is unknown.""" + ADHOC = 1 + """For both devices and access point objects, indicates the object is part + of an Ad-Hoc 802.11 network without a central coordinating access point.""" + INFRA = 2 + """The device or access point is in infrastructure mode. + + For devices, this indicates the device is an 802.11 client/station. For + access point objects, this indicates the object is an access point that + provides connectivity to clients. """ - NONE = 0x0 - ANALOG_WIRE = 0x1 - CDMA = 0x2 - GSM = 0x4 - LTE = 0x8 - - -class WirelessCapabilities(IntFlag): - """Wireless device capabilities flags - - Flags: - - * NONE - * CIPHER_WEP40 - * CIPHER_WEP104 - * CIPHER_TKIP - * CIPHER_CCMP - * WPA - * WPA2 - * AP - * ADHOC - * FREQ_VALID - * FREQ_2GHZ - * FREQ_5GHZ - * MESH - * IBSS_WPA2 + AP = 3 + """The device is an access point/hotspot. + + Not valid for access point objects; used only for hotspot mode on the + local machine. + """ + MESH = 4 + """The device is a 802.11s mesh point. + + Since NetworkManager 1.20. """ - NONE = 0x0 - CIPHER_WEP40 = 0x1 - CIPHER_WEP104 = 0x2 - CIPHER_TKIP = 0x4 - CIPHER_CCMP = 0x8 - WPA = 0x10 - WPA2 = 0x20 - AP = 0x40 - ADHOC = 0x80 - FREQ_VALID = 0x100 - FREQ_2GHZ = 0x200 - FREQ_5GHZ = 0x400 - MESH = 0x800 - IBSS_WPA2 = 0x2000 -class DeviceCapabilities(IntFlag): - """Device Capabilities +class BluetoothCapabilitiesFlags(IntFlag): + """Bluetooth device capabilities.""" - Flags: + NONE = 0x00000000 + """Device has no usable capabilities.""" + DUN = 0x00000001 + """Device provides Dial-Up Networking capability.""" + NAP = 0x00000002 + """Device provides Network Access Point capability.""" - * NONE - * SUPPORTED - * CARRIER_DETECTABLE - * IS_SOFTWARE - * CAN_SRIOV + +class ModemCapabilitiesFlags(IntFlag): + """Modem device capabilities. + + Indicates the generic radio access technology families a modem device + supports. For more information on the specific access technologies + the device supports use the ModemManager D-Bus API. """ - NONE = 0x0 - SUPPORTED = 0x1 - CARRIER_DETECTABLE = 0x2 - IS_SOFTWARE = 0x4 - CAN_SRIOV = 0x8 + + NONE = 0x00000000 + """Modem has no usable capabilities.""" + POTS = 0x00000001 + """Modem uses the analog wired telephone network and is not a + wireless/cellular device.""" + CDMA_EVDO = 0x00000002 + """Modem supports at least one of CDMA 1xRTT, EVDO revision 0, EVDO + revision A, or EVDO revision B.""" + GSM_UMTS = 0x00000004 + """Modem supports at least one of GSM, GPRS, EDGE, UMTS, HSDPA, HSUPA + or HSPA+ packet switched data capability.""" + LTE = 0x00000008 + """Modem has LTE data capability.""" + SGNR = 0x00000040 + """Modem has 5GNR data capability. + + Since NetworkManager 1.36. + """ + + +class WimaxNSPNetworkType(IntEnum): + """WiMAX network type.""" + + UNKNOWN = 0 + """Unknown network type.""" + HOME = 1 + """Home network.""" + PARTNER = 2 + """Partner network.""" + ROAMING_PARTNER = 3 + """Roaming partner network.""" class DeviceState(IntEnum): - """Device State - - * UNKNOWN - * UNMANAGED - * UNAVAILABLE - * DISCONNECTED - * PREPARE - * CONFIG - * NEED_AUTH - * IP_CONFIG - * IP_CHECK - * SECONDARIES - * ACTIVATED - * DEACTIVATING - * FAILED - """ + """Device's state.""" + UNKNOWN = 0 + """The device's state is unknown.""" UNMANAGED = 10 + """The device is recognized, but not managed by NetworkManager.""" UNAVAILABLE = 20 + """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. + """ DISCONNECTED = 30 + """The device can be activated, but is currently idle and not connected + to a network.""" PREPARE = 40 + """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. + """ CONFIG = 50 + """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. + """ NEED_AUTH = 60 + """The device requires more information to continue connecting to + the requested network. + + This includes secrets like WiFi passphrases, login passwords, PIN + codes, etc. + """ IP_CONFIG = 70 + """The device is requesting IPv4 and/or IPv6 addresses and routing + information from the network.""" IP_CHECK = 80 + """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. + """ SECONDARIES = 90 + """The device is waiting for a secondary connection (like a VPN) which + must activated before the device can be activated""" ACTIVATED = 100 + """The device has a network connection, either local or global.""" DEACTIVATING = 110 + """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. + """ FAILED = 120 + """The device failed to connect to the requested network and + is cleaning up the connection request""" class DeviceStateReason(IntEnum): - """Device State reason - - * NONE - * UNKNOWN - * NOW_MANAGED - * NOW_UNMANAGED - * CONFIG_FAILED - * IP_CONFIG_UNAVAILABLE - * IP_CONFIG_EXPIRED - * NO_SECRETS - * SUPPLICANT_DISCONNECT - * SUPPLICANT_CONFIG_FAILED - * SUPPLICANT_FAILED - * SUPPLICANT_TIMEOUT - * PPP_START_FAILED - * PPP_DISCONNECT - * PPP_FAILED - * DHCP_START_FAILED - * DHCP_ERROR - * DHCP_FAILED - * SHARED_START_FAILED - * SHARED_FAILED - * AUTOIP_START_FAILED - * AUTOIP_ERROR - * AUTOIP_FAILED - * MODEM_BUSY - * MODEM_NO_DIAL_TONE - * MODEM_NO_CARRIER - * MODEM_DIAL_TIMEOUT - * MODEM_DIAL_FAILED - * MODEM_INIT_FAILED - * GSM_APN_FAILED - * GSM_REGISTRATION_NOT_SEARCHING - * GSM_REGISTRATION_DENIED - * GSM_REGISTRATION_TIMEOUT - * GSM_REGISTRATION_FAILED - * GSM_PIN_CHECK_FAILED - * FIRMWARE_MISSING - * REMOVED - * SLEEPING - * CONNECTION_REMOVED - * USER_REQUESTED - * CARRIER - * CONNECTION_ASSUMED - * SUPPLICANT_AVAILABLE - * MODEM_NOT_FOUND - * BT_FAILED - * GSM_SIM_NOT_INSERTED - * GSM_SIM_PIN_REQUIRED - * GSM_SIM_PUK_REQUIRED - * GSM_SIM_WRONG - * INFINIBAND_MODE - * DEPENDENCY_FAILED - * BR2684_FAILED - * MODEM_MANAGER_UNAVAILABLE - * SSID_NOT_FOUND - * SECONDARY_CONNECTION_FAILED - * DCB_FCOE_FAILED - * TEAMD_CONTROL_FAILED - * MODEM_FAILED - * MODEM_AVAILABLE - * SIM_PIN_INCORRECT - * NEW_ACTIVATION - * PARENT_CHANGED - * PARENT_MANAGED_CHANGED - * OVSDB_FAILED - * IP_ADDRESS_DUPLICATE - * IP_METHOD_UNSUPPORTED - * SRIOV_CONFIGURATION_FAILED - * PEER_NOT_FOUND - """ + """Device state change reason codes.""" + + NONE = 0 + """No reason given.""" UNKNOWN = 1 + """Unknown error.""" NOW_MANAGED = 2 + """Device is now managed.""" NOW_UNMANAGED = 3 + """Device is now unmanaged.""" CONFIG_FAILED = 4 + """The device could not be readied for configuration.""" IP_CONFIG_UNAVAILABLE = 5 + """IP configuration could not be reserved. + + No available address, timeout, etc... + """ IP_CONFIG_EXPIRED = 6 + """The IP config is no longer valid.""" NO_SECRETS = 7 + """Secrets were required, but not provided.""" SUPPLICANT_DISCONNECT = 8 + """802.1x supplicant disconnected.""" SUPPLICANT_CONFIG_FAILED = 9 + """802.1x supplicant configuration failed.""" SUPPLICANT_FAILED = 10 + """802.1x supplicant failed.""" SUPPLICANT_TIMEOUT = 11 + """802.1x supplicant took too long to authenticate.""" PPP_START_FAILED = 12 + """PPP service failed to start.""" PPP_DISCONNECT = 13 + """PPP service disconnected.""" PPP_FAILED = 14 + """PPP failed.""" DHCP_START_FAILED = 15 + """DHCP client failed to start.""" DHCP_ERROR = 16 + """DHCP client error.""" DHCP_FAILED = 17 + """DHCP client failed.""" SHARED_START_FAILED = 18 + """Shared connection service failed to start.""" SHARED_FAILED = 19 + """Shared connection service failed.""" AUTOIP_START_FAILED = 20 + """AutoIP service failed to start.""" AUTOIP_ERROR = 21 + """AutoIP service error.""" AUTOIP_FAILED = 22 + """AutoIP service failed.""" MODEM_BUSY = 23 + """The line is busy.""" MODEM_NO_DIAL_TONE = 24 + """No dial tone.""" MODEM_NO_CARRIER = 25 + """No carrier could be established.""" MODEM_DIAL_TIMEOUT = 26 + """The dialing request timed out.""" MODEM_DIAL_FAILED = 27 + """The dialing attempt failed.""" MODEM_INIT_FAILED = 28 + """Modem initialization failed.""" GSM_APN_FAILED = 29 + """Failed to select the specified APN.""" GSM_REGISTRATION_NOT_SEARCHING = 30 + """Not searching for networks.""" GSM_REGISTRATION_DENIED = 31 + """Network registration denied.""" GSM_REGISTRATION_TIMEOUT = 32 + """Network registration timed out.""" GSM_REGISTRATION_FAILED = 33 + """Failed to register with the requested network.""" GSM_PIN_CHECK_FAILED = 34 + """PIN check failed.""" FIRMWARE_MISSING = 35 + """Necessary firmware for the device may be missing.""" REMOVED = 36 + """The device was removed.""" SLEEPING = 37 + """NetworkManager went to sleep.""" CONNECTION_REMOVED = 38 + """The device's active connection disappeared.""" USER_REQUESTED = 39 + """Device disconnected by user or client.""" CARRIER = 40 + """Carrier/link changed.""" CONNECTION_ASSUMED = 41 + """The device's existing connection was assumed.""" SUPPLICANT_AVAILABLE = 42 + """The supplicant is now available.""" MODEM_NOT_FOUND = 43 + """The modem could not be found.""" BT_FAILED = 44 + """The Bluetooth connection failed or timed out.""" GSM_SIM_NOT_INSERTED = 45 + """GSM Modem's SIM Card not inserted.""" GSM_SIM_PIN_REQUIRED = 46 + """GSM Modem's SIM Pin required.""" GSM_SIM_PUK_REQUIRED = 47 + """GSM Modem's SIM Puk required.""" GSM_SIM_WRONG = 48 + """GSM Modem's SIM wrong.""" INFINIBAND_MODE = 49 + """InfiniBand device does not support connected mode.""" DEPENDENCY_FAILED = 50 + """A dependency of the connection failed.""" BR2684_FAILED = 51 + """Problem with the RFC 2684 Ethernet over ADSL bridge.""" MODEM_MANAGER_UNAVAILABLE = 52 + """ModemManager not running.""" SSID_NOT_FOUND = 53 + """The Wi-Fi network could not be found.""" SECONDARY_CONNECTION_FAILED = 54 + """A secondary connection of the base connection failed.""" DCB_FCOE_FAILED = 55 + """DCB or FCoE setup failed.""" TEAMD_CONTROL_FAILED = 56 + """teamd control failed.""" MODEM_FAILED = 57 + """Modem failed or no longer available.""" MODEM_AVAILABLE = 58 + """Modem now ready and available.""" SIM_PIN_INCORRECT = 59 + """SIM PIN was incorrect.""" NEW_ACTIVATION = 60 + """New connection activation was enqueued.""" PARENT_CHANGED = 61 + """The device's parent changed.""" PARENT_MANAGED_CHANGED = 62 + """The device parent's management changed.""" OVSDB_FAILED = 63 + """Problem communicating with Open vSwitch database.""" IP_ADDRESS_DUPLICATE = 64 + """A duplicate IP address was detected.""" IP_METHOD_UNSUPPORTED = 65 + """The selected IP method is not supported.""" SRIOV_CONFIGURATION_FAILED = 66 + """Configuration of SR-IOV parameters failed.""" PEER_NOT_FOUND = 67 + """The Wi-Fi P2P peer could not be found.""" -# Connection Types, e.g. from connecion_profile.connection.type: -# -# There is no central list of all connection types in NM. -# The best bet is to look for nm_connection_is_type() checks which use -# NM_SETTING_(TYPE)_SETTING_NAME #defines (which are fined used for -# settings for this connection-type. One connection_type can have several -# of such settings groups, so we have to filter those to get the strings: -# -# Generated from NetworkManager source using: -# grep -r nm_connection_is_type src/| -# sed -n 's/.*NM_SETTING_/NM_SETTING_/;s/_SETTING_NAME.*/=/p' | -# sort -u >.connection_is_type -# grep -hr define.*_SETTING_NAME src/| -# sed 's/#define //;s/_SETTING_NAME//;s/ /=/' >.setting_defines -# grep -f .connection_is_type .setting_defines | -# sed 's/NM_SETTING_/ /;s/6L/SIXL/;/GENERIC/d;s/=/ = /' -# Manual edit: This resulted in WIRED instead of ETHERNET, but -# ETHERNET is the name used for DeviceType, so use ETHERNET instead to -# be able to lookup connection profiles for Ethernet using DeviceType. -# -# One src/core/nm-device-*.c can support more than one ConnectionType, -# thus there are more ConnectionTypes than DeviceTypes: +class DeviceMetered(IntEnum): + """Device metered state. + + The NMMetered enum has two different purposes: one is to configure + "connection.metered" setting of a ConnectionSettings, and + the other is to express the actual metered state of the Device at a given + moment. + + For the connection profile only UNKNOWN, NO and YES are allowed. + + The device's metered state at runtime is determined by the profile which + is currently active. If the profile explicitly specifies NO or YES, then + the device's metered state is as such. If the connection profile leaves it + undecided at UNKNOWN (the default), then NetworkManager tries to guess + the metered state, for example based on the device type or on DHCP options + (like Android devices exposing a "ANDROID_METERED" DHCP vendor option). + This then leads to either GUESS_NO or GUESS_YES. + + Most applications probably should treat the runtime state + GUESS_YES like YES, and all other states as not metered. + + Note that the per-device metered states are then combined to a global + metered state. This is basically the metered state of the device with the + best default route. However, that generalization of a global metered state + may not be correct if the default routes for IPv4 and IPv6 are on different + devices, or if policy routing is configured. In general, the global metered + state tries to express whether the traffic is likely metered, but since + that depends on the traffic itself, there is not one answer in all cases. + Hence, an application may want to consider the per-device's metered states. + """ -# From NetworkManager-1.35: -class ConnectionType(str, Enum): - """Connection Types + UNKNOWN = 0 + """The metered status is unknown.""" + YES = 1 + """Metered, the value was explicitly configured.""" + NO = 2 + """Not metered, the value was explicitly configured.""" + GUESS_YES = 3 + """Metered, the value was guessed.""" + GUESS_NO = 4 + """Not metered, the value was guessed.""" - * ADSL - * BLUETOOTH - * BOND - * BRIDGE - * CDMA - * DUMMY - * ETHERNET - * MODEM - * INFINIBAND - * IP_TUNNEL - * MACSEC - * MACVLAN - * OLPC_MESH - * OVS_BRIDGE - * OVS_INTERFACE - * OVS_INTERFACE - * PPPOE - * SIXLOWPAN - * TEAM - * TUN - * VETH - * VLAN - * VPN - * VRF - * VXLAN - * WIFI_P2P - * WIREGUARD - * WIFI - * WPAN - * LOOPBACK - """ - ADSL = "adsl" - BLUETOOTH = "bluetooth" - BOND = "bond" - BRIDGE = "bridge" - CDMA = "cdma" - DUMMY = "dummy" - ETHERNET = "802-3-ethernet" - MODEM = "gsm" - INFINIBAND = "infiniband" - IP_TUNNEL = "ip-tunnel" - MACSEC = "macsec" - MACVLAN = "macvlan" - OLPC_MESH = "802-11-olpc-mesh" - OVS_BRIDGE = "ovs-bridge" - OVS_INTERFACE = "ovs-interface" - OVS_PORT = "ovs-port" - PPPOE = "pppoe" - SIXLOWPAN = "6lowpan" - TEAM = "team" - TUN = "tun" - VETH = "veth" - VLAN = "vlan" - VPN = "vpn" - VRF = "vrf" - VXLAN = "vxlan" - WIFI_P2P = "wifi-p2p" - WIREGUARD = "wireguard" - WIFI = "802-11-wireless" - WPAN = "wpan" - LOOPBACK = "loopback" +class ConnectionMultiConnect(IntEnum): + """Ability of a connection to be active on multiple devices. -class DeviceType(IntEnum): - """Device Type + Since NetworkManager 1.14. + """ - * UNKNOWN - * ETHERNET - * WIFI - * UNUSED1 - * UNUSED2 - * BLUETOOTH - * OLPC_MESH - * WIMAX - * MODEM - * INFINIBAND - * BOND - * VLAN - * ADSL - * BRIDGE - * GENERIC - * TEAM - * TUN - * IP_TUNNEL - * MACVLAN - * VXLAN - * VETH - * MACSEC - * DUMMY - * PPP - * OVS_INTERFACE - * OVS_PORT - * OVS_BRIDGE - * WPAN - * SIXLOWPAN - * WIREGUARD - * WIFI_P2P - * VRF - * LOOPBACK - """ - UNKNOWN = 0 - ETHERNET = 1 - WIFI = 2 - UNUSED1 = 3 - UNUSED2 = 4 - BLUETOOTH = 5 - OLPC_MESH = 6 - WIMAX = 7 - MODEM = 8 - INFINIBAND = 9 - BOND = 10 - VLAN = 11 - ADSL = 12 - BRIDGE = 13 - GENERIC = 14 - TEAM = 15 - TUN = 16 - IP_TUNNEL = 17 - MACVLAN = 18 - VXLAN = 19 - VETH = 20 - MACSEC = 21 - DUMMY = 22 - PPP = 23 - OVS_INTERFACE = 24 - OVS_PORT = 25 - OVS_BRIDGE = 26 - WPAN = 27 - SIXLOWPAN = 28 - WIREGUARD = 29 - WIFI_P2P = 30 - VRF = 31 - LOOPBACK = 32 + DEFAULT = 0 + """Indicates that the per-connection setting is unspecified. + In this case, it will fallback to the default value of SINGLE. + """ + SINGLE = 1 + """The connection profile can only be active once at each moment. -class DeviceMetered(IntEnum): - """Device Metered state + Activating a profile that is already active, will first deactivate it. + """ + MANUAL_MULTIPLE = 2 + """The profile can be manually activated multiple times + on different devices. - * UNKNOWN - * YES - * NO - * GUESS_YES - * GUESS_NO + However, regarding autoconnect, the profile will autoconnect only if it + is currently not connected otherwise. """ + MULTIPLE = 3 + """The profile can autoactivate and be manually activated multiple + times together.""" + + +class ActiveConnectionState(IntEnum): + """Indicates the state of an active connection to a specific network.""" + UNKNOWN = 0 - YES = 1 - NO = 2 - GUESS_YES = 3 - GUESS_NO = 4 + """The state of the connection is unknown.""" + ACTIVATING = 1 + """A network connection is being prepared.""" + ACTIVATED = 2 + """There is a connection to the network.""" + DEACTIVATING = 3 + """The network connection is being torn down and cleaned up.""" + DEACTIVATED = 4 + """The network connection is disconnected and will be removed.""" -class ConnectivityState(IntEnum): - """Connectivity state +class ActiveConnectionStateReason(IntEnum): + """Active connection state reasons. - * UNKNOWN - * NONE - * PORTAL - * LIMITED - * FULL + Since NetworkManager 1.8. """ + UNKNOWN = 0 + """The reason for the active connection state change is unknown.""" NONE = 1 - PORTAL = 2 - LIMITED = 3 - FULL = 4 + """No reason was given for the active connection state change.""" + USER_DISCONNECTED = 2 + """The active connection changed state because the user disconnected it.""" + DEVICE_DISCONNECTED = 3 + """The active connection changed state because the device it was using was + disconnected.""" + SERVICE_STOPPED = 4 + """The service providing the VPN connection was stopped.""" + IP_CONFIG_INVALID = 5 + """The IP config of the active connection was invalid.""" + CONNECT_TIMEOUT = 6 + """The connection attempt to the VPN service timed out.""" + SERVICE_START_TIMEOUT = 7 + """A timeout occurred while starting the service providing the + VPN connection.""" + SERVICE_START_FAILED = 8 + """Starting the service providing the VPN connection failed.""" + NO_SECRETS = 9 + """Necessary secrets for the connection were not provided.""" + LOGIN_FAILED = 10 + """Authentication to the server failed.""" + CONNECTION_REMOVED = 11 + """The connection was deleted from settings.""" + DEPENDENCY_FAILED = 12 + """Master connection of this connection failed to activate.""" + DEVICE_REALIZE_FAILED = 13 + """Could not create the software device link.""" + DEVICE_REMOVED = 14 + """The device this connection depended on disappeared.""" -class DeviceInterfaceFlags(IntFlag): - """Device network interface flags +class SecretAgentGetSecretsFlags(IntFlag): + """Flags to modify the behavior of a get_secrets request.""" - Flags: + NONE = 0x0 + """No special behavior. + + By default no user interaction is allowed and requests for secrets + are fulfilled from persistent storage, or if no secrets are available + an error is returned. + """ + ALLOW_INTERACTION = 0x1 + """Allows the request to interact with the user. + + Possibly prompting via UI for secrets if any are required, or if none + are found in persistent storage. + """ + REQUEST_NEW = 0x2 + """Explicitly prompt for new secrets from the user. - * NONE - * UP - * LOWER_UP - * CARRIER + This flag signals that NetworkManager thinks any existing secrets + are invalid or wrong. This flag implies that interaction is allowed. """ + FLAG_USER_REQUESTED = 0x4 + """Set if the request was initiated by user-requested action via the D-Bus + interface, as opposed to automatically initiated by NetworkManager + in response to (for example) scan results or carrier changes.""" + WPS_PBC_ACTIVE = 0x8 + """Indicates that WPS enrollment is active with PBC method. + + The agent may suggest that the user pushes a button on the router + instead of supplying a PSK. + """ + + +class SecretAgentCapabilitiesFlags(IntFlag): + """Secret agent capabilities.""" + NONE = 0x0 + """The agent supports no special capabilities.""" + VPN_HINTS = 0x1 + """The agent supports passing hints to VPN plugin + authentication dialogs.""" + + +class IpTunnelMode(IntEnum): + """Mode of IP tunnel. + + Since NetworkManager 1.2. + """ + + UNKNOWN = 0 + """Unknown/unset tunnel mode.""" + IP_IP = 1 + """IP in IP tunnel.""" + GRE = 2 + """GRE tunnel.""" + SIT = 3 + """SIT tunnel.""" + ISATAP = 4 + """ISATAP tunnel.""" + VTI = 5 + """VTI tunnel.""" + IP6_IP6 = 6 + """IPv6 in IPv6 tunnel.""" + IP_IP6 = 7 + """IPv4 in IPv6 tunnel.""" + IP6_GRE = 8 + """IPv6 GRE tunnel.""" + VTI6 = 9 + """IPv6 VTI tunnel.""" + GRE_TAP = 10 + """GRETAP tunnel.""" + IP6_GRE_TAP = 11 + """IPv6 GRETAP tunnel.""" + + +class CheckpointCreateFlags(IntFlag): + """Flags for checkpoint_create call. + + Since NetworkManager 1.4. + """ + + NONE = 0 + """No flags.""" + DESTROY_ALL = 0x01 + """When creating a new checkpoint, destroy all existing ones.""" + DELETE_NEW_CONNECTIONS = 0x02 + """Upon rollback, delete any new connection added after the checkpoint. + + Since NetworkManager 1.6. + """ + NEW_DEVICES = 0x04 + """Upon rollback, disconnect any new device appeared after the checkpoint. + + Since NetworkManager 1.6. + """ + ALLOW_OVERLAPPING = 0x08 + """By default, creating a checkpoint fails if there are already existing + checkpoints that reference the same devices. With this flag, creation of + such checkpoints is allowed, however, if an older checkpoint that + references overlapping devices gets rolled back, it will automatically + destroy this checkpoint during rollback. This allows to create several + overlapping checkpoints in parallel, and rollback to them at will. With + the special case that rolling back to an older checkpoint will invalidate + all overlapping younger checkpoints. This opts-in that the checkpoint can + be automatically destroyed by the rollback of an older checkpoint. + + Since NetworkManager 1.12. + """ + NO_PRESERVE_EXTERNAL_PORTS = 0x10 + """During rollback, by default externally added ports attached to + bridge devices are preserved. With this flag, the rollback detaches all + external ports. This only has an effect for bridge ports. Before + NetworkManager 1.38, this was the default behavior. + + Since NetworkManager 1.38. + """ + + +class CheckpointRollbackResult(IntEnum): + """The result of a checkpoint rollback for a specific device.""" + + OK = 0 + """The rollback succeeded.""" + ERR_NO_DEVICE = 1 + """The device no longer exists.""" + ERR_DEVICE_UNMANAGED = 2 + """The device is now unmanaged.""" + ERR_FAILED = 3 + """Other errors during rollback.""" + + +class SettingsConnectionFlags(IntFlag): + """Settings Connection flags.""" + + NONE = 0 + """An alias for numeric zero, no flags set.""" + UNSAVED = 0x01 + """The connection is not saved to disk. + + That either means, that the connection is in-memory only + and currently is not backed by a file. Or, that the connection is + backed by a file, but has modifications in-memory that were not + persisted to disk. + """ + NM_GENERATED = 0x02 + """A connection is "nm-generated" if it was generated by NetworkManger. + + If the connection gets modified or saved by the user, the flag + gets cleared. A nm-generated is also unsaved and has no backing + file as it is in-memory only. + """ + VOLATILE = 0x04 + """The connection will be deleted when it disconnects. + + That is for in-memory connections (unsaved), which are currently active + but deleted on disconnect. Volatile connections are always unsaved, but + they are also no backing file on disk and are entirely in-memory only. + """ + EXTERNAL = 0x08 + """The profile was generated to represent + an external configuration of a networking device. + + Since NetworkManager 1.26. + """ + + +class ActivationStateFlags(IntFlag): + """Flags describing the current activation state. + + Since NetworkManager 1.10. + """ + + NONE = 0 + """An alias for numeric zero, no flags set.""" + IS_MASTER = 0x1 + """The device is a master.""" + IS_SLAVE = 0x2 + """The device is a slave.""" + LAYER2_READY = 0x4 + """Layer2 is activated and ready.""" + IP4_READY = 0x8 + """IPv4 setting is completed.""" + IP6_READY = 0x10 + """IPv6 setting is completed.""" + MASTER_HAS_SLAVES = 0x20 + """The master has any slave devices attached. + + This only makes sense if the device is a master. + """ + LIFE_TIME_BOUND_TO_PROFILE_VISIBILITY = 0x40 + """The lifetime of the activation is bound to the visibility of + the connection profile, which in turn depends on "connection.permissions" + and whether a session for the user exists. + + Since NetworkManager 1.16. + """ + EXTERNAL = 0x80 + """The active connection was generated to represent an external + configuration of a networking device. + + Since NetworkManager 1.26. + """ + + +class SettingsAddConnection2Flags(IntFlag): + """Flags for the add_connection2() method.""" + + NONE = 0 + """An alias for numeric zero, no flags set.""" + TO_DISK = 0x1 + """To persist the connection to disk.""" + IN_MEMORY = 0x2 + """To make the connection in-memory only.""" + BLOCK_AUTOCONNECT = 0x20 + """Usually, when the connection has autoconnect enabled and gets added, + it becomes eligible to autoconnect right away. Setting this flag, disables + autoconnect until the connection is manually activated.""" + + +class SettingsUpdate2Flags(IntFlag): + """Flags for the update2() method.""" + + NONE = 0 + """An alias for numeric zero, no flags set.""" + TO_DISK = 0x1 + """To persist the connection to disk.""" + IN_MEMORY = 0x2 + """Makes the profile in-memory. + + Note that such profiles are stored in keyfile format under /run. + If the file is already in-memory, the file in /run is updated in-place. + Otherwise, the previous storage for the profile is left unchanged on disk, + and the in-memory copy shadows it. Note that the original filename of the + previous persistent storage (if any) is remembered. That means, when later + persisting the profile again to disk, the file on disk will be overwritten + again. Likewise, when finally deleting the profile, both the storage from + /run and persistent storage are deleted (or if the persistent storage does + not allow deletion, and nmmeta file is written to mark the UUID + as deleted). + """ + IN_MEMORY_DETACHED = 0x4 + """This is almost the same as IN_MEMORY, with one difference: + when later deleting the profile, the original profile will not + be deleted. Instead a nmmeta file is written to /run to indicate + that the profile is gone. Note that if such a nmmeta tombstone + file exists and hides a file in persistent storage, then when + re-adding the profile with the same UUID, then the original storage + is taken over again.""" + IN_MEMORY_ONLY = 0x8 + """This is like IN_MEMORY, but if the connection has a corresponding + file on persistent storage, the file will be deleted right away. + If the profile is later again persisted to disk, a new, unused + filename will be chosen.""" + VOLATILE = 0x10 + """This can be specified with either IN_MEMORY, IN_MEMORY_DETACHED or + IN_MEMORY_ONLY. After making the connection in-memory only, the connection + is marked as volatile. That means, if the connection is currently not + active it will be deleted right away. Otherwise, it is marked to for + deletion once the connection deactivates. A volatile connection cannot + autoactivate again (because it's about to be deleted), but a manual + activation will clear the volatile flag.""" + BLOCK_AUTOCONNECT = 0x20 + """Usually, when the connection has autoconnect enabled and is modified, + it becomes eligible to autoconnect right away. Setting this flag, disables + autoconnect until the connection is manually activated.""" + NO_REAPPLY = 0x40 + """When a profile gets modified that is currently active, then + these changes don't take effect for the active device unless the + profile gets reactivated or the configuration reapplied. There are two + exceptions: by default "connection.zone" and "connection.metered" + properties take effect immediately. Specify this flag to prevent these + properties to take effect, so that the change is restricted to modify + the profile. + + Since NetworkManager 1.20. + """ + + +class DeviceReapplyFlags(IntFlag): + """Flags for the reapply() methodof a device. + + Since NetworkManager 1.42. + """ + + NONE = 0 + """No flag set.""" + PRESERVE_EXTERNAL_IP = 0x1 + """During reapply, preserve external IP addresses and routes.""" + + +class NetworkManagerReloadFlags(IntFlag): + """Flags for the NetworkManager reload() call.""" + + NONE = 0 + """An alias for numeric zero, no flags set. This reloads everything + that is supported and is identical to a SIGHUP.""" + CONF = 0x1 + """Reload the NetworkManager.conf configuration from disk. + + Note that this does not include connections, which can be reloaded + via Setting's reload_connections(). + """ + DNS_RC = 0x2 + """Update DNS configuration, which usually involves + writing /etc/resolv.conf anew.""" + DNS_FULL = 0x4 + """Means to restart the DNS plugin. + + This is for example useful when using dnsmasq plugin, which uses additional + configuration in /etc/NetworkManager/dnsmasq.d. If you edit those files, + you can restart the DNS plugin. This action shortly interrupts name + resolution. + """ + ALL = 0x7 + """All flags.""" + + +class DeviceInterfaceFlags(IntFlag): + """Flags for a network interface. + + Since NetworkManager 1.22. + """ + + NONE = 0 + """An alias for numeric zero, no flags set.""" UP = 0x1 + """The interface is enabled from the administrative point of view. + + Corresponds to kernel IFF_UP. + """ LOWER_UP = 0x2 + """The physical link is up. + + Corresponds to kernel IFF_LOWER_UP. + """ + PROMISC = 0x4 + """Receive all packets. + + Corresponds to kernel IFF_PROMISC. + + Since NetworkManager 1.32. + """ CARRIER = 0x10000 + """The interface has carrier. + + In most cases this is equal to the value of LOWER_UP. + However some devices have a non-standard carrier detection mechanism. + """ + LLDP_CLIENT_ENABLED = 0x20000 + """The flag to indicate device LLDP status. + Since NetworkManager 1.32. + """ -class ConnectionFlags(IntFlag): - """Connection flags - Flags +class RadioFlags(IntFlag): + """Flags related to radio interfaces. - * NONE - * UNSAVED - * GENERATED - * VOLATILE - * EXTERNAL + Since NetworkManager 1.38. """ - NONE = 0x0 - UNSAVED = 0x1 - GENERATED = 0x2 - VOLATILE = 0x4 - EXTERNAL = 0x8 + NONE = 0 + """An alias for numeric zero, no flags set.""" + WLAN_AVAILABLE = 0x1 + """A Wireless LAN device or rfkill switch is detected in the system.""" + WWAN_AVAILABLE = 0x2 + """A Wireless WAN device or rfkill switch is detected in the system.""" + + +class MptcpFlags(IntFlag): + """Flags related to Multi-path TCP. -class VpnState(IntEnum): - """VPN State + Since NetworkManager 1.40. + """ - * UNKNOWN - * INIT - * SHUTDOWN - * STARTING - * STARTED - * STOPPING - * STOPPED + NONE = 0 + """The default, meaning that no MPTCP flags are set.""" + DISABLED = 0x1 + """Don't configure MPTCP endpoints on the device.""" + ENABLED = 0x2 + """MPTCP is enabled and endpoints will be configured. + + This flag is implied if any of the other flags indicate that MPTCP is + enabled and therefore in most cases unnecessary. Note that + if "/proc/sys/net/mptcp/enabled" sysctl is disabled, MPTCP handling is + disabled despite this flag. This can be overruled with the + "also-without-sysctl" flag. Note that by default interfaces that don't + have a default route are excluded from having MPTCP endpoints configured. + This can be overruled with the "also-without-default-route" and + this affects endpoints per address family. + """ + ALSO_WITHOUT_SYSCTL = 0x4 + """Even if MPTCP handling is enabled via the "enabled" flag, + it is ignored unless "/proc/sys/net/mptcp/enabled" is on. + With this flag, MPTCP endpoints will be configured regardless + of the sysctl setting.""" + ALSO_WITHOUT_DEFAULT_ROUTE = 0x8 + """Even if MPTCP handling is enabled via the "enabled" flag, + it is ignored per-address family unless NetworkManager + configures a default route. With this flag, NetworkManager will + also configure MPTCP endpoints if there is no default route. + This takes effect per-address family.""" + SIGNAL = 0x10 + """Flag for the MPTCP endpoint. + + The endpoint will be announced/signaled to each peer via an MPTCP + ADD_ADDR sub-option. + """ + SUBFLOW = 0x20 + """Flag for the MPTCP endpoint. + + If additional subflow creation is allowed by the MPTCP limits, the MPTCP + path manager will try to create an additional subflow using this endpoint + as the source address after the MPTCP connection is established. + """ + BACKUP = 0x40 + """Flag for the MPTCP endpoint. + + If this is a subflow endpoint, the subflows created using this endpoint + will have the backup flag set during the connection process. This flag + instructs the peer to only send data on a given subflow when all non-backup + subflows are unavailable. This does not affect outgoing data, where subflow + priority is determined by the backup/non-backup flag received from + the peer. """ + FULLMESH = 0x80 + """Flag for the MPTCP endpoint. + + If this is a subflow endpoint and additional subflow creation is + allowed by the MPTCP limits, the MPTCP path manager will try to create + an additional subflow for each known peer address, using this endpoint as + the source address. This will occur after the MPTCP connection is + established. If the peer did not announce any additional addresses using + the MPTCP ADD_ADDR sub-option, this will behave the same as a plain + subflow endpoint. When the peer does announce addresses, each received + ADD_ADDR sub-option will trigger creation of an additional subflow + to generate a full mesh topology. + """ + + +# From VPN plugin + +class VpnServiceState(IntEnum): + """VPN daemon states.""" + UNKNOWN = 0 + """The state of the VPN plugin is unknown.""" INIT = 1 + """The VPN plugin is initialized.""" SHUTDOWN = 2 + """Not used.""" STARTING = 3 + """The plugin is attempting to connect to a VPN server.""" STARTED = 4 + """The plugin has connected to a VPN server.""" STOPPING = 5 + """The plugin is disconnecting from the VPN server.""" STOPPED = 6 + """The plugin has disconnected from the VPN server.""" -class VpnFailure(IntEnum): - """VPN Failure +class VpnConnectionState(IntEnum): + """VPN connection states.""" - * LOGIN_FAILURE - * CONNECT_FAILED - * BAD_IP_CONFIG - """ - LOGIN_FAILURE = 0 - CONNECT_FAILED = 1 - BAD_IP_CONFIG = 3 - - -class NetworkManagerConnectivityState(IntEnum): - """NetworkManager connectivity state enum + UNKNOWN = 0 + """The state of the VPN connection is unknown.""" + PREPARE = 1 + """The VPN connection is preparing to connect.""" + NEED_AUTH = 2 + """The VPN connection needs authorization credentials.""" + CONNECT = 3 + """The VPN connection is being established.""" + IP_CONFIG_GET = 4 + """The VPN connection is getting an IP address.""" + ACTIVATED = 5 + """The VPN connection is active.""" + FAILED = 6 + """The VPN connection failed.""" + DISCONNECTED = 7 + """The VPN connection is disconnected.""" + + +class VpnConnectionStateReason(IntEnum): + """VPN connection state reasons.""" - * UNKNOWN - * NONE - * PORTAL - * LIMITED - * FULL - """ UNKNOWN = 0 + """The reason for the VPN connection state change is unknown.""" NONE = 1 - PORTAL = 2 - LIMITED = 3 - FULL = 4 + """No reason was given for the VPN connection state change.""" + USER_DISCONNECTED = 2 + """The VPN connection changed state because the user disconnected it.""" + DEVICE_DISCONNECTED = 3 + """The VPN connection changed state because the device it was using + was disconnected.""" + STOPPED = 4 + """The service providing the VPN connection was stopped.""" + IP_CONFIG_INVALID = 5 + """The IP config of the VPN connection was invalid.""" + CONNECT_TIMEOUT = 6 + """The connection attempt to the VPN service timed out.""" + SERVICE_START_TIMEOUT = 7 + """A timeout occurred while starting the service providing + the VPN connection.""" + SERVICE_START_FAILED = 8 + """Starting the service starting the service providing the VPN connection + failed.""" + NO_SECRETS = 9 + """Necessary secrets for the VPN connection were not provided.""" + LOGIN_FAILED = 10 + """Authentication to the VPN server failed.""" + CONNECTION_REMOVED = 11 + """The connection was deleted from settings.""" -class NetworkManagerState(IntEnum): - """NetworkManager state enum +class VpnFailure(IntEnum): + """VPN plugin failure reasons.""" + + LOGIN_FAILED = 0 + """Login failed.""" + CONNECT_FAILED = 1 + """Connect failed.""" + BAD_IP_CONFIG = 2 + """Invalid IP configuration returned from the VPN plugin.""" + +# Connection Types, e.g. from connecion_profile.connection.type: +# +# There is no central list of all connection types in NM. +# The best bet is to look for nm_connection_is_type() checks which use +# NM_SETTING_(TYPE)_SETTING_NAME #defines (which are fined used for +# settings for this connection-type. One connection_type can have several +# of such settings groups, so we have to filter those to get the strings: +# +# Generated from NetworkManager source using: +# grep -r nm_connection_is_type src/| +# sed -n 's/.*NM_SETTING_/NM_SETTING_/;s/_SETTING_NAME.*/=/p' | +# sort -u >.connection_is_type +# grep -hr define.*_SETTING_NAME src/| +# sed 's/#define //;s/_SETTING_NAME//;s/ /=/' >.setting_defines +# grep -f .connection_is_type .setting_defines | +# sed 's/NM_SETTING_/ /;s/6L/SIXL/;/GENERIC/d;s/=/ = /' +# Manual edit: This resulted in WIRED instead of ETHERNET, but +# ETHERNET is the name used for DeviceType, so use ETHERNET instead to +# be able to lookup connection profiles for Ethernet using DeviceType. +# +# One src/core/nm-device-*.c can support more than one ConnectionType, +# thus there are more ConnectionTypes than DeviceTypes: - * UNKNOWN - * ASLEEP - * DISCONNECTED - * DISCONNECTING - * CONNECTING - * CONNECTED_LOCAL - * CONNECTED_SITE - * GLOBAL + +# From NetworkManager-1.35: +class ConnectionType(str, Enum): + """Connection Types. + + * ADSL + * BLUETOOTH + * BOND + * BRIDGE + * CDMA + * DUMMY + * ETHERNET + * MODEM + * INFINIBAND + * IP_TUNNEL + * MACSEC + * MACVLAN + * OLPC_MESH + * OVS_BRIDGE + * OVS_INTERFACE + * OVS_INTERFACE + * PPPOE + * SIXLOWPAN + * TEAM + * TUN + * VETH + * VLAN + * VPN + * VRF + * VXLAN + * WIFI_P2P + * WIREGUARD + * WIFI + * WPAN + * LOOPBACK """ - UNKNOWN = 0 - ASLEEP = 10 - DISCONNECTED = 20 - DISCONNECTING = 30 - CONNECTING = 40 - CONNECTED_LOCAL = 50 - CONNECTED_SITE = 60 - GLOBAL = 70 + + ADSL = "adsl" + BLUETOOTH = "bluetooth" + BOND = "bond" + BRIDGE = "bridge" + CDMA = "cdma" + DUMMY = "dummy" + ETHERNET = "802-3-ethernet" + MODEM = "gsm" + INFINIBAND = "infiniband" + IP_TUNNEL = "ip-tunnel" + MACSEC = "macsec" + MACVLAN = "macvlan" + OLPC_MESH = "802-11-olpc-mesh" + OVS_BRIDGE = "ovs-bridge" + OVS_INTERFACE = "ovs-interface" + OVS_PORT = "ovs-port" + PPPOE = "pppoe" + SIXLOWPAN = "6lowpan" + TEAM = "team" + TUN = "tun" + VETH = "veth" + VLAN = "vlan" + VPN = "vpn" + VRF = "vrf" + VXLAN = "vxlan" + WIFI_P2P = "wifi-p2p" + WIREGUARD = "wireguard" + WIFI = "802-11-wireless" + WPAN = "wpan" + LOOPBACK = "loopback" diff --git a/sdbus_async/networkmanager/interfaces_devices.py b/sdbus_async/networkmanager/interfaces_devices.py index a111eea..e433e42 100644 --- a/sdbus_async/networkmanager/interfaces_devices.py +++ b/sdbus_async/networkmanager/interfaces_devices.py @@ -45,7 +45,8 @@ def name(self) -> str: def bt_capabilities(self) -> int: """Bluetooth device capabilities - See :py:class:`BluetoothCapabilities` + See :py:class:`BluetoothCapabilitiesFlags + `. """ raise NotImplementedError @@ -92,7 +93,8 @@ class NetworkManagerDeviceIPTunnelInterfaceAsync( def mode(self) -> int: """Tunnel mode - See :py:class:`IpTunnelMode` + See :py:class:`IpTunnelMode + `. """ raise NotImplementedError @@ -305,7 +307,8 @@ def modem_capabilities(self) -> int: Switching the radio technology might require firmware reboot. - See :py:class:`ModemCapabilities` + See :py:class:`ModemCapabilitiesFlags + `. """ raise NotImplementedError @@ -707,7 +710,8 @@ def perm_hw_address(self) -> str: def mode(self) -> int: """Operating mode of the device - See :py:class:`WiFiOperationMode` + See :py:class:`WiFiOperationMode + `. """ raise NotImplementedError @@ -730,7 +734,8 @@ def active_access_point(self) -> str: def wireless_capabilities(self) -> int: """List of wireless device capabilities - See :py:class:`WirelessCapabilities` + See :py:class:`WifiCapabilitiesFlags + `. """ raise NotImplementedError @@ -850,7 +855,8 @@ def firmware_version(self) -> str: def capabilities(self) -> int: """Capabilities of the device - See :py:class:`DeviceCapabilities` + See :py:class:`DeviceCapabilitiesFlags + `. """ raise NotImplementedError @@ -858,7 +864,8 @@ def capabilities(self) -> int: def state(self) -> int: """Device state. - See :py:class:`DeviceState` + See :py:class:`DeviceState + `. """ raise NotImplementedError @@ -866,7 +873,10 @@ def state(self) -> int: def state_reason(self) -> Tuple[int, int]: """Current state and the reason. - See :py:class:`DeviceState` and :py:class:`DeviceStateReason` + See :py:class:`DeviceState + ` and + :py:class:`DeviceStateReason + `. """ raise NotImplementedError @@ -938,7 +948,8 @@ def nm_plugin_missing(self) -> bool: def device_type(self) -> int: """Device type - See :py:class:`DeviceType` + See :py:class:`DeviceType + `. """ raise NotImplementedError @@ -961,7 +972,8 @@ def mtu(self) -> int: def metered(self) -> int: """Whether the traffic is subject to limitations - See :py:class:`DeviceMetered` + See :py:class:`DeviceMetered + `. """ raise NotImplementedError @@ -987,7 +999,8 @@ def real(self) -> bool: def ip4_connectivity(self) -> int: """IPv4 connectivity state - See :py:class:`ConnectivityState` + See :py:class:`ConnectivityState + `. """ raise NotImplementedError @@ -995,7 +1008,8 @@ def ip4_connectivity(self) -> int: def ip6_connectivity(self) -> int: """IPv6 connectivity state - See :py:class:`ConnectivityState` + See :py:class:`ConnectivityState + `. """ raise NotImplementedError @@ -1003,7 +1017,8 @@ def ip6_connectivity(self) -> int: def interface_flags(self) -> int: """Interface flags - See :py:class:`DeviceInterfaceFlags` + See :py:class:`DeviceInterfaceFlags + `. """ raise NotImplementedError @@ -1018,7 +1033,10 @@ def state_changed(self) -> Tuple[int, int, int]: Tuple of new state, old state and reason for new state. - See :py:class:`DeviceState` and :py:class:`DeviceStateReason` + See :py:class:`DeviceState + ` and + :py:class:`DeviceStateReason + `. """ raise NotImplementedError diff --git a/sdbus_async/networkmanager/interfaces_other.py b/sdbus_async/networkmanager/interfaces_other.py index 2a4c4af..2a38d67 100644 --- a/sdbus_async/networkmanager/interfaces_other.py +++ b/sdbus_async/networkmanager/interfaces_other.py @@ -41,7 +41,8 @@ class NetworkManagerAccessPointInterfaceAsync( def flags(self) -> int: """Flags describing capabilities of the point - See :py:class:`AccessPointCapabilities` + See :py:class:`WifiAccessPointCapabilitiesFlags + `. """ raise NotImplementedError @@ -49,7 +50,8 @@ def flags(self) -> int: def wpa_flags(self) -> int: """Flags WPA authentication and encryption - See :py:class:`WpaSecurityFlags` + See :py:class:`WifiAccessPointSecurityFlags + `. """ raise NotImplementedError @@ -57,7 +59,8 @@ def wpa_flags(self) -> int: def rsn_flags(self) -> int: """Flags describing RSN (Robust Secure Network) capabilities - See :py:class:`WpaSecurityFlags` + See :py:class:`WifiAccessPointSecurityFlags + `. """ raise NotImplementedError @@ -80,7 +83,8 @@ def hw_address(self) -> str: def mode(self) -> int: """Mode of operation of access point - See :py:class:`WiFiOperationMode` + See :py:class:`WiFiOperationMode + `. """ raise NotImplementedError @@ -127,7 +131,8 @@ async def register_with_capabilities( ) -> None: """Same as register() but with agent capabilities - See :py:class:`SecretAgentCapabilities` + See :py:class:`SecretAgentCapabilitiesFlags + `. """ raise NotImplementedError @@ -202,7 +207,8 @@ def devices(self) -> List[str]: def state(self) -> int: """Connection state - See :py:class:`ConnectionState` + See :py:class:`ActiveConnectionState + `. """ raise NotImplementedError @@ -210,7 +216,8 @@ def state(self) -> int: def state_flags(self) -> int: """Connection state flags - See :py:class:`ConnectionStateFlags` + See :py:class:`ActivationStateFlags + `. """ raise NotImplementedError @@ -270,7 +277,10 @@ def master(self) -> str: def state_changed(self) -> Tuple[int, int]: """Signal of the new state and the reason - See :py:class:`ConnectionState` and :py:class:`ConnectionStateReason` + See :py:class:`ActiveConnectionState + ` + and :py:class:`ActiveConnectionStateReason + `. """ raise NotImplementedError @@ -284,7 +294,8 @@ class NetworkManagerVPNConnectionInterfaceAsync( def vpn_state(self) -> int: """VPN connection state - See :py:class:`ConnectionState` + See :py:class:`VpnConnectionState + `. """ raise NotImplementedError @@ -298,7 +309,10 @@ def vpn_state_changed(self) -> Tuple[int, int]: """Signal when VPN state changed Tuple of new state and reason. - See :py:class:`ConnectionState` and :py:class:`ConnectionStateReason` + See :py:class:`VpnConnectionState + ` + and :py:class:`VpnConnectionStateReason + `. """ raise NotImplementedError @@ -595,7 +609,8 @@ def unsaved(self) -> bool: def flags(self) -> int: """Connection flags - See :py:class:`ConnectionFlags` + See :py:class:`SettingsConnectionFlags + `. """ raise NotImplementedError @@ -909,7 +924,8 @@ async def new_secrets( def state(self) -> int: """VPN state - See :py:class:`VpnState` + See :py:class:`VpnServiceState + `. """ raise NotImplementedError @@ -917,7 +933,8 @@ def state(self) -> int: def state_changed(self) -> int: """Signal when VPN state changed with new VPN state. - See :py:class:`VpnState` + See :py:class:`VpnServiceState + `. """ raise NotImplementedError @@ -950,7 +967,8 @@ def login_banner(self) -> str: def failure(self) -> int: """Signal when VPN failure occurs - See :py:class:`VpnFailure` + See :py:class:`VpnFailure + `. """ raise NotImplementedError @@ -969,7 +987,8 @@ def name(self) -> str: def flags(self) -> int: """Flags describing capabilities of the point - See :py:class:`AccessPointCapabilities` + See :py:class:`WifiAccessPointCapabilitiesFlags + `. """ raise NotImplementedError @@ -1024,14 +1043,13 @@ async def reload( ) -> None: """Reload NetworkManager configuration - Flags control what to reload: + Flags control what to reload. - * 0x0 everything - * 0x1 NetworkManager.conf - * 0x2 DNS configuration - * 0x4 Restart DNS plugin + Use :py:class:`NetworkManagerReloadFlags + ` + to create flags. - :param flags: Reload what? + :param flags: What to reload. """ raise NotImplementedError @@ -1166,7 +1184,8 @@ async def check_connectivity( ) -> int: """Get current connectivity state - See :py:class:`NetworkManagerConnectivityState` + See :py:class:`ConnectivityState + `. """ raise NotImplementedError @@ -1179,7 +1198,8 @@ async def get_state( ) -> int: """Get current NetworkManager state - See :py:class:`NetworkManagerState` + See :py:class:`NetworkManagerState + `. """ raise NotImplementedError @@ -1290,7 +1310,8 @@ def primary_connection_type(self) -> str: def metered(self) -> int: """Primary connection metered status - See :py:class:`DeviceMetered` + See :py:class:`DeviceMetered + `. """ raise NotImplementedError @@ -1322,7 +1343,8 @@ def capabilities(self) -> List[int]: def state(self) -> int: """Overall state of NetworkManager - See :py:class:`NetworkManagerState` + See :py:class:`NetworkManagerState + `. """ raise NotImplementedError @@ -1330,7 +1352,8 @@ def state(self) -> int: def connectivity(self) -> int: """Overall state of connectivity - See :py:class:`NetworkManagerConnectivityState` + See :py:class:`ConnectivityState + `. """ raise NotImplementedError @@ -1365,7 +1388,8 @@ def check_permissions(self) -> None: def state_changed(self) -> int: """NetworkManager state changed - See :py:class:`NetworkManagerState` + See :py:class:`NetworkManagerState + `. """ raise NotImplementedError diff --git a/sdbus_block/networkmanager/__init__.py b/sdbus_block/networkmanager/__init__.py index dbd8dcf..6b06a65 100644 --- a/sdbus_block/networkmanager/__init__.py +++ b/sdbus_block/networkmanager/__init__.py @@ -20,30 +20,43 @@ from __future__ import annotations from .enums import ( - AccessPointCapabilities, - BluetoothCapabilities, - ConnectionFlags, - ConnectionState, - ConnectionStateFlags, - ConnectionStateReason, + ActivationStateFlags, + ActiveConnectionState, + ActiveConnectionStateReason, + BluetoothCapabilitiesFlags, + CheckpointCreateFlags, + CheckpointRollbackResult, + ConnectionMultiConnect, ConnectionType, ConnectivityState, - DeviceCapabilities, + DeviceCapabilitiesFlags, DeviceInterfaceFlags, DeviceMetered, + DeviceReapplyFlags, DeviceState, DeviceStateReason, DeviceType, IpTunnelMode, - ModemCapabilities, - NetworkManagerConnectivityState, + ModemCapabilitiesFlags, + MptcpFlags, + NetworkManagerCapabilitiesFlags, + NetworkManagerReloadFlags, NetworkManagerState, - SecretAgentCapabilities, + RadioFlags, + SecretAgentCapabilitiesFlags, + SecretAgentGetSecretsFlags, + SettingsAddConnection2Flags, + SettingsConnectionFlags, + SettingsUpdate2Flags, + VpnConnectionState, + VpnConnectionStateReason, VpnFailure, - VpnState, + VpnServiceState, + WifiAccessPointCapabilitiesFlags, + WifiAccessPointSecurityFlags, + WifiCapabilitiesFlags, WiFiOperationMode, - WirelessCapabilities, - WpaSecurityFlags, + WimaxNSPNetworkType, ) from .exceptions import ( NetworkManagerAlreadyAsleepOrAwakeError, @@ -218,30 +231,43 @@ __all__ = ( # .enums - 'AccessPointCapabilities', - 'BluetoothCapabilities', - 'ConnectionFlags', - 'ConnectionState', - 'ConnectionStateFlags', - 'ConnectionStateReason', + 'ActivationStateFlags', + 'ActiveConnectionState', + 'ActiveConnectionStateReason', + 'BluetoothCapabilitiesFlags', + 'CheckpointCreateFlags', + 'CheckpointRollbackResult', + 'ConnectionMultiConnect', 'ConnectionType', 'ConnectivityState', - 'DeviceCapabilities', + 'DeviceCapabilitiesFlags', 'DeviceInterfaceFlags', 'DeviceMetered', + 'DeviceReapplyFlags', 'DeviceState', 'DeviceStateReason', 'DeviceType', 'IpTunnelMode', - 'ModemCapabilities', - 'NetworkManagerConnectivityState', + 'ModemCapabilitiesFlags', + 'MptcpFlags', + 'NetworkManagerCapabilitiesFlags', + 'NetworkManagerReloadFlags', 'NetworkManagerState', - 'SecretAgentCapabilities', + 'RadioFlags', + 'SecretAgentCapabilitiesFlags', + 'SecretAgentGetSecretsFlags', + 'SettingsAddConnection2Flags', + 'SettingsConnectionFlags', + 'SettingsUpdate2Flags', + 'VpnConnectionState', + 'VpnConnectionStateReason', 'VpnFailure', - 'VpnState', + 'VpnServiceState', + 'WifiAccessPointCapabilitiesFlags', + 'WifiAccessPointSecurityFlags', + 'WifiCapabilitiesFlags', 'WiFiOperationMode', - 'WirelessCapabilities', - 'WpaSecurityFlags', + 'WimaxNSPNetworkType', # .exceptions 'NetworkManagerAlreadyAsleepOrAwakeError', 'NetworkManagerAlreadyEnabledOrDisabledError', From 1c80ffb1d80c91c68d9dc487b62ee8c9d1f8c1ce Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 20 Nov 2023 00:37:27 +0600 Subject: [PATCH 72/80] Update readthedocs configuration to recent changes Copy pasted from the working sdbus configuration. --- .readthedocs.yml | 17 ++++++++++++++--- docs/conf.py | 3 ++- docs/requirements.txt | 4 ++++ requirements.txt | 1 - 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 docs/requirements.txt delete mode 100644 requirements.txt diff --git a/.readthedocs.yml b/.readthedocs.yml index f5fcf5d..327f8d4 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,6 +1,17 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright (C) 2023 igo95862 +--- + version: 2 +build: + os: "ubuntu-22.04" + tools: + python: "3.9" + +sphinx: + configuration: "docs/conf.py" + python: - version: 3.8 - install: - - requirements: requirements.txt + install: + - requirements: docs/requirements.txt diff --git a/docs/conf.py b/docs/conf.py index 62ae238..7c1a777 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -# Copyright (C) 2020, 2021 igo95862 +# Copyright (C) 2020-2023 igo95862 # This file is part of python-sdbus @@ -24,6 +24,7 @@ author = 'igo95862' source_suffix = '.rst' extensions = ['sdbus.autodoc'] +html_theme = "sphinx_rtd_theme" autoclass_content = 'both' autodoc_typehints = 'description' diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..7c490fe --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright (C) 2023 igo95862 +sphinx_rtd_theme +sdbus>=0.10.2 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index c64eda8..0000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -sdbus>=0.10.2 From de2cf89f027f09d6352163bc75854517fe57e59c Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 25 Nov 2023 14:53:37 +0600 Subject: [PATCH 73/80] docs: Fix enums example using outdated WifiCapabilities name The new name is WifiCapabilitiesFlags. Also add a link to the enums themselves. --- docs/enums.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/enums.rst b/docs/enums.rst index 90a8cc4..10a5d60 100644 --- a/docs/enums.rst +++ b/docs/enums.rst @@ -5,10 +5,11 @@ Python's Enum quick intro ------------------------- There are two types of enums. ``IntEnum`` is used for a discrete values -and ``IntFlag`` is used for bit flags. For example, ``DeviceType`` identifies -a single device type as a device cannot be of multiple types. -``WifiCapabilities`` shows a particular Wifi device capabilities which it -can have multiple, for example, supporting both 5GHz and 2.4GHz radio bands. +and ``IntFlag`` is used for bit flags. For example, :py:class:`DeviceType ` +identifies a single device type as a device cannot be of multiple types. +:py:class:`WifiCapabilitiesFlags ` +shows a particular Wifi device capabilities which it can have multiple, for example, supporting +both 5GHz and 2.4GHz radio bands. Usually ``IntEnum`` is implied unless the enum's name ends with ``Flag``. @@ -16,19 +17,19 @@ Example code using enums: .. code-block:: python - from sdbus_async.networkmanager.enums import DeviceType, WifiCapabilities + from sdbus_async.networkmanager.enums import DeviceType, WifiCapabilitiesFlags # Get particular device type from an integer DeviceType(2) == DeviceType.WIFI # Returns: True # Check if a specific flag is enabled - WifiCapabilities.FREQ_2GHZ in WifiCapabilities(0x00000400 | 0x00000200) + WifiCapabilitiesFlags.FREQ_2GHZ in WifiCapabilitiesFlags(0x00000400 | 0x00000200) # Returns: True # Iterate over all enabled flags - list(WifiCapabilities(0x00000400 | 0x00000200)) - # Returns: [, ] + list(WifiCapabilitiesFlags(0x00000400 | 0x00000200)) + # Returns: [, ] `See Python's standard library documentation for more detailed tutorial and API reference. `_ From 21a95dddead60ade1d6ed574f02de74cb5f7c735 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 25 Nov 2023 17:03:26 +0600 Subject: [PATCH 74/80] docs: Create a quickstart guide It explains the basic objects used in the NetworkManager. --- docs/index.rst | 1 + docs/quickstart.rst | 100 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 docs/quickstart.rst diff --git a/docs/index.rst b/docs/index.rst index e7c9bfd..7fc3c5f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,6 +13,7 @@ of `NetworkManager `_. :maxdepth: 3 :caption: Contents: + quickstart objects examples device_interfaces diff --git a/docs/quickstart.rst b/docs/quickstart.rst new file mode 100644 index 0000000..a145050 --- /dev/null +++ b/docs/quickstart.rst @@ -0,0 +1,100 @@ +NetworkManager D-Bus API quickstart +=================================== + +This is a tutorial to understand the structure of the NetworkManager +D-Bus API and how to use it. + +.. note:: + + NetworkManager usually uses the system D-Bus, however, sdbus uses the session + D-Bus by default. It is recommend to call ``sdbus.set_default_bus(sdbus.sd_bus_open_system())`` + to set the system bus as default bus. + +NetworkManager main object +-------------------------- + +This is a static object that contains information about +entire state of NetworkManager. The Python class +:py:class:`NetworkManager ` +has a predefined service name and object path. + +.. code-block:: python + + import sdbus + from sdbus_block.networkmanager import NetworkManager + + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + network_manager = NetworkManager() + +Devices +------- + +Every device object represents a network device. Device object has a generic +methods and properties that are universal across all device types and +a type specific methods. The :py:class:`NetworkDeviceGeneric +` implements generic methods +and, for example, :py:class:`NetworkDeviceWireless ` +adds Wi-Fi specific methods. + +The :py:attr:`device_type ` +property and enum :py:class:`DeviceType ` +can be used to determine particular type of a device. + +.. code-block:: python + + from sdbus_block.networkmanager import NetworkDeviceGeneric, NetworkDeviceWireless + from sdbus_block.networkmanager.enums import DeviceType + + all_devices = {path: NetworkDeviceGeneric(path) for path in network_manager.devices} + + wifi_devices = [ + NetworkDeviceWireless(path) + for path, device in all_devices.items() + if device.device_type == DeviceType.WIFI + ] + +Connection +---------- + +Connection represents a configuration containing an IP address, Wifi password, +proxy settings and etc... The main object to access connections is the +:py:class:`NetworkManagerSettings ` +which has predefined object path. + +Each individual connection has a separate path which can be accessed with +:py:class:`NetworkConnectionSettings ` +class. + +.. code-block:: python + + from sdbus_block.networkmanager import NetworkManagerSettings + + networwork_manager_settings = NetworkManagerSettings() + + all_connections = [NetworkConnectionSettings(x) for x in networwork_manager_settings.connections] + +The actual connection settings are represented by a complex double nested dictionary +of D-Bus variants. For convenience a `dataclass `_ +based helper is provided. + +The :py:meth:`get_profile ` +and :py:meth:`update_profile ` +are two main methods to interact with connection settings helper. + +.. code-block:: python + + connection = all_connections[0] + setting_dataclass = connection.get_profile() + print("uuid:", profile.connection.uuid) + +Active Connection +----------------- + +:py:class:`ActiveConnection ` +is a product of a Connection being applied to a Device. + +For example, :py:meth:`activate_connection ` +of the main NetworkManager object will create new Active Connection +(therefore configuring network on a device) and return its path. +The :py:meth:`deactivate_connection ` +will remove the active connection and remove the device's network configuration. From 709b8d30809c858a242d764fa44ec9c3d495bdaf Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sat, 25 Nov 2023 17:11:12 +0600 Subject: [PATCH 75/80] Added quickstart link to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0522dbb..56e02f9 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ See [python-sdbus requirements](https://github.com/igo95862/python-sdbus#require # [Documentation](https://python-sdbus-networkmanager.readthedocs.io/en/latest/) +See [this quickstart guide for brief introduction to NetworkManager D-Bus API](https://python-sdbus-networkmanager.readthedocs.io/en/latest/quickstart.html). + This is the sub-project of [python-sdbus](https://github.com/igo95862/python-sdbus). See the [python-sdbus documentation](https://python-sdbus.readthedocs.io/en/latest/). From 76b9141b3e4a5dc169ec8c27c63a91d9b09029b5 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 12 Feb 2024 00:25:43 +0600 Subject: [PATCH 76/80] Separate examples by versions While the master branch undergoing version 3.0.0 development people will try to run the examples on PyPI version and fail. Separating them by version will hopefully make it very apparent which version the examples should be run against. --- .../async/add-eth-connection-async.py | 0 .../async/add-openvpn-connection-async.py | 0 .../async/add-wifi-psk-connection-async.py | 0 .../async/delete-connection-by-uuid-async.py | 0 examples/2.0.0/async/device-state-async.py | 74 ++++++++++ .../async/list-connections-async.py | 0 .../{ => 2.0.0}/async/netdevinfo-async.py | 0 .../async/update-connection-async.py | 0 .../{ => 2.0.0}/block/add-eth-connection.py | 0 .../block/add-wifi-psk-connection.py | 0 .../block/delete-connection-by-uuid.py | 0 examples/2.0.0/block/device-state.py | 74 ++++++++++ .../{ => 2.0.0}/block/list-connections.py | 0 examples/{ => 2.0.0}/block/netdevinfo.py | 0 .../{ => 2.0.0}/block/update-connection.py | 0 .../dev/async/add-eth-connection-async.py | 108 ++++++++++++++ .../dev/async/add-openvpn-connection-async.py | 135 +++++++++++++++++ .../async/add-wifi-psk-connection-async.py | 137 ++++++++++++++++++ .../async/delete-connection-by-uuid-async.py | 41 ++++++ .../{ => dev}/async/device-state-async.py | 0 examples/dev/async/list-connections-async.py | 61 ++++++++ examples/dev/async/netdevinfo-async.py | 119 +++++++++++++++ examples/dev/async/update-connection-async.py | 67 +++++++++ examples/dev/block/add-eth-connection.py | 107 ++++++++++++++ examples/dev/block/add-wifi-psk-connection.py | 124 ++++++++++++++++ .../dev/block/delete-connection-by-uuid.py | 40 +++++ examples/{ => dev}/block/device-state.py | 0 examples/dev/block/list-connections.py | 59 ++++++++ examples/dev/block/netdevinfo.py | 112 ++++++++++++++ examples/dev/block/update-connection.py | 48 ++++++ 30 files changed, 1306 insertions(+) rename examples/{ => 2.0.0}/async/add-eth-connection-async.py (100%) rename examples/{ => 2.0.0}/async/add-openvpn-connection-async.py (100%) rename examples/{ => 2.0.0}/async/add-wifi-psk-connection-async.py (100%) rename examples/{ => 2.0.0}/async/delete-connection-by-uuid-async.py (100%) create mode 100755 examples/2.0.0/async/device-state-async.py rename examples/{ => 2.0.0}/async/list-connections-async.py (100%) rename examples/{ => 2.0.0}/async/netdevinfo-async.py (100%) rename examples/{ => 2.0.0}/async/update-connection-async.py (100%) rename examples/{ => 2.0.0}/block/add-eth-connection.py (100%) rename examples/{ => 2.0.0}/block/add-wifi-psk-connection.py (100%) rename examples/{ => 2.0.0}/block/delete-connection-by-uuid.py (100%) create mode 100755 examples/2.0.0/block/device-state.py rename examples/{ => 2.0.0}/block/list-connections.py (100%) rename examples/{ => 2.0.0}/block/netdevinfo.py (100%) rename examples/{ => 2.0.0}/block/update-connection.py (100%) create mode 100755 examples/dev/async/add-eth-connection-async.py create mode 100755 examples/dev/async/add-openvpn-connection-async.py create mode 100755 examples/dev/async/add-wifi-psk-connection-async.py create mode 100755 examples/dev/async/delete-connection-by-uuid-async.py rename examples/{ => dev}/async/device-state-async.py (100%) create mode 100755 examples/dev/async/list-connections-async.py create mode 100755 examples/dev/async/netdevinfo-async.py create mode 100755 examples/dev/async/update-connection-async.py create mode 100755 examples/dev/block/add-eth-connection.py create mode 100755 examples/dev/block/add-wifi-psk-connection.py create mode 100755 examples/dev/block/delete-connection-by-uuid.py rename examples/{ => dev}/block/device-state.py (100%) create mode 100755 examples/dev/block/list-connections.py create mode 100755 examples/dev/block/netdevinfo.py create mode 100644 examples/dev/block/update-connection.py diff --git a/examples/async/add-eth-connection-async.py b/examples/2.0.0/async/add-eth-connection-async.py similarity index 100% rename from examples/async/add-eth-connection-async.py rename to examples/2.0.0/async/add-eth-connection-async.py diff --git a/examples/async/add-openvpn-connection-async.py b/examples/2.0.0/async/add-openvpn-connection-async.py similarity index 100% rename from examples/async/add-openvpn-connection-async.py rename to examples/2.0.0/async/add-openvpn-connection-async.py diff --git a/examples/async/add-wifi-psk-connection-async.py b/examples/2.0.0/async/add-wifi-psk-connection-async.py similarity index 100% rename from examples/async/add-wifi-psk-connection-async.py rename to examples/2.0.0/async/add-wifi-psk-connection-async.py diff --git a/examples/async/delete-connection-by-uuid-async.py b/examples/2.0.0/async/delete-connection-by-uuid-async.py similarity index 100% rename from examples/async/delete-connection-by-uuid-async.py rename to examples/2.0.0/async/delete-connection-by-uuid-async.py diff --git a/examples/2.0.0/async/device-state-async.py b/examples/2.0.0/async/device-state-async.py new file mode 100755 index 0000000..d55e36b --- /dev/null +++ b/examples/2.0.0/async/device-state-async.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to list the network devices including type, state, internet +# connectivitycheck state and the identifier of the active connection. +# +# NetworkDeviceGeneric/org.freedesktop.NetworkManager.Device is described at +# https://networkmanager.dev/docs/api/latest/ref-dbus-devices.html +# +# The output resembles the output of the NM CLI command "nmcli device": +# +# Interface Type State Internet Connection +# lo Generic Unmanaged Unknown +# wlp0s20f3 Wifi Activated Full Wolke7 [primary connection] +# docker0 Bridge Activated None docker0 +# enx0c3796090408 Ethernet Activated Full enx0c3796090408 +# p2p-dev-wlp0s20f3 Wifi_P2P Disconnected None + +import argparse +import asyncio +import sdbus +from sdbus_async.networkmanager import ( + NetworkManager, + NetworkDeviceGeneric, + DeviceState, + DeviceType, + DeviceCapabilities as Capabilities, + ActiveConnection, + ConnectivityState, +) +from enum import Enum + + +def title(enum: Enum) -> str: + """Get the name of an enum: 1st character is uppercase, rest lowercase""" + return enum.name.title() + + +async def list_active_hardware_networkdevice_states(only_hw: bool) -> None: + """Print the list of activated network devices similar to nmcli device""" + nm = NetworkManager() + devices_paths = await nm.get_devices() + + print("Interface Type State Internet Connection") + for device_path in devices_paths: + generic = NetworkDeviceGeneric(device_path) + + # Demonstrates an enum to match devices using capabilities: + if only_hw and await generic.capabilities & Capabilities.IS_SOFTWARE: + continue + + # Create the strings for the columns using the names of the enums: + dev: str = await generic.interface + dtype = title(DeviceType(await generic.device_type)) + state = title(DeviceState(await generic.state)) + connectivity = title(ConnectivityState(await generic.ip4_connectivity)) + + name: str = "" + if await generic.active_connection != "/": # Connection is active + # ActiveConnection() gets propertites from active connection path: + active_conn = ActiveConnection(await generic.active_connection) + name = await active_conn.id + if await active_conn.default: + name += " [primary connection]" + + print(f"{dev:<17} {dtype:<8} {state:<12} {connectivity:<8} {name:<14}") + + +if __name__ == "__main__": + p = argparse.ArgumentParser() + p.add_argument("--hw", action="store_true", dest="only_hw", help="Only HW") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + asyncio.run(list_active_hardware_networkdevice_states(args.only_hw)) diff --git a/examples/async/list-connections-async.py b/examples/2.0.0/async/list-connections-async.py similarity index 100% rename from examples/async/list-connections-async.py rename to examples/2.0.0/async/list-connections-async.py diff --git a/examples/async/netdevinfo-async.py b/examples/2.0.0/async/netdevinfo-async.py similarity index 100% rename from examples/async/netdevinfo-async.py rename to examples/2.0.0/async/netdevinfo-async.py diff --git a/examples/async/update-connection-async.py b/examples/2.0.0/async/update-connection-async.py similarity index 100% rename from examples/async/update-connection-async.py rename to examples/2.0.0/async/update-connection-async.py diff --git a/examples/block/add-eth-connection.py b/examples/2.0.0/block/add-eth-connection.py similarity index 100% rename from examples/block/add-eth-connection.py rename to examples/2.0.0/block/add-eth-connection.py diff --git a/examples/block/add-wifi-psk-connection.py b/examples/2.0.0/block/add-wifi-psk-connection.py similarity index 100% rename from examples/block/add-wifi-psk-connection.py rename to examples/2.0.0/block/add-wifi-psk-connection.py diff --git a/examples/block/delete-connection-by-uuid.py b/examples/2.0.0/block/delete-connection-by-uuid.py similarity index 100% rename from examples/block/delete-connection-by-uuid.py rename to examples/2.0.0/block/delete-connection-by-uuid.py diff --git a/examples/2.0.0/block/device-state.py b/examples/2.0.0/block/device-state.py new file mode 100755 index 0000000..2070072 --- /dev/null +++ b/examples/2.0.0/block/device-state.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to list the network devices including type, state, internet +# connectivitycheck state and the identifier of the active connection. +# +# NetworkDeviceGeneric/org.freedesktop.NetworkManager.Device is described at +# https://networkmanager.dev/docs/api/latest/ref-dbus-devices.html +# +# The output resembles the output of the NM CLI command "nmcli device": +# +# Interface Type State Internet Connection +# lo Generic Unmanaged Unknown +# wlp0s20f3 Wifi Activated Full Wolke7 [primary connection] +# docker0 Bridge Activated None docker0 +# enx0c3796090408 Ethernet Activated Full enx0c3796090408 +# p2p-dev-wlp0s20f3 Wifi_P2P Disconnected None + +import argparse +import sdbus +from sdbus_block.networkmanager import ( + NetworkManager, + NetworkDeviceGeneric, + DeviceState, + DeviceType, + DeviceCapabilities as Capabilities, + ActiveConnection, + ConnectivityState, +) +from enum import Enum + + +def title(enum: Enum) -> str: + """Get the name of an enum: 1st character is uppercase, rest lowercase""" + return enum.name.title() + + +def list_active_hardware_networkdevice_states(only_hw: bool) -> None: + """Print the list of activated network devices similar to nmcli device""" + nm = NetworkManager() + devices_paths = nm.get_devices() + + print("Interface Type State Internet Connection") + for device_path in devices_paths: + generic_dev = NetworkDeviceGeneric(device_path) + + # Demonstrates an enum to match devices using capabilities: + if only_hw and generic_dev.capabilities & Capabilities.IS_SOFTWARE: + continue + + # Create the strings for the columns using the names of the enums: + dev = generic_dev.interface + type = title(DeviceType(generic_dev.device_type)) + state = title(DeviceState(generic_dev.state)) + connectivity = title(ConnectivityState(generic_dev.ip4_connectivity)) + + if generic_dev.active_connection == "/": # No active connection + id = "" + else: + # ActiveConnection() gets propertites from active connection path: + active_connection = ActiveConnection(generic_dev.active_connection) + id = active_connection.id + if active_connection.default: + id += " [primary connection]" + + print(f"{dev:<17} {type:<8} {state:<12} {connectivity:<8} {id:<14}") + + +if __name__ == "__main__": + p = argparse.ArgumentParser() + p.add_argument("--hw", action="store_true", dest="only_hw", help="Only HW") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + list_active_hardware_networkdevice_states(args.only_hw) diff --git a/examples/block/list-connections.py b/examples/2.0.0/block/list-connections.py similarity index 100% rename from examples/block/list-connections.py rename to examples/2.0.0/block/list-connections.py diff --git a/examples/block/netdevinfo.py b/examples/2.0.0/block/netdevinfo.py similarity index 100% rename from examples/block/netdevinfo.py rename to examples/2.0.0/block/netdevinfo.py diff --git a/examples/block/update-connection.py b/examples/2.0.0/block/update-connection.py similarity index 100% rename from examples/block/update-connection.py rename to examples/2.0.0/block/update-connection.py diff --git a/examples/dev/async/add-eth-connection-async.py b/examples/dev/async/add-eth-connection-async.py new file mode 100755 index 0000000..f7be36f --- /dev/null +++ b/examples/dev/async/add-eth-connection-async.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new Ethernet network connection profile: +# +# examples/block/add-eth-connection-async.py --help +# usage: add-eth-connection-async.py [-h] [-c CONN_ID] [-u UUID] [-4 IP4] +# [-i INTERFACE_NAME] [-g GW] [-a] [--save] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -i INTERFACE_NAME ethX device +# -4 IP4 IP4/prefix +# -g GW gw/metric +# -a autoconnect +# --save Save +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html + +import asyncio +import sdbus +import functools +import logging +import pprint +import sys +from uuid import uuid4 +from argparse import ArgumentParser, Namespace +from sdbus_async.networkmanager import NetworkManagerSettings +from sdbus_async.networkmanager import NetworkManagerConnectionProperties + + +async def add_ethernet_connection_async(args: Namespace) -> str: + """Add a (by default) temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info + + # If we add many connections using the same id, things get messy. Check: + if await NetworkManagerSettings().get_connections_by_id(args.conn_id): + info(f'Connections using ID "{args.conn_id}" exist, remove them:') + info(f'Run: nmcli connection delete "{args.conn_id}"') + return "" + + ipaddr, prefix = args.ip4.split("/") + properties: NetworkManagerConnectionProperties = { + "connection": { + "id": ("s", args.conn_id), + "uuid": ("s", str(args.uuid)), + "type": ("s", "802-3-ethernet"), + "autoconnect": ("b", args.auto), + }, + "ipv4": { + "method": ("s", "manual"), + "address-data": ( + "aa{sv}", + [ + { + "address": ("s", ipaddr), + "prefix": ("u", int(prefix)), + }, + ], + ), + }, + "ipv6": {"method": ("s", "disabled")}, + } + if args.interface_name: + properties["connection"]["interface-name"] = ("s", args.interface_name) + if len(sys.argv) == 1 or args.gw != "192.0.2.1/4000": + default_gateway, route_metric = args.gw.split("/") + properties["ipv4"]["gateway"] = ("s", default_gateway) + properties["ipv4"]["route-metric"] = ("u", int(route_metric)) + + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(properties) + created = "created and saved" if args.save else "created" + + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("-i", dest="interface_name", default="", help="ethX device") + p.add_argument("-4", dest="ip4", default="192.0.2.8/24", help="IP4/prefix") + p.add_argument("-g", dest="gw", default="192.0.2.1/4000", help="gw/metric") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := asyncio.run(add_ethernet_connection_async(args)): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/dev/async/add-openvpn-connection-async.py b/examples/dev/async/add-openvpn-connection-async.py new file mode 100755 index 0000000..4200ebd --- /dev/null +++ b/examples/dev/async/add-openvpn-connection-async.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new VPN network connection profile. Currently supported only with tls-auth +# +# $ examples/async/add-openvpn-connection-async.py --help +# usage: add-openvpn-connection.py [-h] [-c CONN_ID] [-d DEV] [--remote REMOTE] [--remote-cert-tls] [-a] [--save] +# [--ca, CA_PATH] [--cert, CERT_PATH] [--key, KEY_path] [--ta, TA_PATH] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -f OVPN .ovpn connection file +# -a autoconnect +# --save Save +# --ca Path to CA file +# --cert Path to cert file +# --key Path to key file +# --ta Path to tls-auth file +# +# $ add-vpn-connection.py +# New unsaved connection profile created, show it with: +# nmcli connection show "MyConnectionExample"|grep -v -e -- -e default +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Note: By default, it uses add_connection_unsaved() to add a temporary +# memory-only connection which is not saved to the system-connections folder: +# For reference, see: https://networkmanager.dev/docs/api/latest/spec.html +# -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) + +import asyncio +import functools +import logging +import sdbus +from uuid import uuid4 +from argparse import ArgumentParser +from pprint import pformat +from sdbus_async.networkmanager import ( + NetworkManagerSettings as SettingsManager, + ConnectionType, +) +from sdbus_async.networkmanager.settings import ( + ConnectionProfile, + ConnectionSettings, + Ipv4Settings, + Ipv6Settings, + VpnSettings +) + + +async def add_vpn_connection_async(conn_id: str, + dev: str, + remote: str, + remote_cert_tls: str, + uuid, + auto: bool, + save: bool, + ca: str, + cert: str, + key: str, + ta: str) -> str: + # Add a temporary (not yet saved) network connection profile + # param Namespace args: dev, remote, remote_cert_tls, ca_path, cert_path, key_path, ta_path + # return: dbus connection path of the created connection profile + + info = logging.getLogger().info + + # If we add many connections passing the same id, things get messy. Check: + if await SettingsManager().get_connections_by_id(conn_id): + print(f'Connection "{conn_id}" exists, remove it first') + print(f'Run: nmcli connection delete "{conn_id}"') + return "" + + profile = ConnectionProfile( + connection=ConnectionSettings( + connection_id=conn_id, + uuid=str(uuid), + connection_type=ConnectionType.VPN.value, + autoconnect=bool(auto), + ), + ipv4=Ipv4Settings(method="auto"), + ipv6=Ipv6Settings(method="auto"), + vpn=VpnSettings(data={ + 'ca': ca, + 'cert': cert, + 'cert-pass-flags': '0', + 'connection-type': 'tls', + 'dev': dev, + 'key': key, + 'remote': remote, + 'remote-cert-tls': remote_cert_tls, + 'ta': ta, + 'ta-dir': '1' + }, service_type='org.freedesktop.NetworkManager.openvpn') + ) + + s = SettingsManager() + save = bool(save) + addconnection = s.add_connection if save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(profile.to_dbus()) + created = "created and saved" if save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pformat, sort_dicts=False)(profile.to_settings_dict())) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("--dev", dest="dev", default="tun", help="VPN Dev") + p.add_argument("--remote", dest="remote", default="example.com:443:tcp", help="VPN Remote") + p.add_argument("--remote-cert-tls", dest="remote_cert_tls", default="server", help="VPN Remote cert tls") + p.add_argument("--ca", dest="ca", required=True, help="VPN CA file path") + p.add_argument("--cert", dest="cert", required=True, help="VPN cert file path") + p.add_argument("--key", dest="key", required=True, help="VPN key file path") + p.add_argument("--ta", dest="ta", required=True, help="VPN TA file path") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := asyncio.run(add_vpn_connection_async(**vars(args))): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/dev/async/add-wifi-psk-connection-async.py b/examples/dev/async/add-wifi-psk-connection-async.py new file mode 100755 index 0000000..fb9022a --- /dev/null +++ b/examples/dev/async/add-wifi-psk-connection-async.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new WiFi-PSK network connection profile: +# +# $ examples/async/add-wifi-psk-connection-async.py --help +# usage: add-wifi-psk-connection.py [-h] [-c CONN_ID] [-s SSID] [-p PSK] +# [-i INTERFACE_NAME] [-a] [--save] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -s SSID WiFi SSID +# -p PSK WiFi PSK +# -i INTERFACE_NAME WiFi device +# -a autoconnect +# --save Save +# +# $ add-wifi-psk-connection.py +# New unsaved connection profile created, show it with: +# nmcli connection show "MyConnectionExample"|grep -v -e -- -e default +# Settings used: +# {'connection': {'id': ('s', 'MyConnectionExample'), +# 'uuid': ('s', '90e3bcc8-d3a5-4725-a363-abb788fd47bf'), +# 'type': ('s', '802-11-wireless'), +# 'autoconnect': ('b', False)}, +# '802-11-wireless': {'mode': ('s', 'infrastructure'), +# 'security': ('s', '802-11-wireless-security'), +# 'ssid': ('ay', b'CafeSSID')}, +# '802-11-wireless-security': {'key-mgmt': ('s', 'wpa-psk'), +# 'auth-alg': ('s', 'open'), +# 'psk': ('s', 'Coffee!!')}, +# 'ipv4': {'method': ('s', 'auto')}, +# 'ipv6': {'method': ('s', 'auto')}} +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Note: By default, it uses add_connection_unsaved() to add a temporary +# memory-only connection which is not saved to the system-connections folder: +# For reference, see: https://networkmanager.dev/docs/api/latest/spec.html +# -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) + +import asyncio +import binascii +import functools +import logging +import sdbus +from uuid import uuid4 +from argparse import ArgumentParser, Namespace +from passlib.utils.pbkdf2 import pbkdf2 # type: ignore +from pprint import pformat +from sdbus_async.networkmanager import ( + NetworkManagerSettings as SettingsManager, + ConnectionType, +) +from sdbus_async.networkmanager.settings import ( + ConnectionProfile, + ConnectionSettings, + Ipv4Settings, + Ipv6Settings, + WirelessSettings, + WirelessSecuritySettings, +) + + +async def add_wifi_psk_connection_async(args: Namespace) -> str: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info + + # If we add many connections passing the same id, things get messy. Check: + if await SettingsManager().get_connections_by_id(args.conn_id): + print(f'Connection "{args.conn_id}" exists, remove it first') + print(f'Run: nmcli connection delete "{args.conn_id}"') + return "" + + if args.key_mgmt == "wpa-psk" and len(args.password) < 64: + # Hash the password into a psk hash to not store it in clear form: + pw = pbkdf2(args.password.encode(), args.ssid.encode(), 4096, 32) + args.password = binascii.hexlify(pw).decode("utf-8") + + profile = ConnectionProfile( + connection=ConnectionSettings( + connection_id=args.conn_id, + uuid=str(args.uuid), + connection_type=ConnectionType.WIFI.value, + autoconnect=bool(hasattr(args, "auto") and args.auto), + ), + ipv4=Ipv4Settings(method="auto"), + ipv6=Ipv6Settings(method="auto"), + wireless=WirelessSettings(ssid=args.ssid.encode("utf-8")), + wireless_security=WirelessSecuritySettings( + key_mgmt=args.key_mgmt, auth_alg="open", psk=args.password + ), + ) + + # To bind the new connection to a specific interface, use this: + if hasattr(args, "interface_name") and args.interface_name: + profile.connection.interface_name = args.interface_name + + s = SettingsManager() + save = bool(hasattr(args, "save") and args.save) + addconnection = s.add_connection if save else s.add_connection_unsaved + connection_settings_dbus_path = await addconnection(profile.to_dbus()) + created = "created and saved" if save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pformat, sort_dicts=False)(profile.to_settings_dict())) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("-s", dest="ssid", default="CafeSSID", help="WiFi SSID") + p.add_argument("-k", dest="key_mgmt", default="wpa-psk", help="key-mgmt") + p.add_argument("-p", dest="password", default="Coffee!!", help="WiFi PSK") + p.add_argument("-i", dest="interface_name", default="", help="WiFi device") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := asyncio.run(add_wifi_psk_connection_async(args)): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/dev/async/delete-connection-by-uuid-async.py b/examples/dev/async/delete-connection-by-uuid-async.py new file mode 100755 index 0000000..ac1ee3d --- /dev/null +++ b/examples/dev/async/delete-connection-by-uuid-async.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Create and delete a connection profile using the unique connection uuid +# +import asyncio +import logging +import sdbus +from uuid import uuid4 +from argparse import Namespace +from sdbus_async.networkmanager import NetworkManagerSettings +from sdbus_async.networkmanager import NmSettingsInvalidConnectionError + + +async def delete_connection_by_uuid(uuid: str) -> bool: + """Find and delete the connection identified by the given UUID""" + try: + await NetworkManagerSettings().delete_connection_by_uuid(uuid) + except NmSettingsInvalidConnectionError: + logging.getLogger().fatal(f"Connection {uuid} for deletion not found") + return False + return True + + +async def create_and_delete_wifi_psk_connection_async(args: Namespace) -> bool: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + add_wifi_psk_connection = __import__("add-wifi-psk-connection-async") + if not await add_wifi_psk_connection.add_wifi_psk_connection_async(args): + return False + return await delete_connection_by_uuid(str(args.uuid)) + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.WARNING) + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = Namespace(conn_id="Example", uuid=uuid4(), ssid="S", psk="Password") + if asyncio.run(create_and_delete_wifi_psk_connection_async(args)): + print(f"Succeeded in creating and deleting connection {args.uuid}") diff --git a/examples/async/device-state-async.py b/examples/dev/async/device-state-async.py similarity index 100% rename from examples/async/device-state-async.py rename to examples/dev/async/device-state-async.py diff --git a/examples/dev/async/list-connections-async.py b/examples/dev/async/list-connections-async.py new file mode 100755 index 0000000..cd39131 --- /dev/null +++ b/examples/dev/async/list-connections-async.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example which lists the details of NetworkManager's connection profiles. +# This is the asyncio variant of this example using sdbus_async.networkmanager. +# The blocking variant of this example is examples/block/list-connections.py +# +# Configuration settings are described at +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Example output: +# | name: Wired connection 1 +# | uuid: b2caabdc-98bb-3f88-8d28-d10369d6ded9 +# | type: 802-3-ethernet +# | interface-name: enx001e101f0000 +# | ipv4: method: manual +# | ipaddr: 192.168.178.34/24 +# | route-metric: 200 +# | ipv6: method: disabled +import asyncio +import sdbus +import pprint +from sdbus_async.networkmanager import ( + NetworkManagerSettings, + NetworkConnectionSettings, +) +from typing import List + + +async def list_connection_profiles_async() -> None: + networkmanager_settings = NetworkManagerSettings() + connections_paths: List[str] = await networkmanager_settings.connections + for dbus_connection_path in connections_paths: + await print_connection_profile(dbus_connection_path) + + +async def print_connection_profile(connection_path: str) -> None: + connectionsettings_service = NetworkConnectionSettings(connection_path) + profile = await connectionsettings_service.get_profile() + connection = profile.connection + print("-------------------------------------------------------------") + print("name:", connection.connection_id) + print("uuid:", connection.uuid) + print("type:", connection.connection_type) + if connection.interface_name: + print(" interface-name:", connection.interface_name) + if profile.ipv4: + print("ipv4: method:", profile.ipv4.method) + if profile.ipv4.address_data: + for address in profile.ipv4.address_data: + print(f' ipaddr: {address.address}/{address.prefix}') + if profile.ipv4.route_metric: + print(f' route-metric: {profile.ipv4.route_metric}') + if profile.ipv6: + print("ipv6: method:", profile.ipv6.method) + pprint.pprint(profile.to_settings_dict(), sort_dicts=False) + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + asyncio.run(list_connection_profiles_async()) diff --git a/examples/dev/async/netdevinfo-async.py b/examples/dev/async/netdevinfo-async.py new file mode 100755 index 0000000..e4ef140 --- /dev/null +++ b/examples/dev/async/netdevinfo-async.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to list the active IPv4 protocol configuration of network devices +# and the current status of WiFi adapters +# +# For IPv4 and org.freedesktop.NetworkManager.Device.Wireless see: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# https://networkmanager.dev/docs/api/latest/ref-dbus-devices.html +import asyncio +import sdbus +from sdbus_async.networkmanager import ( + ConnectionType, + NetworkConnectionSettings, + NetworkManager, + NetworkManagerSettings, + NetworkDeviceGeneric, + IPv4Config, + DeviceType, + NetworkDeviceWireless, + WiFiOperationMode, + AccessPoint, +) +from typing import Any, Dict, List, Optional, Tuple +NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] + + +async def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[str]: + """Return the most-recently used connection_id for this device + + Besides getting the currently active connection, this will succeed + in getting the most recent connection when a device is not connected + at the moment this function is executed. + + It uses getattr(ConnectionType, dev_type) to get the connection_type + used for connection_profiles for this DeviceType. + + With a slight modification, this could return the most recent connections + of the given device, ordered by the time of the last use of them. + """ + settings_service = NetworkManagerSettings() + connection_paths: List[str] = await settings_service.connections + conns = {} + for connection_path in connection_paths: + connection_manager = NetworkConnectionSettings(connection_path) + connection = (await connection_manager.get_profile()).connection + # Filter connection profiles matching the connection type for the device: + if connection.connection_type != getattr(ConnectionType, dev_type): + continue + # If the interface_name of a connection profiles is set, it must match: + if connection.interface_name and connection.interface_name != ifname: + continue + # If connection.timestamp is not set, it was never active. Set it to 0: + if not connection.timestamp: + connection.timestamp = 0 + # Record the connection_ids of the matches, and timestamp is the key: + conns[connection.timestamp] = connection.connection_id + if not len(conns): + return None + # Returns the connection_id of the highest timestamp which was found: + return conns.get(max(conns.keys())) + + +async def list_networkdevice_details_async() -> None: + nm = NetworkManager() + devices_paths = await nm.get_devices() + + for device_path in devices_paths: + generic_device = NetworkDeviceGeneric(device_path) + device_ip4_conf_path: str = await generic_device.ip4_config + if device_ip4_conf_path == "/": + continue + if not await generic_device.managed: + continue + dev_type = DeviceType(await generic_device.device_type).name + if dev_type == DeviceType.BRIDGE.name: + continue + + dev_name = await generic_device.interface + ip4_conf = IPv4Config(device_ip4_conf_path) + gateway: str = await ip4_conf.gateway + + print("Type: ", dev_type.title()) + print("Name: ", dev_name) + + if gateway: + print("Gateway:", gateway) + + address_data: NetworkManagerAddressData = await ip4_conf.address_data + for inetaddr in address_data: + print(f'Address: {inetaddr["address"][1]}/{inetaddr["prefix"][1]}') + + nameservers: NetworkManagerAddressData = await ip4_conf.nameserver_data + for dns in nameservers: + print("DNS: ", dns["address"][1]) + + if dev_type == DeviceType.WIFI.name: + wifi = NetworkDeviceWireless(device_path) + print("Wifi: ", WiFiOperationMode(await wifi.mode).name.title()) + ap_path = await wifi.active_access_point + if ap_path == "/": + print("No active access point") + else: + ap = AccessPoint(ap_path) + ssid: bytes = await ap.ssid + if ssid: + print("SSID: ", ssid.decode("utf-8", "ignore")) + if await ap.strength: + print("Signal: ", await ap.strength) + connection_id = await get_most_recent_connection_id(dev_name, dev_type) + if connection_id: + print("Profile:", connection_id) + + print("") + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + asyncio.run(list_networkdevice_details_async()) diff --git a/examples/dev/async/update-connection-async.py b/examples/dev/async/update-connection-async.py new file mode 100755 index 0000000..d838bda --- /dev/null +++ b/examples/dev/async/update-connection-async.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Update a property of a connection profile, looked up by connection id +# +# This version uses connection_manager.get_profile().to_settings_dict() +# to retrieve the connection profile from NetworkManager as a settings dict. +# +# It then updates it dynamically using the given arguments: +# The default is to set ipv4.dns-search to ["domain1.com", "domain2.com"]. +# +# The dynamically updated dict is then used to update connection profile of NM. +# +# The IPv4 settings of connections profiles are documented here: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# +import asyncio +import sdbus +from functools import partial +from sdbus_async.networkmanager import NetworkManagerSettings +from sdbus_async.networkmanager import NetworkConnectionSettings +from sdbus_async.networkmanager.settings import ConnectionProfile +from pprint import pprint +from typing import Any, Dict + + +async def update_connection_async(args: Dict[str, Any]) -> None: + """Update the settings for [key][entry] of the 1st matching connection""" + + # Get the connection path of the connection(s) with the received id + fn = NetworkManagerSettings().get_connections_by_id(args["connection_id"]) + connection_paths = await fn + if not connection_paths: + print(f"No connection {id}, create with add-wifi-psk-connection-async") + return + + # Get the profile settings of the first connection with given id + connection_manager = NetworkConnectionSettings(connection_paths[0]) + existing_connection_profile = await connection_manager.get_profile() + settings = existing_connection_profile.to_settings_dict() + + # Update the given setting's property using the given value + setting, property = args["connection_setting"] + settings[setting][property] = args["value"] + + # Get a new ConnectionProfile with the change incorporated + new_connection_profile = ConnectionProfile.from_settings_dict(settings) + + # Update the new ConnectionProfile in NetworkManager's configuration + await connection_manager.update(new_connection_profile.to_dbus()) + + print(f'Updated {new_connection_profile.connection.uuid}.{setting}:') + partial(pprint, sort_dicts=False)(settings) + + # Restore the previous connection profile: + await connection_manager.update(existing_connection_profile.to_dbus()) + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = { + # Set MyConnectionExample.ipv4.dns-search to "domain1.com,domain2.com": + "connection_id": "MyConnectionExample", + "connection_setting": ("ipv4", "dns-search"), + "value": ["domain1.com", "domain2.com"], + } + asyncio.run(update_connection_async(args)) diff --git a/examples/dev/block/add-eth-connection.py b/examples/dev/block/add-eth-connection.py new file mode 100755 index 0000000..b692890 --- /dev/null +++ b/examples/dev/block/add-eth-connection.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new Ethernet network connection profile: +# +# examples/block/add-eth-connection.py --help +# usage: add-eth-connection.py [-h] [-c CONN_ID] [-u UUID] [-i INTERFACE_NAME] +# [-4 IP4] [-g GW] [-a] [--save] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -i INTERFACE_NAME ethX device +# -4 IP4 IP4/prefix +# -g GW gw/metric +# -a autoconnect +# --save Save +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html + +import sdbus +import functools +import logging +import pprint +import sys +from uuid import uuid4 +from argparse import ArgumentParser, Namespace +from sdbus_block.networkmanager import NetworkManagerSettings +from sdbus_block.networkmanager import NetworkManagerConnectionProperties + + +def add_ethernet_connection(args: Namespace) -> str: + """Add a (by default) temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info + + # If we add many connections using the same id, things get messy. Check: + if NetworkManagerSettings().get_connections_by_id(args.conn_id): + info(f'Connections using ID "{args.conn_id}" exist, remove them:') + info(f'Run: nmcli connection delete "{args.conn_id}"') + return "" + + ipaddr, prefix = args.ip4.split("/") + properties: NetworkManagerConnectionProperties = { + "connection": { + "id": ("s", args.conn_id), + "uuid": ("s", str(args.uuid)), + "type": ("s", "802-3-ethernet"), + "autoconnect": ("b", args.auto), + }, + "ipv4": { + "method": ("s", "manual"), + "address-data": ( + "aa{sv}", + [ + { + "address": ("s", ipaddr), + "prefix": ("u", int(prefix)), + }, + ], + ), + }, + "ipv6": {"method": ("s", "disabled")}, + } + if args.interface_name: + properties["connection"]["interface-name"] = ("s", args.interface_name) + if len(sys.argv) == 1 or args.gw != "192.0.2.1/4000": + default_gateway, route_metric = args.gw.split("/") + properties["ipv4"]["gateway"] = ("s", default_gateway) + properties["ipv4"]["route-metric"] = ("u", int(route_metric)) + + s = NetworkManagerSettings() + addconnection = s.add_connection if args.save else s.add_connection_unsaved + connection_settings_dbus_path = addconnection(properties) + created = "created and saved" if args.save else "created" + + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("-i", dest="interface_name", default="", help="ethX device") + p.add_argument("-4", dest="ip4", default="192.0.2.8/24", help="IP4/prefix") + p.add_argument("-g", dest="gw", default="192.0.2.1/4000", help="gw/metric") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := add_ethernet_connection(args): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/dev/block/add-wifi-psk-connection.py b/examples/dev/block/add-wifi-psk-connection.py new file mode 100755 index 0000000..3b732be --- /dev/null +++ b/examples/dev/block/add-wifi-psk-connection.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to create a new WiFi-PSK network connection profile: +# +# $ examples/block/add-wifi-psk-connection.py --help +# usage: add-wifi-psk-connection.py [-h] [-c CONN_ID] [-s SSID] [-p PSK] +# [-i INTERFACE_NAME] [-a] [--save] +# +# Optional arguments have example values: +# +# optional arguments: +# -h, --help show this help message and exit +# -c CONN_ID Connection Id +# -u UUID Connection UUID +# -s SSID WiFi SSID +# -p PSK WiFi PSK +# -i INTERFACE_NAME WiFi device +# -a autoconnect +# --save Save +# +# $ add-wifi-psk-connection.py +# New unsaved connection profile created, show it with: +# nmcli connection show "MyConnectionExample"|grep -v -e -- -e default +# Settings used: +# {'connection': {'id': ('s', 'MyConnectionExample'), +# 'uuid': ('s', '90e3bcc8-d3a5-4725-a363-abb788fd47bf'), +# 'type': ('s', '802-11-wireless'), +# 'autoconnect': ('b', False)}, +# '802-11-wireless': {'mode': ('s', 'infrastructure'), +# 'security': ('s', '802-11-wireless-security'), +# 'ssid': ('ay', b'CafeSSID')}, +# '802-11-wireless-security': {'key-mgmt': ('s', 'wpa-psk'), +# 'auth-alg': ('s', 'open'), +# 'psk': ('s', 'Coffee!!')}, +# 'ipv4': {'method': ('s', 'auto')}, +# 'ipv6': {'method': ('s', 'auto')}} +# +# Connection Profile settings are described at: +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Note: By default, it uses add_connection_unsaved() to add a temporary +# memory-only connection which is not saved to the system-connections folder: +# For reference, see: https://networkmanager.dev/docs/api/latest/spec.html +# -> org.freedesktop.NetworkManager.Settings (Settings Profile Manager) + +import functools +import logging +import pprint +import sdbus +from uuid import uuid4 +from argparse import ArgumentParser, Namespace +from sdbus_block.networkmanager import NetworkManagerSettings +from sdbus_block.networkmanager import NetworkManagerConnectionProperties + + +def add_wifi_psk_connection(args: Namespace) -> str: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + info = logging.getLogger().info + + # If we add many connections passing the same id, things get messy. Check: + if NetworkManagerSettings().get_connections_by_id(args.conn_id): + print(f'Connection "{args.conn_id}" exists, remove it first') + print(f'Run: nmcli connection delete "{args.conn_id}"') + return "" + + properties: NetworkManagerConnectionProperties = { + "connection": { + "id": ("s", args.conn_id), + "uuid": ("s", str(args.uuid)), + "type": ("s", "802-11-wireless"), + "autoconnect": ("b", bool(hasattr(args, "auto") and args.auto)), + }, + "802-11-wireless": { + "mode": ("s", "infrastructure"), + "security": ("s", "802-11-wireless-security"), + "ssid": ("ay", args.ssid.encode("utf-8")), + }, + "802-11-wireless-security": { + "key-mgmt": ("s", "wpa-psk"), + "auth-alg": ("s", "open"), + "psk": ("s", args.psk), + }, + "ipv4": {"method": ("s", "auto")}, + "ipv6": {"method": ("s", "auto")}, + } + + # To bind the new connection to a specific interface, use this: + if hasattr(args, "interface_name") and args.interface_name: + properties["connection"]["interface-name"] = ("s", args.interface_name) + + s = NetworkManagerSettings() + save = bool(hasattr(args, "save") and args.save) + addconnection = s.add_connection if save else s.add_connection_unsaved + connection_settings_dbus_path = addconnection(properties) + created = "created and saved" if save else "created" + info(f"New unsaved connection profile {created}, show it with:") + info(f'nmcli connection show "{args.conn_id}"|grep -v -e -- -e default') + info("Settings used:") + info(functools.partial(pprint.pformat, sort_dicts=False)(properties)) + return connection_settings_dbus_path + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.INFO) + p = ArgumentParser(description="Optional arguments have example values:") + conn_id = "MyConnectionExample" + p.add_argument("-c", dest="conn_id", default=conn_id, help="Connection Id") + p.add_argument("-u", dest="uuid", default=uuid4(), help="Connection UUID") + p.add_argument("-s", dest="ssid", default="CafeSSID", help="WiFi SSID") + p.add_argument("-p", dest="psk", default="Coffee!!", help="WiFi PSK") + p.add_argument("-i", dest="interface_name", default="", help="WiFi device") + p.add_argument("-a", dest="auto", action="store_true", help="autoconnect") + p.add_argument("--save", dest="save", action="store_true", help="Save") + args = p.parse_args() + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + if connection_dpath := add_wifi_psk_connection(args): + print(f"Path of the new connection: {connection_dpath}") + print(f"UUID of the new connection: {args.uuid}") + else: + print("Error: No new connection created.") diff --git a/examples/dev/block/delete-connection-by-uuid.py b/examples/dev/block/delete-connection-by-uuid.py new file mode 100755 index 0000000..2b42509 --- /dev/null +++ b/examples/dev/block/delete-connection-by-uuid.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Create and delete a connection profile using the unique connection uuid +# +import logging +import sdbus +from uuid import uuid4 +from argparse import Namespace +from sdbus_block.networkmanager import NetworkManagerSettings +from sdbus_block.networkmanager import NmSettingsInvalidConnectionError + + +def delete_connection_by_uuid(uuid: str) -> bool: + """Find and delete the connection identified by the given UUID""" + try: + NetworkManagerSettings().delete_connection_by_uuid(uuid) + except NmSettingsInvalidConnectionError: + logging.getLogger().fatal(f"Connection {uuid} for deletion not found") + return False + return True + + +def create_and_delete_wifi_psk_connection_async(args: Namespace) -> bool: + """Add a temporary (not yet saved) network connection profile + :param Namespace args: autoconnect, conn_id, psk, save, ssid, uuid + :return: dbus connection path of the created connection profile + """ + add_wifi_psk_connection = __import__("add-wifi-psk-connection") + if not add_wifi_psk_connection.add_wifi_psk_connection(args): + return False + return delete_connection_by_uuid(str(args.uuid)) + + +if __name__ == "__main__": + logging.basicConfig(format="%(message)s", level=logging.WARNING) + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = Namespace(conn_id="Example", uuid=uuid4(), ssid="S", psk="Password") + if create_and_delete_wifi_psk_connection_async(args): + print(f"Succeeded in creating and deleting connection {args.uuid}") diff --git a/examples/block/device-state.py b/examples/dev/block/device-state.py similarity index 100% rename from examples/block/device-state.py rename to examples/dev/block/device-state.py diff --git a/examples/dev/block/list-connections.py b/examples/dev/block/list-connections.py new file mode 100755 index 0000000..f8d262a --- /dev/null +++ b/examples/dev/block/list-connections.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example which lists the details of NetworkManager's connection profiles. +# +# Configuration settings are described at +# https://networkmanager.dev/docs/api/latest/ref-settings.html +# +# Example output: +# | name: Wired connection 1 +# | uuid: b2caabdc-98bb-3f88-8d28-d10369d6ded9 +# | type: 802-3-ethernet +# | interface-name: enx001e101f0000 +# | ipv4: method: manual +# | ipaddr: 192.168.178.34/24 +# | route-metric: 200 +# | ipv6: method: disabled +import sdbus +from sdbus_block.networkmanager import ( + ConnectionType, + NetworkManagerSettings, + NetworkConnectionSettings, +) + + +def list_connection_profiles_blocking() -> None: + """Call print_connection_profile_blocking() for all connection profiles""" + networkmanager_settings = NetworkManagerSettings() + for dbus_connection_path in networkmanager_settings.connections: + print_connection_profile_blocking(dbus_connection_path) + + +def print_connection_profile_blocking(connection_path: str) -> None: + """Show the use of NetworkConnectionSettings(path).get_profile()""" + profile = NetworkConnectionSettings(connection_path).get_profile() + print("-------------------------------------------------------------") + print("name:", profile.connection.connection_id) + print("uuid:", profile.connection.uuid) + print("type:", profile.connection.connection_type) + if profile.connection.interface_name: + print(" interface-name:", profile.connection.interface_name) + if profile.ipv4: + print("ipv4: method:", profile.ipv4.method) + if profile.ipv4.address_data: + for address in profile.ipv4.address_data: + print(f' ipaddr: {address.address}/{address.prefix}') + if profile.ipv4.route_metric: + print(f' route-metric: {profile.ipv4.route_metric}') + if profile.ipv6: + print("ipv6: method:", profile.ipv6.method) + if profile.connection.connection_type == ConnectionType.WIFI: + assert profile.wireless + assert profile.wireless.ssid + print("ssid:", profile.wireless.ssid.decode()) + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + list_connection_profiles_blocking() diff --git a/examples/dev/block/netdevinfo.py b/examples/dev/block/netdevinfo.py new file mode 100755 index 0000000..1dec341 --- /dev/null +++ b/examples/dev/block/netdevinfo.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Example to list the active IPv4 protocol configuration of network devices +# and the current status of WiFi adapters +# +# For IPv4 and org.freedesktop.NetworkManager.Device.Wireless see: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# https://networkmanager.dev/docs/api/latest/ref-dbus-devices.html +import sdbus +from sdbus_block.networkmanager import ( + ConnectionType, + NetworkConnectionSettings, + NetworkManager, + NetworkManagerSettings, + NetworkDeviceGeneric, + IPv4Config, + DeviceType, + NetworkDeviceWireless, + WiFiOperationMode, + AccessPoint, +) +from typing import Any, Dict, List, Optional, Tuple +NetworkManagerAddressData = List[Dict[str, Tuple[str, Any]]] + + +def get_most_recent_connection_id(ifname: str, dev_type: str) -> Optional[str]: + """Return the most-recently used connection_id for this device + + Besides getting the currently active connection, this will succeed + in getting the most recent connection when a device is not connected + at the moment this function is executed. + + It uses getattr(ConnectionType, dev_type) to get the connection_type + used for connection_profiles for this DeviceType. + + With a slight modification, this could return the most recent connections + of the given device, ordered by the time of the last use of them. + """ + settings_service = NetworkManagerSettings() + connection_paths: List[str] = settings_service.connections + conns = {} + for connection_path in connection_paths: + connection_manager = NetworkConnectionSettings(connection_path) + connection = connection_manager.get_profile().connection + # Filter connection profiles matching the connection type for the device: + if connection.connection_type != getattr(ConnectionType, dev_type): + continue + # If the interface_name of a connection profiles is set, it must match: + if connection.interface_name and connection.interface_name != ifname: + continue + # If connection.timestamp is not set, it was never active. Set it to 0: + if not connection.timestamp: + connection.timestamp = 0 + # Record the connection_ids of the matches, and timestamp is the key: + conns[connection.timestamp] = connection.connection_id + if not len(conns): + return None + # Returns the connection_id of the highest timestamp which was found: + return conns.get(max(conns.keys())) + + +def list_networkdevice_details_blocking() -> None: + + for device_path in NetworkManager().get_devices(): + generic_device = NetworkDeviceGeneric(device_path) + device_ip4_conf_path: str = generic_device.ip4_config + if device_ip4_conf_path == "/": + continue + if not generic_device.managed: + continue + dev_type = DeviceType(generic_device.device_type).name + if dev_type == DeviceType.BRIDGE.name: + continue + + dev_name = generic_device.interface + ip4_conf = IPv4Config(device_ip4_conf_path) + gateway: str = ip4_conf.gateway + + print("Type: ", dev_type.title()) + print("Name: ", dev_name) + + if gateway: + print("Gateway:", gateway) + + address_data: NetworkManagerAddressData = ip4_conf.address_data + for inetaddr in address_data: + print(f'Address: {inetaddr["address"][1]}/{inetaddr["prefix"][1]}') + + nameservers: NetworkManagerAddressData = ip4_conf.nameserver_data + for dns in nameservers: + print("DNS: ", dns["address"][1]) + + if dev_type == DeviceType.WIFI.name: + wifi = NetworkDeviceWireless(device_path) + print("Wifi: ", WiFiOperationMode(wifi.mode).name.title()) + ap = AccessPoint(wifi.active_access_point) + ssid: bytes = ap.ssid + if ssid: + print("SSID: ", ssid.decode("utf-8", "ignore")) + if ap.strength: + print("Signal: ", ap.strength) + connection_id = get_most_recent_connection_id(dev_name, dev_type) + if connection_id: + print("Profile:", connection_id) + + print("") + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + list_networkdevice_details_blocking() diff --git a/examples/dev/block/update-connection.py b/examples/dev/block/update-connection.py new file mode 100644 index 0000000..10d86f1 --- /dev/null +++ b/examples/dev/block/update-connection.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Update a property of a connection profile, looked up by connection id +# +# The IPv4 settings of connections profiles are documented here: +# https://networkmanager.dev/docs/api/latest/settings-ipv4.html +# + +import sdbus +from functools import partial +from sdbus_block.networkmanager import NetworkManagerSettings +from sdbus_block.networkmanager import NetworkConnectionSettings +from pprint import pprint +from typing import Any, Dict + + +def update_connection(args: Dict[str, Any]) -> None: + """Update the settings for [key][entry] of the 1st matching connection""" + con = NetworkManagerSettings().get_connections_by_id(args["connection_id"]) + settings_domain, setting = args["connection_setting"] + if con: + connection_settings = NetworkConnectionSettings(con[0]) + properties = connection_settings.get_settings() + # For compatibility with old tools, NM adds and prefers them, delete: + properties["ipv4"].pop("addresses") # -> Use ["ipv4"]["address-data"] + properties["ipv4"].pop("routes") # ----> Use ["ipv4"]["route-data"] + + # Update the setting's value in the given configuration group: + properties[settings_domain][setting] = args["value"] + connection_settings.update(properties) + + print(f'Updated {properties["connection"]["uuid"]}.{settings_domain}:') + partial(pprint, sort_dicts=False)(properties[settings_domain]) + else: + print(f"No connection matching {id}") + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + args = { + # Set MyConnectionExample.ipv4.dns-search to "domain1.com,domain2.com": + "connection_id": "MyConnectionExample", + "connection_setting": ("ipv4", "dns-search"), + # "as" is the so-called DBus signature, it means "array of strings": + "value": ("as", ["domain1.com", "domain2.com"]), + } + update_connection(args) From 5666c1845b235ddc994b01548fa47259adbeebcc Mon Sep 17 00:00:00 2001 From: igo95862 Date: Mon, 18 Mar 2024 22:10:02 +0500 Subject: [PATCH 77/80] docs: Make all quickstart code snippets a valid scripts Otherwise it might be confusing on where the variables come from. --- docs/quickstart.rst | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index a145050..17d3880 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -42,9 +42,18 @@ can be used to determine particular type of a device. .. code-block:: python - from sdbus_block.networkmanager import NetworkDeviceGeneric, NetworkDeviceWireless + import sdbus + + from sdbus_block.networkmanager import ( + NetworkDeviceGeneric, + NetworkDeviceWireless, + NetworkManager, + ) from sdbus_block.networkmanager.enums import DeviceType + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + network_manager = NetworkManager() + all_devices = {path: NetworkDeviceGeneric(path) for path in network_manager.devices} wifi_devices = [ @@ -67,11 +76,22 @@ class. .. code-block:: python - from sdbus_block.networkmanager import NetworkManagerSettings + import sdbus + + from sdbus_block.networkmanager import ( + NetworkConnectionSettings, + NetworkManager, + NetworkManagerSettings, + ) + + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + network_manager = NetworkManager() networwork_manager_settings = NetworkManagerSettings() - all_connections = [NetworkConnectionSettings(x) for x in networwork_manager_settings.connections] + all_connections = [ + NetworkConnectionSettings(x) for x in networwork_manager_settings.connections + ] The actual connection settings are represented by a complex double nested dictionary of D-Bus variants. For convenience a `dataclass `_ @@ -83,9 +103,23 @@ are two main methods to interact with connection settings helper. .. code-block:: python - connection = all_connections[0] + import sdbus + + from sdbus_block.networkmanager import ( + NetworkConnectionSettings, + NetworkManager, + NetworkManagerSettings, + ) + + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + network_manager = NetworkManager() + + networwork_manager_settings = NetworkManagerSettings() + + + connection = NetworkConnectionSettings(networwork_manager_settings.connections[0]) setting_dataclass = connection.get_profile() - print("uuid:", profile.connection.uuid) + print("uuid:", setting_dataclass.connection.uuid) Active Connection ----------------- From 9edda490835d8e3b81b96d69097e8cfe1ea4f7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?= Date: Thu, 17 Apr 2025 14:20:05 +0200 Subject: [PATCH 78/80] Update URL to github repository MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The github URL has changed but it was not updated at least in some places, so update it now. Signed-off-by: Raphaël Mélotte --- README.md | 4 ++-- docs/index.rst | 2 +- setup.py | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 56e02f9..111a641 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Implements most NetworkManager dbus interfaces and objects. * `python-sdbus` version higher than 0.8rc2 -See [python-sdbus requirements](https://github.com/igo95862/python-sdbus#requirements). +See [python-sdbus requirements](https://github.com/python-sdbus/python-sdbus#requirements). ## Installation @@ -19,6 +19,6 @@ See [python-sdbus requirements](https://github.com/igo95862/python-sdbus#require See [this quickstart guide for brief introduction to NetworkManager D-Bus API](https://python-sdbus-networkmanager.readthedocs.io/en/latest/quickstart.html). -This is the sub-project of [python-sdbus](https://github.com/igo95862/python-sdbus). +This is the sub-project of [python-sdbus](https://github.com/python-sdbus/python-sdbus). See the [python-sdbus documentation](https://python-sdbus.readthedocs.io/en/latest/). diff --git a/docs/index.rst b/docs/index.rst index 7fc3c5f..3003952 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,5 +22,5 @@ of `NetworkManager `_. enums exceptions -See `python-sdbus `_ homepage if you are +See `python-sdbus `_ homepage if you are unfamiliar with python-sdbus. diff --git a/setup.py b/setup.py index 85c82fe..0a29d26 100644 --- a/setup.py +++ b/setup.py @@ -30,15 +30,15 @@ long_description=long_description, long_description_content_type='text/markdown', version='2.0.0', - url='https://github.com/igo95862/python-sdbus', + url='https://github.com/python-sdbus/python-sdbus', author='igo95862', author_email='igo95862@yandex.ru', license='LGPL-2.1-or-later', keywords='dbus networkmanager networking linux freedesktop', project_urls={ 'Documentation': 'https://python-sdbus.readthedocs.io/en/latest/', - 'Source': 'https://github.com/igo95862/python-sdbus/', - 'Tracker': 'https://github.com/igo95862/python-sdbus/issues/', + 'Source': 'https://github.com/python-sdbus/python-sdbus/', + 'Tracker': 'https://github.com/python-sdbus/python-sdbus/issues/', }, classifiers=[ 'Development Status :: 4 - Beta', From a2230d8cd08c22312534390d337645f1790cadbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20M=C3=A9lotte?= Date: Thu, 17 Apr 2025 14:23:43 +0200 Subject: [PATCH 79/80] setup.py: fix URLs that are specific to python-sdbus-networkmanager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation URL in the README.md pointed to 'https://python-sdbus-networkmanager.readthedocs.io', but the one in setup.py pointed to python-sdbus instead. Fix the documentation URL, and while at it fix some others that had the same issue. Signed-off-by: Raphaël Mélotte --- setup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 0a29d26..02c1185 100644 --- a/setup.py +++ b/setup.py @@ -30,15 +30,15 @@ long_description=long_description, long_description_content_type='text/markdown', version='2.0.0', - url='https://github.com/python-sdbus/python-sdbus', + url='https://github.com/python-sdbus/python-sdbus-networkmanager', author='igo95862', author_email='igo95862@yandex.ru', license='LGPL-2.1-or-later', keywords='dbus networkmanager networking linux freedesktop', project_urls={ - 'Documentation': 'https://python-sdbus.readthedocs.io/en/latest/', - 'Source': 'https://github.com/python-sdbus/python-sdbus/', - 'Tracker': 'https://github.com/python-sdbus/python-sdbus/issues/', + 'Documentation': 'https://python-sdbus-networkmanager.readthedocs.io/en/latest/', + 'Source': 'https://github.com/python-sdbus/python-sdbus-networkmanager/', + 'Tracker': 'https://github.com/python-sdbus/python-sdbus-networkmanager/issues/', }, classifiers=[ 'Development Status :: 4 - Beta', From 7fb2d1869b078ff94f5d9038e0039aac6893ab38 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 20 Apr 2025 18:15:26 +0100 Subject: [PATCH 80/80] examples: Add example of listening on device state changes Apparently some people struggle with signals. This example should show them how to use signals. --- .../async/listen-device-changes-async.py | 52 +++++++++++++++++++ .../dev/async/listen-device-changes-async.py | 52 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 examples/2.0.0/async/listen-device-changes-async.py create mode 100644 examples/dev/async/listen-device-changes-async.py diff --git a/examples/2.0.0/async/listen-device-changes-async.py b/examples/2.0.0/async/listen-device-changes-async.py new file mode 100644 index 0000000..725010f --- /dev/null +++ b/examples/2.0.0/async/listen-device-changes-async.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright (C) 2025 igo95862 +# +# Example of listening to device state change signals. +# Also shows the use of enums. +from __future__ import annotations + +import asyncio +from argparse import ArgumentParser + +import sdbus + +from sdbus_async.networkmanager import NetworkDeviceGeneric, NetworkManager +from sdbus_async.networkmanager.enums import DeviceState, DeviceStateReason + + +async def listen_device(device_path: str, device_name: str) -> None: + generic_device = NetworkDeviceGeneric(device_path) + print(f"Listening state changes for device {device_name!r}") + + async for ( + new_state, + old_state, + reason, + ) in generic_device.state_changed.catch(): + print( + f"Now {DeviceState(new_state).name}, " + f"was {DeviceState(old_state).name}, " + f"reason {DeviceStateReason(reason).name}" + ) + + +async def main() -> None: + arg_parser = ArgumentParser() + arg_parser.add_argument("device_name") + + args = arg_parser.parse_args() + + network_manager = NetworkManager() + + device_name = args.device_name + device_path = await network_manager.get_device_by_ip_iface(device_name) + + # If you use create_task() make sure to keep a reference to the + # task or it will get garbage collected. + await listen_device(device_path, device_name) + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + asyncio.run(main()) diff --git a/examples/dev/async/listen-device-changes-async.py b/examples/dev/async/listen-device-changes-async.py new file mode 100644 index 0000000..725010f --- /dev/null +++ b/examples/dev/async/listen-device-changes-async.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: LGPL-2.1-or-later +# Copyright (C) 2025 igo95862 +# +# Example of listening to device state change signals. +# Also shows the use of enums. +from __future__ import annotations + +import asyncio +from argparse import ArgumentParser + +import sdbus + +from sdbus_async.networkmanager import NetworkDeviceGeneric, NetworkManager +from sdbus_async.networkmanager.enums import DeviceState, DeviceStateReason + + +async def listen_device(device_path: str, device_name: str) -> None: + generic_device = NetworkDeviceGeneric(device_path) + print(f"Listening state changes for device {device_name!r}") + + async for ( + new_state, + old_state, + reason, + ) in generic_device.state_changed.catch(): + print( + f"Now {DeviceState(new_state).name}, " + f"was {DeviceState(old_state).name}, " + f"reason {DeviceStateReason(reason).name}" + ) + + +async def main() -> None: + arg_parser = ArgumentParser() + arg_parser.add_argument("device_name") + + args = arg_parser.parse_args() + + network_manager = NetworkManager() + + device_name = args.device_name + device_path = await network_manager.get_device_by_ip_iface(device_name) + + # If you use create_task() make sure to keep a reference to the + # task or it will get garbage collected. + await listen_device(device_path, device_name) + + +if __name__ == "__main__": + sdbus.set_default_bus(sdbus.sd_bus_open_system()) + asyncio.run(main())