mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-13 12:16:29 +00:00
Add IPv6 address generation mode & privacy extensions (#5892)
* feat: Add IPv6 address generation mode & privacy extensions Signed-off-by: David Rapan <david@rapan.cz> * Use NetworkManager fixture for settings init tests This fixes the test by since the extended implementation now can read the version of NetworkManager. * Add pytest for addr_gen_mode --------- Signed-off-by: David Rapan <david@rapan.cz> Co-authored-by: Stefan Agner <stefan@agner.ch>
This commit is contained in:
parent
6e6fe5ba39
commit
3b575eedba
@ -10,6 +10,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from ..const import (
|
from ..const import (
|
||||||
ATTR_ACCESSPOINTS,
|
ATTR_ACCESSPOINTS,
|
||||||
|
ATTR_ADDR_GEN_MODE,
|
||||||
ATTR_ADDRESS,
|
ATTR_ADDRESS,
|
||||||
ATTR_AUTH,
|
ATTR_AUTH,
|
||||||
ATTR_CONNECTED,
|
ATTR_CONNECTED,
|
||||||
@ -22,6 +23,7 @@ from ..const import (
|
|||||||
ATTR_ID,
|
ATTR_ID,
|
||||||
ATTR_INTERFACE,
|
ATTR_INTERFACE,
|
||||||
ATTR_INTERFACES,
|
ATTR_INTERFACES,
|
||||||
|
ATTR_IP6_PRIVACY,
|
||||||
ATTR_IPV4,
|
ATTR_IPV4,
|
||||||
ATTR_IPV6,
|
ATTR_IPV6,
|
||||||
ATTR_MAC,
|
ATTR_MAC,
|
||||||
@ -46,7 +48,10 @@ from ..exceptions import APIError, APINotFound, HostNetworkNotFound
|
|||||||
from ..host.configuration import (
|
from ..host.configuration import (
|
||||||
AccessPoint,
|
AccessPoint,
|
||||||
Interface,
|
Interface,
|
||||||
|
InterfaceAddrGenMode,
|
||||||
|
InterfaceIp6Privacy,
|
||||||
InterfaceMethod,
|
InterfaceMethod,
|
||||||
|
Ip6Setting,
|
||||||
IpConfig,
|
IpConfig,
|
||||||
IpSetting,
|
IpSetting,
|
||||||
VlanConfig,
|
VlanConfig,
|
||||||
@ -68,6 +73,8 @@ _SCHEMA_IPV6_CONFIG = vol.Schema(
|
|||||||
{
|
{
|
||||||
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv6Interface)],
|
vol.Optional(ATTR_ADDRESS): [vol.Coerce(IPv6Interface)],
|
||||||
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
|
vol.Optional(ATTR_METHOD): vol.Coerce(InterfaceMethod),
|
||||||
|
vol.Optional(ATTR_ADDR_GEN_MODE): vol.Coerce(InterfaceAddrGenMode),
|
||||||
|
vol.Optional(ATTR_IP6_PRIVACY): vol.Coerce(InterfaceIp6Privacy),
|
||||||
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv6Address),
|
vol.Optional(ATTR_GATEWAY): vol.Coerce(IPv6Address),
|
||||||
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv6Address)],
|
vol.Optional(ATTR_NAMESERVERS): [vol.Coerce(IPv6Address)],
|
||||||
}
|
}
|
||||||
@ -94,8 +101,8 @@ SCHEMA_UPDATE = vol.Schema(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def ipconfig_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
|
def ip4config_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
|
||||||
"""Return a dict with information about ip configuration."""
|
"""Return a dict with information about IPv4 configuration."""
|
||||||
return {
|
return {
|
||||||
ATTR_METHOD: setting.method,
|
ATTR_METHOD: setting.method,
|
||||||
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
|
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
|
||||||
@ -105,6 +112,19 @@ def ipconfig_struct(config: IpConfig, setting: IpSetting) -> dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def ip6config_struct(config: IpConfig, setting: Ip6Setting) -> dict[str, Any]:
|
||||||
|
"""Return a dict with information about IPv6 configuration."""
|
||||||
|
return {
|
||||||
|
ATTR_METHOD: setting.method,
|
||||||
|
ATTR_ADDR_GEN_MODE: setting.addr_gen_mode,
|
||||||
|
ATTR_IP6_PRIVACY: setting.ip6_privacy,
|
||||||
|
ATTR_ADDRESS: [address.with_prefixlen for address in config.address],
|
||||||
|
ATTR_NAMESERVERS: [str(address) for address in config.nameservers],
|
||||||
|
ATTR_GATEWAY: str(config.gateway) if config.gateway else None,
|
||||||
|
ATTR_READY: config.ready,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def wifi_struct(config: WifiConfig) -> dict[str, Any]:
|
def wifi_struct(config: WifiConfig) -> dict[str, Any]:
|
||||||
"""Return a dict with information about wifi configuration."""
|
"""Return a dict with information about wifi configuration."""
|
||||||
return {
|
return {
|
||||||
@ -132,10 +152,10 @@ def interface_struct(interface: Interface) -> dict[str, Any]:
|
|||||||
ATTR_CONNECTED: interface.connected,
|
ATTR_CONNECTED: interface.connected,
|
||||||
ATTR_PRIMARY: interface.primary,
|
ATTR_PRIMARY: interface.primary,
|
||||||
ATTR_MAC: interface.mac,
|
ATTR_MAC: interface.mac,
|
||||||
ATTR_IPV4: ipconfig_struct(interface.ipv4, interface.ipv4setting)
|
ATTR_IPV4: ip4config_struct(interface.ipv4, interface.ipv4setting)
|
||||||
if interface.ipv4 and interface.ipv4setting
|
if interface.ipv4 and interface.ipv4setting
|
||||||
else None,
|
else None,
|
||||||
ATTR_IPV6: ipconfig_struct(interface.ipv6, interface.ipv6setting)
|
ATTR_IPV6: ip6config_struct(interface.ipv6, interface.ipv6setting)
|
||||||
if interface.ipv6 and interface.ipv6setting
|
if interface.ipv6 and interface.ipv6setting
|
||||||
else None,
|
else None,
|
||||||
ATTR_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
|
ATTR_WIFI: wifi_struct(interface.wifi) if interface.wifi else None,
|
||||||
@ -212,25 +232,31 @@ class APINetwork(CoreSysAttributes):
|
|||||||
for key, config in body.items():
|
for key, config in body.items():
|
||||||
if key == ATTR_IPV4:
|
if key == ATTR_IPV4:
|
||||||
interface.ipv4setting = IpSetting(
|
interface.ipv4setting = IpSetting(
|
||||||
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
|
method=config.get(ATTR_METHOD, InterfaceMethod.STATIC),
|
||||||
config.get(ATTR_ADDRESS, []),
|
address=config.get(ATTR_ADDRESS, []),
|
||||||
config.get(ATTR_GATEWAY),
|
gateway=config.get(ATTR_GATEWAY),
|
||||||
config.get(ATTR_NAMESERVERS, []),
|
nameservers=config.get(ATTR_NAMESERVERS, []),
|
||||||
)
|
)
|
||||||
elif key == ATTR_IPV6:
|
elif key == ATTR_IPV6:
|
||||||
interface.ipv6setting = IpSetting(
|
interface.ipv6setting = Ip6Setting(
|
||||||
config.get(ATTR_METHOD, InterfaceMethod.STATIC),
|
method=config.get(ATTR_METHOD, InterfaceMethod.STATIC),
|
||||||
config.get(ATTR_ADDRESS, []),
|
addr_gen_mode=config.get(
|
||||||
config.get(ATTR_GATEWAY),
|
ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.DEFAULT
|
||||||
config.get(ATTR_NAMESERVERS, []),
|
),
|
||||||
|
ip6_privacy=config.get(
|
||||||
|
ATTR_IP6_PRIVACY, InterfaceIp6Privacy.DEFAULT
|
||||||
|
),
|
||||||
|
address=config.get(ATTR_ADDRESS, []),
|
||||||
|
gateway=config.get(ATTR_GATEWAY),
|
||||||
|
nameservers=config.get(ATTR_NAMESERVERS, []),
|
||||||
)
|
)
|
||||||
elif key == ATTR_WIFI:
|
elif key == ATTR_WIFI:
|
||||||
interface.wifi = WifiConfig(
|
interface.wifi = WifiConfig(
|
||||||
config.get(ATTR_MODE, WifiMode.INFRASTRUCTURE),
|
mode=config.get(ATTR_MODE, WifiMode.INFRASTRUCTURE),
|
||||||
config.get(ATTR_SSID, ""),
|
ssid=config.get(ATTR_SSID, ""),
|
||||||
config.get(ATTR_AUTH, AuthMethod.OPEN),
|
auth=config.get(ATTR_AUTH, AuthMethod.OPEN),
|
||||||
config.get(ATTR_PSK, None),
|
psk=config.get(ATTR_PSK, None),
|
||||||
None,
|
signal=None,
|
||||||
)
|
)
|
||||||
elif key == ATTR_ENABLED:
|
elif key == ATTR_ENABLED:
|
||||||
interface.enabled = config
|
interface.enabled = config
|
||||||
@ -277,19 +303,25 @@ class APINetwork(CoreSysAttributes):
|
|||||||
ipv4_setting = None
|
ipv4_setting = None
|
||||||
if ATTR_IPV4 in body:
|
if ATTR_IPV4 in body:
|
||||||
ipv4_setting = IpSetting(
|
ipv4_setting = IpSetting(
|
||||||
body[ATTR_IPV4].get(ATTR_METHOD, InterfaceMethod.AUTO),
|
method=body[ATTR_IPV4].get(ATTR_METHOD, InterfaceMethod.AUTO),
|
||||||
body[ATTR_IPV4].get(ATTR_ADDRESS, []),
|
address=body[ATTR_IPV4].get(ATTR_ADDRESS, []),
|
||||||
body[ATTR_IPV4].get(ATTR_GATEWAY, None),
|
gateway=body[ATTR_IPV4].get(ATTR_GATEWAY, None),
|
||||||
body[ATTR_IPV4].get(ATTR_NAMESERVERS, []),
|
nameservers=body[ATTR_IPV4].get(ATTR_NAMESERVERS, []),
|
||||||
)
|
)
|
||||||
|
|
||||||
ipv6_setting = None
|
ipv6_setting = None
|
||||||
if ATTR_IPV6 in body:
|
if ATTR_IPV6 in body:
|
||||||
ipv6_setting = IpSetting(
|
ipv6_setting = Ip6Setting(
|
||||||
body[ATTR_IPV6].get(ATTR_METHOD, InterfaceMethod.AUTO),
|
method=body[ATTR_IPV6].get(ATTR_METHOD, InterfaceMethod.AUTO),
|
||||||
body[ATTR_IPV6].get(ATTR_ADDRESS, []),
|
addr_gen_mode=body[ATTR_IPV6].get(
|
||||||
body[ATTR_IPV6].get(ATTR_GATEWAY, None),
|
ATTR_ADDR_GEN_MODE, InterfaceAddrGenMode.DEFAULT
|
||||||
body[ATTR_IPV6].get(ATTR_NAMESERVERS, []),
|
),
|
||||||
|
ip6_privacy=body[ATTR_IPV6].get(
|
||||||
|
ATTR_IP6_PRIVACY, InterfaceIp6Privacy.DEFAULT
|
||||||
|
),
|
||||||
|
address=body[ATTR_IPV6].get(ATTR_ADDRESS, []),
|
||||||
|
gateway=body[ATTR_IPV6].get(ATTR_GATEWAY, None),
|
||||||
|
nameservers=body[ATTR_IPV6].get(ATTR_NAMESERVERS, []),
|
||||||
)
|
)
|
||||||
|
|
||||||
vlan_interface = Interface(
|
vlan_interface = Interface(
|
||||||
|
@ -97,6 +97,7 @@ ATTR_ADDON = "addon"
|
|||||||
ATTR_ADDONS = "addons"
|
ATTR_ADDONS = "addons"
|
||||||
ATTR_ADDONS_CUSTOM_LIST = "addons_custom_list"
|
ATTR_ADDONS_CUSTOM_LIST = "addons_custom_list"
|
||||||
ATTR_ADDONS_REPOSITORIES = "addons_repositories"
|
ATTR_ADDONS_REPOSITORIES = "addons_repositories"
|
||||||
|
ATTR_ADDR_GEN_MODE = "addr_gen_mode"
|
||||||
ATTR_ADDRESS = "address"
|
ATTR_ADDRESS = "address"
|
||||||
ATTR_ADDRESS_DATA = "address-data"
|
ATTR_ADDRESS_DATA = "address-data"
|
||||||
ATTR_ADMIN = "admin"
|
ATTR_ADMIN = "admin"
|
||||||
@ -220,6 +221,7 @@ ATTR_INSTALLED = "installed"
|
|||||||
ATTR_INTERFACE = "interface"
|
ATTR_INTERFACE = "interface"
|
||||||
ATTR_INTERFACES = "interfaces"
|
ATTR_INTERFACES = "interfaces"
|
||||||
ATTR_IP_ADDRESS = "ip_address"
|
ATTR_IP_ADDRESS = "ip_address"
|
||||||
|
ATTR_IP6_PRIVACY = "ip6_privacy"
|
||||||
ATTR_IPV4 = "ipv4"
|
ATTR_IPV4 = "ipv4"
|
||||||
ATTR_IPV6 = "ipv6"
|
ATTR_IPV6 = "ipv6"
|
||||||
ATTR_ISSUES = "issues"
|
ATTR_ISSUES = "issues"
|
||||||
|
@ -210,6 +210,24 @@ class InterfaceMethod(StrEnum):
|
|||||||
LINK_LOCAL = "link-local"
|
LINK_LOCAL = "link-local"
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceAddrGenMode(IntEnum):
|
||||||
|
"""Interface addr_gen_mode."""
|
||||||
|
|
||||||
|
EUI64 = 0
|
||||||
|
STABLE_PRIVACY = 1
|
||||||
|
DEFAULT_OR_EUI64 = 2
|
||||||
|
DEFAULT = 3
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceIp6Privacy(IntEnum):
|
||||||
|
"""Interface ip6_privacy."""
|
||||||
|
|
||||||
|
DEFAULT = -1
|
||||||
|
DISABLED = 0
|
||||||
|
ENABLED_PREFER_PUBLIC = 1
|
||||||
|
ENABLED = 2
|
||||||
|
|
||||||
|
|
||||||
class ConnectionType(StrEnum):
|
class ConnectionType(StrEnum):
|
||||||
"""Connection type."""
|
"""Connection type."""
|
||||||
|
|
||||||
|
@ -77,6 +77,14 @@ class IpProperties:
|
|||||||
dns: list[bytes | int] | None
|
dns: list[bytes | int] | None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class Ip6Properties(IpProperties):
|
||||||
|
"""IPv6 properties object for Network Manager."""
|
||||||
|
|
||||||
|
addr_gen_mode: int
|
||||||
|
ip6_privacy: int
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
class MatchProperties:
|
class MatchProperties:
|
||||||
"""Match properties object for Network Manager."""
|
"""Match properties object for Network Manager."""
|
||||||
|
@ -12,6 +12,7 @@ from ...utils import dbus_connected
|
|||||||
from ..configuration import (
|
from ..configuration import (
|
||||||
ConnectionProperties,
|
ConnectionProperties,
|
||||||
EthernetProperties,
|
EthernetProperties,
|
||||||
|
Ip6Properties,
|
||||||
IpAddress,
|
IpAddress,
|
||||||
IpProperties,
|
IpProperties,
|
||||||
MatchProperties,
|
MatchProperties,
|
||||||
@ -58,6 +59,8 @@ CONF_ATTR_IPV4_GATEWAY = "gateway"
|
|||||||
CONF_ATTR_IPV4_DNS = "dns"
|
CONF_ATTR_IPV4_DNS = "dns"
|
||||||
|
|
||||||
CONF_ATTR_IPV6_METHOD = "method"
|
CONF_ATTR_IPV6_METHOD = "method"
|
||||||
|
CONF_ATTR_IPV6_ADDR_GEN_MODE = "addr-gen-mode"
|
||||||
|
CONF_ATTR_IPV6_PRIVACY = "ip6-privacy"
|
||||||
CONF_ATTR_IPV6_ADDRESS_DATA = "address-data"
|
CONF_ATTR_IPV6_ADDRESS_DATA = "address-data"
|
||||||
CONF_ATTR_IPV6_GATEWAY = "gateway"
|
CONF_ATTR_IPV6_GATEWAY = "gateway"
|
||||||
CONF_ATTR_IPV6_DNS = "dns"
|
CONF_ATTR_IPV6_DNS = "dns"
|
||||||
@ -69,6 +72,8 @@ IPV4_6_IGNORE_FIELDS = [
|
|||||||
"dns-data",
|
"dns-data",
|
||||||
"gateway",
|
"gateway",
|
||||||
"method",
|
"method",
|
||||||
|
"addr-gen-mode",
|
||||||
|
"ip6-privacy",
|
||||||
]
|
]
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
@ -111,7 +116,7 @@ class NetworkSetting(DBusInterface):
|
|||||||
self._ethernet: EthernetProperties | None = None
|
self._ethernet: EthernetProperties | None = None
|
||||||
self._vlan: VlanProperties | None = None
|
self._vlan: VlanProperties | None = None
|
||||||
self._ipv4: IpProperties | None = None
|
self._ipv4: IpProperties | None = None
|
||||||
self._ipv6: IpProperties | None = None
|
self._ipv6: Ip6Properties | None = None
|
||||||
self._match: MatchProperties | None = None
|
self._match: MatchProperties | None = None
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@ -151,7 +156,7 @@ class NetworkSetting(DBusInterface):
|
|||||||
return self._ipv4
|
return self._ipv4
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ipv6(self) -> IpProperties | None:
|
def ipv6(self) -> Ip6Properties | None:
|
||||||
"""Return ipv6 properties if any."""
|
"""Return ipv6 properties if any."""
|
||||||
return self._ipv6
|
return self._ipv6
|
||||||
|
|
||||||
@ -223,44 +228,52 @@ class NetworkSetting(DBusInterface):
|
|||||||
# See: https://developer-old.gnome.org/NetworkManager/stable/ch01.html
|
# See: https://developer-old.gnome.org/NetworkManager/stable/ch01.html
|
||||||
if CONF_ATTR_CONNECTION in data:
|
if CONF_ATTR_CONNECTION in data:
|
||||||
self._connection = ConnectionProperties(
|
self._connection = ConnectionProperties(
|
||||||
data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_ID),
|
id=data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_ID),
|
||||||
data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_UUID),
|
uuid=data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_UUID),
|
||||||
data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_TYPE),
|
type=data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_TYPE),
|
||||||
data[CONF_ATTR_CONNECTION].get(CONF_ATTR_CONNECTION_INTERFACE_NAME),
|
interface_name=data[CONF_ATTR_CONNECTION].get(
|
||||||
|
CONF_ATTR_CONNECTION_INTERFACE_NAME
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_802_ETHERNET in data:
|
if CONF_ATTR_802_ETHERNET in data:
|
||||||
self._ethernet = EthernetProperties(
|
self._ethernet = EthernetProperties(
|
||||||
data[CONF_ATTR_802_ETHERNET].get(CONF_ATTR_802_ETHERNET_ASSIGNED_MAC),
|
assigned_mac=data[CONF_ATTR_802_ETHERNET].get(
|
||||||
|
CONF_ATTR_802_ETHERNET_ASSIGNED_MAC
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_802_WIRELESS in data:
|
if CONF_ATTR_802_WIRELESS in data:
|
||||||
self._wireless = WirelessProperties(
|
self._wireless = WirelessProperties(
|
||||||
bytes(
|
ssid=bytes(
|
||||||
data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_SSID, [])
|
data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_SSID, [])
|
||||||
).decode(),
|
).decode(),
|
||||||
data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_ASSIGNED_MAC),
|
assigned_mac=data[CONF_ATTR_802_WIRELESS].get(
|
||||||
data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_MODE),
|
CONF_ATTR_802_WIRELESS_ASSIGNED_MAC
|
||||||
data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_POWERSAVE),
|
),
|
||||||
|
mode=data[CONF_ATTR_802_WIRELESS].get(CONF_ATTR_802_WIRELESS_MODE),
|
||||||
|
powersave=data[CONF_ATTR_802_WIRELESS].get(
|
||||||
|
CONF_ATTR_802_WIRELESS_POWERSAVE
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_802_WIRELESS_SECURITY in data:
|
if CONF_ATTR_802_WIRELESS_SECURITY in data:
|
||||||
self._wireless_security = WirelessSecurityProperties(
|
self._wireless_security = WirelessSecurityProperties(
|
||||||
data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
auth_alg=data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
||||||
CONF_ATTR_802_WIRELESS_SECURITY_AUTH_ALG
|
CONF_ATTR_802_WIRELESS_SECURITY_AUTH_ALG
|
||||||
),
|
),
|
||||||
data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
key_mgmt=data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
||||||
CONF_ATTR_802_WIRELESS_SECURITY_KEY_MGMT
|
CONF_ATTR_802_WIRELESS_SECURITY_KEY_MGMT
|
||||||
),
|
),
|
||||||
data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
psk=data[CONF_ATTR_802_WIRELESS_SECURITY].get(
|
||||||
CONF_ATTR_802_WIRELESS_SECURITY_PSK
|
CONF_ATTR_802_WIRELESS_SECURITY_PSK
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_VLAN in data:
|
if CONF_ATTR_VLAN in data:
|
||||||
self._vlan = VlanProperties(
|
self._vlan = VlanProperties(
|
||||||
data[CONF_ATTR_VLAN].get(CONF_ATTR_VLAN_ID),
|
id=data[CONF_ATTR_VLAN].get(CONF_ATTR_VLAN_ID),
|
||||||
data[CONF_ATTR_VLAN].get(CONF_ATTR_VLAN_PARENT),
|
parent=data[CONF_ATTR_VLAN].get(CONF_ATTR_VLAN_PARENT),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_IPV4 in data:
|
if CONF_ATTR_IPV4 in data:
|
||||||
@ -268,21 +281,23 @@ class NetworkSetting(DBusInterface):
|
|||||||
if ips := data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_ADDRESS_DATA):
|
if ips := data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_ADDRESS_DATA):
|
||||||
address_data = [IpAddress(ip["address"], ip["prefix"]) for ip in ips]
|
address_data = [IpAddress(ip["address"], ip["prefix"]) for ip in ips]
|
||||||
self._ipv4 = IpProperties(
|
self._ipv4 = IpProperties(
|
||||||
data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_METHOD),
|
method=data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_METHOD),
|
||||||
address_data,
|
address_data=address_data,
|
||||||
data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_GATEWAY),
|
gateway=data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_GATEWAY),
|
||||||
data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_DNS),
|
dns=data[CONF_ATTR_IPV4].get(CONF_ATTR_IPV4_DNS),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_IPV6 in data:
|
if CONF_ATTR_IPV6 in data:
|
||||||
address_data = None
|
address_data = None
|
||||||
if ips := data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_ADDRESS_DATA):
|
if ips := data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_ADDRESS_DATA):
|
||||||
address_data = [IpAddress(ip["address"], ip["prefix"]) for ip in ips]
|
address_data = [IpAddress(ip["address"], ip["prefix"]) for ip in ips]
|
||||||
self._ipv6 = IpProperties(
|
self._ipv6 = Ip6Properties(
|
||||||
data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_METHOD),
|
method=data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_METHOD),
|
||||||
address_data,
|
addr_gen_mode=data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_ADDR_GEN_MODE),
|
||||||
data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_GATEWAY),
|
ip6_privacy=data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_PRIVACY),
|
||||||
data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_DNS),
|
address_data=address_data,
|
||||||
|
gateway=data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_GATEWAY),
|
||||||
|
dns=data[CONF_ATTR_IPV6].get(CONF_ATTR_IPV6_DNS),
|
||||||
)
|
)
|
||||||
|
|
||||||
if CONF_ATTR_MATCH in data:
|
if CONF_ATTR_MATCH in data:
|
||||||
|
@ -8,8 +8,13 @@ from uuid import uuid4
|
|||||||
|
|
||||||
from dbus_fast import Variant
|
from dbus_fast import Variant
|
||||||
|
|
||||||
from ....host.configuration import VlanConfig
|
from ....host.configuration import Ip6Setting, IpSetting, VlanConfig
|
||||||
from ....host.const import InterfaceMethod, InterfaceType
|
from ....host.const import (
|
||||||
|
InterfaceAddrGenMode,
|
||||||
|
InterfaceIp6Privacy,
|
||||||
|
InterfaceMethod,
|
||||||
|
InterfaceType,
|
||||||
|
)
|
||||||
from .. import NetworkManager
|
from .. import NetworkManager
|
||||||
from . import (
|
from . import (
|
||||||
CONF_ATTR_802_ETHERNET,
|
CONF_ATTR_802_ETHERNET,
|
||||||
@ -36,10 +41,12 @@ from . import (
|
|||||||
CONF_ATTR_IPV4_GATEWAY,
|
CONF_ATTR_IPV4_GATEWAY,
|
||||||
CONF_ATTR_IPV4_METHOD,
|
CONF_ATTR_IPV4_METHOD,
|
||||||
CONF_ATTR_IPV6,
|
CONF_ATTR_IPV6,
|
||||||
|
CONF_ATTR_IPV6_ADDR_GEN_MODE,
|
||||||
CONF_ATTR_IPV6_ADDRESS_DATA,
|
CONF_ATTR_IPV6_ADDRESS_DATA,
|
||||||
CONF_ATTR_IPV6_DNS,
|
CONF_ATTR_IPV6_DNS,
|
||||||
CONF_ATTR_IPV6_GATEWAY,
|
CONF_ATTR_IPV6_GATEWAY,
|
||||||
CONF_ATTR_IPV6_METHOD,
|
CONF_ATTR_IPV6_METHOD,
|
||||||
|
CONF_ATTR_IPV6_PRIVACY,
|
||||||
CONF_ATTR_MATCH,
|
CONF_ATTR_MATCH,
|
||||||
CONF_ATTR_MATCH_PATH,
|
CONF_ATTR_MATCH_PATH,
|
||||||
CONF_ATTR_VLAN,
|
CONF_ATTR_VLAN,
|
||||||
@ -51,7 +58,7 @@ if TYPE_CHECKING:
|
|||||||
from ....host.configuration import Interface
|
from ....host.configuration import Interface
|
||||||
|
|
||||||
|
|
||||||
def _get_ipv4_connection_settings(ipv4setting) -> dict:
|
def _get_ipv4_connection_settings(ipv4setting: IpSetting | None) -> dict:
|
||||||
ipv4 = {}
|
ipv4 = {}
|
||||||
if not ipv4setting or ipv4setting.method == InterfaceMethod.AUTO:
|
if not ipv4setting or ipv4setting.method == InterfaceMethod.AUTO:
|
||||||
ipv4[CONF_ATTR_IPV4_METHOD] = Variant("s", "auto")
|
ipv4[CONF_ATTR_IPV4_METHOD] = Variant("s", "auto")
|
||||||
@ -93,10 +100,32 @@ def _get_ipv4_connection_settings(ipv4setting) -> dict:
|
|||||||
return ipv4
|
return ipv4
|
||||||
|
|
||||||
|
|
||||||
def _get_ipv6_connection_settings(ipv6setting) -> dict:
|
def _get_ipv6_connection_settings(
|
||||||
|
ipv6setting: Ip6Setting | None, support_addr_gen_mode_defaults: bool = False
|
||||||
|
) -> dict:
|
||||||
ipv6 = {}
|
ipv6 = {}
|
||||||
if not ipv6setting or ipv6setting.method == InterfaceMethod.AUTO:
|
if not ipv6setting or ipv6setting.method == InterfaceMethod.AUTO:
|
||||||
ipv6[CONF_ATTR_IPV6_METHOD] = Variant("s", "auto")
|
ipv6[CONF_ATTR_IPV6_METHOD] = Variant("s", "auto")
|
||||||
|
if ipv6setting:
|
||||||
|
if ipv6setting.addr_gen_mode == InterfaceAddrGenMode.EUI64:
|
||||||
|
ipv6[CONF_ATTR_IPV6_ADDR_GEN_MODE] = Variant("i", 0)
|
||||||
|
elif (
|
||||||
|
not support_addr_gen_mode_defaults
|
||||||
|
or ipv6setting.addr_gen_mode == InterfaceAddrGenMode.STABLE_PRIVACY
|
||||||
|
):
|
||||||
|
ipv6[CONF_ATTR_IPV6_ADDR_GEN_MODE] = Variant("i", 1)
|
||||||
|
elif ipv6setting.addr_gen_mode == InterfaceAddrGenMode.DEFAULT_OR_EUI64:
|
||||||
|
ipv6[CONF_ATTR_IPV6_ADDR_GEN_MODE] = Variant("i", 2)
|
||||||
|
else:
|
||||||
|
ipv6[CONF_ATTR_IPV6_ADDR_GEN_MODE] = Variant("i", 3)
|
||||||
|
if ipv6setting.ip6_privacy == InterfaceIp6Privacy.DISABLED:
|
||||||
|
ipv6[CONF_ATTR_IPV6_PRIVACY] = Variant("i", 0)
|
||||||
|
elif ipv6setting.ip6_privacy == InterfaceIp6Privacy.ENABLED_PREFER_PUBLIC:
|
||||||
|
ipv6[CONF_ATTR_IPV6_PRIVACY] = Variant("i", 1)
|
||||||
|
elif ipv6setting.ip6_privacy == InterfaceIp6Privacy.ENABLED:
|
||||||
|
ipv6[CONF_ATTR_IPV6_PRIVACY] = Variant("i", 2)
|
||||||
|
else:
|
||||||
|
ipv6[CONF_ATTR_IPV6_PRIVACY] = Variant("i", -1)
|
||||||
elif ipv6setting.method == InterfaceMethod.DISABLED:
|
elif ipv6setting.method == InterfaceMethod.DISABLED:
|
||||||
ipv6[CONF_ATTR_IPV6_METHOD] = Variant("s", "link-local")
|
ipv6[CONF_ATTR_IPV6_METHOD] = Variant("s", "link-local")
|
||||||
elif ipv6setting.method == InterfaceMethod.STATIC:
|
elif ipv6setting.method == InterfaceMethod.STATIC:
|
||||||
@ -183,7 +212,9 @@ def get_connection_from_interface(
|
|||||||
|
|
||||||
conn[CONF_ATTR_IPV4] = _get_ipv4_connection_settings(interface.ipv4setting)
|
conn[CONF_ATTR_IPV4] = _get_ipv4_connection_settings(interface.ipv4setting)
|
||||||
|
|
||||||
conn[CONF_ATTR_IPV6] = _get_ipv6_connection_settings(interface.ipv6setting)
|
conn[CONF_ATTR_IPV6] = _get_ipv6_connection_settings(
|
||||||
|
interface.ipv6setting, network_manager.version >= "1.40.0"
|
||||||
|
)
|
||||||
|
|
||||||
if interface.type == InterfaceType.ETHERNET:
|
if interface.type == InterfaceType.ETHERNET:
|
||||||
conn[CONF_ATTR_802_ETHERNET] = {
|
conn[CONF_ATTR_802_ETHERNET] = {
|
||||||
|
@ -8,11 +8,20 @@ from ..dbus.const import (
|
|||||||
ConnectionStateFlags,
|
ConnectionStateFlags,
|
||||||
ConnectionStateType,
|
ConnectionStateType,
|
||||||
DeviceType,
|
DeviceType,
|
||||||
|
InterfaceAddrGenMode as NMInterfaceAddrGenMode,
|
||||||
|
InterfaceIp6Privacy as NMInterfaceIp6Privacy,
|
||||||
InterfaceMethod as NMInterfaceMethod,
|
InterfaceMethod as NMInterfaceMethod,
|
||||||
)
|
)
|
||||||
from ..dbus.network.connection import NetworkConnection
|
from ..dbus.network.connection import NetworkConnection
|
||||||
from ..dbus.network.interface import NetworkInterface
|
from ..dbus.network.interface import NetworkInterface
|
||||||
from .const import AuthMethod, InterfaceMethod, InterfaceType, WifiMode
|
from .const import (
|
||||||
|
AuthMethod,
|
||||||
|
InterfaceAddrGenMode,
|
||||||
|
InterfaceIp6Privacy,
|
||||||
|
InterfaceMethod,
|
||||||
|
InterfaceType,
|
||||||
|
WifiMode,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
@ -46,6 +55,14 @@ class IpSetting:
|
|||||||
nameservers: list[IPv4Address | IPv6Address]
|
nameservers: list[IPv4Address | IPv6Address]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(slots=True)
|
||||||
|
class Ip6Setting(IpSetting):
|
||||||
|
"""Represent a user IPv6 setting."""
|
||||||
|
|
||||||
|
addr_gen_mode: InterfaceAddrGenMode = InterfaceAddrGenMode.DEFAULT
|
||||||
|
ip6_privacy: InterfaceIp6Privacy = InterfaceIp6Privacy.DEFAULT
|
||||||
|
|
||||||
|
|
||||||
@dataclass(slots=True)
|
@dataclass(slots=True)
|
||||||
class WifiConfig:
|
class WifiConfig:
|
||||||
"""Represent a wifi configuration."""
|
"""Represent a wifi configuration."""
|
||||||
@ -79,7 +96,7 @@ class Interface:
|
|||||||
ipv4: IpConfig | None
|
ipv4: IpConfig | None
|
||||||
ipv4setting: IpSetting | None
|
ipv4setting: IpSetting | None
|
||||||
ipv6: IpConfig | None
|
ipv6: IpConfig | None
|
||||||
ipv6setting: IpSetting | None
|
ipv6setting: Ip6Setting | None
|
||||||
wifi: WifiConfig | None
|
wifi: WifiConfig | None
|
||||||
vlan: VlanConfig | None
|
vlan: VlanConfig | None
|
||||||
|
|
||||||
@ -118,8 +135,14 @@ class Interface:
|
|||||||
ipv4_setting = IpSetting(InterfaceMethod.DISABLED, [], None, [])
|
ipv4_setting = IpSetting(InterfaceMethod.DISABLED, [], None, [])
|
||||||
|
|
||||||
if inet.settings and inet.settings.ipv6:
|
if inet.settings and inet.settings.ipv6:
|
||||||
ipv6_setting = IpSetting(
|
ipv6_setting = Ip6Setting(
|
||||||
method=Interface._map_nm_method(inet.settings.ipv6.method),
|
method=Interface._map_nm_method(inet.settings.ipv6.method),
|
||||||
|
addr_gen_mode=Interface._map_nm_addr_gen_mode(
|
||||||
|
inet.settings.ipv6.addr_gen_mode
|
||||||
|
),
|
||||||
|
ip6_privacy=Interface._map_nm_ip6_privacy(
|
||||||
|
inet.settings.ipv6.ip6_privacy
|
||||||
|
),
|
||||||
address=[
|
address=[
|
||||||
IPv6Interface(f"{ip.address}/{ip.prefix}")
|
IPv6Interface(f"{ip.address}/{ip.prefix}")
|
||||||
for ip in inet.settings.ipv6.address_data
|
for ip in inet.settings.ipv6.address_data
|
||||||
@ -134,7 +157,7 @@ class Interface:
|
|||||||
else [],
|
else [],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ipv6_setting = IpSetting(InterfaceMethod.DISABLED, [], None, [])
|
ipv6_setting = Ip6Setting(InterfaceMethod.DISABLED, [], None, [])
|
||||||
|
|
||||||
ipv4_ready = (
|
ipv4_ready = (
|
||||||
bool(inet.connection)
|
bool(inet.connection)
|
||||||
@ -195,6 +218,28 @@ class Interface:
|
|||||||
|
|
||||||
return mapping.get(method, InterfaceMethod.DISABLED)
|
return mapping.get(method, InterfaceMethod.DISABLED)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _map_nm_addr_gen_mode(addr_gen_mode: int) -> InterfaceAddrGenMode:
|
||||||
|
"""Map IPv6 interface addr_gen_mode."""
|
||||||
|
mapping = {
|
||||||
|
NMInterfaceAddrGenMode.EUI64: InterfaceAddrGenMode.EUI64,
|
||||||
|
NMInterfaceAddrGenMode.STABLE_PRIVACY: InterfaceAddrGenMode.STABLE_PRIVACY,
|
||||||
|
NMInterfaceAddrGenMode.DEFAULT_OR_EUI64: InterfaceAddrGenMode.DEFAULT_OR_EUI64,
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping.get(addr_gen_mode, InterfaceAddrGenMode.DEFAULT)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _map_nm_ip6_privacy(ip6_privacy: int) -> InterfaceIp6Privacy:
|
||||||
|
"""Map IPv6 interface ip6_privacy."""
|
||||||
|
mapping = {
|
||||||
|
NMInterfaceIp6Privacy.DISABLED: InterfaceIp6Privacy.DISABLED,
|
||||||
|
NMInterfaceIp6Privacy.ENABLED_PREFER_PUBLIC: InterfaceIp6Privacy.ENABLED_PREFER_PUBLIC,
|
||||||
|
NMInterfaceIp6Privacy.ENABLED: InterfaceIp6Privacy.ENABLED,
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping.get(ip6_privacy, InterfaceIp6Privacy.DEFAULT)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _map_nm_connected(connection: NetworkConnection | None) -> bool:
|
def _map_nm_connected(connection: NetworkConnection | None) -> bool:
|
||||||
"""Map connectivity state."""
|
"""Map connectivity state."""
|
||||||
|
@ -15,6 +15,24 @@ class InterfaceMethod(StrEnum):
|
|||||||
AUTO = "auto"
|
AUTO = "auto"
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceAddrGenMode(StrEnum):
|
||||||
|
"""Configuration of an interface."""
|
||||||
|
|
||||||
|
EUI64 = "eui64"
|
||||||
|
STABLE_PRIVACY = "stable-privacy"
|
||||||
|
DEFAULT_OR_EUI64 = "default-or-eui64"
|
||||||
|
DEFAULT = "default"
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceIp6Privacy(StrEnum):
|
||||||
|
"""Configuration of an interface."""
|
||||||
|
|
||||||
|
DEFAULT = "default"
|
||||||
|
DISABLED = "disabled"
|
||||||
|
ENABLED_PREFER_PUBLIC = "enabled-prefer-public"
|
||||||
|
ENABLED = "enabled"
|
||||||
|
|
||||||
|
|
||||||
class InterfaceType(StrEnum):
|
class InterfaceType(StrEnum):
|
||||||
"""Configuration of an interface."""
|
"""Configuration of an interface."""
|
||||||
|
|
||||||
|
@ -51,8 +51,10 @@ async def test_api_network_info(api_client: TestClient, coresys: CoreSys):
|
|||||||
"ready": False,
|
"ready": False,
|
||||||
}
|
}
|
||||||
assert interface["ipv6"] == {
|
assert interface["ipv6"] == {
|
||||||
|
"addr_gen_mode": "default",
|
||||||
"address": [],
|
"address": [],
|
||||||
"gateway": None,
|
"gateway": None,
|
||||||
|
"ip6_privacy": "default",
|
||||||
"method": "disabled",
|
"method": "disabled",
|
||||||
"nameservers": [],
|
"nameservers": [],
|
||||||
"ready": False,
|
"ready": False,
|
||||||
|
@ -5,7 +5,7 @@ from unittest.mock import PropertyMock, patch
|
|||||||
from supervisor.dbus.network import NetworkManager
|
from supervisor.dbus.network import NetworkManager
|
||||||
from supervisor.dbus.network.interface import NetworkInterface
|
from supervisor.dbus.network.interface import NetworkInterface
|
||||||
from supervisor.dbus.network.setting.generate import get_connection_from_interface
|
from supervisor.dbus.network.setting.generate import get_connection_from_interface
|
||||||
from supervisor.host.configuration import IpConfig, IpSetting, VlanConfig
|
from supervisor.host.configuration import Ip6Setting, IpConfig, IpSetting, VlanConfig
|
||||||
from supervisor.host.const import InterfaceMethod, InterfaceType
|
from supervisor.host.const import InterfaceMethod, InterfaceType
|
||||||
from supervisor.host.network import Interface
|
from supervisor.host.network import Interface
|
||||||
|
|
||||||
@ -57,8 +57,8 @@ async def test_generate_from_vlan(network_manager: NetworkManager):
|
|||||||
type=InterfaceType.VLAN,
|
type=InterfaceType.VLAN,
|
||||||
ipv4=IpConfig([], None, [], None),
|
ipv4=IpConfig([], None, [], None),
|
||||||
ipv4setting=IpSetting(InterfaceMethod.AUTO, [], None, []),
|
ipv4setting=IpSetting(InterfaceMethod.AUTO, [], None, []),
|
||||||
ipv6=None,
|
ipv6=IpConfig([], None, [], None),
|
||||||
ipv6setting=None,
|
ipv6setting=Ip6Setting(InterfaceMethod.AUTO, [], None, []),
|
||||||
wifi=None,
|
wifi=None,
|
||||||
vlan=VlanConfig(1, "eth0"),
|
vlan=VlanConfig(1, "eth0"),
|
||||||
)
|
)
|
||||||
@ -70,6 +70,8 @@ async def test_generate_from_vlan(network_manager: NetworkManager):
|
|||||||
assert "match" not in connection_payload["connection"]
|
assert "match" not in connection_payload["connection"]
|
||||||
assert "interface-name" not in connection_payload["connection"]
|
assert "interface-name" not in connection_payload["connection"]
|
||||||
assert connection_payload["ipv4"]["method"].value == "auto"
|
assert connection_payload["ipv4"]["method"].value == "auto"
|
||||||
|
assert connection_payload["ipv6"]["addr-gen-mode"].value == 1
|
||||||
|
assert connection_payload["ipv6"]["ip6-privacy"].value == -1
|
||||||
|
|
||||||
assert connection_payload["vlan"]["id"].value == 1
|
assert connection_payload["vlan"]["id"].value == 1
|
||||||
assert (
|
assert (
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
"""Test Network Manager Connection object."""
|
"""Test Network Manager Connection object."""
|
||||||
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
|
|
||||||
|
from awesomeversion import AwesomeVersion
|
||||||
from dbus_fast import Variant
|
from dbus_fast import Variant
|
||||||
from dbus_fast.aio.message_bus import MessageBus
|
from dbus_fast.aio.message_bus import MessageBus
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from supervisor.dbus.network import NetworkManager
|
||||||
from supervisor.dbus.network.interface import NetworkInterface
|
from supervisor.dbus.network.interface import NetworkInterface
|
||||||
from supervisor.dbus.network.setting import NetworkSetting
|
from supervisor.dbus.network.setting import NetworkSetting
|
||||||
from supervisor.dbus.network.setting.generate import get_connection_from_interface
|
from supervisor.dbus.network.setting.generate import get_connection_from_interface
|
||||||
|
from supervisor.host.configuration import Ip6Setting
|
||||||
from supervisor.host.const import InterfaceMethod
|
from supervisor.host.const import InterfaceMethod
|
||||||
from supervisor.host.network import Interface
|
from supervisor.host.network import Interface
|
||||||
|
|
||||||
@ -48,6 +51,7 @@ async def fixture_dbus_interface(
|
|||||||
async def test_ethernet_update(
|
async def test_ethernet_update(
|
||||||
dbus_interface: NetworkInterface,
|
dbus_interface: NetworkInterface,
|
||||||
connection_settings_service: ConnectionSettingsService,
|
connection_settings_service: ConnectionSettingsService,
|
||||||
|
network_manager: NetworkManager,
|
||||||
):
|
):
|
||||||
"""Test network manager update."""
|
"""Test network manager update."""
|
||||||
connection_settings_service.Update.calls.clear()
|
connection_settings_service.Update.calls.clear()
|
||||||
@ -55,7 +59,7 @@ async def test_ethernet_update(
|
|||||||
interface = Interface.from_dbus_interface(dbus_interface)
|
interface = Interface.from_dbus_interface(dbus_interface)
|
||||||
conn = get_connection_from_interface(
|
conn = get_connection_from_interface(
|
||||||
interface,
|
interface,
|
||||||
MagicMock(),
|
network_manager,
|
||||||
name=dbus_interface.settings.connection.id,
|
name=dbus_interface.settings.connection.id,
|
||||||
uuid=dbus_interface.settings.connection.uuid,
|
uuid=dbus_interface.settings.connection.uuid,
|
||||||
)
|
)
|
||||||
@ -124,14 +128,16 @@ async def test_ethernet_update(
|
|||||||
assert "802-11-wireless-security" not in settings
|
assert "802-11-wireless-security" not in settings
|
||||||
|
|
||||||
|
|
||||||
async def test_ipv6_disabled_is_link_local(dbus_interface: NetworkInterface):
|
async def test_ipv6_disabled_is_link_local(
|
||||||
|
dbus_interface: NetworkInterface, network_manager: NetworkManager
|
||||||
|
):
|
||||||
"""Test disabled equals link local for ipv6."""
|
"""Test disabled equals link local for ipv6."""
|
||||||
interface = Interface.from_dbus_interface(dbus_interface)
|
interface = Interface.from_dbus_interface(dbus_interface)
|
||||||
interface.ipv4setting.method = InterfaceMethod.DISABLED
|
interface.ipv4setting.method = InterfaceMethod.DISABLED
|
||||||
interface.ipv6setting.method = InterfaceMethod.DISABLED
|
interface.ipv6setting.method = InterfaceMethod.DISABLED
|
||||||
conn = get_connection_from_interface(
|
conn = get_connection_from_interface(
|
||||||
interface,
|
interface,
|
||||||
MagicMock(),
|
network_manager,
|
||||||
name=dbus_interface.settings.connection.id,
|
name=dbus_interface.settings.connection.id,
|
||||||
uuid=dbus_interface.settings.connection.uuid,
|
uuid=dbus_interface.settings.connection.uuid,
|
||||||
)
|
)
|
||||||
@ -140,6 +146,33 @@ async def test_ipv6_disabled_is_link_local(dbus_interface: NetworkInterface):
|
|||||||
assert conn["ipv6"]["method"] == Variant("s", "link-local")
|
assert conn["ipv6"]["method"] == Variant("s", "link-local")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
["version", "addr_gen_mode"],
|
||||||
|
[
|
||||||
|
("1.38.0", 1),
|
||||||
|
("1.40.0", 3),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_ipv6_addr_gen_mode(
|
||||||
|
dbus_interface: NetworkInterface, version: str, addr_gen_mode: int
|
||||||
|
):
|
||||||
|
"""Test addr_gen_mode with various NetworkManager versions."""
|
||||||
|
interface = Interface.from_dbus_interface(dbus_interface)
|
||||||
|
interface.ipv6setting = Ip6Setting(InterfaceMethod.AUTO, [], None, [])
|
||||||
|
|
||||||
|
network_manager = MagicMock()
|
||||||
|
type(network_manager).version = PropertyMock(return_value=AwesomeVersion(version))
|
||||||
|
conn = get_connection_from_interface(
|
||||||
|
interface,
|
||||||
|
network_manager,
|
||||||
|
name=dbus_interface.settings.connection.id,
|
||||||
|
uuid=dbus_interface.settings.connection.uuid,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert conn["ipv6"]["method"] == Variant("s", "auto")
|
||||||
|
assert conn["ipv6"]["addr-gen-mode"] == Variant("i", addr_gen_mode)
|
||||||
|
|
||||||
|
|
||||||
async def test_watching_updated_signal(
|
async def test_watching_updated_signal(
|
||||||
connection_settings_service: ConnectionSettingsService, dbus_session_bus: MessageBus
|
connection_settings_service: ConnectionSettingsService, dbus_session_bus: MessageBus
|
||||||
):
|
):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user