schema: Add constants for IP subtree

Three class was added:

    * schema.InterfaceIP
    * schema.InterfaceIPv4
    * schema.InterfaceIPv6

Signed-off-by: Gris Ge <fge@redhat.com>
This commit is contained in:
Gris Ge 2019-07-23 01:33:34 +08:00 committed by Edward Haas
parent d33d0fb9b7
commit 191e6343a2
26 changed files with 810 additions and 427 deletions

View File

@ -25,6 +25,7 @@ from libnmstate.error import NmstateValueError
from libnmstate import nm
from libnmstate.schema import DNS
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIP
from libnmstate.schema import InterfaceState
@ -342,7 +343,7 @@ def _dns_config_not_changed(desired_state, current_state):
return False
for family in six.viewkeys(iface_dns_config):
if family in iface_state and not iface_state[family].get(
'enabled'
InterfaceIP.ENABLED
):
return False
return True

View File

@ -22,12 +22,13 @@ import socket
from . import nmclient
from libnmstate.nm import dns as nm_dns
from libnmstate.nm import route as nm_route
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import Route
def create_setting(config, base_con_profile):
setting_ipv4 = None
if base_con_profile and config and config.get('enabled'):
if base_con_profile and config and config.get(InterfaceIPv4.ENABLED):
setting_ipv4 = base_con_profile.get_setting_ip4_config()
if setting_ipv4:
setting_ipv4 = setting_ipv4.duplicate()
@ -47,25 +48,25 @@ def create_setting(config, base_con_profile):
setting_ipv4 = nmclient.NM.SettingIP4Config.new()
setting_ipv4.props.method = nmclient.NM.SETTING_IP4_CONFIG_METHOD_DISABLED
if config and config.get('enabled'):
if config.get('dhcp'):
if config and config.get(InterfaceIPv4.ENABLED):
if config.get(InterfaceIPv4.DHCP):
setting_ipv4.props.method = (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO
)
setting_ipv4.props.ignore_auto_routes = not config.get(
'auto-routes', True
InterfaceIPv4.AUTO_ROUTES, True
)
setting_ipv4.props.never_default = not config.get(
'auto-gateway', True
InterfaceIPv4.AUTO_GATEWAY, True
)
setting_ipv4.props.ignore_auto_dns = not config.get(
'auto-dns', True
InterfaceIPv4.AUTO_DNS, True
)
elif config.get('address'):
elif config.get(InterfaceIPv4.ADDRESS):
setting_ipv4.props.method = (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_MANUAL
)
_add_addresses(setting_ipv4, config['address'])
_add_addresses(setting_ipv4, config[InterfaceIPv4.ADDRESS])
nm_route.add_routes(
setting_ipv4, config.get(nm_route.ROUTE_METADATA, [])
)
@ -76,7 +77,9 @@ def create_setting(config, base_con_profile):
def _add_addresses(setting_ipv4, addresses):
for address in addresses:
naddr = nmclient.NM.IPAddress.new(
socket.AF_INET, address['ip'], address['prefix-length']
socket.AF_INET,
address[InterfaceIPv4.ADDRESS_IP],
address[InterfaceIPv4.ADDRESS_PREFIX_LENGTH],
)
setting_ipv4.add_address(naddr)
@ -88,42 +91,43 @@ def get_info(active_connection):
configuration (as in the case of ipv4.method=auto, where the address is
not explicitly defined).
"""
info = {'enabled': False}
info = {InterfaceIPv4.ENABLED: False}
if active_connection is None:
return info
ip_profile = get_ip_profile(active_connection)
if ip_profile:
info['dhcp'] = ip_profile.get_method() == (
info[InterfaceIPv4.DHCP] = ip_profile.get_method() == (
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO
)
props = ip_profile.props
if info['dhcp']:
info['auto-routes'] = not ip_profile.props.ignore_auto_routes
info['auto-gateway'] = not ip_profile.props.never_default
info['auto-dns'] = not ip_profile.props.ignore_auto_dns
info['enabled'] = True
info['address'] = []
info[InterfaceIPv4.AUTO_ROUTES] = not props.ignore_auto_routes
info[InterfaceIPv4.AUTO_GATEWAY] = not props.never_default
info[InterfaceIPv4.AUTO_DNS] = not props.ignore_auto_dns
info[InterfaceIPv4.ENABLED] = True
info[InterfaceIPv4.ADDRESS] = []
else:
info['dhcp'] = False
info[InterfaceIPv4.DHCP] = False
ip4config = active_connection.get_ip4_config()
if ip4config is None:
if not info['dhcp']:
del info['dhcp']
if not info[InterfaceIPv4.DHCP]:
del info[InterfaceIPv4.DHCP]
return info
addresses = [
{
'ip': address.get_address(),
'prefix-length': int(address.get_prefix()),
InterfaceIPv4.ADDRESS_IP: address.get_address(),
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: int(address.get_prefix()),
}
for address in ip4config.get_addresses()
]
if not addresses:
return info
info['enabled'] = True
info['address'] = addresses
info[InterfaceIPv4.ENABLED] = True
info[InterfaceIPv4.ADDRESS] = addresses
return info

View File

@ -25,6 +25,7 @@ from libnmstate.error import NmstateNotImplementedError
from libnmstate.nm import nmclient
from libnmstate.nm import dns as nm_dns
from libnmstate.nm import route as nm_route
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import Route
@ -32,62 +33,67 @@ IPV6_DEFAULT_ROUTE_METRIC = 1024
def get_info(active_connection):
info = {'enabled': False}
info = {InterfaceIPv6.ENABLED: False}
if active_connection is None:
return info
info['dhcp'] = False
info['autoconf'] = False
info[InterfaceIPv6.DHCP] = False
info[InterfaceIPv6.AUTOCONF] = False
is_link_local_method = False
ip_profile = get_ip_profile(active_connection)
if ip_profile:
method = ip_profile.get_method()
if method == nmclient.NM.SETTING_IP6_CONFIG_METHOD_AUTO:
info['dhcp'] = True
info['autoconf'] = True
info[InterfaceIPv6.DHCP] = True
info[InterfaceIPv6.AUTOCONF] = True
elif method == nmclient.NM.SETTING_IP6_CONFIG_METHOD_DHCP:
info['dhcp'] = True
info['autoconf'] = False
info[InterfaceIPv6.DHCP] = True
info[InterfaceIPv6.AUTOCONF] = False
elif method == nmclient.NM.SETTING_IP6_CONFIG_METHOD_LINK_LOCAL:
is_link_local_method = True
if info['dhcp'] or info['autoconf']:
info['auto-routes'] = not ip_profile.props.ignore_auto_routes
info['auto-gateway'] = not ip_profile.props.never_default
info['auto-dns'] = not ip_profile.props.ignore_auto_dns
if info[InterfaceIPv6.DHCP] or info[InterfaceIPv6.AUTOCONF]:
props = ip_profile.props
info[InterfaceIPv6.AUTO_ROUTES] = not props.ignore_auto_routes
info[InterfaceIPv6.AUTO_GATEWAY] = not props.never_default
info[InterfaceIPv6.AUTO_DNS] = not props.ignore_auto_dns
ipconfig = active_connection.get_ip6_config()
if ipconfig is None:
# When DHCP is enable, it might be possible, the active_connection does
# not got IP address yet. In that case, we still mark
# info['enabled'] as True.
if info['dhcp'] or info['autoconf'] or is_link_local_method:
info['enabled'] = True
info['address'] = []
# info[InterfaceIPv6.ENABLED] as True.
if (
info[InterfaceIPv6.DHCP]
or info[InterfaceIPv6.AUTOCONF]
or is_link_local_method
):
info[InterfaceIPv6.ENABLED] = True
info[InterfaceIPv6.ADDRESS] = []
else:
del info['dhcp']
del info['autoconf']
del info[InterfaceIPv6.DHCP]
del info[InterfaceIPv6.AUTOCONF]
return info
addresses = [
{
'ip': address.get_address(),
'prefix-length': int(address.get_prefix()),
InterfaceIPv6.ADDRESS_IP: address.get_address(),
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: int(address.get_prefix()),
}
for address in ipconfig.get_addresses()
]
if not addresses:
return info
info['enabled'] = True
info['address'] = addresses
info[InterfaceIPv6.ENABLED] = True
info[InterfaceIPv6.ADDRESS] = addresses
return info
def create_setting(config, base_con_profile):
setting_ip = None
if base_con_profile and config and config.get('enabled'):
if base_con_profile and config and config.get(InterfaceIPv6.ENABLED):
setting_ip = base_con_profile.get_setting_ip6_config()
if setting_ip:
setting_ip = setting_ip.duplicate()
@ -106,21 +112,25 @@ def create_setting(config, base_con_profile):
if not setting_ip:
setting_ip = nmclient.NM.SettingIP6Config.new()
if not config or not config.get('enabled'):
if not config or not config.get(InterfaceIPv6.ENABLED):
setting_ip.props.method = nmclient.NM.SETTING_IP6_CONFIG_METHOD_IGNORE
return setting_ip
is_dhcp = config.get('dhcp', False)
is_autoconf = config.get('autoconf', False)
ip_addresses = config.get('address', ())
is_dhcp = config.get(InterfaceIPv6.DHCP, False)
is_autoconf = config.get(InterfaceIPv6.AUTOCONF, False)
ip_addresses = config.get(InterfaceIPv6.ADDRESS, ())
if is_dhcp or is_autoconf:
_set_dynamic(setting_ip, is_dhcp, is_autoconf)
setting_ip.props.ignore_auto_routes = not config.get(
'auto-routes', True
InterfaceIPv6.AUTO_ROUTES, True
)
setting_ip.props.never_default = not config.get(
InterfaceIPv6.AUTO_GATEWAY, True
)
setting_ip.props.ignore_auto_dns = not config.get(
InterfaceIPv6.AUTO_DNS, True
)
setting_ip.props.never_default = not config.get('auto-gateway', True)
setting_ip.props.ignore_auto_dns = not config.get('auto-dns', True)
elif ip_addresses:
_set_static(setting_ip, ip_addresses)
else:
@ -148,7 +158,8 @@ def _set_dynamic(setting_ip, is_dhcp, is_autoconf):
def _set_static(setting_ip, ip_addresses):
for address in ip_addresses:
if iplib.is_ipv6_link_local_addr(
address['ip'], address['prefix-length']
address[InterfaceIPv6.ADDRESS_IP],
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
):
logging.warning(
'IPv6 link local address '
@ -157,7 +168,9 @@ def _set_static(setting_ip, ip_addresses):
)
else:
naddr = nmclient.NM.IPAddress.new(
socket.AF_INET6, address['ip'], address['prefix-length']
socket.AF_INET6,
address[InterfaceIPv6.ADDRESS_IP],
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
)
setting_ip.add_address(naddr)

View File

@ -106,6 +106,25 @@ class InterfaceType(object):
)
class InterfaceIP(object):
ENABLED = 'enabled'
ADDRESS = 'address'
ADDRESS_IP = 'ip'
ADDRESS_PREFIX_LENGTH = 'prefix-length'
DHCP = 'dhcp'
AUTO_DNS = 'auto-dns'
AUTO_GATEWAY = 'auto-gateway'
AUTO_ROUTES = 'auto-routes'
class InterfaceIPv4(InterfaceIP):
pass
class InterfaceIPv6(InterfaceIP):
AUTOCONF = 'autoconf'
class Bond(object):
KEY = InterfaceType.BOND
CONFIG_SUBTREE = 'link-aggregation'

View File

@ -40,6 +40,9 @@ from libnmstate.prettystate import format_desired_current_state_diff
from libnmstate.schema import DNS
from libnmstate.schema import Ethernet
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIP
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import InterfaceType
from libnmstate.schema import Route
@ -224,15 +227,15 @@ class State(object):
for iface_state in six.viewvalues(self.interfaces):
for family in ('ipv4', 'ipv6'):
ip = iface_state[family]
if ip.get('enabled') and (
ip.get('dhcp') or ip.get('autoconf')
if ip.get(InterfaceIP.ENABLED) and (
ip.get(InterfaceIP.DHCP) or ip.get(InterfaceIPv6.AUTOCONF)
):
ip['address'] = []
ip[InterfaceIP.ADDRESS] = []
else:
for dhcp_option in (
'auto-routes',
'auto-gateway',
'auto-dns',
InterfaceIP.AUTO_ROUTES,
InterfaceIP.AUTO_GATEWAY,
InterfaceIP.AUTO_DNS,
):
ip.pop(dhcp_option, None)
@ -351,14 +354,14 @@ class State(object):
iface_up = ifstate.get(Interface.STATE) not in NON_UP_STATES
if iface_up:
ipv4_state = ifstate.get(Interface.IPV4, {})
ipv4_disabled = ipv4_state.get('enabled') is False
ipv4_disabled = ipv4_state.get(InterfaceIPv4.ENABLED) is False
if ipv4_disabled and any(
not is_ipv6_address(r.destination) for r in routes
):
return False
ipv6_state = ifstate.get(Interface.IPV6, {})
ipv6_disabled = ipv6_state.get('enabled') is False
ipv6_disabled = ipv6_state.get(InterfaceIPv6.ENABLED) is False
if ipv6_disabled and any(
is_ipv6_address(r.destination) for r in routes
):
@ -438,24 +441,32 @@ class State(object):
def _canonicalize_ipv6(self):
for ifstate in six.viewvalues(self.interfaces):
new_state = {Interface.IPV6: {'enabled': False, 'address': []}}
new_state = {
Interface.IPV6: {
InterfaceIPv6.ENABLED: False,
InterfaceIPv6.ADDRESS: [],
}
}
dict_update(new_state, ifstate)
self._ifaces_state[ifstate[Interface.NAME]] = new_state
def _remove_iface_ipv6_link_local_addr(self):
for ifstate in six.viewvalues(self.interfaces):
ifstate['ipv6']['address'] = list(
ifstate['ipv6'][InterfaceIPv6.ADDRESS] = list(
addr
for addr in ifstate['ipv6']['address']
for addr in ifstate['ipv6'][InterfaceIPv6.ADDRESS]
if not iplib.is_ipv6_link_local_addr(
addr['ip'], addr['prefix-length']
addr[InterfaceIPv6.ADDRESS_IP],
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
)
)
def _sort_ip_addresses(self):
for ifstate in six.viewvalues(self.interfaces):
for family in ('ipv4', 'ipv6'):
ifstate[family].get('address', []).sort(key=itemgetter('ip'))
ifstate[family].get(InterfaceIP.ADDRESS, []).sort(
key=itemgetter(InterfaceIP.ADDRESS_IP)
)
def _capitalize_mac(self):
for ifstate in six.viewvalues(self.interfaces):
@ -559,10 +570,10 @@ def _get_ip_enable_states(family, desire_state, current_state):
ip_enable_states = {}
for iface_name, iface_state in six.viewitems(current_state.interfaces):
ip_enable_states[iface_name] = iface_state.get(family, {}).get(
'enabled', False
InterfaceIP.ENABLED, False
)
for iface_name, iface_state in six.viewitems(desire_state.interfaces):
ip_enable_state = iface_state.get(family, {}).get('enabled')
ip_enable_state = iface_state.get(family, {}).get(InterfaceIP.ENABLED)
if ip_enable_state is not None:
# If desire_state does not have Interface.IPV4/IPV6, it will use
# current_state settings.

View File

@ -27,6 +27,8 @@ from . import nm
from . import schema
from .schema import Constants
from libnmstate.schema import DNS
from libnmstate.schema import InterfaceIP
from libnmstate.schema import InterfaceIPv6
from libnmstate.error import NmstateDependencyError
from libnmstate.error import NmstateNotImplementedError
from libnmstate.error import NmstateValueError
@ -111,9 +113,11 @@ def validate_dhcp(state):
for family in ('ipv4', 'ipv6'):
ip = iface_state.get(family, {})
if (
ip.get('enabled')
and ip.get('address')
and (ip.get('dhcp') or ip.get('autoconf'))
ip.get(InterfaceIP.ENABLED)
and ip.get(InterfaceIP.ADDRESS)
and (
ip.get(InterfaceIP.DHCP) or ip.get(InterfaceIPv6.AUTOCONF)
)
):
logging.warning(
'%s addresses are ignored when ' 'dynamic IP is enabled',
@ -200,12 +204,12 @@ def _assert_iface_ip_enabled(desired_iface_state, current_iface_state, ipkey):
if desired_iface_state:
ip_state = desired_iface_state.get(ipkey)
if ip_state is not None:
ip_enabled = ip_state.get('enabled')
ip_enabled = ip_state.get(InterfaceIP.ENABLED)
if ip_enabled is True:
return
elif ip_enabled is False:
raise NmstateRouteWithNoIPInterfaceError(desired_iface_state)
if current_iface_state:
ip_state = current_iface_state.get(ipkey)
if not ip_state.get('enabled'):
if not ip_state.get(InterfaceIP.ENABLED):
raise NmstateRouteWithNoIPInterfaceError(current_iface_state)

View File

@ -29,6 +29,8 @@ from libnmstate.schema import BondMode
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceState
from libnmstate.schema import InterfaceType
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from .testlib import assertlib
from .testlib import statelib
@ -175,9 +177,12 @@ def test_add_bond_with_slaves_and_ipv4(eth1_up, eth2_up, setup_remove_bond99):
Interface.TYPE: InterfaceType.BOND,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {
'enabled': True,
'address': [
{'ip': '192.168.122.250', 'prefix-length': 24}
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.168.122.250',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
Bond.CONFIG_SUBTREE: {
@ -206,9 +211,12 @@ def test_rollback_for_bond(eth1_up, eth2_up):
Interface.TYPE: InterfaceType.BOND,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {
'enabled': True,
'address': [
{'ip': '192.168.122.250', 'prefix-length': 24}
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.168.122.250',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
Bond.CONFIG_SUBTREE: {
@ -349,7 +357,11 @@ def test_reordering_the_slaves_does_not_change_the_mac(bond99_with_2_slaves):
def test_bond_with_empty_ipv6_static_address(eth1_up):
extra_iface_state = {
Interface.IPV6: {'enabled': True, 'autoconf': False, 'dhcp': False}
Interface.IPV6: {
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.DHCP: False,
}
}
with bond_interface(
name='bond99', slaves=['eth1'], extra_iface_state=extra_iface_state

View File

@ -22,6 +22,7 @@ import logging
import pytest
import libnmstate
from libnmstate.schema import InterfaceIPv6
from .testlib import statelib
from .testlib.statelib import INTERFACES
@ -79,7 +80,9 @@ def _set_eth_admin_state(ifname, state):
}
# FIXME: On most systems, IPv6 cannot be disabled by Nmstate/NM.
if state == 'up':
desired_state[INTERFACES][0].update({'ipv6': {'enabled': True}})
desired_state[INTERFACES][0].update(
{'ipv6': {InterfaceIPv6.ENABLED: True}}
)
libnmstate.apply(desired_state)

View File

@ -24,6 +24,8 @@ import pytest
import libnmstate
from libnmstate.schema import Constants
from libnmstate.schema import DNS
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import Route as RT
from libnmstate.error import NmstateNotImplementedError
@ -151,12 +153,12 @@ def test_ipv4_dhcp(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = True
dhcp_cli_desired_state['ipv4']['auto-routes'] = True
dhcp_cli_desired_state['ipv4']['auto-dns'] = True
dhcp_cli_desired_state['ipv4']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_ROUTES] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
assertlib.assert_state(desired_state)
@ -170,12 +172,12 @@ def test_ipv6_dhcp_only(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = False
dhcp_cli_desired_state['ipv6']['auto-routes'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = True
libnmstate.apply(desired_state)
@ -184,8 +186,11 @@ def test_ipv6_dhcp_only(dhcp_env):
current_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_current_state = current_state[INTERFACES][0]
has_dhcp_ip_addr = False
for addr in dhcp_cli_current_state['ipv6']['address']:
if addr['prefix-length'] == 128 and DHCP_SRV_IP6_PREFIX in addr['ip']:
for addr in dhcp_cli_current_state['ipv6'][InterfaceIPv6.ADDRESS]:
if (
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH] == 128
and DHCP_SRV_IP6_PREFIX in addr[InterfaceIPv6.ADDRESS_IP]
):
has_dhcp_ip_addr = True
break
assert has_dhcp_ip_addr
@ -198,12 +203,12 @@ def test_ipv6_dhcp_and_autoconf(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['auto-routes'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = True
libnmstate.apply(desired_state)
@ -218,8 +223,8 @@ def test_ipv6_dhcp_and_autoconf(dhcp_env):
def test_ipv6_autoconf_only(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['ipv6']['dhcp'] = False
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
libnmstate.apply(desired_state)
@ -232,20 +237,32 @@ def test_dhcp_with_addresses(dhcp_env):
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'dhcp': True,
'address': [
{'ip': IPV4_ADDRESS1, 'prefix-length': 24},
{'ip': IPV4_ADDRESS2, 'prefix-length': 24},
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS2,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
],
},
'ipv6': {
'enabled': True,
'dhcp': True,
'autoconf': True,
'address': [
{'ip': IPV6_ADDRESS1, 'prefix-length': 64},
{'ip': IPV6_ADDRESS2, 'prefix-length': 64},
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.DHCP: True,
InterfaceIPv6.AUTOCONF: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS2,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
],
},
}
@ -266,7 +283,10 @@ def test_dhcp_for_bond_with_ip_address_and_slave(
'name': 'bond99',
'type': 'bond',
'state': 'up',
'ipv4': {'enabled': True, 'dhcp': False},
'ipv4': {
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: False,
},
'link-aggregation': {
'mode': 'balance-rr',
'slaves': [DHCP_CLI_NIC],
@ -289,7 +309,7 @@ def test_dhcp_for_bond_with_ip_address_and_slave(
# As above, the master bond99 might has no link carrier, hence the
# interface will result in `state:down`. As a workaround the
# verification is ignored.
desired_state[INTERFACES][0]['ipv4']['dhcp'] = True
desired_state[INTERFACES][0]['ipv4'][InterfaceIPv4.DHCP] = True
libnmstate.apply(desired_state)
assertlib.assert_state(desired_state)
@ -299,12 +319,12 @@ def test_ipv4_dhcp_ignore_gateway(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = True
dhcp_cli_desired_state['ipv4']['auto-gateway'] = False
dhcp_cli_desired_state['ipv4']['auto-routes'] = True
dhcp_cli_desired_state['ipv4']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_ROUTES] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
@ -319,11 +339,11 @@ def test_ipv4_dhcp_ignore_dns(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = True
dhcp_cli_desired_state['ipv4']['auto-dns'] = False
dhcp_cli_desired_state['ipv4']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
@ -337,12 +357,12 @@ def test_ipv4_dhcp_ignore_routes(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = True
dhcp_cli_desired_state['ipv4']['auto-routes'] = False
dhcp_cli_desired_state['ipv4']['auto-gateway'] = True
dhcp_cli_desired_state['ipv4']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_ROUTES] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
@ -357,11 +377,11 @@ def test_ipv6_dhcp_and_autoconf_ignore_gateway(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['auto-gateway'] = False
dhcp_cli_desired_state['ipv6']['auto-routes'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = True
libnmstate.apply(desired_state)
@ -376,11 +396,11 @@ def test_ipv6_dhcp_and_autoconf_ignore_dns(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = False
dhcp_cli_desired_state['ipv6']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['auto-routes'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = True
libnmstate.apply(desired_state)
@ -395,11 +415,11 @@ def test_ipv6_dhcp_and_autoconf_ignore_routes(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['auto-routes'] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = False
libnmstate.apply(desired_state)
@ -414,20 +434,20 @@ def test_ipv4_dhcp_off_and_option_on(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['dhcp'] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = False
# Below options should be silently ignored.
dhcp_cli_desired_state['ipv4']['auto-routes'] = False
dhcp_cli_desired_state['ipv4']['auto-dns'] = False
dhcp_cli_desired_state['ipv4']['auto-gateway'] = False
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_ROUTES] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = False
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
dhcp_cli_current_state = statelib.show_only((DHCP_CLI_NIC,))[INTERFACES][0]
assert not dhcp_cli_current_state['ipv4']['dhcp']
assert 'auto-routes' not in dhcp_cli_current_state['ipv4']
assert 'auto-dns' not in dhcp_cli_current_state['ipv4']
assert 'auto-gateway' not in dhcp_cli_current_state['ipv4']
assert not dhcp_cli_current_state['ipv4'][InterfaceIPv4.DHCP]
assert InterfaceIPv4.AUTO_ROUTES not in dhcp_cli_current_state['ipv4']
assert InterfaceIPv4.AUTO_DNS not in dhcp_cli_current_state['ipv4']
assert InterfaceIPv4.AUTO_GATEWAY not in dhcp_cli_current_state['ipv4']
assert not _has_ipv4_dhcp_nameserver()
assert not _has_ipv4_dhcp_gateway()
assert not _has_ipv4_classless_route()
@ -437,20 +457,20 @@ def test_ipv6_dhcp_off_and_option_on(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = False
dhcp_cli_desired_state['ipv6']['autoconf'] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = False
# Below options should be silently ignored.
dhcp_cli_desired_state['ipv6']['auto-routes'] = False
dhcp_cli_desired_state['ipv6']['auto-dns'] = False
dhcp_cli_desired_state['ipv6']['auto-gateway'] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = False
libnmstate.apply(desired_state)
dhcp_cli_current_state = statelib.show_only((DHCP_CLI_NIC,))[INTERFACES][0]
assert not dhcp_cli_current_state['ipv6']['dhcp']
assert 'auto-routes' not in dhcp_cli_current_state['ipv6']
assert 'auto-dns' not in dhcp_cli_current_state['ipv6']
assert 'auto-gateway' not in dhcp_cli_current_state['ipv6']
assert not dhcp_cli_current_state['ipv6'][InterfaceIPv6.DHCP]
assert InterfaceIPv6.AUTO_ROUTES not in dhcp_cli_current_state['ipv6']
assert InterfaceIPv6.AUTO_DNS not in dhcp_cli_current_state['ipv6']
assert InterfaceIPv6.AUTO_GATEWAY not in dhcp_cli_current_state['ipv6']
assert not _has_ipv6_auto_gateway()
assert not _has_ipv6_auto_extra_route()
assert not _has_ipv6_auto_nameserver()
@ -460,12 +480,12 @@ def test_ipv4_dhcp_switch_on_to_off(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = True
dhcp_cli_desired_state['ipv4']['auto-gateway'] = True
dhcp_cli_desired_state['ipv4']['auto-dns'] = True
dhcp_cli_desired_state['ipv4']['auto-routes'] = True
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_DNS] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.AUTO_ROUTES] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
assertlib.assert_state(desired_state)
@ -478,9 +498,9 @@ def test_ipv4_dhcp_switch_on_to_off(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv4']['enabled'] = True
dhcp_cli_desired_state['ipv4']['dhcp'] = False
dhcp_cli_desired_state['ipv6']['enabled'] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
dhcp_cli_desired_state['ipv4'][InterfaceIPv4.DHCP] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
assertlib.assert_state(desired_state)
@ -493,11 +513,11 @@ def test_ipv6_dhcp_switch_on_to_off(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = True
dhcp_cli_desired_state['ipv6']['autoconf'] = True
dhcp_cli_desired_state['ipv6']['auto-gateway'] = True
dhcp_cli_desired_state['ipv6']['auto-dns'] = True
dhcp_cli_desired_state['ipv6']['auto-routes'] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_GATEWAY] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_DNS] = True
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTO_ROUTES] = True
libnmstate.apply(desired_state)
@ -511,8 +531,8 @@ def test_ipv6_dhcp_switch_on_to_off(dhcp_env):
desired_state = statelib.show_only((DHCP_CLI_NIC,))
dhcp_cli_desired_state = desired_state[INTERFACES][0]
dhcp_cli_desired_state['state'] = 'up'
dhcp_cli_desired_state['ipv6']['dhcp'] = False
dhcp_cli_desired_state['ipv6']['autoconf'] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.DHCP] = False
dhcp_cli_desired_state['ipv6'][InterfaceIPv6.AUTOCONF] = False
libnmstate.apply(desired_state)
@ -606,7 +626,10 @@ def test_slave_ipaddr_learned_via_dhcp_added_as_static_to_linux_bridge(
'name': 'dhcpcli',
'type': 'ethernet',
'state': 'up',
'ipv4': {'enabled': True, 'dhcp': True},
'ipv4': {
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: True,
},
}
]
}
@ -615,7 +638,7 @@ def test_slave_ipaddr_learned_via_dhcp_added_as_static_to_linux_bridge(
current_state = statelib.show_only(('dhcpcli',))
client_current_state = current_state[INTERFACES][0]
dhcpcli_ip = client_current_state['ipv4']['address']
dhcpcli_ip = client_current_state['ipv4'][InterfaceIPv4.ADDRESS]
bridge_desired_state = {
INTERFACES: [
@ -624,9 +647,9 @@ def test_slave_ipaddr_learned_via_dhcp_added_as_static_to_linux_bridge(
'type': 'linux-bridge',
'state': 'up',
'ipv4': {
'enabled': True,
'dhcp': False,
'address': dhcpcli_ip,
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ADDRESS: dhcpcli_ip,
},
'bridge': {
'options': {},
@ -644,8 +667,14 @@ def test_slave_ipaddr_learned_via_dhcp_added_as_static_to_linux_bridge(
'name': 'dhcpcli',
'type': 'ethernet',
'state': 'up',
'ipv4': {'enabled': False, 'dhcp': False},
'ipv6': {'enabled': False, 'dhcp': False},
'ipv4': {
InterfaceIPv4.ENABLED: False,
InterfaceIPv4.DHCP: False,
},
'ipv6': {
InterfaceIPv6.ENABLED: False,
InterfaceIPv6.DHCP: False,
},
},
]
}

View File

@ -24,6 +24,8 @@ from libnmstate import netinfo
from libnmstate.error import NmstateNotImplementedError
from libnmstate.schema import DNS
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import InterfaceType
from libnmstate.schema import Route
@ -205,15 +207,25 @@ def _get_test_iface_states():
Interface.STATE: InterfaceState.UP,
Interface.TYPE: InterfaceType.ETHERNET,
Interface.IPV4: {
'address': [{'ip': '192.0.2.251', 'prefix-length': 24}],
'dhcp': False,
'enabled': True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.0.2.251',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ENABLED: True,
},
Interface.IPV6: {
'address': [{'ip': '2001:db8:1::1', 'prefix-length': 64}],
'dhcp': False,
'autoconf': False,
'enabled': True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001:db8:1::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
InterfaceIPv6.DHCP: False,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.ENABLED: True,
},
},
{
@ -221,15 +233,25 @@ def _get_test_iface_states():
Interface.STATE: InterfaceState.UP,
Interface.TYPE: InterfaceType.ETHERNET,
Interface.IPV4: {
'address': [{'ip': '198.51.100.1', 'prefix-length': 24}],
'dhcp': False,
'enabled': True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '198.51.100.1',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ENABLED: True,
},
Interface.IPV6: {
'address': [{'ip': '2001:db8:2::1', 'prefix-length': 64}],
'dhcp': False,
'autoconf': False,
'enabled': True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001:db8:2::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
InterfaceIPv6.DHCP: False,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.ENABLED: True,
},
},
]

View File

@ -24,6 +24,8 @@ import yaml
import libnmstate
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import InterfaceType
from libnmstate.schema import LinuxBridge
@ -114,8 +116,8 @@ def test_remove_bridge_and_keep_slave_up(bridge0_with_port0, port0_up):
{
Interface.NAME: port_name,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {'enabled': False},
Interface.IPV6: {'enabled': False},
Interface.IPV4: {InterfaceIPv4.ENABLED: False},
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
}
]
}
@ -167,7 +169,11 @@ def test_add_linux_bridge_with_empty_ipv6_static_address(port0_up):
options_subtree[LinuxBridge.STP_SUBTREE][LinuxBridge.STP_ENABLED] = False
extra_iface_state = {
Interface.IPV6: {'enabled': True, 'autoconf': False, 'dhcp': False}
Interface.IPV6: {
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.DHCP: False,
}
}
with _linux_bridge(
bridge_name, bridge_state, extra_iface_state

View File

@ -18,6 +18,7 @@
#
from libnmstate import nm
from libnmstate.schema import InterfaceIPv4
from ..testlib import iproutelib
from .testlib import mainloop
@ -33,9 +34,14 @@ def test_interface_ipv4_change(eth1_up):
with mainloop():
_modify_interface(
ipv4_state={
'enabled': True,
'dhcp': False,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
}
)
@ -43,9 +49,14 @@ def test_interface_ipv4_change(eth1_up):
ipv4_current_state = _get_ipv4_current_state(TEST_IFACE)
ip4_expected_state = {
'enabled': True,
'dhcp': False,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
}
assert ip4_expected_state == ipv4_current_state
@ -53,18 +64,22 @@ def test_interface_ipv4_change(eth1_up):
def test_enable_dhcp_with_no_server(eth1_up):
with mainloop():
_modify_interface(
ipv4_state={'enabled': True, 'dhcp': True, 'address': []}
ipv4_state={
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: True,
InterfaceIPv4.ADDRESS: [],
}
)
nm.nmclient.client(refresh=True)
ipv4_current_state = _get_ipv4_current_state(TEST_IFACE)
expected_ipv4_state = {
'enabled': True,
'dhcp': True,
'address': [],
'auto-dns': True,
'auto-gateway': True,
'auto-routes': True,
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: True,
InterfaceIPv4.ADDRESS: [],
InterfaceIPv4.AUTO_DNS: True,
InterfaceIPv4.AUTO_GATEWAY: True,
InterfaceIPv4.AUTO_ROUTES: True,
}
assert ipv4_current_state == expected_ipv4_state

View File

@ -20,6 +20,7 @@
import yaml
import libnmstate
from libnmstate.schema import InterfaceIPv4
from .testlib import statelib
from .testlib.statelib import INTERFACES
@ -83,8 +84,13 @@ def test_create_and_remove_ovs_bridge_with_an_internal_port():
'state': 'up',
'mtu': 1500,
'ipv4': {
'enabled': True,
'address': [{'ip': '192.0.2.1', 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.0.2.1',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
}
state[INTERFACES].append(ovs_internal_interface_state)

View File

@ -21,6 +21,8 @@ from contextlib import contextmanager
import libnmstate
from libnmstate.nm import nmclient
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from .testlib import statelib
from .testlib import cmd as libcmd
@ -44,16 +46,22 @@ def test_reapply_preserve_ip_config(eth1_up):
'type': 'ethernet',
'state': 'up',
'ipv4': {
'address': [
{'ip': IPV4_ADDRESS1, 'prefix-length': 24}
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
'enabled': True,
InterfaceIPv4.ENABLED: True,
},
'ipv6': {
'address': [
{'ip': IPV6_ADDRESS1, 'prefix-length': 64}
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
'enabled': True,
InterfaceIPv6.ENABLED: True,
},
'mtu': 1500,
}

View File

@ -23,6 +23,8 @@ import pytest
import libnmstate
from libnmstate.error import NmstateNotImplementedError
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import InterfaceType
from libnmstate.schema import Route
@ -36,15 +38,25 @@ ETH1_INTERFACE_STATE = {
Interface.STATE: InterfaceState.UP,
Interface.TYPE: InterfaceType.ETHERNET,
Interface.IPV4: {
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
'dhcp': False,
'enabled': True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ENABLED: True,
},
Interface.IPV6: {
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
'dhcp': False,
'autoconf': False,
'enabled': True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
InterfaceIPv6.DHCP: False,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.ENABLED: True,
},
}
@ -393,7 +405,7 @@ def test_disable_ipv4_with_routes_in_current(eth1_up):
)
eth1_state = copy.deepcopy(ETH1_INTERFACE_STATE)
eth1_state[Interface.IPV4] = {'enabled': False}
eth1_state[Interface.IPV4] = {InterfaceIPv4.ENABLED: False}
libnmstate.apply({Interface.KEY: [eth1_state]})

View File

@ -20,6 +20,8 @@
import pytest
import libnmstate
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from .testlib import assertlib
from .testlib import statelib
@ -47,8 +49,13 @@ def setup_eth1_ipv4(eth1_up):
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
}
]
@ -65,8 +72,13 @@ def setup_eth1_ipv6(eth1_up):
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
}
]
@ -84,7 +96,7 @@ def setup_eth1_ipv6_disable(eth1_up):
'name': 'eth1',
'type': 'ethernet',
'state': 'up',
'ipv6': {'enabled': False},
'ipv6': {InterfaceIPv6.ENABLED: False},
}
]
}
@ -98,9 +110,12 @@ def test_add_static_ipv4_with_full_state(eth1_up):
eth1_desired_state = desired_state[INTERFACES][0]
eth1_desired_state['state'] = 'up'
eth1_desired_state['ipv4']['enabled'] = True
eth1_desired_state['ipv4']['address'] = [
{'ip': IPV4_ADDRESS3, 'prefix-length': 24}
eth1_desired_state['ipv4'][InterfaceIPv4.ENABLED] = True
eth1_desired_state['ipv4'][InterfaceIPv4.ADDRESS] = [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS3,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
]
libnmstate.apply(desired_state)
@ -115,8 +130,13 @@ def test_add_static_ipv4_with_min_state(eth2_up):
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS4, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS4,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
}
]
@ -129,7 +149,11 @@ def test_add_static_ipv4_with_min_state(eth2_up):
def test_remove_static_ipv4(setup_eth1_ipv4):
desired_state = {
INTERFACES: [
{'name': 'eth1', 'type': 'ethernet', 'ipv4': {'enabled': False}}
{
'name': 'eth1',
'type': 'ethernet',
'ipv4': {InterfaceIPv4.ENABLED: False},
}
]
}
@ -146,8 +170,13 @@ def test_edit_static_ipv4_address_and_prefix(setup_eth1_ipv4):
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS2, 'prefix-length': 30}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS2,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 30,
}
],
},
}
]
@ -168,8 +197,13 @@ def test_add_ifaces_with_same_static_ipv4_address_in_one_transaction(
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
},
{
@ -177,8 +211,13 @@ def test_add_ifaces_with_same_static_ipv4_address_in_one_transaction(
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
},
]
@ -199,8 +238,13 @@ def test_add_iface_with_same_static_ipv4_address_to_existing(
'type': 'ethernet',
'state': 'up',
'ipv4': {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
},
}
]
@ -214,11 +258,17 @@ def test_add_static_ipv6_with_full_state(eth1_up):
desired_state = statelib.show_only(('eth1',))
eth1_desired_state = desired_state[INTERFACES][0]
eth1_desired_state['state'] = 'up'
eth1_desired_state['ipv6']['enabled'] = True
eth1_desired_state['ipv6']['address'] = [
{'ip': IPV6_ADDRESS2, 'prefix-length': 64},
eth1_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS] = [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS2,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
# This sequence is intentionally made for IP address sorting.
{'ip': IPV6_ADDRESS1, 'prefix-length': 64},
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
]
libnmstate.apply(desired_state)
assertlib.assert_state(desired_state)
@ -228,10 +278,16 @@ def test_add_static_ipv6_with_link_local(eth1_up):
desired_state = statelib.show_only(('eth1',))
eth1_desired_state = desired_state[INTERFACES][0]
eth1_desired_state['state'] = 'up'
eth1_desired_state['ipv6']['enabled'] = True
eth1_desired_state['ipv6']['address'] = [
{'ip': IPV6_LINK_LOCAL_ADDRESS1, 'prefix-length': 64},
{'ip': IPV6_ADDRESS1, 'prefix-length': 64},
eth1_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS] = [
{
InterfaceIPv6.ADDRESS_IP: IPV6_LINK_LOCAL_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
]
libnmstate.apply(desired_state)
@ -240,12 +296,12 @@ def test_add_static_ipv6_with_link_local(eth1_up):
cur_state = statelib.show_only(('eth1',))
eth1_cur_state = cur_state[INTERFACES][0]
assert (
eth1_desired_state['ipv6']['address'][0]
not in eth1_cur_state['ipv6']['address']
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS][0]
not in eth1_cur_state['ipv6'][InterfaceIPv6.ADDRESS]
)
assert (
eth1_desired_state['ipv6']['address'][1]
in eth1_cur_state['ipv6']['address']
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS][1]
in eth1_cur_state['ipv6'][InterfaceIPv6.ADDRESS]
)
@ -253,10 +309,16 @@ def test_add_static_ipv6_with_link_local_only(eth1_up):
desired_state = statelib.show_only(('eth1',))
eth1_desired_state = desired_state[INTERFACES][0]
eth1_desired_state['state'] = 'up'
eth1_desired_state['ipv6']['enabled'] = True
eth1_desired_state['ipv6']['address'] = [
{'ip': IPV6_LINK_LOCAL_ADDRESS1, 'prefix-length': 64},
{'ip': IPV6_LINK_LOCAL_ADDRESS2, 'prefix-length': 64},
eth1_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS] = [
{
InterfaceIPv6.ADDRESS_IP: IPV6_LINK_LOCAL_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: IPV6_LINK_LOCAL_ADDRESS2,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
]
libnmstate.apply(desired_state)
@ -265,12 +327,12 @@ def test_add_static_ipv6_with_link_local_only(eth1_up):
cur_state = statelib.show_only(('eth1',))
eth1_cur_state = cur_state[INTERFACES][0]
assert (
eth1_desired_state['ipv6']['address'][0]
not in eth1_cur_state['ipv6']['address']
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS][0]
not in eth1_cur_state['ipv6'][InterfaceIPv6.ADDRESS]
)
assert (
eth1_desired_state['ipv6']['address'][1]
not in eth1_cur_state['ipv6']['address']
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS][1]
not in eth1_cur_state['ipv6'][InterfaceIPv6.ADDRESS]
)
@ -278,14 +340,14 @@ def test_add_static_ipv6_with_no_address(eth1_up):
desired_state = statelib.show_only(('eth1',))
eth1_desired_state = desired_state[INTERFACES][0]
eth1_desired_state['state'] = 'up'
eth1_desired_state['ipv6']['enabled'] = True
eth1_desired_state['ipv6'][InterfaceIPv6.ENABLED] = True
libnmstate.apply(desired_state)
cur_state = statelib.show_only(('eth1',))
eth1_cur_state = cur_state[INTERFACES][0]
# Should have at least 1 link-local address.
assert len(eth1_cur_state['ipv6']['address']) >= 1
assert len(eth1_cur_state['ipv6'][InterfaceIPv6.ADDRESS]) >= 1
def test_add_static_ipv6_with_min_state(eth2_up):
@ -296,8 +358,13 @@ def test_add_static_ipv6_with_min_state(eth2_up):
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
}
]
@ -310,7 +377,11 @@ def test_add_static_ipv6_with_min_state(eth2_up):
def test_disable_static_ipv6(setup_eth1_ipv6):
desired_state = {
INTERFACES: [
{'name': 'eth1', 'type': 'ethernet', 'ipv6': {'enabled': False}}
{
'name': 'eth1',
'type': 'ethernet',
'ipv6': {InterfaceIPv6.ENABLED: False},
}
]
}
@ -330,7 +401,7 @@ def test_disable_static_ipv6_and_rollback(setup_eth1_ipv6):
{
'name': 'eth1',
'type': 'ethernet',
'ipv6': {'enabled': False},
'ipv6': {InterfaceIPv6.ENABLED: False},
'foo': 'bad_value',
}
]
@ -349,8 +420,13 @@ def test_enable_ipv6_and_rollback_to_disable_ipv6(setup_eth1_ipv6_disable):
'name': 'eth1',
'type': 'ethernet',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
'foo': 'bad_value',
}
@ -372,8 +448,13 @@ def test_edit_static_ipv6_address_and_prefix(setup_eth1_ipv6):
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS2, 'prefix-length': 24}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS2,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
}
]
@ -386,13 +467,13 @@ def test_edit_static_ipv6_address_and_prefix(setup_eth1_ipv6):
eth1_current_state = current_state[INTERFACES][0]
assert (
eth1_desired_state['ipv6']['address'][0]
in eth1_current_state['ipv6']['address']
eth1_desired_state['ipv6'][InterfaceIPv6.ADDRESS][0]
in eth1_current_state['ipv6'][InterfaceIPv6.ADDRESS]
)
assert (
eth1_setup['ipv6']['address'][0]
not in eth1_current_state['ipv6']['address']
eth1_setup['ipv6'][InterfaceIPv6.ADDRESS][0]
not in eth1_current_state['ipv6'][InterfaceIPv6.ADDRESS]
)
@ -406,8 +487,13 @@ def test_add_ifaces_with_same_static_ipv6_address_in_one_transaction(
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
},
{
@ -415,8 +501,13 @@ def test_add_ifaces_with_same_static_ipv6_address_in_one_transaction(
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
},
]
@ -437,8 +528,13 @@ def test_add_iface_with_same_static_ipv6_address_to_existing(
'type': 'ethernet',
'state': 'up',
'ipv6': {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 64}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
},
}
]

View File

@ -30,6 +30,9 @@ import six
import libnmstate
from libnmstate.schema import Constants
from libnmstate.schema import InterfaceIP
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
INTERFACES = Constants.INTERFACES
@ -141,51 +144,57 @@ class State(object):
def _ipv6_skeleton_canonicalization(self):
for iface_state in self._state.get(INTERFACES, []):
iface_state.setdefault('ipv6', {})
iface_state['ipv6'].setdefault('enabled', False)
iface_state['ipv6'].setdefault('address', [])
iface_state['ipv6'].setdefault('dhcp', False)
iface_state['ipv6'].setdefault('autoconf', False)
iface_state['ipv6'].setdefault(InterfaceIPv6.ENABLED, False)
iface_state['ipv6'].setdefault(InterfaceIPv6.ADDRESS, [])
iface_state['ipv6'].setdefault(InterfaceIPv6.DHCP, False)
iface_state['ipv6'].setdefault(InterfaceIPv6.AUTOCONF, False)
def _ipv4_skeleton_canonicalization(self):
for iface_state in self._state.get(INTERFACES, []):
iface_state.setdefault('ipv4', {})
iface_state['ipv4'].setdefault('enabled', False)
iface_state['ipv4'].setdefault('address', [])
iface_state['ipv4'].setdefault('dhcp', False)
iface_state['ipv4'].setdefault(InterfaceIPv4.ENABLED, False)
iface_state['ipv4'].setdefault(InterfaceIPv4.ADDRESS, [])
iface_state['ipv4'].setdefault(InterfaceIPv4.DHCP, False)
def _ignore_ipv6_link_local(self):
for iface_state in self._state.get(INTERFACES, []):
iface_state['ipv6']['address'] = list(
iface_state['ipv6'][InterfaceIPv6.ADDRESS] = list(
addr
for addr in iface_state['ipv6']['address']
if not _is_ipv6_link_local(addr['ip'], addr['prefix-length'])
for addr in iface_state['ipv6'][InterfaceIPv6.ADDRESS]
if not _is_ipv6_link_local(
addr[InterfaceIPv6.ADDRESS_IP],
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
)
)
def _sort_ip_addresses(self):
for iface_state in self._state.get(INTERFACES, []):
for family in ('ipv4', 'ipv6'):
iface_state.get(family, {}).get('address', []).sort(
key=itemgetter('ip')
iface_state.get(family, {}).get(InterfaceIP.ADDRESS, []).sort(
key=itemgetter(InterfaceIP.ADDRESS_IP)
)
def _ignore_dhcp_manual_addr(self):
for iface_state in self._state.get(INTERFACES, []):
for family in ('ipv4', 'ipv6'):
if iface_state.get(family, {}).get('dhcp'):
iface_state[family]['address'] = []
if iface_state.get(family, {}).get(InterfaceIP.DHCP):
iface_state[family][InterfaceIP.ADDRESS] = []
def _ignore_dhcp_option_when_off(self):
for iface_state in self._state.get(INTERFACES, []):
for family in ('ipv4', 'ipv6'):
ip = iface_state.get(family, {})
if not (
ip.get('enabled')
and (ip.get('dhcp') or ip.get('autoconf'))
ip.get(InterfaceIP.ENABLED)
and (
ip.get(InterfaceIP.DHCP)
or ip.get(InterfaceIPv6.AUTOCONF)
)
):
for dhcp_option in (
'auto-routes',
'auto-gateway',
'auto-dns',
InterfaceIP.AUTO_ROUTES,
InterfaceIP.AUTO_GATEWAY,
InterfaceIP.AUTO_DNS,
):
ip.pop(dhcp_option, None)

View File

@ -26,6 +26,8 @@ from libnmstate import state
from libnmstate.nm import dns as nm_dns
from libnmstate.schema import DNS
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceType
from libnmstate.schema import InterfaceState
from libnmstate.schema import OVSBridgePortType as OBPortType
@ -904,15 +906,25 @@ def _get_test_iface_states():
Interface.STATE: InterfaceState.UP,
Interface.TYPE: InterfaceType.ETHERNET,
Interface.IPV4: {
'address': [{'ip': '192.0.2.251', 'prefix-length': 24}],
'dhcp': False,
'enabled': True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.0.2.251',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ENABLED: True,
},
Interface.IPV6: {
'address': [{'ip': '2001:db8:1::1', 'prefix-length': 64}],
'dhcp': False,
'autoconf': False,
'enabled': True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001:db8:1::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
InterfaceIPv6.DHCP: False,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.ENABLED: True,
},
},
{
@ -920,15 +932,25 @@ def _get_test_iface_states():
Interface.STATE: InterfaceState.UP,
Interface.TYPE: InterfaceType.ETHERNET,
Interface.IPV4: {
'address': [{'ip': '198.51.100.1', 'prefix-length': 24}],
'dhcp': False,
'enabled': True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '198.51.100.1',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ENABLED: True,
},
Interface.IPV6: {
'address': [{'ip': '2001:db8:2::1', 'prefix-length': 64}],
'dhcp': False,
'autoconf': False,
'enabled': True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001:db8:2::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
}
],
InterfaceIPv6.DHCP: False,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.ENABLED: True,
},
},
]

View File

@ -24,6 +24,8 @@ from .compat import mock
from libnmstate import netapplier
from libnmstate.schema import Constants
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
INTERFACES = Constants.INTERFACES
BOND_TYPE = 'bond'
@ -57,8 +59,8 @@ def test_iface_admin_state_change(netinfo_nm_mock, netapplier_nm_mock):
'name': 'foo',
'type': 'unknown',
'state': 'up',
'ipv4': {'enabled': False},
'ipv6': {'enabled': False},
'ipv4': {InterfaceIPv4.ENABLED: False},
'ipv6': {InterfaceIPv6.ENABLED: False},
}
]
}
@ -144,8 +146,8 @@ def test_edit_existing_bond(netinfo_nm_mock, netapplier_nm_mock):
'slaves': [],
'options': {'miimon': '100'},
},
'ipv4': {'enabled': False},
'ipv6': {'enabled': False},
'ipv4': {InterfaceIPv4.ENABLED: False},
'ipv6': {InterfaceIPv6.ENABLED: False},
}
]
}

View File

@ -23,6 +23,8 @@ from .compat import mock
from libnmstate import netinfo
from libnmstate.schema import Constants
from libnmstate.schema import DNS
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
INTERFACES = Constants.INTERFACES
@ -50,8 +52,8 @@ def test_netinfo_show_generic_iface(nm_mock, nm_dns_mock):
'name': 'foo',
'type': 'unknown',
'state': 'up',
'ipv4': {'enabled': False},
'ipv6': {'enabled': False},
'ipv4': {InterfaceIPv4.ENABLED: False},
'ipv6': {InterfaceIPv6.ENABLED: False},
}
],
}
@ -90,8 +92,8 @@ def test_netinfo_show_bond_iface(nm_mock, nm_dns_mock):
'slaves': [],
'options': {'miimon': '100'},
},
'ipv4': {'enabled': False},
'ipv6': {'enabled': False},
'ipv4': {InterfaceIPv4.ENABLED: False},
'ipv6': {InterfaceIPv6.ENABLED: False},
}
],
}

View File

@ -24,6 +24,7 @@ import libnmstate.nm.dns as nm_dns
import libnmstate.nm.ipv4 as nm_ipv4
import libnmstate.nm.ipv6 as nm_ipv6
from libnmstate.schema import DNS
from libnmstate.schema import InterfaceIP
from libnmstate.schema import Route
@ -64,7 +65,8 @@ parametrize_ip_ver_dns = pytest.mark.parametrize(
def test_add_dns_empty(nm_ip):
dns_conf = {}
setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: dns_conf}, base_con_profile=None
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: dns_conf},
base_con_profile=None,
)
_assert_dns(setting_ip, dns_conf)
@ -74,7 +76,8 @@ def test_add_dns_empty(nm_ip):
def test_add_dns(nm_ip, get_test_dns_func):
dns_conf = get_test_dns_func()
setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: dns_conf}, base_con_profile=None
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: dns_conf},
base_con_profile=None,
)
_assert_dns(setting_ip, dns_conf)
@ -85,7 +88,8 @@ def test_add_dns_duplicate_server(nm_ip, get_test_dns_func):
dns_conf = get_test_dns_func()
dns_conf[DNS.SERVER] = [dns_conf[DNS.SERVER][0], dns_conf[DNS.SERVER][0]]
setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: dns_conf}, base_con_profile=None
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: dns_conf},
base_con_profile=None,
)
dns_conf[DNS.SERVER] = [dns_conf[DNS.SERVER][0]]
@ -97,7 +101,8 @@ def test_add_dns_duplicate_search(nm_ip, get_test_dns_func):
dns_conf = get_test_dns_func()
dns_conf[DNS.SEARCH] = [dns_conf[DNS.SEARCH][0], dns_conf[DNS.SEARCH][0]]
setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: dns_conf}, base_con_profile=None
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: dns_conf},
base_con_profile=None,
)
dns_conf[DNS.SEARCH] = [dns_conf[DNS.SEARCH][0]]
@ -108,12 +113,13 @@ def test_add_dns_duplicate_search(nm_ip, get_test_dns_func):
def test_clear_dns(nm_ip, get_test_dns_func):
dns_conf = get_test_dns_func()
setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: dns_conf}, base_con_profile=None
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: dns_conf},
base_con_profile=None,
)
con_profile = nm_connection.ConnectionProfile()
con_profile.create([setting_ip])
new_setting_ip = nm_ip.create_setting(
{'enabled': True, nm_dns.DNS_METADATA: {}},
{InterfaceIP.ENABLED: True, nm_dns.DNS_METADATA: {}},
base_con_profile=con_profile.profile,
)

View File

@ -22,6 +22,7 @@ import pytest
from lib.compat import mock
from libnmstate import nm
from libnmstate.schema import InterfaceIPv4
IPV4_ADDRESS1 = '192.0.2.251'
@ -43,7 +44,7 @@ def test_create_setting_without_config(NM_mock):
def test_create_setting_with_ipv4_disabled(NM_mock):
ipv4_setting = nm.ipv4.create_setting(
config={'enabled': False}, base_con_profile=None
config={InterfaceIPv4.ENABLED: False}, base_con_profile=None
)
assert (
@ -53,7 +54,8 @@ def test_create_setting_with_ipv4_disabled(NM_mock):
def test_create_setting_without_addresses(NM_mock):
ipv4_setting = nm.ipv4.create_setting(
config={'enabled': True, 'address': []}, base_con_profile=None
config={InterfaceIPv4.ENABLED: True, InterfaceIPv4.ADDRESS: []},
base_con_profile=None,
)
assert (
@ -63,10 +65,16 @@ def test_create_setting_without_addresses(NM_mock):
def test_create_setting_with_static_addresses(NM_mock):
config = {
'enabled': True,
'address': [
{'ip': '10.10.10.1', 'prefix-length': 24},
{'ip': '10.10.20.1', 'prefix-length': 24},
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '10.10.10.1',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
{
InterfaceIPv4.ADDRESS_IP: '10.10.20.1',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
],
}
ipv4_setting = nm.ipv4.create_setting(config=config, base_con_profile=None)
@ -78,13 +86,17 @@ def test_create_setting_with_static_addresses(NM_mock):
[
mock.call(
nm.ipv4.socket.AF_INET,
config['address'][0]['ip'],
config['address'][0]['prefix-length'],
config[InterfaceIPv4.ADDRESS][0][InterfaceIPv4.ADDRESS_IP],
config[InterfaceIPv4.ADDRESS][0][
InterfaceIPv4.ADDRESS_PREFIX_LENGTH
],
),
mock.call(
nm.ipv4.socket.AF_INET,
config['address'][1]['ip'],
config['address'][1]['prefix-length'],
config[InterfaceIPv4.ADDRESS][1][InterfaceIPv4.ADDRESS_IP],
config[InterfaceIPv4.ADDRESS][1][
InterfaceIPv4.ADDRESS_PREFIX_LENGTH
],
),
]
)
@ -99,7 +111,7 @@ def test_create_setting_with_static_addresses(NM_mock):
def test_get_info_with_no_connection():
info = nm.ipv4.get_info(active_connection=None)
assert info == {'enabled': False}
assert info == {InterfaceIPv4.ENABLED: False}
def test_get_info_with_no_ipv4_config():
@ -109,7 +121,7 @@ def test_get_info_with_no_ipv4_config():
info = nm.ipv4.get_info(active_connection=con_mock)
assert info == {'enabled': False}
assert info == {InterfaceIPv4.ENABLED: False}
def test_get_info_with_ipv4_config(NM_mock):
@ -131,12 +143,16 @@ def test_get_info_with_ipv4_config(NM_mock):
info = nm.ipv4.get_info(active_connection=act_con_mock)
assert info == {
'enabled': True,
'dhcp': False,
'address': [
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.DHCP: False,
InterfaceIPv4.ADDRESS: [
{
'ip': address_mock.get_address.return_value,
'prefix-length': int(address_mock.get_prefix.return_value),
InterfaceIPv4.ADDRESS_IP: (
address_mock.get_address.return_value
),
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: int(
address_mock.get_prefix.return_value
),
}
],
}
@ -144,8 +160,13 @@ def test_get_info_with_ipv4_config(NM_mock):
def test_create_setting_with_base_con_profile(NM_mock):
config = {
'enabled': True,
'address': [{'ip': IPV4_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv4.ENABLED: True,
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: IPV4_ADDRESS1,
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
}
],
}
base_con_profile_mock = mock.MagicMock()
config_mock = base_con_profile_mock.get_setting_ip4_config.return_value

View File

@ -22,6 +22,7 @@ import pytest
from lib.compat import mock
from libnmstate import nm
from libnmstate.schema import InterfaceIPv6
# IPv6 Address Prefix Reserved for Documentation:
# https://tools.ietf.org/html/rfc3849
@ -50,7 +51,7 @@ def test_create_setting_with_ipv6_disabled(NM_mock):
NM_mock.SettingIP6Config.new().props.addresses = []
ipv6_setting = nm.ipv6.create_setting(
config={'enabled': False}, base_con_profile=None
config={InterfaceIPv6.ENABLED: False}, base_con_profile=None
)
assert (
@ -62,7 +63,8 @@ def test_create_setting_without_addresses(NM_mock):
NM_mock.SettingIP6Config.new().props.addresses = []
ipv6_setting = nm.ipv6.create_setting(
config={'enabled': True, 'address': []}, base_con_profile=None
config={InterfaceIPv6.ENABLED: True, InterfaceIPv6.ADDRESS: []},
base_con_profile=None,
)
assert (
@ -73,10 +75,16 @@ def test_create_setting_without_addresses(NM_mock):
def test_create_setting_with_static_addresses(NM_mock):
config = {
'enabled': True,
'address': [
{'ip': 'fd12:3456:789a:1::1', 'prefix-length': 24},
{'ip': 'fd12:3456:789a:2::1', 'prefix-length': 24},
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: 'fd12:3456:789a:1::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 24,
},
{
InterfaceIPv6.ADDRESS_IP: 'fd12:3456:789a:2::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 24,
},
],
}
ipv6_setting = nm.ipv6.create_setting(config=config, base_con_profile=None)
@ -88,13 +96,17 @@ def test_create_setting_with_static_addresses(NM_mock):
[
mock.call(
nm.ipv6.socket.AF_INET6,
config['address'][0]['ip'],
config['address'][0]['prefix-length'],
config[InterfaceIPv6.ADDRESS][0][InterfaceIPv6.ADDRESS_IP],
config[InterfaceIPv6.ADDRESS][0][
InterfaceIPv6.ADDRESS_PREFIX_LENGTH
],
),
mock.call(
nm.ipv6.socket.AF_INET6,
config['address'][1]['ip'],
config['address'][1]['prefix-length'],
config[InterfaceIPv6.ADDRESS][1][InterfaceIPv6.ADDRESS_IP],
config[InterfaceIPv6.ADDRESS][1][
InterfaceIPv6.ADDRESS_PREFIX_LENGTH
],
),
]
)
@ -109,7 +121,7 @@ def test_create_setting_with_static_addresses(NM_mock):
def test_get_info_with_no_connection():
info = nm.ipv6.get_info(active_connection=None)
assert info == {'enabled': False}
assert info == {InterfaceIPv6.ENABLED: False}
def test_get_info_with_no_ipv6_config():
@ -119,7 +131,7 @@ def test_get_info_with_no_ipv6_config():
info = nm.ipv6.get_info(active_connection=con_mock)
assert info == {'enabled': False}
assert info == {InterfaceIPv6.ENABLED: False}
def test_get_info_with_ipv6_config(NM_mock):
@ -141,13 +153,17 @@ def test_get_info_with_ipv6_config(NM_mock):
info = nm.ipv6.get_info(active_connection=act_con_mock)
assert info == {
'enabled': True,
'autoconf': False,
'dhcp': False,
'address': [
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.AUTOCONF: False,
InterfaceIPv6.DHCP: False,
InterfaceIPv6.ADDRESS: [
{
'ip': address_mock.get_address.return_value,
'prefix-length': int(address_mock.get_prefix.return_value),
InterfaceIPv6.ADDRESS_IP: (
address_mock.get_address.return_value
),
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: int(
address_mock.get_prefix.return_value
),
}
],
}
@ -155,10 +171,16 @@ def test_get_info_with_ipv6_config(NM_mock):
def test_create_setting_with_link_local_addresses(NM_mock):
config = {
'enabled': True,
'address': [
{'ip': IPV6_LINK_LOCAL_ADDRESS1, 'prefix-length': 64},
{'ip': IPV6_ADDRESS1, 'prefix-length': 64},
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_LINK_LOCAL_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
],
}
ipv6_setting = nm.ipv6.create_setting(config=config, base_con_profile=None)
@ -170,8 +192,10 @@ def test_create_setting_with_link_local_addresses(NM_mock):
[
mock.call(
nm.ipv6.socket.AF_INET6,
config['address'][1]['ip'],
config['address'][1]['prefix-length'],
config[InterfaceIPv6.ADDRESS][1][InterfaceIPv6.ADDRESS_IP],
config[InterfaceIPv6.ADDRESS][1][
InterfaceIPv6.ADDRESS_PREFIX_LENGTH
],
)
]
)
@ -182,8 +206,13 @@ def test_create_setting_with_link_local_addresses(NM_mock):
def test_create_setting_with_base_con_profile(NM_mock):
config = {
'enabled': True,
'address': [{'ip': IPV6_ADDRESS1, 'prefix-length': 24}],
InterfaceIPv6.ENABLED: True,
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: IPV6_ADDRESS1,
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 24,
}
],
}
base_con_profile_mock = mock.MagicMock()
config_mock = base_con_profile_mock.get_setting_ip6_config.return_value

View File

@ -26,6 +26,7 @@ from libnmstate.error import NmstateNotImplementedError
from libnmstate.nm import ipv4 as nm_ipv4
from libnmstate.nm import ipv6 as nm_ipv6
from libnmstate.nm import connection as nm_connection
from libnmstate.schema import InterfaceIP
from libnmstate.schema import Route
IPV4_DEFAULT_GATEWAY_DESTINATION = '0.0.0.0/0'
@ -116,7 +117,8 @@ parametrize_ip_ver_routes_gw = pytest.mark.parametrize(
@parametrize_ip_ver_routes
def test_add_multiple_route(nm_ip, routes):
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes}, base_con_profile=None
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes},
base_con_profile=None,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == routes
@ -124,7 +126,7 @@ def test_add_multiple_route(nm_ip, routes):
@parametrize_ip_ver_routes
def test_add_duplicate_routes(nm_ip, routes):
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: [routes[0], routes[0]]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: [routes[0], routes[0]]},
base_con_profile=None,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == [
@ -135,12 +137,13 @@ def test_add_duplicate_routes(nm_ip, routes):
@parametrize_ip_ver_routes
def test_clear_route(nm_ip, routes):
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes}, base_con_profile=None
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes},
base_con_profile=None,
)
con_profile = nm_connection.ConnectionProfile()
con_profile.create([setting_ip])
new_setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: []},
{InterfaceIP.ENABLED: True, metadata.ROUTES: []},
base_con_profile=con_profile.profile,
)
assert not [_nm_route_to_dict(r) for r in new_setting_ip.props.routes]
@ -153,7 +156,7 @@ def test_add_route_without_metric(nm_ip, routes):
route_without_metric = copy.deepcopy(routes[0])
del route_without_metric[Route.METRIC]
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: [route_without_metric]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: [route_without_metric]},
base_con_profile=None,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == [
@ -168,7 +171,7 @@ def test_add_route_without_table_id(nm_ip, routes):
route_without_table_id = copy.deepcopy(routes[0])
del route_without_table_id[Route.TABLE_ID]
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: [route_without_table_id]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: [route_without_table_id]},
base_con_profile=None,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == [
@ -180,7 +183,7 @@ def test_add_route_without_table_id(nm_ip, routes):
def test_change_gateway(nm_ip, routes, gateways):
desired_routes = routes + gateways[:1]
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: desired_routes},
{InterfaceIP.ENABLED: True, metadata.ROUTES: desired_routes},
base_con_profile=None,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == routes
@ -195,7 +198,7 @@ def test_change_gateway(nm_ip, routes, gateways):
@parametrize_ip_ver_routes_gw
def test_add_two_gateway(nm_ip, routes, gateways):
nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes + gateways},
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes + gateways},
base_con_profile=None,
)
@ -209,7 +212,7 @@ def test_add_two_gateway(nm_ip, routes, gateways):
def test_add_duplicate_gateways(nm_ip, routes, gateways):
nm_ip.create_setting(
{
'enabled': True,
InterfaceIP.ENABLED: True,
metadata.ROUTES: routes + [gateways[0], gateways[0]],
},
base_con_profile=None,
@ -220,7 +223,7 @@ def test_add_duplicate_gateways(nm_ip, routes, gateways):
def test_change_gateway_without_metric(nm_ip, routes, gateways):
del gateways[0][Route.METRIC]
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes + [gateways[0]]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes + [gateways[0]]},
base_con_profile=None,
)
gateways[0][Route.METRIC] = Route.USE_DEFAULT_METRIC
@ -232,7 +235,7 @@ def test_change_gateway_without_metric(nm_ip, routes, gateways):
def test_change_gateway_without_table_id(nm_ip, routes, gateways):
del gateways[0][Route.TABLE_ID]
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes + [gateways[0]]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes + [gateways[0]]},
base_con_profile=None,
)
gateways[0][Route.TABLE_ID] = Route.USE_DEFAULT_ROUTE_TABLE
@ -244,13 +247,13 @@ def test_change_gateway_without_table_id(nm_ip, routes, gateways):
@parametrize_ip_ver_routes_gw
def test_clear_gateway(nm_ip, routes, gateways):
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes + gateways[:1]},
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes + gateways[:1]},
base_con_profile=None,
)
con_profile = nm_connection.ConnectionProfile()
con_profile.create([setting_ip])
setting_ip = nm_ip.create_setting(
{'enabled': True, metadata.ROUTES: routes},
{InterfaceIP.ENABLED: True, metadata.ROUTES: routes},
base_con_profile=con_profile.profile,
)
assert [_nm_route_to_dict(r) for r in setting_ip.props.routes] == routes

View File

@ -24,6 +24,8 @@ from libnmstate import state
from libnmstate.error import NmstateVerificationError
from libnmstate.schema import DNS
from libnmstate.schema import Interface
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.schema import InterfaceState
from libnmstate.schema import Route
@ -76,32 +78,56 @@ class TestAssertIfaceState(object):
desired_state = self._base_state
current_state = self._base_state
desired_state.interfaces['foo-name']['ipv4'] = {
'address': [
{'ip': '192.168.122.10', 'prefix-length': 24},
{'ip': '192.168.121.10', 'prefix-length': 24},
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.168.122.10',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
{
InterfaceIPv4.ADDRESS_IP: '192.168.121.10',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
],
'enabled': True,
InterfaceIPv4.ENABLED: True,
}
current_state.interfaces['foo-name']['ipv4'] = {
'address': [
{'ip': '192.168.121.10', 'prefix-length': 24},
{'ip': '192.168.122.10', 'prefix-length': 24},
InterfaceIPv4.ADDRESS: [
{
InterfaceIPv4.ADDRESS_IP: '192.168.121.10',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
{
InterfaceIPv4.ADDRESS_IP: '192.168.122.10',
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
},
],
'enabled': True,
InterfaceIPv4.ENABLED: True,
}
desired_state.interfaces['foo-name']['ipv6'] = {
'address': [
{'ip': '2001::2', 'prefix-length': 64},
{'ip': '2001::1', 'prefix-length': 64},
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001::2',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: '2001::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
],
'enabled': True,
InterfaceIPv6.ENABLED: True,
}
current_state.interfaces['foo-name']['ipv6'] = {
'address': [
{'ip': '2001::1', 'prefix-length': 64},
{'ip': '2001::2', 'prefix-length': 64},
InterfaceIPv6.ADDRESS: [
{
InterfaceIPv6.ADDRESS_IP: '2001::1',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
{
InterfaceIPv6.ADDRESS_IP: '2001::2',
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
},
],
'enabled': True,
InterfaceIPv6.ENABLED: True,
}
desired_state.verify_interfaces(current_state)
@ -416,7 +442,7 @@ class TestRouteStateMerge(object):
{
Interface.NAME: route0_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {'enabled': False},
Interface.IPV4: {InterfaceIPv4.ENABLED: False},
}
]
}
@ -430,7 +456,7 @@ class TestRouteStateMerge(object):
{
Interface.NAME: route0_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {'enabled': False},
Interface.IPV4: {InterfaceIPv4.ENABLED: False},
Interface.IPV6: {},
}
],
@ -448,7 +474,7 @@ class TestRouteStateMerge(object):
{
Interface.NAME: route1_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV6: {'enabled': False},
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
}
]
}
@ -463,7 +489,7 @@ class TestRouteStateMerge(object):
Interface.NAME: route1_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {},
Interface.IPV6: {'enabled': False},
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
}
],
Route.KEY: {Route.CONFIG: []},
@ -480,7 +506,7 @@ class TestRouteStateMerge(object):
{
Interface.NAME: route0_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV6: {'enabled': False},
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
}
]
}
@ -495,7 +521,7 @@ class TestRouteStateMerge(object):
Interface.NAME: route0_obj.next_hop_interface,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {},
Interface.IPV6: {'enabled': False},
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
}
],
Route.KEY: {Route.CONFIG: [route0]},
@ -668,8 +694,8 @@ def _gen_iface_states_for_routes(routes):
{
Interface.NAME: iface,
Interface.STATE: InterfaceState.UP,
Interface.IPV4: {'enabled': True},
Interface.IPV6: {'enabled': True},
Interface.IPV4: {InterfaceIPv4.ENABLED: True},
Interface.IPV6: {InterfaceIPv6.ENABLED: True},
}
for iface in ifaces
]

View File

@ -24,6 +24,8 @@ from libnmstate import schema
from libnmstate import state
from libnmstate import validator
from libnmstate.schema import DNS
from libnmstate.schema import InterfaceIPv4
from libnmstate.schema import InterfaceIPv6
from libnmstate.error import NmstateNotImplementedError
from libnmstate.error import NmstateValueError
@ -295,8 +297,8 @@ def _create_interface_state(
schema.Interface.NAME: iface_name,
schema.Interface.TYPE: schema.InterfaceType.ETHERNET,
schema.Interface.STATE: state,
schema.Interface.IPV4: {'enabled': ipv4},
schema.Interface.IPV6: {'enabled': ipv6},
schema.Interface.IPV4: {InterfaceIPv4.ENABLED: ipv4},
schema.Interface.IPV6: {InterfaceIPv6.ENABLED: ipv6},
}