Black: Enable string normalization
Signed-off-by: Till Maas <opensource@till.name>
This commit is contained in:
parent
03bb579ce2
commit
ca3450dc93
@ -37,7 +37,6 @@ Please follow these steps to have your contribution considered by the maintainer
|
||||
- Nmstate is written primarily in Python, and its coding style should follow
|
||||
the best practices of Python coding unless otherwise declared.
|
||||
- Nmstate uses the [black](https://github.com/python/black) code formatter
|
||||
(except for string normalization).
|
||||
- PEP8 is holy.
|
||||
- Tests are holy.
|
||||
Production code must be covered by unit tests and/or basic integration tests.
|
||||
@ -58,7 +57,6 @@ Please follow these steps to have your contribution considered by the maintainer
|
||||
White space between code stanzas are welcome. They help to create breathing
|
||||
while reading long code.
|
||||
However, splitting stanzas into helper functions could be even better.
|
||||
- Prefer single quotes (') whenever possible.
|
||||
|
||||
Ref:
|
||||
https://www.ovirt.org/develop/developer-guide/vdsm/coding-guidelines/
|
||||
|
@ -28,11 +28,11 @@ from .prettystate import PrettyState
|
||||
|
||||
|
||||
__all__ = [
|
||||
'show',
|
||||
'apply',
|
||||
'commit',
|
||||
'rollback',
|
||||
'error',
|
||||
'schema',
|
||||
'PrettyState',
|
||||
"show",
|
||||
"apply",
|
||||
"commit",
|
||||
"rollback",
|
||||
"error",
|
||||
"schema",
|
||||
"PrettyState",
|
||||
]
|
||||
|
@ -19,20 +19,20 @@
|
||||
|
||||
|
||||
def get_slaves_from_state(state, default=()):
|
||||
ports = state.get('bridge', {}).get('port')
|
||||
ports = state.get("bridge", {}).get("port")
|
||||
if ports is None:
|
||||
return default
|
||||
return [p['name'] for p in ports]
|
||||
return [p["name"] for p in ports]
|
||||
|
||||
|
||||
def set_bridge_ports_metadata(master_state, slave_state):
|
||||
_set_common_slaves_metadata(master_state, slave_state)
|
||||
|
||||
ports = master_state.get('bridge', {}).get('port', [])
|
||||
port = next(filter(lambda n: n['name'] == slave_state['name'], ports), {})
|
||||
slave_state['_brport_options'] = port
|
||||
ports = master_state.get("bridge", {}).get("port", [])
|
||||
port = next(filter(lambda n: n["name"] == slave_state["name"], ports), {})
|
||||
slave_state["_brport_options"] = port
|
||||
|
||||
|
||||
def _set_common_slaves_metadata(master_state, slave_state):
|
||||
slave_state['_master'] = master_state['name']
|
||||
slave_state['_master_type'] = master_state['type']
|
||||
slave_state["_master"] = master_state["name"]
|
||||
slave_state["_master_type"] = master_state["type"]
|
||||
|
@ -52,17 +52,17 @@ def minimal_ethtool(interface):
|
||||
sockfd = sock.fileno()
|
||||
|
||||
ecmd = array.array(
|
||||
'B', struct.pack('I39s', ETHTOOL_GSET, b'\x00' * 39)
|
||||
"B", struct.pack("I39s", ETHTOOL_GSET, b"\x00" * 39)
|
||||
)
|
||||
|
||||
interface = interface.encode('utf-8')
|
||||
ifreq = struct.pack('16sP', interface, ecmd.buffer_info()[0])
|
||||
interface = interface.encode("utf-8")
|
||||
ifreq = struct.pack("16sP", interface, ecmd.buffer_info()[0])
|
||||
|
||||
fcntl.ioctl(sockfd, SIOCETHTOOL, ifreq)
|
||||
# pylint: disable=no-member
|
||||
res = ecmd.tobytes() if hasattr(ecmd, 'tobytes') else ecmd.tostring()
|
||||
res = ecmd.tobytes() if hasattr(ecmd, "tobytes") else ecmd.tostring()
|
||||
# pylint: enable=no-member
|
||||
speed, duplex, auto = struct.unpack('12xHB3xB24x', res)
|
||||
speed, duplex, auto = struct.unpack("12xHB3xB24x", res)
|
||||
except IOError:
|
||||
speed, duplex, auto = 65535, 255, 255
|
||||
finally:
|
||||
@ -72,9 +72,9 @@ def minimal_ethtool(interface):
|
||||
speed = 0
|
||||
|
||||
if duplex == 255:
|
||||
duplex = 'unknown'
|
||||
duplex = "unknown"
|
||||
else:
|
||||
duplex = 'full' if bool(duplex) else 'half'
|
||||
duplex = "full" if bool(duplex) else "half"
|
||||
|
||||
if auto == 255:
|
||||
auto = None
|
||||
|
@ -20,7 +20,7 @@
|
||||
import ipaddress
|
||||
from libnmstate.error import NmstateValueError
|
||||
|
||||
_IPV6_LINK_LOCAL_NETWORK_PREFIXES = ['fe8', 'fe9', 'fea', 'feb']
|
||||
_IPV6_LINK_LOCAL_NETWORK_PREFIXES = ["fe8", "fe9", "fea", "feb"]
|
||||
_IPV6_LINK_LOCAL_NETWORK_PREFIX_LENGTH = 10
|
||||
|
||||
KERNEL_MAIN_ROUTE_TABLE_ID = 254
|
||||
@ -35,12 +35,12 @@ def is_ipv6_link_local_addr(ip, prefix):
|
||||
|
||||
|
||||
def is_ipv6_address(addr):
|
||||
return ':' in addr
|
||||
return ":" in addr
|
||||
|
||||
|
||||
def to_ip_address_full(ip, prefix=None):
|
||||
if prefix:
|
||||
return f'{ip}/{prefix}'
|
||||
return f"{ip}/{prefix}"
|
||||
else:
|
||||
return to_ip_address_full(*ip_address_full_to_tuple(ip))
|
||||
|
||||
@ -49,6 +49,6 @@ def ip_address_full_to_tuple(addr):
|
||||
try:
|
||||
net = ipaddress.ip_network(addr)
|
||||
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||
raise NmstateValueError(f'Invalid IP address, error: {err}')
|
||||
raise NmstateValueError(f"Invalid IP address, error: {err}")
|
||||
|
||||
return f'{net.network_address}', net.prefixlen
|
||||
return f"{net.network_address}", net.prefixlen
|
||||
|
@ -27,13 +27,13 @@ from libnmstate.schema import InterfaceIP
|
||||
from libnmstate.schema import InterfaceState
|
||||
|
||||
|
||||
BRPORT_OPTIONS = '_brport_options'
|
||||
MASTER = '_master'
|
||||
MASTER_TYPE = '_master_type'
|
||||
ROUTES = '_routes'
|
||||
DNS_METADATA = '_dns'
|
||||
DNS_METADATA_PRIORITY = '_priority'
|
||||
ROUTE_RULES_METADATA = '_route_rules'
|
||||
BRPORT_OPTIONS = "_brport_options"
|
||||
MASTER = "_master"
|
||||
MASTER_TYPE = "_master_type"
|
||||
ROUTES = "_routes"
|
||||
DNS_METADATA = "_dns"
|
||||
DNS_METADATA_PRIORITY = "_priority"
|
||||
ROUTE_RULES_METADATA = "_route_rules"
|
||||
|
||||
|
||||
def generate_ifaces_metadata(desired_state, current_state):
|
||||
@ -52,21 +52,21 @@ def generate_ifaces_metadata(desired_state, current_state):
|
||||
_generate_link_master_metadata(
|
||||
desired_state.interfaces,
|
||||
current_state.interfaces,
|
||||
master_type='bond',
|
||||
master_type="bond",
|
||||
get_slaves_func=_get_bond_slaves_from_state,
|
||||
set_metadata_func=_set_common_slaves_metadata,
|
||||
)
|
||||
_generate_link_master_metadata(
|
||||
desired_state.interfaces,
|
||||
current_state.interfaces,
|
||||
master_type='ovs-bridge',
|
||||
master_type="ovs-bridge",
|
||||
get_slaves_func=_get_ovs_slaves_from_state,
|
||||
set_metadata_func=_set_ovs_bridge_ports_metadata,
|
||||
)
|
||||
_generate_link_master_metadata(
|
||||
desired_state.interfaces,
|
||||
current_state.interfaces,
|
||||
master_type='linux-bridge',
|
||||
master_type="linux-bridge",
|
||||
get_slaves_func=linux_bridge.get_slaves_from_state,
|
||||
set_metadata_func=linux_bridge.set_bridge_ports_metadata,
|
||||
)
|
||||
@ -89,27 +89,27 @@ def remove_ifaces_metadata(ifaces_state):
|
||||
|
||||
|
||||
def _get_bond_slaves_from_state(iface_state, default=()):
|
||||
return iface_state.get('link-aggregation', {}).get('slaves', default)
|
||||
return iface_state.get("link-aggregation", {}).get("slaves", default)
|
||||
|
||||
|
||||
def _set_ovs_bridge_ports_metadata(master_state, slave_state):
|
||||
_set_common_slaves_metadata(master_state, slave_state)
|
||||
|
||||
ports = master_state.get('bridge', {}).get('port', [])
|
||||
port = next(filter(lambda n: n['name'] == slave_state['name'], ports), {})
|
||||
ports = master_state.get("bridge", {}).get("port", [])
|
||||
port = next(filter(lambda n: n["name"] == slave_state["name"], ports), {})
|
||||
slave_state[BRPORT_OPTIONS] = port
|
||||
|
||||
|
||||
def _set_common_slaves_metadata(master_state, slave_state):
|
||||
slave_state[MASTER] = master_state['name']
|
||||
slave_state[MASTER_TYPE] = master_state.get('type')
|
||||
slave_state[MASTER] = master_state["name"]
|
||||
slave_state[MASTER_TYPE] = master_state.get("type")
|
||||
|
||||
|
||||
def _get_ovs_slaves_from_state(iface_state, default=()):
|
||||
ports = iface_state.get('bridge', {}).get('port')
|
||||
ports = iface_state.get("bridge", {}).get("port")
|
||||
if ports is None:
|
||||
return default
|
||||
return [p['name'] for p in ports]
|
||||
return [p["name"] for p in ports]
|
||||
|
||||
|
||||
def _generate_link_master_metadata(
|
||||
@ -132,8 +132,8 @@ def _generate_link_master_metadata(
|
||||
desired_masters = [
|
||||
(ifname, ifstate)
|
||||
for ifname, ifstate in ifaces_desired_state.items()
|
||||
if ifstate.get('type') == master_type
|
||||
and ifstate.get('state') not in ('down', 'absent')
|
||||
if ifstate.get("type") == master_type
|
||||
and ifstate.get("state") not in ("down", "absent")
|
||||
]
|
||||
for master_name, master_state in desired_masters:
|
||||
desired_slaves = get_slaves_func(master_state)
|
||||
@ -142,8 +142,8 @@ def _generate_link_master_metadata(
|
||||
set_metadata_func(master_state, ifaces_desired_state[slave])
|
||||
elif slave in ifaces_current_state:
|
||||
ifaces_desired_state[slave] = {
|
||||
'name': slave,
|
||||
'state': master_state['state'],
|
||||
"name": slave,
|
||||
"state": master_state["state"],
|
||||
}
|
||||
set_metadata_func(master_state, ifaces_desired_state[slave])
|
||||
|
||||
@ -155,19 +155,19 @@ def _generate_link_master_metadata(
|
||||
slaves2remove = set(current_slaves) - set(desired_slaves)
|
||||
for slave in slaves2remove:
|
||||
if slave not in ifaces_desired_state:
|
||||
ifaces_desired_state[slave] = {'name': slave}
|
||||
ifaces_desired_state[slave] = {"name": slave}
|
||||
|
||||
current_masters = (
|
||||
(ifname, ifstate)
|
||||
for ifname, ifstate in ifaces_current_state.items()
|
||||
if ifstate.get('type') == master_type
|
||||
if ifstate.get("type") == master_type
|
||||
)
|
||||
for master_name, master_state in current_masters:
|
||||
current_slaves = get_slaves_func(master_state)
|
||||
for slave in current_slaves:
|
||||
if slave in ifaces_desired_state:
|
||||
iface_state = ifaces_desired_state.get(master_name, {})
|
||||
if iface_state.get('state') not in ('down', 'absent'):
|
||||
if iface_state.get("state") not in ("down", "absent"):
|
||||
master_has_no_slaves_specified_in_desired = (
|
||||
get_slaves_func(iface_state, None) is None
|
||||
)
|
||||
@ -265,8 +265,8 @@ def _save_dns_metadata(
|
||||
family = Interface.IPV4
|
||||
if not iface_name:
|
||||
raise NmstateValueError(
|
||||
'Failed to find suitable interface for saving DNS '
|
||||
'name servers: %s' % server
|
||||
"Failed to find suitable interface for saving DNS "
|
||||
"name servers: %s" % server
|
||||
)
|
||||
|
||||
_include_name_only_iface_state(
|
||||
@ -391,8 +391,8 @@ def _generate_route_rule_per_stack_metadata(
|
||||
iface_name = _find_iface_for_route_table(routes, route_table)
|
||||
if not iface_name:
|
||||
raise NmstateValueError(
|
||||
'Failed to find suitable interface for saving route rule: '
|
||||
'{}'.format(rules[0])
|
||||
"Failed to find suitable interface for saving route rule: "
|
||||
"{}".format(rules[0])
|
||||
)
|
||||
iface_state = desired_state.interfaces[iface_name]
|
||||
_attach_route_rule_metadata(iface_state, rules, family)
|
||||
|
@ -154,9 +154,9 @@ def _apply_ifaces_state(
|
||||
if not commit:
|
||||
return checkpoint
|
||||
except nm.checkpoint.NMCheckPointPermissionError:
|
||||
raise NmstatePermissionError('Error creating a check point')
|
||||
raise NmstatePermissionError("Error creating a check point")
|
||||
except nm.checkpoint.NMCheckPointCreationError:
|
||||
raise NmstateConflictError('Error creating a check point')
|
||||
raise NmstateConflictError("Error creating a check point")
|
||||
except NmstateError:
|
||||
# Assume rollback occured, revert IPv6 stack state.
|
||||
# Checkpoint rollback is async, there is a need to wait for it to
|
||||
@ -211,14 +211,14 @@ def _setup_providers():
|
||||
if not success:
|
||||
nmclient.mainloop(refresh=True)
|
||||
raise NmstateLibnmError(
|
||||
'Unexpected failure of libnm when running the mainloop: {}'.format(
|
||||
"Unexpected failure of libnm when running the mainloop: {}".format(
|
||||
mainloop.error
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _add_interfaces(new_interfaces, desired_state):
|
||||
logging.debug('Adding new interfaces: %s', new_interfaces)
|
||||
logging.debug("Adding new interfaces: %s", new_interfaces)
|
||||
|
||||
ifaces2add = [desired_state.interfaces[name] for name in new_interfaces]
|
||||
|
||||
@ -230,13 +230,13 @@ def _add_interfaces(new_interfaces, desired_state):
|
||||
|
||||
|
||||
def _edit_interfaces(state2edit):
|
||||
logging.debug('Editing interfaces: %s', list(state2edit.interfaces))
|
||||
logging.debug("Editing interfaces: %s", list(state2edit.interfaces))
|
||||
|
||||
ifaces2edit = list(state2edit.interfaces.values())
|
||||
|
||||
iface2prepare = list(
|
||||
filter(
|
||||
lambda state: state.get('state') not in ('absent', 'down'),
|
||||
lambda state: state.get("state") not in ("absent", "down"),
|
||||
ifaces2edit,
|
||||
)
|
||||
)
|
||||
@ -250,7 +250,7 @@ def _edit_interfaces(state2edit):
|
||||
|
||||
|
||||
def _index_by_name(ifaces_state):
|
||||
return {iface['name']: iface for iface in ifaces_state}
|
||||
return {iface["name"]: iface for iface in ifaces_state}
|
||||
|
||||
|
||||
def _disable_ipv6(desired_state):
|
||||
@ -264,5 +264,5 @@ def _disable_ipv6(desired_state):
|
||||
if ifstate.get(schema.Interface.STATE) != schema.InterfaceState.UP:
|
||||
continue
|
||||
ipv6_state = ifstate.get(schema.Interface.IPV6, {})
|
||||
if ipv6_state.get('enabled') is False:
|
||||
if ipv6_state.get("enabled") is False:
|
||||
sysctl.disable_ipv6(ifstate[schema.Interface.NAME])
|
||||
|
@ -42,7 +42,7 @@ def show(include_status_data=False):
|
||||
|
||||
report = {Constants.INTERFACES: interfaces()}
|
||||
if include_status_data:
|
||||
report['capabilities'] = capabilities()
|
||||
report["capabilities"] = capabilities()
|
||||
|
||||
report[Constants.ROUTES] = {
|
||||
Route.RUNNING: (
|
||||
@ -92,13 +92,13 @@ def interfaces():
|
||||
]
|
||||
|
||||
for dev, devinfo in devices_info:
|
||||
type_id = devinfo['type_id']
|
||||
type_id = devinfo["type_id"]
|
||||
|
||||
iface_info = nm.translator.Nm2Api.get_common_device_info(devinfo)
|
||||
|
||||
act_con = nm.connection.get_device_active_connection(dev)
|
||||
iface_info['ipv4'] = nm.ipv4.get_info(act_con)
|
||||
iface_info['ipv6'] = nm.ipv6.get_info(act_con)
|
||||
iface_info["ipv4"] = nm.ipv4.get_info(act_con)
|
||||
iface_info["ipv6"] = nm.ipv6.get_info(act_con)
|
||||
iface_info.update(nm.wired.get_info(dev))
|
||||
iface_info.update(nm.user.get_info(dev))
|
||||
iface_info.update(nm.vlan.get_info(dev))
|
||||
@ -110,14 +110,14 @@ def interfaces():
|
||||
iface_info.update(_ifaceinfo_bond(bondinfo))
|
||||
elif nm.ovs.has_ovs_capability():
|
||||
if nm.ovs.is_ovs_bridge_type_id(type_id):
|
||||
iface_info['bridge'] = nm.ovs.get_ovs_info(dev, devices_info)
|
||||
iface_info["bridge"] = nm.ovs.get_ovs_info(dev, devices_info)
|
||||
iface_info = _remove_ovs_bridge_unsupported_entries(iface_info)
|
||||
elif nm.ovs.is_ovs_port_type_id(type_id):
|
||||
continue
|
||||
|
||||
info.append(iface_info)
|
||||
|
||||
info.sort(key=itemgetter('name'))
|
||||
info.sort(key=itemgetter("name"))
|
||||
|
||||
return info
|
||||
|
||||
@ -125,7 +125,7 @@ def interfaces():
|
||||
def _ifaceinfo_bond(devinfo):
|
||||
# TODO: What about unmanaged devices?
|
||||
bondinfo = nm.translator.Nm2Api.get_bond_info(devinfo)
|
||||
if 'link-aggregation' in bondinfo:
|
||||
if "link-aggregation" in bondinfo:
|
||||
return bondinfo
|
||||
return {}
|
||||
|
||||
|
@ -26,7 +26,7 @@ from .nmclient import GLib
|
||||
from .nmclient import NM
|
||||
|
||||
|
||||
NM_MANAGER_ERROR_DOMAIN = 'nm-manager-error-quark'
|
||||
NM_MANAGER_ERROR_DOMAIN = "nm-manager-error-quark"
|
||||
|
||||
|
||||
class ActivationError(Exception):
|
||||
@ -88,7 +88,7 @@ class ActiveConnection:
|
||||
except Exception as e:
|
||||
if self._mainloop.is_action_canceled(e):
|
||||
logging.debug(
|
||||
'Connection deactivation aborted on %s: error=%s',
|
||||
"Connection deactivation aborted on %s: error=%s",
|
||||
self._nmdev.get_iface(),
|
||||
e,
|
||||
)
|
||||
@ -102,25 +102,25 @@ class ActiveConnection:
|
||||
):
|
||||
success = True
|
||||
logging.debug(
|
||||
'Connection is not active on {}, no need to '
|
||||
'deactivate'.format(self.devname)
|
||||
"Connection is not active on {}, no need to "
|
||||
"deactivate".format(self.devname)
|
||||
)
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection deactivation failed on {}: '
|
||||
'error={}'.format(self._nmdev.get_iface(), e)
|
||||
"Connection deactivation failed on {}: "
|
||||
"error={}".format(self._nmdev.get_iface(), e)
|
||||
)
|
||||
return
|
||||
|
||||
if success:
|
||||
logging.debug(
|
||||
'Connection deactivation succeeded on %s',
|
||||
"Connection deactivation succeeded on %s",
|
||||
self._nmdev.get_iface(),
|
||||
)
|
||||
self._mainloop.execute_next_action()
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection deactivation failed on %s: error=unknown'
|
||||
"Connection deactivation failed on %s: error=unknown"
|
||||
% self._nmdev.get_iface()
|
||||
)
|
||||
|
||||
|
@ -43,11 +43,11 @@ from . import vxlan
|
||||
from . import wired
|
||||
|
||||
|
||||
MASTER_METADATA = '_master'
|
||||
MASTER_TYPE_METADATA = '_master_type'
|
||||
MASTER_METADATA = "_master"
|
||||
MASTER_TYPE_METADATA = "_master_type"
|
||||
MASTER_IFACE_TYPES = ovs.BRIDGE_TYPE, bond.BOND_TYPE, LB.TYPE
|
||||
|
||||
BRPORT_OPTIONS_METADATA = '_brport_options'
|
||||
BRPORT_OPTIONS_METADATA = "_brport_options"
|
||||
|
||||
|
||||
def create_new_ifaces(con_profiles):
|
||||
@ -197,7 +197,7 @@ def set_ifaces_admin_state(ifaces_desired_state, con_profiles=()):
|
||||
remove_devs_actions[nmdev].append(device.delete_device)
|
||||
else:
|
||||
raise NmstateValueError(
|
||||
'Invalid state {} for interface {}'.format(
|
||||
"Invalid state {} for interface {}".format(
|
||||
iface_desired_state[Interface.STATE],
|
||||
iface_desired_state[Interface.NAME],
|
||||
)
|
||||
@ -330,12 +330,12 @@ def prepare_proxy_ifaces_desired_state(ifaces_desired_state):
|
||||
|
||||
def _create_ovs_port_iface_desired_state(iface_desired_state, port_options):
|
||||
return {
|
||||
'name': ovs.PORT_PROFILE_PREFIX + iface_desired_state[Interface.NAME],
|
||||
'type': ovs.PORT_TYPE,
|
||||
'state': iface_desired_state[Interface.STATE],
|
||||
"name": ovs.PORT_PROFILE_PREFIX + iface_desired_state[Interface.NAME],
|
||||
"type": ovs.PORT_TYPE,
|
||||
"state": iface_desired_state[Interface.STATE],
|
||||
MASTER_METADATA: iface_desired_state[MASTER_METADATA],
|
||||
MASTER_TYPE_METADATA: iface_desired_state[MASTER_TYPE_METADATA],
|
||||
'options': port_options,
|
||||
"options": port_options,
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@ from . import nmclient
|
||||
from libnmstate.error import NmstateValueError
|
||||
|
||||
|
||||
BOND_TYPE = 'bond'
|
||||
BOND_TYPE = "bond"
|
||||
|
||||
|
||||
def create_setting(options):
|
||||
@ -31,7 +31,7 @@ def create_setting(options):
|
||||
success = bond_setting.add_option(option_name, option_value)
|
||||
if not success:
|
||||
raise NmstateValueError(
|
||||
'Invalid bond option: \'{}\'=\'{}\''.format(
|
||||
"Invalid bond option: '{}'='{}'".format(
|
||||
option_name, option_value
|
||||
)
|
||||
)
|
||||
@ -47,7 +47,7 @@ def get_bond_info(nm_device):
|
||||
slaves = get_slaves(nm_device)
|
||||
options = get_options(nm_device)
|
||||
if slaves or options:
|
||||
return {'slaves': slaves, 'options': options}
|
||||
return {"slaves": slaves, "options": options}
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
@ -23,7 +23,7 @@ from libnmstate.nm import nmclient
|
||||
from libnmstate.schema import LinuxBridge as LB
|
||||
|
||||
|
||||
BRIDGE_TYPE = 'bridge'
|
||||
BRIDGE_TYPE = "bridge"
|
||||
|
||||
|
||||
def create_setting(options, base_con_profile):
|
||||
|
@ -24,13 +24,13 @@ import dbus
|
||||
import libnmstate.nm.nmclient
|
||||
|
||||
|
||||
DBUS_STD_PROPERTIES_IFNAME = 'org.freedesktop.DBus.Properties'
|
||||
DBUS_STD_PROPERTIES_IFNAME = "org.freedesktop.DBus.Properties"
|
||||
|
||||
CHECKPOINT_CREATE_FLAG_DESTROY_ALL = 0x01
|
||||
CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS = 0x02
|
||||
CHECKPOINT_CREATE_FLAG_DISCONNECT_NEW_DEVICES = 0x04
|
||||
|
||||
NM_PERMISSION_DENIED = 'org.freedesktop.NetworkManager.PermissionDenied'
|
||||
NM_PERMISSION_DENIED = "org.freedesktop.NetworkManager.PermissionDenied"
|
||||
|
||||
|
||||
_nmdbus_manager = None
|
||||
@ -62,7 +62,7 @@ def nmdbus_manager():
|
||||
|
||||
|
||||
class _NMDbus:
|
||||
BUS_NAME = 'org.freedesktop.NetworkManager'
|
||||
BUS_NAME = "org.freedesktop.NetworkManager"
|
||||
|
||||
bus = None
|
||||
|
||||
@ -72,8 +72,8 @@ class _NMDbus:
|
||||
|
||||
|
||||
class _NMDbusManager:
|
||||
IF_NAME = 'org.freedesktop.NetworkManager'
|
||||
OBJ_PATH = '/org/freedesktop/NetworkManager'
|
||||
IF_NAME = "org.freedesktop.NetworkManager"
|
||||
OBJ_PATH = "/org/freedesktop/NetworkManager"
|
||||
|
||||
def __init__(self):
|
||||
mng_proxy = _NMDbus.bus.get_object(
|
||||
@ -121,7 +121,7 @@ class CheckPoint:
|
||||
devs, timeout, cp_flags
|
||||
)
|
||||
logging.debug(
|
||||
'Checkpoint %s created for all devices: %s', dbuspath, timeout
|
||||
"Checkpoint %s created for all devices: %s", dbuspath, timeout
|
||||
)
|
||||
self._dbuspath = dbuspath
|
||||
except dbus.exceptions.DBusException as e:
|
||||
@ -135,7 +135,7 @@ class CheckPoint:
|
||||
except dbus.exceptions.DBusException as e:
|
||||
raise NMCheckPointError(str(e))
|
||||
|
||||
logging.debug('Checkpoint %s destroyed', self._dbuspath)
|
||||
logging.debug("Checkpoint %s destroyed", self._dbuspath)
|
||||
|
||||
def rollback(self):
|
||||
try:
|
||||
@ -143,7 +143,7 @@ class CheckPoint:
|
||||
except dbus.exceptions.DBusException as e:
|
||||
raise NMCheckPointError(str(e))
|
||||
logging.debug(
|
||||
'Checkpoint %s rollback executed: %s', self._dbuspath, result
|
||||
"Checkpoint %s rollback executed: %s", self._dbuspath, result
|
||||
)
|
||||
return result
|
||||
|
||||
|
@ -137,7 +137,7 @@ class ConnectionProfile:
|
||||
elif self.nmdevice:
|
||||
self.import_by_device()
|
||||
elif not self.profile:
|
||||
err_format = 'Missing base properties: profile={}, id={}, dev={}'
|
||||
err_format = "Missing base properties: profile={}, id={}, dev={}"
|
||||
err_msg = err_format.format(
|
||||
self.profile, self.con_id, self.devname
|
||||
)
|
||||
@ -151,7 +151,7 @@ class ConnectionProfile:
|
||||
ac.import_by_device(self.nmdevice)
|
||||
if ac.is_activating:
|
||||
logging.debug(
|
||||
'Connection activation in progress: dev=%s, state=%s',
|
||||
"Connection activation in progress: dev=%s, state=%s",
|
||||
ac.devname,
|
||||
ac.state,
|
||||
)
|
||||
@ -188,14 +188,14 @@ class ConnectionProfile:
|
||||
|
||||
if self._mainloop.is_action_canceled(e):
|
||||
logging.debug(
|
||||
'Connection activation canceled on %s %s: error=%s',
|
||||
"Connection activation canceled on %s %s: error=%s",
|
||||
act_type,
|
||||
act_object,
|
||||
e,
|
||||
)
|
||||
elif self._is_connection_unavailable(e):
|
||||
logging.warning(
|
||||
'Connection unavailable on %s %s, retrying',
|
||||
"Connection unavailable on %s %s, retrying",
|
||||
act_type,
|
||||
act_object,
|
||||
)
|
||||
@ -204,7 +204,7 @@ class ConnectionProfile:
|
||||
self.safe_activate_async()
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection activation failed on {} {}: error={}'.format(
|
||||
"Connection activation failed on {} {}: error={}".format(
|
||||
act_type, act_object, e
|
||||
)
|
||||
)
|
||||
@ -213,14 +213,14 @@ class ConnectionProfile:
|
||||
if nm_act_con is None:
|
||||
act_type, act_object = self._get_activation_metadata()
|
||||
self._mainloop.quit(
|
||||
'Connection activation failed on {} {}: error=unknown'.format(
|
||||
"Connection activation failed on {} {}: error=unknown".format(
|
||||
act_type, act_object
|
||||
)
|
||||
)
|
||||
else:
|
||||
devname = nm_act_con.props.connection.get_interface_name()
|
||||
logging.debug(
|
||||
'Connection activation initiated: dev=%s, con-state=%s',
|
||||
"Connection activation initiated: dev=%s, con-state=%s",
|
||||
devname,
|
||||
nm_act_con.props.state,
|
||||
)
|
||||
@ -232,7 +232,7 @@ class ConnectionProfile:
|
||||
self.waitfor_active_connection_async(ac)
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection activation failed on {}: reason={}'.format(
|
||||
"Connection activation failed on {}: reason={}".format(
|
||||
ac.devname, ac.reason
|
||||
)
|
||||
)
|
||||
@ -241,32 +241,32 @@ class ConnectionProfile:
|
||||
def _is_connection_unavailable(err):
|
||||
return (
|
||||
isinstance(err, nmclient.GLib.GError)
|
||||
and err.domain == 'nm-manager-error-quark'
|
||||
and err.domain == "nm-manager-error-quark"
|
||||
and err.code == 2
|
||||
and 'is not available on the device' in err.message
|
||||
and "is not available on the device" in err.message
|
||||
)
|
||||
|
||||
def _get_activation_metadata(self):
|
||||
if self._nmdevice:
|
||||
activation_type = 'device'
|
||||
activation_type = "device"
|
||||
activation_object = self._nmdevice.get_iface()
|
||||
elif self._con_id:
|
||||
activation_type = 'connection_id'
|
||||
activation_type = "connection_id"
|
||||
activation_object = self._con_id
|
||||
else:
|
||||
activation_type = activation_object = 'unknown'
|
||||
activation_type = activation_object = "unknown"
|
||||
|
||||
return activation_type, activation_object
|
||||
|
||||
def waitfor_active_connection_async(self, ac):
|
||||
ac.handlers.add(
|
||||
ac.nm_active_connection.connect(
|
||||
'state-changed', self._waitfor_active_connection_callback, ac
|
||||
"state-changed", self._waitfor_active_connection_callback, ac
|
||||
)
|
||||
)
|
||||
ac.device_handlers.add(
|
||||
ac.nmdevice.connect(
|
||||
'state-changed', self._waitfor_device_state_change_callback, ac
|
||||
"state-changed", self._waitfor_device_state_change_callback, ac
|
||||
)
|
||||
)
|
||||
|
||||
@ -281,7 +281,7 @@ class ConnectionProfile:
|
||||
cur_nm_act_conn = get_device_active_connection(self.nmdevice)
|
||||
if cur_nm_act_conn and cur_nm_act_conn != ac.nm_active_connection:
|
||||
logging.debug(
|
||||
'Active connection of device {} has been replaced'.format(
|
||||
"Active connection of device {} has been replaced".format(
|
||||
self.devname
|
||||
)
|
||||
)
|
||||
@ -293,8 +293,8 @@ class ConnectionProfile:
|
||||
self.waitfor_active_connection_async(ac)
|
||||
if ac.is_active:
|
||||
logging.debug(
|
||||
'Connection activation succeeded: dev=%s, con-state=%s, '
|
||||
'dev-state= %s',
|
||||
"Connection activation succeeded: dev=%s, con-state=%s, "
|
||||
"dev-state= %s",
|
||||
ac.devname,
|
||||
ac.state,
|
||||
ac.nmdev_state,
|
||||
@ -304,7 +304,7 @@ class ConnectionProfile:
|
||||
elif not ac.is_activating:
|
||||
ac.remove_handlers()
|
||||
self._mainloop.quit(
|
||||
'Connection activation failed on {}: reason={}'.format(
|
||||
"Connection activation failed on {}: reason={}".format(
|
||||
ac.devname, ac.reason
|
||||
)
|
||||
)
|
||||
@ -316,16 +316,16 @@ class ConnectionProfile:
|
||||
con = src_object.add_connection_finish(result)
|
||||
except Exception as e:
|
||||
if mainloop.is_action_canceled(e):
|
||||
logging.debug('Connection adding canceled: error=%s', e)
|
||||
logging.debug("Connection adding canceled: error=%s", e)
|
||||
else:
|
||||
mainloop.quit('Connection adding failed: error={}'.format(e))
|
||||
mainloop.quit("Connection adding failed: error={}".format(e))
|
||||
return
|
||||
|
||||
if con is None:
|
||||
mainloop.quit('Connection adding failed: error=unknown')
|
||||
mainloop.quit("Connection adding failed: error=unknown")
|
||||
else:
|
||||
devname = con.get_interface_name()
|
||||
logging.debug('Connection adding succeeded: dev=%s', devname)
|
||||
logging.debug("Connection adding succeeded: dev=%s", devname)
|
||||
mainloop.execute_next_action()
|
||||
|
||||
def _delete_connection_callback(self, src_object, result, user_data):
|
||||
@ -333,17 +333,17 @@ class ConnectionProfile:
|
||||
success = src_object.delete_finish(result)
|
||||
except Exception as e:
|
||||
if self.nmdevice:
|
||||
target = 'dev/' + str(self.nmdevice.get_iface())
|
||||
target = "dev/" + str(self.nmdevice.get_iface())
|
||||
else:
|
||||
target = 'con/' + str(self.con_id)
|
||||
target = "con/" + str(self.con_id)
|
||||
|
||||
if self._mainloop.is_action_canceled(e):
|
||||
logging.debug(
|
||||
'Connection deletion aborted on %s: error=%s', target, e
|
||||
"Connection deletion aborted on %s: error=%s", target, e
|
||||
)
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection deletion failed on {}: error={}'.format(
|
||||
"Connection deletion failed on {}: error={}".format(
|
||||
target, e
|
||||
)
|
||||
)
|
||||
@ -351,12 +351,12 @@ class ConnectionProfile:
|
||||
|
||||
devname = src_object.get_interface_name()
|
||||
if success:
|
||||
logging.debug('Connection deletion succeeded: dev=%s', devname)
|
||||
logging.debug("Connection deletion succeeded: dev=%s", devname)
|
||||
self._mainloop.execute_next_action()
|
||||
else:
|
||||
self._mainloop.quit(
|
||||
'Connection deletion failed: '
|
||||
'dev={}, error=unknown'.format(devname)
|
||||
"Connection deletion failed: "
|
||||
"dev={}, error=unknown".format(devname)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@ -366,10 +366,10 @@ class ConnectionProfile:
|
||||
success = src_object.commit_changes_finish(result)
|
||||
except Exception as e:
|
||||
if mainloop.is_action_canceled(e):
|
||||
logging.debug('Connection update aborted: error=%s', e)
|
||||
logging.debug("Connection update aborted: error=%s", e)
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Connection update failed: error={}, dev={}/{}'.format(
|
||||
"Connection update failed: error={}, dev={}/{}".format(
|
||||
e, nmdev.props.interface, nmdev.props.state
|
||||
)
|
||||
)
|
||||
@ -377,12 +377,12 @@ class ConnectionProfile:
|
||||
|
||||
devname = src_object.get_interface_name()
|
||||
if success:
|
||||
logging.debug('Connection update succeeded: dev=%s', devname)
|
||||
logging.debug("Connection update succeeded: dev=%s", devname)
|
||||
mainloop.execute_next_action()
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Connection update failed: '
|
||||
'dev={}, error=unknown'.format(devname)
|
||||
"Connection update failed: "
|
||||
"dev={}, error=unknown".format(devname)
|
||||
)
|
||||
|
||||
def _reset_profile(self):
|
||||
@ -405,7 +405,7 @@ class ConnectionSetting:
|
||||
)
|
||||
|
||||
self._setting = con_setting
|
||||
self._log_connection_info('ConnectionSetting.create')
|
||||
self._log_connection_info("ConnectionSetting.create")
|
||||
|
||||
def import_by_profile(self, con_profile):
|
||||
base = con_profile.profile.get_setting_connection()
|
||||
@ -418,7 +418,7 @@ class ConnectionSetting:
|
||||
new.props.autoconnect_slaves = base.props.autoconnect_slaves
|
||||
|
||||
self._setting = new
|
||||
self._log_connection_info('ConnectionSetting.import_by_profile')
|
||||
self._log_connection_info("ConnectionSetting.import_by_profile")
|
||||
|
||||
def set_master(self, master, slave_type):
|
||||
if master is not None:
|
||||
@ -432,15 +432,15 @@ class ConnectionSetting:
|
||||
def _log_connection_info(self, source):
|
||||
setting = self._setting
|
||||
logging.debug(
|
||||
'Connection settings for %s:\n'
|
||||
+ '\n'.join(
|
||||
"Connection settings for %s:\n"
|
||||
+ "\n".join(
|
||||
[
|
||||
'id: %s',
|
||||
'iface: %s',
|
||||
'uuid: %s',
|
||||
'type: %s',
|
||||
'autoconnect: %s',
|
||||
'autoconnect_slaves: %s',
|
||||
"id: %s",
|
||||
"iface: %s",
|
||||
"uuid: %s",
|
||||
"type: %s",
|
||||
"autoconnect: %s",
|
||||
"autoconnect_slaves: %s",
|
||||
]
|
||||
),
|
||||
source,
|
||||
|
@ -84,7 +84,7 @@ def _wait_for_active_connection_async(dev, connection_profile):
|
||||
act_conn = ac.ActiveConnection(active_conn)
|
||||
if act_conn.is_activating:
|
||||
logging.debug(
|
||||
'Connection activation in progress: dev=%s, state=%s',
|
||||
"Connection activation in progress: dev=%s, state=%s",
|
||||
act_conn.devname,
|
||||
act_conn.state,
|
||||
)
|
||||
@ -103,19 +103,19 @@ def _reapply_callback(src_object, result, user_data):
|
||||
success = src_object.reapply_finish(result)
|
||||
except Exception as e:
|
||||
if mainloop.is_action_canceled(e):
|
||||
logging.debug('Device reapply aborted on %s: error=%s', devname, e)
|
||||
logging.debug("Device reapply aborted on %s: error=%s", devname, e)
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Device reapply failed on {}: error={}'.format(devname, e)
|
||||
"Device reapply failed on {}: error={}".format(devname, e)
|
||||
)
|
||||
return
|
||||
|
||||
if success:
|
||||
logging.debug('Device reapply succeeded: dev=%s', devname)
|
||||
logging.debug("Device reapply succeeded: dev=%s", devname)
|
||||
mainloop.execute_next_action()
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Device reapply failed: dev={}, error=unknown'.format(devname)
|
||||
"Device reapply failed: dev={}, error=unknown".format(devname)
|
||||
)
|
||||
|
||||
|
||||
@ -164,11 +164,11 @@ def _modify_callback(src_object, result, user_data):
|
||||
success = src_object.reapply_finish(result)
|
||||
except Exception as e:
|
||||
if mainloop.is_action_canceled(e):
|
||||
logging.debug('Device reapply aborted on %s: error=%s', devname, e)
|
||||
logging.debug("Device reapply aborted on %s: error=%s", devname, e)
|
||||
else:
|
||||
logging.debug(
|
||||
'Device reapply failed on %s: error=%s\n'
|
||||
'Fallback to device activation',
|
||||
"Device reapply failed on %s: error=%s\n"
|
||||
"Fallback to device activation",
|
||||
devname,
|
||||
e,
|
||||
)
|
||||
@ -176,12 +176,12 @@ def _modify_callback(src_object, result, user_data):
|
||||
return
|
||||
|
||||
if success:
|
||||
logging.debug('Device reapply succeeded: dev=%s', devname)
|
||||
logging.debug("Device reapply succeeded: dev=%s", devname)
|
||||
mainloop.execute_next_action()
|
||||
else:
|
||||
logging.debug(
|
||||
'Device reapply failed, fallback to device activation: dev=%s, '
|
||||
'error=unknown',
|
||||
"Device reapply failed, fallback to device activation: dev=%s, "
|
||||
"error=unknown",
|
||||
devname,
|
||||
)
|
||||
_activate_async(src_object)
|
||||
@ -189,11 +189,11 @@ def _modify_callback(src_object, result, user_data):
|
||||
|
||||
def _requires_activation(dev, connection_profile):
|
||||
if StrictVersion(nmclient.nm_version()) < StrictVersion(
|
||||
'1.18'
|
||||
"1.18"
|
||||
) and _mtu_changed(dev, connection_profile):
|
||||
logging.debug(
|
||||
'Device reapply does not support mtu changes, '
|
||||
'fallback to device activation: dev=%s',
|
||||
"Device reapply does not support mtu changes, "
|
||||
"fallback to device activation: dev=%s",
|
||||
dev.get_iface(),
|
||||
)
|
||||
return True
|
||||
@ -249,14 +249,14 @@ def _delete_device_callback(src_object, result, user_data):
|
||||
and nmdev.is_software()
|
||||
):
|
||||
logging.debug(
|
||||
'Device %s has been already deleted: error=%s',
|
||||
"Device %s has been already deleted: error=%s",
|
||||
nmdev.get_iface(),
|
||||
e,
|
||||
)
|
||||
mainloop.execute_next_action()
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Device deletion failed on {}: error={}'.format(
|
||||
"Device deletion failed on {}: error={}".format(
|
||||
nmdev.get_iface(), e
|
||||
)
|
||||
)
|
||||
@ -264,11 +264,11 @@ def _delete_device_callback(src_object, result, user_data):
|
||||
except Exception as e:
|
||||
if mainloop.is_action_canceled(e):
|
||||
logging.debug(
|
||||
'Device deletion aborted on %s: error=%s', nmdev.get_iface(), e
|
||||
"Device deletion aborted on %s: error=%s", nmdev.get_iface(), e
|
||||
)
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Device deletion failed on {}: error={}'.format(
|
||||
"Device deletion failed on {}: error={}".format(
|
||||
nmdev.get_iface(), e
|
||||
)
|
||||
)
|
||||
@ -276,11 +276,11 @@ def _delete_device_callback(src_object, result, user_data):
|
||||
|
||||
devname = src_object.get_iface()
|
||||
if success:
|
||||
logging.debug('Device deletion succeeded: dev=%s', devname)
|
||||
logging.debug("Device deletion succeeded: dev=%s", devname)
|
||||
mainloop.execute_next_action()
|
||||
else:
|
||||
mainloop.quit(
|
||||
'Device deletion failed: dev={}, error=unknown'.format(devname)
|
||||
"Device deletion failed: dev={}, error=unknown".format(devname)
|
||||
)
|
||||
|
||||
|
||||
@ -296,8 +296,8 @@ def list_devices():
|
||||
|
||||
def get_device_common_info(dev):
|
||||
return {
|
||||
'name': dev.get_iface(),
|
||||
'type_id': dev.get_device_type(),
|
||||
'type_name': dev.get_type_description(),
|
||||
'state': dev.get_state(),
|
||||
"name": dev.get_iface(),
|
||||
"type_id": dev.get_device_type(),
|
||||
"type_name": dev.get_type_description(),
|
||||
"state": dev.get_state(),
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ from libnmstate.schema import Interface
|
||||
|
||||
DNS_DEFAULT_PRIORITY_VPN = 50
|
||||
DNS_DEFAULT_PRIORITY_OTHER = 100
|
||||
DNS_METADATA = '_dns'
|
||||
DNS_METADATA_PRIORITY = '_priority'
|
||||
DNS_METADATA = "_dns"
|
||||
DNS_METADATA_PRIORITY = "_priority"
|
||||
DEFAULT_DNS_PRIORITY = 0
|
||||
# The 40 is chose as default DHCP DNS priority is 100, and VPN DNS priority is
|
||||
# 50, the static DNS configuration should be list before them.
|
||||
@ -52,10 +52,10 @@ def get_running():
|
||||
# For IPv6 link local address, the interface name should be
|
||||
# appended also.
|
||||
raise NmstateInternalError(
|
||||
'Missing interface for IPv6 link-local DNS server '
|
||||
'entry {}'.format(ns)
|
||||
"Missing interface for IPv6 link-local DNS server "
|
||||
"entry {}".format(ns)
|
||||
)
|
||||
ns_addr = '{}%{}'.format(ns, iface_name)
|
||||
ns_addr = "{}%{}".format(ns, iface_name)
|
||||
else:
|
||||
ns_addr = ns
|
||||
dns_state[DNS.SERVER].append(ns_addr)
|
||||
@ -82,9 +82,9 @@ def get_config(acs_and_ipv4_profiles, acs_and_ipv6_profiles):
|
||||
|
||||
tmp_dns_confs.append(
|
||||
{
|
||||
'server': ip_profile.props.dns,
|
||||
'priority': priority,
|
||||
'search': ip_profile.props.dns_search,
|
||||
"server": ip_profile.props.dns,
|
||||
"priority": priority,
|
||||
"search": ip_profile.props.dns_search,
|
||||
}
|
||||
)
|
||||
# NetworkManager sorts the DNS entries based on various criteria including
|
||||
@ -93,10 +93,10 @@ def get_config(acs_and_ipv4_profiles, acs_and_ipv6_profiles):
|
||||
# order in a declarative way, Nmstate only uses the priority to order the
|
||||
# entries. Reference:
|
||||
# https://developer.gnome.org/NetworkManager/stable/nm-settings.html#nm-settings.property.ipv4.dns-priority
|
||||
tmp_dns_confs.sort(key=itemgetter('priority'))
|
||||
tmp_dns_confs.sort(key=itemgetter("priority"))
|
||||
for e in tmp_dns_confs:
|
||||
dns_conf[DNS.SERVER].extend(e['server'])
|
||||
dns_conf[DNS.SEARCH].extend(e['search'])
|
||||
dns_conf[DNS.SERVER].extend(e["server"])
|
||||
dns_conf[DNS.SEARCH].extend(e["search"])
|
||||
if not dns_conf[DNS.SERVER] and dns_conf[DNS.SEARCH]:
|
||||
return {}
|
||||
return dns_conf
|
||||
|
@ -48,7 +48,7 @@ def create_setting(config, base_con_profile):
|
||||
if not setting_ipv4:
|
||||
setting_ipv4 = nmclient.NM.SettingIP4Config.new()
|
||||
|
||||
setting_ipv4.props.dhcp_client_id = 'mac'
|
||||
setting_ipv4.props.dhcp_client_id = "mac"
|
||||
setting_ipv4.props.method = nmclient.NM.SETTING_IP4_CONFIG_METHOD_DISABLED
|
||||
if config and config.get(InterfaceIPv4.ENABLED):
|
||||
if config.get(InterfaceIPv4.DHCP):
|
||||
@ -108,7 +108,7 @@ def get_info(active_connection):
|
||||
nmclient.NM.SETTING_IP4_CONFIG_METHOD_AUTO
|
||||
)
|
||||
props = ip_profile.props
|
||||
if info['dhcp']:
|
||||
if info["dhcp"]:
|
||||
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
|
||||
|
@ -123,7 +123,7 @@ def create_setting(config, base_con_profile):
|
||||
setting_ip.props.addr_gen_mode = (
|
||||
nmclient.NM.SettingIP6ConfigAddrGenMode.EUI64
|
||||
)
|
||||
setting_ip.props.dhcp_duid = 'll'
|
||||
setting_ip.props.dhcp_duid = "ll"
|
||||
|
||||
if not config or not config.get(InterfaceIPv6.ENABLED):
|
||||
try:
|
||||
@ -173,7 +173,7 @@ def create_setting(config, base_con_profile):
|
||||
def _set_dynamic(setting_ip, is_dhcp, is_autoconf):
|
||||
if not is_dhcp and is_autoconf:
|
||||
raise NmstateNotImplementedError(
|
||||
'Autoconf without DHCP is not supported yet'
|
||||
"Autoconf without DHCP is not supported yet"
|
||||
)
|
||||
|
||||
if is_dhcp and is_autoconf:
|
||||
@ -189,9 +189,9 @@ def _set_static(setting_ip, ip_addresses):
|
||||
address[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
|
||||
):
|
||||
logging.warning(
|
||||
'IPv6 link local address '
|
||||
'{a[ip]}/{a[prefix-length]} is ignored '
|
||||
'when applying desired state'.format(a=address)
|
||||
"IPv6 link local address "
|
||||
"{a[ip]}/{a[prefix-length]} is ignored "
|
||||
"when applying desired state".format(a=address)
|
||||
)
|
||||
else:
|
||||
naddr = nmclient.NM.IPAddress.new(
|
||||
|
@ -23,7 +23,7 @@ import logging
|
||||
import gi
|
||||
|
||||
try:
|
||||
gi.require_version('NM', '1.0') # NOQA: F402
|
||||
gi.require_version("NM", "1.0") # NOQA: F402
|
||||
from gi.repository import NM # pylint: disable=no-name-in-module
|
||||
except ValueError:
|
||||
NM = None
|
||||
@ -39,7 +39,7 @@ GObject
|
||||
_mainloop = None
|
||||
_nmclient = None
|
||||
|
||||
_can_disable_ipv6 = hasattr(NM, 'SETTING_IP6_CONFIG_METHOD_DISABLED')
|
||||
_can_disable_ipv6 = hasattr(NM, "SETTING_IP6_CONFIG_METHOD_DISABLED")
|
||||
|
||||
|
||||
def can_disable_ipv6():
|
||||
@ -59,21 +59,21 @@ def client(refresh=False):
|
||||
_nmclient = NM.Client.new(None)
|
||||
if not _nmclient.get_nm_running():
|
||||
logging.error(
|
||||
'NetworkManager is not running, please make sure'
|
||||
'it is installed and running prior to running nmstate.\n'
|
||||
'Check the documentation for more information.'
|
||||
"NetworkManager is not running, please make sure"
|
||||
"it is installed and running prior to running nmstate.\n"
|
||||
"Check the documentation for more information."
|
||||
)
|
||||
raise error.NmstateDependencyError(
|
||||
'NetworkManager is not running'
|
||||
"NetworkManager is not running"
|
||||
)
|
||||
else:
|
||||
logging.error(
|
||||
'Missing introspection data for libnm'
|
||||
'please make sure to install it prior to running nmstate.\n'
|
||||
'Check the documentation for more information.'
|
||||
"Missing introspection data for libnm"
|
||||
"please make sure to install it prior to running nmstate.\n"
|
||||
"Check the documentation for more information."
|
||||
)
|
||||
raise error.NmstateDependencyError(
|
||||
'Missing introspection data for libnm'
|
||||
"Missing introspection data for libnm"
|
||||
)
|
||||
return _nmclient
|
||||
|
||||
@ -96,24 +96,24 @@ def mainloop(refresh=False):
|
||||
class _MainLoop:
|
||||
SUCCESS = True
|
||||
FAIL = False
|
||||
RUN_TIMEOUT_ERROR = 'run timeout'
|
||||
RUN_EXECUTION_ERROR = 'run execution'
|
||||
RUN_TIMEOUT_ERROR = "run timeout"
|
||||
RUN_EXECUTION_ERROR = "run execution"
|
||||
|
||||
def __init__(self):
|
||||
self._action_queue = deque()
|
||||
self._mainloop = GLib.MainLoop()
|
||||
self._cancellables = []
|
||||
self.new_cancellable()
|
||||
self._error = ''
|
||||
self._error = ""
|
||||
|
||||
def execute_next_action(self):
|
||||
action = self.pop_action()
|
||||
if action:
|
||||
func, args, kwargs = action
|
||||
logging.debug('Executing NM action: func=%s', func.__name__)
|
||||
logging.debug("Executing NM action: func=%s", func.__name__)
|
||||
func(*args, **kwargs)
|
||||
else:
|
||||
logging.debug('NM action queue exhausted, quiting mainloop')
|
||||
logging.debug("NM action queue exhausted, quiting mainloop")
|
||||
self._mainloop.quit()
|
||||
|
||||
def push_action(self, func, *args, **kwargs):
|
||||
@ -165,7 +165,7 @@ class _MainLoop:
|
||||
def drop_cancellable(self, c):
|
||||
idx = self._cancellables.index(c)
|
||||
if idx == 0:
|
||||
raise error.NmstateInternalError('Cannot drop main cancellable')
|
||||
raise error.NmstateInternalError("Cannot drop main cancellable")
|
||||
del self._cancellables[idx]
|
||||
|
||||
def _cancel_cancellables(self):
|
||||
@ -173,7 +173,7 @@ class _MainLoop:
|
||||
c.cancel()
|
||||
|
||||
def quit(self, reason):
|
||||
logging.error('NM main-loop aborted: %s', reason)
|
||||
logging.error("NM main-loop aborted: %s", reason)
|
||||
# In case it was the last action, add a sentinel to fail run.
|
||||
self.push_action(None)
|
||||
self._mainloop.quit()
|
||||
@ -182,7 +182,7 @@ class _MainLoop:
|
||||
def is_action_canceled(self, err):
|
||||
return (
|
||||
isinstance(err, GLib.GError)
|
||||
and err.domain == 'g-io-error-quark'
|
||||
and err.domain == "g-io-error-quark"
|
||||
and err.code == Gio.IOErrorEnum.CANCELLED
|
||||
)
|
||||
|
||||
@ -208,7 +208,7 @@ class _MainLoop:
|
||||
def _timeout_cb(data):
|
||||
mainloop, result = data
|
||||
result.append(1)
|
||||
logging.warning('NM main-loop timed out.')
|
||||
logging.warning("NM main-loop timed out.")
|
||||
mainloop.quit()
|
||||
return _MainLoop.FAIL
|
||||
|
||||
|
@ -25,23 +25,23 @@ from . import device
|
||||
from . import nmclient
|
||||
|
||||
|
||||
BRIDGE_TYPE = 'ovs-bridge'
|
||||
INTERNAL_INTERFACE_TYPE = 'ovs-interface'
|
||||
PORT_TYPE = 'ovs-port'
|
||||
PORT_PROFILE_PREFIX = 'ovs-port-'
|
||||
CAPABILITY = 'openvswitch'
|
||||
BRIDGE_TYPE = "ovs-bridge"
|
||||
INTERNAL_INTERFACE_TYPE = "ovs-interface"
|
||||
PORT_TYPE = "ovs-port"
|
||||
PORT_PROFILE_PREFIX = "ovs-port-"
|
||||
CAPABILITY = "openvswitch"
|
||||
|
||||
|
||||
_BRIDGE_OPTION_NAMES = ['fail-mode', 'mcast-snooping-enable', 'rstp', 'stp']
|
||||
_BRIDGE_OPTION_NAMES = ["fail-mode", "mcast-snooping-enable", "rstp", "stp"]
|
||||
|
||||
|
||||
_PORT_OPTION_NAMES = [
|
||||
'tag',
|
||||
'vlan-mode',
|
||||
'bond-mode',
|
||||
'lacp',
|
||||
'bond-updelay',
|
||||
'bond-downdelay',
|
||||
"tag",
|
||||
"vlan-mode",
|
||||
"bond-mode",
|
||||
"lacp",
|
||||
"bond-updelay",
|
||||
"bond-downdelay",
|
||||
]
|
||||
|
||||
|
||||
@ -56,18 +56,18 @@ def has_ovs_capability():
|
||||
def create_bridge_setting(options):
|
||||
bridge_setting = nmclient.NM.SettingOvsBridge.new()
|
||||
for option_name, option_value in options.items():
|
||||
if option_name == 'fail-mode':
|
||||
if option_name == "fail-mode":
|
||||
if option_value:
|
||||
bridge_setting.props.fail_mode = option_value
|
||||
elif option_name == 'mcast-snooping-enable':
|
||||
elif option_name == "mcast-snooping-enable":
|
||||
bridge_setting.props.mcast_snooping_enable = option_value
|
||||
elif option_name == 'rstp':
|
||||
elif option_name == "rstp":
|
||||
bridge_setting.props.rstp_enable = option_value
|
||||
elif option_name == 'stp':
|
||||
elif option_name == "stp":
|
||||
bridge_setting.props.stp_enable = option_value
|
||||
else:
|
||||
raise NmstateValueError(
|
||||
'Invalid OVS bridge option: \'{}\'=\'{}\''.format(
|
||||
"Invalid OVS bridge option: '{}'='{}'".format(
|
||||
option_name, option_value
|
||||
)
|
||||
)
|
||||
@ -78,21 +78,21 @@ def create_bridge_setting(options):
|
||||
def create_port_setting(options):
|
||||
port_setting = nmclient.NM.SettingOvsPort.new()
|
||||
for option_name, option_value in options.items():
|
||||
if option_name == 'tag':
|
||||
if option_name == "tag":
|
||||
port_setting.props.tag = option_value
|
||||
elif option_name == 'vlan-mode':
|
||||
elif option_name == "vlan-mode":
|
||||
port_setting.props.vlan_mode = option_value
|
||||
elif option_name == 'bond-mode':
|
||||
elif option_name == "bond-mode":
|
||||
port_setting.props.bond_mode = option_value
|
||||
elif option_name == 'lacp':
|
||||
elif option_name == "lacp":
|
||||
port_setting.props.lacp = option_value
|
||||
elif option_name == 'bond-updelay':
|
||||
elif option_name == "bond-updelay":
|
||||
port_setting.props.bond_updelay = option_value
|
||||
elif option_name == 'bond-downdelay':
|
||||
elif option_name == "bond-downdelay":
|
||||
port_setting.props.bond_downdelay = option_value
|
||||
else:
|
||||
raise NmstateValueError(
|
||||
'Invalid OVS port option: \'{}\'=\'{}\''.format(
|
||||
"Invalid OVS port option: '{}'='{}'".format(
|
||||
option_name, option_value
|
||||
)
|
||||
)
|
||||
@ -102,13 +102,13 @@ def create_port_setting(options):
|
||||
|
||||
def create_interface_setting():
|
||||
interface_setting = nmclient.NM.SettingOvsInterface.new()
|
||||
interface_setting.props.type = 'internal'
|
||||
interface_setting.props.type = "internal"
|
||||
return interface_setting
|
||||
|
||||
|
||||
def translate_bridge_options(iface_state):
|
||||
br_opts = {}
|
||||
bridge_state = iface_state.get('bridge', {}).get('options', {})
|
||||
bridge_state = iface_state.get("bridge", {}).get("options", {})
|
||||
for key in bridge_state.keys() & set(_BRIDGE_OPTION_NAMES):
|
||||
br_opts[key] = bridge_state[key]
|
||||
|
||||
@ -149,7 +149,7 @@ def get_ovs_info(bridge_device, devices_info):
|
||||
options = _get_bridge_options(bridge_device)
|
||||
|
||||
if ports or options:
|
||||
return {'port': ports, 'options': options}
|
||||
return {"port": ports, "options": options}
|
||||
else:
|
||||
return {}
|
||||
|
||||
@ -181,10 +181,10 @@ def _get_bridge_port_info(port_profile, devices_info):
|
||||
|
||||
if port_slave_names:
|
||||
iface_slave_name = port_slave_names[0]
|
||||
port_info['name'] = iface_slave_name
|
||||
port_info["name"] = iface_slave_name
|
||||
if vlan_mode:
|
||||
port_info['vlan-mode'] = vlan_mode
|
||||
port_info['access-tag'] = port_setting.props.tag
|
||||
port_info["vlan-mode"] = vlan_mode
|
||||
port_info["access-tag"] = port_setting.props.tag
|
||||
|
||||
return port_info
|
||||
|
||||
@ -195,11 +195,11 @@ def _get_bridge_options(bridge_device):
|
||||
con.import_by_device(bridge_device)
|
||||
if con.profile:
|
||||
bridge_setting = con.profile.get_setting(nmclient.NM.SettingOvsBridge)
|
||||
bridge_options['stp'] = bridge_setting.props.stp_enable
|
||||
bridge_options['rstp'] = bridge_setting.props.rstp_enable
|
||||
bridge_options['fail-mode'] = bridge_setting.props.fail_mode or ''
|
||||
bridge_options["stp"] = bridge_setting.props.stp_enable
|
||||
bridge_options["rstp"] = bridge_setting.props.rstp_enable
|
||||
bridge_options["fail-mode"] = bridge_setting.props.fail_mode or ""
|
||||
bridge_options[
|
||||
'mcast-snooping-enable'
|
||||
"mcast-snooping-enable"
|
||||
] = bridge_setting.props.mcast_snooping_enable
|
||||
|
||||
return bridge_options
|
||||
|
@ -30,11 +30,11 @@ from libnmstate.schema import Interface
|
||||
from libnmstate.schema import Route
|
||||
from libnmstate.schema import RouteRule
|
||||
|
||||
NM_ROUTE_TABLE_ATTRIBUTE = 'table'
|
||||
IPV4_DEFAULT_GATEWAY_DESTINATION = '0.0.0.0/0'
|
||||
IPV6_DEFAULT_GATEWAY_DESTINATION = '::/0'
|
||||
ROUTE_METADATA = '_routes'
|
||||
ROUTE_RULES_METADATA = '_route_rules'
|
||||
NM_ROUTE_TABLE_ATTRIBUTE = "table"
|
||||
IPV4_DEFAULT_GATEWAY_DESTINATION = "0.0.0.0/0"
|
||||
IPV6_DEFAULT_GATEWAY_DESTINATION = "::/0"
|
||||
ROUTE_METADATA = "_routes"
|
||||
ROUTE_RULES_METADATA = "_route_rules"
|
||||
|
||||
# NM require route rule priority been set explicitly, use 30,000 when
|
||||
# desire state instruct to use USE_DEFAULT_PRIORITY
|
||||
@ -54,7 +54,7 @@ def get_running(acs_and_ip_cfgs):
|
||||
iface_name = nm_ac.ActiveConnection(active_connection).devname
|
||||
if not iface_name:
|
||||
raise NmstateInternalError(
|
||||
'Got connection {} has not interface name'.format(
|
||||
"Got connection {} has not interface name".format(
|
||||
active_connection.get_id()
|
||||
)
|
||||
)
|
||||
@ -88,7 +88,7 @@ def get_config(acs_and_ip_profiles):
|
||||
iface_name = nm_ac.ActiveConnection(active_connection).devname
|
||||
if not iface_name:
|
||||
raise NmstateInternalError(
|
||||
'Got connection {} has not interface name'.format(
|
||||
"Got connection {} has not interface name".format(
|
||||
active_connection.get_id()
|
||||
)
|
||||
)
|
||||
@ -126,10 +126,10 @@ def _get_per_route_table_id(nm_route, default_table_id):
|
||||
|
||||
|
||||
def _nm_route_to_route(nm_route, table_id, iface_name):
|
||||
dst = '{ip}/{prefix}'.format(
|
||||
dst = "{ip}/{prefix}".format(
|
||||
ip=nm_route.get_dest(), prefix=nm_route.get_prefix()
|
||||
)
|
||||
next_hop = nm_route.get_next_hop() or ''
|
||||
next_hop = nm_route.get_next_hop() or ""
|
||||
metric = int(nm_route.get_metric())
|
||||
|
||||
return {
|
||||
@ -163,9 +163,9 @@ def add_routes(setting_ip, routes):
|
||||
):
|
||||
if setting_ip.get_gateway():
|
||||
raise NmstateNotImplementedError(
|
||||
'Only a single default gateway is supported due to a '
|
||||
'limitation of NetworkManager: '
|
||||
'https://bugzilla.redhat.com/1707396'
|
||||
"Only a single default gateway is supported due to a "
|
||||
"limitation of NetworkManager: "
|
||||
"https://bugzilla.redhat.com/1707396"
|
||||
)
|
||||
_add_route_gateway(setting_ip, route)
|
||||
else:
|
||||
@ -173,7 +173,7 @@ def add_routes(setting_ip, routes):
|
||||
|
||||
|
||||
def _add_specfic_route(setting_ip, route):
|
||||
destination, prefix_len = route[Route.DESTINATION].split('/')
|
||||
destination, prefix_len = route[Route.DESTINATION].split("/")
|
||||
prefix_len = int(prefix_len)
|
||||
if iplib.is_ipv6_address(destination):
|
||||
family = socket.AF_INET6
|
||||
@ -268,7 +268,7 @@ def _rule_info_to_nm_rule(rule, family):
|
||||
ip_to = rule.get(RouteRule.IP_TO)
|
||||
if not ip_from and not ip_to:
|
||||
raise NmstateValueError(
|
||||
f'Neither {RouteRule.IP_FROM} or {RouteRule.IP_TO} is defined'
|
||||
f"Neither {RouteRule.IP_FROM} or {RouteRule.IP_TO} is defined"
|
||||
)
|
||||
|
||||
if ip_from:
|
||||
|
@ -22,12 +22,12 @@ import copy
|
||||
from . import nmclient
|
||||
|
||||
|
||||
IFACE_TYPE_UNKNOWN = 'unknown'
|
||||
IFACE_TYPE_UNKNOWN = "unknown"
|
||||
|
||||
|
||||
class ApiIfaceAdminState:
|
||||
DOWN = 'down'
|
||||
UP = 'up'
|
||||
DOWN = "down"
|
||||
UP = "up"
|
||||
|
||||
|
||||
class Api2Nm:
|
||||
@ -41,18 +41,18 @@ class Api2Nm:
|
||||
def get_iface_type_map():
|
||||
if Api2Nm._iface_types_map is None:
|
||||
Api2Nm._iface_types_map = {
|
||||
'ethernet': nmclient.NM.SETTING_WIRED_SETTING_NAME,
|
||||
'bond': nmclient.NM.SETTING_BOND_SETTING_NAME,
|
||||
'dummy': nmclient.NM.SETTING_DUMMY_SETTING_NAME,
|
||||
'vlan': nmclient.NM.SETTING_VLAN_SETTING_NAME,
|
||||
'vxlan': nmclient.NM.SETTING_VXLAN_SETTING_NAME,
|
||||
'linux-bridge': nmclient.NM.SETTING_BRIDGE_SETTING_NAME,
|
||||
"ethernet": nmclient.NM.SETTING_WIRED_SETTING_NAME,
|
||||
"bond": nmclient.NM.SETTING_BOND_SETTING_NAME,
|
||||
"dummy": nmclient.NM.SETTING_DUMMY_SETTING_NAME,
|
||||
"vlan": nmclient.NM.SETTING_VLAN_SETTING_NAME,
|
||||
"vxlan": nmclient.NM.SETTING_VXLAN_SETTING_NAME,
|
||||
"linux-bridge": nmclient.NM.SETTING_BRIDGE_SETTING_NAME,
|
||||
}
|
||||
try:
|
||||
ovs_types = {
|
||||
'ovs-bridge': nmclient.NM.SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||
'ovs-port': nmclient.NM.SETTING_OVS_PORT_SETTING_NAME,
|
||||
'ovs-interface': (
|
||||
"ovs-bridge": nmclient.NM.SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||
"ovs-port": nmclient.NM.SETTING_OVS_PORT_SETTING_NAME,
|
||||
"ovs-interface": (
|
||||
nmclient.NM.SETTING_OVS_INTERFACE_SETTING_NAME
|
||||
),
|
||||
}
|
||||
@ -64,12 +64,12 @@ class Api2Nm:
|
||||
|
||||
@staticmethod
|
||||
def get_bond_options(iface_desired_state):
|
||||
iface_type = Api2Nm.get_iface_type(iface_desired_state['type'])
|
||||
if iface_type == 'bond':
|
||||
iface_type = Api2Nm.get_iface_type(iface_desired_state["type"])
|
||||
if iface_type == "bond":
|
||||
# Is the mode a must config parameter?
|
||||
bond_conf = iface_desired_state['link-aggregation']
|
||||
bond_opts = {'mode': bond_conf['mode']}
|
||||
bond_opts.update(bond_conf.get('options', {}))
|
||||
bond_conf = iface_desired_state["link-aggregation"]
|
||||
bond_opts = {"mode": bond_conf["mode"]}
|
||||
bond_opts.update(bond_conf.get("options", {}))
|
||||
else:
|
||||
bond_opts = {}
|
||||
|
||||
@ -81,29 +81,29 @@ class Nm2Api:
|
||||
|
||||
@staticmethod
|
||||
def get_common_device_info(devinfo):
|
||||
type_name = devinfo['type_name']
|
||||
if type_name != 'ethernet':
|
||||
type_name = devinfo["type_name"]
|
||||
if type_name != "ethernet":
|
||||
type_name = Nm2Api.get_iface_type(type_name)
|
||||
return {
|
||||
'name': devinfo['name'],
|
||||
'type': type_name,
|
||||
'state': Nm2Api.get_iface_admin_state(devinfo['state']),
|
||||
"name": devinfo["name"],
|
||||
"type": type_name,
|
||||
"state": Nm2Api.get_iface_admin_state(devinfo["state"]),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_bond_info(bondinfo):
|
||||
bond_options = copy.deepcopy(bondinfo.get('options'))
|
||||
bond_options = copy.deepcopy(bondinfo.get("options"))
|
||||
if not bond_options:
|
||||
return {}
|
||||
bond_slaves = bondinfo['slaves']
|
||||
bond_slaves = bondinfo["slaves"]
|
||||
|
||||
bond_mode = bond_options['mode']
|
||||
del bond_options['mode']
|
||||
bond_mode = bond_options["mode"]
|
||||
del bond_options["mode"]
|
||||
return {
|
||||
'link-aggregation': {
|
||||
'mode': bond_mode,
|
||||
'slaves': [slave.props.interface for slave in bond_slaves],
|
||||
'options': bond_options,
|
||||
"link-aggregation": {
|
||||
"mode": bond_mode,
|
||||
"slaves": [slave.props.interface for slave in bond_slaves],
|
||||
"options": bond_options,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,13 @@ NMSTATE_DESCRIPTION = "nmstate.interface.description"
|
||||
|
||||
|
||||
def create_setting(iface_state, base_con_profile):
|
||||
description = iface_state.get('description')
|
||||
description = iface_state.get("description")
|
||||
|
||||
if not description:
|
||||
return None
|
||||
|
||||
if not nmclient.NM.SettingUser.check_val(description):
|
||||
raise NmstateValueError('Invalid description')
|
||||
raise NmstateValueError("Invalid description")
|
||||
|
||||
user_setting = None
|
||||
if base_con_profile:
|
||||
@ -70,7 +70,7 @@ def get_info(device):
|
||||
)
|
||||
description = user_setting.get_data(NMSTATE_DESCRIPTION)
|
||||
if description:
|
||||
info['description'] = description
|
||||
info["description"] = description
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
@ -56,12 +56,12 @@ def get_info(device):
|
||||
Provides the current active values for a device
|
||||
"""
|
||||
if device.get_device_type() == nmclient.NM.DeviceType.VXLAN:
|
||||
base_iface = ''
|
||||
base_iface = ""
|
||||
if device.props.parent:
|
||||
base_iface = device.props.parent.get_iface()
|
||||
remote = device.props.group
|
||||
if not remote:
|
||||
remote = ''
|
||||
remote = ""
|
||||
return {
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: device.props.id,
|
||||
@ -83,7 +83,7 @@ def _get_destination_port(device):
|
||||
|
||||
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1768388
|
||||
"""
|
||||
if nm.nmclient.nm_version() >= StrictVersion('1.20.6'):
|
||||
if nm.nmclient.nm_version() >= StrictVersion("1.20.6"):
|
||||
return device.get_dst_port()
|
||||
else:
|
||||
con = connection.ConnectionProfile()
|
||||
|
@ -24,7 +24,7 @@ from libnmstate.schema import Ethernet
|
||||
from libnmstate.schema import Interface
|
||||
|
||||
|
||||
ZEROED_MAC = '00:00:00:00:00:00'
|
||||
ZEROED_MAC = "00:00:00:00:00:00"
|
||||
|
||||
|
||||
class WiredSetting:
|
||||
|
@ -32,26 +32,26 @@ def format_desired_current_state_diff(desired_state, current_state):
|
||||
pretty_desired_state = PrettyState(desired_state).yaml
|
||||
pretty_current_state = PrettyState(current_state).yaml
|
||||
|
||||
diff = ''.join(
|
||||
diff = "".join(
|
||||
difflib.unified_diff(
|
||||
pretty_desired_state.splitlines(True),
|
||||
pretty_current_state.splitlines(True),
|
||||
fromfile='desired',
|
||||
tofile='current',
|
||||
fromfile="desired",
|
||||
tofile="current",
|
||||
n=3,
|
||||
)
|
||||
)
|
||||
return (
|
||||
'\n'
|
||||
'desired\n'
|
||||
'=======\n'
|
||||
'{}\n'
|
||||
'current\n'
|
||||
'=======\n'
|
||||
'{}\n'
|
||||
'difference\n'
|
||||
'==========\n'
|
||||
'{}\n'.format(pretty_desired_state, pretty_current_state, diff)
|
||||
"\n"
|
||||
"desired\n"
|
||||
"=======\n"
|
||||
"{}\n"
|
||||
"current\n"
|
||||
"=======\n"
|
||||
"{}\n"
|
||||
"difference\n"
|
||||
"==========\n"
|
||||
"{}\n".format(pretty_desired_state, pretty_current_state, diff)
|
||||
)
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ class PrettyState:
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
return json.dumps(self.state, indent=4, separators=(',', ': '))
|
||||
return json.dumps(self.state, indent=4, separators=(",", ": "))
|
||||
|
||||
|
||||
def represent_ordereddict(dumper, data):
|
||||
@ -85,7 +85,7 @@ def represent_ordereddict(dumper, data):
|
||||
|
||||
value.append((node_key, node_value))
|
||||
|
||||
return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', value)
|
||||
return yaml.nodes.MappingNode(u"tag:yaml.org,2002:map", value)
|
||||
|
||||
|
||||
def order_state(state):
|
||||
@ -96,7 +96,7 @@ def order_state(state):
|
||||
if iface_states is not None:
|
||||
state[Constants.INTERFACES] = [
|
||||
order_iface_state(iface_state)
|
||||
for iface_state in sorted(iface_states, key=itemgetter('name'))
|
||||
for iface_state in sorted(iface_states, key=itemgetter("name"))
|
||||
]
|
||||
|
||||
return state
|
||||
@ -112,14 +112,14 @@ def represent_unicode(_, data):
|
||||
"""
|
||||
|
||||
return yaml.ScalarNode(
|
||||
tag=u'tag:yaml.org,2002:str', value=data.encode('utf-8')
|
||||
tag=u"tag:yaml.org,2002:str", value=data.encode("utf-8")
|
||||
)
|
||||
|
||||
|
||||
def order_iface_state(iface_state):
|
||||
ordered_state = OrderedDict()
|
||||
|
||||
for setting in ('name', 'type', 'state'):
|
||||
for setting in ("name", "type", "state"):
|
||||
try:
|
||||
ordered_state[setting] = iface_state.pop(setting)
|
||||
except KeyError:
|
||||
|
@ -26,62 +26,62 @@ import yaml
|
||||
|
||||
def load(schema_name):
|
||||
return yaml.load(
|
||||
pkgutil.get_data('libnmstate', 'schemas/' + schema_name + '.yaml'),
|
||||
pkgutil.get_data("libnmstate", "schemas/" + schema_name + ".yaml"),
|
||||
Loader=yaml.SafeLoader,
|
||||
)
|
||||
|
||||
|
||||
ifaces_schema = load('operational-state')
|
||||
ifaces_schema = load("operational-state")
|
||||
|
||||
|
||||
class Interface:
|
||||
KEY = 'interfaces'
|
||||
KEY = "interfaces"
|
||||
|
||||
NAME = 'name'
|
||||
TYPE = 'type'
|
||||
STATE = 'state'
|
||||
DESCRIPTION = 'description'
|
||||
NAME = "name"
|
||||
TYPE = "type"
|
||||
STATE = "state"
|
||||
DESCRIPTION = "description"
|
||||
|
||||
IPV4 = 'ipv4'
|
||||
IPV6 = 'ipv6'
|
||||
IPV4 = "ipv4"
|
||||
IPV6 = "ipv6"
|
||||
|
||||
MAC = 'mac-address'
|
||||
MTU = 'mtu'
|
||||
MAC = "mac-address"
|
||||
MTU = "mtu"
|
||||
|
||||
|
||||
class Route:
|
||||
KEY = 'routes'
|
||||
KEY = "routes"
|
||||
|
||||
RUNNING = 'running'
|
||||
CONFIG = 'config'
|
||||
STATE = 'state'
|
||||
STATE_ABSENT = 'absent'
|
||||
TABLE_ID = 'table-id'
|
||||
DESTINATION = 'destination'
|
||||
NEXT_HOP_INTERFACE = 'next-hop-interface'
|
||||
NEXT_HOP_ADDRESS = 'next-hop-address'
|
||||
METRIC = 'metric'
|
||||
RUNNING = "running"
|
||||
CONFIG = "config"
|
||||
STATE = "state"
|
||||
STATE_ABSENT = "absent"
|
||||
TABLE_ID = "table-id"
|
||||
DESTINATION = "destination"
|
||||
NEXT_HOP_INTERFACE = "next-hop-interface"
|
||||
NEXT_HOP_ADDRESS = "next-hop-address"
|
||||
METRIC = "metric"
|
||||
USE_DEFAULT_METRIC = -1
|
||||
USE_DEFAULT_ROUTE_TABLE = 0
|
||||
|
||||
|
||||
class RouteRule:
|
||||
KEY = 'route-rules'
|
||||
CONFIG = 'config'
|
||||
IP_FROM = 'ip-from'
|
||||
IP_TO = 'ip-to'
|
||||
PRIORITY = 'priority'
|
||||
ROUTE_TABLE = 'route-table'
|
||||
KEY = "route-rules"
|
||||
CONFIG = "config"
|
||||
IP_FROM = "ip-from"
|
||||
IP_TO = "ip-to"
|
||||
PRIORITY = "priority"
|
||||
ROUTE_TABLE = "route-table"
|
||||
USE_DEFAULT_PRIORITY = -1
|
||||
USE_DEFAULT_ROUTE_TABLE = 0
|
||||
|
||||
|
||||
class DNS:
|
||||
KEY = 'dns-resolver'
|
||||
RUNNING = 'running'
|
||||
CONFIG = 'config'
|
||||
SERVER = 'server'
|
||||
SEARCH = 'search'
|
||||
KEY = "dns-resolver"
|
||||
RUNNING = "running"
|
||||
CONFIG = "config"
|
||||
SERVER = "server"
|
||||
SEARCH = "search"
|
||||
|
||||
|
||||
class Constants:
|
||||
@ -93,25 +93,25 @@ class Constants:
|
||||
class InterfaceState:
|
||||
KEY = Interface.STATE
|
||||
|
||||
DOWN = 'down'
|
||||
UP = 'up'
|
||||
ABSENT = 'absent'
|
||||
DOWN = "down"
|
||||
UP = "up"
|
||||
ABSENT = "absent"
|
||||
|
||||
|
||||
class InterfaceType:
|
||||
KEY = Interface.TYPE
|
||||
|
||||
BOND = 'bond'
|
||||
DUMMY = 'dummy'
|
||||
ETHERNET = 'ethernet'
|
||||
LINUX_BRIDGE = 'linux-bridge'
|
||||
OVS_BRIDGE = 'ovs-bridge'
|
||||
OVS_INTERFACE = 'ovs-interface'
|
||||
OVS_PORT = 'ovs-port'
|
||||
UNKNOWN = 'unknown'
|
||||
VLAN = 'vlan'
|
||||
VXLAN = 'vxlan'
|
||||
TEAM = 'team'
|
||||
BOND = "bond"
|
||||
DUMMY = "dummy"
|
||||
ETHERNET = "ethernet"
|
||||
LINUX_BRIDGE = "linux-bridge"
|
||||
OVS_BRIDGE = "ovs-bridge"
|
||||
OVS_INTERFACE = "ovs-interface"
|
||||
OVS_PORT = "ovs-port"
|
||||
UNKNOWN = "unknown"
|
||||
VLAN = "vlan"
|
||||
VXLAN = "vxlan"
|
||||
TEAM = "team"
|
||||
|
||||
VIRT_TYPES = (
|
||||
BOND,
|
||||
@ -127,14 +127,14 @@ class InterfaceType:
|
||||
|
||||
|
||||
class InterfaceIP:
|
||||
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'
|
||||
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):
|
||||
@ -142,47 +142,47 @@ class InterfaceIPv4(InterfaceIP):
|
||||
|
||||
|
||||
class InterfaceIPv6(InterfaceIP):
|
||||
AUTOCONF = 'autoconf'
|
||||
AUTOCONF = "autoconf"
|
||||
|
||||
|
||||
class Bond:
|
||||
KEY = InterfaceType.BOND
|
||||
CONFIG_SUBTREE = 'link-aggregation'
|
||||
CONFIG_SUBTREE = "link-aggregation"
|
||||
|
||||
MODE = 'mode'
|
||||
SLAVES = 'slaves'
|
||||
OPTIONS_SUBTREE = 'options'
|
||||
MODE = "mode"
|
||||
SLAVES = "slaves"
|
||||
OPTIONS_SUBTREE = "options"
|
||||
|
||||
|
||||
class BondMode:
|
||||
ROUND_ROBIN = 'balance-rr'
|
||||
ACTIVE_BACKUP = 'active-backup'
|
||||
XOR = 'balance-xor'
|
||||
BROADCAST = 'broadcast'
|
||||
LACP = '802.3ad'
|
||||
TLB = 'balance-tlb'
|
||||
ALB = 'balance-alb'
|
||||
ROUND_ROBIN = "balance-rr"
|
||||
ACTIVE_BACKUP = "active-backup"
|
||||
XOR = "balance-xor"
|
||||
BROADCAST = "broadcast"
|
||||
LACP = "802.3ad"
|
||||
TLB = "balance-tlb"
|
||||
ALB = "balance-alb"
|
||||
|
||||
|
||||
_NEW_OVSBR_OPTS_MCAST_SNOOP = 'OVSBridge.Options.MCAST_SNOOPING_ENABLED'
|
||||
_NEW_OVSBR_OPTS_MCAST_SNOOP = "OVSBridge.Options.MCAST_SNOOPING_ENABLED"
|
||||
DEPRECATED_CONSTANTS = {
|
||||
'LinuxBridge.GROUP_FORWARD_MASK': 'LinuxBridge.Options.GROUP_FORWARD_MASK',
|
||||
'LinuxBridge.MAC_AGEING_TIME': 'LinuxBridge.Options.MAC_AGEING_TIME',
|
||||
'LinuxBridge.MULTICAST_SNOOPING': 'LinuxBridge.Options.MULTICAST_SNOOPING',
|
||||
'LinuxBridge.PORT_NAME': 'LinuxBridge.Port.NAME',
|
||||
'LinuxBridge.PORT_STP_HAIRPIN_MODE': 'LinuxBridge.Port.STP_HAIRPIN_MODE',
|
||||
'LinuxBridge.PORT_STP_PATH_COST': 'LinuxBridge.Port.STP_PATH_COST',
|
||||
'LinuxBridge.PORT_STP_PRIORITY': 'LinuxBridge.Port.STP_PRIORITY',
|
||||
'LinuxBridge.STP_ENABLED': 'LinuxBridge.STP.ENABLED',
|
||||
'LinuxBridge.STP_FORWARD_DELAY': 'LinuxBridge.STP.FORWARD_DELAY',
|
||||
'LinuxBridge.STP_HELLO_TIME': 'LinuxBridge.STP.HELLO_TIME',
|
||||
'LinuxBridge.STP_MAX_AGE': 'LinuxBridge.STP.MAX_AGE',
|
||||
'LinuxBridge.STP_PRIORITY': 'LinuxBridge.STP.PRIORITY',
|
||||
'OVSBridge.PORT_NAME': 'OVSBridge.Port.NAME',
|
||||
'OVSBridge.FAIL_MODE': 'OVSBridge.Options.FAIL_MODE',
|
||||
'OVSBridge.MCAST_SNOOPING_ENABLED': _NEW_OVSBR_OPTS_MCAST_SNOOP,
|
||||
'OVSBridge.RSTP': 'OVSBridge.Options.RSTP',
|
||||
'OVSBridge.STP': 'OVSBridge.Options.STP',
|
||||
"LinuxBridge.GROUP_FORWARD_MASK": "LinuxBridge.Options.GROUP_FORWARD_MASK",
|
||||
"LinuxBridge.MAC_AGEING_TIME": "LinuxBridge.Options.MAC_AGEING_TIME",
|
||||
"LinuxBridge.MULTICAST_SNOOPING": "LinuxBridge.Options.MULTICAST_SNOOPING",
|
||||
"LinuxBridge.PORT_NAME": "LinuxBridge.Port.NAME",
|
||||
"LinuxBridge.PORT_STP_HAIRPIN_MODE": "LinuxBridge.Port.STP_HAIRPIN_MODE",
|
||||
"LinuxBridge.PORT_STP_PATH_COST": "LinuxBridge.Port.STP_PATH_COST",
|
||||
"LinuxBridge.PORT_STP_PRIORITY": "LinuxBridge.Port.STP_PRIORITY",
|
||||
"LinuxBridge.STP_ENABLED": "LinuxBridge.STP.ENABLED",
|
||||
"LinuxBridge.STP_FORWARD_DELAY": "LinuxBridge.STP.FORWARD_DELAY",
|
||||
"LinuxBridge.STP_HELLO_TIME": "LinuxBridge.STP.HELLO_TIME",
|
||||
"LinuxBridge.STP_MAX_AGE": "LinuxBridge.STP.MAX_AGE",
|
||||
"LinuxBridge.STP_PRIORITY": "LinuxBridge.STP.PRIORITY",
|
||||
"OVSBridge.PORT_NAME": "OVSBridge.Port.NAME",
|
||||
"OVSBridge.FAIL_MODE": "OVSBridge.Options.FAIL_MODE",
|
||||
"OVSBridge.MCAST_SNOOPING_ENABLED": _NEW_OVSBR_OPTS_MCAST_SNOOP,
|
||||
"OVSBridge.RSTP": "OVSBridge.Options.RSTP",
|
||||
"OVSBridge.STP": "OVSBridge.Options.STP",
|
||||
}
|
||||
|
||||
|
||||
@ -195,7 +195,7 @@ class _DeprecatorType(type):
|
||||
deprecated_classname = deprecated_class.__name__
|
||||
deprecated_name = attribute
|
||||
|
||||
oldconstant = f'{deprecated_classname}.{deprecated_name}'
|
||||
oldconstant = f"{deprecated_classname}.{deprecated_name}"
|
||||
newconstant = DEPRECATED_CONSTANTS.get(oldconstant)
|
||||
|
||||
if newconstant:
|
||||
@ -206,7 +206,7 @@ class _DeprecatorType(type):
|
||||
stacklevel=3,
|
||||
)
|
||||
|
||||
attributes = newconstant.split('.')
|
||||
attributes = newconstant.split(".")
|
||||
new_classname = attributes.pop(0)
|
||||
new_value = globals()[new_classname]
|
||||
while attributes:
|
||||
@ -218,143 +218,143 @@ class _DeprecatorType(type):
|
||||
|
||||
|
||||
class LinuxBridge(metaclass=_DeprecatorType):
|
||||
TYPE = 'linux-bridge'
|
||||
CONFIG_SUBTREE = 'bridge'
|
||||
TYPE = "linux-bridge"
|
||||
CONFIG_SUBTREE = "bridge"
|
||||
|
||||
OPTIONS_SUBTREE = 'options'
|
||||
OPTIONS_SUBTREE = "options"
|
||||
|
||||
STP_SUBTREE = 'stp'
|
||||
STP_SUBTREE = "stp"
|
||||
|
||||
PORT_SUBTREE = 'port'
|
||||
PORT_SUBTREE = "port"
|
||||
|
||||
class Options:
|
||||
GROUP_FORWARD_MASK = 'group-forward-mask'
|
||||
MAC_AGEING_TIME = 'mac-ageing-time'
|
||||
MULTICAST_SNOOPING = 'multicast-snooping'
|
||||
GROUP_FORWARD_MASK = "group-forward-mask"
|
||||
MAC_AGEING_TIME = "mac-ageing-time"
|
||||
MULTICAST_SNOOPING = "multicast-snooping"
|
||||
|
||||
class Port:
|
||||
NAME = 'name'
|
||||
STP_HAIRPIN_MODE = 'stp-hairpin-mode'
|
||||
STP_PATH_COST = 'stp-path-cost'
|
||||
STP_PRIORITY = 'stp-priority'
|
||||
VLAN_SUBTREE = 'vlan'
|
||||
NAME = "name"
|
||||
STP_HAIRPIN_MODE = "stp-hairpin-mode"
|
||||
STP_PATH_COST = "stp-path-cost"
|
||||
STP_PRIORITY = "stp-priority"
|
||||
VLAN_SUBTREE = "vlan"
|
||||
|
||||
class Vlan:
|
||||
ENABLE_NATIVE = 'enable-native'
|
||||
MODE = 'mode'
|
||||
TAG = 'tag'
|
||||
TRUNK_TAGS = 'trunk-tags'
|
||||
ENABLE_NATIVE = "enable-native"
|
||||
MODE = "mode"
|
||||
TAG = "tag"
|
||||
TRUNK_TAGS = "trunk-tags"
|
||||
|
||||
class Mode:
|
||||
ACCESS = 'access'
|
||||
TRUNK = 'trunk'
|
||||
ACCESS = "access"
|
||||
TRUNK = "trunk"
|
||||
|
||||
class TrunkTags:
|
||||
ID = 'id'
|
||||
ID_RANGE = 'id-range'
|
||||
MIN_RANGE = 'min'
|
||||
MAX_RANGE = 'max'
|
||||
ID = "id"
|
||||
ID_RANGE = "id-range"
|
||||
MIN_RANGE = "min"
|
||||
MAX_RANGE = "max"
|
||||
|
||||
class STP:
|
||||
ENABLED = 'enabled'
|
||||
FORWARD_DELAY = 'forward-delay'
|
||||
HELLO_TIME = 'hello-time'
|
||||
MAX_AGE = 'max-age'
|
||||
PRIORITY = 'priority'
|
||||
ENABLED = "enabled"
|
||||
FORWARD_DELAY = "forward-delay"
|
||||
HELLO_TIME = "hello-time"
|
||||
MAX_AGE = "max-age"
|
||||
PRIORITY = "priority"
|
||||
|
||||
|
||||
class Ethernet:
|
||||
TYPE = InterfaceType.ETHERNET
|
||||
CONFIG_SUBTREE = 'ethernet'
|
||||
CONFIG_SUBTREE = "ethernet"
|
||||
|
||||
AUTO_NEGOTIATION = 'auto-negotiation'
|
||||
SPEED = 'speed'
|
||||
DUPLEX = 'duplex'
|
||||
AUTO_NEGOTIATION = "auto-negotiation"
|
||||
SPEED = "speed"
|
||||
DUPLEX = "duplex"
|
||||
|
||||
FULL_DUPLEX = 'full'
|
||||
HALF_DUPLEX = 'half'
|
||||
FULL_DUPLEX = "full"
|
||||
HALF_DUPLEX = "half"
|
||||
|
||||
SRIOV_SUBTREE = 'sr-iov'
|
||||
SRIOV_SUBTREE = "sr-iov"
|
||||
|
||||
class SRIOV:
|
||||
TOTAL_VFS = 'total-vfs'
|
||||
TOTAL_VFS = "total-vfs"
|
||||
|
||||
|
||||
class VLAN:
|
||||
TYPE = InterfaceType.VLAN
|
||||
CONFIG_SUBTREE = 'vlan'
|
||||
CONFIG_SUBTREE = "vlan"
|
||||
|
||||
ID = 'id'
|
||||
BASE_IFACE = 'base-iface'
|
||||
ID = "id"
|
||||
BASE_IFACE = "base-iface"
|
||||
|
||||
|
||||
class VXLAN:
|
||||
TYPE = InterfaceType.VXLAN
|
||||
CONFIG_SUBTREE = 'vxlan'
|
||||
CONFIG_SUBTREE = "vxlan"
|
||||
|
||||
ID = 'id'
|
||||
BASE_IFACE = 'base-iface'
|
||||
REMOTE = 'remote'
|
||||
DESTINATION_PORT = 'destination-port'
|
||||
ID = "id"
|
||||
BASE_IFACE = "base-iface"
|
||||
REMOTE = "remote"
|
||||
DESTINATION_PORT = "destination-port"
|
||||
|
||||
|
||||
class OVSBridge(metaclass=_DeprecatorType):
|
||||
TYPE = 'ovs-bridge'
|
||||
CONFIG_SUBTREE = 'bridge'
|
||||
TYPE = "ovs-bridge"
|
||||
CONFIG_SUBTREE = "bridge"
|
||||
|
||||
OPTIONS_SUBTREE = 'options'
|
||||
OPTIONS_SUBTREE = "options"
|
||||
|
||||
class Options:
|
||||
FAIL_MODE = 'fail-mode'
|
||||
MCAST_SNOOPING_ENABLED = 'mcast-snooping-enable'
|
||||
RSTP = 'rstp'
|
||||
STP = 'stp'
|
||||
FAIL_MODE = "fail-mode"
|
||||
MCAST_SNOOPING_ENABLED = "mcast-snooping-enable"
|
||||
RSTP = "rstp"
|
||||
STP = "stp"
|
||||
|
||||
PORT_SUBTREE = 'port'
|
||||
PORT_SUBTREE = "port"
|
||||
|
||||
class Port:
|
||||
NAME = 'name'
|
||||
NAME = "name"
|
||||
|
||||
VLAN_SUBTREE = 'vlan'
|
||||
VLAN_SUBTREE = "vlan"
|
||||
|
||||
class Vlan:
|
||||
TRUNK_TAGS = 'trunk-tags'
|
||||
TAG = 'tag'
|
||||
ENABLE_NATIVE = 'enable-native'
|
||||
MODE = 'mode'
|
||||
TRUNK_TAGS = "trunk-tags"
|
||||
TAG = "tag"
|
||||
ENABLE_NATIVE = "enable-native"
|
||||
MODE = "mode"
|
||||
|
||||
class Mode:
|
||||
ACCESS = 'access'
|
||||
TRUNK = 'trunk'
|
||||
ACCESS = "access"
|
||||
TRUNK = "trunk"
|
||||
|
||||
class TrunkTags:
|
||||
ID = 'id'
|
||||
ID_RANGE = 'id-range'
|
||||
MIN_RANGE = 'min'
|
||||
MAX_RANGE = 'max'
|
||||
ID = "id"
|
||||
ID_RANGE = "id-range"
|
||||
MIN_RANGE = "min"
|
||||
MAX_RANGE = "max"
|
||||
|
||||
LINK_AGGREGATION_SUBTREE = 'link-aggregation'
|
||||
LINK_AGGREGATION_SUBTREE = "link-aggregation"
|
||||
|
||||
class LinkAggregation:
|
||||
MODE = 'mode'
|
||||
SLAVES_SUBTREE = 'slaves'
|
||||
MODE = "mode"
|
||||
SLAVES_SUBTREE = "slaves"
|
||||
|
||||
class Slave:
|
||||
NAME = 'name'
|
||||
NAME = "name"
|
||||
|
||||
|
||||
class Team:
|
||||
TYPE = InterfaceType.TEAM
|
||||
CONFIG_SUBTREE = InterfaceType.TEAM
|
||||
|
||||
PORT_SUBTREE = 'ports'
|
||||
RUNNER_SUBTREE = 'runner'
|
||||
PORT_SUBTREE = "ports"
|
||||
RUNNER_SUBTREE = "runner"
|
||||
|
||||
class Port:
|
||||
NAME = 'name'
|
||||
NAME = "name"
|
||||
|
||||
class Runner:
|
||||
NAME = 'name'
|
||||
NAME = "name"
|
||||
|
||||
class RunnerMode:
|
||||
LOAD_BALANCE = 'loadbalance'
|
||||
LOAD_BALANCE = "loadbalance"
|
||||
|
@ -83,9 +83,9 @@ class StateEntry(metaclass=ABCMeta):
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
key.replace('_', '-'): value
|
||||
key.replace("_", "-"): value
|
||||
for key, value in vars(self).items()
|
||||
if (not key.startswith('_')) and (value is not None)
|
||||
if (not key.startswith("_")) and (value is not None)
|
||||
}
|
||||
|
||||
def match(self, other):
|
||||
@ -117,7 +117,7 @@ class RouteEntry(StateEntry):
|
||||
if self.metric is None:
|
||||
self.metric = Route.USE_DEFAULT_METRIC
|
||||
if self.next_hop_address is None:
|
||||
self.next_hop_address = ''
|
||||
self.next_hop_address = ""
|
||||
|
||||
def _keys(self):
|
||||
return (
|
||||
@ -131,12 +131,12 @@ class RouteEntry(StateEntry):
|
||||
def __lt__(self, other):
|
||||
return (
|
||||
self.table_id or Route.USE_DEFAULT_ROUTE_TABLE,
|
||||
self.next_hop_interface or '',
|
||||
self.destination or '',
|
||||
self.next_hop_interface or "",
|
||||
self.destination or "",
|
||||
) < (
|
||||
other.table_id or Route.USE_DEFAULT_ROUTE_TABLE,
|
||||
other.next_hop_interface or '',
|
||||
other.destination or '',
|
||||
other.next_hop_interface or "",
|
||||
other.destination or "",
|
||||
)
|
||||
|
||||
@property
|
||||
@ -154,9 +154,9 @@ class RouteRuleEntry(StateEntry):
|
||||
|
||||
def complement_defaults(self):
|
||||
if self.ip_from is None:
|
||||
self.ip_from = ''
|
||||
self.ip_from = ""
|
||||
if self.ip_to is None:
|
||||
self.ip_to = ''
|
||||
self.ip_to = ""
|
||||
if self.priority is None:
|
||||
self.priority = RouteRule.USE_DEFAULT_PRIORITY
|
||||
if (
|
||||
@ -171,7 +171,7 @@ class RouteRuleEntry(StateEntry):
|
||||
@property
|
||||
def absent(self):
|
||||
raise NmstateNotImplementedError(
|
||||
'RouteRuleEntry does not support absent property'
|
||||
"RouteRuleEntry does not support absent property"
|
||||
)
|
||||
|
||||
|
||||
@ -295,7 +295,7 @@ class State:
|
||||
If dynamic IP is disabled, all dynamic IP options should be removed.
|
||||
"""
|
||||
for iface_state in self.interfaces.values():
|
||||
for family in ('ipv4', 'ipv6'):
|
||||
for family in ("ipv4", "ipv6"):
|
||||
ip = iface_state[family]
|
||||
if ip.get(InterfaceIP.ENABLED) and (
|
||||
ip.get(InterfaceIP.DHCP) or ip.get(InterfaceIPv6.AUTOCONF)
|
||||
@ -501,7 +501,7 @@ class State:
|
||||
def _index_routes_by_iface(self):
|
||||
iface_routes = defaultdict(list)
|
||||
for route in self._config_routes:
|
||||
iface_name = route.get(Route.NEXT_HOP_INTERFACE, '')
|
||||
iface_name = route.get(Route.NEXT_HOP_INTERFACE, "")
|
||||
iface_routes[iface_name].append(RouteEntry(route))
|
||||
for routes in iface_routes.values():
|
||||
routes.sort()
|
||||
@ -538,12 +538,12 @@ class State:
|
||||
|
||||
def _sort_lag_slaves(self):
|
||||
for ifstate in self.interfaces.values():
|
||||
ifstate.get('link-aggregation', {}).get('slaves', []).sort()
|
||||
ifstate.get("link-aggregation", {}).get("slaves", []).sort()
|
||||
|
||||
def _sort_bridge_ports(self):
|
||||
for ifstate in self.interfaces.values():
|
||||
ifstate.get('bridge', {}).get('port', []).sort(
|
||||
key=itemgetter('name')
|
||||
ifstate.get("bridge", {}).get("port", []).sort(
|
||||
key=itemgetter("name")
|
||||
)
|
||||
|
||||
def _canonicalize_ipv6(self):
|
||||
@ -570,9 +570,9 @@ class State:
|
||||
|
||||
def _remove_iface_ipv6_link_local_addr(self):
|
||||
for ifstate in self.interfaces.values():
|
||||
ifstate['ipv6'][InterfaceIPv6.ADDRESS] = list(
|
||||
ifstate["ipv6"][InterfaceIPv6.ADDRESS] = list(
|
||||
addr
|
||||
for addr in ifstate['ipv6'][InterfaceIPv6.ADDRESS]
|
||||
for addr in ifstate["ipv6"][InterfaceIPv6.ADDRESS]
|
||||
if not iplib.is_ipv6_link_local_addr(
|
||||
addr[InterfaceIPv6.ADDRESS_IP],
|
||||
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH],
|
||||
@ -588,7 +588,7 @@ class State:
|
||||
|
||||
def _sort_ip_addresses(self):
|
||||
for ifstate in self.interfaces.values():
|
||||
for family in ('ipv4', 'ipv6'):
|
||||
for family in ("ipv4", "ipv6"):
|
||||
ifstate[family].get(InterfaceIP.ADDRESS, []).sort(
|
||||
key=itemgetter(InterfaceIP.ADDRESS_IP)
|
||||
)
|
||||
@ -601,7 +601,7 @@ class State:
|
||||
|
||||
def _remove_empty_description(self):
|
||||
for ifstate in self.interfaces.values():
|
||||
if ifstate.get(Interface.DESCRIPTION) == '':
|
||||
if ifstate.get(Interface.DESCRIPTION) == "":
|
||||
del ifstate[Interface.DESCRIPTION]
|
||||
|
||||
def _assert_interfaces_equal(self, current_state):
|
||||
@ -676,10 +676,10 @@ def _validate_routes(
|
||||
continue
|
||||
iface_enable_state = iface_enable_states.get(iface_name)
|
||||
if iface_enable_state is None:
|
||||
raise NmstateValueError('Cannot set route to non-exist interface')
|
||||
raise NmstateValueError("Cannot set route to non-exist interface")
|
||||
if iface_enable_state != InterfaceState.UP:
|
||||
raise NmstateValueError(
|
||||
'Cannot set route to {} interface'.format(iface_enable_state)
|
||||
"Cannot set route to {} interface".format(iface_enable_state)
|
||||
)
|
||||
# Interface is already check, so the ip enable status should be defined
|
||||
ipv4_enabled = ipv4_enable_states[iface_name]
|
||||
@ -688,11 +688,11 @@ def _validate_routes(
|
||||
if iplib.is_ipv6_address(route_obj.destination):
|
||||
if not ipv6_enabled:
|
||||
raise NmstateValueError(
|
||||
'Cannot set IPv6 route when IPv6 is disabled'
|
||||
"Cannot set IPv6 route when IPv6 is disabled"
|
||||
)
|
||||
elif not ipv4_enabled:
|
||||
raise NmstateValueError(
|
||||
'Cannot set IPv4 route when IPv4 is disabled'
|
||||
"Cannot set IPv4 route when IPv4 is disabled"
|
||||
)
|
||||
|
||||
|
||||
|
@ -36,8 +36,8 @@ def disable_ipv6(dev):
|
||||
|
||||
def _change_ipv6_state(dev, disable):
|
||||
try:
|
||||
with open('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % dev, 'w') as f:
|
||||
f.write('1' if disable else '0')
|
||||
with open("/proc/sys/net/ipv6/conf/%s/disable_ipv6" % dev, "w") as f:
|
||||
f.write("1" if disable else "0")
|
||||
except IOError as e:
|
||||
if e.errno == errno.ENOENT and disable:
|
||||
# IPv6 stack is (already) not available on this device
|
||||
@ -45,9 +45,9 @@ def _change_ipv6_state(dev, disable):
|
||||
raise ChangeIpv6StateError(str(e))
|
||||
|
||||
|
||||
def is_disabled_ipv6(dev='default'):
|
||||
def is_disabled_ipv6(dev="default"):
|
||||
try:
|
||||
with open('/proc/sys/net/ipv6/conf/%s/disable_ipv6' % dev) as f:
|
||||
with open("/proc/sys/net/ipv6/conf/%s/disable_ipv6" % dev) as f:
|
||||
return int(f.read())
|
||||
except IOError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
|
@ -61,7 +61,7 @@ def validate_capabilities(state, capabilities):
|
||||
|
||||
|
||||
def validate_interface_capabilities(ifaces_state, capabilities):
|
||||
ifaces_types = [iface_state.get('type') for iface_state in ifaces_state]
|
||||
ifaces_types = [iface_state.get("type") for iface_state in ifaces_state]
|
||||
has_ovs_capability = nm.ovs.CAPABILITY in capabilities
|
||||
for iface_type in ifaces_types:
|
||||
is_ovs_type = iface_type in (
|
||||
@ -84,16 +84,16 @@ def validate_link_aggregation_state(desired_state, current_state):
|
||||
available_ifaces = {
|
||||
ifname
|
||||
for ifname, ifstate in desired_state.interfaces.items()
|
||||
if ifstate.get('state') != 'absent'
|
||||
if ifstate.get("state") != "absent"
|
||||
}
|
||||
available_ifaces |= set(current_state.interfaces)
|
||||
|
||||
specified_slaves = set()
|
||||
for iface_state in desired_state.interfaces.values():
|
||||
if iface_state.get('state') != 'absent':
|
||||
link_aggregation = iface_state.get('link-aggregation')
|
||||
if iface_state.get("state") != "absent":
|
||||
link_aggregation = iface_state.get("link-aggregation")
|
||||
if link_aggregation:
|
||||
slaves = set(link_aggregation.get('slaves', []))
|
||||
slaves = set(link_aggregation.get("slaves", []))
|
||||
if not (slaves <= available_ifaces):
|
||||
raise NmstateValueError(
|
||||
"Link aggregation has missing slave: {}".format(
|
||||
@ -111,7 +111,7 @@ def validate_link_aggregation_state(desired_state, current_state):
|
||||
|
||||
def validate_dhcp(state):
|
||||
for iface_state in state[Constants.INTERFACES]:
|
||||
for family in ('ipv4', 'ipv6'):
|
||||
for family in ("ipv4", "ipv6"):
|
||||
ip = iface_state.get(family, {})
|
||||
if (
|
||||
ip.get(InterfaceIP.ENABLED)
|
||||
@ -121,7 +121,7 @@ def validate_dhcp(state):
|
||||
)
|
||||
):
|
||||
logging.warning(
|
||||
'%s addresses are ignored when ' 'dynamic IP is enabled',
|
||||
"%s addresses are ignored when " "dynamic IP is enabled",
|
||||
family,
|
||||
)
|
||||
|
||||
@ -136,7 +136,7 @@ def validate_dns(state):
|
||||
)
|
||||
if len(dns_servers) > 2:
|
||||
raise NmstateNotImplementedError(
|
||||
'Nmstate only support at most 2 DNS name servers'
|
||||
"Nmstate only support at most 2 DNS name servers"
|
||||
)
|
||||
|
||||
|
||||
@ -240,7 +240,7 @@ def _assert_vxlan_has_missing_attribute(state, *attributes):
|
||||
vxlan_config_set = set(vxlan_config)
|
||||
if not (attributes_set <= vxlan_config_set):
|
||||
raise NmstateValueError(
|
||||
'Vxlan tunnel {} has missing {}: {}'.format(
|
||||
"Vxlan tunnel {} has missing {}: {}".format(
|
||||
state[schema.Interface.NAME],
|
||||
attributes_set.difference(vxlan_config_set),
|
||||
state,
|
||||
@ -256,11 +256,11 @@ def _assert_vlan_filtering_trunk_tags(ports_state):
|
||||
|
||||
if vlan_mode == LB.Port.Vlan.Mode.ACCESS:
|
||||
if trunk_tags:
|
||||
raise NmstateValueError('Access port cannot have trunk tags')
|
||||
raise NmstateValueError("Access port cannot have trunk tags")
|
||||
elif port_vlan_state:
|
||||
if not trunk_tags:
|
||||
raise NmstateValueError(
|
||||
'A trunk port needs to specify trunk tags'
|
||||
"A trunk port needs to specify trunk tags"
|
||||
)
|
||||
for trunk_tag in trunk_tags:
|
||||
_assert_vlan_filtering_trunk_tag(trunk_tag)
|
||||
@ -272,7 +272,7 @@ def _assert_vlan_filtering_trunk_tag(trunk_tag_state):
|
||||
|
||||
if vlan_id and vlan_id_range:
|
||||
raise NmstateValueError(
|
||||
'Trunk port cannot be configured by both id and range: {}'.format(
|
||||
"Trunk port cannot be configured by both id and range: {}".format(
|
||||
trunk_tag_state
|
||||
)
|
||||
)
|
||||
@ -285,7 +285,7 @@ def _assert_vlan_filtering_trunk_tag(trunk_tag_state):
|
||||
<= set(vlan_id_range)
|
||||
):
|
||||
raise NmstateValueError(
|
||||
'Trunk port range requires min / max keys: {}'.format(
|
||||
"Trunk port range requires min / max keys: {}".format(
|
||||
vlan_id_range
|
||||
)
|
||||
)
|
||||
|
@ -39,7 +39,7 @@ from libnmstate.schema import Route
|
||||
|
||||
def main():
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
||||
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
|
||||
level=logging.DEBUG,
|
||||
)
|
||||
|
||||
@ -60,100 +60,100 @@ def main():
|
||||
|
||||
|
||||
def setup_subcommand_commit(subparsers):
|
||||
parser_commit = subparsers.add_parser('commit', help='Commit a change')
|
||||
parser_commit = subparsers.add_parser("commit", help="Commit a change")
|
||||
parser_commit.add_argument(
|
||||
'checkpoint', nargs='?', default=None, help='checkpoint to commit'
|
||||
"checkpoint", nargs="?", default=None, help="checkpoint to commit"
|
||||
)
|
||||
parser_commit.set_defaults(func=commit)
|
||||
|
||||
|
||||
def setup_subcommand_edit(subparsers):
|
||||
parser_edit = subparsers.add_parser(
|
||||
'edit', help='Edit network state in EDITOR'
|
||||
"edit", help="Edit network state in EDITOR"
|
||||
)
|
||||
parser_edit.set_defaults(func=edit)
|
||||
parser_edit.add_argument(
|
||||
'--json',
|
||||
help='Edit as JSON',
|
||||
"--json",
|
||||
help="Edit as JSON",
|
||||
default=True,
|
||||
action='store_false',
|
||||
dest='yaml',
|
||||
action="store_false",
|
||||
dest="yaml",
|
||||
)
|
||||
parser_edit.add_argument(
|
||||
'only',
|
||||
default='*',
|
||||
nargs='?',
|
||||
"only",
|
||||
default="*",
|
||||
nargs="?",
|
||||
metavar=Interface.KEY,
|
||||
help='Edit only specified interfaces (comma-separated)',
|
||||
help="Edit only specified interfaces (comma-separated)",
|
||||
)
|
||||
parser_edit.add_argument(
|
||||
'--no-verify',
|
||||
action='store_false',
|
||||
dest='verify',
|
||||
"--no-verify",
|
||||
action="store_false",
|
||||
dest="verify",
|
||||
default=True,
|
||||
help='Do not verify that the state was completely set and disable '
|
||||
'rollback to previous state.',
|
||||
help="Do not verify that the state was completely set and disable "
|
||||
"rollback to previous state.",
|
||||
)
|
||||
|
||||
|
||||
def setup_subcommand_rollback(subparsers):
|
||||
parser_rollback = subparsers.add_parser(
|
||||
'rollback', help='Rollback a change'
|
||||
"rollback", help="Rollback a change"
|
||||
)
|
||||
parser_rollback.add_argument(
|
||||
'checkpoint', nargs='?', default=None, help='checkpoint to roll back'
|
||||
"checkpoint", nargs="?", default=None, help="checkpoint to roll back"
|
||||
)
|
||||
parser_rollback.set_defaults(func=rollback)
|
||||
|
||||
|
||||
def setup_subcommand_set(subparsers):
|
||||
parser_set = subparsers.add_parser('set', help='Set network state')
|
||||
parser_set = subparsers.add_parser("set", help="Set network state")
|
||||
parser_set.add_argument(
|
||||
'file',
|
||||
help='File containing desired state. '
|
||||
'stdin is used when no file is specified.',
|
||||
nargs='*',
|
||||
"file",
|
||||
help="File containing desired state. "
|
||||
"stdin is used when no file is specified.",
|
||||
nargs="*",
|
||||
)
|
||||
parser_set.add_argument(
|
||||
'--no-verify',
|
||||
action='store_false',
|
||||
dest='verify',
|
||||
"--no-verify",
|
||||
action="store_false",
|
||||
dest="verify",
|
||||
default=True,
|
||||
help='Do not verify that the state was completely set and disable '
|
||||
'rollback to previous state',
|
||||
help="Do not verify that the state was completely set and disable "
|
||||
"rollback to previous state",
|
||||
)
|
||||
parser_set.add_argument(
|
||||
'--no-commit',
|
||||
action='store_false',
|
||||
dest='commit',
|
||||
"--no-commit",
|
||||
action="store_false",
|
||||
dest="commit",
|
||||
default=True,
|
||||
help='Do not commit new state after verification',
|
||||
help="Do not commit new state after verification",
|
||||
)
|
||||
parser_set.add_argument(
|
||||
'--timeout',
|
||||
"--timeout",
|
||||
type=int,
|
||||
default=60,
|
||||
help='Timeout in seconds before reverting uncommited changes.',
|
||||
help="Timeout in seconds before reverting uncommited changes.",
|
||||
)
|
||||
parser_set.set_defaults(func=apply)
|
||||
|
||||
|
||||
def setup_subcommand_show(subparsers):
|
||||
parser_show = subparsers.add_parser('show', help='Show network state')
|
||||
parser_show = subparsers.add_parser("show", help="Show network state")
|
||||
parser_show.set_defaults(func=show)
|
||||
parser_show.add_argument(
|
||||
'--json',
|
||||
help='Edit as JSON',
|
||||
"--json",
|
||||
help="Edit as JSON",
|
||||
default=True,
|
||||
action='store_false',
|
||||
dest='yaml',
|
||||
action="store_false",
|
||||
dest="yaml",
|
||||
)
|
||||
parser_show.add_argument(
|
||||
'only',
|
||||
default='*',
|
||||
nargs='?',
|
||||
"only",
|
||||
default="*",
|
||||
nargs="?",
|
||||
metavar=Interface.KEY,
|
||||
help='Show only specified interfaces (comma-separated)',
|
||||
help="Show only specified interfaces (comma-separated)",
|
||||
)
|
||||
|
||||
|
||||
@ -169,23 +169,23 @@ def edit(args):
|
||||
state = _filter_state(libnmstate.show(), args.only)
|
||||
|
||||
if not state[Interface.KEY]:
|
||||
sys.stderr.write('ERROR: No such interface\n')
|
||||
sys.stderr.write("ERROR: No such interface\n")
|
||||
return os.EX_USAGE
|
||||
|
||||
pretty_state = PrettyState(state)
|
||||
|
||||
if args.yaml:
|
||||
suffix = '.yaml'
|
||||
suffix = ".yaml"
|
||||
txtstate = pretty_state.yaml
|
||||
else:
|
||||
suffix = '.json'
|
||||
suffix = ".json"
|
||||
txtstate = pretty_state.json
|
||||
|
||||
new_state = _get_edited_state(txtstate, suffix, args.yaml)
|
||||
if not new_state:
|
||||
return os.EX_DATAERR
|
||||
|
||||
print('Applying the following state: ')
|
||||
print("Applying the following state: ")
|
||||
print_state(new_state, use_yaml=args.yaml)
|
||||
|
||||
libnmstate.apply(new_state, verify_change=args.verify)
|
||||
@ -207,7 +207,7 @@ def show(args):
|
||||
def apply(args):
|
||||
if args.file:
|
||||
for statefile in args.file:
|
||||
if statefile == '-' and not os.path.isfile(statefile):
|
||||
if statefile == "-" and not os.path.isfile(statefile):
|
||||
statedata = sys.stdin.read()
|
||||
else:
|
||||
with open(statefile) as statefile:
|
||||
@ -220,14 +220,14 @@ def apply(args):
|
||||
statedata = sys.stdin.read()
|
||||
return apply_state(statedata, args.verify, args.commit, args.timeout)
|
||||
else:
|
||||
sys.stderr.write('ERROR: No state specified\n')
|
||||
sys.stderr.write("ERROR: No state specified\n")
|
||||
return 1
|
||||
|
||||
|
||||
def apply_state(statedata, verify_change, commit, timeout):
|
||||
use_yaml = False
|
||||
# JSON dictionaries start with a curly brace
|
||||
if statedata[0] == '{':
|
||||
if statedata[0] == "{":
|
||||
state = json.loads(statedata)
|
||||
else:
|
||||
state = yaml.load(statedata, Loader=yaml.SafeLoader)
|
||||
@ -236,24 +236,24 @@ def apply_state(statedata, verify_change, commit, timeout):
|
||||
try:
|
||||
checkpoint = libnmstate.apply(state, verify_change, commit, timeout)
|
||||
except NmstatePermissionError as e:
|
||||
sys.stderr.write('ERROR: Missing permissions:{}\n'.format(str(e)))
|
||||
sys.stderr.write("ERROR: Missing permissions:{}\n".format(str(e)))
|
||||
return os.EX_NOPERM
|
||||
except NmstateConflictError:
|
||||
sys.stderr.write(
|
||||
'ERROR: State editing already in progress.\n'
|
||||
'Commit, roll back or wait before retrying.\n'
|
||||
"ERROR: State editing already in progress.\n"
|
||||
"Commit, roll back or wait before retrying.\n"
|
||||
)
|
||||
return os.EX_UNAVAILABLE
|
||||
|
||||
print('Desired state applied: ')
|
||||
print("Desired state applied: ")
|
||||
print_state(state, use_yaml=use_yaml)
|
||||
if checkpoint:
|
||||
print('Checkpoint: {}'.format(checkpoint))
|
||||
print("Checkpoint: {}".format(checkpoint))
|
||||
|
||||
|
||||
def _filter_state(state, whitelist):
|
||||
if whitelist != '*':
|
||||
patterns = [p for p in whitelist.split(',')]
|
||||
if whitelist != "*":
|
||||
patterns = [p for p in whitelist.split(",")]
|
||||
state[Interface.KEY] = _filter_interfaces(state, patterns)
|
||||
state[Route.KEY] = _filter_routes(state, patterns)
|
||||
return state
|
||||
@ -268,7 +268,7 @@ def _filter_interfaces(state, patterns):
|
||||
|
||||
for interface in state[Interface.KEY]:
|
||||
for pattern in patterns:
|
||||
if fnmatch.fnmatch(interface['name'], pattern):
|
||||
if fnmatch.fnmatch(interface["name"], pattern):
|
||||
showinterfaces.append(interface)
|
||||
break
|
||||
return showinterfaces
|
||||
@ -291,11 +291,11 @@ def _get_edited_state(txtstate, suffix, use_yaml):
|
||||
|
||||
|
||||
def _run_editor(txtstate, suffix):
|
||||
editor = os.environ.get('EDITOR', 'vi')
|
||||
editor = os.environ.get("EDITOR", "vi")
|
||||
with tempfile.NamedTemporaryFile(
|
||||
suffix=suffix, prefix='nmstate-'
|
||||
suffix=suffix, prefix="nmstate-"
|
||||
) as statefile:
|
||||
statefile.write(txtstate.encode('utf-8'))
|
||||
statefile.write(txtstate.encode("utf-8"))
|
||||
statefile.flush()
|
||||
|
||||
try:
|
||||
@ -304,25 +304,25 @@ def _run_editor(txtstate, suffix):
|
||||
return statefile.read()
|
||||
|
||||
except subprocess.CalledProcessError:
|
||||
sys.stderr.write('Error running editor, aborting...\n')
|
||||
sys.stderr.write("Error running editor, aborting...\n")
|
||||
return None
|
||||
|
||||
|
||||
def _parse_state(txtstate, parse_yaml):
|
||||
error = ''
|
||||
error = ""
|
||||
state = {}
|
||||
if parse_yaml:
|
||||
try:
|
||||
state = yaml.load(txtstate, Loader=yaml.SafeLoader)
|
||||
except yaml.parser.ParserError as e:
|
||||
error = 'Invalid YAML syntax: %s\n' % e
|
||||
error = "Invalid YAML syntax: %s\n" % e
|
||||
except yaml.parser.ScannerError as e:
|
||||
error = 'Invalid YAML syntax: %s\n' % e
|
||||
error = "Invalid YAML syntax: %s\n" % e
|
||||
else:
|
||||
try:
|
||||
state = json.loads(txtstate)
|
||||
except ValueError as e:
|
||||
error = 'Invalid JSON syntax: %s\n' % e
|
||||
error = "Invalid JSON syntax: %s\n" % e
|
||||
|
||||
if not error and Interface.KEY not in state:
|
||||
# Allow editing routes only.
|
||||
@ -337,16 +337,16 @@ def _try_edit_again(error):
|
||||
edited again and False otherwise.
|
||||
"""
|
||||
|
||||
sys.stderr.write('ERROR: ' + error)
|
||||
response = ''
|
||||
while response not in ('y', 'n'):
|
||||
sys.stderr.write("ERROR: " + error)
|
||||
response = ""
|
||||
while response not in ("y", "n"):
|
||||
response = input(
|
||||
'Try again? [y,n]:\n'
|
||||
'y - yes, start editor again\n'
|
||||
'n - no, throw away my changes\n'
|
||||
'> '
|
||||
"Try again? [y,n]:\n"
|
||||
"y - yes, start editor again\n"
|
||||
"n - no, throw away my changes\n"
|
||||
"> "
|
||||
).lower()
|
||||
if response == 'n':
|
||||
if response == "n":
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -1,3 +1,2 @@
|
||||
[tool.black]
|
||||
line-length = 79
|
||||
skip-string-normalization = true
|
||||
|
28
setup.py
28
setup.py
@ -3,52 +3,52 @@ from datetime import date
|
||||
|
||||
|
||||
def readme():
|
||||
with open('README.md') as f:
|
||||
with open("README.md") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def requirements():
|
||||
req = []
|
||||
with open('requirements.txt') as fd:
|
||||
with open("requirements.txt") as fd:
|
||||
for line in fd:
|
||||
line.strip()
|
||||
if not line.startswith('#'):
|
||||
if not line.startswith("#"):
|
||||
req.append(line)
|
||||
return req
|
||||
|
||||
|
||||
def get_version():
|
||||
with open('VERSION') as f:
|
||||
with open("VERSION") as f:
|
||||
version = f.read().strip()
|
||||
return version
|
||||
|
||||
|
||||
def gen_manpage():
|
||||
manpage = ""
|
||||
with open('doc/nmstatectl.8.in') as f:
|
||||
with open("doc/nmstatectl.8.in") as f:
|
||||
manpage = f.read()
|
||||
manpage = manpage.replace("@DATE@", date.today().strftime("%B %d, %Y"))
|
||||
manpage = manpage.replace("@VERSION@", get_version())
|
||||
with open('doc/nmstatectl.8', 'w') as f:
|
||||
with open("doc/nmstatectl.8", "w") as f:
|
||||
f.write(manpage)
|
||||
return [('share/man/man8', ['doc/nmstatectl.8'])]
|
||||
return [("share/man/man8", ["doc/nmstatectl.8"])]
|
||||
|
||||
|
||||
setup(
|
||||
name='nmstate',
|
||||
name="nmstate",
|
||||
version=get_version(),
|
||||
description='Declarative network manager API',
|
||||
description="Declarative network manager API",
|
||||
author="Edward Haas",
|
||||
author_email="ehaas@redhat.com",
|
||||
long_description=readme(),
|
||||
long_description_content_type='text/markdown',
|
||||
url='https://nmstate.github.io/',
|
||||
license='LGPL2.1+',
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://nmstate.github.io/",
|
||||
license="LGPL2.1+",
|
||||
packages=find_packages(),
|
||||
install_requires=requirements(),
|
||||
entry_points={
|
||||
'console_scripts': ['nmstatectl = nmstatectl.nmstatectl:main']
|
||||
"console_scripts": ["nmstatectl = nmstatectl.nmstatectl:main"]
|
||||
},
|
||||
package_data={'libnmstate': ['schemas/operational-state.yaml']},
|
||||
package_data={"libnmstate": ["schemas/operational-state.yaml"]},
|
||||
data_files=gen_manpage(),
|
||||
)
|
||||
|
@ -66,67 +66,67 @@ interfaces:
|
||||
"""
|
||||
|
||||
|
||||
@mock.patch('sys.argv', ['nmstatectl', 'set', 'mystate.json'])
|
||||
@mock.patch("sys.argv", ["nmstatectl", "set", "mystate.json"])
|
||||
@mock.patch.object(
|
||||
nmstatectl.libnmstate,
|
||||
'apply',
|
||||
"apply",
|
||||
lambda state, verify_change, commit, timeout: None,
|
||||
)
|
||||
@mock.patch.object(
|
||||
nmstatectl, 'open', mock.mock_open(read_data='{}'), create=True
|
||||
nmstatectl, "open", mock.mock_open(read_data="{}"), create=True
|
||||
)
|
||||
def test_run_ctl_directly_set():
|
||||
nmstatectl.main()
|
||||
|
||||
|
||||
@mock.patch('sys.argv', ['nmstatectl', 'show'])
|
||||
@mock.patch.object(nmstatectl.libnmstate, 'show', lambda: {})
|
||||
@mock.patch("sys.argv", ["nmstatectl", "show"])
|
||||
@mock.patch.object(nmstatectl.libnmstate, "show", lambda: {})
|
||||
def test_run_ctl_directly_show_empty():
|
||||
nmstatectl.main()
|
||||
|
||||
|
||||
@mock.patch('sys.argv', ['nmstatectl', 'show', 'non_existing_interface'])
|
||||
@mock.patch("sys.argv", ["nmstatectl", "show", "non_existing_interface"])
|
||||
@mock.patch.object(
|
||||
nmstatectl.libnmstate, 'show', lambda: json.loads(LO_JSON_STATE)
|
||||
nmstatectl.libnmstate, "show", lambda: json.loads(LO_JSON_STATE)
|
||||
)
|
||||
@mock.patch('nmstatectl.nmstatectl.sys.stdout', new_callable=io.StringIO)
|
||||
@mock.patch("nmstatectl.nmstatectl.sys.stdout", new_callable=io.StringIO)
|
||||
def test_run_ctl_directly_show_only_empty(mock_stdout):
|
||||
nmstatectl.main()
|
||||
assert mock_stdout.getvalue() == EMPTY_YAML_STATE
|
||||
|
||||
|
||||
@mock.patch('sys.argv', ['nmstatectl', 'show', 'lo'])
|
||||
@mock.patch("sys.argv", ["nmstatectl", "show", "lo"])
|
||||
@mock.patch.object(
|
||||
nmstatectl.libnmstate, 'show', lambda: json.loads(LO_JSON_STATE)
|
||||
nmstatectl.libnmstate, "show", lambda: json.loads(LO_JSON_STATE)
|
||||
)
|
||||
@mock.patch('nmstatectl.nmstatectl.sys.stdout', new_callable=io.StringIO)
|
||||
@mock.patch("nmstatectl.nmstatectl.sys.stdout", new_callable=io.StringIO)
|
||||
def test_run_ctl_directly_show_only(mock_stdout):
|
||||
nmstatectl.main()
|
||||
assert mock_stdout.getvalue() == LO_YAML_STATE
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'sys.argv', ['nmstatectl', 'show', '--json', 'non_existing_interface']
|
||||
"sys.argv", ["nmstatectl", "show", "--json", "non_existing_interface"]
|
||||
)
|
||||
@mock.patch.object(
|
||||
nmstatectl.libnmstate, 'show', lambda: json.loads(LO_JSON_STATE)
|
||||
nmstatectl.libnmstate, "show", lambda: json.loads(LO_JSON_STATE)
|
||||
)
|
||||
@mock.patch('nmstatectl.nmstatectl.sys.stdout', new_callable=io.StringIO)
|
||||
@mock.patch("nmstatectl.nmstatectl.sys.stdout", new_callable=io.StringIO)
|
||||
def test_run_ctl_directly_show_json_only_empty(mock_stdout):
|
||||
nmstatectl.main()
|
||||
assert mock_stdout.getvalue() == EMPTY_JSON_STATE
|
||||
|
||||
|
||||
@mock.patch('sys.argv', ['nmstatectl', 'show', '--json', 'lo'])
|
||||
@mock.patch("sys.argv", ["nmstatectl", "show", "--json", "lo"])
|
||||
@mock.patch.object(
|
||||
nmstatectl.libnmstate, 'show', lambda: json.loads(LO_JSON_STATE)
|
||||
nmstatectl.libnmstate, "show", lambda: json.loads(LO_JSON_STATE)
|
||||
)
|
||||
@mock.patch('nmstatectl.nmstatectl.sys.stdout', new_callable=io.StringIO)
|
||||
@mock.patch("nmstatectl.nmstatectl.sys.stdout", new_callable=io.StringIO)
|
||||
def test_run_ctl_directly_show_json_only(mock_stdout):
|
||||
nmstatectl.main()
|
||||
assert mock_stdout.getvalue() == LO_JSON_STATE
|
||||
|
||||
|
||||
def test_run_ctl_executable():
|
||||
rc = subprocess.call(['nmstatectl', '--help'])
|
||||
rc = subprocess.call(["nmstatectl", "--help"])
|
||||
assert rc == 0
|
||||
|
@ -41,10 +41,10 @@ from .testlib.bridgelib import linux_bridge
|
||||
from .testlib.bridgelib import add_port_to_bridge
|
||||
from .testlib.bridgelib import create_bridge_subtree_state
|
||||
|
||||
BOND99 = 'bond99'
|
||||
BOND99 = "bond99"
|
||||
|
||||
MAC0 = '02:ff:ff:ff:ff:00'
|
||||
MAC1 = '02:ff:ff:ff:ff:01'
|
||||
MAC0 = "02:ff:ff:ff:ff:00"
|
||||
MAC1 = "02:ff:ff:ff:ff:01"
|
||||
|
||||
BOND99_YAML_BASE = """
|
||||
interfaces:
|
||||
@ -65,7 +65,7 @@ def setup_remove_bond99():
|
||||
remove_bond = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'bond99',
|
||||
Interface.NAME: "bond99",
|
||||
Interface.TYPE: InterfaceType.BOND,
|
||||
Interface.STATE: InterfaceState.ABSENT,
|
||||
}
|
||||
@ -80,7 +80,7 @@ def bond99_with_2_slaves(eth1_up, eth2_up):
|
||||
eth1_up[Interface.KEY][0][Interface.NAME],
|
||||
eth2_up[Interface.KEY][0][Interface.NAME],
|
||||
]
|
||||
with bond_interface('bond99', slaves) as state:
|
||||
with bond_interface("bond99", slaves) as state:
|
||||
yield state
|
||||
|
||||
|
||||
@ -133,7 +133,7 @@ def test_remove_bond_with_minimum_desired_state(eth1_up, eth2_up):
|
||||
|
||||
|
||||
def test_add_bond_without_slaves():
|
||||
with bond_interface(name='bond99', slaves=[]) as state:
|
||||
with bond_interface(name="bond99", slaves=[]) as state:
|
||||
|
||||
assert state[Interface.KEY][0][Bond.CONFIG_SUBTREE][Bond.SLAVES] == []
|
||||
|
||||
@ -142,14 +142,14 @@ def test_add_bond_with_slaves_and_ipv4(eth1_up, eth2_up, setup_remove_bond99):
|
||||
desired_bond_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'bond99',
|
||||
Interface.NAME: "bond99",
|
||||
Interface.TYPE: InterfaceType.BOND,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.122.250',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.122.250",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -160,7 +160,7 @@ def test_add_bond_with_slaves_and_ipv4(eth1_up, eth2_up, setup_remove_bond99):
|
||||
eth1_up[Interface.KEY][0][Interface.NAME],
|
||||
eth2_up[Interface.KEY][0][Interface.NAME],
|
||||
],
|
||||
Bond.OPTIONS_SUBTREE: {'miimon': '140'},
|
||||
Bond.OPTIONS_SUBTREE: {"miimon": "140"},
|
||||
},
|
||||
}
|
||||
]
|
||||
@ -176,14 +176,14 @@ def test_rollback_for_bond(eth1_up, eth2_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'bond99',
|
||||
Interface.NAME: "bond99",
|
||||
Interface.TYPE: InterfaceType.BOND,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.122.250',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.122.250",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -194,13 +194,13 @@ def test_rollback_for_bond(eth1_up, eth2_up):
|
||||
eth1_up[Interface.KEY][0][Interface.NAME],
|
||||
eth2_up[Interface.KEY][0][Interface.NAME],
|
||||
],
|
||||
Bond.OPTIONS_SUBTREE: {'miimon': '140'},
|
||||
Bond.OPTIONS_SUBTREE: {"miimon": "140"},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
desired_state[Interface.KEY][0]['invalid_key'] = 'foo'
|
||||
desired_state[Interface.KEY][0]["invalid_key"] = "foo"
|
||||
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
libnmstate.apply(desired_state)
|
||||
@ -333,18 +333,18 @@ def test_bond_with_empty_ipv6_static_address(eth1_up):
|
||||
}
|
||||
}
|
||||
with bond_interface(
|
||||
name='bond99', slaves=['eth1'], extra_iface_state=extra_iface_state
|
||||
name="bond99", slaves=["eth1"], extra_iface_state=extra_iface_state
|
||||
) as bond_state:
|
||||
assertlib.assert_state(bond_state)
|
||||
|
||||
assertlib.assert_absent('bond99')
|
||||
assertlib.assert_absent("bond99")
|
||||
|
||||
|
||||
def test_create_vlan_over_a_bond_slave(bond99_with_slave):
|
||||
bond_ifstate = bond99_with_slave[Interface.KEY][0]
|
||||
bond_slave_ifname = bond_ifstate[Bond.CONFIG_SUBTREE][Bond.SLAVES][0]
|
||||
vlan_id = 102
|
||||
vlan_iface_name = '{}.{}'.format(bond_slave_ifname, vlan_id)
|
||||
vlan_iface_name = "{}.{}".format(bond_slave_ifname, vlan_id)
|
||||
with vlan_interface(
|
||||
vlan_iface_name, vlan_id, bond_slave_ifname
|
||||
) as desired_state:
|
||||
@ -354,11 +354,11 @@ def test_create_vlan_over_a_bond_slave(bond99_with_slave):
|
||||
|
||||
def test_create_linux_bridge_over_bond(bond99_with_slave):
|
||||
port_state = {
|
||||
'stp-hairpin-mode': False,
|
||||
'stp-path-cost': 100,
|
||||
'stp-priority': 32,
|
||||
"stp-hairpin-mode": False,
|
||||
"stp-path-cost": 100,
|
||||
"stp-priority": 32,
|
||||
}
|
||||
bridge_name = 'linux-br0'
|
||||
bridge_name = "linux-br0"
|
||||
bridge_state = add_port_to_bridge(
|
||||
create_bridge_subtree_state(), BOND99, port_state
|
||||
)
|
||||
@ -370,7 +370,7 @@ def test_create_linux_bridge_over_bond(bond99_with_slave):
|
||||
strict=True, reason="https://nmstate.atlassian.net/browse/NMSTATE-272"
|
||||
)
|
||||
def test_preserve_bond_after_bridge_removal(bond99_with_slave):
|
||||
bridge_name = 'linux-br0'
|
||||
bridge_name = "linux-br0"
|
||||
bridge_state = add_port_to_bridge(create_bridge_subtree_state(), BOND99)
|
||||
with linux_bridge(bridge_name, bridge_state) as desired_state:
|
||||
assertlib.assert_state_match(desired_state)
|
||||
@ -380,7 +380,7 @@ def test_preserve_bond_after_bridge_removal(bond99_with_slave):
|
||||
def test_create_vlan_over_a_bond(bond99_with_slave):
|
||||
vlan_base_iface = bond99_with_slave[Interface.KEY][0][Interface.NAME]
|
||||
vlan_id = 102
|
||||
vlan_iface_name = '{}.{}'.format(vlan_base_iface, vlan_id)
|
||||
vlan_iface_name = "{}.{}".format(vlan_base_iface, vlan_id)
|
||||
with vlan_interface(
|
||||
vlan_iface_name, vlan_id, vlan_base_iface
|
||||
) as desired_state:
|
||||
|
@ -33,29 +33,29 @@ OS: {osname}
|
||||
"""
|
||||
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def logging_setup():
|
||||
logging.basicConfig(
|
||||
format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
||||
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
|
||||
level=logging.DEBUG,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def ethx_init(diff_initial_state):
|
||||
""" Remove any existing definitions on the ethX interfaces. """
|
||||
ifacelib.ifaces_init('eth1', 'eth2')
|
||||
ifacelib.ifaces_init("eth1", "eth2")
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def eth1_up():
|
||||
with ifacelib.iface_up('eth1') as ifstate:
|
||||
with ifacelib.iface_up("eth1") as ifstate:
|
||||
yield ifstate
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def eth2_up():
|
||||
with ifacelib.iface_up('eth2') as ifstate:
|
||||
with ifacelib.iface_up("eth2") as ifstate:
|
||||
yield ifstate
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ port0_up = eth1_up
|
||||
port1_up = eth2_up
|
||||
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def diff_initial_state():
|
||||
old_state = libnmstate.show()
|
||||
yield
|
||||
@ -71,8 +71,8 @@ def diff_initial_state():
|
||||
|
||||
if old_state != new_state:
|
||||
warnings.warn(
|
||||
'Network state after test run does not match network state '
|
||||
'before test run:\n {}\n'.format(
|
||||
"Network state after test run does not match network state "
|
||||
"before test run:\n {}\n".format(
|
||||
libnmstate.prettystate.format_desired_current_state_diff(
|
||||
old_state, new_state
|
||||
)
|
||||
@ -82,19 +82,19 @@ def diff_initial_state():
|
||||
|
||||
def pytest_report_header(config):
|
||||
return REPORT_HEADER.format(
|
||||
rpms=_get_package_nvr('NetworkManager'), osname=_get_osname()
|
||||
rpms=_get_package_nvr("NetworkManager"), osname=_get_osname()
|
||||
)
|
||||
|
||||
|
||||
def _get_package_nvr(package):
|
||||
return (
|
||||
subprocess.check_output(['rpm', '-q', package]).strip().decode('utf-8')
|
||||
subprocess.check_output(["rpm", "-q", package]).strip().decode("utf-8")
|
||||
)
|
||||
|
||||
|
||||
def _get_osname():
|
||||
with open('/etc/os-release') as os_release:
|
||||
with open("/etc/os-release") as os_release:
|
||||
for line in os_release.readlines():
|
||||
if line.startswith('PRETTY_NAME='):
|
||||
return line.split('=', maxsplit=1)[1].strip().strip('"')
|
||||
return ''
|
||||
if line.startswith("PRETTY_NAME="):
|
||||
return line.split("=", maxsplit=1)[1].strip().strip('"')
|
||||
return ""
|
||||
|
@ -31,21 +31,21 @@ from libnmstate.schema import InterfaceType
|
||||
from libnmstate.schema import Route
|
||||
|
||||
|
||||
IPV4_DNS_NAMESERVERS = ['8.8.8.8', '1.1.1.1']
|
||||
IPV6_DNS_NAMESERVERS = ['2001:4860:4860::8888', '2606:4700:4700::1111']
|
||||
EXAMPLE_SEARCHES = ['example.org', 'example.com']
|
||||
IPV4_DNS_NAMESERVERS = ["8.8.8.8", "1.1.1.1"]
|
||||
IPV6_DNS_NAMESERVERS = ["2001:4860:4860::8888", "2606:4700:4700::1111"]
|
||||
EXAMPLE_SEARCHES = ["example.org", "example.com"]
|
||||
|
||||
parametrize_ip_ver = pytest.mark.parametrize(
|
||||
'dns_config',
|
||||
"dns_config",
|
||||
[
|
||||
({DNS.SERVER: IPV4_DNS_NAMESERVERS, DNS.SEARCH: EXAMPLE_SEARCHES}),
|
||||
({DNS.SERVER: IPV6_DNS_NAMESERVERS, DNS.SEARCH: EXAMPLE_SEARCHES}),
|
||||
],
|
||||
ids=['ipv4', 'ipv6'],
|
||||
ids=["ipv4", "ipv6"],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function', autouse=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def dns_test_env(eth1_up, eth2_up):
|
||||
yield
|
||||
# Remove DNS config as it be saved in eth1 or eth2 which might trigger
|
||||
@ -101,7 +101,7 @@ def test_dns_edit_ipv6_nameserver_before_ipv4():
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
reason='https://nmstate.atlassian.net/browse/NMSTATE-220',
|
||||
reason="https://nmstate.atlassian.net/browse/NMSTATE-220",
|
||||
strict=True,
|
||||
)
|
||||
def test_dns_edit_three_nameservers():
|
||||
@ -158,11 +158,11 @@ def test_preserve_dns_config():
|
||||
Route.KEY: {
|
||||
Route.CONFIG: [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.STATE: Route.STATE_ABSENT,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.STATE: Route.STATE_ABSENT,
|
||||
},
|
||||
]
|
||||
@ -203,13 +203,13 @@ def test_preserve_dns_config_with_empty_state(setup_ipv4_ipv6_name_server):
|
||||
def _get_test_iface_states():
|
||||
return [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.0.2.251',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.0.2.251",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -219,7 +219,7 @@ def _get_test_iface_states():
|
||||
Interface.IPV6: {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001:db8:1::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001:db8:1::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
}
|
||||
],
|
||||
@ -229,13 +229,13 @@ def _get_test_iface_states():
|
||||
},
|
||||
},
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '198.51.100.1',
|
||||
InterfaceIPv4.ADDRESS_IP: "198.51.100.1",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -245,7 +245,7 @@ def _get_test_iface_states():
|
||||
Interface.IPV6: {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001:db8:2::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001:db8:2::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
}
|
||||
],
|
||||
@ -260,15 +260,15 @@ def _get_test_iface_states():
|
||||
def _gen_default_gateway_route():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 200,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 201,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:2::f',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:2::f",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
},
|
||||
]
|
||||
|
@ -47,28 +47,28 @@ from .testlib.bridgelib import linux_bridge
|
||||
|
||||
DEFAULT_TIMEOUT = 20
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV4_ADDRESS2 = '192.0.2.252'
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV6_ADDRESS2 = '2001:db8:2::1'
|
||||
IPV4_CLASSLESS_ROUTE_DST_NET1 = '198.51.100.0/24'
|
||||
IPV4_CLASSLESS_ROUTE_NEXT_HOP1 = '192.0.2.1'
|
||||
IPV6_CLASSLESS_ROUTE_PREFIX = '2001:db8:f'
|
||||
IPV6_CLASSLESS_ROUTE_DST_NET1 = '{}::/64'.format(IPV6_CLASSLESS_ROUTE_PREFIX)
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
IPV4_ADDRESS2 = "192.0.2.252"
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
IPV6_ADDRESS2 = "2001:db8:2::1"
|
||||
IPV4_CLASSLESS_ROUTE_DST_NET1 = "198.51.100.0/24"
|
||||
IPV4_CLASSLESS_ROUTE_NEXT_HOP1 = "192.0.2.1"
|
||||
IPV6_CLASSLESS_ROUTE_PREFIX = "2001:db8:f"
|
||||
IPV6_CLASSLESS_ROUTE_DST_NET1 = "{}::/64".format(IPV6_CLASSLESS_ROUTE_PREFIX)
|
||||
|
||||
TEST_BRIDGE_NIC = 'brtest0'
|
||||
TEST_BRIDGE_NIC = "brtest0"
|
||||
|
||||
DHCP_SRV_NIC = 'dhcpsrv'
|
||||
DHCP_CLI_NIC = 'dhcpcli'
|
||||
DHCP_SRV_NIC = "dhcpsrv"
|
||||
DHCP_CLI_NIC = "dhcpcli"
|
||||
DHCP_SRV_IP4 = IPV4_ADDRESS1
|
||||
DHCP_SRV_IP6 = IPV6_ADDRESS1
|
||||
DHCP_SRV_IP6_2 = "{}::1".format(IPV6_CLASSLESS_ROUTE_PREFIX)
|
||||
DHCP_SRV_IP4_PREFIX = '192.0.2'
|
||||
DHCP_SRV_IP6_PREFIX = '2001:db8:1'
|
||||
DHCP_SRV_IP6_NETWORK = '{}::/64'.format(DHCP_SRV_IP6_PREFIX)
|
||||
DHCP_SRV_IP4_PREFIX = "192.0.2"
|
||||
DHCP_SRV_IP6_PREFIX = "2001:db8:1"
|
||||
DHCP_SRV_IP6_NETWORK = "{}::/64".format(DHCP_SRV_IP6_PREFIX)
|
||||
|
||||
IPV6_DEFAULT_GATEWAY = '::/0'
|
||||
IPV4_DEFAULT_GATEWAY = '0.0.0.0/0'
|
||||
IPV6_DEFAULT_GATEWAY = "::/0"
|
||||
IPV4_DEFAULT_GATEWAY = "0.0.0.0/0"
|
||||
|
||||
DNSMASQ_CONF_STR = """
|
||||
interface={iface}
|
||||
@ -80,25 +80,25 @@ dhcp-option=option:classless-static-route,{classless_rt},{classless_rt_dst}
|
||||
dhcp-option=option:dns-server,{v4_dns_server}
|
||||
""".format(
|
||||
**{
|
||||
'iface': DHCP_SRV_NIC,
|
||||
'ipv4_prefix': DHCP_SRV_IP4_PREFIX,
|
||||
'ipv6_prefix': DHCP_SRV_IP6_PREFIX,
|
||||
'classless_rt': IPV4_CLASSLESS_ROUTE_DST_NET1,
|
||||
'classless_rt_dst': IPV4_CLASSLESS_ROUTE_NEXT_HOP1,
|
||||
'v4_dns_server': DHCP_SRV_IP4,
|
||||
'ipv6_classless_route': IPV6_CLASSLESS_ROUTE_PREFIX,
|
||||
"iface": DHCP_SRV_NIC,
|
||||
"ipv4_prefix": DHCP_SRV_IP4_PREFIX,
|
||||
"ipv6_prefix": DHCP_SRV_IP6_PREFIX,
|
||||
"classless_rt": IPV4_CLASSLESS_ROUTE_DST_NET1,
|
||||
"classless_rt_dst": IPV4_CLASSLESS_ROUTE_NEXT_HOP1,
|
||||
"v4_dns_server": DHCP_SRV_IP4,
|
||||
"ipv6_classless_route": IPV6_CLASSLESS_ROUTE_PREFIX,
|
||||
}
|
||||
)
|
||||
|
||||
DNSMASQ_CONF_PATH = '/etc/dnsmasq.d/nmstate.conf'
|
||||
DNSMASQ_CONF_PATH = "/etc/dnsmasq.d/nmstate.conf"
|
||||
# Docker does not allow NetworkManager to edit /etc/resolv.conf.
|
||||
# Have to read NetworkManager internal resolv.conf
|
||||
RESOLV_CONF_PATH = '/var/run/NetworkManager/resolv.conf'
|
||||
RESOLV_CONF_PATH = "/var/run/NetworkManager/resolv.conf"
|
||||
|
||||
SYSFS_DISABLE_IPV6_FILE = '/proc/sys/net/ipv6/conf/{}/disable_ipv6'.format(
|
||||
SYSFS_DISABLE_IPV6_FILE = "/proc/sys/net/ipv6/conf/{}/disable_ipv6".format(
|
||||
DHCP_SRV_NIC
|
||||
)
|
||||
SYSFS_DISABLE_RA_SRV = '/proc/sys/net/ipv6/conf/{}/accept_ra'.format(
|
||||
SYSFS_DISABLE_RA_SRV = "/proc/sys/net/ipv6/conf/{}/accept_ra".format(
|
||||
DHCP_SRV_NIC
|
||||
)
|
||||
|
||||
@ -109,15 +109,15 @@ except NameError:
|
||||
FileNotFoundError = IOError
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
@pytest.fixture(scope="module")
|
||||
def dhcp_env():
|
||||
try:
|
||||
_create_veth_pair()
|
||||
_setup_dhcp_nics()
|
||||
|
||||
with open(DNSMASQ_CONF_PATH, 'w') as fd:
|
||||
with open(DNSMASQ_CONF_PATH, "w") as fd:
|
||||
fd.write(DNSMASQ_CONF_STR)
|
||||
assert libcmd.exec_cmd(['systemctl', 'restart', 'dnsmasq'])[0] == 0
|
||||
assert libcmd.exec_cmd(["systemctl", "restart", "dnsmasq"])[0] == 0
|
||||
|
||||
yield
|
||||
finally:
|
||||
@ -251,7 +251,7 @@ def test_dhcp_with_addresses(dhcpcli_up):
|
||||
def test_ipv4_dhcp_on_bond(dhcpcli_up):
|
||||
ipv4_state = {Interface.IPV4: create_ipv4_state(enabled=True, dhcp=True)}
|
||||
with bondlib.bond_interface(
|
||||
'bond99', slaves=[DHCP_CLI_NIC], extra_iface_state=ipv4_state
|
||||
"bond99", slaves=[DHCP_CLI_NIC], extra_iface_state=ipv4_state
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
@ -574,14 +574,14 @@ def _create_veth_pair():
|
||||
assert (
|
||||
libcmd.exec_cmd(
|
||||
[
|
||||
'ip',
|
||||
'link',
|
||||
'add',
|
||||
"ip",
|
||||
"link",
|
||||
"add",
|
||||
DHCP_SRV_NIC,
|
||||
'type',
|
||||
'veth',
|
||||
'peer',
|
||||
'name',
|
||||
"type",
|
||||
"veth",
|
||||
"peer",
|
||||
"name",
|
||||
DHCP_CLI_NIC,
|
||||
]
|
||||
)[0]
|
||||
@ -590,20 +590,20 @@ def _create_veth_pair():
|
||||
|
||||
|
||||
def _remove_veth_pair():
|
||||
libcmd.exec_cmd(['ip', 'link', 'del', 'dev', DHCP_SRV_NIC])
|
||||
libcmd.exec_cmd(["ip", "link", "del", "dev", DHCP_SRV_NIC])
|
||||
|
||||
|
||||
def _setup_dhcp_nics():
|
||||
assert libcmd.exec_cmd(['ip', 'link', 'set', DHCP_SRV_NIC, 'up'])[0] == 0
|
||||
assert libcmd.exec_cmd(['ip', 'link', 'set', DHCP_CLI_NIC, 'up'])[0] == 0
|
||||
assert libcmd.exec_cmd(["ip", "link", "set", DHCP_SRV_NIC, "up"])[0] == 0
|
||||
assert libcmd.exec_cmd(["ip", "link", "set", DHCP_CLI_NIC, "up"])[0] == 0
|
||||
assert (
|
||||
libcmd.exec_cmd(
|
||||
[
|
||||
'ip',
|
||||
'addr',
|
||||
'add',
|
||||
"ip",
|
||||
"addr",
|
||||
"add",
|
||||
"{}/24".format(DHCP_SRV_IP4),
|
||||
'dev',
|
||||
"dev",
|
||||
DHCP_SRV_NIC,
|
||||
]
|
||||
)[0]
|
||||
@ -611,25 +611,25 @@ def _setup_dhcp_nics():
|
||||
)
|
||||
assert (
|
||||
libcmd.exec_cmd(
|
||||
['nmcli', 'device', 'set', DHCP_CLI_NIC, 'managed', 'yes']
|
||||
["nmcli", "device", "set", DHCP_CLI_NIC, "managed", "yes"]
|
||||
)[0]
|
||||
== 0
|
||||
)
|
||||
# This stop dhcp server NIC get another IPv6 address from dnsmasq.
|
||||
with open(SYSFS_DISABLE_RA_SRV, 'w') as fd:
|
||||
fd.write('0')
|
||||
with open(SYSFS_DISABLE_RA_SRV, "w") as fd:
|
||||
fd.write("0")
|
||||
|
||||
with open(SYSFS_DISABLE_IPV6_FILE, 'w') as fd:
|
||||
fd.write('0')
|
||||
with open(SYSFS_DISABLE_IPV6_FILE, "w") as fd:
|
||||
fd.write("0")
|
||||
|
||||
assert (
|
||||
libcmd.exec_cmd(
|
||||
[
|
||||
'ip',
|
||||
'addr',
|
||||
'add',
|
||||
"ip",
|
||||
"addr",
|
||||
"add",
|
||||
"{}/64".format(DHCP_SRV_IP6),
|
||||
'dev',
|
||||
"dev",
|
||||
DHCP_SRV_NIC,
|
||||
]
|
||||
)[0]
|
||||
@ -639,11 +639,11 @@ def _setup_dhcp_nics():
|
||||
assert (
|
||||
libcmd.exec_cmd(
|
||||
[
|
||||
'ip',
|
||||
'addr',
|
||||
'add',
|
||||
"ip",
|
||||
"addr",
|
||||
"add",
|
||||
"{}/64".format(DHCP_SRV_IP6_2),
|
||||
'dev',
|
||||
"dev",
|
||||
DHCP_SRV_NIC,
|
||||
]
|
||||
)[0]
|
||||
@ -652,7 +652,7 @@ def _setup_dhcp_nics():
|
||||
|
||||
|
||||
def _clean_up():
|
||||
libcmd.exec_cmd(['systemctl', 'stop', 'dnsmasq'])
|
||||
libcmd.exec_cmd(["systemctl", "stop", "dnsmasq"])
|
||||
_remove_veth_pair()
|
||||
try:
|
||||
os.unlink(DNSMASQ_CONF_PATH)
|
||||
@ -754,7 +754,7 @@ def _has_dhcpv6_addr(nic=DHCP_CLI_NIC):
|
||||
current_state = statelib.show_only((nic,))[Interface.KEY][0]
|
||||
has_dhcp_ip_addr = False
|
||||
addrs = current_state[Interface.IPV6].get(InterfaceIPv6.ADDRESS, [])
|
||||
logging.debug('Current IPv6 address of {}: {}'.format(nic, addrs))
|
||||
logging.debug("Current IPv6 address of {}: {}".format(nic, addrs))
|
||||
for addr in addrs:
|
||||
if (
|
||||
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH] == 128
|
||||
@ -769,7 +769,7 @@ def _has_dhcpv4_addr(nic=DHCP_CLI_NIC):
|
||||
current_state = statelib.show_only((nic,))[Interface.KEY][0]
|
||||
has_dhcp_ip_addr = False
|
||||
addrs = current_state[Interface.IPV4].get(InterfaceIPv4.ADDRESS, [])
|
||||
logging.debug('Current IPv4 address of {}: {}'.format(nic, addrs))
|
||||
logging.debug("Current IPv4 address of {}: {}".format(nic, addrs))
|
||||
for addr in addrs:
|
||||
if (
|
||||
addr[InterfaceIPv6.ADDRESS_PREFIX_LENGTH] == 24
|
||||
@ -826,7 +826,7 @@ def create_ipv6_address_state(address, prefix_length):
|
||||
|
||||
def test_activate_dummy_without_dhcp_service():
|
||||
ifstate = {
|
||||
Interface.NAME: 'dummy00',
|
||||
Interface.NAME: "dummy00",
|
||||
Interface.TYPE: InterfaceType.DUMMY,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: create_ipv4_state(enabled=True, dhcp=True),
|
||||
|
@ -33,7 +33,7 @@ from .testlib.iproutelib import ip_monitor_assert_stable_link_up
|
||||
from .testlib.vlan import vlan_interface
|
||||
|
||||
|
||||
@pytest.fixture(scope='function', autouse=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def eth1(eth1_up):
|
||||
pass
|
||||
|
||||
@ -46,7 +46,7 @@ def eth1_with_ipv6(eth1_up):
|
||||
|
||||
|
||||
def test_increase_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 1900
|
||||
|
||||
@ -56,7 +56,7 @@ def test_increase_iface_mtu():
|
||||
|
||||
|
||||
def test_decrease_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 1400
|
||||
|
||||
@ -66,7 +66,7 @@ def test_decrease_iface_mtu():
|
||||
|
||||
|
||||
def test_upper_limit_jambo_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 9000
|
||||
|
||||
@ -76,7 +76,7 @@ def test_upper_limit_jambo_iface_mtu():
|
||||
|
||||
|
||||
def test_increase_more_than_jambo_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 10000
|
||||
|
||||
@ -86,33 +86,33 @@ def test_increase_more_than_jambo_iface_mtu():
|
||||
|
||||
|
||||
def test_decrease_to_zero_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
origin_desired_state = copy.deepcopy(desired_state)
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 0
|
||||
|
||||
with pytest.raises(NmstateVerificationError) as err:
|
||||
libnmstate.apply(desired_state)
|
||||
assert '-mtu: 0' in err.value.args[0]
|
||||
assert "-mtu: 0" in err.value.args[0]
|
||||
# FIXME: Drop the sleep when the waiting logic is implemented.
|
||||
time.sleep(2)
|
||||
assertlib.assert_state(origin_desired_state)
|
||||
|
||||
|
||||
def test_decrease_to_negative_iface_mtu():
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
origin_desired_state = copy.deepcopy(desired_state)
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = -1
|
||||
|
||||
with pytest.raises(js.ValidationError) as err:
|
||||
libnmstate.apply(desired_state)
|
||||
assert '-1' in err.value.args[0]
|
||||
assert "-1" in err.value.args[0]
|
||||
assertlib.assert_state(origin_desired_state)
|
||||
|
||||
|
||||
def test_decrease_to_ipv6_min_ethernet_frame_size_iface_mtu(eth1_with_ipv6):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 1280
|
||||
|
||||
@ -122,24 +122,24 @@ def test_decrease_to_ipv6_min_ethernet_frame_size_iface_mtu(eth1_with_ipv6):
|
||||
|
||||
|
||||
def test_decrease_to_lower_than_min_ipv6_iface_mtu(eth1_with_ipv6):
|
||||
original_state = statelib.show_only(('eth1',))
|
||||
original_state = statelib.show_only(("eth1",))
|
||||
desired_state = copy.deepcopy(original_state)
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 1279
|
||||
|
||||
with pytest.raises(NmstateVerificationError) as err:
|
||||
libnmstate.apply(desired_state)
|
||||
assert '1279' in err.value.args[0]
|
||||
assert "1279" in err.value.args[0]
|
||||
# FIXME: Drop the sleep when the waiting logic is implemented.
|
||||
time.sleep(2)
|
||||
assertlib.assert_state(original_state)
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='https://bugzilla.redhat.com/1751079', strict=True)
|
||||
@pytest.mark.xfail(reason="https://bugzilla.redhat.com/1751079", strict=True)
|
||||
def test_set_mtu_on_two_vlans_with_a_shared_base(eth1_up):
|
||||
base_ifname = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
v101 = vlan_interface('eth1.101', 101, base_ifname)
|
||||
v102 = vlan_interface('eth1.102', 102, base_ifname)
|
||||
v101 = vlan_interface("eth1.101", 101, base_ifname)
|
||||
v102 = vlan_interface("eth1.102", 102, base_ifname)
|
||||
with v101 as v101_state, v102 as v102_state:
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
@ -156,9 +156,9 @@ def test_set_mtu_on_two_vlans_with_a_shared_base(eth1_up):
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
|
||||
@ip_monitor_assert_stable_link_up('eth1')
|
||||
@ip_monitor_assert_stable_link_up("eth1")
|
||||
def test_change_mtu_with_stable_link_up(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.MTU] = 1900
|
||||
|
||||
|
@ -32,54 +32,54 @@ def test_add_down_remove_vlan(eth1_up):
|
||||
Test adding, downing and removing a vlan
|
||||
"""
|
||||
|
||||
vlan_ifname = 'eth1.101'
|
||||
vlan_ifname = "eth1.101"
|
||||
with example_state(
|
||||
'vlan101_eth1_up.yml', cleanup='vlan101_eth1_absent.yml'
|
||||
"vlan101_eth1_up.yml", cleanup="vlan101_eth1_absent.yml"
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
with example_state('vlan101_eth1_down.yml') as desired_state:
|
||||
with example_state("vlan101_eth1_down.yml") as desired_state:
|
||||
assertlib.assert_absent(vlan_ifname)
|
||||
|
||||
assertlib.assert_absent(vlan_ifname)
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateLibnmError, reason='https://bugzilla.redhat.com/1724901'
|
||||
raises=NmstateLibnmError, reason="https://bugzilla.redhat.com/1724901"
|
||||
)
|
||||
def test_add_remove_ovs_bridge(eth1_up):
|
||||
with example_state(
|
||||
'ovsbridge_create.yml', cleanup='ovsbridge_delete.yml'
|
||||
"ovsbridge_create.yml", cleanup="ovsbridge_delete.yml"
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
assertlib.assert_absent('ovs-br0')
|
||||
assertlib.assert_absent("ovs-br0")
|
||||
|
||||
|
||||
def test_add_remove_linux_bridge(eth1_up):
|
||||
with example_state(
|
||||
'linuxbrige_eth1_up.yml', cleanup='linuxbrige_eth1_absent.yml'
|
||||
"linuxbrige_eth1_up.yml", cleanup="linuxbrige_eth1_absent.yml"
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
assertlib.assert_absent('linux-br0')
|
||||
assertlib.assert_absent("linux-br0")
|
||||
|
||||
|
||||
def test_bond_linuxbridge_vlan(eth1_up, eth2_up):
|
||||
with example_state(
|
||||
'bond_linuxbridge_vlan_up.yml',
|
||||
cleanup='bond_linuxbridge_vlan_absent.yml',
|
||||
"bond_linuxbridge_vlan_up.yml",
|
||||
cleanup="bond_linuxbridge_vlan_absent.yml",
|
||||
) as desired_state:
|
||||
assertlib.assert_state_match(desired_state)
|
||||
|
||||
assertlib.assert_absent('bond0')
|
||||
assertlib.assert_absent('br0')
|
||||
assertlib.assert_absent('br29')
|
||||
assertlib.assert_absent('vlan29')
|
||||
assertlib.assert_absent("bond0")
|
||||
assertlib.assert_absent("br0")
|
||||
assertlib.assert_absent("br29")
|
||||
assertlib.assert_absent("vlan29")
|
||||
|
||||
|
||||
def test_dns_edit(eth1_up):
|
||||
with example_state(
|
||||
'dns_edit_eth1.yml', cleanup='dns_remove.yml'
|
||||
"dns_edit_eth1.yml", cleanup="dns_remove.yml"
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
@ -95,8 +95,8 @@ def test_add_remove_routes(eth1_up):
|
||||
Test adding a strict route and removing all routes next hop to eth1.
|
||||
"""
|
||||
with example_state(
|
||||
'eth1_add_route.yml', cleanup='eth1_del_all_routes.yml'
|
||||
"eth1_add_route.yml", cleanup="eth1_del_all_routes.yml"
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
assertlib.assert_no_config_route_to_iface('eth1')
|
||||
assertlib.assert_no_config_route_to_iface("eth1")
|
||||
|
@ -31,7 +31,7 @@ def test_set_a_down_iface_down(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.DOWN,
|
||||
}
|
||||
@ -45,12 +45,12 @@ def test_set_a_down_iface_down(eth1_up):
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='Some ifaces cannot be removed', strict=True)
|
||||
@pytest.mark.xfail(reason="Some ifaces cannot be removed", strict=True)
|
||||
def test_removing_a_non_removable_iface(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.ABSENT,
|
||||
}
|
||||
@ -65,7 +65,7 @@ def test_removing_a_non_removable_iface(eth1_up):
|
||||
def test_set_iface_down_without_type(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{Interface.NAME: 'eth1', Interface.STATE: InterfaceState.DOWN}
|
||||
{Interface.NAME: "eth1", Interface.STATE: InterfaceState.DOWN}
|
||||
]
|
||||
}
|
||||
libnmstate.apply(desired_state)
|
||||
@ -75,7 +75,7 @@ def test_set_iface_down_without_type(eth1_up):
|
||||
|
||||
def test_change_iface_without_type(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [{Interface.NAME: 'eth1', Interface.MTU: 1400}]
|
||||
Interface.KEY: [{Interface.NAME: "eth1", Interface.MTU: 1400}]
|
||||
}
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
|
@ -32,16 +32,16 @@ from libnmstate.schema import InterfaceIPv4
|
||||
from libnmstate.schema import InterfaceIPv6
|
||||
from libnmstate.schema import InterfaceState
|
||||
|
||||
DUMMY_INTERFACE = 'dummy_test'
|
||||
DUMMY_INTERFACE = "dummy_test"
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def ip_link_dummy():
|
||||
libcmd.exec_cmd(['ip', 'link', 'add', DUMMY_INTERFACE, 'type', 'dummy'])
|
||||
libcmd.exec_cmd(["ip", "link", "add", DUMMY_INTERFACE, "type", "dummy"])
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
libcmd.exec_cmd(['ip', 'link', 'del', DUMMY_INTERFACE])
|
||||
libcmd.exec_cmd(["ip", "link", "del", DUMMY_INTERFACE])
|
||||
|
||||
|
||||
@contextmanager
|
||||
@ -67,14 +67,14 @@ def dummy_interface(name):
|
||||
|
||||
def test_iface_description_removal(eth1_up):
|
||||
desired_state = eth1_up
|
||||
desired_state[Interface.KEY][0][Interface.DESCRIPTION] = 'bar'
|
||||
desired_state[Interface.KEY][0][Interface.DESCRIPTION] = "bar"
|
||||
libnmstate.apply(desired_state)
|
||||
current_state = statelib.show_only(('eth1',))
|
||||
assert current_state[Interface.KEY][0][Interface.DESCRIPTION] == 'bar'
|
||||
current_state = statelib.show_only(("eth1",))
|
||||
assert current_state[Interface.KEY][0][Interface.DESCRIPTION] == "bar"
|
||||
|
||||
desired_state[Interface.KEY][0][Interface.DESCRIPTION] = ''
|
||||
desired_state[Interface.KEY][0][Interface.DESCRIPTION] = ""
|
||||
libnmstate.apply(desired_state)
|
||||
current_state = statelib.show_only(('eth1',))
|
||||
current_state = statelib.show_only(("eth1",))
|
||||
assert Interface.DESCRIPTION not in current_state[Interface.KEY][0]
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ def test_take_over_virtual_interface_and_rollback(ip_link_dummy):
|
||||
with dummy_interface(DUMMY_INTERFACE) as dummy_desired_state:
|
||||
assertlib.assert_state_match(dummy_desired_state)
|
||||
|
||||
dummy_desired_state[Interface.KEY][0]['invalid_key'] = 'foo'
|
||||
dummy_desired_state[Interface.KEY][0]["invalid_key"] = "foo"
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
libnmstate.apply(dummy_desired_state)
|
||||
|
||||
|
@ -43,7 +43,7 @@ from .testlib.assertlib import assert_mac_address
|
||||
from .testlib.vlan import vlan_interface
|
||||
from .testlib.env import is_fedora
|
||||
|
||||
TEST_BRIDGE0 = 'linux-br0'
|
||||
TEST_BRIDGE0 = "linux-br0"
|
||||
|
||||
|
||||
BRIDGE_OPTIONS_YAML = """
|
||||
@ -106,7 +106,7 @@ def _bridge0_with_port0(port0_up, use_port_mac=False):
|
||||
def port0_vlan101(port0_up):
|
||||
vlan_id = 101
|
||||
vlan_base_iface = port0_up[Interface.KEY][0][Interface.NAME]
|
||||
port_name = '{}.{}'.format(vlan_base_iface, vlan_id)
|
||||
port_name = "{}.{}".format(vlan_base_iface, vlan_id)
|
||||
with vlan_interface(port_name, vlan_id, vlan_base_iface):
|
||||
state = show_only((port_name,))
|
||||
yield state
|
||||
@ -114,7 +114,7 @@ def port0_vlan101(port0_up):
|
||||
|
||||
@pytest.fixture
|
||||
def bond0(port0_up):
|
||||
bond_name = 'testbond0'
|
||||
bond_name = "testbond0"
|
||||
port_name = port0_up[Interface.KEY][0][Interface.NAME]
|
||||
with bond_interface(bond_name, [port_name], create=False) as bond0:
|
||||
yield bond0
|
||||
@ -194,7 +194,7 @@ def test_create_vlan_as_slave_of_linux_bridge(port0_vlan101):
|
||||
def test_create_vlan_over_linux_bridge(bridge0_with_port0):
|
||||
vlan_base_iface = TEST_BRIDGE0
|
||||
vlan_id = 101
|
||||
port_name = '{}.{}'.format(vlan_base_iface, vlan_id)
|
||||
port_name = "{}.{}".format(vlan_base_iface, vlan_id)
|
||||
with vlan_interface(port_name, vlan_id, vlan_base_iface) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
@ -215,8 +215,8 @@ def test_add_port_to_existing_bridge(bridge0_with_port0, port1_up):
|
||||
@pytest.mark.xfail(
|
||||
is_fedora(),
|
||||
reason=(
|
||||
'On Fedora 31+, users need to explicitly configure the port MAC '
|
||||
'due to changes to the default systemd config.'
|
||||
"On Fedora 31+, users need to explicitly configure the port MAC "
|
||||
"due to changes to the default systemd config."
|
||||
),
|
||||
raises=AssertionError,
|
||||
strict=True,
|
||||
@ -348,7 +348,7 @@ def test_rollback_for_linux_bridge():
|
||||
bridge_state = _create_bridge_subtree_config(())
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
with linux_bridge(bridge_name, bridge_state) as desired_state:
|
||||
desired_state[Interface.KEY][0]['invalid_key'] = 'foo'
|
||||
desired_state[Interface.KEY][0]["invalid_key"] = "foo"
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
time.sleep(5) # Give some time for NetworkManager to rollback
|
||||
@ -378,7 +378,7 @@ def test_activate_empty_bridge_does_not_blocked_by_dhcp():
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
reason='https://nmstate.atlassian.net/browse/NMSTATE-230',
|
||||
reason="https://nmstate.atlassian.net/browse/NMSTATE-230",
|
||||
strict=True,
|
||||
)
|
||||
def test_port_vlan_not_implemented(port0_up):
|
||||
|
@ -26,13 +26,13 @@ from libnmstate.schema import Interface
|
||||
from .testlib import mainloop_run
|
||||
|
||||
|
||||
BOND0 = 'bondtest0'
|
||||
BOND0 = "bondtest0"
|
||||
|
||||
|
||||
def test_create_and_remove_bond(eth1_up):
|
||||
bond_options = {
|
||||
schema.Bond.MODE: schema.BondMode.ROUND_ROBIN,
|
||||
'miimon': '140',
|
||||
"miimon": "140",
|
||||
}
|
||||
|
||||
with _bond_interface(BOND0, bond_options):
|
||||
@ -126,12 +126,12 @@ def _attach_slave_to_bond(bond, slave):
|
||||
def _create_connection_setting(bond, port_con_profile):
|
||||
con_setting = nm.connection.ConnectionSetting()
|
||||
con_setting.import_by_profile(port_con_profile)
|
||||
con_setting.set_master(bond, 'bond')
|
||||
con_setting.set_master(bond, "bond")
|
||||
|
||||
return con_setting.setting
|
||||
|
||||
|
||||
def _convert_slaves_devices_to_iface_names(info):
|
||||
if info:
|
||||
info['slaves'] = [slave.props.interface for slave in info['slaves']]
|
||||
info["slaves"] = [slave.props.interface for slave in info["slaves"]]
|
||||
return info
|
||||
|
@ -24,9 +24,9 @@ from ..testlib import iproutelib
|
||||
from .testlib import mainloop
|
||||
|
||||
|
||||
TEST_IFACE = 'eth1'
|
||||
TEST_IFACE = "eth1"
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
|
||||
|
||||
@iproutelib.ip_monitor_assert_stable_link_up(TEST_IFACE)
|
||||
|
@ -29,7 +29,7 @@ from ..testlib import iproutelib
|
||||
from .testlib import mainloop_run
|
||||
|
||||
|
||||
BRIDGE0 = 'brtest0'
|
||||
BRIDGE0 = "brtest0"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -168,7 +168,7 @@ def _create_bridge(bridge_desired_state):
|
||||
|
||||
|
||||
def _attach_port_to_bridge(port_state):
|
||||
port_nmdev = nm.device.get_device_by_name(port_state['name'])
|
||||
port_nmdev = nm.device.get_device_by_name(port_state["name"])
|
||||
curr_port_con_profile = nm.connection.ConnectionProfile()
|
||||
curr_port_con_profile.import_by_device(port_nmdev)
|
||||
iface_port_settings = _get_iface_port_settings(
|
||||
@ -192,7 +192,7 @@ def _create_bridge_iface(iface_bridge_settings):
|
||||
def _get_iface_port_settings(port_state, port_con_profile):
|
||||
con_setting = nm.connection.ConnectionSetting()
|
||||
con_setting.import_by_profile(port_con_profile)
|
||||
con_setting.set_master(BRIDGE0, 'bridge')
|
||||
con_setting.set_master(BRIDGE0, "bridge")
|
||||
|
||||
bridge_port_setting = nm.bridge.create_port_setting(
|
||||
port_state, port_con_profile.profile
|
||||
|
@ -28,8 +28,8 @@ from .testlib import mainloop
|
||||
from .testlib import MainloopTestError
|
||||
|
||||
|
||||
BRIDGE0 = 'brtest0'
|
||||
ETH1 = 'eth1'
|
||||
BRIDGE0 = "brtest0"
|
||||
ETH1 = "eth1"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -42,7 +42,7 @@ def bridge_default_config():
|
||||
return {
|
||||
OB.CONFIG_SUBTREE: {
|
||||
OB.OPTIONS_SUBTREE: {
|
||||
OB.Options.FAIL_MODE: '',
|
||||
OB.Options.FAIL_MODE: "",
|
||||
OB.Options.MCAST_SNOOPING_ENABLED: False,
|
||||
OB.Options.RSTP: False,
|
||||
OB.Options.STP: False,
|
||||
@ -54,7 +54,7 @@ def bridge_default_config():
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(MainloopTestError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_create_and_remove_minimum_config_bridge(
|
||||
bridge_minimum_config, bridge_default_config
|
||||
@ -71,13 +71,13 @@ def test_create_and_remove_minimum_config_bridge(
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(MainloopTestError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_bridge_with_system_port(eth1_up, bridge_default_config):
|
||||
bridge_desired_state = bridge_default_config
|
||||
|
||||
eth1_port = {
|
||||
OB.Port.NAME: 'eth1',
|
||||
OB.Port.NAME: "eth1",
|
||||
# OVS vlan/s are not yet supported.
|
||||
# OB.VLAN.MODE: None,
|
||||
# OB.VLAN.TAG: 0,
|
||||
@ -94,12 +94,12 @@ def test_bridge_with_system_port(eth1_up, bridge_default_config):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(MainloopTestError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_bridge_with_internal_interface(bridge_default_config):
|
||||
bridge_desired_state = bridge_default_config
|
||||
|
||||
ovs_port = {OB.Port.NAME: 'ovs0'}
|
||||
ovs_port = {OB.Port.NAME: "ovs0"}
|
||||
|
||||
bridge_desired_state[OB.CONFIG_SUBTREE][OB.PORT_SUBTREE].append(ovs_port)
|
||||
|
||||
|
@ -32,13 +32,13 @@ from libnmstate.schema import InterfaceIPv6
|
||||
from .testlib import mainloop_run
|
||||
from ..testlib import iprule
|
||||
|
||||
ETH1 = 'eth1'
|
||||
ETH1 = "eth1"
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def eth1_up_with_static(eth1_up):
|
||||
state = eth1_up
|
||||
iface_state = state[Interface.KEY][0]
|
||||
@ -72,13 +72,13 @@ def eth1_up_with_static(eth1_up):
|
||||
|
||||
|
||||
def test_create_rule_add_full(eth1_up_with_static):
|
||||
rule_v4_0 = _create_route_rule('198.51.100.0/24', '192.0.2.1/32', 50, 103)
|
||||
rule_v4_1 = _create_route_rule('198.51.100.0/24', '192.0.2.2/32', 51, 104)
|
||||
rule_v4_0 = _create_route_rule("198.51.100.0/24", "192.0.2.1/32", 50, 103)
|
||||
rule_v4_1 = _create_route_rule("198.51.100.0/24", "192.0.2.2/32", 51, 104)
|
||||
rule_v6_0 = _create_route_rule(
|
||||
'2001:db8:a::/64', '2001:db8:1::a/128', 50, 103
|
||||
"2001:db8:a::/64", "2001:db8:1::a/128", 50, 103
|
||||
)
|
||||
rule_v6_1 = _create_route_rule(
|
||||
'2001:db8:b::/64', '2001:db8:1::a/128', 51, 104
|
||||
"2001:db8:b::/64", "2001:db8:1::a/128", 51, 104
|
||||
)
|
||||
|
||||
ipv4_state = eth1_up_with_static[Interface.KEY][0][Interface.IPV4]
|
||||
@ -94,7 +94,7 @@ def test_create_rule_add_full(eth1_up_with_static):
|
||||
|
||||
|
||||
def test_route_rule_without_prioriry(eth1_up_with_static):
|
||||
rule = _create_route_rule('198.51.100.0/24', '192.0.2.1/32', 50, 103)
|
||||
rule = _create_route_rule("198.51.100.0/24", "192.0.2.1/32", 50, 103)
|
||||
del rule[RouteRule.PRIORITY]
|
||||
ipv4_state = eth1_up_with_static[Interface.KEY][0][Interface.IPV4]
|
||||
ipv4_state.update({nm.route.ROUTE_RULES_METADATA: [rule]})
|
||||
@ -107,7 +107,7 @@ def test_route_rule_without_prioriry(eth1_up_with_static):
|
||||
|
||||
|
||||
def test_route_rule_without_table(eth1_up_with_static):
|
||||
rule = _create_route_rule('198.51.100.0/24', '192.0.2.1/32', 50, 103)
|
||||
rule = _create_route_rule("198.51.100.0/24", "192.0.2.1/32", 50, 103)
|
||||
del rule[RouteRule.ROUTE_TABLE]
|
||||
ipv4_state = eth1_up_with_static[Interface.KEY][0][Interface.IPV4]
|
||||
ipv4_state.update({nm.route.ROUTE_RULES_METADATA: [rule]})
|
||||
@ -120,7 +120,7 @@ def test_route_rule_without_table(eth1_up_with_static):
|
||||
|
||||
|
||||
def test_route_rule_without_from(eth1_up_with_static):
|
||||
rule = _create_route_rule('198.51.100.0/24', '192.0.2.1/32', 50, 103)
|
||||
rule = _create_route_rule("198.51.100.0/24", "192.0.2.1/32", 50, 103)
|
||||
del rule[RouteRule.IP_FROM]
|
||||
ipv4_state = eth1_up_with_static[Interface.KEY][0][Interface.IPV4]
|
||||
ipv4_state.update({nm.route.ROUTE_RULES_METADATA: [rule]})
|
||||
@ -132,7 +132,7 @@ def test_route_rule_without_from(eth1_up_with_static):
|
||||
|
||||
|
||||
def test_route_rule_without_to(eth1_up_with_static):
|
||||
rule = _create_route_rule('198.51.100.0/24', '192.0.2.1/32', 50, 103)
|
||||
rule = _create_route_rule("198.51.100.0/24", "192.0.2.1/32", 50, 103)
|
||||
del rule[RouteRule.IP_TO]
|
||||
ipv4_state = eth1_up_with_static[Interface.KEY][0][Interface.IPV4]
|
||||
ipv4_state.update({nm.route.ROUTE_RULES_METADATA: [rule]})
|
||||
@ -191,6 +191,6 @@ def _assert_route_rules(expected_rules):
|
||||
cur_rules = (
|
||||
nm.ipv4.get_routing_rule_config() + nm.ipv6.get_routing_rule_config()
|
||||
)
|
||||
logging.debug(f'Current route rules reported by NM {cur_rules}')
|
||||
logging.debug(f"Current route rules reported by NM {cur_rules}")
|
||||
for rule in expected_rules:
|
||||
assert rule in expected_rules
|
||||
|
@ -25,7 +25,7 @@ from libnmstate.schema import VLAN
|
||||
from .testlib import mainloop
|
||||
|
||||
|
||||
ETH1 = 'eth1'
|
||||
ETH1 = "eth1"
|
||||
|
||||
|
||||
def test_create_and_remove_vlan(eth1_up):
|
||||
@ -89,6 +89,6 @@ def _delete_vlan(devname):
|
||||
def _get_vlan_ifname(state):
|
||||
return (
|
||||
state[VLAN.CONFIG_SUBTREE][VLAN.BASE_IFACE]
|
||||
+ '.'
|
||||
+ "."
|
||||
+ str(state[VLAN.CONFIG_SUBTREE][VLAN.ID])
|
||||
)
|
||||
|
@ -42,9 +42,9 @@ def test_create_and_remove_vxlan(eth1_up):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
condition=StrictVersion(nm.nmclient.nm_version())
|
||||
< StrictVersion('1.20.6'),
|
||||
< StrictVersion("1.20.6"),
|
||||
strict=True,
|
||||
reason='https://bugzilla.redhat.com/show_bug.cgi?id=1768388',
|
||||
reason="https://bugzilla.redhat.com/show_bug.cgi?id=1768388",
|
||||
)
|
||||
def test_read_destination_port_from_libnm(eth1_up):
|
||||
vxlan_desired_state = _create_vxlan_state(eth1_up)
|
||||
@ -65,7 +65,7 @@ def _create_vxlan_state(eth1_up):
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: 201,
|
||||
VXLAN.BASE_IFACE: ifname,
|
||||
VXLAN.REMOTE: '192.168.1.18',
|
||||
VXLAN.REMOTE: "192.168.1.18",
|
||||
VXLAN.DESTINATION_PORT: 4789,
|
||||
}
|
||||
}
|
||||
@ -123,6 +123,6 @@ def _get_vxlan_device(ifname):
|
||||
def _vxlan_ifname(state):
|
||||
return (
|
||||
state[VXLAN.CONFIG_SUBTREE][VXLAN.BASE_IFACE]
|
||||
+ '.'
|
||||
+ "."
|
||||
+ str(state[VXLAN.CONFIG_SUBTREE][VXLAN.ID])
|
||||
)
|
||||
|
@ -28,15 +28,15 @@ from .testlib import mainloop
|
||||
from .testlib import MainloopTestError
|
||||
|
||||
|
||||
ETH1 = 'eth1'
|
||||
ETH1 = "eth1"
|
||||
|
||||
MAC0 = '02:FF:FF:FF:FF:00'
|
||||
MAC0 = "02:FF:FF:FF:FF:00"
|
||||
MTU0 = 1200
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
condition=StrictVersion(nm.nmclient.nm_version()) < StrictVersion('1.18'),
|
||||
reason='https://bugzilla.redhat.com/1702657',
|
||||
condition=StrictVersion(nm.nmclient.nm_version()) < StrictVersion("1.18"),
|
||||
reason="https://bugzilla.redhat.com/1702657",
|
||||
strict=True,
|
||||
)
|
||||
def test_interface_mtu_change_with_reapply(eth1_up):
|
||||
|
@ -28,11 +28,11 @@ RC_SUCCESS = 0
|
||||
|
||||
def test_edit_abort():
|
||||
runenv = dict(os.environ)
|
||||
env = {'EDITOR': 'false'}
|
||||
env = {"EDITOR": "false"}
|
||||
|
||||
runenv.update(env)
|
||||
|
||||
cmds = ['nmstatectl', 'edit', 'lo']
|
||||
cmds = ["nmstatectl", "edit", "lo"]
|
||||
ret = libcmd.exec_cmd(cmds, env=runenv)
|
||||
rc, out, err = ret
|
||||
|
||||
@ -41,11 +41,11 @@ def test_edit_abort():
|
||||
|
||||
def test_edit_no_change_eth1():
|
||||
runenv = dict(os.environ)
|
||||
env = {'EDITOR': 'touch'}
|
||||
env = {"EDITOR": "touch"}
|
||||
|
||||
runenv.update(env)
|
||||
|
||||
cmds = ['nmstatectl', 'edit', 'eth1']
|
||||
cmds = ["nmstatectl", "edit", "eth1"]
|
||||
ret = libcmd.exec_cmd(cmds, env=runenv)
|
||||
rc, out, err = ret
|
||||
|
||||
@ -53,4 +53,4 @@ def test_edit_no_change_eth1():
|
||||
|
||||
|
||||
def assert_rc(actual, expected, return_tuple):
|
||||
assert actual == expected, 'rc={}, out={}, err={}'.format(*return_tuple)
|
||||
assert actual == expected, "rc={}, out={}, err={}".format(*return_tuple)
|
||||
|
@ -31,10 +31,10 @@ from .testlib.examplelib import find_examples_dir
|
||||
from .testlib.examplelib import load_example
|
||||
|
||||
|
||||
SET_CMD = ['nmstatectl', 'set']
|
||||
SHOW_CMD = ['nmstatectl', 'show']
|
||||
CONFIRM_CMD = ['nmstatectl', 'commit']
|
||||
ROLLBACK_CMD = ['nmstatectl', 'rollback']
|
||||
SET_CMD = ["nmstatectl", "set"]
|
||||
SHOW_CMD = ["nmstatectl", "show"]
|
||||
CONFIRM_CMD = ["nmstatectl", "commit"]
|
||||
ROLLBACK_CMD = ["nmstatectl", "rollback"]
|
||||
|
||||
LOOPBACK_JSON_CONFIG = """ {
|
||||
"name": "lo",
|
||||
@ -73,25 +73,25 @@ ETH1_YAML_CONFIG = b"""interfaces:
|
||||
"""
|
||||
|
||||
EXAMPLES = find_examples_dir()
|
||||
CONFIRMATION_INTERFACE = 'eth1.101'
|
||||
CONFIRMATION_CLEAN = 'vlan101_eth1_absent.yml'
|
||||
CONFIRMATION_TEST = 'vlan101_eth1_up.yml'
|
||||
CONFIRMATION_INTERFACE = "eth1.101"
|
||||
CONFIRMATION_CLEAN = "vlan101_eth1_absent.yml"
|
||||
CONFIRMATION_TEST = "vlan101_eth1_up.yml"
|
||||
CONFIRMATION_TEST_STATE = load_example(CONFIRMATION_TEST)
|
||||
CONFIRMATION_SET = SET_CMD + [
|
||||
'--no-commit',
|
||||
"--no-commit",
|
||||
os.path.join(EXAMPLES, CONFIRMATION_TEST),
|
||||
]
|
||||
CONFIRMATION_TIMEOUT = 5
|
||||
CONFIRMATION_TIMOUT_COMMAND = SET_CMD + [
|
||||
'--no-commit',
|
||||
'--timeout',
|
||||
"--no-commit",
|
||||
"--timeout",
|
||||
str(CONFIRMATION_TIMEOUT),
|
||||
os.path.join(EXAMPLES, CONFIRMATION_TEST),
|
||||
]
|
||||
|
||||
|
||||
def test_missing_operation():
|
||||
cmds = ['nmstatectl', 'no-such-oper']
|
||||
cmds = ["nmstatectl", "no-such-oper"]
|
||||
ret = libcmd.exec_cmd(cmds)
|
||||
rc, out, err = ret
|
||||
|
||||
@ -100,7 +100,7 @@ def test_missing_operation():
|
||||
|
||||
|
||||
def test_show_command_with_json():
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ['--json'])
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ["--json"])
|
||||
rc, out, err = ret
|
||||
|
||||
assert rc == libcmd.RC_SUCCESS, libcmd.format_exec_cmd_result(ret)
|
||||
@ -119,18 +119,18 @@ def test_show_command_with_yaml_format():
|
||||
|
||||
|
||||
def test_show_command_json_only_lo():
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ['--json', 'lo'])
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ["--json", "lo"])
|
||||
rc, out, err = ret
|
||||
|
||||
assert rc == libcmd.RC_SUCCESS, libcmd.format_exec_cmd_result(ret)
|
||||
|
||||
state = json.loads(out)
|
||||
assert len(state[Constants.INTERFACES]) == 1
|
||||
assert state[Constants.INTERFACES][0]['name'] == 'lo'
|
||||
assert state[Constants.INTERFACES][0]["name"] == "lo"
|
||||
|
||||
|
||||
def test_show_command_only_non_existing():
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ['--json', 'non_existing_interface'])
|
||||
ret = libcmd.exec_cmd(SHOW_CMD + ["--json", "non_existing_interface"])
|
||||
rc, out, err = ret
|
||||
|
||||
assert rc == libcmd.RC_SUCCESS, libcmd.format_exec_cmd_result(ret)
|
||||
@ -149,8 +149,8 @@ def test_set_command_with_yaml_format():
|
||||
def test_set_command_with_two_states():
|
||||
examples = find_examples_dir()
|
||||
cmd = SET_CMD + [
|
||||
os.path.join(examples, 'linuxbrige_eth1_up.yml'),
|
||||
os.path.join(examples, 'linuxbrige_eth1_absent.yml'),
|
||||
os.path.join(examples, "linuxbrige_eth1_up.yml"),
|
||||
os.path.join(examples, "linuxbrige_eth1_absent.yml"),
|
||||
]
|
||||
ret = libcmd.exec_cmd(cmd)
|
||||
rc = ret[0]
|
||||
|
@ -28,13 +28,13 @@ from .testlib import assertlib
|
||||
from .testlib.ovslib import Bridge
|
||||
|
||||
|
||||
BRIDGE1 = 'br1'
|
||||
PORT1 = 'ovs1'
|
||||
BRIDGE1 = "br1"
|
||||
PORT1 = "ovs1"
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(NmstateLibnmError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_create_and_remove_ovs_bridge_with_min_desired_state():
|
||||
with Bridge(BRIDGE1).create() as state:
|
||||
@ -45,13 +45,13 @@ def test_create_and_remove_ovs_bridge_with_min_desired_state():
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(NmstateLibnmError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_create_and_remove_ovs_bridge_options_specified():
|
||||
bridge = Bridge(BRIDGE1)
|
||||
bridge.set_options(
|
||||
{
|
||||
OVSBridge.Options.FAIL_MODE: '',
|
||||
OVSBridge.Options.FAIL_MODE: "",
|
||||
OVSBridge.Options.MCAST_SNOOPING_ENABLED: False,
|
||||
OVSBridge.Options.RSTP: False,
|
||||
OVSBridge.Options.STP: True,
|
||||
@ -66,7 +66,7 @@ def test_create_and_remove_ovs_bridge_options_specified():
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(NmstateLibnmError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_create_and_remove_ovs_bridge_with_a_system_port(port0_up):
|
||||
bridge = Bridge(BRIDGE1)
|
||||
@ -81,7 +81,7 @@ def test_create_and_remove_ovs_bridge_with_a_system_port(port0_up):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=(NmstateLibnmError, AssertionError),
|
||||
reason='https://bugzilla.redhat.com/1724901',
|
||||
reason="https://bugzilla.redhat.com/1724901",
|
||||
)
|
||||
def test_create_and_remove_ovs_bridge_with_internal_port_and_static_ip():
|
||||
bridge = Bridge(BRIDGE1)
|
||||
@ -91,7 +91,7 @@ def test_create_and_remove_ovs_bridge_with_internal_port_and_static_ip():
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.0.2.1',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.0.2.1",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
|
@ -30,13 +30,13 @@ from libnmstate.schema import InterfaceState
|
||||
from .testlib import statelib
|
||||
from .testlib import cmd as libcmd
|
||||
|
||||
_IPV4_EXTRA_CONFIG = 'ipv4.dad-timeout'
|
||||
_IPV4_EXTRA_VALUE = '0'
|
||||
_IPV6_EXTRA_CONFIG = 'ipv6.dhcp-hostname'
|
||||
_IPV6_EXTRA_VALUE = 'libnmstate.example.com'
|
||||
_IPV4_EXTRA_CONFIG = "ipv4.dad-timeout"
|
||||
_IPV4_EXTRA_VALUE = "0"
|
||||
_IPV6_EXTRA_CONFIG = "ipv6.dhcp-hostname"
|
||||
_IPV6_EXTRA_VALUE = "libnmstate.example.com"
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
|
||||
|
||||
def test_reapply_preserve_ip_config(eth1_up):
|
||||
@ -44,7 +44,7 @@ def test_reapply_preserve_ip_config(eth1_up):
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -70,7 +70,7 @@ def test_reapply_preserve_ip_config(eth1_up):
|
||||
]
|
||||
}
|
||||
)
|
||||
cur_state = statelib.show_only(('eth1',))
|
||||
cur_state = statelib.show_only(("eth1",))
|
||||
iface_name = cur_state[Interface.KEY][0][Interface.NAME]
|
||||
|
||||
uuid = _get_nm_profile_uuid(iface_name)
|
||||
@ -98,10 +98,10 @@ def _get_nm_profile_uuid(iface_name):
|
||||
|
||||
def _get_cur_extra_ip_config(uuid, key):
|
||||
rc, output, _ = libcmd.exec_cmd(
|
||||
['nmcli', '--get-values', key, 'connection', 'show', uuid]
|
||||
["nmcli", "--get-values", key, "connection", "show", uuid]
|
||||
)
|
||||
assert rc == 0
|
||||
return output.split('\n')[0]
|
||||
return output.split("\n")[0]
|
||||
|
||||
|
||||
@contextmanager
|
||||
@ -116,7 +116,7 @@ def _extra_ip_config(uuid, key, value):
|
||||
|
||||
def _apply_extra_ip_config(uuid, key, value):
|
||||
assert (
|
||||
libcmd.exec_cmd(['nmcli', 'connection', 'modify', uuid, key, value])[0]
|
||||
libcmd.exec_cmd(["nmcli", "connection", "modify", uuid, key, value])[0]
|
||||
== 0
|
||||
)
|
||||
|
||||
|
@ -31,45 +31,45 @@ from libnmstate.schema import InterfaceState
|
||||
from .testlib import cmd as libcmd
|
||||
|
||||
|
||||
DUMMY0_IFNAME = 'dummy0'
|
||||
DUMMY0_IFNAME = "dummy0"
|
||||
|
||||
NMCLI_CON_ADD_DUMMY_CMD = [
|
||||
'nmcli',
|
||||
'con',
|
||||
'add',
|
||||
'type',
|
||||
'dummy',
|
||||
'con-name',
|
||||
'testProfile',
|
||||
'connection.autoconnect',
|
||||
'no',
|
||||
'ifname',
|
||||
"nmcli",
|
||||
"con",
|
||||
"add",
|
||||
"type",
|
||||
"dummy",
|
||||
"con-name",
|
||||
"testProfile",
|
||||
"connection.autoconnect",
|
||||
"no",
|
||||
"ifname",
|
||||
DUMMY0_IFNAME,
|
||||
]
|
||||
|
||||
NMCLI_CON_ADD_ETH_CMD = [
|
||||
'nmcli',
|
||||
'con',
|
||||
'add',
|
||||
'type',
|
||||
'ethernet',
|
||||
'con-name',
|
||||
'testProfile',
|
||||
'connection.autoconnect',
|
||||
'no',
|
||||
'ifname',
|
||||
'eth1',
|
||||
"nmcli",
|
||||
"con",
|
||||
"add",
|
||||
"type",
|
||||
"ethernet",
|
||||
"con-name",
|
||||
"testProfile",
|
||||
"connection.autoconnect",
|
||||
"no",
|
||||
"ifname",
|
||||
"eth1",
|
||||
]
|
||||
|
||||
DUMMY_PROFILE_DIRECTORY = '/etc/NetworkManager/system-connections/'
|
||||
DUMMY_PROFILE_DIRECTORY = "/etc/NetworkManager/system-connections/"
|
||||
|
||||
ETH_PROFILE_DIRECTORY = '/etc/sysconfig/network-scripts/'
|
||||
ETH_PROFILE_DIRECTORY = "/etc/sysconfig/network-scripts/"
|
||||
|
||||
|
||||
def test_delete_new_interface_inactive_profiles(dummy_inactive_profile):
|
||||
with dummy_interface(dummy_inactive_profile):
|
||||
profile_exists = _profile_exists(
|
||||
DUMMY_PROFILE_DIRECTORY + 'testProfile.nmconnection'
|
||||
DUMMY_PROFILE_DIRECTORY + "testProfile.nmconnection"
|
||||
)
|
||||
assert not profile_exists
|
||||
|
||||
@ -79,7 +79,7 @@ def test_delete_existing_interface_inactive_profiles(eth1_up):
|
||||
eth1_up[Interface.KEY][0][Interface.MTU] = 2000
|
||||
libnmstate.apply(eth1_up)
|
||||
profile_exists = _profile_exists(
|
||||
ETH_PROFILE_DIRECTORY + 'ifcfg-testProfile'
|
||||
ETH_PROFILE_DIRECTORY + "ifcfg-testProfile"
|
||||
)
|
||||
assert not profile_exists
|
||||
|
||||
@ -108,13 +108,13 @@ def dummy_interface(ifname):
|
||||
def dummy_inactive_profile():
|
||||
libcmd.exec_cmd(NMCLI_CON_ADD_DUMMY_CMD)
|
||||
profile_exists = _profile_exists(
|
||||
DUMMY_PROFILE_DIRECTORY + 'testProfile.nmconnection'
|
||||
DUMMY_PROFILE_DIRECTORY + "testProfile.nmconnection"
|
||||
)
|
||||
assert profile_exists
|
||||
try:
|
||||
yield DUMMY0_IFNAME
|
||||
finally:
|
||||
libcmd.exec_cmd(_nmcli_delete_connection('testProfile'))
|
||||
libcmd.exec_cmd(_nmcli_delete_connection("testProfile"))
|
||||
|
||||
|
||||
@contextmanager
|
||||
@ -122,21 +122,21 @@ def create_inactive_profile(con_name):
|
||||
libcmd.exec_cmd(_nmcli_deactivate_connection(con_name))
|
||||
libcmd.exec_cmd(NMCLI_CON_ADD_ETH_CMD)
|
||||
profile_exists = _profile_exists(
|
||||
ETH_PROFILE_DIRECTORY + 'ifcfg-testProfile'
|
||||
ETH_PROFILE_DIRECTORY + "ifcfg-testProfile"
|
||||
)
|
||||
assert profile_exists
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
libcmd.exec_cmd(_nmcli_delete_connection('testProfile'))
|
||||
libcmd.exec_cmd(_nmcli_delete_connection("testProfile"))
|
||||
|
||||
|
||||
def _nmcli_deactivate_connection(con_name):
|
||||
return ['nmcli', 'con', 'down', con_name]
|
||||
return ["nmcli", "con", "down", con_name]
|
||||
|
||||
|
||||
def _nmcli_delete_connection(con_name):
|
||||
return ['nmcli', 'con', 'delete', con_name]
|
||||
return ["nmcli", "con", "delete", con_name]
|
||||
|
||||
|
||||
def _profile_exists(profile_name):
|
||||
|
@ -34,21 +34,21 @@ from libnmstate.schema import RouteRule
|
||||
|
||||
from .testlib import iprule
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
IPV4_ROUTE_TABLE_ID1 = 50
|
||||
IPV4_ROUTE_TABLE_ID2 = 51
|
||||
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
IPV6_ROUTE_TABLE_ID1 = 50
|
||||
IPV6_ROUTE_TABLE_ID2 = 51
|
||||
|
||||
IPV4_DNS_NAMESERVER = '8.8.8.8'
|
||||
IPV6_DNS_NAMESERVER = '2001:4860:4860::8888'
|
||||
DNS_SEARCHES = ['example.org', 'example.com']
|
||||
IPV4_DNS_NAMESERVER = "8.8.8.8"
|
||||
IPV6_DNS_NAMESERVER = "2001:4860:4860::8888"
|
||||
DNS_SEARCHES = ["example.org", "example.com"]
|
||||
|
||||
|
||||
ETH1_INTERFACE_STATE = {
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV4: {
|
||||
@ -166,13 +166,13 @@ def test_change_gateway(eth1_up):
|
||||
Route.CONFIG: [
|
||||
{
|
||||
Route.STATE: Route.STATE_ABSENT,
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
},
|
||||
{
|
||||
Route.STATE: Route.STATE_ABSENT,
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.DESTINATION: "::/0",
|
||||
},
|
||||
]
|
||||
+ routes
|
||||
@ -197,7 +197,7 @@ def _assert_routes(routes, state):
|
||||
routes.sort(key=_route_sort_key)
|
||||
config_routes = []
|
||||
for config_route in state[Route.KEY][Route.CONFIG]:
|
||||
if config_route[Route.NEXT_HOP_INTERFACE] == 'eth1':
|
||||
if config_route[Route.NEXT_HOP_INTERFACE] == "eth1":
|
||||
config_routes.append(config_route)
|
||||
|
||||
config_routes.sort(key=_route_sort_key)
|
||||
@ -232,17 +232,17 @@ def _assert_in_running_route(route, running_routes):
|
||||
def _get_ipv4_test_routes():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '198.51.100.0/24',
|
||||
Route.DESTINATION: "198.51.100.0/24",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: IPV4_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '203.0.113.0/24',
|
||||
Route.DESTINATION: "203.0.113.0/24",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: IPV4_ROUTE_TABLE_ID2,
|
||||
},
|
||||
]
|
||||
@ -251,17 +251,17 @@ def _get_ipv4_test_routes():
|
||||
def _get_ipv4_gateways():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: 254,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 101,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.2',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.2",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: 254,
|
||||
},
|
||||
]
|
||||
@ -270,17 +270,17 @@ def _get_ipv4_gateways():
|
||||
def _get_ipv6_test_routes():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '2001:db8:a::/64',
|
||||
Route.DESTINATION: "2001:db8:a::/64",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::a',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::a",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: IPV6_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '2001:db8:b::/64',
|
||||
Route.DESTINATION: "2001:db8:b::/64",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::b',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::b",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: IPV6_ROUTE_TABLE_ID2,
|
||||
},
|
||||
]
|
||||
@ -289,17 +289,17 @@ def _get_ipv6_test_routes():
|
||||
def _get_ipv6_gateways():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::f',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::f",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: 254,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 101,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::e',
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::e",
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
Route.TABLE_ID: 254,
|
||||
},
|
||||
]
|
||||
@ -308,15 +308,15 @@ def _get_ipv6_gateways():
|
||||
def _route_sort_key(route):
|
||||
return (
|
||||
route.get(Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE),
|
||||
route.get(Route.NEXT_HOP_INTERFACE, ''),
|
||||
route.get(Route.DESTINATION, ''),
|
||||
route.get(Route.NEXT_HOP_INTERFACE, ""),
|
||||
route.get(Route.DESTINATION, ""),
|
||||
)
|
||||
|
||||
|
||||
parametrize_ip_ver_routes = pytest.mark.parametrize(
|
||||
'get_routes_func',
|
||||
"get_routes_func",
|
||||
[(_get_ipv4_test_routes), (_get_ipv6_test_routes)],
|
||||
ids=['ipv4', 'ipv6'],
|
||||
ids=["ipv4", "ipv6"],
|
||||
)
|
||||
|
||||
|
||||
@ -361,7 +361,7 @@ def test_remove_wildcast_route_with_iface(eth1_up, get_routes_func):
|
||||
|
||||
absent_route = {
|
||||
Route.STATE: Route.STATE_ABSENT,
|
||||
Route.NEXT_HOP_INTERFACE: 'eth1',
|
||||
Route.NEXT_HOP_INTERFACE: "eth1",
|
||||
}
|
||||
libnmstate.apply(
|
||||
{
|
||||
@ -440,7 +440,7 @@ def test_iface_down_with_routes_in_current(eth1_up, get_routes_func):
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.DOWN,
|
||||
}
|
||||
@ -452,7 +452,7 @@ def test_iface_down_with_routes_in_current(eth1_up, get_routes_func):
|
||||
_assert_routes([], cur_state)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def eth1_static_gateway_dns(eth1_up):
|
||||
routes = (
|
||||
[_get_ipv4_gateways()[0], _get_ipv6_gateways()[0]]
|
||||
@ -481,7 +481,7 @@ def eth1_static_gateway_dns(eth1_up):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=AssertionError,
|
||||
reason='https://bugzilla.redhat.com/1748389',
|
||||
reason="https://bugzilla.redhat.com/1748389",
|
||||
strict=True,
|
||||
)
|
||||
def test_apply_empty_state_preserve_routes(eth1_static_gateway_dns):
|
||||
@ -498,7 +498,7 @@ def test_apply_empty_state_preserve_routes(eth1_static_gateway_dns):
|
||||
assert current_state[DNS.KEY][DNS.CONFIG] == state[DNS.KEY][DNS.CONFIG]
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@pytest.fixture(scope="function")
|
||||
def route_rule_test_env(eth1_static_gateway_dns):
|
||||
yield eth1_static_gateway_dns
|
||||
libnmstate.apply(
|
||||
@ -529,11 +529,11 @@ def test_route_rule_add_from_only(route_rule_test_env):
|
||||
state = route_rule_test_env
|
||||
rules = [
|
||||
{
|
||||
RouteRule.IP_FROM: '2001:db8:f::/64',
|
||||
RouteRule.IP_FROM: "2001:db8:f::/64",
|
||||
RouteRule.ROUTE_TABLE: IPV6_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
RouteRule.IP_FROM: '192.0.2.0/24',
|
||||
RouteRule.IP_FROM: "192.0.2.0/24",
|
||||
RouteRule.ROUTE_TABLE: IPV4_ROUTE_TABLE_ID1,
|
||||
},
|
||||
]
|
||||
@ -547,11 +547,11 @@ def test_route_rule_add_to_only(route_rule_test_env):
|
||||
state = route_rule_test_env
|
||||
rules = [
|
||||
{
|
||||
RouteRule.IP_TO: '2001:db8:f::/64',
|
||||
RouteRule.IP_TO: "2001:db8:f::/64",
|
||||
RouteRule.ROUTE_TABLE: IPV6_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
RouteRule.IP_TO: '192.0.2.0/24',
|
||||
RouteRule.IP_TO: "192.0.2.0/24",
|
||||
RouteRule.ROUTE_TABLE: IPV4_ROUTE_TABLE_ID1,
|
||||
},
|
||||
]
|
||||
@ -565,14 +565,14 @@ def test_route_rule_add(route_rule_test_env):
|
||||
state = route_rule_test_env
|
||||
rules = [
|
||||
{
|
||||
RouteRule.IP_FROM: '2001:db8:a::/64',
|
||||
RouteRule.IP_TO: '2001:db8:f::/64',
|
||||
RouteRule.IP_FROM: "2001:db8:a::/64",
|
||||
RouteRule.IP_TO: "2001:db8:f::/64",
|
||||
RouteRule.PRIORITY: 1000,
|
||||
RouteRule.ROUTE_TABLE: IPV6_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
RouteRule.IP_FROM: '203.0.113.0/24',
|
||||
RouteRule.IP_TO: '192.0.2.0/24',
|
||||
RouteRule.IP_FROM: "203.0.113.0/24",
|
||||
RouteRule.IP_TO: "192.0.2.0/24",
|
||||
RouteRule.PRIORITY: 1000,
|
||||
RouteRule.ROUTE_TABLE: IPV4_ROUTE_TABLE_ID1,
|
||||
},
|
||||
@ -587,13 +587,13 @@ def test_route_rule_add_without_priority(route_rule_test_env):
|
||||
state = route_rule_test_env
|
||||
rules = [
|
||||
{
|
||||
RouteRule.IP_FROM: '2001:db8:a::/64',
|
||||
RouteRule.IP_TO: '2001:db8:f::/64',
|
||||
RouteRule.IP_FROM: "2001:db8:a::/64",
|
||||
RouteRule.IP_TO: "2001:db8:f::/64",
|
||||
RouteRule.ROUTE_TABLE: IPV6_ROUTE_TABLE_ID1,
|
||||
},
|
||||
{
|
||||
RouteRule.IP_FROM: '203.0.113.0/24',
|
||||
RouteRule.IP_TO: '192.0.2.0/24',
|
||||
RouteRule.IP_FROM: "203.0.113.0/24",
|
||||
RouteRule.IP_TO: "192.0.2.0/24",
|
||||
RouteRule.ROUTE_TABLE: IPV4_ROUTE_TABLE_ID1,
|
||||
},
|
||||
]
|
||||
@ -611,13 +611,13 @@ def test_route_rule_add_without_route_table(route_rule_test_env):
|
||||
state = route_rule_test_env
|
||||
rules = [
|
||||
{
|
||||
RouteRule.IP_FROM: '2001:db8:a::/64',
|
||||
RouteRule.IP_TO: '2001:db8:f::/64',
|
||||
RouteRule.IP_FROM: "2001:db8:a::/64",
|
||||
RouteRule.IP_TO: "2001:db8:f::/64",
|
||||
RouteRule.PRIORITY: 1000,
|
||||
},
|
||||
{
|
||||
RouteRule.IP_FROM: '203.0.113.0/24',
|
||||
RouteRule.IP_TO: '192.0.2.0/24',
|
||||
RouteRule.IP_FROM: "203.0.113.0/24",
|
||||
RouteRule.IP_TO: "192.0.2.0/24",
|
||||
RouteRule.PRIORITY: 1000,
|
||||
},
|
||||
]
|
||||
|
@ -32,7 +32,7 @@ SRIOV_CONFIG = {Ethernet.SRIOV_SUBTREE: {Ethernet.SRIOV.TOTAL_VFS: 0}}
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotSupportedError,
|
||||
reason='The device does not support SR-IOV.',
|
||||
reason="The device does not support SR-IOV.",
|
||||
)
|
||||
def test_sriov_zero_vfs(sriov_interface):
|
||||
assertlib.assert_state(sriov_interface)
|
||||
@ -40,7 +40,7 @@ def test_sriov_zero_vfs(sriov_interface):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotSupportedError,
|
||||
reason='The device does not support SR-IOV.',
|
||||
reason="The device does not support SR-IOV.",
|
||||
)
|
||||
def test_sriov_increase_vfs(sriov_interface):
|
||||
eth_config = sriov_interface[Interface.KEY][0][Ethernet.CONFIG_SUBTREE]
|
||||
@ -51,7 +51,7 @@ def test_sriov_increase_vfs(sriov_interface):
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotSupportedError,
|
||||
reason='The device does not support SR-IOV.',
|
||||
reason="The device does not support SR-IOV.",
|
||||
)
|
||||
def test_sriov_decrease_vfs(sriov_interface):
|
||||
eth_config = sriov_interface[Interface.KEY][0][Ethernet.CONFIG_SUBTREE]
|
||||
|
@ -31,16 +31,16 @@ from .testlib import statelib
|
||||
from .testlib.iproutelib import ip_monitor_assert_stable_link_up
|
||||
|
||||
# TEST-NET addresses: https://tools.ietf.org/html/rfc5737#section-3
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV4_ADDRESS2 = '192.0.2.252'
|
||||
IPV4_ADDRESS3 = '198.51.100.249'
|
||||
IPV4_ADDRESS4 = '198.51.100.250'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
IPV4_ADDRESS2 = "192.0.2.252"
|
||||
IPV4_ADDRESS3 = "198.51.100.249"
|
||||
IPV4_ADDRESS4 = "198.51.100.250"
|
||||
# IPv6 Address Prefix Reserved for Documentation:
|
||||
# https://tools.ietf.org/html/rfc3849
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV6_ADDRESS2 = '2001:db8:2::1'
|
||||
IPV6_LINK_LOCAL_ADDRESS1 = 'fe80::1'
|
||||
IPV6_LINK_LOCAL_ADDRESS2 = 'fe80::2'
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
IPV6_ADDRESS2 = "2001:db8:2::1"
|
||||
IPV6_LINK_LOCAL_ADDRESS1 = "fe80::1"
|
||||
IPV6_LINK_LOCAL_ADDRESS2 = "fe80::2"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -48,7 +48,7 @@ def setup_eth1_ipv4(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -71,7 +71,7 @@ def setup_eth1_ipv6(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -96,7 +96,7 @@ def setup_eth1_ipv6_disable(eth1_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
|
||||
@ -109,7 +109,7 @@ def setup_eth1_ipv6_disable(eth1_up):
|
||||
|
||||
|
||||
def test_add_static_ipv4_with_full_state(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
|
||||
eth1_desired_state[Interface.STATE] = InterfaceState.UP
|
||||
@ -129,7 +129,7 @@ def test_add_static_ipv4_with_min_state(eth2_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -153,7 +153,7 @@ def test_remove_static_ipv4(setup_eth1_ipv4):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV4: {InterfaceIPv4.ENABLED: False},
|
||||
}
|
||||
@ -169,7 +169,7 @@ def test_edit_static_ipv4_address_and_prefix(setup_eth1_ipv4):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -196,7 +196,7 @@ def test_add_ifaces_with_same_static_ipv4_address_in_one_transaction(
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -210,7 +210,7 @@ def test_add_ifaces_with_same_static_ipv4_address_in_one_transaction(
|
||||
},
|
||||
},
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -237,7 +237,7 @@ def test_add_iface_with_same_static_ipv4_address_to_existing(
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV4: {
|
||||
@ -258,7 +258,7 @@ def test_add_iface_with_same_static_ipv4_address_to_existing(
|
||||
|
||||
|
||||
def test_add_static_ipv6_with_full_state(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.STATE] = InterfaceState.UP
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ENABLED] = True
|
||||
@ -278,7 +278,7 @@ def test_add_static_ipv6_with_full_state(eth1_up):
|
||||
|
||||
|
||||
def test_add_static_ipv6_with_link_local(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.STATE] = InterfaceState.UP
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ENABLED] = True
|
||||
@ -296,7 +296,7 @@ def test_add_static_ipv6_with_link_local(eth1_up):
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
# Make sure only the link local address got ignored.
|
||||
cur_state = statelib.show_only(('eth1',))
|
||||
cur_state = statelib.show_only(("eth1",))
|
||||
eth1_cur_state = cur_state[Interface.KEY][0]
|
||||
assert (
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ADDRESS][0]
|
||||
@ -309,7 +309,7 @@ def test_add_static_ipv6_with_link_local(eth1_up):
|
||||
|
||||
|
||||
def test_add_static_ipv6_with_link_local_only(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.STATE] = InterfaceState.UP
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ENABLED] = True
|
||||
@ -327,7 +327,7 @@ def test_add_static_ipv6_with_link_local_only(eth1_up):
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
# Make sure the link local address got ignored.
|
||||
cur_state = statelib.show_only(('eth1',))
|
||||
cur_state = statelib.show_only(("eth1",))
|
||||
eth1_cur_state = cur_state[Interface.KEY][0]
|
||||
assert (
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ADDRESS][0]
|
||||
@ -340,14 +340,14 @@ def test_add_static_ipv6_with_link_local_only(eth1_up):
|
||||
|
||||
|
||||
def test_add_static_ipv6_with_no_address(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
eth1_desired_state[Interface.STATE] = InterfaceState.UP
|
||||
eth1_desired_state[Interface.IPV6][InterfaceIPv6.ENABLED] = True
|
||||
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
cur_state = statelib.show_only(('eth1',))
|
||||
cur_state = statelib.show_only(("eth1",))
|
||||
eth1_cur_state = cur_state[Interface.KEY][0]
|
||||
# Should have at least 1 link-local address.
|
||||
assert len(eth1_cur_state[Interface.IPV6][InterfaceIPv6.ADDRESS]) >= 1
|
||||
@ -357,7 +357,7 @@ def test_add_static_ipv6_with_min_state(eth2_up):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -381,7 +381,7 @@ def test_disable_static_ipv6(setup_eth1_ipv6):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
|
||||
}
|
||||
@ -397,10 +397,10 @@ def test_disable_static_ipv6_and_rollback(setup_eth1_ipv6):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV6: {InterfaceIPv6.ENABLED: False},
|
||||
'foo': 'bad_value',
|
||||
"foo": "bad_value",
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -415,7 +415,7 @@ def test_enable_ipv6_and_rollback_to_disable_ipv6(setup_eth1_ipv6_disable):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV6: {
|
||||
InterfaceIPv6.ENABLED: True,
|
||||
@ -426,7 +426,7 @@ def test_enable_ipv6_and_rollback_to_disable_ipv6(setup_eth1_ipv6_disable):
|
||||
}
|
||||
],
|
||||
},
|
||||
'foo': 'bad_value',
|
||||
"foo": "bad_value",
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -442,7 +442,7 @@ def test_edit_static_ipv6_address_and_prefix(setup_eth1_ipv6):
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -460,7 +460,7 @@ def test_edit_static_ipv6_address_and_prefix(setup_eth1_ipv6):
|
||||
|
||||
libnmstate.apply(desired_state)
|
||||
eth1_desired_state = desired_state[Interface.KEY][0]
|
||||
current_state = statelib.show_only(('eth1',))
|
||||
current_state = statelib.show_only(("eth1",))
|
||||
|
||||
eth1_current_state = current_state[Interface.KEY][0]
|
||||
|
||||
@ -481,7 +481,7 @@ def test_add_ifaces_with_same_static_ipv6_address_in_one_transaction(
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth1',
|
||||
Interface.NAME: "eth1",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -495,7 +495,7 @@ def test_add_ifaces_with_same_static_ipv6_address_in_one_transaction(
|
||||
},
|
||||
},
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -522,7 +522,7 @@ def test_add_iface_with_same_static_ipv6_address_to_existing(
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.IPV6: {
|
||||
@ -543,7 +543,7 @@ def test_add_iface_with_same_static_ipv6_address_to_existing(
|
||||
|
||||
|
||||
def test_add_iface_with_static_ipv6_expanded_format(eth1_up):
|
||||
ipv6_addr_lead_zeroes = '2001:0db8:85a3:0000:0000:8a2e:0370:7331'
|
||||
ipv6_addr_lead_zeroes = "2001:0db8:85a3:0000:0000:8a2e:0370:7331"
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
@ -566,7 +566,7 @@ def test_add_iface_with_static_ipv6_expanded_format(eth1_up):
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
|
||||
@ip_monitor_assert_stable_link_up('eth1')
|
||||
@ip_monitor_assert_stable_link_up("eth1")
|
||||
def test_modify_ipv6_with_reapply(setup_eth1_ipv6):
|
||||
ipv6_addr = IPV6_ADDRESS2
|
||||
ipv6_state = setup_eth1_ipv6[Interface.KEY][0][Interface.IPV6]
|
||||
|
@ -26,7 +26,7 @@ from libnmstate.schema import InterfaceType
|
||||
from libnmstate.schema import Team
|
||||
|
||||
|
||||
TEAM0 = 'team0'
|
||||
TEAM0 = "team0"
|
||||
|
||||
TEAM0_STATE = {
|
||||
Interface.KEY: [
|
||||
@ -34,7 +34,7 @@ TEAM0_STATE = {
|
||||
Interface.NAME: TEAM0,
|
||||
Interface.TYPE: InterfaceType.TEAM,
|
||||
Team.CONFIG_SUBTREE: {
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: 'eth1'}]
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: "eth1"}]
|
||||
},
|
||||
}
|
||||
]
|
||||
@ -43,7 +43,7 @@ TEAM0_STATE = {
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
reason='Team interface is not supported yet',
|
||||
reason="Team interface is not supported yet",
|
||||
strict=True,
|
||||
)
|
||||
def test_sriov_not_implemented():
|
||||
|
@ -19,4 +19,4 @@
|
||||
|
||||
import pytest
|
||||
|
||||
pytest.register_assert_rewrite(__name__ + '.assertlib')
|
||||
pytest.register_assert_rewrite(__name__ + ".assertlib")
|
||||
|
@ -52,7 +52,7 @@ def exec_cmd(cmd, env=None, stdin=None):
|
||||
|
||||
logging.debug(_retcode_log_line(p.returncode, err=err))
|
||||
|
||||
return (p.returncode, out.decode('utf-8'), err.decode('utf-8'))
|
||||
return (p.returncode, out.decode("utf-8"), err.decode("utf-8"))
|
||||
|
||||
|
||||
def command_log_line(args, cwd=None):
|
||||
@ -60,7 +60,7 @@ def command_log_line(args, cwd=None):
|
||||
|
||||
|
||||
def format_exec_cmd_result(result):
|
||||
return 'rc={}, out={}, err={}'.format(*result)
|
||||
return "rc={}, out={}, err={}".format(*result)
|
||||
|
||||
|
||||
def _retcode_log_line(code, err=None):
|
||||
@ -76,13 +76,13 @@ def _list2cmdline(args):
|
||||
"""
|
||||
parts = []
|
||||
for arg in args:
|
||||
if _needs_quoting(arg) or arg == '':
|
||||
if _needs_quoting(arg) or arg == "":
|
||||
arg = "'" + arg.replace("'", r"'\''") + "'"
|
||||
parts.append(arg)
|
||||
return ' '.join(parts)
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
# This function returns truthy value if its argument contains unsafe characters
|
||||
# for including in a command passed to the shell. The safe characters were
|
||||
# stolen from pipes._safechars.
|
||||
_needs_quoting = re.compile(r'[^A-Za-z0-9_%+,\-./:=@]').search
|
||||
_needs_quoting = re.compile(r"[^A-Za-z0-9_%+,\-./:=@]").search
|
||||
|
@ -21,4 +21,4 @@ import os
|
||||
|
||||
|
||||
def is_fedora():
|
||||
return os.path.exists('/etc/fedora-release')
|
||||
return os.path.exists("/etc/fedora-release")
|
||||
|
@ -62,12 +62,12 @@ def find_examples_dir():
|
||||
Look recursively for the directory containing the examples
|
||||
"""
|
||||
|
||||
path = ''
|
||||
parent = '../'
|
||||
rootdir = '/'
|
||||
path = ""
|
||||
parent = "../"
|
||||
rootdir = "/"
|
||||
examples = None
|
||||
for _ in range(PATH_MAX // len('x/')):
|
||||
maybe_examples = os.path.abspath(os.path.join(path, 'examples'))
|
||||
for _ in range(PATH_MAX // len("x/")):
|
||||
maybe_examples = os.path.abspath(os.path.join(path, "examples"))
|
||||
if os.path.isdir(maybe_examples):
|
||||
examples = maybe_examples
|
||||
break
|
||||
@ -80,4 +80,4 @@ def find_examples_dir():
|
||||
if examples:
|
||||
return examples
|
||||
else:
|
||||
raise RuntimeError('Cannot find examples directory')
|
||||
raise RuntimeError("Cannot find examples directory")
|
||||
|
@ -38,10 +38,10 @@ def ip_monitor_assert_stable_link_up(dev, timeout=10):
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def wrapper_ip_monitor(*args, **kwargs):
|
||||
with ip_monitor('link', dev, timeout) as result:
|
||||
with ip_monitor("link", dev, timeout) as result:
|
||||
func(*args, **kwargs)
|
||||
assert len(get_non_up_events(result, dev)) == 0, (
|
||||
'result: ' + result.out
|
||||
"result: " + result.out
|
||||
)
|
||||
|
||||
return wrapper_ip_monitor
|
||||
@ -53,7 +53,7 @@ def ip_monitor_assert_stable_link_up(dev, timeout=10):
|
||||
def ip_monitor(object_type, dev, timeout=10):
|
||||
result = IpMonitorResult()
|
||||
|
||||
cmds = 'timeout {} ip monitor {} dev {}'.format(timeout, object_type, dev)
|
||||
cmds = "timeout {} ip monitor {} dev {}".format(timeout, object_type, dev)
|
||||
|
||||
def run():
|
||||
result.popen = subprocess.Popen(
|
||||
@ -65,14 +65,14 @@ def ip_monitor(object_type, dev, timeout=10):
|
||||
env=None,
|
||||
)
|
||||
result.out, result.err = result.popen.communicate(None)
|
||||
result.out = result.out.decode('utf-8')
|
||||
result.err = result.err.decode('utf-8')
|
||||
result.out = result.out.decode("utf-8")
|
||||
result.err = result.err.decode("utf-8")
|
||||
|
||||
def finalize():
|
||||
if result.popen:
|
||||
result.popen.terminate()
|
||||
|
||||
with _thread(run, 'ip-monitor', teardown_cb=finalize):
|
||||
with _thread(run, "ip-monitor", teardown_cb=finalize):
|
||||
# Let the ip monitor thread start before proceeding to the action.
|
||||
time.sleep(1)
|
||||
yield result
|
||||
@ -86,7 +86,7 @@ def get_non_up_events(result, dev):
|
||||
:return: List of non UP events
|
||||
"""
|
||||
return [
|
||||
l for l in result.out.split('\n') if 'state UP' not in l and dev in l
|
||||
l for l in result.out.split("\n") if "state UP" not in l and dev in l
|
||||
]
|
||||
|
||||
|
||||
|
@ -26,44 +26,44 @@ from . import cmd as libcmd
|
||||
|
||||
def ip_rule_exist_in_os(ip_from, ip_to, priority, table):
|
||||
expected_rule = locals()
|
||||
logging.debug('Checking ip rule for {}'.format(expected_rule))
|
||||
cmds = ['ip']
|
||||
logging.debug("Checking ip rule for {}".format(expected_rule))
|
||||
cmds = ["ip"]
|
||||
if (ip_from and iplib.is_ipv6_address(ip_from)) or (
|
||||
ip_to and iplib.is_ipv6_address(ip_to)
|
||||
):
|
||||
cmds.append('-6')
|
||||
result = libcmd.exec_cmd(cmds + ['--json', 'rule'])
|
||||
logging.debug(f'Current ip rules in OS: {result[1]}')
|
||||
cmds.append("-6")
|
||||
result = libcmd.exec_cmd(cmds + ["--json", "rule"])
|
||||
logging.debug(f"Current ip rules in OS: {result[1]}")
|
||||
assert result[0] == 0
|
||||
current_rules = json.loads(result[1])
|
||||
found = True
|
||||
for rule in current_rules:
|
||||
if rule.get('src') == 'all' or rule.get('dst') == 'all':
|
||||
if rule.get("src") == "all" or rule.get("dst") == "all":
|
||||
continue
|
||||
|
||||
if rule.get('table') == 'main':
|
||||
rule['table'] = f'{iplib.KERNEL_MAIN_ROUTE_TABLE_ID}'
|
||||
if rule.get("table") == "main":
|
||||
rule["table"] = f"{iplib.KERNEL_MAIN_ROUTE_TABLE_ID}"
|
||||
|
||||
logging.debug(f'Checking ip rule is OS: {rule}')
|
||||
logging.debug(f"Checking ip rule is OS: {rule}")
|
||||
found = True
|
||||
if ip_from and ip_from != iplib.to_ip_address_full(
|
||||
rule['src'], rule.get('srclen')
|
||||
rule["src"], rule.get("srclen")
|
||||
):
|
||||
found = False
|
||||
continue
|
||||
if ip_to and ip_to != iplib.to_ip_address_full(
|
||||
rule['dst'], rule.get('dstlen')
|
||||
rule["dst"], rule.get("dstlen")
|
||||
):
|
||||
found = False
|
||||
continue
|
||||
if priority is not None and rule['priority'] != priority:
|
||||
if priority is not None and rule["priority"] != priority:
|
||||
found = False
|
||||
continue
|
||||
if table is not None and rule['table'] != f'{table}':
|
||||
if table is not None and rule["table"] != f"{table}":
|
||||
found = False
|
||||
continue
|
||||
if found:
|
||||
break
|
||||
if not found:
|
||||
logging.debug(f'Failed to find expected ip rule: {expected_rule}')
|
||||
logging.debug(f"Failed to find expected ip rule: {expected_rule}")
|
||||
assert found
|
||||
|
@ -271,7 +271,7 @@ def _is_ipv6_link_local(ip, prefix):
|
||||
"""
|
||||
The IPv6 link local address range is fe80::/10.
|
||||
"""
|
||||
return ip[:3] in ['fe8', 'fe9', 'fea', 'feb'] and prefix >= 10
|
||||
return ip[:3] in ["fe8", "fe9", "fea", "feb"] and prefix >= 10
|
||||
|
||||
|
||||
def _state_match(desire, current):
|
||||
|
@ -28,7 +28,7 @@ from libnmstate.schema import VXLAN
|
||||
|
||||
class VxlanState:
|
||||
def __init__(self, id, base_if, remote, destination_port=4789):
|
||||
self.name = f'{base_if}.{id}'
|
||||
self.name = f"{base_if}.{id}"
|
||||
self.id = id
|
||||
self.base_if = base_if
|
||||
self.remote = remote
|
||||
|
@ -34,8 +34,8 @@ from .testlib import statelib
|
||||
from .testlib.assertlib import assert_mac_address
|
||||
from .testlib.vlan import vlan_interface
|
||||
|
||||
VLAN_IFNAME = 'eth1.101'
|
||||
VLAN2_IFNAME = 'eth1.102'
|
||||
VLAN_IFNAME = "eth1.101"
|
||||
VLAN2_IFNAME = "eth1.102"
|
||||
|
||||
|
||||
def test_add_and_remove_vlan(eth1_up):
|
||||
@ -74,7 +74,7 @@ def test_add_and_remove_two_vlans_on_same_iface(eth1_up):
|
||||
|
||||
|
||||
def test_two_vlans_on_eth1_change_mtu(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_state = desired_state[Interface.KEY][0]
|
||||
vlans_state = create_two_vlans_state()
|
||||
desired_state[Interface.KEY].extend(vlans_state[Interface.KEY])
|
||||
@ -96,7 +96,7 @@ def test_two_vlans_on_eth1_change_mtu(eth1_up):
|
||||
|
||||
|
||||
def test_two_vlans_on_eth1_change_base_iface_mtu(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
eth1_state = desired_state[Interface.KEY][0]
|
||||
vlans_state = create_two_vlans_state()
|
||||
desired_state[Interface.KEY].extend(vlans_state[Interface.KEY])
|
||||
@ -111,7 +111,7 @@ def test_two_vlans_on_eth1_change_base_iface_mtu(eth1_up):
|
||||
|
||||
|
||||
def test_two_vlans_on_eth1_change_mtu_rollback(eth1_up):
|
||||
desired_state = statelib.show_only(('eth1',))
|
||||
desired_state = statelib.show_only(("eth1",))
|
||||
vlans_state = create_two_vlans_state()
|
||||
desired_state[Interface.KEY].extend(vlans_state[Interface.KEY])
|
||||
for iface in desired_state[Interface.KEY]:
|
||||
@ -131,7 +131,7 @@ def test_rollback_for_vlans(eth1_up):
|
||||
current_state = libnmstate.show()
|
||||
desired_state = create_two_vlans_state()
|
||||
|
||||
desired_state[Interface.KEY][1]['invalid_key'] = 'foo'
|
||||
desired_state[Interface.KEY][1]["invalid_key"] = "foo"
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
@ -161,11 +161,11 @@ def test_set_vlan_iface_down(eth1_up):
|
||||
|
||||
|
||||
def test_add_new_base_iface_with_vlan():
|
||||
iface_base = 'dummy00'
|
||||
iface_base = "dummy00"
|
||||
desired_state = {
|
||||
Interface.KEY: [
|
||||
{
|
||||
Interface.NAME: 'dummy00.101',
|
||||
Interface.NAME: "dummy00.101",
|
||||
Interface.TYPE: InterfaceType.VLAN,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
VLAN.CONFIG_SUBTREE: {
|
||||
@ -220,13 +220,13 @@ def create_two_vlans_state():
|
||||
Interface.NAME: VLAN_IFNAME,
|
||||
Interface.TYPE: InterfaceType.VLAN,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
VLAN.CONFIG_SUBTREE: {VLAN.ID: 101, VLAN.BASE_IFACE: 'eth1'},
|
||||
VLAN.CONFIG_SUBTREE: {VLAN.ID: 101, VLAN.BASE_IFACE: "eth1"},
|
||||
},
|
||||
{
|
||||
Interface.NAME: VLAN2_IFNAME,
|
||||
Interface.TYPE: InterfaceType.VLAN,
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
VLAN.CONFIG_SUBTREE: {VLAN.ID: 102, VLAN.BASE_IFACE: 'eth1'},
|
||||
VLAN.CONFIG_SUBTREE: {VLAN.ID: 102, VLAN.BASE_IFACE: "eth1"},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ VXLAN2_ID = 202
|
||||
def test_add_and_remove_vxlan(eth1_up):
|
||||
ifname = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
with vxlan_interfaces(
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote='192.168.100.1')
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote="192.168.100.1")
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
@ -55,8 +55,8 @@ def test_add_and_remove_vxlan(eth1_up):
|
||||
def test_add_and_remove_two_vxlans_on_same_iface(eth1_up):
|
||||
ifname = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
with vxlan_interfaces(
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote='192.168.100.1'),
|
||||
VxlanState(id=VXLAN2_ID, base_if=ifname, remote='192.168.100.2'),
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote="192.168.100.1"),
|
||||
VxlanState(id=VXLAN2_ID, base_if=ifname, remote="192.168.100.2"),
|
||||
) as desired_state:
|
||||
assertlib.assert_state(desired_state)
|
||||
|
||||
@ -71,11 +71,11 @@ def test_rollback_for_vxlans(eth1_up):
|
||||
current_state = libnmstate.show()
|
||||
desired_state = vxlans_up(
|
||||
[
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote='192.168.100.1'),
|
||||
VxlanState(id=VXLAN2_ID, base_if=ifname, remote='192.168.100.2'),
|
||||
VxlanState(id=VXLAN1_ID, base_if=ifname, remote="192.168.100.1"),
|
||||
VxlanState(id=VXLAN2_ID, base_if=ifname, remote="192.168.100.2"),
|
||||
]
|
||||
)
|
||||
desired_state[Interface.KEY][1]['invalid_key'] = 'foo'
|
||||
desired_state[Interface.KEY][1]["invalid_key"] = "foo"
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
libnmstate.apply(desired_state)
|
||||
|
||||
@ -86,7 +86,7 @@ def test_rollback_for_vxlans(eth1_up):
|
||||
|
||||
def test_set_vxlan_iface_down(eth1_up):
|
||||
ifname = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=ifname, remote='192.168.100.1')
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=ifname, remote="192.168.100.1")
|
||||
with vxlan_interfaces(vxlan):
|
||||
desired_state = vxlans_down([vxlan])
|
||||
libnmstate.apply(desired_state)
|
||||
@ -94,12 +94,12 @@ def test_set_vxlan_iface_down(eth1_up):
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason='https://bugzilla.redhat.com/show_bug.cgi?id=1772382', strict=False
|
||||
reason="https://bugzilla.redhat.com/show_bug.cgi?id=1772382", strict=False
|
||||
)
|
||||
def test_add_new_bond_iface_with_vxlan(eth1_up):
|
||||
eth_name = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
bond_name = 'bond1'
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=bond_name, remote='192.168.100.2')
|
||||
bond_name = "bond1"
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=bond_name, remote="192.168.100.2")
|
||||
with bond_interface(
|
||||
name=bond_name, slaves=[eth_name], extra_iface_state=None, create=False
|
||||
) as bond_desired_state:
|
||||
@ -116,10 +116,10 @@ def test_add_new_bond_iface_with_vxlan(eth1_up):
|
||||
|
||||
def test_show_vxlan_with_no_remote(eth1_up):
|
||||
eth_name = eth1_up[Interface.KEY][0][Interface.NAME]
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=eth_name, remote='')
|
||||
vxlan = VxlanState(id=VXLAN1_ID, base_if=eth_name, remote="")
|
||||
add_vxlan_cmd = (
|
||||
f'ip link add {vxlan.name} type vxlan id {vxlan.id}'
|
||||
f' dstport {vxlan.destination_port} dev {eth_name}'.split()
|
||||
f"ip link add {vxlan.name} type vxlan id {vxlan.id}"
|
||||
f" dstport {vxlan.destination_port} dev {eth_name}".split()
|
||||
)
|
||||
try:
|
||||
ret = exec_cmd(add_vxlan_cmd)
|
||||
|
@ -38,14 +38,14 @@ from libnmstate.schema import RouteRule
|
||||
TYPE_BOND = InterfaceType.BOND
|
||||
TYPE_OVS_BR = InterfaceType.OVS_BRIDGE
|
||||
|
||||
BOND_NAME = 'bond99'
|
||||
OVS_NAME = 'ovs-br99'
|
||||
TEST_IFACE1 = 'eth1'
|
||||
BOND_NAME = "bond99"
|
||||
OVS_NAME = "ovs-br99"
|
||||
TEST_IFACE1 = "eth1"
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def nm_mock():
|
||||
with mock.patch.object(metadata, 'nm') as m:
|
||||
with mock.patch.object(metadata, "nm") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@ -76,19 +76,19 @@ class TestDesiredStateBondMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State({})
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -99,26 +99,26 @@ class TestDesiredStateBondMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1'])
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"])
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces['eth1'] = {'name': 'eth1', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth1"] = {"name": "eth1", "state": "up"}
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -129,16 +129,16 @@ class TestDesiredStateBondMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': BOND_NAME, 'type': TYPE_BOND, 'state': 'down'}
|
||||
{"name": BOND_NAME, "type": TYPE_BOND, "state": "down"}
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -154,21 +154,21 @@ class TestDesiredStateBondMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{Interface.KEY: [{'name': 'eth0', 'type': 'unknown'}]}
|
||||
{Interface.KEY: [{"name": "eth0", "type": "unknown"}]}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -177,23 +177,23 @@ class TestDesiredStateBondMetadata:
|
||||
|
||||
def test_bond_removing_slaves(self):
|
||||
desired_state = state.State(
|
||||
{Interface.KEY: [create_bond_state_dict(BOND_NAME, ['eth0'])]}
|
||||
{Interface.KEY: [create_bond_state_dict(BOND_NAME, ["eth0"])]}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces['eth1'] = {'name': 'eth1'}
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth1"] = {"name": "eth1"}
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -204,23 +204,23 @@ class TestDesiredStateBondMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'type': 'unknown', 'fookey': 'fooval'}
|
||||
{"name": "eth0", "type": "unknown", "fookey": "fooval"}
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -228,24 +228,24 @@ class TestDesiredStateBondMetadata:
|
||||
assert current_state == expected_cstate
|
||||
|
||||
def test_bond_reusing_slave_used_by_existing_bond(self):
|
||||
BOND2_NAME = 'bond88'
|
||||
BOND2_NAME = "bond88"
|
||||
desired_state = state.State(
|
||||
{Interface.KEY: [create_bond_state_dict(BOND2_NAME, ['eth0'])]}
|
||||
{Interface.KEY: [create_bond_state_dict(BOND2_NAME, ["eth0"])]}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND2_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND2_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -253,33 +253,33 @@ class TestDesiredStateBondMetadata:
|
||||
assert current_state == expected_cstate
|
||||
|
||||
def test_swap_slaves_between_bonds(self):
|
||||
BOND2_NAME = 'bond88'
|
||||
BOND2_NAME = "bond88"
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth1']),
|
||||
create_bond_state_dict(BOND2_NAME, ['eth0']),
|
||||
create_bond_state_dict(BOND_NAME, ["eth1"]),
|
||||
create_bond_state_dict(BOND2_NAME, ["eth0"]),
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0']),
|
||||
create_bond_state_dict(BOND2_NAME, ['eth1']),
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0"]),
|
||||
create_bond_state_dict(BOND2_NAME, ["eth1"]),
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth1'] = {'name': 'eth1', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = BOND2_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth1"] = {"name": "eth1", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = BOND2_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = BOND_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_BOND
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -295,7 +295,7 @@ class TestDesiredStateBondMetadata:
|
||||
Interface.STATE: InterfaceState.ABSENT,
|
||||
},
|
||||
{
|
||||
Interface.NAME: 'eth0',
|
||||
Interface.NAME: "eth0",
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.TYPE: InterfaceType.UNKNOWN,
|
||||
},
|
||||
@ -305,9 +305,9 @@ class TestDesiredStateBondMetadata:
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
create_bond_state_dict(BOND_NAME, ['eth0', 'eth1']),
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
create_bond_state_dict(BOND_NAME, ["eth0", "eth1"]),
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -323,10 +323,10 @@ class TestDesiredStateBondMetadata:
|
||||
def create_bond_state_dict(name, slaves=None):
|
||||
slaves = slaves or []
|
||||
return {
|
||||
'name': name,
|
||||
'type': TYPE_BOND,
|
||||
'state': 'up',
|
||||
'link-aggregation': {'mode': 'balance-rr', 'slaves': slaves},
|
||||
"name": name,
|
||||
"type": TYPE_BOND,
|
||||
"state": "up",
|
||||
"link-aggregation": {"mode": "balance-rr", "slaves": slaves},
|
||||
}
|
||||
|
||||
|
||||
@ -336,31 +336,31 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State({})
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][0]
|
||||
expected_dstate.interfaces['eth1'][
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][0]
|
||||
expected_dstate.interfaces["eth1"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][1]
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][1]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -372,11 +372,11 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
}
|
||||
]
|
||||
@ -385,25 +385,25 @@ class TestDesiredStateOvsMetadata:
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth1'] = {'name': 'eth1', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth1"] = {"name": "eth1", "state": "up"}
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][0]
|
||||
expected_dstate.interfaces['eth1'][
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][0]
|
||||
expected_dstate.interfaces["eth1"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][1]
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][1]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -414,7 +414,7 @@ class TestDesiredStateOvsMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': OVS_NAME, 'type': TYPE_OVS_BR, 'state': 'down'}
|
||||
{"name": OVS_NAME, "type": TYPE_OVS_BR, "state": "down"}
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -422,15 +422,15 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -447,37 +447,37 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'}
|
||||
{"name": "eth0", "state": "up", "type": "unknown"}
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth1'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth1"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][0]
|
||||
expected_dstate.interfaces['eth1'][
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][0]
|
||||
expected_dstate.interfaces["eth1"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][1]
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][1]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -489,10 +489,10 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {'port': [{'name': 'eth0'}]},
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {"port": [{"name": "eth0"}]},
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -501,27 +501,27 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth1'] = {'name': 'eth1'}
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth1"] = {"name": "eth1"}
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS_NAME]['bridge']['port'][0]
|
||||
] = desired_state.interfaces[OVS_NAME]["bridge"]["port"][0]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -532,7 +532,7 @@ class TestDesiredStateOvsMetadata:
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'type': 'unknown', 'fookey': 'fooval'}
|
||||
{"name": "eth0", "type": "unknown", "fookey": "fooval"}
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -540,25 +540,25 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth0', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'type': 'unknown'},
|
||||
{"name": "eth0", "type": "unknown"},
|
||||
{"name": "eth1", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = current_state.interfaces[OVS_NAME]['bridge']['port'][0]
|
||||
] = current_state.interfaces[OVS_NAME]["bridge"]["port"][0]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -566,15 +566,15 @@ class TestDesiredStateOvsMetadata:
|
||||
assert current_state == expected_cstate
|
||||
|
||||
def test_ovs_reusing_slave_used_by_existing_bridge(self):
|
||||
OVS2_NAME = 'ovs-br88'
|
||||
OVS2_NAME = "ovs-br88"
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS2_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {'port': [{'name': 'eth0'}]},
|
||||
"name": OVS2_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {"port": [{"name": "eth0"}]},
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -583,26 +583,26 @@ class TestDesiredStateOvsMetadata:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': OVS_NAME,
|
||||
'type': TYPE_OVS_BR,
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0'}, {'name': 'eth1'}]
|
||||
"name": OVS_NAME,
|
||||
"type": TYPE_OVS_BR,
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0"}, {"name": "eth1"}]
|
||||
},
|
||||
},
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
expected_dstate = state.State(desired_state.state)
|
||||
expected_cstate = state.State(current_state.state)
|
||||
expected_dstate.interfaces['eth0'] = {'name': 'eth0', 'state': 'up'}
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER] = OVS2_NAME
|
||||
expected_dstate.interfaces['eth0'][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces['eth0'][
|
||||
expected_dstate.interfaces["eth0"] = {"name": "eth0", "state": "up"}
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER] = OVS2_NAME
|
||||
expected_dstate.interfaces["eth0"][metadata.MASTER_TYPE] = TYPE_OVS_BR
|
||||
expected_dstate.interfaces["eth0"][
|
||||
metadata.BRPORT_OPTIONS
|
||||
] = desired_state.interfaces[OVS2_NAME]['bridge']['port'][0]
|
||||
] = desired_state.interfaces[OVS2_NAME]["bridge"]["port"][0]
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
@ -646,27 +646,27 @@ class TestRouteMetadata:
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('foo')],
|
||||
Interface.KEY: [_create_interface_state("foo")],
|
||||
Route.KEY: {Route.CONFIG: [route0.to_dict()]},
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('boo')],
|
||||
Interface.KEY: [_create_interface_state("boo")],
|
||||
Route.KEY: {Route.CONFIG: []},
|
||||
}
|
||||
)
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
assert 'foo' in desired_state.interfaces
|
||||
assert metadata.ROUTES not in desired_state.interfaces['foo']
|
||||
assert "foo" in desired_state.interfaces
|
||||
assert metadata.ROUTES not in desired_state.interfaces["foo"]
|
||||
|
||||
def test_route_with_matching_desired_interface(self):
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: [route0.to_dict()]},
|
||||
}
|
||||
)
|
||||
@ -674,7 +674,7 @@ class TestRouteMetadata:
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
iface_state = desired_state.interfaces['eth1']
|
||||
iface_state = desired_state.interfaces["eth1"]
|
||||
(route_metadata,) = iface_state[Interface.IPV4][metadata.ROUTES]
|
||||
assert route0.to_dict() == route_metadata
|
||||
|
||||
@ -685,14 +685,14 @@ class TestRouteMetadata:
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: []},
|
||||
}
|
||||
)
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
iface_state = desired_state.interfaces['eth1']
|
||||
iface_state = desired_state.interfaces["eth1"]
|
||||
(route_metadata,) = iface_state[Interface.IPV4][metadata.ROUTES]
|
||||
assert route0.to_dict() == route_metadata
|
||||
|
||||
@ -701,7 +701,7 @@ class TestRouteMetadata:
|
||||
route1 = self._create_route1()
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {
|
||||
Route.CONFIG: [route0.to_dict(), route1.to_dict()]
|
||||
},
|
||||
@ -709,26 +709,26 @@ class TestRouteMetadata:
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth2')],
|
||||
Interface.KEY: [_create_interface_state("eth2")],
|
||||
Route.KEY: {Route.CONFIG: []},
|
||||
}
|
||||
)
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
iface0_state = desired_state.interfaces['eth1']
|
||||
iface1_state = desired_state.interfaces['eth2']
|
||||
iface0_state = desired_state.interfaces["eth1"]
|
||||
iface1_state = desired_state.interfaces["eth2"]
|
||||
(route0_metadata,) = iface0_state[Interface.IPV4][metadata.ROUTES]
|
||||
(route1_metadata,) = iface1_state[Interface.IPV6][metadata.ROUTES]
|
||||
assert route0.to_dict() == route0_metadata
|
||||
assert route1.to_dict() == route1_metadata
|
||||
|
||||
def _create_route0(self):
|
||||
return _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
return _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
|
||||
def _create_route1(self):
|
||||
return _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
|
||||
|
||||
@ -774,8 +774,8 @@ def test_dns_gen_metadata_static_gateway_ipv6_name_server_before_ipv4(
|
||||
nm_dns_mock,
|
||||
):
|
||||
dns_config = {
|
||||
DNS.SERVER: ['2001:4860:4860::8888', '8.8.8.8'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888", "8.8.8.8"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
}
|
||||
|
||||
desired_state = state.State(
|
||||
@ -789,13 +789,13 @@ def test_dns_gen_metadata_static_gateway_ipv6_name_server_before_ipv4(
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
ipv4_dns_config = {
|
||||
DNS.SERVER: ['8.8.8.8'],
|
||||
DNS.SERVER: ["8.8.8.8"],
|
||||
DNS.SEARCH: [],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE + 1,
|
||||
}
|
||||
ipv6_dns_config = {
|
||||
DNS.SERVER: ['2001:4860:4860::8888'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE,
|
||||
}
|
||||
iface_state = desired_state.interfaces[TEST_IFACE1]
|
||||
@ -807,8 +807,8 @@ def test_dns_gen_metadata_static_gateway_ipv6_name_server_after_ipv4(
|
||||
nm_dns_mock,
|
||||
):
|
||||
dns_config = {
|
||||
DNS.SERVER: ['8.8.8.8', '2001:4860:4860::8888'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["8.8.8.8", "2001:4860:4860::8888"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
}
|
||||
|
||||
desired_state = state.State(
|
||||
@ -822,12 +822,12 @@ def test_dns_gen_metadata_static_gateway_ipv6_name_server_after_ipv4(
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
ipv4_dns_config = {
|
||||
DNS.SERVER: ['8.8.8.8'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["8.8.8.8"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE,
|
||||
}
|
||||
ipv6_dns_config = {
|
||||
DNS.SERVER: ['2001:4860:4860::8888'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888"],
|
||||
DNS.SEARCH: [],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE + 1,
|
||||
}
|
||||
@ -838,8 +838,8 @@ def test_dns_gen_metadata_static_gateway_ipv6_name_server_after_ipv4(
|
||||
|
||||
def test_dns_metadata_interface_not_included_in_desire(nm_dns_mock):
|
||||
dns_config = {
|
||||
DNS.SERVER: ['2001:4860:4860::8888', '8.8.8.8'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888", "8.8.8.8"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
}
|
||||
|
||||
desired_state = state.State(
|
||||
@ -858,13 +858,13 @@ def test_dns_metadata_interface_not_included_in_desire(nm_dns_mock):
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
iface_state = desired_state.interfaces[TEST_IFACE1]
|
||||
ipv4_dns_config = {
|
||||
DNS.SERVER: ['8.8.8.8'],
|
||||
DNS.SERVER: ["8.8.8.8"],
|
||||
DNS.SEARCH: [],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE + 1,
|
||||
}
|
||||
ipv6_dns_config = {
|
||||
DNS.SERVER: ['2001:4860:4860::8888'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
nm_dns.DNS_METADATA_PRIORITY: nm_dns.DNS_PRIORITY_STATIC_BASE,
|
||||
}
|
||||
assert ipv4_dns_config == iface_state[Interface.IPV4][nm_dns.DNS_METADATA]
|
||||
@ -880,7 +880,7 @@ def _get_test_iface_states():
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.0.2.251',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.0.2.251",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -890,7 +890,7 @@ def _get_test_iface_states():
|
||||
Interface.IPV6: {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001:db8:1::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001:db8:1::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
}
|
||||
],
|
||||
@ -900,13 +900,13 @@ def _get_test_iface_states():
|
||||
},
|
||||
},
|
||||
{
|
||||
Interface.NAME: 'eth2',
|
||||
Interface.NAME: "eth2",
|
||||
Interface.STATE: InterfaceState.UP,
|
||||
Interface.TYPE: InterfaceType.ETHERNET,
|
||||
Interface.IPV4: {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '198.51.100.1',
|
||||
InterfaceIPv4.ADDRESS_IP: "198.51.100.1",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
}
|
||||
],
|
||||
@ -916,7 +916,7 @@ def _get_test_iface_states():
|
||||
Interface.IPV6: {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001:db8:2::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001:db8:2::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
}
|
||||
],
|
||||
@ -931,16 +931,16 @@ def _get_test_iface_states():
|
||||
def _gen_default_gateway_route(iface_name):
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 200,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: iface_name,
|
||||
Route.TABLE_ID: 54,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 201,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:2::f',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:2::f",
|
||||
Route.NEXT_HOP_INTERFACE: iface_name,
|
||||
Route.TABLE_ID: 54,
|
||||
},
|
||||
@ -986,43 +986,43 @@ class TestRouteRuleMetadata:
|
||||
def test_rule_with_no_matching_route_table(self):
|
||||
rule0 = self._create_rule0()
|
||||
route = _create_route(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
'eth1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
"eth1",
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE + 1,
|
||||
103,
|
||||
)
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: [route.to_dict()]},
|
||||
RouteRule.KEY: {RouteRule.CONFIG: [rule0.to_dict()]},
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: [route.to_dict()]},
|
||||
}
|
||||
)
|
||||
rule0 = self._create_rule0()
|
||||
route = _create_route(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
'eth1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
"eth1",
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE + 1,
|
||||
103,
|
||||
)
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: [route.to_dict()]},
|
||||
RouteRule.KEY: {RouteRule.CONFIG: [rule0.to_dict()]},
|
||||
}
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {Route.CONFIG: [route.to_dict()]},
|
||||
}
|
||||
)
|
||||
@ -1034,22 +1034,22 @@ class TestRouteRuleMetadata:
|
||||
rule0 = self._create_rule0()
|
||||
rule1 = self._create_rule1()
|
||||
route0 = _create_route(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
'eth1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
"eth1",
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE,
|
||||
103,
|
||||
)
|
||||
route1 = _create_route(
|
||||
'2001:db8:f::/64',
|
||||
'2001:db8:e::',
|
||||
'eth1',
|
||||
"2001:db8:f::/64",
|
||||
"2001:db8:e::",
|
||||
"eth1",
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE,
|
||||
103,
|
||||
)
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [_create_interface_state('eth1')],
|
||||
Interface.KEY: [_create_interface_state("eth1")],
|
||||
Route.KEY: {
|
||||
Route.CONFIG: [route0.to_dict(), route1.to_dict()]
|
||||
},
|
||||
@ -1062,7 +1062,7 @@ class TestRouteRuleMetadata:
|
||||
|
||||
metadata.generate_ifaces_metadata(desired_state, current_state)
|
||||
|
||||
iface_state = desired_state.interfaces['eth1']
|
||||
iface_state = desired_state.interfaces["eth1"]
|
||||
(rule0_metadata,) = iface_state[Interface.IPV4][
|
||||
metadata.ROUTE_RULES_METADATA
|
||||
]
|
||||
@ -1074,16 +1074,16 @@ class TestRouteRuleMetadata:
|
||||
|
||||
def _create_rule0(self):
|
||||
return _create_rule(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
103,
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE,
|
||||
)
|
||||
|
||||
def _create_rule1(self):
|
||||
return _create_rule(
|
||||
'2001:db8:a::/64',
|
||||
'2001:db8:1::a',
|
||||
"2001:db8:a::/64",
|
||||
"2001:db8:1::a",
|
||||
104,
|
||||
TestRouteRuleMetadata.TEST_ROUTE_TABLE,
|
||||
)
|
||||
|
@ -29,27 +29,27 @@ from libnmstate.schema import InterfaceIPv6
|
||||
from libnmstate.schema import InterfaceType
|
||||
|
||||
INTERFACES = Constants.INTERFACES
|
||||
BOND_TYPE = 'bond'
|
||||
BOND_TYPE = "bond"
|
||||
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def nmclient_mock():
|
||||
client_mock = mock.patch.object(netapplier.nmclient, 'client')
|
||||
mainloop_mock = mock.patch.object(netapplier.nmclient, 'mainloop')
|
||||
client_mock = mock.patch.object(netapplier.nmclient, "client")
|
||||
mainloop_mock = mock.patch.object(netapplier.nmclient, "mainloop")
|
||||
with client_mock, mainloop_mock:
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def netapplier_nm_mock():
|
||||
with mock.patch.object(netapplier, 'nm') as m:
|
||||
with mock.patch.object(netapplier, "nm") as m:
|
||||
m.applier.prepare_proxy_ifaces_desired_state.return_value = []
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def netinfo_nm_mock():
|
||||
with mock.patch.object(netapplier.netinfo, 'nm') as m:
|
||||
with mock.patch.object(netapplier.netinfo, "nm") as m:
|
||||
m.ipv4.get_routing_rule_config.return_value = []
|
||||
m.ipv6.get_routing_rule_config.return_value = []
|
||||
yield m
|
||||
@ -59,32 +59,32 @@ def test_iface_admin_state_change(netinfo_nm_mock, netapplier_nm_mock):
|
||||
current_config = {
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'foo',
|
||||
'type': InterfaceType.DUMMY,
|
||||
'state': 'up',
|
||||
'ipv4': {InterfaceIPv4.ENABLED: False},
|
||||
'ipv6': {InterfaceIPv6.ENABLED: False},
|
||||
"name": "foo",
|
||||
"type": InterfaceType.DUMMY,
|
||||
"state": "up",
|
||||
"ipv4": {InterfaceIPv4.ENABLED: False},
|
||||
"ipv6": {InterfaceIPv6.ENABLED: False},
|
||||
}
|
||||
]
|
||||
}
|
||||
desired_config = copy.deepcopy(current_config)
|
||||
|
||||
current_iface0 = current_config[INTERFACES][0]
|
||||
netinfo_nm_mock.device.list_devices.return_value = ['one-item']
|
||||
netinfo_nm_mock.device.list_devices.return_value = ["one-item"]
|
||||
netinfo_nm_mock.translator.Nm2Api.get_common_device_info.return_value = (
|
||||
current_iface0
|
||||
)
|
||||
netinfo_nm_mock.bond.is_bond_type_id.return_value = False
|
||||
netinfo_nm_mock.ovs.is_ovs_bridge_type_id.return_value = False
|
||||
netinfo_nm_mock.ovs.is_ovs_port_type_id.return_value = False
|
||||
netinfo_nm_mock.ipv4.get_info.return_value = current_iface0['ipv4']
|
||||
netinfo_nm_mock.ipv6.get_info.return_value = current_iface0['ipv6']
|
||||
netinfo_nm_mock.ipv4.get_info.return_value = current_iface0["ipv4"]
|
||||
netinfo_nm_mock.ipv6.get_info.return_value = current_iface0["ipv6"]
|
||||
netinfo_nm_mock.ipv4.get_route_running.return_value = []
|
||||
netinfo_nm_mock.ipv4.get_route_config.return_value = []
|
||||
netinfo_nm_mock.ipv6.get_route_running.return_value = []
|
||||
netinfo_nm_mock.ipv6.get_route_config.return_value = []
|
||||
|
||||
desired_config[INTERFACES][0]['state'] = 'down'
|
||||
desired_config[INTERFACES][0]["state"] = "down"
|
||||
netapplier.apply(desired_config, verify_change=False)
|
||||
|
||||
applier_mock = netapplier_nm_mock.applier
|
||||
@ -114,16 +114,16 @@ def test_add_new_bond(netinfo_nm_mock, netapplier_nm_mock):
|
||||
desired_config = {
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'bond99',
|
||||
'type': BOND_TYPE,
|
||||
'state': 'up',
|
||||
'link-aggregation': {
|
||||
'mode': 'balance-rr',
|
||||
'slaves': [],
|
||||
'options': {'miimon': 200},
|
||||
"name": "bond99",
|
||||
"type": BOND_TYPE,
|
||||
"state": "up",
|
||||
"link-aggregation": {
|
||||
"mode": "balance-rr",
|
||||
"slaves": [],
|
||||
"options": {"miimon": 200},
|
||||
},
|
||||
'ipv4': {},
|
||||
'ipv6': {},
|
||||
"ipv4": {},
|
||||
"ipv6": {},
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -141,41 +141,41 @@ def test_edit_existing_bond(netinfo_nm_mock, netapplier_nm_mock):
|
||||
current_config = {
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'bond99',
|
||||
'type': BOND_TYPE,
|
||||
'state': 'up',
|
||||
'link-aggregation': {
|
||||
'mode': 'balance-rr',
|
||||
'slaves': [],
|
||||
'options': {'miimon': '100'},
|
||||
"name": "bond99",
|
||||
"type": BOND_TYPE,
|
||||
"state": "up",
|
||||
"link-aggregation": {
|
||||
"mode": "balance-rr",
|
||||
"slaves": [],
|
||||
"options": {"miimon": "100"},
|
||||
},
|
||||
'ipv4': {InterfaceIPv4.ENABLED: False},
|
||||
'ipv6': {InterfaceIPv6.ENABLED: False},
|
||||
"ipv4": {InterfaceIPv4.ENABLED: False},
|
||||
"ipv6": {InterfaceIPv6.ENABLED: False},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
current_iface0 = current_config[INTERFACES][0]
|
||||
netinfo_nm_mock.device.list_devices.return_value = ['one-item']
|
||||
netinfo_nm_mock.device.list_devices.return_value = ["one-item"]
|
||||
netinfo_nm_mock.translator.Nm2Api.get_common_device_info.return_value = {
|
||||
'name': current_iface0['name'],
|
||||
'type': current_iface0['type'],
|
||||
'state': current_iface0['state'],
|
||||
"name": current_iface0["name"],
|
||||
"type": current_iface0["type"],
|
||||
"state": current_iface0["state"],
|
||||
}
|
||||
netinfo_nm_mock.bond.is_bond_type_id.return_value = True
|
||||
netinfo_nm_mock.translator.Nm2Api.get_bond_info.return_value = {
|
||||
'link-aggregation': current_iface0['link-aggregation']
|
||||
"link-aggregation": current_iface0["link-aggregation"]
|
||||
}
|
||||
netinfo_nm_mock.ipv4.get_info.return_value = current_iface0['ipv4']
|
||||
netinfo_nm_mock.ipv6.get_info.return_value = current_iface0['ipv6']
|
||||
netinfo_nm_mock.ipv4.get_info.return_value = current_iface0["ipv4"]
|
||||
netinfo_nm_mock.ipv6.get_info.return_value = current_iface0["ipv6"]
|
||||
netinfo_nm_mock.ipv4.get_route_running.return_value = []
|
||||
netinfo_nm_mock.ipv4.get_route_config.return_value = []
|
||||
netinfo_nm_mock.ipv6.get_route_running.return_value = []
|
||||
netinfo_nm_mock.ipv6.get_route_config.return_value = []
|
||||
|
||||
desired_config = copy.deepcopy(current_config)
|
||||
options = desired_config[INTERFACES][0]['link-aggregation']['options']
|
||||
options['miimon'] = 200
|
||||
options = desired_config[INTERFACES][0]["link-aggregation"]["options"]
|
||||
options["miimon"] = 200
|
||||
|
||||
netapplier.apply(desired_config, verify_change=False)
|
||||
|
||||
|
@ -34,7 +34,7 @@ ROUTES = Constants.ROUTES
|
||||
|
||||
@pytest.fixture
|
||||
def nm_mock():
|
||||
with mock.patch.object(netinfo, 'nm') as m:
|
||||
with mock.patch.object(netinfo, "nm") as m:
|
||||
m.ipv4.get_routing_rule_config.return_value = []
|
||||
m.ipv6.get_routing_rule_config.return_value = []
|
||||
yield m
|
||||
@ -42,34 +42,34 @@ def nm_mock():
|
||||
|
||||
@pytest.fixture
|
||||
def nm_dns_mock():
|
||||
with mock.patch.object(netinfo, 'nm_dns') as m:
|
||||
with mock.patch.object(netinfo, "nm_dns") as m:
|
||||
yield m
|
||||
|
||||
|
||||
def test_netinfo_show_generic_iface(nm_mock, nm_dns_mock):
|
||||
current_config = {
|
||||
DNS.KEY: {DNS.RUNNING: {}, DNS.CONFIG: {}},
|
||||
ROUTES: {'config': [], 'running': []},
|
||||
ROUTES: {"config": [], "running": []},
|
||||
RouteRule.KEY: {RouteRule.CONFIG: []},
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'foo',
|
||||
'type': 'unknown',
|
||||
'state': 'up',
|
||||
'ipv4': {InterfaceIPv4.ENABLED: False},
|
||||
'ipv6': {InterfaceIPv6.ENABLED: False},
|
||||
"name": "foo",
|
||||
"type": "unknown",
|
||||
"state": "up",
|
||||
"ipv4": {InterfaceIPv4.ENABLED: False},
|
||||
"ipv6": {InterfaceIPv6.ENABLED: False},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
current_iface0 = current_config[INTERFACES][0]
|
||||
nm_mock.device.list_devices.return_value = ['one-item']
|
||||
nm_mock.device.list_devices.return_value = ["one-item"]
|
||||
nm_mock.translator.Nm2Api.get_common_device_info.return_value = (
|
||||
current_iface0
|
||||
)
|
||||
nm_mock.bond.is_bond_type_id.return_value = False
|
||||
nm_mock.ipv4.get_info.return_value = current_iface0['ipv4']
|
||||
nm_mock.ipv6.get_info.return_value = current_iface0['ipv6']
|
||||
nm_mock.ipv4.get_info.return_value = current_iface0["ipv4"]
|
||||
nm_mock.ipv6.get_info.return_value = current_iface0["ipv6"]
|
||||
nm_mock.ipv4.get_route_running.return_value = []
|
||||
nm_mock.ipv4.get_route_config.return_value = []
|
||||
nm_mock.ipv6.get_route_running.return_value = []
|
||||
@ -85,36 +85,36 @@ def test_netinfo_show_generic_iface(nm_mock, nm_dns_mock):
|
||||
def test_netinfo_show_bond_iface(nm_mock, nm_dns_mock):
|
||||
current_config = {
|
||||
DNS.KEY: {DNS.RUNNING: {}, DNS.CONFIG: {}},
|
||||
ROUTES: {'config': [], 'running': []},
|
||||
ROUTES: {"config": [], "running": []},
|
||||
RouteRule.KEY: {RouteRule.CONFIG: []},
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'bond99',
|
||||
'type': 'bond',
|
||||
'state': 'up',
|
||||
'link-aggregation': {
|
||||
'mode': 'balance-rr',
|
||||
'slaves': [],
|
||||
'options': {'miimon': '100'},
|
||||
"name": "bond99",
|
||||
"type": "bond",
|
||||
"state": "up",
|
||||
"link-aggregation": {
|
||||
"mode": "balance-rr",
|
||||
"slaves": [],
|
||||
"options": {"miimon": "100"},
|
||||
},
|
||||
'ipv4': {InterfaceIPv4.ENABLED: False},
|
||||
'ipv6': {InterfaceIPv6.ENABLED: False},
|
||||
"ipv4": {InterfaceIPv4.ENABLED: False},
|
||||
"ipv6": {InterfaceIPv6.ENABLED: False},
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
nm_mock.device.list_devices.return_value = ['one-item']
|
||||
nm_mock.device.list_devices.return_value = ["one-item"]
|
||||
nm_mock.translator.Nm2Api.get_common_device_info.return_value = {
|
||||
'name': current_config[INTERFACES][0]['name'],
|
||||
'type': current_config[INTERFACES][0]['type'],
|
||||
'state': current_config[INTERFACES][0]['state'],
|
||||
"name": current_config[INTERFACES][0]["name"],
|
||||
"type": current_config[INTERFACES][0]["type"],
|
||||
"state": current_config[INTERFACES][0]["state"],
|
||||
}
|
||||
nm_mock.bond.is_bond_type_id.return_value = True
|
||||
nm_mock.translator.Nm2Api.get_bond_info.return_value = {
|
||||
'link-aggregation': current_config[INTERFACES][0]['link-aggregation']
|
||||
"link-aggregation": current_config[INTERFACES][0]["link-aggregation"]
|
||||
}
|
||||
nm_mock.ipv4.get_info.return_value = current_config[INTERFACES][0]['ipv4']
|
||||
nm_mock.ipv6.get_info.return_value = current_config[INTERFACES][0]['ipv6']
|
||||
nm_mock.ipv4.get_info.return_value = current_config[INTERFACES][0]["ipv4"]
|
||||
nm_mock.ipv6.get_info.return_value = current_config[INTERFACES][0]["ipv6"]
|
||||
nm_mock.ipv4.get_route_running.return_value = []
|
||||
nm_mock.ipv4.get_route_config.return_value = []
|
||||
nm_mock.ipv6.get_route_running.return_value = []
|
||||
|
@ -27,41 +27,41 @@ from libnmstate import nm
|
||||
|
||||
@pytest.fixture
|
||||
def nm_bond_mock():
|
||||
with mock.patch.object(nm.applier, 'bond') as m:
|
||||
with mock.patch.object(nm.applier, "bond") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_connection_mock():
|
||||
with mock.patch.object(nm.applier, 'connection') as m:
|
||||
with mock.patch.object(nm.applier, "connection") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_device_mock():
|
||||
with mock.patch.object(nm.applier, 'device') as m:
|
||||
with mock.patch.object(nm.applier, "device") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_ipv4_mock():
|
||||
with mock.patch.object(nm.applier, 'ipv4') as m:
|
||||
with mock.patch.object(nm.applier, "ipv4") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_ipv6_mock():
|
||||
with mock.patch.object(nm.applier, 'ipv6') as m:
|
||||
with mock.patch.object(nm.applier, "ipv6") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_ovs_mock():
|
||||
with mock.patch.object(nm.applier, 'ovs') as m:
|
||||
with mock.patch.object(nm.applier, "ovs") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@mock.patch.object(nm.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.connection, "ConnectionProfile")
|
||||
def test_create_new_ifaces(con_profile_mock):
|
||||
con_profiles = [con_profile_mock(), con_profile_mock()]
|
||||
|
||||
@ -72,7 +72,7 @@ def test_create_new_ifaces(con_profile_mock):
|
||||
|
||||
|
||||
@mock.patch.object(
|
||||
nm.translator.Api2Nm, 'get_iface_type', staticmethod(lambda t: t)
|
||||
nm.translator.Api2Nm, "get_iface_type", staticmethod(lambda t: t)
|
||||
)
|
||||
def test_prepare_new_ifaces_configuration(
|
||||
nm_bond_mock, nm_connection_mock, nm_ipv4_mock, nm_ipv6_mock, nm_ovs_mock
|
||||
@ -82,20 +82,20 @@ def test_prepare_new_ifaces_configuration(
|
||||
|
||||
ifaces_desired_state = [
|
||||
{
|
||||
'name': 'eth0',
|
||||
'type': 'ethernet',
|
||||
'state': 'up',
|
||||
metadata.MASTER: 'bond99',
|
||||
metadata.MASTER_TYPE: 'bond',
|
||||
"name": "eth0",
|
||||
"type": "ethernet",
|
||||
"state": "up",
|
||||
metadata.MASTER: "bond99",
|
||||
metadata.MASTER_TYPE: "bond",
|
||||
},
|
||||
{
|
||||
'name': 'bond99',
|
||||
'type': 'bond',
|
||||
'state': 'up',
|
||||
'link-aggregation': {
|
||||
'mode': 'balance-rr',
|
||||
'slaves': ['eth0'],
|
||||
'options': {'miimon': 120},
|
||||
"name": "bond99",
|
||||
"type": "bond",
|
||||
"state": "up",
|
||||
"link-aggregation": {
|
||||
"mode": "balance-rr",
|
||||
"slaves": ["eth0"],
|
||||
"options": {"miimon": 120},
|
||||
},
|
||||
},
|
||||
]
|
||||
@ -104,7 +104,7 @@ def test_prepare_new_ifaces_configuration(
|
||||
|
||||
con_setting = nm_connection_mock.ConnectionSetting.return_value
|
||||
con_setting.set_master.assert_has_calls(
|
||||
[mock.call('bond99', 'bond'), mock.call(None, None)], any_order=True
|
||||
[mock.call("bond99", "bond"), mock.call(None, None)], any_order=True
|
||||
)
|
||||
con_profile = nm_connection_mock.ConnectionProfile.return_value
|
||||
con_profile.create.assert_has_calls(
|
||||
@ -128,7 +128,7 @@ def test_prepare_new_ifaces_configuration(
|
||||
)
|
||||
|
||||
|
||||
@mock.patch.object(nm.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.connection, "ConnectionProfile")
|
||||
def test_edit_existing_ifaces_with_profile(con_profile_mock, nm_device_mock):
|
||||
con_profiles = [con_profile_mock(), con_profile_mock()]
|
||||
|
||||
@ -140,7 +140,7 @@ def test_edit_existing_ifaces_with_profile(con_profile_mock, nm_device_mock):
|
||||
)
|
||||
|
||||
|
||||
@mock.patch.object(nm.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.connection, "ConnectionProfile")
|
||||
def test_edit_existing_ifaces_without_profile(
|
||||
con_profile_mock, nm_device_mock
|
||||
):
|
||||
@ -154,7 +154,7 @@ def test_edit_existing_ifaces_without_profile(
|
||||
|
||||
|
||||
@mock.patch.object(
|
||||
nm.translator.Api2Nm, 'get_iface_type', staticmethod(lambda t: t)
|
||||
nm.translator.Api2Nm, "get_iface_type", staticmethod(lambda t: t)
|
||||
)
|
||||
def test_prepare_edited_ifaces_configuration(
|
||||
nm_device_mock, nm_connection_mock, nm_ipv4_mock, nm_ipv6_mock, nm_ovs_mock
|
||||
@ -163,7 +163,7 @@ def test_prepare_edited_ifaces_configuration(
|
||||
nm_ovs_mock.translate_port_options.return_value = {}
|
||||
|
||||
ifaces_desired_state = [
|
||||
{'name': 'eth0', 'type': 'ethernet', 'state': 'up'}
|
||||
{"name": "eth0", "type": "ethernet", "state": "up"}
|
||||
]
|
||||
cons = nm.applier.prepare_edited_ifaces_configuration(ifaces_desired_state)
|
||||
|
||||
@ -176,10 +176,10 @@ def test_prepare_edited_ifaces_configuration(
|
||||
class TestIfaceAdminStateControl:
|
||||
def test_set_ifaces_admin_state_up(self, nm_device_mock):
|
||||
ifaces_desired_state = [
|
||||
{'name': 'eth0', 'type': 'ethernet', 'state': 'up'}
|
||||
{"name": "eth0", "type": "ethernet", "state": "up"}
|
||||
]
|
||||
con_profile = mock.MagicMock()
|
||||
con_profile.devname = ifaces_desired_state[0]['name']
|
||||
con_profile.devname = ifaces_desired_state[0]["name"]
|
||||
nm.applier.set_ifaces_admin_state(ifaces_desired_state, [con_profile])
|
||||
|
||||
nm_device_mock.modify.assert_called_once_with(
|
||||
@ -188,7 +188,7 @@ class TestIfaceAdminStateControl:
|
||||
|
||||
def test_set_ifaces_admin_state_down(self, nm_device_mock):
|
||||
ifaces_desired_state = [
|
||||
{'name': 'eth0', 'type': 'ethernet', 'state': 'down'}
|
||||
{"name": "eth0", "type": "ethernet", "state": "down"}
|
||||
]
|
||||
nm.applier.set_ifaces_admin_state(ifaces_desired_state)
|
||||
|
||||
@ -201,7 +201,7 @@ class TestIfaceAdminStateControl:
|
||||
|
||||
def test_set_ifaces_admin_state_absent(self, nm_device_mock):
|
||||
ifaces_desired_state = [
|
||||
{'name': 'eth0', 'type': 'ethernet', 'state': 'absent'}
|
||||
{"name": "eth0", "type": "ethernet", "state": "absent"}
|
||||
]
|
||||
nm.applier.set_ifaces_admin_state(ifaces_desired_state)
|
||||
|
||||
@ -217,24 +217,24 @@ class TestIfaceAdminStateControl:
|
||||
):
|
||||
ifaces_desired_state = [
|
||||
{
|
||||
'name': 'bond0',
|
||||
'type': 'bond',
|
||||
'state': 'up',
|
||||
'link-aggregation': {'mode': '802.3ad', 'slaves': ['eth0']},
|
||||
"name": "bond0",
|
||||
"type": "bond",
|
||||
"state": "up",
|
||||
"link-aggregation": {"mode": "802.3ad", "slaves": ["eth0"]},
|
||||
},
|
||||
{'name': 'eth0', 'type': 'ethernet', 'state': 'up'},
|
||||
{"name": "eth0", "type": "ethernet", "state": "up"},
|
||||
]
|
||||
|
||||
nm_device_mock.get_device_by_name = lambda devname: devname
|
||||
bond = ifaces_desired_state[0]['name']
|
||||
slaves = ifaces_desired_state[0]['link-aggregation']['slaves']
|
||||
bond = ifaces_desired_state[0]["name"]
|
||||
slaves = ifaces_desired_state[0]["link-aggregation"]["slaves"]
|
||||
nm_bond_mock.BOND_TYPE = nm.bond.BOND_TYPE
|
||||
nm_bond_mock.get_slaves.return_value = slaves
|
||||
|
||||
bond_con_profile = mock.MagicMock()
|
||||
bond_con_profile.devname = ifaces_desired_state[0]['name']
|
||||
bond_con_profile.devname = ifaces_desired_state[0]["name"]
|
||||
slave_con_profile = mock.MagicMock()
|
||||
slave_con_profile.devname = ifaces_desired_state[1]['name']
|
||||
slave_con_profile.devname = ifaces_desired_state[1]["name"]
|
||||
|
||||
nm.applier.set_ifaces_admin_state(
|
||||
ifaces_desired_state, [bond_con_profile, slave_con_profile]
|
||||
|
@ -29,39 +29,39 @@ def dev_mock():
|
||||
return mock.MagicMock()
|
||||
|
||||
|
||||
@mock.patch.object(nm.bond.nmclient, 'NM')
|
||||
@mock.patch.object(nm.bond.nmclient, "NM")
|
||||
def test_create_setting(NM_mock):
|
||||
bond_setting_mock = NM_mock.SettingBond.new.return_value
|
||||
bond_setting_mock.add_option.return_value = True
|
||||
|
||||
options = {'mode': 'balance-rr', 'miimon': '100'}
|
||||
options = {"mode": "balance-rr", "miimon": "100"}
|
||||
nm.bond.create_setting(options)
|
||||
|
||||
bond_setting_mock.add_option.assert_has_calls(
|
||||
[mock.call('mode', 'balance-rr'), mock.call('miimon', '100')],
|
||||
[mock.call("mode", "balance-rr"), mock.call("miimon", "100")],
|
||||
any_order=True,
|
||||
)
|
||||
|
||||
|
||||
@mock.patch.object(nm.bond.nmclient, 'NM')
|
||||
@mock.patch.object(nm.bond.nmclient, "NM")
|
||||
def test_create_setting_with_invalid_bond_option(NM_mock):
|
||||
bond_setting_mock = NM_mock.SettingBond.new.return_value
|
||||
bond_setting_mock.add_option.return_value = False
|
||||
|
||||
options = {'mode': 'balance-rr', 'foo': '100'}
|
||||
options = {"mode": "balance-rr", "foo": "100"}
|
||||
|
||||
with pytest.raises(NmstateValueError):
|
||||
nm.bond.create_setting(options)
|
||||
|
||||
|
||||
@mock.patch.object(nm.bond.nmclient, 'NM')
|
||||
@mock.patch.object(nm.bond.nmclient, "NM")
|
||||
def test_is_bond_type_id(NM_mock):
|
||||
type_id = NM_mock.DeviceType.BOND
|
||||
|
||||
assert nm.bond.is_bond_type_id(type_id)
|
||||
|
||||
|
||||
@mock.patch.object(nm.bond.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.bond.connection, "ConnectionProfile")
|
||||
def test_get_bond_info(con_profile_mock, dev_mock):
|
||||
info = nm.bond.get_bond_info(dev_mock)
|
||||
|
||||
@ -73,7 +73,7 @@ def test_get_bond_info(con_profile_mock, dev_mock):
|
||||
opts_mock = connection_mock.get_setting_bond.return_value.props.options
|
||||
|
||||
expected_info = {
|
||||
'slaves': dev_mock.get_slaves.return_value,
|
||||
'options': opts_mock,
|
||||
"slaves": dev_mock.get_slaves.return_value,
|
||||
"options": opts_mock,
|
||||
}
|
||||
assert expected_info == info
|
||||
|
@ -26,19 +26,19 @@ from libnmstate import nm
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.connection.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.connection.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client_mock():
|
||||
with mock.patch.object(nm.connection.nmclient, 'client') as m:
|
||||
with mock.patch.object(nm.connection.nmclient, "client") as m:
|
||||
yield m.return_value
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mainloop_mock():
|
||||
with mock.patch.object(nm.connection.nmclient, 'mainloop') as m:
|
||||
with mock.patch.object(nm.connection.nmclient, "mainloop") as m:
|
||||
yield m.return_value
|
||||
|
||||
|
||||
@ -57,12 +57,12 @@ def test_create_profile(NM_mock):
|
||||
|
||||
def test_add_profile(client_mock, mainloop_mock):
|
||||
save_to_disk = True
|
||||
con_profile = nm.connection.ConnectionProfile('profile')
|
||||
con_profile = nm.connection.ConnectionProfile("profile")
|
||||
con_profile.add(save_to_disk)
|
||||
|
||||
mainloop_mock.push_action.assert_called_once_with(
|
||||
client_mock.add_connection_async,
|
||||
'profile',
|
||||
"profile",
|
||||
save_to_disk,
|
||||
mainloop_mock.cancellable,
|
||||
nm.connection.ConnectionProfile._add_connection_callback,
|
||||
@ -71,13 +71,13 @@ def test_add_profile(client_mock, mainloop_mock):
|
||||
|
||||
|
||||
def test_update_profile():
|
||||
base_profile = nm.connection.ConnectionProfile('p')
|
||||
base_profile = nm.connection.ConnectionProfile("p")
|
||||
|
||||
profile = mock.MagicMock()
|
||||
con_profile = nm.connection.ConnectionProfile(profile)
|
||||
con_profile.update(base_profile)
|
||||
|
||||
profile.replace_settings_from_connection.assert_called_once_with('p')
|
||||
profile.replace_settings_from_connection.assert_called_once_with("p")
|
||||
|
||||
|
||||
def test_commit_profile(mainloop_mock):
|
||||
@ -97,12 +97,12 @@ def test_commit_profile(mainloop_mock):
|
||||
|
||||
def test_create_setting(NM_mock):
|
||||
con_setting = nm.connection.ConnectionSetting()
|
||||
con_setting.create('con-name', 'iface-name', 'iface-type')
|
||||
con_setting.create("con-name", "iface-name", "iface-type")
|
||||
|
||||
assert con_setting.setting.props.id == 'con-name'
|
||||
assert con_setting.setting.props.interface_name == 'iface-name'
|
||||
assert con_setting.setting.props.id == "con-name"
|
||||
assert con_setting.setting.props.interface_name == "iface-name"
|
||||
assert con_setting.setting.props.uuid
|
||||
assert con_setting.setting.props.type == 'iface-type'
|
||||
assert con_setting.setting.props.type == "iface-type"
|
||||
assert con_setting.setting.props.autoconnect is True
|
||||
assert con_setting.setting.props.autoconnect_slaves == (
|
||||
NM_mock.SettingConnectionAutoconnectSlaves.YES
|
||||
@ -127,10 +127,10 @@ def test_duplicate_settings(NM_mock):
|
||||
|
||||
def test_set_master_setting():
|
||||
con_setting = nm.connection.ConnectionSetting(mock.MagicMock())
|
||||
con_setting.set_master('master0', 'slave-type')
|
||||
con_setting.set_master("master0", "slave-type")
|
||||
|
||||
assert con_setting.setting.props.master == 'master0'
|
||||
assert con_setting.setting.props.slave_type == 'slave-type'
|
||||
assert con_setting.setting.props.master == "master0"
|
||||
assert con_setting.setting.props.slave_type == "slave-type"
|
||||
|
||||
|
||||
def test_get_device_connection():
|
||||
|
@ -25,23 +25,23 @@ from libnmstate import nm
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.device.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.device.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client_mock():
|
||||
with mock.patch.object(nm.device.nmclient, 'client') as m:
|
||||
with mock.patch.object(nm.device.nmclient, "client") as m:
|
||||
yield m.return_value
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mainloop_mock():
|
||||
with mock.patch.object(nm.device.nmclient, 'mainloop') as m:
|
||||
with mock.patch.object(nm.device.nmclient, "mainloop") as m:
|
||||
yield m.return_value
|
||||
|
||||
|
||||
@mock.patch.object(nm.device.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.device.connection, "ConnectionProfile")
|
||||
def test_activate(con_profile_mock):
|
||||
dev = mock.MagicMock()
|
||||
con_profile = con_profile_mock()
|
||||
@ -51,7 +51,7 @@ def test_activate(con_profile_mock):
|
||||
con_profile.activate.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch.object(nm.device.ac, 'ActiveConnection')
|
||||
@mock.patch.object(nm.device.ac, "ActiveConnection")
|
||||
def test_deactivate(act_con_mock):
|
||||
dev = mock.MagicMock()
|
||||
act_con = act_con_mock()
|
||||
@ -62,7 +62,7 @@ def test_deactivate(act_con_mock):
|
||||
act_con.deactivate.assert_called_once()
|
||||
|
||||
|
||||
@mock.patch.object(nm.connection, 'ConnectionProfile')
|
||||
@mock.patch.object(nm.connection, "ConnectionProfile")
|
||||
def test_delete(con_profile_mock):
|
||||
dev = mock.MagicMock()
|
||||
dev.get_available_connections.return_value = [mock.MagicMock()]
|
||||
@ -74,7 +74,7 @@ def test_delete(con_profile_mock):
|
||||
|
||||
|
||||
def test_get_device_by_name(client_mock):
|
||||
devname = 'foo'
|
||||
devname = "foo"
|
||||
nm.device.get_device_by_name(devname)
|
||||
|
||||
client_mock.get_device_by_iface.assert_called_once_with(devname)
|
||||
@ -92,9 +92,9 @@ def test_get_device_common_info():
|
||||
info = nm.device.get_device_common_info(dev)
|
||||
|
||||
expected_info = {
|
||||
'name': dev.get_iface.return_value,
|
||||
'type_id': dev.get_device_type.return_value,
|
||||
'type_name': dev.get_type_description.return_value,
|
||||
'state': dev.get_state.return_value,
|
||||
"name": dev.get_iface.return_value,
|
||||
"type_id": dev.get_device_type.return_value,
|
||||
"type_name": dev.get_type_description.return_value,
|
||||
"state": dev.get_state.return_value,
|
||||
}
|
||||
assert expected_info == info
|
||||
|
@ -28,36 +28,36 @@ from libnmstate.schema import InterfaceIP
|
||||
from libnmstate.schema import Route
|
||||
|
||||
|
||||
TEST_IPV4_GATEWAY_IFACE = 'eth1'
|
||||
TEST_IPV6_GATEWAY_IFACE = 'eth2'
|
||||
TEST_STATIC_ROUTE_IFACE = 'eth3'
|
||||
TEST_IPV4_GATEWAY_IFACE = "eth1"
|
||||
TEST_IPV6_GATEWAY_IFACE = "eth2"
|
||||
TEST_STATIC_ROUTE_IFACE = "eth3"
|
||||
|
||||
|
||||
def _get_test_dns_v4():
|
||||
return {
|
||||
nm_dns.DNS_METADATA_PRIORITY: 40,
|
||||
DNS.SERVER: ['8.8.8.8', '1.1.1.1'],
|
||||
DNS.SEARCH: ['example.org', 'example.com'],
|
||||
DNS.SERVER: ["8.8.8.8", "1.1.1.1"],
|
||||
DNS.SEARCH: ["example.org", "example.com"],
|
||||
}
|
||||
|
||||
|
||||
def _get_test_dns_v6():
|
||||
return {
|
||||
nm_dns.DNS_METADATA_PRIORITY: 40,
|
||||
DNS.SERVER: ['2001:4860:4860::8888', '2606:4700:4700::1111'],
|
||||
DNS.SEARCH: ['example.net', 'example.edu'],
|
||||
DNS.SERVER: ["2001:4860:4860::8888", "2606:4700:4700::1111"],
|
||||
DNS.SEARCH: ["example.net", "example.edu"],
|
||||
}
|
||||
|
||||
|
||||
parametrize_ip_ver = pytest.mark.parametrize(
|
||||
'nm_ip', [(nm_ipv4), (nm_ipv6)], ids=['ipv4', 'ipv6']
|
||||
"nm_ip", [(nm_ipv4), (nm_ipv6)], ids=["ipv4", "ipv6"]
|
||||
)
|
||||
|
||||
|
||||
parametrize_ip_ver_dns = pytest.mark.parametrize(
|
||||
'nm_ip, get_test_dns_func',
|
||||
"nm_ip, get_test_dns_func",
|
||||
[(nm_ipv4, _get_test_dns_v4), (nm_ipv6, _get_test_dns_v6)],
|
||||
ids=['ipv4', 'ipv6'],
|
||||
ids=["ipv4", "ipv6"],
|
||||
)
|
||||
|
||||
|
||||
@ -182,9 +182,9 @@ def test_find_interfaces_for_dns_with_no_gateway():
|
||||
def _get_test_ipv4_gateway():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 200,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: TEST_IPV4_GATEWAY_IFACE,
|
||||
Route.TABLE_ID: 54,
|
||||
}
|
||||
@ -194,9 +194,9 @@ def _get_test_ipv4_gateway():
|
||||
def _get_test_ipv6_gateway():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 201,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:2::f',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:2::f",
|
||||
Route.NEXT_HOP_INTERFACE: TEST_IPV6_GATEWAY_IFACE,
|
||||
Route.TABLE_ID: 54,
|
||||
}
|
||||
@ -206,16 +206,16 @@ def _get_test_ipv6_gateway():
|
||||
def _get_test_static_routes():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '2001:db8:3::1',
|
||||
Route.DESTINATION: "2001:db8:3::1",
|
||||
Route.METRIC: 201,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:2::f',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:2::f",
|
||||
Route.NEXT_HOP_INTERFACE: TEST_STATIC_ROUTE_IFACE,
|
||||
Route.TABLE_ID: 54,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '198.51.100.0/24',
|
||||
Route.DESTINATION: "198.51.100.0/24",
|
||||
Route.METRIC: 201,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.NEXT_HOP_INTERFACE: TEST_STATIC_ROUTE_IFACE,
|
||||
Route.TABLE_ID: 54,
|
||||
},
|
||||
|
@ -24,12 +24,12 @@ from unittest import mock
|
||||
from libnmstate import nm
|
||||
from libnmstate.schema import InterfaceIPv4
|
||||
|
||||
IPV4_ADDRESS1 = '192.0.2.251'
|
||||
IPV4_ADDRESS1 = "192.0.2.251"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.ipv4.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.ipv4.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@ -68,11 +68,11 @@ def test_create_setting_with_static_addresses(NM_mock):
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '10.10.10.1',
|
||||
InterfaceIPv4.ADDRESS_IP: "10.10.10.1",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '10.10.20.1',
|
||||
InterfaceIPv4.ADDRESS_IP: "10.10.20.1",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
],
|
||||
|
@ -26,19 +26,19 @@ from libnmstate.schema import InterfaceIPv6
|
||||
|
||||
# IPv6 Address Prefix Reserved for Documentation:
|
||||
# https://tools.ietf.org/html/rfc3849
|
||||
IPV6_ADDRESS1 = '2001:db8:1::1'
|
||||
IPV6_LINK_LOCAL_ADDRESS1 = 'fe80::1'
|
||||
IPV6_ADDRESS1 = "2001:db8:1::1"
|
||||
IPV6_LINK_LOCAL_ADDRESS1 = "fe80::1"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.ipv6.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.ipv6.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
def test_create_setting_without_config(NM_mock):
|
||||
NM_mock.SettingIP6Config.new().props.addresses = []
|
||||
NM_mock.NM.SETTING_IP6_CONFIG_METHOD_DISABLED = 'disabled'
|
||||
NM_mock.NM.SETTING_IP6_CONFIG_METHOD_DISABLED = "disabled"
|
||||
|
||||
ipv6_setting = nm.ipv6.create_setting(config=None, base_con_profile=None)
|
||||
|
||||
@ -49,7 +49,7 @@ def test_create_setting_without_config(NM_mock):
|
||||
|
||||
def test_create_setting_with_ipv6_disabled(NM_mock):
|
||||
NM_mock.SettingIP6Config.new().props.addresses = []
|
||||
NM_mock.NM.SETTING_IP6_CONFIG_METHOD_DISABLED = 'disabled'
|
||||
NM_mock.NM.SETTING_IP6_CONFIG_METHOD_DISABLED = "disabled"
|
||||
|
||||
ipv6_setting = nm.ipv6.create_setting(
|
||||
config={InterfaceIPv6.ENABLED: False}, base_con_profile=None
|
||||
@ -80,11 +80,11 @@ def test_create_setting_with_static_addresses(NM_mock):
|
||||
InterfaceIPv6.ENABLED: True,
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: 'fd12:3456:789a:1::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "fd12:3456:789a:1::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: 'fd12:3456:789a:2::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "fd12:3456:789a:2::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
],
|
||||
|
@ -26,19 +26,19 @@ from libnmstate import nm
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.ovs.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.ovs.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_connection_mock():
|
||||
with mock.patch.object(nm.ovs, 'connection') as m:
|
||||
with mock.patch.object(nm.ovs, "connection") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def nm_device_mock():
|
||||
with mock.patch.object(nm.ovs, 'device') as m:
|
||||
with mock.patch.object(nm.ovs, "device") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@ -65,12 +65,12 @@ def test_get_ovs_info_without_ports(nm_connection_mock, NM_mock):
|
||||
info = nm.ovs.get_ovs_info(bridge_device, device_info)
|
||||
|
||||
expected_info = {
|
||||
'port': [],
|
||||
'options': {
|
||||
'fail-mode': '',
|
||||
'mcast-snooping-enable': False,
|
||||
'rstp': False,
|
||||
'stp': False,
|
||||
"port": [],
|
||||
"options": {
|
||||
"fail-mode": "",
|
||||
"mcast-snooping-enable": False,
|
||||
"rstp": False,
|
||||
"stp": False,
|
||||
},
|
||||
}
|
||||
assert expected_info == info
|
||||
@ -89,12 +89,12 @@ def test_get_ovs_info_with_ports_without_interfaces(
|
||||
info = nm.ovs.get_ovs_info(bridge_device, device_info)
|
||||
|
||||
expected_info = {
|
||||
'port': [],
|
||||
'options': {
|
||||
'fail-mode': '',
|
||||
'mcast-snooping-enable': False,
|
||||
'rstp': False,
|
||||
'stp': False,
|
||||
"port": [],
|
||||
"options": {
|
||||
"fail-mode": "",
|
||||
"mcast-snooping-enable": False,
|
||||
"rstp": False,
|
||||
"stp": False,
|
||||
},
|
||||
}
|
||||
assert expected_info == info
|
||||
@ -120,46 +120,46 @@ def test_get_ovs_info_with_ports_with_interfaces(
|
||||
device_info = [(bridge_device, None), (port_device, None)]
|
||||
info = nm.ovs.get_ovs_info(bridge_device, device_info)
|
||||
|
||||
assert len(info['port']) == 1
|
||||
assert 'name' in info['port'][0]
|
||||
assert 'vlan-mode' in info['port'][0]
|
||||
assert 'access-tag' in info['port'][0]
|
||||
assert len(info["port"]) == 1
|
||||
assert "name" in info["port"][0]
|
||||
assert "vlan-mode" in info["port"][0]
|
||||
assert "access-tag" in info["port"][0]
|
||||
|
||||
|
||||
def test_create_bridge_setting(NM_mock):
|
||||
options = {
|
||||
'fail-mode': 'foo',
|
||||
'mcast-snooping-enable': False,
|
||||
'rstp': False,
|
||||
'stp': False,
|
||||
"fail-mode": "foo",
|
||||
"mcast-snooping-enable": False,
|
||||
"rstp": False,
|
||||
"stp": False,
|
||||
}
|
||||
bridge_setting = nm.ovs.create_bridge_setting(options)
|
||||
|
||||
assert bridge_setting.props.fail_mode == options['fail-mode']
|
||||
assert bridge_setting.props.fail_mode == options["fail-mode"]
|
||||
assert bridge_setting.props.mcast_snooping_enable == (
|
||||
options['mcast-snooping-enable']
|
||||
options["mcast-snooping-enable"]
|
||||
)
|
||||
assert bridge_setting.props.rstp_enable == options['rstp']
|
||||
assert bridge_setting.props.stp_enable == options['stp']
|
||||
assert bridge_setting.props.rstp_enable == options["rstp"]
|
||||
assert bridge_setting.props.stp_enable == options["stp"]
|
||||
|
||||
|
||||
def test_create_port_setting(NM_mock):
|
||||
options = {
|
||||
'tag': 101,
|
||||
'vlan-mode': 'voomode',
|
||||
'bond-mode': 'boomode',
|
||||
'lacp': 'yes',
|
||||
'bond-updelay': 0,
|
||||
'bond-downdelay': 0,
|
||||
"tag": 101,
|
||||
"vlan-mode": "voomode",
|
||||
"bond-mode": "boomode",
|
||||
"lacp": "yes",
|
||||
"bond-updelay": 0,
|
||||
"bond-downdelay": 0,
|
||||
}
|
||||
port_setting = nm.ovs.create_port_setting(options)
|
||||
|
||||
assert port_setting.props.tag == options['tag']
|
||||
assert port_setting.props.vlan_mode == options['vlan-mode']
|
||||
assert port_setting.props.bond_mode == options['bond-mode']
|
||||
assert port_setting.props.lacp == options['lacp']
|
||||
assert port_setting.props.bond_updelay == options['bond-updelay']
|
||||
assert port_setting.props.bond_downdelay == options['bond-downdelay']
|
||||
assert port_setting.props.tag == options["tag"]
|
||||
assert port_setting.props.vlan_mode == options["vlan-mode"]
|
||||
assert port_setting.props.bond_mode == options["bond-mode"]
|
||||
assert port_setting.props.lacp == options["lacp"]
|
||||
assert port_setting.props.bond_updelay == options["bond-updelay"]
|
||||
assert port_setting.props.bond_downdelay == options["bond-downdelay"]
|
||||
|
||||
|
||||
def _mock_port_profile(nm_connection_mock):
|
||||
|
@ -29,59 +29,59 @@ 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'
|
||||
IPV6_DEFAULT_GATEWAY_DESTINATION = '::/0'
|
||||
IPV4_DEFAULT_GATEWAY_DESTINATION = "0.0.0.0/0"
|
||||
IPV6_DEFAULT_GATEWAY_DESTINATION = "::/0"
|
||||
|
||||
IPV4_ROUTE1 = {
|
||||
Route.DESTINATION: '198.51.100.0/24',
|
||||
Route.DESTINATION: "198.51.100.0/24",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.TABLE_ID: 50,
|
||||
}
|
||||
|
||||
IPV4_ROUTE2 = {
|
||||
Route.DESTINATION: '203.0.113.0/24',
|
||||
Route.DESTINATION: "203.0.113.0/24",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.2',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.2",
|
||||
Route.TABLE_ID: 51,
|
||||
}
|
||||
|
||||
IPV6_ROUTE1 = {
|
||||
Route.DESTINATION: '2001:db8:a::/64',
|
||||
Route.DESTINATION: "2001:db8:a::/64",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::a',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::a",
|
||||
Route.TABLE_ID: 50,
|
||||
}
|
||||
|
||||
IPV6_ROUTE2 = {
|
||||
Route.DESTINATION: '2001:db8:b::/64',
|
||||
Route.DESTINATION: "2001:db8:b::/64",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::b',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::b",
|
||||
Route.TABLE_ID: 51,
|
||||
}
|
||||
|
||||
parametrize_ip_ver_routes = pytest.mark.parametrize(
|
||||
'nm_ip, routes',
|
||||
"nm_ip, routes",
|
||||
[
|
||||
(nm_ipv4, [IPV4_ROUTE1, IPV4_ROUTE2]),
|
||||
(nm_ipv6, [IPV6_ROUTE1, IPV6_ROUTE2]),
|
||||
],
|
||||
ids=['ipv4', 'ipv6'],
|
||||
ids=["ipv4", "ipv6"],
|
||||
)
|
||||
|
||||
|
||||
def _get_test_ipv4_gateways():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.1',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.1",
|
||||
Route.TABLE_ID: 52,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '0.0.0.0/0',
|
||||
Route.DESTINATION: "0.0.0.0/0",
|
||||
Route.METRIC: 101,
|
||||
Route.NEXT_HOP_ADDRESS: '192.0.2.2',
|
||||
Route.NEXT_HOP_ADDRESS: "192.0.2.2",
|
||||
Route.TABLE_ID: 53,
|
||||
},
|
||||
]
|
||||
@ -90,27 +90,27 @@ def _get_test_ipv4_gateways():
|
||||
def _get_test_ipv6_gateways():
|
||||
return [
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 103,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::f',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::f",
|
||||
Route.TABLE_ID: 52,
|
||||
},
|
||||
{
|
||||
Route.DESTINATION: '::/0',
|
||||
Route.DESTINATION: "::/0",
|
||||
Route.METRIC: 101,
|
||||
Route.NEXT_HOP_ADDRESS: '2001:db8:1::e',
|
||||
Route.NEXT_HOP_ADDRESS: "2001:db8:1::e",
|
||||
Route.TABLE_ID: 53,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
parametrize_ip_ver_routes_gw = pytest.mark.parametrize(
|
||||
'nm_ip, routes, gateways',
|
||||
"nm_ip, routes, gateways",
|
||||
[
|
||||
(nm_ipv4, [IPV4_ROUTE1, IPV4_ROUTE2], _get_test_ipv4_gateways()),
|
||||
(nm_ipv6, [IPV6_ROUTE1, IPV6_ROUTE2], _get_test_ipv6_gateways()),
|
||||
],
|
||||
ids=['ipv4', 'ipv6'],
|
||||
ids=["ipv4", "ipv6"],
|
||||
)
|
||||
|
||||
|
||||
@ -193,7 +193,7 @@ def test_change_gateway(nm_ip, routes, gateways):
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
strict=True,
|
||||
reason='Network Manager Bug: ' 'https://bugzilla.redhat.com/1707396',
|
||||
reason="Network Manager Bug: " "https://bugzilla.redhat.com/1707396",
|
||||
)
|
||||
@parametrize_ip_ver_routes_gw
|
||||
def test_add_two_gateway(nm_ip, routes, gateways):
|
||||
@ -206,7 +206,7 @@ def test_add_two_gateway(nm_ip, routes, gateways):
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
strict=True,
|
||||
reason='Network Manager Bug: ' 'https://bugzilla.redhat.com/1707396',
|
||||
reason="Network Manager Bug: " "https://bugzilla.redhat.com/1707396",
|
||||
)
|
||||
@parametrize_ip_ver_routes_gw
|
||||
def test_add_duplicate_gateways(nm_ip, routes, gateways):
|
||||
@ -263,12 +263,12 @@ def test_clear_gateway(nm_ip, routes, gateways):
|
||||
|
||||
|
||||
def _nm_route_to_dict(nm_route):
|
||||
dst = '{ip}/{prefix}'.format(
|
||||
dst = "{ip}/{prefix}".format(
|
||||
ip=nm_route.get_dest(), prefix=nm_route.get_prefix()
|
||||
)
|
||||
next_hop = nm_route.get_next_hop() or ''
|
||||
next_hop = nm_route.get_next_hop() or ""
|
||||
metric = int(nm_route.get_metric())
|
||||
table_id_variant = nm_route.get_attribute('table')
|
||||
table_id_variant = nm_route.get_attribute("table")
|
||||
|
||||
return {
|
||||
Route.TABLE_ID: int(table_id_variant.get_uint32()),
|
||||
|
@ -24,14 +24,14 @@ from unittest import mock
|
||||
from libnmstate import nm
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
@pytest.fixture(scope="module")
|
||||
def NM_mock():
|
||||
saved_api2nm_map = nm.translator.Api2Nm._iface_types_map
|
||||
saved_nm2api_map = nm.translator.Nm2Api._iface_types_map
|
||||
nm.translator.Api2Nm._iface_types_map = None
|
||||
nm.translator.Nm2Api._iface_types_map = None
|
||||
|
||||
with mock.patch.object(nm.translator.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.translator.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
nm.translator.Api2Nm._iface_types_map = saved_api2nm_map
|
||||
@ -42,38 +42,38 @@ def test_api2nm_iface_type_map(NM_mock):
|
||||
map = nm.translator.Api2Nm.get_iface_type_map()
|
||||
|
||||
expected_map = {
|
||||
'ethernet': NM_mock.SETTING_WIRED_SETTING_NAME,
|
||||
'bond': NM_mock.SETTING_BOND_SETTING_NAME,
|
||||
'dummy': NM_mock.SETTING_DUMMY_SETTING_NAME,
|
||||
'ovs-bridge': NM_mock.SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||
'ovs-port': NM_mock.SETTING_OVS_PORT_SETTING_NAME,
|
||||
'ovs-interface': NM_mock.SETTING_OVS_INTERFACE_SETTING_NAME,
|
||||
'vlan': NM_mock.SETTING_VLAN_SETTING_NAME,
|
||||
'linux-bridge': NM_mock.SETTING_BRIDGE_SETTING_NAME,
|
||||
'vxlan': NM_mock.SETTING_VXLAN_SETTING_NAME,
|
||||
"ethernet": NM_mock.SETTING_WIRED_SETTING_NAME,
|
||||
"bond": NM_mock.SETTING_BOND_SETTING_NAME,
|
||||
"dummy": NM_mock.SETTING_DUMMY_SETTING_NAME,
|
||||
"ovs-bridge": NM_mock.SETTING_OVS_BRIDGE_SETTING_NAME,
|
||||
"ovs-port": NM_mock.SETTING_OVS_PORT_SETTING_NAME,
|
||||
"ovs-interface": NM_mock.SETTING_OVS_INTERFACE_SETTING_NAME,
|
||||
"vlan": NM_mock.SETTING_VLAN_SETTING_NAME,
|
||||
"linux-bridge": NM_mock.SETTING_BRIDGE_SETTING_NAME,
|
||||
"vxlan": NM_mock.SETTING_VXLAN_SETTING_NAME,
|
||||
}
|
||||
|
||||
assert map == expected_map
|
||||
|
||||
|
||||
def test_api2nm_get_iface_type(NM_mock):
|
||||
nm_type = nm.translator.Api2Nm.get_iface_type('ethernet')
|
||||
nm_type = nm.translator.Api2Nm.get_iface_type("ethernet")
|
||||
assert NM_mock.SETTING_WIRED_SETTING_NAME == nm_type
|
||||
|
||||
|
||||
@mock.patch.object(
|
||||
nm.translator.Api2Nm, 'get_iface_type', staticmethod(lambda t: t)
|
||||
nm.translator.Api2Nm, "get_iface_type", staticmethod(lambda t: t)
|
||||
)
|
||||
def test_api2nm_bond_options():
|
||||
bond_options = {
|
||||
'name': 'bond99',
|
||||
'type': 'bond',
|
||||
'state': 'up',
|
||||
'link-aggregation': {'mode': 'balance-rr', 'options': {'miimon': 120}},
|
||||
"name": "bond99",
|
||||
"type": "bond",
|
||||
"state": "up",
|
||||
"link-aggregation": {"mode": "balance-rr", "options": {"miimon": 120}},
|
||||
}
|
||||
nm_bond_options = nm.translator.Api2Nm.get_bond_options(bond_options)
|
||||
|
||||
assert {'miimon': 120, 'mode': 'balance-rr'} == nm_bond_options
|
||||
assert {"miimon": 120, "mode": "balance-rr"} == nm_bond_options
|
||||
|
||||
|
||||
def test_nm2api_common_device_info(NM_mock):
|
||||
@ -81,33 +81,33 @@ def test_nm2api_common_device_info(NM_mock):
|
||||
NM_mock.DeviceState.IP_CONFIG = 70
|
||||
nm.nmclient.NM.DeviceState.DISCONNECTED = 30
|
||||
devinfo = {
|
||||
'name': 'devname',
|
||||
'type_id': 'devtypeid',
|
||||
'type_name': 'devtypename',
|
||||
'state': nm.nmclient.NM.DeviceState.DISCONNECTED,
|
||||
"name": "devname",
|
||||
"type_id": "devtypeid",
|
||||
"type_name": "devtypename",
|
||||
"state": nm.nmclient.NM.DeviceState.DISCONNECTED,
|
||||
}
|
||||
info = nm.translator.Nm2Api.get_common_device_info(devinfo)
|
||||
|
||||
expected_info = {'name': 'devname', 'state': 'down', 'type': 'unknown'}
|
||||
expected_info = {"name": "devname", "state": "down", "type": "unknown"}
|
||||
assert expected_info == info
|
||||
|
||||
|
||||
def test_nm2api_bond_info():
|
||||
slaves_mock = [mock.MagicMock(), mock.MagicMock()]
|
||||
bondinfo = {
|
||||
'slaves': slaves_mock,
|
||||
'options': {'mode': 'balance-rr', 'miimon': 120},
|
||||
"slaves": slaves_mock,
|
||||
"options": {"mode": "balance-rr", "miimon": 120},
|
||||
}
|
||||
info = nm.translator.Nm2Api.get_bond_info(bondinfo)
|
||||
|
||||
expected_info = {
|
||||
'link-aggregation': {
|
||||
'mode': 'balance-rr',
|
||||
'slaves': [
|
||||
"link-aggregation": {
|
||||
"mode": "balance-rr",
|
||||
"slaves": [
|
||||
slaves_mock[0].props.interface,
|
||||
slaves_mock[1].props.interface,
|
||||
],
|
||||
'options': {'miimon': 120},
|
||||
"options": {"miimon": 120},
|
||||
}
|
||||
}
|
||||
assert expected_info == info
|
||||
|
@ -26,7 +26,7 @@ from libnmstate import nm
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.user.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.user.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ def test_create_setting_duplicate(NM_mock):
|
||||
base_profile = mock.MagicMock()
|
||||
|
||||
setting = nm.user.create_setting(
|
||||
{'description': 'test_interface'}, base_profile
|
||||
{"description": "test_interface"}, base_profile
|
||||
)
|
||||
base_profile.get_setting_by_name.assert_called_with(
|
||||
NM_mock.SETTING_USER_SETTING_NAME
|
||||
@ -51,8 +51,8 @@ def test_create_setting_duplicate(NM_mock):
|
||||
|
||||
|
||||
def test_create_setting_description(NM_mock):
|
||||
setting = nm.user.create_setting({'description': 'test_interface'}, None)
|
||||
setting = nm.user.create_setting({"description": "test_interface"}, None)
|
||||
assert setting == NM_mock.SettingUser.new.return_value
|
||||
setting.set_data.assert_called_with(
|
||||
'nmstate.interface.description', 'test_interface'
|
||||
"nmstate.interface.description", "test_interface"
|
||||
)
|
||||
|
@ -27,7 +27,7 @@ from libnmstate import schema
|
||||
|
||||
@pytest.fixture
|
||||
def NM_mock():
|
||||
with mock.patch.object(nm.wired.nmclient, 'NM') as m:
|
||||
with mock.patch.object(nm.wired.nmclient, "NM") as m:
|
||||
yield m
|
||||
|
||||
|
||||
@ -51,10 +51,10 @@ def test_create_setting_duplicate(NM_mock):
|
||||
|
||||
def test_create_setting_mac(NM_mock):
|
||||
setting = nm.wired.create_setting(
|
||||
{schema.Interface.MAC: '01:23:45:67:89:ab'}, None
|
||||
{schema.Interface.MAC: "01:23:45:67:89:ab"}, None
|
||||
)
|
||||
assert setting == NM_mock.SettingWired.new.return_value
|
||||
assert setting.props.cloned_mac_address == '01:23:45:67:89:ab'
|
||||
assert setting.props.cloned_mac_address == "01:23:45:67:89:ab"
|
||||
|
||||
|
||||
def test_create_setting_mtu(NM_mock):
|
||||
@ -65,17 +65,17 @@ def test_create_setting_mtu(NM_mock):
|
||||
|
||||
@mock.patch.object(
|
||||
nm.wired,
|
||||
'minimal_ethtool',
|
||||
"minimal_ethtool",
|
||||
return_value={
|
||||
'speed': 1337,
|
||||
'duplex': 'full',
|
||||
'auto-negotiation': 'mocked',
|
||||
"speed": 1337,
|
||||
"duplex": "full",
|
||||
"auto-negotiation": "mocked",
|
||||
},
|
||||
)
|
||||
def test_create_setting_auto_negotiation_False(ethtool_mock, NM_mock):
|
||||
setting = nm.wired.create_setting(
|
||||
{
|
||||
schema.Interface.NAME: 'nmstate_test',
|
||||
schema.Interface.NAME: "nmstate_test",
|
||||
schema.Ethernet.CONFIG_SUBTREE: {
|
||||
schema.Ethernet.AUTO_NEGOTIATION: False
|
||||
},
|
||||
@ -86,7 +86,7 @@ def test_create_setting_auto_negotiation_False(ethtool_mock, NM_mock):
|
||||
assert setting.props.auto_negotiate is False
|
||||
assert setting.props.speed == 1337
|
||||
assert setting.props.duplex == schema.Ethernet.FULL_DUPLEX
|
||||
assert ethtool_mock.called_with('nmstate_test')
|
||||
assert ethtool_mock.called_with("nmstate_test")
|
||||
|
||||
|
||||
def test_create_setting_only_auto_negotiation_True(NM_mock):
|
||||
@ -138,17 +138,17 @@ def test_create_setting_speed_duplex(NM_mock):
|
||||
|
||||
@mock.patch.object(
|
||||
nm.wired,
|
||||
'minimal_ethtool',
|
||||
"minimal_ethtool",
|
||||
return_value={
|
||||
'speed': 1500,
|
||||
'duplex': 'unknown',
|
||||
'auto-negotiation': True,
|
||||
"speed": 1500,
|
||||
"duplex": "unknown",
|
||||
"auto-negotiation": True,
|
||||
},
|
||||
)
|
||||
def test_get_info_with_invalid_duplex(ethtool_mock, NM_mock):
|
||||
dev_mock = mock.MagicMock()
|
||||
dev_mock.get_iface.return_value = 'nmstate_test'
|
||||
dev_mock.get_hw_address.return_value = 'ab:cd:ef:01:23:45'
|
||||
dev_mock.get_iface.return_value = "nmstate_test"
|
||||
dev_mock.get_hw_address.return_value = "ab:cd:ef:01:23:45"
|
||||
dev_mock.get_mtu.return_value = 1500
|
||||
dev_mock.get_device_type.return_value = NM_mock.DeviceType.ETHERNET
|
||||
|
||||
@ -175,19 +175,19 @@ class TestWiredSetting:
|
||||
assert not obj
|
||||
|
||||
def test_no_relevant_keys_is_false(self):
|
||||
state = {'foo': 'boo'}
|
||||
state = {"foo": "boo"}
|
||||
obj = nm.wired.WiredSetting(state)
|
||||
|
||||
assert not obj
|
||||
|
||||
def test_relevant_keys_with_false_values_is_false(self):
|
||||
state = {schema.Interface.MTU: 0, schema.Interface.MAC: ''}
|
||||
state = {schema.Interface.MTU: 0, schema.Interface.MAC: ""}
|
||||
obj = nm.wired.WiredSetting(state)
|
||||
|
||||
assert not obj
|
||||
|
||||
def test_partial_relevant_keys_is_true(self):
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
obj = nm.wired.WiredSetting(state)
|
||||
|
||||
assert obj
|
||||
@ -201,7 +201,7 @@ class TestWiredSetting:
|
||||
assert not (obj1 != obj2)
|
||||
|
||||
def test_equality_for_partial_states(self):
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
obj1 = nm.wired.WiredSetting(state)
|
||||
obj2 = nm.wired.WiredSetting(state)
|
||||
|
||||
@ -209,8 +209,8 @@ class TestWiredSetting:
|
||||
assert not (obj1 != obj2)
|
||||
|
||||
def test_inequality_for_partial_states(self):
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state2 = {schema.Interface.MTU: 1000, schema.Interface.MAC: 'abc'}
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
state2 = {schema.Interface.MTU: 1000, schema.Interface.MAC: "abc"}
|
||||
obj1 = nm.wired.WiredSetting(state1)
|
||||
obj2 = nm.wired.WiredSetting(state2)
|
||||
|
||||
@ -218,8 +218,8 @@ class TestWiredSetting:
|
||||
assert not (obj1 == obj2)
|
||||
|
||||
def test_inequality_for_partial_states_with_missing_properties(self):
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state2 = {schema.Interface.MAC: 'abc'}
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
state2 = {schema.Interface.MAC: "abc"}
|
||||
|
||||
obj1 = nm.wired.WiredSetting(state1)
|
||||
obj2 = nm.wired.WiredSetting(state2)
|
||||
@ -228,16 +228,16 @@ class TestWiredSetting:
|
||||
assert not (obj1 == obj2)
|
||||
|
||||
def test_hash_unique(self):
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
obj1 = nm.wired.WiredSetting(state)
|
||||
obj2 = nm.wired.WiredSetting(state)
|
||||
|
||||
assert hash(obj1) == hash(obj2)
|
||||
|
||||
def test_behaviour_with_set(self):
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state2 = {schema.Interface.MTU: 1500, schema.Interface.MAC: 'abc'}
|
||||
state3 = {schema.Interface.MAC: 'abc'}
|
||||
state1 = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
state2 = {schema.Interface.MTU: 1500, schema.Interface.MAC: "abc"}
|
||||
state3 = {schema.Interface.MAC: "abc"}
|
||||
|
||||
obj1 = nm.wired.WiredSetting(state1)
|
||||
obj2 = nm.wired.WiredSetting(state2)
|
||||
|
@ -23,20 +23,20 @@ from libnmstate.schema import OVSBridge
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'changes',
|
||||
"changes",
|
||||
argvalues=[
|
||||
['GROUP_FORWARD_MASK', LinuxBridge.Options.GROUP_FORWARD_MASK],
|
||||
['MAC_AGEING_TIME', LinuxBridge.Options.MAC_AGEING_TIME],
|
||||
['MULTICAST_SNOOPING', LinuxBridge.Options.MULTICAST_SNOOPING],
|
||||
['PORT_NAME', LinuxBridge.Port.NAME],
|
||||
['PORT_STP_HAIRPIN_MODE', LinuxBridge.Port.STP_HAIRPIN_MODE],
|
||||
['PORT_STP_PATH_COST', LinuxBridge.Port.STP_PATH_COST],
|
||||
['PORT_STP_PRIORITY', LinuxBridge.Port.STP_PRIORITY],
|
||||
['STP_ENABLED', LinuxBridge.STP.ENABLED],
|
||||
['STP_FORWARD_DELAY', LinuxBridge.STP.FORWARD_DELAY],
|
||||
['STP_HELLO_TIME', LinuxBridge.STP.HELLO_TIME],
|
||||
['STP_MAX_AGE', LinuxBridge.STP.MAX_AGE],
|
||||
['STP_PRIORITY', LinuxBridge.STP.PRIORITY],
|
||||
["GROUP_FORWARD_MASK", LinuxBridge.Options.GROUP_FORWARD_MASK],
|
||||
["MAC_AGEING_TIME", LinuxBridge.Options.MAC_AGEING_TIME],
|
||||
["MULTICAST_SNOOPING", LinuxBridge.Options.MULTICAST_SNOOPING],
|
||||
["PORT_NAME", LinuxBridge.Port.NAME],
|
||||
["PORT_STP_HAIRPIN_MODE", LinuxBridge.Port.STP_HAIRPIN_MODE],
|
||||
["PORT_STP_PATH_COST", LinuxBridge.Port.STP_PATH_COST],
|
||||
["PORT_STP_PRIORITY", LinuxBridge.Port.STP_PRIORITY],
|
||||
["STP_ENABLED", LinuxBridge.STP.ENABLED],
|
||||
["STP_FORWARD_DELAY", LinuxBridge.STP.FORWARD_DELAY],
|
||||
["STP_HELLO_TIME", LinuxBridge.STP.HELLO_TIME],
|
||||
["STP_MAX_AGE", LinuxBridge.STP.MAX_AGE],
|
||||
["STP_PRIORITY", LinuxBridge.STP.PRIORITY],
|
||||
],
|
||||
)
|
||||
def test_linuxbridge_deprecated_constants(changes):
|
||||
@ -49,13 +49,13 @@ def test_linuxbridge_deprecated_constants(changes):
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'changes',
|
||||
"changes",
|
||||
argvalues=[
|
||||
['PORT_NAME', OVSBridge.Port.NAME],
|
||||
['FAIL_MODE', OVSBridge.Options.FAIL_MODE],
|
||||
['MCAST_SNOOPING_ENABLED', OVSBridge.Options.MCAST_SNOOPING_ENABLED],
|
||||
['RSTP', OVSBridge.Options.RSTP],
|
||||
['STP', OVSBridge.Options.STP],
|
||||
["PORT_NAME", OVSBridge.Port.NAME],
|
||||
["FAIL_MODE", OVSBridge.Options.FAIL_MODE],
|
||||
["MCAST_SNOOPING_ENABLED", OVSBridge.Options.MCAST_SNOOPING_ENABLED],
|
||||
["RSTP", OVSBridge.Options.RSTP],
|
||||
["STP", OVSBridge.Options.STP],
|
||||
],
|
||||
)
|
||||
def test_ovsbridge_deprecated_constants(changes):
|
||||
|
@ -37,69 +37,69 @@ from libnmstate.schema import VXLAN
|
||||
|
||||
INTERFACES = Constants.INTERFACES
|
||||
ROUTES = Constants.ROUTES
|
||||
THE_BRIDGE = 'br0'
|
||||
VXLAN0 = 'vxlan0'
|
||||
TEAM0 = 'team0'
|
||||
THE_BRIDGE = "br0"
|
||||
VXLAN0 = "vxlan0"
|
||||
TEAM0 = "team0"
|
||||
|
||||
COMMON_DATA = {
|
||||
INTERFACES: [
|
||||
{
|
||||
'name': 'lo',
|
||||
'description': 'Loopback Interface',
|
||||
'type': 'unknown',
|
||||
'state': 'down',
|
||||
'link-speed': 1000,
|
||||
'mac-address': '12:34:56:78:90:ab',
|
||||
'mtu': 1500,
|
||||
"name": "lo",
|
||||
"description": "Loopback Interface",
|
||||
"type": "unknown",
|
||||
"state": "down",
|
||||
"link-speed": 1000,
|
||||
"mac-address": "12:34:56:78:90:ab",
|
||||
"mtu": 1500,
|
||||
# Read Only entries
|
||||
'if-index': 0,
|
||||
'admin-status': 'up',
|
||||
'link-status': 'down',
|
||||
'phys-address': '12:34:56:78:90:ab',
|
||||
'higher-layer-if': '',
|
||||
'lower-layer-if': '',
|
||||
'low-control': True,
|
||||
'statistics': {
|
||||
'in-octets': 0,
|
||||
'in-unicast-pkts': 0,
|
||||
'in-broadcast-pkts': 0,
|
||||
'in-multicast-pkts': 0,
|
||||
'in-discards': 0,
|
||||
'in-errors': 0,
|
||||
'out-octets': 0,
|
||||
'out-unicast-pkts': 0,
|
||||
'out-broadcast-pkts': 0,
|
||||
'out-multicast-pkts': 0,
|
||||
'out-discards': 0,
|
||||
'out-errors': 0,
|
||||
"if-index": 0,
|
||||
"admin-status": "up",
|
||||
"link-status": "down",
|
||||
"phys-address": "12:34:56:78:90:ab",
|
||||
"higher-layer-if": "",
|
||||
"lower-layer-if": "",
|
||||
"low-control": True,
|
||||
"statistics": {
|
||||
"in-octets": 0,
|
||||
"in-unicast-pkts": 0,
|
||||
"in-broadcast-pkts": 0,
|
||||
"in-multicast-pkts": 0,
|
||||
"in-discards": 0,
|
||||
"in-errors": 0,
|
||||
"out-octets": 0,
|
||||
"out-unicast-pkts": 0,
|
||||
"out-broadcast-pkts": 0,
|
||||
"out-multicast-pkts": 0,
|
||||
"out-discards": 0,
|
||||
"out-errors": 0,
|
||||
},
|
||||
}
|
||||
],
|
||||
ROUTES: {
|
||||
'config': [
|
||||
"config": [
|
||||
{
|
||||
'table-id': 254,
|
||||
'metric': 100,
|
||||
'destination': '0.0.0.0/0',
|
||||
'next-hop-interface': 'eth0',
|
||||
'next-hop-address': '192.0.2.1',
|
||||
"table-id": 254,
|
||||
"metric": 100,
|
||||
"destination": "0.0.0.0/0",
|
||||
"next-hop-interface": "eth0",
|
||||
"next-hop-address": "192.0.2.1",
|
||||
}
|
||||
],
|
||||
'running': [
|
||||
"running": [
|
||||
{
|
||||
'table-id': 254,
|
||||
'metric': 100,
|
||||
'destination': '::/0',
|
||||
'next-hop-interface': 'eth0',
|
||||
'next-hop-address': 'fe80::1',
|
||||
"table-id": 254,
|
||||
"metric": 100,
|
||||
"destination": "::/0",
|
||||
"next-hop-interface": "eth0",
|
||||
"next-hop-address": "fe80::1",
|
||||
}
|
||||
],
|
||||
},
|
||||
RouteRule.KEY: {
|
||||
RouteRule.CONFIG: [
|
||||
{
|
||||
RouteRule.IP_FROM: '192.0.2.0/24',
|
||||
RouteRule.IP_TO: '198.51.100.0/24',
|
||||
RouteRule.IP_FROM: "192.0.2.0/24",
|
||||
RouteRule.IP_TO: "198.51.100.0/24",
|
||||
RouteRule.PRIORITY: 500,
|
||||
RouteRule.ROUTE_TABLE: 254,
|
||||
}
|
||||
@ -127,7 +127,7 @@ def default_data():
|
||||
def portless_bridge_state():
|
||||
return {
|
||||
Interface.NAME: THE_BRIDGE,
|
||||
Interface.STATE: 'up',
|
||||
Interface.STATE: "up",
|
||||
Interface.TYPE: LB.TYPE,
|
||||
LB.CONFIG_SUBTREE: {LB.PORT_SUBTREE: []},
|
||||
}
|
||||
@ -135,7 +135,7 @@ def portless_bridge_state():
|
||||
|
||||
@pytest.fixture
|
||||
def bridge_state(portless_bridge_state):
|
||||
port = {LB.Port.NAME: 'eth1', LB.Port.VLAN_SUBTREE: {}}
|
||||
port = {LB.Port.NAME: "eth1", LB.Port.VLAN_SUBTREE: {}}
|
||||
portless_bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE].append(port)
|
||||
return portless_bridge_state
|
||||
|
||||
@ -144,7 +144,7 @@ def bridge_state(portless_bridge_state):
|
||||
def portless_ovs_bridge_state():
|
||||
return {
|
||||
Interface.NAME: THE_BRIDGE,
|
||||
Interface.STATE: 'up',
|
||||
Interface.STATE: "up",
|
||||
Interface.TYPE: OVSBridge.TYPE,
|
||||
LB.CONFIG_SUBTREE: {OVSBridge.PORT_SUBTREE: []},
|
||||
}
|
||||
@ -152,7 +152,7 @@ def portless_ovs_bridge_state():
|
||||
|
||||
@pytest.fixture
|
||||
def ovs_bridge_state(portless_ovs_bridge_state):
|
||||
port = {LB.Port.NAME: 'eth1', OVSBridge.Port.VLAN_SUBTREE: {}}
|
||||
port = {LB.Port.NAME: "eth1", OVSBridge.Port.VLAN_SUBTREE: {}}
|
||||
ovs_bridge_state_config = portless_ovs_bridge_state[
|
||||
OVSBridge.CONFIG_SUBTREE
|
||||
]
|
||||
@ -165,13 +165,13 @@ class TestIfaceCommon:
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_invalid_instance(self, default_data):
|
||||
default_data[INTERFACES][0]['state'] = 'bad-state'
|
||||
default_data[INTERFACES][0]["state"] = "bad-state"
|
||||
|
||||
with pytest.raises(js.ValidationError):
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_invalid_type(self, default_data):
|
||||
default_data[INTERFACES][0]['type'] = 'bad-type'
|
||||
default_data[INTERFACES][0]["type"] = "bad-type"
|
||||
|
||||
with pytest.raises(js.ValidationError):
|
||||
libnmstate.validator.validate(default_data)
|
||||
@ -180,13 +180,13 @@ class TestIfaceCommon:
|
||||
class TestIfaceTypeEthernet:
|
||||
def test_valid_ethernet_with_auto_neg(self, default_data):
|
||||
default_data[INTERFACES][0].update(
|
||||
{'type': 'ethernet', 'auto-negotiation': True}
|
||||
{"type": "ethernet", "auto-negotiation": True}
|
||||
)
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_valid_ethernet_without_auto_neg(self, default_data):
|
||||
default_data[INTERFACES][0].update(
|
||||
{'auto-negotiation': False, 'link-speed': 1000, 'duplex': 'full'}
|
||||
{"auto-negotiation": False, "link-speed": 1000, "duplex": "full"}
|
||||
)
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
@ -197,13 +197,13 @@ class TestIfaceTypeEthernet:
|
||||
at the moment, deferring the handling to the application code.
|
||||
"""
|
||||
default_data[INTERFACES][0].update(
|
||||
{'type': 'ethernet', 'auto-negotiation': False}
|
||||
{"type": "ethernet", "auto-negotiation": False}
|
||||
)
|
||||
del default_data[INTERFACES][0]['link-speed']
|
||||
del default_data[INTERFACES][0]["link-speed"]
|
||||
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
@pytest.mark.parametrize('valid_values', [0, 150, 256])
|
||||
@pytest.mark.parametrize("valid_values", [0, 150, 256])
|
||||
def test_valid_with_sriov_total_vfs(self, default_data, valid_values):
|
||||
default_data[Interface.KEY][0].update(
|
||||
{
|
||||
@ -215,7 +215,7 @@ class TestIfaceTypeEthernet:
|
||||
)
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
@pytest.mark.parametrize('invalid_values', [-50, -1])
|
||||
@pytest.mark.parametrize("invalid_values", [-50, -1])
|
||||
def test_over_maximum_total_vfs_is_invalid(
|
||||
self, default_data, invalid_values
|
||||
):
|
||||
@ -239,9 +239,9 @@ class TestIfaceTypeVxlan:
|
||||
Interface.NAME: VXLAN0,
|
||||
Interface.TYPE: VXLAN.TYPE,
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: 'badtype',
|
||||
VXLAN.BASE_IFACE: 'eth1',
|
||||
VXLAN.REMOTE: '192.168.3.3',
|
||||
VXLAN.ID: "badtype",
|
||||
VXLAN.BASE_IFACE: "eth1",
|
||||
VXLAN.REMOTE: "192.168.3.3",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -256,8 +256,8 @@ class TestIfaceTypeVxlan:
|
||||
Interface.TYPE: VXLAN.TYPE,
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: 16777216,
|
||||
VXLAN.BASE_IFACE: 'eth1',
|
||||
VXLAN.REMOTE: '192.168.3.3',
|
||||
VXLAN.BASE_IFACE: "eth1",
|
||||
VXLAN.REMOTE: "192.168.3.3",
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -291,7 +291,7 @@ class TestIfaceTypeTeam:
|
||||
Interface.NAME: TEAM0,
|
||||
Interface.TYPE: Team.TYPE,
|
||||
Team.CONFIG_SUBTREE: {
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: 'eth1'}]
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: "eth1"}]
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -320,7 +320,7 @@ class TestIfaceTypeTeam:
|
||||
Interface.NAME: TEAM0,
|
||||
Interface.TYPE: Team.TYPE,
|
||||
Team.CONFIG_SUBTREE: {
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: 'eth1'}],
|
||||
Team.PORT_SUBTREE: [{Team.Port.NAME: "eth1"}],
|
||||
Team.RUNNER_SUBTREE: {
|
||||
Team.Runner.NAME: Team.Runner.RunnerMode.LOAD_BALANCE
|
||||
},
|
||||
@ -333,18 +333,18 @@ class TestIfaceTypeTeam:
|
||||
|
||||
class TestRoutes:
|
||||
def test_valid_state_absent(self, default_data):
|
||||
default_data[ROUTES]['config'][0]['state'] = 'absent'
|
||||
default_data[ROUTES]["config"][0]["state"] = "absent"
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_invalid_state(self, default_data):
|
||||
default_data[ROUTES]['config'][0]['state'] = 'bad-state'
|
||||
default_data[ROUTES]["config"][0]["state"] = "bad-state"
|
||||
|
||||
with pytest.raises(js.ValidationError):
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
|
||||
class TestLinuxBridgeVlanFiltering:
|
||||
@pytest.mark.parametrize('port_type', argvalues=['trunk', 'access'])
|
||||
@pytest.mark.parametrize("port_type", argvalues=["trunk", "access"])
|
||||
def test_vlan_port_types(self, default_data, bridge_state, port_type):
|
||||
valid_port_type = self._generate_vlan_filtering_config(port_type)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
@ -354,7 +354,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_invalid_vlan_port_type(self, default_data, bridge_state):
|
||||
invalid_port_type = self._generate_vlan_filtering_config('fake-type')
|
||||
invalid_port_type = self._generate_vlan_filtering_config("fake-type")
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
the_port.update(invalid_port_type)
|
||||
default_data[Interface.KEY].append(bridge_state)
|
||||
@ -364,7 +364,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
|
||||
def test_access_port_accepted(self, default_data, bridge_state):
|
||||
vlan_access_port_state = self._generate_vlan_filtering_config(
|
||||
'access', access_tag=101
|
||||
"access", access_tag=101
|
||||
)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
the_port.update(vlan_access_port_state)
|
||||
@ -374,7 +374,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
|
||||
def test_wrong_access_port_tag_type(self, default_data, bridge_state):
|
||||
invalid_access_port_tag_type = self._generate_vlan_filtering_config(
|
||||
'access', access_tag='holy-guacamole!'
|
||||
"access", access_tag="holy-guacamole!"
|
||||
)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
the_port.update(invalid_access_port_tag_type)
|
||||
@ -385,7 +385,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
|
||||
def test_wrong_access_tag_range(self, default_data, bridge_state):
|
||||
invalid_vlan_id_range = self._generate_vlan_filtering_config(
|
||||
'access', access_tag=48000
|
||||
"access", access_tag=48000
|
||||
)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
the_port.update(invalid_vlan_id_range)
|
||||
@ -395,13 +395,13 @@ class TestLinuxBridgeVlanFiltering:
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'is_native_vlan', argvalues=[True, False], ids=['native', 'not-native']
|
||||
"is_native_vlan", argvalues=[True, False], ids=["native", "not-native"]
|
||||
)
|
||||
def test_trunk_port_native_vlan(
|
||||
self, default_data, bridge_state, is_native_vlan
|
||||
):
|
||||
vlan_access_port_state = self._generate_vlan_filtering_config(
|
||||
'trunk',
|
||||
"trunk",
|
||||
access_tag=101 if is_native_vlan else None,
|
||||
native_vlan=is_native_vlan,
|
||||
)
|
||||
@ -415,7 +415,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
trunk_tags = self._generate_vlan_id_config(101, 102, 103)
|
||||
trunk_tags.append(self._generate_vlan_id_range_config(500, 1000))
|
||||
vlan_trunk_tags_port_state = self._generate_vlan_filtering_config(
|
||||
'trunk', trunk_tags=trunk_tags
|
||||
"trunk", trunk_tags=trunk_tags
|
||||
)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
the_port.update(vlan_trunk_tags_port_state)
|
||||
@ -425,7 +425,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
|
||||
def test_invalid_trunk_port_vlan_range(self, default_data, bridge_state):
|
||||
invalid_port_vlan_configuration = self._generate_vlan_filtering_config(
|
||||
'trunk',
|
||||
"trunk",
|
||||
trunk_tags=[self._generate_vlan_id_range_config(100, 5000)],
|
||||
)
|
||||
the_port = bridge_state[LB.CONFIG_SUBTREE][LB.PORT_SUBTREE][0]
|
||||
@ -466,7 +466,7 @@ class TestLinuxBridgeVlanFiltering:
|
||||
|
||||
|
||||
class TestOvsBridgeVlan:
|
||||
@pytest.mark.parametrize('vlan_mode', argvalues=['trunk', 'access'])
|
||||
@pytest.mark.parametrize("vlan_mode", argvalues=["trunk", "access"])
|
||||
def test_vlan_port_modes(self, default_data, ovs_bridge_state, vlan_mode):
|
||||
valid_vlan_mode = self._generate_vlan_config(vlan_mode)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
@ -477,7 +477,7 @@ class TestOvsBridgeVlan:
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
def test_invalid_vlan_port_mode(self, default_data, ovs_bridge_state):
|
||||
invalid_vlan_mode = self._generate_vlan_config('fake-mode')
|
||||
invalid_vlan_mode = self._generate_vlan_config("fake-mode")
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
the_port = bridge_state_config[OVSBridge.PORT_SUBTREE][0]
|
||||
the_port.update(invalid_vlan_mode)
|
||||
@ -488,7 +488,7 @@ class TestOvsBridgeVlan:
|
||||
|
||||
def test_access_port_accepted(self, default_data, ovs_bridge_state):
|
||||
vlan_access_port_state = self._generate_vlan_config(
|
||||
'access', access_tag=101
|
||||
"access", access_tag=101
|
||||
)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
the_port = bridge_state_config[OVSBridge.PORT_SUBTREE][0]
|
||||
@ -499,7 +499,7 @@ class TestOvsBridgeVlan:
|
||||
|
||||
def test_wrong_access_port_tag_mode(self, default_data, ovs_bridge_state):
|
||||
invalid_access_port_tag_mode = self._generate_vlan_config(
|
||||
'access', access_tag='holy-guacamole!'
|
||||
"access", access_tag="holy-guacamole!"
|
||||
)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
the_port = bridge_state_config[OVSBridge.PORT_SUBTREE][0]
|
||||
@ -511,7 +511,7 @@ class TestOvsBridgeVlan:
|
||||
|
||||
def test_wrong_access_tag_range(self, default_data, ovs_bridge_state):
|
||||
invalid_vlan_id_range = self._generate_vlan_config(
|
||||
'access', access_tag=48000
|
||||
"access", access_tag=48000
|
||||
)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
the_port = bridge_state_config[OVSBridge.PORT_SUBTREE][0]
|
||||
@ -522,13 +522,13 @@ class TestOvsBridgeVlan:
|
||||
libnmstate.validator.validate(default_data)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'is_native_vlan', argvalues=[True, False], ids=['native', 'not-native']
|
||||
"is_native_vlan", argvalues=[True, False], ids=["native", "not-native"]
|
||||
)
|
||||
def test_trunk_port_native_vlan(
|
||||
self, default_data, ovs_bridge_state, is_native_vlan
|
||||
):
|
||||
vlan_access_port_state = self._generate_vlan_config(
|
||||
'trunk',
|
||||
"trunk",
|
||||
access_tag=101 if is_native_vlan else None,
|
||||
native_vlan=is_native_vlan,
|
||||
)
|
||||
@ -543,7 +543,7 @@ class TestOvsBridgeVlan:
|
||||
trunk_tags = self._generate_vlan_id_config(101, 102, 103)
|
||||
trunk_tags.append(self._generate_vlan_id_range_config(500, 1000))
|
||||
vlan_trunk_tags_port_state = self._generate_vlan_config(
|
||||
'trunk', trunk_tags=trunk_tags
|
||||
"trunk", trunk_tags=trunk_tags
|
||||
)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
the_port = bridge_state_config[OVSBridge.PORT_SUBTREE][0]
|
||||
@ -556,7 +556,7 @@ class TestOvsBridgeVlan:
|
||||
self, default_data, ovs_bridge_state
|
||||
):
|
||||
invalid_port_vlan_configuration = self._generate_vlan_config(
|
||||
'trunk',
|
||||
"trunk",
|
||||
trunk_tags=[self._generate_vlan_id_range_config(100, 5000)],
|
||||
)
|
||||
bridge_state_config = ovs_bridge_state[OVSBridge.CONFIG_SUBTREE]
|
||||
@ -603,7 +603,7 @@ class TestOvsBridgeVlan:
|
||||
class TestRouteRules:
|
||||
def test_non_interger_route_table(self, default_data):
|
||||
route_rules = default_data[RouteRule.KEY][RouteRule.CONFIG]
|
||||
route_rules[0][RouteRule.ROUTE_TABLE] = 'main'
|
||||
route_rules[0][RouteRule.ROUTE_TABLE] = "main"
|
||||
|
||||
with pytest.raises(js.ValidationError):
|
||||
libnmstate.validator.validate(default_data)
|
||||
@ -612,18 +612,18 @@ class TestRouteRules:
|
||||
class TestOVSBridgeLinkAggregation:
|
||||
def test_valid_link_aggregation_port(self, default_data):
|
||||
link_aggregation_port = {
|
||||
OVSBridge.Port.NAME: 'bond',
|
||||
OVSBridge.Port.NAME: "bond",
|
||||
OVSBridge.Port.LINK_AGGREGATION_SUBTREE: {
|
||||
OVSBridge.Port.LinkAggregation.MODE: 'bond-mode',
|
||||
OVSBridge.Port.LinkAggregation.MODE: "bond-mode",
|
||||
OVSBridge.Port.LinkAggregation.SLAVES_SUBTREE: [
|
||||
{OVSBridge.Port.LinkAggregation.Slave.NAME: 'iface1'},
|
||||
{OVSBridge.Port.LinkAggregation.Slave.NAME: 'iface2'},
|
||||
{OVSBridge.Port.LinkAggregation.Slave.NAME: "iface1"},
|
||||
{OVSBridge.Port.LinkAggregation.Slave.NAME: "iface2"},
|
||||
],
|
||||
},
|
||||
}
|
||||
default_data[Interface.KEY].append(
|
||||
{
|
||||
Interface.NAME: 'bridge',
|
||||
Interface.NAME: "bridge",
|
||||
Interface.TYPE: InterfaceType.OVS_BRIDGE,
|
||||
OVSBridge.CONFIG_SUBTREE: {
|
||||
OVSBridge.PORT_SUBTREE: [link_aggregation_port]
|
||||
|
@ -33,7 +33,7 @@ from libnmstate.schema import RouteRule
|
||||
|
||||
|
||||
parametrize_route_property = pytest.mark.parametrize(
|
||||
'route_property',
|
||||
"route_property",
|
||||
[
|
||||
Route.TABLE_ID,
|
||||
Route.DESTINATION,
|
||||
@ -71,27 +71,27 @@ class TestAssertIfaceState:
|
||||
def test_desired_is_not_equal_to_current(self):
|
||||
desired_state = self._base_state
|
||||
current_state = self._base_state
|
||||
current_state.interfaces['foo-name']['state'] = 'down'
|
||||
current_state.interfaces["foo-name"]["state"] = "down"
|
||||
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
desired_state.verify_interfaces(current_state)
|
||||
|
||||
def test_desired_has_extra_info_when_ip_disabled(self):
|
||||
desired_state = self._base_state
|
||||
desired_state.interfaces['foo-name'][Interface.IPV4] = {
|
||||
desired_state.interfaces["foo-name"][Interface.IPV4] = {
|
||||
InterfaceIPv4.ENABLED: False,
|
||||
InterfaceIPv4.DHCP: False,
|
||||
}
|
||||
desired_state.interfaces['foo-name'][Interface.IPV6] = {
|
||||
desired_state.interfaces["foo-name"][Interface.IPV6] = {
|
||||
InterfaceIPv6.ENABLED: False,
|
||||
InterfaceIPv6.DHCP: False,
|
||||
InterfaceIPv6.AUTOCONF: False,
|
||||
}
|
||||
current_state = self._base_state
|
||||
current_state.interfaces['foo-name'][Interface.IPV4] = {
|
||||
current_state.interfaces["foo-name"][Interface.IPV4] = {
|
||||
InterfaceIPv4.ENABLED: False
|
||||
}
|
||||
current_state.interfaces['foo-name'][Interface.IPV6] = {
|
||||
current_state.interfaces["foo-name"][Interface.IPV6] = {
|
||||
InterfaceIPv6.ENABLED: False
|
||||
}
|
||||
|
||||
@ -100,53 +100,53 @@ class TestAssertIfaceState:
|
||||
def test_sort_multiple_ip(self):
|
||||
desired_state = self._base_state
|
||||
current_state = self._base_state
|
||||
desired_state.interfaces['foo-name']['ipv4'] = {
|
||||
desired_state.interfaces["foo-name"]["ipv4"] = {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.122.10',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.122.10",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.121.10',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.121.10",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
],
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
}
|
||||
current_state.interfaces['foo-name']['ipv4'] = {
|
||||
current_state.interfaces["foo-name"]["ipv4"] = {
|
||||
InterfaceIPv4.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.121.10',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.121.10",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
{
|
||||
InterfaceIPv4.ADDRESS_IP: '192.168.122.10',
|
||||
InterfaceIPv4.ADDRESS_IP: "192.168.122.10",
|
||||
InterfaceIPv4.ADDRESS_PREFIX_LENGTH: 24,
|
||||
},
|
||||
],
|
||||
InterfaceIPv4.ENABLED: True,
|
||||
}
|
||||
desired_state.interfaces['foo-name']['ipv6'] = {
|
||||
desired_state.interfaces["foo-name"]["ipv6"] = {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001::2',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001::2",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
},
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
},
|
||||
],
|
||||
InterfaceIPv6.ENABLED: True,
|
||||
}
|
||||
current_state.interfaces['foo-name']['ipv6'] = {
|
||||
current_state.interfaces["foo-name"]["ipv6"] = {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001::1',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001::1",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
},
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001::2',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001::2",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
},
|
||||
],
|
||||
@ -158,24 +158,24 @@ class TestAssertIfaceState:
|
||||
def test_description_is_empty(self):
|
||||
desired_state = self._base_state
|
||||
current_state = self._base_state
|
||||
desired_state.interfaces['foo-name'][Interface.DESCRIPTION] = ''
|
||||
desired_state.interfaces["foo-name"][Interface.DESCRIPTION] = ""
|
||||
|
||||
desired_state.verify_interfaces(current_state)
|
||||
|
||||
def test_description_is_not_empty(self):
|
||||
desired_state = self._base_state
|
||||
current_state = self._base_state
|
||||
desired_state.interfaces['foo-name'][Interface.DESCRIPTION] = 'bar'
|
||||
current_state.interfaces['foo-name'][Interface.DESCRIPTION] = 'bar'
|
||||
desired_state.interfaces["foo-name"][Interface.DESCRIPTION] = "bar"
|
||||
current_state.interfaces["foo-name"][Interface.DESCRIPTION] = "bar"
|
||||
|
||||
desired_state.verify_interfaces(current_state)
|
||||
|
||||
def test_accept_expanded_ipv6_notation(self):
|
||||
desired_state = self._base_state
|
||||
current_state = self._base_state
|
||||
expanded_ipv6_addr = '2001:0db8:85a3:0000:0000:8a2e:0370:7331'
|
||||
expanded_ipv6_addr = "2001:0db8:85a3:0000:0000:8a2e:0370:7331"
|
||||
|
||||
desired_state.interfaces['foo-name']['ipv6'] = {
|
||||
desired_state.interfaces["foo-name"]["ipv6"] = {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: expanded_ipv6_addr,
|
||||
@ -184,10 +184,10 @@ class TestAssertIfaceState:
|
||||
],
|
||||
InterfaceIPv6.ENABLED: True,
|
||||
}
|
||||
current_state.interfaces['foo-name']['ipv6'] = {
|
||||
current_state.interfaces["foo-name"]["ipv6"] = {
|
||||
InterfaceIPv6.ADDRESS: [
|
||||
{
|
||||
InterfaceIPv6.ADDRESS_IP: '2001:db8:85a3::8a2e:370:7331',
|
||||
InterfaceIPv6.ADDRESS_IP: "2001:db8:85a3::8a2e:370:7331",
|
||||
InterfaceIPv6.ADDRESS_PREFIX_LENGTH: 64,
|
||||
}
|
||||
],
|
||||
@ -201,11 +201,11 @@ class TestAssertIfaceState:
|
||||
{
|
||||
Interface.KEY: [
|
||||
{
|
||||
'name': 'foo-name',
|
||||
'type': 'foo-type',
|
||||
'state': 'up',
|
||||
'bridge': {
|
||||
'port': [{'name': 'eth0', 'type': 'system'}]
|
||||
"name": "foo-name",
|
||||
"type": "foo-type",
|
||||
"state": "up",
|
||||
"bridge": {
|
||||
"port": [{"name": "eth0", "type": "system"}]
|
||||
},
|
||||
}
|
||||
]
|
||||
@ -217,8 +217,8 @@ class TestAssertIfaceState:
|
||||
return state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{'name': 'eth0', 'state': 'up', 'type': 'unknown'},
|
||||
{'name': 'eth1', 'state': 'up', 'type': 'unknown'},
|
||||
{"name": "eth0", "state": "up", "type": "unknown"},
|
||||
{"name": "eth1", "state": "up", "type": "unknown"},
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -226,71 +226,71 @@ class TestAssertIfaceState:
|
||||
|
||||
class TestRouteEntry:
|
||||
def test_hash_unique(self):
|
||||
route = _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
route = _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
assert hash(route) == hash(route)
|
||||
|
||||
def test_obj_unique(self):
|
||||
route0 = _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
route0 = _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
route1 = _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
route0_clone = _create_route(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
assert route0 == route0_clone
|
||||
assert route0 != route1
|
||||
|
||||
def test_obj_unique_without_table_id(self):
|
||||
route_with_default_table_id = _create_route(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
'eth1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
"eth1",
|
||||
Route.USE_DEFAULT_ROUTE_TABLE,
|
||||
103,
|
||||
)
|
||||
|
||||
route_without_table_id = _create_route(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', None, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", None, 103
|
||||
)
|
||||
|
||||
assert route_without_table_id == route_with_default_table_id
|
||||
|
||||
def test_obj_unique_without_metric(self):
|
||||
route_with_default_metric = _create_route(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
'eth1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
"eth1",
|
||||
50,
|
||||
Route.USE_DEFAULT_METRIC,
|
||||
)
|
||||
|
||||
route_without_metric = _create_route(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, None
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, None
|
||||
)
|
||||
|
||||
assert route_without_metric == route_with_default_metric
|
||||
|
||||
def test_obj_unique_without_next_hop(self):
|
||||
route_with_default_next_hop = _create_route(
|
||||
'198.51.100.0/24', '', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "", "eth1", 50, 103
|
||||
)
|
||||
|
||||
route_without_next_hop = _create_route(
|
||||
'198.51.100.0/24', None, 'eth1', 50, 103
|
||||
"198.51.100.0/24", None, "eth1", 50, 103
|
||||
)
|
||||
|
||||
assert route_without_next_hop == route_with_default_next_hop
|
||||
|
||||
def test_normal_route_object_as_dict(self):
|
||||
route = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
route_obj = state.RouteEntry(route)
|
||||
assert route_obj.to_dict() == route
|
||||
|
||||
def test_absent_route_object_as_dict(self):
|
||||
route = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
route[Route.STATE] = Route.STATE_ABSENT
|
||||
route_obj = state.RouteEntry(route)
|
||||
@ -300,7 +300,7 @@ class TestRouteEntry:
|
||||
@parametrize_route_property
|
||||
def test_absent_route_with_missing_props_as_dict(self, route_property):
|
||||
absent_route = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
absent_route[Route.STATE] = Route.STATE_ABSENT
|
||||
del absent_route[route_property]
|
||||
@ -308,16 +308,16 @@ class TestRouteEntry:
|
||||
assert route_obj.to_dict() == absent_route
|
||||
|
||||
def test_absent_route_with_exact_match(self):
|
||||
route0 = _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
route0 = _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
|
||||
absent_r0 = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
absent_r0[Route.STATE] = Route.STATE_ABSENT
|
||||
absent_route0 = state.RouteEntry(absent_r0)
|
||||
|
||||
route1 = _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
|
||||
assert absent_route0.match(route0)
|
||||
@ -328,14 +328,14 @@ class TestRouteEntry:
|
||||
@parametrize_route_property
|
||||
def test_absent_route_wildcard_match(self, route_property):
|
||||
original_route0 = _create_route(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
original_route1 = _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
|
||||
absent_route0_state = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
absent_route0_state[Route.STATE] = Route.STATE_ABSENT
|
||||
del absent_route0_state[route_property]
|
||||
@ -346,7 +346,7 @@ class TestRouteEntry:
|
||||
|
||||
def test_absent_route_is_ignored_for_matching_and_equality(self):
|
||||
route = _create_route_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", "eth1", 50, 103
|
||||
)
|
||||
route[Route.STATE] = Route.STATE_ABSENT
|
||||
obj1 = state.RouteEntry(route)
|
||||
@ -356,36 +356,36 @@ class TestRouteEntry:
|
||||
|
||||
def test_sort_routes(self):
|
||||
routes = [
|
||||
_create_route('198.51.100.1/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 10, 103),
|
||||
_create_route("198.51.100.1/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth1", 10, 103),
|
||||
]
|
||||
expected_routes = [
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 10, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.1/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth1", 10, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.1/24", "192.0.2.1", "eth0", 50, 103),
|
||||
]
|
||||
assert expected_routes == sorted(routes)
|
||||
|
||||
@parametrize_route_property
|
||||
def test_sort_routes_with_absent_route(self, route_property):
|
||||
absent_route = _create_route(
|
||||
'198.51.100.0/24', '192.0.1.1', 'eth0', 9, 103
|
||||
"198.51.100.0/24", "192.0.1.1", "eth0", 9, 103
|
||||
).to_dict()
|
||||
absent_route[Route.STATE] = Route.STATE_ABSENT
|
||||
del absent_route[route_property]
|
||||
absent_route = state.RouteEntry(absent_route)
|
||||
routes = [
|
||||
absent_route,
|
||||
_create_route('198.51.100.1/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 10, 103),
|
||||
_create_route("198.51.100.1/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth1", 10, 103),
|
||||
]
|
||||
expected_routes = [
|
||||
absent_route,
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 10, 103),
|
||||
_create_route('198.51.100.0/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route('198.51.100.1/24', '192.0.2.1', 'eth0', 50, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth1", 10, 103),
|
||||
_create_route("198.51.100.0/24", "192.0.2.1", "eth0", 50, 103),
|
||||
_create_route("198.51.100.1/24", "192.0.2.1", "eth0", 50, 103),
|
||||
]
|
||||
assert expected_routes == sorted(routes)
|
||||
|
||||
@ -397,46 +397,46 @@ class TestRouteStateMerge:
|
||||
|
||||
s0.merge_routes(s1)
|
||||
|
||||
assert {'interfaces': [], 'routes': {'config': []}} == s0.state
|
||||
assert {"interfaces": [], "routes": {"config": []}} == s0.state
|
||||
assert {} == s0.config_iface_routes
|
||||
|
||||
def test_merge_identical_states(self):
|
||||
route0_obj = self._create_route0()
|
||||
route0 = route0_obj.to_dict()
|
||||
s0 = state.State({'routes': {'config': [route0]}})
|
||||
s1 = state.State({'routes': {'config': [route0]}})
|
||||
s0 = state.State({"routes": {"config": [route0]}})
|
||||
s1 = state.State({"routes": {"config": [route0]}})
|
||||
|
||||
s0.merge_routes(s1)
|
||||
|
||||
assert {'interfaces': [], 'routes': {'config': [route0]}} == s0.state
|
||||
assert {'eth1': [route0_obj]} == s0.config_iface_routes
|
||||
assert {"interfaces": [], "routes": {"config": [route0]}} == s0.state
|
||||
assert {"eth1": [route0_obj]} == s0.config_iface_routes
|
||||
|
||||
def test_merge_unique_states(self):
|
||||
route0_obj = self._create_route0()
|
||||
route0 = route0_obj.to_dict()
|
||||
route1_obj = self._create_route1()
|
||||
route1 = route1_obj.to_dict()
|
||||
s0 = state.State({'routes': {'config': [route0]}})
|
||||
s1 = state.State({'routes': {'config': [route1]}})
|
||||
s0 = state.State({"routes": {"config": [route0]}})
|
||||
s1 = state.State({"routes": {"config": [route1]}})
|
||||
|
||||
s0.merge_routes(s1)
|
||||
|
||||
expected_state = {'interfaces': [], 'routes': {'config': [route0]}}
|
||||
expected_state = {"interfaces": [], "routes": {"config": [route0]}}
|
||||
assert expected_state == s0.state
|
||||
expected_indexed_routes = {'eth1': [route0_obj]}
|
||||
expected_indexed_routes = {"eth1": [route0_obj]}
|
||||
assert expected_indexed_routes == s0.config_iface_routes
|
||||
|
||||
def test_merge_empty_with_non_empty_state(self):
|
||||
route0_obj = self._create_route0()
|
||||
route0 = route0_obj.to_dict()
|
||||
empty_state = state.State({})
|
||||
state_with_route0 = state.State({'routes': {'config': [route0]}})
|
||||
state_with_route0 = state.State({"routes": {"config": [route0]}})
|
||||
|
||||
empty_state.merge_routes(state_with_route0)
|
||||
|
||||
assert {
|
||||
'interfaces': [],
|
||||
'routes': {'config': []},
|
||||
"interfaces": [],
|
||||
"routes": {"config": []},
|
||||
} == empty_state.state
|
||||
assert {} == empty_state.config_iface_routes
|
||||
|
||||
@ -598,15 +598,15 @@ class TestRouteStateMerge:
|
||||
route0_obj = self._create_route0()
|
||||
route0 = route0_obj.to_dict()
|
||||
empty_state = state.State({})
|
||||
state_with_route0 = state.State({'routes': {'config': [route0]}})
|
||||
state_with_route0 = state.State({"routes": {"config": [route0]}})
|
||||
|
||||
state_with_route0.merge_routes(empty_state)
|
||||
|
||||
assert {
|
||||
'interfaces': [],
|
||||
'routes': {'config': [route0]},
|
||||
"interfaces": [],
|
||||
"routes": {"config": [route0]},
|
||||
} == state_with_route0.state
|
||||
assert {'eth1': [route0_obj]} == state_with_route0.config_iface_routes
|
||||
assert {"eth1": [route0_obj]} == state_with_route0.config_iface_routes
|
||||
|
||||
def test_merge_absent_routes_with_no_matching(self):
|
||||
absent_route_obj = self._create_route0()
|
||||
@ -614,12 +614,12 @@ class TestRouteStateMerge:
|
||||
absent_route = absent_route_obj.to_dict()
|
||||
other_route_obj = self._create_route1()
|
||||
other_route = other_route_obj.to_dict()
|
||||
s0 = state.State({'routes': {'config': [absent_route]}})
|
||||
s1 = state.State({'routes': {'config': [other_route]}})
|
||||
s0 = state.State({"routes": {"config": [absent_route]}})
|
||||
s1 = state.State({"routes": {"config": [other_route]}})
|
||||
|
||||
s0.merge_routes(s1)
|
||||
|
||||
expected_state = {'interfaces': [], 'routes': {'config': []}}
|
||||
expected_state = {"interfaces": [], "routes": {"config": []}}
|
||||
assert expected_state == s0.state
|
||||
assert {} == s0.config_iface_routes
|
||||
|
||||
@ -629,20 +629,20 @@ class TestRouteStateMerge:
|
||||
absent_route = absent_route_obj.to_dict()
|
||||
other_route_obj = self._create_route0()
|
||||
other_route = other_route_obj.to_dict()
|
||||
s0 = state.State({'routes': {'config': [absent_route]}})
|
||||
s1 = state.State({'routes': {'config': [other_route]}})
|
||||
s0 = state.State({"routes": {"config": [absent_route]}})
|
||||
s1 = state.State({"routes": {"config": [other_route]}})
|
||||
|
||||
s0.merge_routes(s1)
|
||||
|
||||
assert {'interfaces': [], 'routes': {'config': []}} == s0.state
|
||||
assert {"interfaces": [], "routes": {"config": []}} == s0.state
|
||||
assert {} == s0.config_iface_routes
|
||||
|
||||
def _create_route0(self):
|
||||
return _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
return _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
|
||||
def _create_route1(self):
|
||||
return _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
|
||||
|
||||
@ -685,10 +685,10 @@ def test_state_iface_routes_with_distinct_ifaces():
|
||||
def test_state_iface_routes_with_same_iface():
|
||||
routes = _get_mixed_test_routes()
|
||||
for route in routes:
|
||||
route[Route.NEXT_HOP_INTERFACE] = 'eth1'
|
||||
route[Route.NEXT_HOP_INTERFACE] = "eth1"
|
||||
route_state = state.State({Route.KEY: {Route.CONFIG: routes}})
|
||||
expected_indexed_route_state = {
|
||||
'eth1': sorted([state.RouteEntry(r) for r in routes])
|
||||
"eth1": sorted([state.RouteEntry(r) for r in routes])
|
||||
}
|
||||
|
||||
assert expected_indexed_route_state == route_state.config_iface_routes
|
||||
@ -698,7 +698,7 @@ def test_state_iface_routes_order():
|
||||
# Changing all routes to eth1
|
||||
routes = _get_mixed_test_routes()
|
||||
for route in routes:
|
||||
route[Route.NEXT_HOP_INTERFACE] = 'eth1'
|
||||
route[Route.NEXT_HOP_INTERFACE] = "eth1"
|
||||
|
||||
route_state = state.State(
|
||||
{Route.KEY: {Route.CONFIG: [routes[0], routes[1]]}}
|
||||
@ -732,7 +732,7 @@ def test_state_verify_route_diff_route_count():
|
||||
def test_state_verify_route_diff_route_prop():
|
||||
routes = _get_mixed_test_routes()
|
||||
route_state = state.State({Route.KEY: {Route.CONFIG: routes}})
|
||||
routes[0][Route.NEXT_HOP_INTERFACE] = 'another_nic'
|
||||
routes[0][Route.NEXT_HOP_INTERFACE] = "another_nic"
|
||||
route_state_2 = state.State({Route.KEY: {Route.CONFIG: routes}})
|
||||
|
||||
with pytest.raises(NmstateVerificationError):
|
||||
@ -746,8 +746,8 @@ def test_state_verify_route_empty():
|
||||
|
||||
|
||||
def _get_mixed_test_routes():
|
||||
r0 = _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
r1 = _create_route('2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104)
|
||||
r0 = _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
r1 = _create_route("2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104)
|
||||
return [r0.to_dict(), r1.to_dict()]
|
||||
|
||||
|
||||
@ -767,8 +767,8 @@ def _gen_iface_states_for_routes(routes):
|
||||
def _route_sort_key(route):
|
||||
return (
|
||||
route.get(Route.TABLE_ID, Route.USE_DEFAULT_ROUTE_TABLE),
|
||||
route.get(Route.NEXT_HOP_INTERFACE, ''),
|
||||
route.get(Route.DESTINATION, ''),
|
||||
route.get(Route.NEXT_HOP_INTERFACE, ""),
|
||||
route.get(Route.DESTINATION, ""),
|
||||
)
|
||||
|
||||
|
||||
@ -815,8 +815,8 @@ class TestAssertDnsState:
|
||||
def _get_test_dns_config(self):
|
||||
return {
|
||||
DNS.CONFIG: {
|
||||
DNS.SERVER: ['192.168.122.1', '2001:db8:a::1'],
|
||||
DNS.SEARCH: ['example.com', 'example.org'],
|
||||
DNS.SERVER: ["192.168.122.1", "2001:db8:a::1"],
|
||||
DNS.SEARCH: ["example.com", "example.org"],
|
||||
}
|
||||
}
|
||||
|
||||
@ -835,111 +835,111 @@ class TestStateMatch:
|
||||
assert not state.state_match({}, [])
|
||||
|
||||
def test_match_list_vs_string(self):
|
||||
assert not state.state_match(['a', 'b', 'c'], 'abc')
|
||||
assert not state.state_match(["a", "b", "c"], "abc")
|
||||
|
||||
def test_match_dict_identical(self):
|
||||
assert state.state_match({'a': 1, 'b': 2}, {'a': 1, 'b': 2})
|
||||
assert state.state_match({"a": 1, "b": 2}, {"a": 1, "b": 2})
|
||||
|
||||
def test_match_dict_current_has_more_data(self):
|
||||
assert state.state_match({'a': 1}, {'a': 1, 'b': 2})
|
||||
assert state.state_match({"a": 1}, {"a": 1, "b": 2})
|
||||
|
||||
def test_match_dict_desire_has_more_data(self):
|
||||
assert not state.state_match({'a': 1, 'b': 2}, {'a': 1})
|
||||
assert not state.state_match({"a": 1, "b": 2}, {"a": 1})
|
||||
|
||||
def test_match_dict_different_value_type(self):
|
||||
assert not state.state_match({'a': 1, 'b': []}, {'a': 1, 'b': 2})
|
||||
assert not state.state_match({"a": 1, "b": []}, {"a": 1, "b": 2})
|
||||
|
||||
def test_match_list_identical(self):
|
||||
assert state.state_match(['a', 'b', 1], ['a', 'b', 1])
|
||||
assert state.state_match(["a", "b", 1], ["a", "b", 1])
|
||||
|
||||
def test_match_list_different_order(self):
|
||||
assert not state.state_match(['a', 'b', 1], ['a', 1, 'b'])
|
||||
assert not state.state_match(["a", "b", 1], ["a", 1, "b"])
|
||||
|
||||
def test_match_list_current_contains_more(self):
|
||||
assert not state.state_match(['a', 'b', 1], ['a', 'b', 'c', 1])
|
||||
assert not state.state_match(["a", "b", 1], ["a", "b", "c", 1])
|
||||
|
||||
def test_match_indentical_set(self):
|
||||
assert state.state_match(set(['a', 'b', 1]), set(['a', 'b', 1]))
|
||||
assert state.state_match(set(['a', 1, 'b']), set(['a', 'b', 1]))
|
||||
assert state.state_match(set(['a', 1, 1, 'b']), set(['a', 'b', 1]))
|
||||
assert state.state_match(set(["a", "b", 1]), set(["a", "b", 1]))
|
||||
assert state.state_match(set(["a", 1, "b"]), set(["a", "b", 1]))
|
||||
assert state.state_match(set(["a", 1, 1, "b"]), set(["a", "b", 1]))
|
||||
|
||||
def test_match_parital_set(self):
|
||||
assert not state.state_match(
|
||||
set(['a', 'b', 1]), set(['a', 'b', 'c', 1])
|
||||
set(["a", "b", 1]), set(["a", "b", "c", 1])
|
||||
)
|
||||
|
||||
def test_match_nested_list_in_dict(self):
|
||||
assert state.state_match({'a': 1, 'b': [1, 2]}, {'a': 1, 'b': [1, 2]})
|
||||
assert state.state_match({"a": 1, "b": [1, 2]}, {"a": 1, "b": [1, 2]})
|
||||
|
||||
def test_match_nested_dict_in_list(self):
|
||||
assert state.state_match(
|
||||
[{'a': 1, 'b': [1, 2]}, {'a': 2, 'b': [3, 4]}],
|
||||
[{'a': 1, 'b': [1, 2]}, {'a': 2, 'b': [3, 4]}],
|
||||
[{"a": 1, "b": [1, 2]}, {"a": 2, "b": [3, 4]}],
|
||||
[{"a": 1, "b": [1, 2]}, {"a": 2, "b": [3, 4]}],
|
||||
)
|
||||
assert state.state_match(
|
||||
[{'a': 1}, {'a': 2, 'b': [3, 4]}],
|
||||
[{'a': 1, 'b': [1, 2]}, {'a': 2, 'b': [3, 4]}],
|
||||
[{"a": 1}, {"a": 2, "b": [3, 4]}],
|
||||
[{"a": 1, "b": [1, 2]}, {"a": 2, "b": [3, 4]}],
|
||||
)
|
||||
assert not state.state_match(
|
||||
[{'a': 2, 'b': [3, 4]}, {'a': 1, 'b': [1, 2]}],
|
||||
[{'a': 1, 'b': [1, 2]}, {'a': 2, 'b': [3, 4]}],
|
||||
[{"a": 2, "b": [3, 4]}, {"a": 1, "b": [1, 2]}],
|
||||
[{"a": 1, "b": [1, 2]}, {"a": 2, "b": [3, 4]}],
|
||||
)
|
||||
|
||||
|
||||
class TestRouteRuleEntry:
|
||||
def test_hash_unique(self):
|
||||
rule = _create_route_rule('198.51.100.0/24', '192.0.2.1', 50, 103)
|
||||
rule = _create_route_rule("198.51.100.0/24", "192.0.2.1", 50, 103)
|
||||
assert hash(rule) == hash(rule)
|
||||
|
||||
def test_obj_unique(self):
|
||||
rule0 = _create_route_rule('198.51.100.0/24', '192.0.2.1', 50, 103)
|
||||
rule1 = _create_route_rule('2001:db8:a::/64', '2001:db8:1::a', 51, 104)
|
||||
rule0 = _create_route_rule("198.51.100.0/24", "192.0.2.1", 50, 103)
|
||||
rule1 = _create_route_rule("2001:db8:a::/64", "2001:db8:1::a", 51, 104)
|
||||
rule0_clone = _create_route_rule(
|
||||
'198.51.100.0/24', '192.0.2.1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", 50, 103
|
||||
)
|
||||
assert rule0 == rule0_clone
|
||||
assert rule0 != rule1
|
||||
|
||||
def test_obj_unique_without_table(self):
|
||||
rule_with_default_table_id = _create_route_rule(
|
||||
'198.51.100.0/24',
|
||||
'192.0.2.1',
|
||||
"198.51.100.0/24",
|
||||
"192.0.2.1",
|
||||
103,
|
||||
RouteRule.USE_DEFAULT_ROUTE_TABLE,
|
||||
)
|
||||
|
||||
rule_without_table_id = _create_route_rule(
|
||||
'198.51.100.0/24', '192.0.2.1', 103, None
|
||||
"198.51.100.0/24", "192.0.2.1", 103, None
|
||||
)
|
||||
|
||||
assert rule_without_table_id == rule_with_default_table_id
|
||||
|
||||
def test_obj_unique_without_priority(self):
|
||||
rule_with_default_priority = _create_route_rule(
|
||||
'198.51.100.0/24', '192.0.2.1', RouteRule.USE_DEFAULT_PRIORITY, 50
|
||||
"198.51.100.0/24", "192.0.2.1", RouteRule.USE_DEFAULT_PRIORITY, 50
|
||||
)
|
||||
|
||||
rule_without_priority = _create_route_rule(
|
||||
'198.51.100.0/24', '192.0.2.1', None, 50
|
||||
"198.51.100.0/24", "192.0.2.1", None, 50
|
||||
)
|
||||
|
||||
assert rule_without_priority == rule_with_default_priority
|
||||
|
||||
def test_normal_object_as_dict(self):
|
||||
rule = _create_route_rule_dict('198.51.100.0/24', '192.0.2.1', 50, 103)
|
||||
rule = _create_route_rule_dict("198.51.100.0/24", "192.0.2.1", 50, 103)
|
||||
rule_obj = state.RouteRuleEntry(rule)
|
||||
assert rule_obj.to_dict() == rule
|
||||
|
||||
def test_sort_routes(self):
|
||||
rules = [
|
||||
_create_route_rule('198.51.100.1/24', '192.0.2.1', 50, 103),
|
||||
_create_route_rule('198.51.100.0/24', '192.0.2.1', 50, 103),
|
||||
_create_route_rule('198.51.100.0/24', '192.0.2.1', 10, 103),
|
||||
_create_route_rule("198.51.100.1/24", "192.0.2.1", 50, 103),
|
||||
_create_route_rule("198.51.100.0/24", "192.0.2.1", 50, 103),
|
||||
_create_route_rule("198.51.100.0/24", "192.0.2.1", 10, 103),
|
||||
]
|
||||
expected_rules = [
|
||||
_create_route_rule('198.51.100.0/24', '192.0.2.1', 10, 103),
|
||||
_create_route_rule('198.51.100.0/24', '192.0.2.1', 50, 103),
|
||||
_create_route_rule('198.51.100.1/24', '192.0.2.1', 50, 103),
|
||||
_create_route_rule("198.51.100.0/24", "192.0.2.1", 10, 103),
|
||||
_create_route_rule("198.51.100.0/24", "192.0.2.1", 50, 103),
|
||||
_create_route_rule("198.51.100.1/24", "192.0.2.1", 50, 103),
|
||||
]
|
||||
assert expected_rules == sorted(rules)
|
||||
|
||||
@ -949,13 +949,13 @@ class TestRouteRuleEntry:
|
||||
RouteRule.KEY: {
|
||||
RouteRule.CONFIG: [
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.1/24', '192.0.2.1', 50, 103
|
||||
"198.51.100.1/24", "192.0.2.1", 50, 103
|
||||
),
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", 50, 103
|
||||
),
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 10, 104
|
||||
"198.51.100.0/24", "192.0.2.1", 10, 104
|
||||
),
|
||||
]
|
||||
}
|
||||
@ -967,13 +967,13 @@ class TestRouteRuleEntry:
|
||||
RouteRule.KEY: {
|
||||
RouteRule.CONFIG: [
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 10, 104
|
||||
"198.51.100.0/24", "192.0.2.1", 10, 104
|
||||
),
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.1/24', '192.0.2.1', 50, 103
|
||||
"198.51.100.1/24", "192.0.2.1", 50, 103
|
||||
),
|
||||
_create_route_rule_dict(
|
||||
'198.51.100.0/24', '192.0.2.1', 50, 103
|
||||
"198.51.100.0/24", "192.0.2.1", 50, 103
|
||||
),
|
||||
]
|
||||
}
|
||||
@ -1001,7 +1001,7 @@ def test_remove_unknown_interfaces():
|
||||
desired_state = state.State(
|
||||
{
|
||||
Interface.KEY: [
|
||||
{Interface.NAME: 'foo', Interface.TYPE: InterfaceType.UNKNOWN}
|
||||
{Interface.NAME: "foo", Interface.TYPE: InterfaceType.UNKNOWN}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
@ -37,8 +37,8 @@ class TestLinkAggregationState:
|
||||
desired_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [
|
||||
{'name': 'bond0', 'link-aggregation': {'slaves': []}},
|
||||
{'name': 'bond1', 'link-aggregation': {'slaves': []}},
|
||||
{"name": "bond0", "link-aggregation": {"slaves": []}},
|
||||
{"name": "bond1", "link-aggregation": {"slaves": []}},
|
||||
]
|
||||
}
|
||||
)
|
||||
@ -51,15 +51,15 @@ class TestLinkAggregationState:
|
||||
desired_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [
|
||||
{'name': 'slave0'},
|
||||
{'name': 'slave1'},
|
||||
{"name": "slave0"},
|
||||
{"name": "slave1"},
|
||||
{
|
||||
'name': 'bond0',
|
||||
'link-aggregation': {'slaves': ['slave0']},
|
||||
"name": "bond0",
|
||||
"link-aggregation": {"slaves": ["slave0"]},
|
||||
},
|
||||
{
|
||||
'name': 'bond1',
|
||||
'link-aggregation': {'slaves': ['slave1']},
|
||||
"name": "bond1",
|
||||
"link-aggregation": {"slaves": ["slave1"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -72,17 +72,17 @@ class TestLinkAggregationState:
|
||||
desired_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [
|
||||
{'name': 'slave0'},
|
||||
{'name': 'slave1'},
|
||||
{'name': 'slave00'},
|
||||
{'name': 'slave11'},
|
||||
{"name": "slave0"},
|
||||
{"name": "slave1"},
|
||||
{"name": "slave00"},
|
||||
{"name": "slave11"},
|
||||
{
|
||||
'name': 'bond0',
|
||||
'link-aggregation': {'slaves': ['slave0', 'slave00']},
|
||||
"name": "bond0",
|
||||
"link-aggregation": {"slaves": ["slave0", "slave00"]},
|
||||
},
|
||||
{
|
||||
'name': 'bond1',
|
||||
'link-aggregation': {'slaves': ['slave1', 'slave11']},
|
||||
"name": "bond1",
|
||||
"link-aggregation": {"slaves": ["slave1", "slave11"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -95,16 +95,16 @@ class TestLinkAggregationState:
|
||||
desired_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [
|
||||
{'name': 'slave0'},
|
||||
{'name': 'slave1'},
|
||||
{'name': 'slave00'},
|
||||
{"name": "slave0"},
|
||||
{"name": "slave1"},
|
||||
{"name": "slave00"},
|
||||
{
|
||||
'name': 'bond0',
|
||||
'link-aggregation': {'slaves': ['slave0', 'slave00']},
|
||||
"name": "bond0",
|
||||
"link-aggregation": {"slaves": ["slave0", "slave00"]},
|
||||
},
|
||||
{
|
||||
'name': 'bond1',
|
||||
'link-aggregation': {'slaves': ['slave1', 'slave00']},
|
||||
"name": "bond1",
|
||||
"link-aggregation": {"slaves": ["slave1", "slave00"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -118,15 +118,15 @@ class TestLinkAggregationState:
|
||||
desired_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [
|
||||
{'name': 'slave0'},
|
||||
{'name': 'slave1'},
|
||||
{"name": "slave0"},
|
||||
{"name": "slave1"},
|
||||
{
|
||||
'name': 'bond0',
|
||||
'link-aggregation': {'slaves': ['slave0', 'slave00']},
|
||||
"name": "bond0",
|
||||
"link-aggregation": {"slaves": ["slave0", "slave00"]},
|
||||
},
|
||||
{
|
||||
'name': 'bond1',
|
||||
'link-aggregation': {'slaves': ['slave1', 'slave11']},
|
||||
"name": "bond1",
|
||||
"link-aggregation": {"slaves": ["slave1", "slave11"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -139,7 +139,7 @@ class TestLinkAggregationState:
|
||||
|
||||
@pytest.mark.xfail(
|
||||
raises=NmstateNotImplementedError,
|
||||
reason='https://nmstate.atlassian.net/browse/NMSTATE-220',
|
||||
reason="https://nmstate.atlassian.net/browse/NMSTATE-220",
|
||||
strict=True,
|
||||
)
|
||||
def test_dns_three_nameservers():
|
||||
@ -147,7 +147,7 @@ def test_dns_three_nameservers():
|
||||
{
|
||||
DNS.KEY: {
|
||||
DNS.CONFIG: {
|
||||
DNS.SERVER: ['8.8.8.8', '2001:4860:4860::8888', '8.8.4.4']
|
||||
DNS.SERVER: ["8.8.8.8", "2001:4860:4860::8888", "8.8.4.4"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(state.State({}), state.State({}))
|
||||
|
||||
def test_valid_route_based_on_desired_state(self):
|
||||
iface0 = _create_interface_state('eth1', ipv4=True)
|
||||
iface0 = _create_interface_state("eth1", ipv4=True)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -175,7 +175,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, state.State({}))
|
||||
|
||||
def test_valid_route_based_on_current_state(self):
|
||||
iface0 = _create_interface_state('eth1', ipv4=True)
|
||||
iface0 = _create_interface_state("eth1", ipv4=True)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -206,7 +206,7 @@ class TestRouteValidation:
|
||||
|
||||
def test_invalid_route_due_to_non_up_iface(self):
|
||||
iface0 = _create_interface_state(
|
||||
'eth1', state=schema.InterfaceState.DOWN, ipv4=True
|
||||
"eth1", state=schema.InterfaceState.DOWN, ipv4=True
|
||||
)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
@ -219,7 +219,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, state.State({}))
|
||||
|
||||
def test_invalid_route_due_to_missing_ipv4(self):
|
||||
iface0 = _create_interface_state('eth1', ipv4=False)
|
||||
iface0 = _create_interface_state("eth1", ipv4=False)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -231,7 +231,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, state.State({}))
|
||||
|
||||
def test_invalid_route_due_to_missing_ipv6(self):
|
||||
iface1 = _create_interface_state('eth2', ipv6=False)
|
||||
iface1 = _create_interface_state("eth2", ipv6=False)
|
||||
route1 = self._create_route1()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -243,7 +243,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, state.State({}))
|
||||
|
||||
def test_valid_route_based_on_desired_state_but_not_current(self):
|
||||
iface0 = _create_interface_state('eth1', ipv4=True)
|
||||
iface0 = _create_interface_state("eth1", ipv4=True)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -252,7 +252,7 @@ class TestRouteValidation:
|
||||
}
|
||||
)
|
||||
iface0_down = _create_interface_state(
|
||||
'eth1', state=schema.InterfaceState.DOWN
|
||||
"eth1", state=schema.InterfaceState.DOWN
|
||||
)
|
||||
current_state = state.State(
|
||||
{
|
||||
@ -264,7 +264,7 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, current_state)
|
||||
|
||||
def test_invalid_route_based_on_desired_state_but_not_current(self):
|
||||
iface0_ipv4_disabled = _create_interface_state('eth1', ipv4=False)
|
||||
iface0_ipv4_disabled = _create_interface_state("eth1", ipv4=False)
|
||||
route0 = self._create_route0()
|
||||
desired_state = state.State(
|
||||
{
|
||||
@ -272,7 +272,7 @@ class TestRouteValidation:
|
||||
schema.Route.KEY: {schema.Route.CONFIG: [route0]},
|
||||
}
|
||||
)
|
||||
iface0_ipv4_enabled = _create_interface_state('eth1', ipv4=True)
|
||||
iface0_ipv4_enabled = _create_interface_state("eth1", ipv4=True)
|
||||
current_state = state.State(
|
||||
{
|
||||
schema.Interface.KEY: [iface0_ipv4_enabled],
|
||||
@ -284,18 +284,18 @@ class TestRouteValidation:
|
||||
validator.validate_routes(desired_state, current_state)
|
||||
|
||||
def _create_route0(self):
|
||||
return _create_route('198.51.100.0/24', '192.0.2.1', 'eth1', 50, 103)
|
||||
return _create_route("198.51.100.0/24", "192.0.2.1", "eth1", 50, 103)
|
||||
|
||||
def _create_route1(self):
|
||||
return _create_route(
|
||||
'2001:db8:a::/64', '2001:db8:1::a', 'eth2', 51, 104
|
||||
"2001:db8:a::/64", "2001:db8:1::a", "eth2", 51, 104
|
||||
)
|
||||
|
||||
|
||||
class TestVxlanValidation:
|
||||
|
||||
parametrize_vxlan_req_fields = pytest.mark.parametrize(
|
||||
'required_field', [VXLAN.ID, VXLAN.REMOTE, VXLAN.BASE_IFACE]
|
||||
"required_field", [VXLAN.ID, VXLAN.REMOTE, VXLAN.BASE_IFACE]
|
||||
)
|
||||
|
||||
@parametrize_vxlan_req_fields
|
||||
@ -303,12 +303,12 @@ class TestVxlanValidation:
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'eth0.101',
|
||||
schema.Interface.NAME: "eth0.101",
|
||||
schema.Interface.TYPE: VXLAN.TYPE,
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: 99,
|
||||
VXLAN.REMOTE: '192.168.3.3',
|
||||
VXLAN.BASE_IFACE: 'eth0',
|
||||
VXLAN.REMOTE: "192.168.3.3",
|
||||
VXLAN.BASE_IFACE: "eth0",
|
||||
},
|
||||
}
|
||||
]
|
||||
@ -327,11 +327,11 @@ class TestVxlanValidation:
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'eth0.101',
|
||||
schema.Interface.NAME: "eth0.101",
|
||||
schema.Interface.TYPE: VXLAN.TYPE,
|
||||
VXLAN.CONFIG_SUBTREE: {
|
||||
VXLAN.ID: 99,
|
||||
VXLAN.REMOTE: '192.168.3.3',
|
||||
VXLAN.REMOTE: "192.168.3.3",
|
||||
VXLAN.BASE_IFACE: "eth0",
|
||||
},
|
||||
}
|
||||
@ -356,12 +356,12 @@ class TestVlanFilteringValidation:
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'br0',
|
||||
schema.Interface.NAME: "br0",
|
||||
schema.Interface.TYPE: LB.TYPE,
|
||||
schema.Interface.STATE: schema.InterfaceState.UP,
|
||||
LB.PORT_SUBTREE: [
|
||||
{
|
||||
LB.Port.NAME: 'eth1',
|
||||
LB.Port.NAME: "eth1",
|
||||
LB.Port.VLAN_SUBTREE: invalid_vlan_config,
|
||||
}
|
||||
],
|
||||
@ -369,7 +369,7 @@ class TestVlanFilteringValidation:
|
||||
]
|
||||
}
|
||||
with pytest.raises(
|
||||
NmstateValueError, match='Access port cannot have trunk tags'
|
||||
NmstateValueError, match="Access port cannot have trunk tags"
|
||||
):
|
||||
libnmstate.validator.validate_bridge(desired_state)
|
||||
|
||||
@ -381,12 +381,12 @@ class TestVlanFilteringValidation:
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'br0',
|
||||
schema.Interface.NAME: "br0",
|
||||
schema.Interface.TYPE: LB.TYPE,
|
||||
schema.Interface.STATE: schema.InterfaceState.UP,
|
||||
LB.PORT_SUBTREE: [
|
||||
{
|
||||
LB.Port.NAME: 'eth1',
|
||||
LB.Port.NAME: "eth1",
|
||||
LB.Port.VLAN_SUBTREE: invalid_vlan_config,
|
||||
}
|
||||
],
|
||||
@ -395,7 +395,7 @@ class TestVlanFilteringValidation:
|
||||
}
|
||||
with pytest.raises(
|
||||
NmstateValueError,
|
||||
match='A trunk port needs to specify trunk tags',
|
||||
match="A trunk port needs to specify trunk tags",
|
||||
):
|
||||
libnmstate.validator.validate_bridge(desired_state)
|
||||
|
||||
@ -415,12 +415,12 @@ class TestVlanFilteringValidation:
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'br0',
|
||||
schema.Interface.NAME: "br0",
|
||||
schema.Interface.TYPE: LB.TYPE,
|
||||
schema.Interface.STATE: schema.InterfaceState.UP,
|
||||
LB.PORT_SUBTREE: [
|
||||
{
|
||||
LB.Port.NAME: 'eth1',
|
||||
LB.Port.NAME: "eth1",
|
||||
LB.Port.VLAN_SUBTREE: invalid_vlan_config,
|
||||
}
|
||||
],
|
||||
@ -430,26 +430,26 @@ class TestVlanFilteringValidation:
|
||||
with pytest.raises(NmstateValueError) as err:
|
||||
libnmstate.validator.validate_bridge(desired_state)
|
||||
assert (
|
||||
'Trunk port cannot be configured by both id and range'
|
||||
"Trunk port cannot be configured by both id and range"
|
||||
in err.value.args[0]
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'range_key',
|
||||
"range_key",
|
||||
[LB.Port.Vlan.TrunkTags.MIN_RANGE, LB.Port.Vlan.TrunkTags.MAX_RANGE],
|
||||
ids=['only_min', 'only_max'],
|
||||
ids=["only_min", "only_max"],
|
||||
)
|
||||
def test_vlan_ranges_must_have_min_and_max(self, range_key):
|
||||
vlan_tag = 101
|
||||
desired_state = {
|
||||
schema.Interface.KEY: [
|
||||
{
|
||||
schema.Interface.NAME: 'br0',
|
||||
schema.Interface.NAME: "br0",
|
||||
schema.Interface.TYPE: LB.TYPE,
|
||||
schema.Interface.STATE: schema.InterfaceState.UP,
|
||||
LB.PORT_SUBTREE: [
|
||||
{
|
||||
LB.Port.NAME: 'eth1',
|
||||
LB.Port.NAME: "eth1",
|
||||
LB.Port.VLAN_SUBTREE: {
|
||||
LB.Port.Vlan.MODE: LB.Port.Vlan.Mode.TRUNK,
|
||||
LB.Port.Vlan.TRUNK_TAGS: [
|
||||
@ -467,7 +467,7 @@ class TestVlanFilteringValidation:
|
||||
}
|
||||
with pytest.raises(NmstateValueError) as err:
|
||||
libnmstate.validator.validate_bridge(desired_state)
|
||||
assert 'Trunk port range requires min / max keys' in err.value.args[0]
|
||||
assert "Trunk port range requires min / max keys" in err.value.args[0]
|
||||
|
||||
|
||||
def _create_interface_state(
|
||||
|
Loading…
x
Reference in New Issue
Block a user