mirror of
https://github.com/linux-system-roles/network.git
synced 2026-01-23 10:25:28 +00:00
5601 lines
206 KiB
Python
5601 lines
206 KiB
Python
#!/usr/bin/env python
|
|
"""Tests for network_connections Ansible module"""
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
import copy
|
|
import itertools
|
|
import pprint as pprint_
|
|
import socket
|
|
import sys
|
|
import unittest
|
|
|
|
try:
|
|
from unittest import mock
|
|
from unittest.mock import MagicMock
|
|
except ImportError: # py2
|
|
import mock
|
|
from mock import MagicMock
|
|
|
|
sys.modules["ansible.module_utils.basic"] = mock.Mock()
|
|
|
|
# pylint: disable=import-error, wrong-import-position
|
|
|
|
import network_lsr
|
|
import network_lsr.argument_validator
|
|
from network_connections import IfcfgUtil, NMUtil, SysUtil, Util
|
|
from network_lsr.argument_validator import ValidationError
|
|
|
|
try:
|
|
my_test_skipIf = unittest.skipIf
|
|
except AttributeError:
|
|
# python 2.6 workaround
|
|
def my_test_skipIf(condition, reason):
|
|
if condition:
|
|
return lambda x: None
|
|
else:
|
|
return lambda x: x
|
|
|
|
|
|
try:
|
|
nmutil = NMUtil()
|
|
assert nmutil
|
|
except Exception:
|
|
# NMUtil is not supported, for example on RHEL 6 or without
|
|
# pygobject.
|
|
nmutil = None
|
|
|
|
if nmutil:
|
|
NM = Util.NM()
|
|
GObject = Util.GObject()
|
|
|
|
|
|
def pprint(msg, obj):
|
|
print("PRINT: %s\n" % (msg))
|
|
|
|
p = pprint_.PrettyPrinter(indent=4)
|
|
p.pprint(obj)
|
|
if nmutil is not None and isinstance(obj, NM.Connection):
|
|
obj.dump()
|
|
|
|
|
|
class Python26CompatTestCase(unittest.TestCase):
|
|
# pylint: disable=no-member
|
|
def assertRaisesRegex(self, exception, regex, *args, **kwargs):
|
|
if sys.version_info[:2] == (2, 6):
|
|
self.assertRaises(exception, *args, **kwargs)
|
|
elif sys.version_info[:2] < (3, 2):
|
|
self.assertRaisesRegexp(exception, regex, *args, **kwargs)
|
|
else:
|
|
super(Python26CompatTestCase, self).assertRaisesRegex(
|
|
exception, regex, *args, **kwargs
|
|
)
|
|
|
|
|
|
ARGS_CONNECTIONS = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
VALIDATE_ONE_MODE_INITSCRIPTS = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_INITSCRIPTS
|
|
VALIDATE_ONE_MODE_NM = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_NM
|
|
|
|
ETHTOOL_FEATURES_DEFAULTS = {
|
|
"esp_hw_offload": None,
|
|
"esp_tx_csum_hw_offload": None,
|
|
"fcoe_mtu": None,
|
|
"gro": None,
|
|
"gso": None,
|
|
"highdma": None,
|
|
"hw_tc_offload": None,
|
|
"l2_fwd_offload": None,
|
|
"loopback": None,
|
|
"lro": None,
|
|
"ntuple": None,
|
|
"rx": None,
|
|
"rx_all": None,
|
|
"rx_fcs": None,
|
|
"rx_gro_hw": None,
|
|
"rx_udp_tunnel_port_offload": None,
|
|
"rx_vlan_filter": None,
|
|
"rx_vlan_stag_filter": None,
|
|
"rx_vlan_stag_hw_parse": None,
|
|
"rxhash": None,
|
|
"rxvlan": None,
|
|
"sg": None,
|
|
"tls_hw_record": None,
|
|
"tls_hw_tx_offload": None,
|
|
"tso": None,
|
|
"tx": None,
|
|
"tx_checksum_fcoe_crc": None,
|
|
"tx_checksum_ip_generic": None,
|
|
"tx_checksum_ipv4": None,
|
|
"tx_checksum_ipv6": None,
|
|
"tx_checksum_sctp": None,
|
|
"tx_esp_segmentation": None,
|
|
"tx_fcoe_segmentation": None,
|
|
"tx_gre_csum_segmentation": None,
|
|
"tx_gre_segmentation": None,
|
|
"tx_gso_partial": None,
|
|
"tx_gso_robust": None,
|
|
"tx_ipxip4_segmentation": None,
|
|
"tx_ipxip6_segmentation": None,
|
|
"tx_nocache_copy": None,
|
|
"tx_scatter_gather": None,
|
|
"tx_scatter_gather_fraglist": None,
|
|
"tx_sctp_segmentation": None,
|
|
"tx_tcp_ecn_segmentation": None,
|
|
"tx_tcp_mangleid_segmentation": None,
|
|
"tx_tcp_segmentation": None,
|
|
"tx_tcp6_segmentation": None,
|
|
"tx_udp_segmentation": None,
|
|
"tx_udp_tnl_csum_segmentation": None,
|
|
"tx_udp_tnl_segmentation": None,
|
|
"tx_vlan_stag_hw_insert": None,
|
|
"txvlan": None,
|
|
}
|
|
|
|
|
|
ETHTOOL_COALESCE_DEFAULTS = {
|
|
"adaptive_rx": None,
|
|
"adaptive_tx": None,
|
|
"pkt_rate_high": None,
|
|
"pkt_rate_low": None,
|
|
"rx_frames": None,
|
|
"rx_frames_high": None,
|
|
"rx_frames_irq": None,
|
|
"rx_frames_low": None,
|
|
"rx_usecs": None,
|
|
"rx_usecs_high": None,
|
|
"rx_usecs_irq": None,
|
|
"rx_usecs_low": None,
|
|
"sample_interval": None,
|
|
"stats_block_usecs": None,
|
|
"tx_frames": None,
|
|
"tx_frames_high": None,
|
|
"tx_frames_irq": None,
|
|
"tx_frames_low": None,
|
|
"tx_usecs": None,
|
|
"tx_usecs_high": None,
|
|
"tx_usecs_irq": None,
|
|
"tx_usecs_low": None,
|
|
}
|
|
|
|
ETHTOOL_RING_DEFAULTS = {
|
|
"rx": None,
|
|
"rx_jumbo": None,
|
|
"rx_mini": None,
|
|
"tx": None,
|
|
}
|
|
|
|
|
|
ETHTOOL_DEFAULTS = {
|
|
"features": ETHTOOL_FEATURES_DEFAULTS,
|
|
"coalesce": ETHTOOL_COALESCE_DEFAULTS,
|
|
"ring": ETHTOOL_RING_DEFAULTS,
|
|
}
|
|
|
|
ETHERNET_DEFAULTS = {"autoneg": None, "duplex": None, "speed": 0}
|
|
|
|
|
|
class TestValidator(Python26CompatTestCase):
|
|
def setUp(self):
|
|
# default values when "type" is specified and state is not
|
|
self.default_connection_settings = {
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"ignore_errors": None,
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"port_type": None,
|
|
"zone": None,
|
|
}
|
|
|
|
def assertValidationError(self, v, value):
|
|
self.assertRaises(ValidationError, v.validate, value)
|
|
|
|
def assert_nm_connection_routes_expected(self, connection, route_list_expected):
|
|
parser = network_lsr.argument_validator.ArgValidatorIPRoute("route[?]")
|
|
route_list_exp = [parser.validate(r) for r in route_list_expected]
|
|
route_list_new = itertools.chain(
|
|
nmutil.setting_ip_config_get_routes(
|
|
connection.get_setting(NM.SettingIP4Config)
|
|
),
|
|
nmutil.setting_ip_config_get_routes(
|
|
connection.get_setting(NM.SettingIP6Config)
|
|
),
|
|
)
|
|
route_list_new = [
|
|
{
|
|
"family": r.get_family(),
|
|
"network": r.get_dest(),
|
|
"prefix": int(r.get_prefix()),
|
|
"gateway": r.get_next_hop(),
|
|
"metric": int(r.get_metric()),
|
|
"type": r.get_attribute("type"),
|
|
"table": r.get_attribute("table"),
|
|
"src": r.get_attribute("src"),
|
|
}
|
|
for r in route_list_new
|
|
]
|
|
self.assertEqual(route_list_exp, route_list_new)
|
|
|
|
def do_connections_check_invalid(self, input_connections):
|
|
self.assertValidationError(ARGS_CONNECTIONS, input_connections)
|
|
|
|
def do_connections_validate_nm(self, input_connections, **kwargs):
|
|
if not nmutil:
|
|
return
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
for connection in connections:
|
|
if "type" in connection:
|
|
connection["nm.exists"] = False
|
|
connection["nm.uuid"] = Util.create_uuid()
|
|
|
|
mode = VALIDATE_ONE_MODE_NM
|
|
for idx, connection in enumerate(connections):
|
|
try:
|
|
ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)
|
|
except ValidationError:
|
|
continue
|
|
if "type" in connection:
|
|
con_new = nmutil.connection_create(connections, idx)
|
|
self.assertTrue(con_new)
|
|
self.assertTrue(con_new.verify())
|
|
if "nm_route_list_current" in kwargs:
|
|
parser = network_lsr.argument_validator.ArgValidatorIPRoute(
|
|
"route[?]"
|
|
)
|
|
s4 = con_new.get_setting(NM.SettingIP4Config)
|
|
s6 = con_new.get_setting(NM.SettingIP6Config)
|
|
s4.clear_routes()
|
|
s6.clear_routes()
|
|
for r in kwargs["nm_route_list_current"][idx]:
|
|
r = parser.validate(r)
|
|
new_route = NM.IPRoute.new(
|
|
r["family"],
|
|
r["network"],
|
|
r["prefix"],
|
|
r["gateway"],
|
|
r["metric"],
|
|
)
|
|
if r["type"]:
|
|
NM.IPRoute.set_attribute(
|
|
new_route,
|
|
"type",
|
|
Util.GLib().Variant("s", r["type"]),
|
|
)
|
|
if r["table"]:
|
|
NM.IPRoute.set_attribute(
|
|
new_route,
|
|
"table",
|
|
Util.GLib().Variant.new_uint32(r["table"]),
|
|
)
|
|
if r["src"]:
|
|
NM.IPRoute.set_attribute(
|
|
new_route,
|
|
"src",
|
|
Util.GLib().Variant.new_uint32(r["src"]),
|
|
)
|
|
if r["family"] == socket.AF_INET:
|
|
s4.add_route(new_route)
|
|
else:
|
|
s6.add_route(new_route)
|
|
con_new = nmutil.connection_create(
|
|
connections, idx, connection_current=con_new
|
|
)
|
|
self.assertTrue(con_new)
|
|
self.assertTrue(con_new.verify())
|
|
if "nm_route_list_expected" in kwargs:
|
|
self.assert_nm_connection_routes_expected(
|
|
con_new, kwargs["nm_route_list_expected"][idx]
|
|
)
|
|
|
|
def do_connections_validate_ifcfg(self, input_connections, **kwargs):
|
|
mode = VALIDATE_ONE_MODE_INITSCRIPTS
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
for idx, connection in enumerate(connections):
|
|
try:
|
|
ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)
|
|
except ValidationError:
|
|
continue
|
|
if "type" not in connection:
|
|
continue
|
|
if (
|
|
connection["type"] in ["macvlan", "wireless"]
|
|
or connection["ieee802_1x"]
|
|
):
|
|
# initscripts do not support this type. Skip the test.
|
|
continue
|
|
content_current = kwargs.get("initscripts_content_current", None)
|
|
if content_current:
|
|
content_current = content_current[idx]
|
|
warnings = []
|
|
config = IfcfgUtil.ifcfg_create(
|
|
connections,
|
|
idx,
|
|
content_current=content_current,
|
|
warn_fcn=warnings.append,
|
|
)
|
|
# pprint("con[%s] = \"%s\"" % (idx, connections[idx]['name']), c)
|
|
expected_config = kwargs.get("initscripts_dict_expected", None)
|
|
if expected_config is not None:
|
|
self.assertEqual(expected_config[idx], config)
|
|
expected_warnings = kwargs.get("initscripts_expected_warnings", [])
|
|
self.assertEqual(expected_warnings, warnings)
|
|
|
|
def do_connections_validate(
|
|
self, expected_connections, input_connections, **kwargs
|
|
):
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
self.assertEqual(expected_connections, connections)
|
|
self.do_connections_validate_nm(input_connections, **kwargs)
|
|
self.do_connections_validate_ifcfg(input_connections, **kwargs)
|
|
|
|
def test_validate_str(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorStr("state")
|
|
self.assertEqual("a", v.validate("a"))
|
|
self.assertValidationError(v, 1)
|
|
self.assertValidationError(v, None)
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorStr("state", required=True)
|
|
self.assertValidationError(v, None)
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorStr(
|
|
"test_max_length", max_length=13
|
|
)
|
|
self.assertEqual("less_than_13", v.validate("less_than_13"))
|
|
self.assertValidationError(v, "longer_than_13")
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorStr(
|
|
"test_min_length", min_length=13
|
|
)
|
|
self.assertEqual("longer_than_13", v.validate("longer_than_13"))
|
|
self.assertValidationError(v, "less_than_13")
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorStr(
|
|
"test_min_max_length", min_length=10, max_length=15
|
|
)
|
|
self.assertEqual("13_characters", v.validate("13_characters"))
|
|
self.assertValidationError(v, "too_short")
|
|
self.assertValidationError(v, "string_is_too_long")
|
|
|
|
self.assertRaises(
|
|
ValueError,
|
|
network_lsr.argument_validator.ArgValidatorStr,
|
|
"non_int",
|
|
min_length="string",
|
|
)
|
|
self.assertRaises(
|
|
ValueError,
|
|
network_lsr.argument_validator.ArgValidatorStr,
|
|
"non_int",
|
|
max_length="string",
|
|
)
|
|
self.assertRaises(
|
|
ValueError,
|
|
network_lsr.argument_validator.ArgValidatorStr,
|
|
"negative_int",
|
|
min_length=-5,
|
|
)
|
|
self.assertRaises(
|
|
ValueError,
|
|
network_lsr.argument_validator.ArgValidatorStr,
|
|
"negative_int",
|
|
max_length=-5,
|
|
)
|
|
|
|
def test_validate_int(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorNum(
|
|
"state", default_value=None, numeric_type=float
|
|
)
|
|
self.assertEqual(1, v.validate(1))
|
|
self.assertEqual(1.5, v.validate(1.5))
|
|
self.assertEqual(1.5, v.validate("1.5"))
|
|
self.assertValidationError(v, None)
|
|
self.assertValidationError(v, "1a")
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorNum("state", default_value=None)
|
|
self.assertEqual(1, v.validate(1))
|
|
self.assertEqual(1, v.validate(1.0))
|
|
self.assertEqual(1, v.validate("1"))
|
|
self.assertValidationError(v, None)
|
|
self.assertValidationError(v, None)
|
|
self.assertValidationError(v, 1.5)
|
|
self.assertValidationError(v, "1.5")
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorNum("state", required=True)
|
|
self.assertValidationError(v, None)
|
|
self.assertValidationError(v, False)
|
|
self.assertValidationError(v, True)
|
|
|
|
def test_validate_range(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorRange(
|
|
"range", val_min=0, val_max=65534
|
|
)
|
|
self.assertEqual((1, 1), v.validate(1))
|
|
self.assertEqual((10, 1000), v.validate("10-1000"))
|
|
self.assertEqual((256, 256), v.validate("256"))
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the range value True is invalid",
|
|
v.validate,
|
|
True,
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the range value 2.5 is invalid",
|
|
v.validate,
|
|
2.5,
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the range start cannot be greater than range end",
|
|
v.validate,
|
|
"2000-1000",
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"upper range value is 65535 but cannot be greater than 65534",
|
|
v.validate,
|
|
"1-65535",
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"lower range value is -1 but cannot be less than 0",
|
|
v.validate,
|
|
-1,
|
|
)
|
|
|
|
def test_validate_bool(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorBool("state")
|
|
self.assertEqual(True, v.validate("yes"))
|
|
self.assertEqual(True, v.validate("yeS"))
|
|
self.assertEqual(True, v.validate("Y"))
|
|
self.assertEqual(True, v.validate(True))
|
|
self.assertEqual(True, v.validate("True"))
|
|
self.assertEqual(True, v.validate("1"))
|
|
self.assertEqual(True, v.validate(1))
|
|
|
|
self.assertEqual(False, v.validate("no"))
|
|
self.assertEqual(False, v.validate("nO"))
|
|
self.assertEqual(False, v.validate("N"))
|
|
self.assertEqual(False, v.validate(False))
|
|
self.assertEqual(False, v.validate("False"))
|
|
self.assertEqual(False, v.validate("0"))
|
|
self.assertEqual(False, v.validate(0))
|
|
|
|
self.assertValidationError(v, 2)
|
|
self.assertValidationError(v, -1)
|
|
self.assertValidationError(v, "Ye")
|
|
self.assertValidationError(v, "")
|
|
self.assertValidationError(v, None)
|
|
v = network_lsr.argument_validator.ArgValidatorBool("state", required=True)
|
|
self.assertValidationError(v, None)
|
|
|
|
def test_validate_dict(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorDict(
|
|
"dict",
|
|
nested=[
|
|
network_lsr.argument_validator.ArgValidatorNum("i", required=True),
|
|
network_lsr.argument_validator.ArgValidatorStr(
|
|
"s", required=False, default_value="s_default"
|
|
),
|
|
network_lsr.argument_validator.ArgValidatorStr(
|
|
"l",
|
|
required=False,
|
|
default_value=network_lsr.argument_validator.ArgValidator.MISSING,
|
|
),
|
|
],
|
|
)
|
|
|
|
self.assertEqual({"i": 5, "s": "s_default"}, v.validate({"i": "5"}))
|
|
self.assertEqual(
|
|
{"i": 5, "s": "s_default", "l": "6"}, v.validate({"i": "5", "l": "6"})
|
|
)
|
|
self.assertValidationError(v, {"k": 1})
|
|
self.assertEqual(v.validate(None), {})
|
|
|
|
def test_validate_list(self):
|
|
|
|
v = network_lsr.argument_validator.ArgValidatorList(
|
|
"list", nested=network_lsr.argument_validator.ArgValidatorNum("i")
|
|
)
|
|
self.assertEqual([1, 5], v.validate(["1", 5]))
|
|
self.assertValidationError(v, [1, "s"])
|
|
self.assertEqual(v.validate(None), [])
|
|
|
|
def test_validate_allow_empty_string_in_list(self):
|
|
"""
|
|
Test that when ArgValidatorStr.allow_empty is True, empty string is allowed in
|
|
in ArgValidatorList
|
|
"""
|
|
v = network_lsr.argument_validator.ArgValidatorList(
|
|
"list",
|
|
nested=network_lsr.argument_validator.ArgValidatorStr(
|
|
"list[?]", allow_empty=True
|
|
),
|
|
)
|
|
self.assertEqual(v.validate(["pci-0001:00:00.0", ""]), ["pci-0001:00:00.0", ""])
|
|
|
|
def test_validate_disallow_none_in_list(self):
|
|
"""
|
|
Test that None is not allowed in ArgValidatorList
|
|
"""
|
|
v = network_lsr.argument_validator.ArgValidatorList(
|
|
"list",
|
|
nested=network_lsr.argument_validator.ArgValidatorStr(
|
|
"list[?]", allow_empty=True
|
|
),
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"must be a string but is 'None'",
|
|
v.validate,
|
|
["pci-0001:00:00.0", None],
|
|
)
|
|
|
|
def test_validate_list_remove_none_or_empty(self):
|
|
"""
|
|
Test that when ArgValidatorStr.remove_none_or_empty is True, None or empty
|
|
string will be removed from ArgValidatorList
|
|
"""
|
|
v = network_lsr.argument_validator.ArgValidatorList(
|
|
"list",
|
|
nested=network_lsr.argument_validator.ArgValidatorStr(
|
|
"list[?]", allow_empty=True
|
|
),
|
|
remove_none_or_empty=True,
|
|
)
|
|
self.assertEqual(v.validate(["pci-0001:00:00.0", ""]), ["pci-0001:00:00.0"])
|
|
self.assertEqual(v.validate(["pci-0001:00:00.0", None]), ["pci-0001:00:00.0"])
|
|
|
|
def test_empty(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate([], [])
|
|
|
|
def test_ethernet_two_defaults(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"ignore_errors": None,
|
|
"interface_name": "5",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": None,
|
|
"type": "ethernet",
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present"],
|
|
"ignore_errors": None,
|
|
"name": "5",
|
|
"persistent_state": "present",
|
|
"state": None,
|
|
},
|
|
],
|
|
[{"name": "5", "type": "ethernet"}, {"name": "5"}],
|
|
)
|
|
|
|
def test_up_ethernet(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "5",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[{"name": "5", "state": "up", "type": "ethernet"}],
|
|
)
|
|
|
|
def test_up_ethernet_no_autoconnect(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": False,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "5",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[{"name": "5", "state": "up", "type": "ethernet", "autoconnect": "no"}],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "no",
|
|
"TYPE": "Ethernet",
|
|
"DEVICE": "5",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_invalid_autoconnect(self):
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid([{"name": "a", "autoconnect": True}])
|
|
|
|
def test_absent(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["absent"],
|
|
"ignore_errors": None,
|
|
"name": "5",
|
|
"persistent_state": "absent",
|
|
"state": None,
|
|
}
|
|
],
|
|
[{"name": "5", "persistent_state": "absent"}],
|
|
)
|
|
|
|
def test_up_ethernet_mac_mtu_static_ip(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": None,
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.174.5",
|
|
}
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": 1450,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"autoconnect": "yes",
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"mtu": 1450,
|
|
"ip": {"address": "192.168.174.5/24"},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_up_single_v4_dns(self):
|
|
self.maxDiff = None
|
|
# set single IPv4 DNS server
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod1",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [{"address": "192.168.174.1", "family": socket.AF_INET}],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.174.5",
|
|
}
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"autoconnect": "yes",
|
|
"ip": {"address": "192.168.174.5/24", "dns": "192.168.174.1"},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_ipv6_static(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod1",
|
|
"match": {},
|
|
"ip": {
|
|
"gateway6": "2001:db8::1",
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": False,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": False,
|
|
"address": [
|
|
{
|
|
"address": "2001:db8::2",
|
|
"family": socket.AF_INET6,
|
|
"prefix": 32,
|
|
},
|
|
{
|
|
"address": "2001:db8::3",
|
|
"family": socket.AF_INET6,
|
|
"prefix": 32,
|
|
},
|
|
{
|
|
"address": "2001:db8::4",
|
|
"family": socket.AF_INET6,
|
|
"prefix": 32,
|
|
},
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": "no",
|
|
"auto6": "no",
|
|
"address": [
|
|
"2001:db8::2/32",
|
|
"2001:db8::3/32",
|
|
"2001:db8::4/32",
|
|
],
|
|
"gateway6": "2001:db8::1",
|
|
},
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "none",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "no",
|
|
"IPV6ADDR": "2001:db8::2/32",
|
|
"IPV6ADDR_SECONDARIES": "2001:db8::3/32 2001:db8::4/32",
|
|
"IPV6_DEFAULTGW": "2001:db8::1",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "Ethernet",
|
|
"DEVICE": "prod1",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_routes(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": None,
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.176.5",
|
|
},
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.177.5",
|
|
},
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"routing_rule": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"dns": [],
|
|
},
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": 1450,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod.100",
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": False,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.174.5",
|
|
},
|
|
{
|
|
"prefix": 65,
|
|
"family": socket.AF_INET6,
|
|
"address": "a:b:c::6",
|
|
},
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.5.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
}
|
|
],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod.100",
|
|
"parent": "prod1",
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "vlan",
|
|
"vlan": {"id": 100},
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"autoconnect": "yes",
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"mtu": 1450,
|
|
"ip": {"address": "192.168.176.5/24 192.168.177.5/24"},
|
|
},
|
|
{
|
|
"name": "prod.100",
|
|
"state": "up",
|
|
"type": "vlan",
|
|
"parent": "prod1",
|
|
"vlan": {"id": "100"},
|
|
"ip": {
|
|
"address": [
|
|
"192.168.174.5/24",
|
|
{"address": "a:b:c::6", "prefix": 65},
|
|
],
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [{"network": "192.168.5.0"}],
|
|
},
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_auto_gateway_true(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod1",
|
|
"ip": {
|
|
"dhcp4": True,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": True,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {"auto_gateway": True},
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"DEFROUTE": "yes",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"DEVICE": "prod1",
|
|
"TYPE": "Ethernet",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_auto_gateway_false(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod1",
|
|
"ip": {
|
|
"dhcp4": True,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": False,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {"auto_gateway": False},
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"DEFROUTE": "no",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"DEVICE": "prod1",
|
|
"TYPE": "Ethernet",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_auto_gateway_no_gateway(self):
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": "no",
|
|
"auto6": "no",
|
|
"auto_gateway": "true",
|
|
"address": "192.168.176.5/24",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_vlan(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": None,
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": True,
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.176.5",
|
|
},
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.177.5",
|
|
},
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"routing_rule": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
},
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": 1450,
|
|
"name": "prod1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "prod.100",
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"auto6": False,
|
|
"dns": [],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.174.5",
|
|
},
|
|
{
|
|
"prefix": 65,
|
|
"family": socket.AF_INET6,
|
|
"address": "a:b:c::6",
|
|
},
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.5.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
}
|
|
],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod.100",
|
|
"parent": "prod1",
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "vlan",
|
|
"vlan": {"id": 101},
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"name": "prod1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"autoconnect": "yes",
|
|
"mac": "52:54:00:44:9f:ba",
|
|
"mtu": 1450,
|
|
"ip": {"address": "192.168.176.5/24 192.168.177.5/24"},
|
|
},
|
|
{
|
|
"name": "prod.100",
|
|
"state": "up",
|
|
"type": "vlan",
|
|
"parent": "prod1",
|
|
"vlan_id": 101,
|
|
"ip": {
|
|
"address": [
|
|
"192.168.174.5/24",
|
|
{"address": "a:b:c::6", "prefix": 65},
|
|
],
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [{"network": "192.168.5.0"}],
|
|
},
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_macvlan(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "eth0",
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": False,
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.122.3",
|
|
}
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"routing_rule": [],
|
|
"dns_options": [],
|
|
"ipv6_disabled": False,
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"dns": [],
|
|
},
|
|
"mac": "33:24:10:24:2f:b9",
|
|
"cloned_mac": "default",
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": 1450,
|
|
"name": "eth0-parent",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "veth0",
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"ipv6_disabled": False,
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": False,
|
|
"dns": [],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.244.1",
|
|
}
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.244.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
}
|
|
],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"macvlan": {"mode": "bridge", "promiscuous": True, "tap": False},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "veth0.0",
|
|
"parent": "eth0-parent",
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "macvlan",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "veth1",
|
|
"match": {},
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"auto6": False,
|
|
"dns": [],
|
|
"address": [
|
|
{
|
|
"prefix": 24,
|
|
"family": socket.AF_INET,
|
|
"address": "192.168.245.7",
|
|
}
|
|
],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.245.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
}
|
|
],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"macvlan": {"mode": "passthru", "promiscuous": False, "tap": True},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "veth0.1",
|
|
"parent": "eth0-parent",
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "macvlan",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"name": "eth0-parent",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"autoconnect": "yes",
|
|
"interface_name": "eth0",
|
|
"mac": "33:24:10:24:2f:b9",
|
|
"mtu": 1450,
|
|
"ip": {"address": "192.168.122.3/24", "auto6": False},
|
|
},
|
|
{
|
|
"name": "veth0.0",
|
|
"state": "up",
|
|
"type": "macvlan",
|
|
"parent": "eth0-parent",
|
|
"interface_name": "veth0",
|
|
"macvlan": {"mode": "bridge", "promiscuous": True, "tap": False},
|
|
"ip": {
|
|
"address": "192.168.244.1/24",
|
|
"auto6": False,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [{"network": "192.168.244.0"}],
|
|
},
|
|
},
|
|
{
|
|
"name": "veth0.1",
|
|
"state": "up",
|
|
"type": "macvlan",
|
|
"parent": "eth0-parent",
|
|
"interface_name": "veth1",
|
|
"macvlan": {"mode": "passthru", "promiscuous": False, "tap": True},
|
|
"ip": {
|
|
"address": "192.168.245.7/24",
|
|
"auto6": False,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [{"network": "192.168.245.0"}],
|
|
},
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_bridge_no_dhcp4_auto6(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "bridge2",
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": False,
|
|
"dhcp4": False,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod2",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "bridge",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "eth1",
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": "prod2",
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "prod2-port1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": "bridge",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"name": "prod2",
|
|
"state": "up",
|
|
"type": "bridge",
|
|
"interface_name": "bridge2",
|
|
"ip": {"dhcp4": False, "auto6": False},
|
|
},
|
|
{
|
|
"name": "prod2-port1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"interface_name": "eth1",
|
|
"controller": "prod2",
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_bond(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"bond": {
|
|
"mode": "balance-rr",
|
|
"ad_actor_sys_prio": None,
|
|
"ad_actor_system": None,
|
|
"ad_select": None,
|
|
"ad_user_port_key": None,
|
|
"all_ports_active": None,
|
|
"arp_all_targets": None,
|
|
"arp_interval": None,
|
|
"arp_ip_target": None,
|
|
"arp_validate": None,
|
|
"downdelay": None,
|
|
"fail_over_mac": None,
|
|
"lacp_rate": None,
|
|
"lp_interval": None,
|
|
"miimon": None,
|
|
"min_links": None,
|
|
"num_grat_arp": None,
|
|
"packets_per_port": None,
|
|
"peer_notif_delay": None,
|
|
"primary": None,
|
|
"primary_reselect": None,
|
|
"resend_igmp": None,
|
|
"tlb_dynamic_lb": None,
|
|
"updelay": None,
|
|
"use_carrier": None,
|
|
"xmit_hash_policy": None,
|
|
},
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "bond1",
|
|
"ip": {
|
|
"dhcp4": True,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "bond1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "bond",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[{"name": "bond1", "state": "up", "type": "bond"}],
|
|
)
|
|
|
|
def test_bond_active_backup(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"bond": {
|
|
"mode": "active-backup",
|
|
"ad_actor_sys_prio": None,
|
|
"ad_actor_system": None,
|
|
"ad_select": None,
|
|
"ad_user_port_key": None,
|
|
"all_ports_active": None,
|
|
"arp_all_targets": None,
|
|
"arp_interval": None,
|
|
"arp_ip_target": None,
|
|
"arp_validate": None,
|
|
"downdelay": None,
|
|
"fail_over_mac": None,
|
|
"lacp_rate": None,
|
|
"lp_interval": None,
|
|
"miimon": None,
|
|
"min_links": None,
|
|
"num_grat_arp": None,
|
|
"packets_per_port": None,
|
|
"peer_notif_delay": None,
|
|
"primary": None,
|
|
"primary_reselect": None,
|
|
"resend_igmp": None,
|
|
"tlb_dynamic_lb": None,
|
|
"updelay": None,
|
|
"use_carrier": None,
|
|
"xmit_hash_policy": None,
|
|
},
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "bond1",
|
|
"ip": {
|
|
"dhcp4": True,
|
|
"route_metric6": None,
|
|
"route_metric4": None,
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"dhcp4_send_hostname": None,
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dns": [],
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "bond1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "bond",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "bond1",
|
|
"state": "up",
|
|
"type": "bond",
|
|
"bond": {"mode": "active-backup"},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_invalid_values(self):
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid([{}])
|
|
self.do_connections_check_invalid([{"name": "b", "xxx": 5}])
|
|
|
|
def test_ethernet_mac_address(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"ignore_errors": None,
|
|
"interface_name": None,
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"routing_rule": [],
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
},
|
|
"mac": "aa:bb:cc:dd:ee:ff",
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": None,
|
|
"type": "ethernet",
|
|
"zone": None,
|
|
}
|
|
],
|
|
[{"name": "5", "type": "ethernet", "mac": "AA:bb:cC:DD:ee:FF"}],
|
|
)
|
|
|
|
def test_ethernet_speed_settings(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": {"autoneg": False, "duplex": "half", "speed": 400},
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "5",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "5",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "5",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {},
|
|
"ethernet": {"duplex": "half", "speed": 400},
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"ETHTOOL_OPTS": "autoneg off speed 400 duplex half",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "Ethernet",
|
|
"DEVICE": "5",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_bridge2(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "6643-controller",
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "6643-controller",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "bridge",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "6643",
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dhcp4": True,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": "6643-controller",
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "6643",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": "bridge",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{"name": "6643-controller", "state": "up", "type": "bridge"},
|
|
{
|
|
"name": "6643",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"controller": "6643-controller",
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_infiniband(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"infiniband": {"p_key": None, "transport_mode": "datagram"},
|
|
"interface_name": None,
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "infiniband.1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "infiniband.1",
|
|
"interface_name": "",
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"CONNECTED_MODE": "no",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "InfiniBand",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_infiniband2(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"infiniband": {"p_key": 5, "transport_mode": "datagram"},
|
|
"interface_name": None,
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "infiniband.2",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "infiniband.2",
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
"mac": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"infiniband_p_key": 5,
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"CONNECTED_MODE": "no",
|
|
"HWADDR": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"PKEY": "yes",
|
|
"PKEY_ID": "5",
|
|
"TYPE": "InfiniBand",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_infiniband3(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"ignore_errors": None,
|
|
"infiniband": {"p_key": None, "transport_mode": "datagram"},
|
|
"interface_name": "ib0",
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "infiniband.3",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": None,
|
|
"type": "infiniband",
|
|
"zone": None,
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"infiniband": {"p_key": 10, "transport_mode": "datagram"},
|
|
"interface_name": None,
|
|
"ip": {
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"dhcp4_send_hostname": None,
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"gateway4": None,
|
|
"gateway6": None,
|
|
"wait_ip": "any",
|
|
"ipv6_disabled": False,
|
|
"route": [],
|
|
"route_append_only": False,
|
|
"route_metric4": None,
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"rule_append_only": False,
|
|
},
|
|
"mac": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "infiniband.3-10",
|
|
"parent": "infiniband.3",
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
"wait": None,
|
|
"zone": None,
|
|
},
|
|
],
|
|
[
|
|
{
|
|
"name": "infiniband.3",
|
|
"interface_name": "ib0",
|
|
"type": "infiniband",
|
|
},
|
|
{
|
|
"name": "infiniband.3-10",
|
|
"state": "up",
|
|
"type": "infiniband",
|
|
"parent": "infiniband.3",
|
|
"mac": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"infiniband_p_key": 10,
|
|
},
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"CONNECTED_MODE": "no",
|
|
"DEVICE": "ib0",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "InfiniBand",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
},
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"CONNECTED_MODE": "no",
|
|
"HWADDR": "11:22:33:44:55:66:77:88:99:00:"
|
|
"11:22:33:44:55:66:77:88:99:00",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"PHYSDEV": "ib0",
|
|
"PKEY": "yes",
|
|
"PKEY_ID": "10",
|
|
"TYPE": "InfiniBand",
|
|
},
|
|
"keys": None,
|
|
"route": None,
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
},
|
|
],
|
|
)
|
|
|
|
def test_route_metric_prefix(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "555",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.45.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": 545,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.46.0",
|
|
"prefix": 30,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
],
|
|
"routing_rule": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": ["aa", "bb"],
|
|
"route_metric6": None,
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "555",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "555",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dns_search": ["aa", "bb"],
|
|
"route": [
|
|
{"network": "192.168.45.0", "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
],
|
|
},
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"DOMAIN": "aa bb",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "Ethernet",
|
|
"DEVICE": "555",
|
|
},
|
|
"keys": None,
|
|
"route": "192.168.45.0/24 dev 555 metric 545\n192.168.46.0/30 dev 555\n",
|
|
"route6": None,
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_route_v6(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "e556",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": True,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.45.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": 545,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.46.0",
|
|
"prefix": 30,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
{
|
|
"family": socket.AF_INET6,
|
|
"network": "a:b:c:d::",
|
|
"prefix": 64,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
],
|
|
"routing_rule": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": ["aa", "bb"],
|
|
"route_metric6": None,
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "e556",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": "external",
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "e556",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"zone": "external",
|
|
"ip": {
|
|
"dns_search": ["aa", "bb"],
|
|
"route_append_only": True,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{"network": "192.168.45.0", "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "a:b:c:d::"},
|
|
],
|
|
},
|
|
}
|
|
],
|
|
nm_route_list_current=[
|
|
[
|
|
{"network": "192.168.40.0", "prefix": 24, "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "a:b:c:f::"},
|
|
]
|
|
],
|
|
nm_route_list_expected=[
|
|
[
|
|
{"network": "192.168.40.0", "prefix": 24, "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "192.168.45.0", "prefix": 24, "metric": 545},
|
|
{"network": "a:b:c:f::"},
|
|
{"network": "a:b:c:d::"},
|
|
]
|
|
],
|
|
initscripts_content_current=[
|
|
{
|
|
"ifcfg": "",
|
|
"keys": None,
|
|
"route": "192.168.40.0/24 dev e556 metric 545\n192.168.46.0/30",
|
|
"route6": "a:b:c:f::/64",
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"DOMAIN": "aa bb",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "Ethernet",
|
|
"ZONE": "external",
|
|
"DEVICE": "e556",
|
|
},
|
|
"keys": None,
|
|
"route": "192.168.40.0/24 dev e556 metric 545\n"
|
|
"192.168.46.0/30\n"
|
|
"192.168.45.0/24 dev e556 metric 545\n"
|
|
"192.168.46.0/30 dev e556\n",
|
|
"route6": "a:b:c:f::/64\na:b:c:d::/64 dev e556\n",
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_route_without_interface_name(self):
|
|
route_device_warning = (
|
|
"The connection e556 does not specify an interface name. Therefore, the "
|
|
"route to {0} will be configured without the output device and the kernel "
|
|
"will choose it automatically which might result in an unwanted device "
|
|
"being used. To avoid this, specify `interface_name` in the connection "
|
|
"appropriately."
|
|
)
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": None,
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": True,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.45.0",
|
|
"prefix": 24,
|
|
"gateway": None,
|
|
"metric": 545,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
{
|
|
"family": socket.AF_INET,
|
|
"network": "192.168.46.0",
|
|
"prefix": 30,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
{
|
|
"family": socket.AF_INET6,
|
|
"network": "a:b:c:d::",
|
|
"prefix": 64,
|
|
"gateway": None,
|
|
"metric": -1,
|
|
"type": None,
|
|
"table": None,
|
|
"src": None,
|
|
},
|
|
],
|
|
"routing_rule": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": ["aa", "bb"],
|
|
"route_metric6": None,
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": "12:23:34:45:56:60",
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "e556",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": "external",
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "e556",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"zone": "external",
|
|
"mac": "12:23:34:45:56:60",
|
|
"ip": {
|
|
"dns_search": ["aa", "bb"],
|
|
"route_append_only": True,
|
|
"rule_append_only": False,
|
|
"route": [
|
|
{"network": "192.168.45.0", "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "a:b:c:d::"},
|
|
],
|
|
},
|
|
}
|
|
],
|
|
nm_route_list_current=[
|
|
[
|
|
{"network": "192.168.40.0", "prefix": 24, "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "a:b:c:f::"},
|
|
]
|
|
],
|
|
nm_route_list_expected=[
|
|
[
|
|
{"network": "192.168.40.0", "prefix": 24, "metric": 545},
|
|
{"network": "192.168.46.0", "prefix": 30},
|
|
{"network": "192.168.45.0", "prefix": 24, "metric": 545},
|
|
{"network": "a:b:c:f::"},
|
|
{"network": "a:b:c:d::"},
|
|
]
|
|
],
|
|
initscripts_content_current=[
|
|
{
|
|
"ifcfg": "",
|
|
"keys": None,
|
|
"route": "192.168.40.0/24 metric 545\n192.168.46.0/30",
|
|
"route6": "a:b:c:f::/64",
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
initscripts_dict_expected=[
|
|
{
|
|
"ifcfg": {
|
|
"BOOTPROTO": "dhcp",
|
|
"DOMAIN": "aa bb",
|
|
"HWADDR": "12:23:34:45:56:60",
|
|
"IPV6INIT": "yes",
|
|
"IPV6_AUTOCONF": "yes",
|
|
"NM_CONTROLLED": "no",
|
|
"ONBOOT": "yes",
|
|
"TYPE": "Ethernet",
|
|
"ZONE": "external",
|
|
},
|
|
"keys": None,
|
|
"route": "192.168.40.0/24 metric 545\n"
|
|
"192.168.46.0/30\n"
|
|
"192.168.45.0/24 metric 545\n",
|
|
"route6": "a:b:c:f::/64\na:b:c:d::/64\n",
|
|
"rule": None,
|
|
"rule6": None,
|
|
}
|
|
],
|
|
initscripts_expected_warnings=[
|
|
route_device_warning.format("192.168.45.0/24"),
|
|
route_device_warning.format("192.168.46.0/30"),
|
|
route_device_warning.format("a:b:c:d::/64"),
|
|
],
|
|
)
|
|
|
|
def test_802_1x_1(self):
|
|
"""
|
|
Test private key with password
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "eth0",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": "p@55w0rD",
|
|
"private_key_password_flags": None,
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": "/etc/pki/tls/cacert.pem",
|
|
"ca_path": None,
|
|
"system_ca_certs": False,
|
|
"domain_suffix_match": None,
|
|
},
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "eth0",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": "p@55w0rD",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": "/etc/pki/tls/cacert.pem",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_802_1x_2(self):
|
|
"""
|
|
Test 802.1x profile with unencrypted private key,
|
|
domain suffix match, and system ca certs
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "eth0",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": None,
|
|
"private_key_password_flags": ["not-required"],
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": None,
|
|
"ca_path": None,
|
|
"system_ca_certs": True,
|
|
"domain_suffix_match": "example.com",
|
|
},
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "eth0",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"system_ca_certs": True,
|
|
"domain_suffix_match": "example.com",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_802_1x_3(self):
|
|
"""
|
|
Test 802.1x profile with unencrypted private key and ca_path
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethernet": ETHERNET_DEFAULTS,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "eth0",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": None,
|
|
"private_key_password_flags": ["not-required"],
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": None,
|
|
"ca_path": "/etc/pki/tls/my_ca_certs",
|
|
"system_ca_certs": False,
|
|
"domain_suffix_match": None,
|
|
},
|
|
"wireless": None,
|
|
"mtu": None,
|
|
"name": "eth0",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"ca_path": "/etc/pki/tls/my_ca_certs",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_wireless_psk(self):
|
|
"""
|
|
Test wireless connection with wpa-psk auth
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "wireless1",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": None,
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "p@55w0rD",
|
|
},
|
|
"mtu": None,
|
|
"name": "wireless1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "p@55w0rD",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_wireless_eap(self):
|
|
"""
|
|
Test wireless connection with wpa-eap
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present", "up"],
|
|
"autoconnect": True,
|
|
"autoconnect_retries": -1,
|
|
"check_iface_exists": True,
|
|
"ethtool": ETHTOOL_DEFAULTS,
|
|
"force_state_change": None,
|
|
"ignore_errors": None,
|
|
"interface_name": "wireless1",
|
|
"ip": {
|
|
"gateway6": None,
|
|
"gateway4": None,
|
|
"wait_ip": "any",
|
|
"route_metric4": None,
|
|
"auto6": True,
|
|
"ipv6_disabled": False,
|
|
"dhcp4": True,
|
|
"address": [],
|
|
"ipv4_ignore_auto_dns": None,
|
|
"ipv6_ignore_auto_dns": None,
|
|
"auto_gateway": None,
|
|
"route_append_only": False,
|
|
"rule_append_only": False,
|
|
"route": [],
|
|
"dns": [],
|
|
"dns_options": [],
|
|
"dns_priority": 0,
|
|
"dns_search": [],
|
|
"route_metric6": None,
|
|
"routing_rule": [],
|
|
"dhcp4_send_hostname": None,
|
|
},
|
|
"mac": None,
|
|
"cloned_mac": "default",
|
|
"match": {},
|
|
"controller": None,
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": "p@55w0rD",
|
|
"private_key_password_flags": None,
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": "/etc/pki/tls/cacert.pem",
|
|
"ca_path": None,
|
|
"system_ca_certs": False,
|
|
"domain_suffix_match": None,
|
|
},
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"password": None,
|
|
"key_mgmt": "wpa-eap",
|
|
},
|
|
"mtu": None,
|
|
"name": "wireless1",
|
|
"parent": None,
|
|
"persistent_state": "present",
|
|
"port_type": None,
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wait": None,
|
|
"zone": None,
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-eap",
|
|
},
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"private_key_password": "p@55w0rD",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"ca_cert": "/etc/pki/tls/cacert.pem",
|
|
},
|
|
}
|
|
],
|
|
)
|
|
|
|
def test_invalid_cert_path(self):
|
|
"""
|
|
should fail if a relative path is used for 802.1x certs/keys
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "client.key",
|
|
"client_cert": "client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"system_ca_certs": True,
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_invalid_password_flag(self):
|
|
"""
|
|
should fail if an invalid private key password flag is set
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["bad-flag"],
|
|
"system_ca_certs": True,
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_802_1x_ca_path_and_system_ca_certs(self):
|
|
"""
|
|
should fail if ca_path and system_ca_certs are used together
|
|
"""
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"ca_path": "/etc/pki/my_ca_certs",
|
|
"system_ca_certs": True,
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_802_1x_initscripts(self):
|
|
"""
|
|
should fail to create ieee802_1x connection with initscripts
|
|
"""
|
|
input_connections = [
|
|
{
|
|
"name": "eth0",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"system_ca_certs": True,
|
|
},
|
|
}
|
|
]
|
|
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
|
|
self.assertRaises(
|
|
ValidationError,
|
|
ARGS_CONNECTIONS.validate_connection_one,
|
|
VALIDATE_ONE_MODE_INITSCRIPTS,
|
|
connections,
|
|
0,
|
|
)
|
|
|
|
def test_802_1x_unsupported_type(self):
|
|
"""
|
|
should fail if a non ethernet/wireless connection has 802.1x settings defined
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "bond0",
|
|
"state": "up",
|
|
"type": "bond",
|
|
"ieee802_1x": {
|
|
"identity": "myhost",
|
|
"eap": "tls",
|
|
"private_key": "/etc/pki/tls/client.key",
|
|
"client_cert": "/etc/pki/tls/client.pem",
|
|
"private_key_password_flags": ["not-required"],
|
|
"system_ca_certs": True,
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_initscripts(self):
|
|
"""
|
|
should fail to create wireless connection with initscripts
|
|
"""
|
|
input_connections = [
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "p@55w0rD",
|
|
},
|
|
}
|
|
]
|
|
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
|
|
self.assertRaises(
|
|
ValidationError,
|
|
ARGS_CONNECTIONS.validate_connection_one,
|
|
VALIDATE_ONE_MODE_INITSCRIPTS,
|
|
connections,
|
|
0,
|
|
)
|
|
|
|
def test_wireless_unsupported_type(self):
|
|
"""
|
|
should fail if a non wireless connection has wireless settings defined
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "wireless-bond",
|
|
"state": "up",
|
|
"type": "bond",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "p@55w0rD",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_ssid_too_long(self):
|
|
"""
|
|
should fail if ssid longer than 32 bytes
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network with ssid too long",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "p@55w0rD",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_no_password(self):
|
|
"""
|
|
should fail if wpa-psk is selected and no password provided
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_password_too_long(self):
|
|
"""
|
|
should fail if wpa-psk is selected and no password provided
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-psk",
|
|
"password": "This password is too long and should "
|
|
"not be able to validate properly",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_no_802_1x_for_wpa_eap(self):
|
|
"""
|
|
should fail if no 802.1x parameters are defined for a wireless
|
|
connection with key_mgmt=wpa-eap
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[
|
|
{
|
|
"name": "wireless1",
|
|
"state": "up",
|
|
"type": "wireless",
|
|
"wireless": {
|
|
"ssid": "test wireless network",
|
|
"key_mgmt": "wpa-eap",
|
|
},
|
|
}
|
|
]
|
|
)
|
|
|
|
def test_wireless_no_options_defined(self):
|
|
"""
|
|
should fail if a connection of type='wireless' does not
|
|
have any 'wireless' settings defined
|
|
"""
|
|
self.do_connections_check_invalid(
|
|
[{"name": "wireless1", "state": "up", "type": "wireless"}]
|
|
)
|
|
|
|
def test_invalid_mac(self):
|
|
self.maxDiff = None
|
|
self.do_connections_check_invalid(
|
|
[{"name": "b", "type": "ethernet", "mac": "aa:b"}]
|
|
)
|
|
|
|
def test_interface_name_ethernet_default(self):
|
|
"""Use the profile name as interface_name for ethernet profiles"""
|
|
cons_without_interface_name = [{"name": "eth0", "type": "ethernet"}]
|
|
connections = ARGS_CONNECTIONS.validate(cons_without_interface_name)
|
|
self.assertTrue(connections[0]["interface_name"] == "eth0")
|
|
|
|
def test_interface_name_ethernet_mac(self):
|
|
"""Do not set interface_name when mac is specified"""
|
|
cons_without_interface_name = [
|
|
{"name": "eth0", "type": "ethernet", "mac": "3b:0b:88:16:6d:1a"}
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(cons_without_interface_name)
|
|
self.assertTrue(connections[0]["interface_name"] is None)
|
|
|
|
def test_interface_name_ethernet_empty(self):
|
|
"""Allow not to restrict the profile to an interface"""
|
|
network_connections = [
|
|
{"name": "internal_network", "type": "ethernet", "interface_name": ""}
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(network_connections)
|
|
|
|
self.assertTrue(connections[0]["interface_name"] is None)
|
|
|
|
def test_interface_name_ethernet_None(self):
|
|
"""Check that interface_name cannot be None"""
|
|
network_connections = [
|
|
{"name": "internal_network", "type": "ethernet", "interface_name": None}
|
|
]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_interface_name_ethernet_explicit(self):
|
|
"""Use the explicitly provided interface name"""
|
|
network_connections = [
|
|
{"name": "internal", "type": "ethernet", "interface_name": "eth0"}
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(network_connections)
|
|
self.assertEqual(connections[0]["interface_name"], "eth0")
|
|
|
|
def test_interface_name_ethernet_invalid_profile(self):
|
|
"""Require explicit interface_name when the profile name is not a
|
|
valid interface_name"""
|
|
network_connections = [{"name": "internal:main", "type": "ethernet"}]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
network_connections = [
|
|
{"name": "internal:main", "type": "ethernet", "interface_name": "eth0"}
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(network_connections)
|
|
self.assertTrue(connections[0]["interface_name"] == "eth0")
|
|
|
|
def test_interface_name_ethernet_invalid_interface_name(self):
|
|
network_connections = [
|
|
{"name": "internal", "type": "ethernet", "interface_name": "invalid:name"}
|
|
]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_interface_name_bond_empty_interface_name(self):
|
|
network_connections = [
|
|
{"name": "internal", "type": "bond", "interface_name": "invalid:name"}
|
|
]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_interface_name_bond_profile_as_interface_name(self):
|
|
network_connections = [{"name": "internal", "type": "bond"}]
|
|
connections = ARGS_CONNECTIONS.validate(network_connections)
|
|
self.assertEqual(connections[0]["interface_name"], "internal")
|
|
|
|
def check_connection(self, connection, expected):
|
|
reduced_connection = {}
|
|
for setting in expected:
|
|
reduced_connection[setting] = connection[setting]
|
|
self.assertEqual(reduced_connection, expected)
|
|
|
|
def check_partial_connection_zero(self, network_config, expected):
|
|
connections = ARGS_CONNECTIONS.validate([network_config])
|
|
self.check_connection(connections[0], expected)
|
|
|
|
def check_one_connection_with_defaults(
|
|
self, network_config, expected_changed_settings
|
|
):
|
|
self.maxDiff = None
|
|
expected = self.default_connection_settings
|
|
expected.update(expected_changed_settings)
|
|
|
|
self.do_connections_validate([expected], [network_config])
|
|
|
|
def test_default_states(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0"},
|
|
{"actions": ["present"], "persistent_state": "present", "state": None},
|
|
)
|
|
|
|
def test_invalid_persistent_state_up(self):
|
|
network_connections = [{"name": "internal", "persistent_state": "up"}]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_invalid_persistent_state_down(self):
|
|
network_connections = [{"name": "internal", "persistent_state": "down"}]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_invalid_state_test(self):
|
|
network_connections = [{"name": "internal", "state": "test"}]
|
|
self.assertRaises(
|
|
ValidationError, ARGS_CONNECTIONS.validate, network_connections
|
|
)
|
|
|
|
def test_default_states_type(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "type": "ethernet"},
|
|
{"actions": ["present"], "persistent_state": "present", "state": None},
|
|
)
|
|
|
|
def test_persistent_state_present(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "persistent_state": "present", "type": "ethernet"},
|
|
{"actions": ["present"], "persistent_state": "present", "state": None},
|
|
)
|
|
|
|
def test_state_present(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "state": "present", "type": "ethernet"},
|
|
{"actions": ["present"], "persistent_state": "present", "state": None},
|
|
)
|
|
|
|
def test_state_absent(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "state": "absent"},
|
|
{"actions": ["absent"], "persistent_state": "absent", "state": None},
|
|
)
|
|
|
|
def test_persistent_state_absent(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "persistent_state": "absent"},
|
|
{"actions": ["absent"], "persistent_state": "absent", "state": None},
|
|
)
|
|
|
|
def test_state_present_up(self):
|
|
self.check_partial_connection_zero(
|
|
{
|
|
"name": "eth0",
|
|
"persistent_state": "present",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"persistent_state": "present",
|
|
"state": "up",
|
|
},
|
|
)
|
|
|
|
def test_state_present_down(self):
|
|
self.check_partial_connection_zero(
|
|
{
|
|
"name": "eth0",
|
|
"persistent_state": "present",
|
|
"state": "down",
|
|
"type": "ethernet",
|
|
},
|
|
{
|
|
"actions": ["present", "down"],
|
|
"persistent_state": "present",
|
|
"state": "down",
|
|
},
|
|
)
|
|
|
|
def test_state_absent_up_no_type(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "persistent_state": "absent", "state": "up"},
|
|
{"actions": ["absent", "up"], "persistent_state": "absent", "state": "up"},
|
|
)
|
|
|
|
def test_state_absent_up_type(self):
|
|
# if type is specified, present should happen, too
|
|
self.check_partial_connection_zero(
|
|
{
|
|
"name": "eth0",
|
|
"persistent_state": "absent",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
},
|
|
{
|
|
"actions": ["present", "absent", "up"],
|
|
"persistent_state": "absent",
|
|
"state": "up",
|
|
},
|
|
)
|
|
|
|
def test_state_absent_down(self):
|
|
# if type is specified, present should happen, too
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "persistent_state": "absent", "state": "down"},
|
|
{
|
|
"actions": ["absent", "down"],
|
|
"persistent_state": "absent",
|
|
"state": "down",
|
|
},
|
|
)
|
|
|
|
def test_state_up_no_type(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "state": "up"},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"persistent_state": "present",
|
|
"state": "up",
|
|
},
|
|
)
|
|
|
|
def test_state_up_type(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "state": "up", "type": "ethernet"},
|
|
{
|
|
"actions": ["present", "up"],
|
|
"persistent_state": "present",
|
|
"state": "up",
|
|
},
|
|
)
|
|
|
|
def test_state_down_no_type(self):
|
|
self.check_partial_connection_zero(
|
|
{"name": "eth0", "state": "down"},
|
|
{
|
|
"actions": ["present", "down"],
|
|
"persistent_state": "present",
|
|
"state": "down",
|
|
},
|
|
)
|
|
|
|
def test_full_state_present_no_type(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["present"],
|
|
"ignore_errors": None,
|
|
"name": "eth0",
|
|
"state": None,
|
|
"persistent_state": "present",
|
|
}
|
|
],
|
|
[{"name": "eth0", "persistent_state": "present"}],
|
|
)
|
|
|
|
def test_full_state_present_type_defaults(self):
|
|
self.check_one_connection_with_defaults(
|
|
{"name": "eth0", "type": "ethernet", "persistent_state": "present"},
|
|
{
|
|
"actions": ["present"],
|
|
"interface_name": "eth0",
|
|
"name": "eth0",
|
|
"persistent_state": "present",
|
|
"state": None,
|
|
"type": "ethernet",
|
|
},
|
|
)
|
|
|
|
def test_full_state_absent_no_type(self):
|
|
self.maxDiff = None
|
|
self.do_connections_validate(
|
|
[
|
|
{
|
|
"actions": ["absent"],
|
|
"ignore_errors": None,
|
|
"name": "eth0",
|
|
"state": None,
|
|
"persistent_state": "absent",
|
|
}
|
|
],
|
|
[{"name": "eth0", "persistent_state": "absent"}],
|
|
)
|
|
|
|
def test_full_state_absent_defaults(self):
|
|
self.maxDiff = None
|
|
self.check_one_connection_with_defaults(
|
|
{"name": "eth0", "persistent_state": "absent", "type": "ethernet"},
|
|
{
|
|
"actions": ["absent"],
|
|
"ignore_errors": None,
|
|
"name": "eth0",
|
|
"state": None,
|
|
"persistent_state": "absent",
|
|
"type": "ethernet",
|
|
"interface_name": "eth0",
|
|
},
|
|
)
|
|
|
|
def _test_ethtool_changes(self, input_ethtool, expected_ethtool):
|
|
"""
|
|
When passing a dictionary 'input_features' with each feature and their
|
|
value to change, and a dictionary 'expected_features' with the expected
|
|
result in the configuration, the expected and resulting connection are
|
|
created and validated.
|
|
"""
|
|
expected_ethtool_full = copy.deepcopy(ETHTOOL_DEFAULTS)
|
|
for key in list(expected_ethtool_full):
|
|
if key in expected_ethtool:
|
|
expected_ethtool_full[key].update(expected_ethtool[key])
|
|
|
|
input_connection = {
|
|
"ethtool": input_ethtool,
|
|
"name": "5",
|
|
"persistent_state": "present",
|
|
"type": "ethernet",
|
|
}
|
|
|
|
expected_connection = {
|
|
"actions": ["present"],
|
|
"ethtool": expected_ethtool_full,
|
|
"interface_name": "5",
|
|
"persistent_state": "present",
|
|
"state": None,
|
|
"type": "ethernet",
|
|
}
|
|
self.check_one_connection_with_defaults(input_connection, expected_connection)
|
|
|
|
def test_set_ethtool_feature(self):
|
|
"""
|
|
When passing the name of an non-deprecated ethtool feature, their
|
|
current version is updated.
|
|
"""
|
|
input_ethtool = {"features": {"tx_tcp_segmentation": "yes"}}
|
|
expected_ethtool = {"features": {"tx_tcp_segmentation": True}}
|
|
self._test_ethtool_changes(input_ethtool, expected_ethtool)
|
|
|
|
def test_set_deprecated_ethtool_feature(self):
|
|
"""
|
|
When passing a deprecated name, their current version is updated.
|
|
"""
|
|
input_ethtool = {"features": {"esp-hw-offload": "yes"}}
|
|
expected_ethtool = {"features": {"esp_hw_offload": True}}
|
|
self._test_ethtool_changes(input_ethtool, expected_ethtool)
|
|
|
|
def test_invalid_ethtool_settings(self):
|
|
"""
|
|
When both the deprecated and current version of a feature are stated,
|
|
a Validation Error is raised.
|
|
"""
|
|
input_features = {"tx-tcp-segmentation": "yes", "tx_tcp_segmentation": "yes"}
|
|
features_validator = (
|
|
network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures()
|
|
)
|
|
self.assertValidationError(features_validator, input_features)
|
|
|
|
def test_deprecated_ethtool_names(self):
|
|
"""
|
|
Test that for each validator in
|
|
ArgValidator_DictEthtoolFeatures.nested there is another non-deprecated
|
|
validator that has the name from the deprecated_by attribute"
|
|
"""
|
|
validators = (
|
|
network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures().nested
|
|
)
|
|
for name, validator in validators.items():
|
|
if isinstance(
|
|
validator, network_lsr.argument_validator.ArgValidatorDeprecated
|
|
):
|
|
assert validator.deprecated_by in validators.keys()
|
|
|
|
def test_valid_persistent_state(self):
|
|
"""
|
|
Test that when persistent_state is present and state is set to present
|
|
or absent, a ValidationError raises.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_DictConnection()
|
|
input_connection = {
|
|
"name": "test",
|
|
"persistent_state": "present",
|
|
"state": "present",
|
|
"type": "ethernet",
|
|
}
|
|
self.assertValidationError(validator, input_connection)
|
|
input_connection.update({"state": "absent"})
|
|
self.assertValidationError(validator, input_connection)
|
|
|
|
def test_dns_options_argvalidator(self):
|
|
"""
|
|
Test that argvalidator for validating dns_options value is correctly defined.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_DictIP()
|
|
|
|
false_testcase_1 = {
|
|
"dns_options": ["attempts:01"],
|
|
}
|
|
false_testcase_2 = {
|
|
"dns_options": ["debug$"],
|
|
}
|
|
false_testcase_3 = {
|
|
"dns_options": ["edns00"],
|
|
}
|
|
false_testcase_4 = {
|
|
"dns_options": ["ndots:"],
|
|
}
|
|
false_testcase_5 = {
|
|
"dns_options": ["no-check-name"],
|
|
}
|
|
false_testcase_6 = {
|
|
"dns_options": ["no-rel0ad"],
|
|
}
|
|
false_testcase_7 = {
|
|
"dns_options": ["bugno-tld-query"],
|
|
}
|
|
false_testcase_8 = {
|
|
"dns_options": ["etator"],
|
|
}
|
|
false_testcase_9 = {
|
|
"dns_options": ["singlerequest"],
|
|
}
|
|
false_testcase_10 = {
|
|
"dns_options": ["single-request-reopen:2"],
|
|
}
|
|
false_testcase_11 = {
|
|
"dns_options": ["timeout"],
|
|
}
|
|
false_testcase_12 = {
|
|
"dns_options": ["*trust-ad*"],
|
|
}
|
|
false_testcase_13 = {
|
|
"dns_options": ["use1-vc2-use-vc"],
|
|
}
|
|
|
|
self.assertValidationError(validator, false_testcase_1)
|
|
self.assertValidationError(validator, false_testcase_2)
|
|
self.assertValidationError(validator, false_testcase_3)
|
|
self.assertValidationError(validator, false_testcase_4)
|
|
self.assertValidationError(validator, false_testcase_5)
|
|
self.assertValidationError(validator, false_testcase_6)
|
|
self.assertValidationError(validator, false_testcase_7)
|
|
self.assertValidationError(validator, false_testcase_8)
|
|
self.assertValidationError(validator, false_testcase_9)
|
|
self.assertValidationError(validator, false_testcase_10)
|
|
self.assertValidationError(validator, false_testcase_11)
|
|
self.assertValidationError(validator, false_testcase_12)
|
|
self.assertValidationError(validator, false_testcase_13)
|
|
|
|
true_testcase_1 = {
|
|
"dns_options": ["attempts:3"],
|
|
}
|
|
true_testcase_2 = {
|
|
"dns_options": ["debug"],
|
|
}
|
|
true_testcase_3 = {
|
|
"dns_options": ["ndots:3", "single-request-reopen"],
|
|
}
|
|
true_testcase_4 = {
|
|
"dns_options": ["ndots:2", "timeout:3"],
|
|
}
|
|
true_testcase_5 = {
|
|
"dns_options": ["no-check-names"],
|
|
}
|
|
true_testcase_6 = {
|
|
"dns_options": ["no-reload"],
|
|
}
|
|
true_testcase_7 = {
|
|
"dns_options": ["no-tld-query"],
|
|
}
|
|
true_testcase_8 = {
|
|
"dns_options": ["rotate"],
|
|
}
|
|
true_testcase_9 = {
|
|
"dns_options": ["single-request"],
|
|
}
|
|
true_testcase_10 = {
|
|
"dns_options": ["single-request-reopen"],
|
|
}
|
|
true_testcase_11 = {
|
|
"dns_options": ["trust-ad"],
|
|
}
|
|
true_testcase_12 = {
|
|
"dns_options": ["use-vc"],
|
|
}
|
|
true_testcase_13 = {
|
|
"dns_options": ["no-aaaa"],
|
|
}
|
|
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_1)["dns_options"], ["attempts:3"]
|
|
)
|
|
self.assertEqual(validator.validate(true_testcase_2)["dns_options"], ["debug"])
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_3)["dns_options"],
|
|
["ndots:3", "single-request-reopen"],
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_4)["dns_options"], ["ndots:2", "timeout:3"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_5)["dns_options"], ["no-check-names"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_6)["dns_options"], ["no-reload"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_7)["dns_options"], ["no-tld-query"]
|
|
)
|
|
self.assertEqual(validator.validate(true_testcase_8)["dns_options"], ["rotate"])
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_9)["dns_options"], ["single-request"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_10)["dns_options"],
|
|
["single-request-reopen"],
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_11)["dns_options"], ["trust-ad"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_12)["dns_options"], ["use-vc"]
|
|
)
|
|
self.assertEqual(
|
|
validator.validate(true_testcase_13)["dns_options"], ["no-aaaa"]
|
|
)
|
|
|
|
def test_ipv4_dns_without_ipv4_config(self):
|
|
"""
|
|
Test that configuring IPv4 DNS is not allowed when IPv4 is disabled.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
ipv4_dns_without_ipv4_config = [
|
|
{
|
|
"name": "test_ipv4_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"auto6": True,
|
|
"dhcp4": False,
|
|
"dns": ["198.51.100.5"],
|
|
},
|
|
}
|
|
]
|
|
self.assertRaises(
|
|
ValidationError,
|
|
validator.validate_connection_one,
|
|
"nm",
|
|
validator.validate(ipv4_dns_without_ipv4_config),
|
|
0,
|
|
)
|
|
|
|
def test_ipv6_dns_with_ipv6_disabled(self):
|
|
"""
|
|
Test that configuring IPv6 DNS is not allowed when IPv6 is disabled.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
ipv6_dns_with_ipv6_disabled = [
|
|
{
|
|
"name": "test_ipv6_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"dhcp4": True,
|
|
"dns": ["2001:db8::20"],
|
|
},
|
|
}
|
|
]
|
|
old_util_nm = Util.NM
|
|
Util.NM = MagicMock(spec=["SETTING_IP6_CONFIG_METHOD_DISABLED"])
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"IPv6 needs to be enabled to support IPv6 nameservers.",
|
|
validator.validate_connection_one,
|
|
"nm",
|
|
validator.validate(ipv6_dns_with_ipv6_disabled),
|
|
0,
|
|
)
|
|
Util.NM = old_util_nm
|
|
|
|
def test_ipv6_dns_with_static_ipv6_configuration(self):
|
|
"""
|
|
Test that configuring IPv6 DNS is allowed when static IPv6 is configured.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
ipv6_dns_with_static_ipv6_configuration = [
|
|
{
|
|
"name": "test_ipv6_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": False,
|
|
"dns": ["2001:db8::20"],
|
|
"address": ["2001:db8::2/32"],
|
|
},
|
|
}
|
|
]
|
|
# the connection index is 0 because there is only one connection profile
|
|
# defined here
|
|
connection_index = 0
|
|
|
|
self.assertEqual(
|
|
validator.validate_connection_one(
|
|
"nm",
|
|
validator.validate(ipv6_dns_with_static_ipv6_configuration),
|
|
connection_index,
|
|
),
|
|
None,
|
|
)
|
|
|
|
def test_ipv6_dns_without_ipv6_configuration(self):
|
|
"""
|
|
Test that configuring IPv6 DNS is not allowed when IPv6 is not configured.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
ipv6_dns_without_ipv6_configuration = [
|
|
{
|
|
"name": "test_ipv6_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": False,
|
|
"dns": ["2001:db8::20"],
|
|
},
|
|
}
|
|
]
|
|
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"IPv6 needs to be enabled to support IPv6 nameservers.",
|
|
validator.validate_connection_one,
|
|
"nm",
|
|
validator.validate(ipv6_dns_without_ipv6_configuration),
|
|
0,
|
|
)
|
|
|
|
def test_ipv6_dns_options_without_ipv6_config(self):
|
|
"""
|
|
Test that configuring IPv6 DNS options is not allowed when IPv6 is disabled.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
ipv6_dns_options_without_ipv6_config = [
|
|
{
|
|
"name": "test_ipv6_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"dhcp4": True,
|
|
"dns_options": ["ip6-bytestring"],
|
|
},
|
|
}
|
|
]
|
|
old_util_nm = Util.NM
|
|
Util.NM = MagicMock(spec=["SETTING_IP6_CONFIG_METHOD_DISABLED"])
|
|
self.assertRaises(
|
|
ValidationError,
|
|
validator.validate_connection_one,
|
|
"nm",
|
|
validator.validate(ipv6_dns_options_without_ipv6_config),
|
|
0,
|
|
)
|
|
Util.NM = old_util_nm
|
|
|
|
def test_dns_search_without_ipv4_and_ipv6_configuration(self):
|
|
"""
|
|
Test that configuring DNS search setting is not allowed when both IPv4 and
|
|
IPv6 are not configured.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
dns_search_without_ipv4_and_ipv6_configuration = [
|
|
{
|
|
"name": "test_dns_search",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"auto6": False,
|
|
"dns_search": ["example.com"],
|
|
},
|
|
}
|
|
]
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"Setting 'dns_search', 'dns_options' and 'dns_priority' are not allowed "
|
|
"when IPv4 is disabled and IPv6 is not configured",
|
|
validator.validate_connection_one,
|
|
"nm",
|
|
validator.validate(dns_search_without_ipv4_and_ipv6_configuration),
|
|
0,
|
|
)
|
|
|
|
def test_auto6_enabled_ipv6_disabled(self):
|
|
"""
|
|
Test that enabling `auto6` and disabling IPv6 are mutually exclusive.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
auto6_enabled_ipv6_disabled = [
|
|
{
|
|
"name": "test_ipv6_method",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"auto6": True,
|
|
},
|
|
}
|
|
]
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'auto6' and 'ipv6_disabled' are mutually exclusive",
|
|
validator.validate,
|
|
auto6_enabled_ipv6_disabled,
|
|
)
|
|
|
|
def test_static_ipv6_configured_ipv6_disabled(self):
|
|
"""
|
|
Test that configuring static IPv6 and disabling IPv6 are mutually exclusive.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
static_ipv6_configured_ipv6_disabled = [
|
|
{
|
|
"name": "test_ipv6_method",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"address": ["2001:db8::2/32"],
|
|
},
|
|
}
|
|
]
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'ipv6_disabled' and static IPv6 addresses are mutually exclusive",
|
|
validator.validate,
|
|
static_ipv6_configured_ipv6_disabled,
|
|
)
|
|
|
|
def test_gateway6_configured_ipv6_disabled(self):
|
|
"""
|
|
Test that configuring `gateway6` and disabling IPv6 are mutually exclusive.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
gateway6_configured_ipv6_disabled = [
|
|
{
|
|
"name": "test_ipv6_method",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"gateway6": "2001:db8::1",
|
|
},
|
|
}
|
|
]
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'ipv6_disabled' and 'gateway6' are mutually exclusive",
|
|
validator.validate,
|
|
gateway6_configured_ipv6_disabled,
|
|
)
|
|
|
|
def test_route_metric6_configured_ipv6_disabled(self):
|
|
"""
|
|
Test that configuring `route_metric6` and disabling IPv6 are mutually
|
|
exclusive.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
route_metric6_configured_ipv6_disabled = [
|
|
{
|
|
"name": "test_ipv6_method",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"ipv6_disabled": True,
|
|
"route_metric6": -1,
|
|
},
|
|
}
|
|
]
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'ipv6_disabled' and 'route_metric6' are mutually exclusive",
|
|
validator.validate,
|
|
route_metric6_configured_ipv6_disabled,
|
|
)
|
|
|
|
# wokeignore:rule=master
|
|
def test_set_deprecated_master(self):
|
|
"""
|
|
wokeignore:rule=master
|
|
When passing the deprecated "master" it is updated to "controller".
|
|
"""
|
|
input_connections = [
|
|
{
|
|
"name": "prod2",
|
|
"state": "up",
|
|
"type": "bridge",
|
|
},
|
|
{
|
|
"name": "prod2-port1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"interface_name": "eth1",
|
|
"master": "prod2", # wokeignore:rule=master
|
|
},
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
self.assertTrue(len(connections) == 2)
|
|
for connection in connections:
|
|
self.assertTrue("controller" in connection)
|
|
# wokeignore:rule=master
|
|
self.assertTrue("master" not in connection)
|
|
|
|
# wokeignore:rule=slave
|
|
def test_set_deprecated_slave_type(self):
|
|
"""
|
|
wokeignore:rule=slave
|
|
When passing the deprecated "slave_type" it is updated to "port_type".
|
|
"""
|
|
input_connections = [
|
|
{
|
|
"name": "prod2",
|
|
"state": "up",
|
|
"type": "bridge",
|
|
},
|
|
{
|
|
"name": "prod2-port1",
|
|
"state": "up",
|
|
"type": "ethernet",
|
|
"interface_name": "eth1",
|
|
"controller": "prod2",
|
|
"slave_type": "bridge", # wokeignore:rule=slave
|
|
},
|
|
]
|
|
connections = ARGS_CONNECTIONS.validate(input_connections)
|
|
self.assertTrue(len(connections) == 2)
|
|
for connection in connections:
|
|
self.assertTrue("port_type" in connection)
|
|
# wokeignore:rule=slave
|
|
self.assertTrue("slave_type" not in connection)
|
|
|
|
def test_validate_ignore_auto_dns(self):
|
|
"""
|
|
Test and validate a connection profile with ipv4_ignore_auto_dns and
|
|
ipv6_ignore_auto_dns enabled.
|
|
"""
|
|
validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
test_ignore_auto_dns = [
|
|
{
|
|
"name": "ignore_auto_dns",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"auto6": True,
|
|
"dhcp4": True,
|
|
"ipv4_ignore_auto_dns": True,
|
|
"ipv6_ignore_auto_dns": True,
|
|
},
|
|
}
|
|
]
|
|
|
|
validator.validate(test_ignore_auto_dns)
|
|
|
|
|
|
@my_test_skipIf(nmutil is None, "no support for NM (libnm via pygobject)")
|
|
class TestNM(unittest.TestCase):
|
|
def test_connection_ensure_setting(self):
|
|
con = NM.SimpleConnection.new()
|
|
self.assertIsNotNone(con)
|
|
self.assertTrue(GObject.type_is_a(con, NM.Connection))
|
|
|
|
s = nmutil.connection_ensure_setting(con, NM.SettingWired)
|
|
self.assertIsNotNone(s)
|
|
self.assertTrue(GObject.type_is_a(s, NM.SettingWired))
|
|
|
|
s2 = nmutil.connection_ensure_setting(con, NM.SettingWired)
|
|
self.assertIsNotNone(s2)
|
|
self.assertIs(s, s2)
|
|
self.assertTrue(GObject.type_is_a(s, NM.SettingWired))
|
|
|
|
def test_connection_list(self):
|
|
connections = nmutil.connection_list()
|
|
self.assertIsNotNone(connections)
|
|
|
|
def test_path_to_glib_bytes(self):
|
|
result = Util.path_to_glib_bytes("/my/test/path")
|
|
self.assertIsInstance(result, Util.GLib().Bytes)
|
|
self.assertEqual(result.get_data(), b"file:///my/test/path\x00")
|
|
|
|
|
|
class TestValidatorMatch(Python26CompatTestCase):
|
|
def setUp(self):
|
|
self.test_profile = {
|
|
"name": "test",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"address": "192.168.245.7/24",
|
|
},
|
|
"match": None,
|
|
}
|
|
self.validator = network_lsr.argument_validator.ArgValidator_DictConnection()
|
|
|
|
def test_match_path_empty_list(self):
|
|
"""
|
|
Test that 'match.path' setting can be defined as None, [], [""], [None] or ""
|
|
and such a setting will be normalized into []
|
|
"""
|
|
for disabled_path in [None, [], [""], [None], ""]:
|
|
self.test_profile["match"] = {"path": disabled_path}
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["match"], {"path": []})
|
|
|
|
def test_match_path_setting_normalization(self):
|
|
"""
|
|
Test that 'match.path' setting ["", "usb123", None] will be normalized into
|
|
["usb123"]
|
|
"""
|
|
self.test_profile["match"] = {"path": ["", "usb123", None]}
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["match"], {"path": ["usb123"]})
|
|
|
|
def test_match_path_valid_setting(self):
|
|
"""
|
|
Test that values like ["pci-0000:00:03.0"] and ["&!pci-0000:00:0[1-3].0"] are
|
|
valid values for 'match.path' setting
|
|
"""
|
|
self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}
|
|
result1 = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result1["match"], {"path": ["pci-0000:00:03.0"]})
|
|
|
|
self.test_profile["match"] = {"path": ["&!pci-0000:00:0[1-3].0"]}
|
|
result2 = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result2["match"], {"path": ["&!pci-0000:00:0[1-3].0"]})
|
|
|
|
def test_match_path_invalid_setting(self):
|
|
"""
|
|
Test that values like ["&"] and ["|"] are invalid values for 'match.path'
|
|
setting
|
|
"""
|
|
self.test_profile["match"] = {"path": ["&", ""]}
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"['&'] will only match the devices that have no PCI path",
|
|
self.validator.validate,
|
|
self.test_profile,
|
|
)
|
|
self.test_profile["match"] = {"path": ["|", None]}
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"['|'] will only match the devices that have no PCI path",
|
|
self.validator.validate,
|
|
self.test_profile,
|
|
)
|
|
|
|
def test_match_path_invalid_connection_type(self):
|
|
"""
|
|
Test that when 'match.path' setting is correctly defined but the connection
|
|
type is neither ethernet nor infiniband, a ValidationError raises.
|
|
"""
|
|
self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["match"], {"path": ["pci-0000:00:03.0"]})
|
|
|
|
self.test_profile["type"] = "dummy" # wokeignore:rule=dummy
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'match.path' settings are only supported for type 'ethernet' or 'infiniband'",
|
|
self.validator.validate,
|
|
self.test_profile,
|
|
)
|
|
|
|
def test_interface_name_when_match_not_specified(self):
|
|
"""
|
|
Test that when 'match' setting is not specified, interface name should be
|
|
profile name.
|
|
"""
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["interface_name"], "test")
|
|
|
|
def test_interface_name_and_match_when_match_is_None(self):
|
|
"""
|
|
Test that when 'match' setting is None, interface name should be profile name
|
|
and 'match' setting will be normalized into {}.
|
|
"""
|
|
self.test_profile["match"] = None
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["match"], {})
|
|
self.assertEqual(result["interface_name"], "test")
|
|
|
|
def test_interface_name_when_match_path_is_empty_list(self):
|
|
"""
|
|
Test that when 'match.path' setting is empty list, interface name should be
|
|
profile name.
|
|
"""
|
|
self.test_profile["match"] = {"path": []}
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["interface_name"], "test")
|
|
|
|
def test_interface_name_when_match_path_is_valid(self):
|
|
"""
|
|
Test that when 'match.path' setting contains interface path, interface name
|
|
should be unset.
|
|
"""
|
|
self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}
|
|
result = self.validator.validate(self.test_profile)
|
|
self.assertEqual(result["interface_name"], None)
|
|
|
|
|
|
class TestUtils(unittest.TestCase):
|
|
def test_mac_ntoa(self):
|
|
mac_bytes = b"\xaa\xbb\xcc\xdd\xee\xff"
|
|
self.assertEqual(Util.mac_ntoa(mac_bytes), "aa:bb:cc:dd:ee:ff")
|
|
|
|
def test_convert_passwd_flags_nm(self):
|
|
test_cases = [
|
|
([], 0),
|
|
(["none"], 0),
|
|
(["agent-owned"], 1),
|
|
(["not-saved"], 2),
|
|
(["agent-owned", "not-saved"], 3),
|
|
(
|
|
["not-required"],
|
|
4,
|
|
),
|
|
(["agent-owned", "not-required"], 5),
|
|
(["not-saved", "not-required"], 6),
|
|
(["agent-owned", "not-saved", "not-required"], 7),
|
|
]
|
|
|
|
for test_case in test_cases:
|
|
result = Util.convert_passwd_flags_nm(test_case[0])
|
|
self.assertEqual(result, test_case[1])
|
|
|
|
|
|
class TestValidatorRouteTable(Python26CompatTestCase):
|
|
def setUp(self):
|
|
self.test_connections = [
|
|
{
|
|
"name": "eth0",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"address": ["198.51.100.3/26"],
|
|
"route": [
|
|
{
|
|
"network": "198.51.100.128",
|
|
"prefix": 26,
|
|
"gateway": "198.51.100.1",
|
|
"metric": 2,
|
|
"table": 30400,
|
|
},
|
|
],
|
|
"routing_rule": [],
|
|
},
|
|
}
|
|
]
|
|
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
self.rt_parsing = network_lsr.argument_validator.IPRouteUtils()
|
|
self.old_getter = (
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping
|
|
)
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
|
|
classmethod(
|
|
lambda cls: {
|
|
"custom": 200,
|
|
"eth": 30400,
|
|
}
|
|
)
|
|
)
|
|
# the connection index is 0 because there is only one connection profile
|
|
# defined here
|
|
self.connection_index = 0
|
|
|
|
def tearDown(self):
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
|
|
self.old_getter
|
|
)
|
|
|
|
def test_valid_numeric_route_tables(self):
|
|
"""
|
|
Test that the value between 1 and 4294967295 are the valid value for numeric
|
|
route tables and the value will not be normalized
|
|
"""
|
|
|
|
self.validator.validate_route_tables(
|
|
self.validator.validate(self.test_connections)[0],
|
|
self.connection_index,
|
|
)
|
|
self.assertEqual(
|
|
self.test_connections[0]["ip"]["route"][0]["table"],
|
|
30400,
|
|
)
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = 200
|
|
self.validator.validate_route_tables(
|
|
self.validator.validate(self.test_connections)[0],
|
|
self.connection_index,
|
|
)
|
|
self.assertEqual(
|
|
self.test_connections[0]["ip"]["route"][0]["table"],
|
|
200,
|
|
)
|
|
|
|
def test_invalid_numeric_route_tables(self):
|
|
"""
|
|
Test that the value less than 1 or greater than 4294967295 are the invalid
|
|
value for numeric route tables
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = 0
|
|
val_min = 1
|
|
val_max = 0xFFFFFFFF
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table value is {0} but cannot be less than {1}".format(
|
|
self.test_connections[0]["ip"]["route"][0]["table"],
|
|
val_min,
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = 4294967296
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table value is {0} but cannot be greater than {1}".format(
|
|
self.test_connections[0]["ip"]["route"][0]["table"],
|
|
val_max,
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_empty_route_table_name(self):
|
|
"""
|
|
Test that empty string is invalid value for route table name
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = ""
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table name cannot be empty string",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_invalid_value_types_for_route_tables(self):
|
|
"""
|
|
Test that the value types apart from string type and integer type are all
|
|
invalid value types for route tables
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = False
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table must be the named or numeric tables but is {0}".format(
|
|
self.test_connections[0]["ip"]["route"][0]["table"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = 2.5
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table must be the named or numeric tables but is {0}".format(
|
|
self.test_connections[0]["ip"]["route"][0]["table"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_invalid_route_table_names(self):
|
|
"""
|
|
Test that the route table names should not be composed from the characters
|
|
which are not contained within the benign set r"^[a-zA-Z0-9_.-]+$"
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = "test*"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table name contains invalid characters",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = "!!!"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"route table name contains invalid characters",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_parse_rt_tables(self):
|
|
"""
|
|
Test that the `IPRouteUtils._parse_route_tables_mapping()` will create the
|
|
route tables mapping dictionary when feeding the proper route table file
|
|
content
|
|
"""
|
|
|
|
def parse(file_content):
|
|
mapping = {}
|
|
network_lsr.argument_validator.IPRouteUtils._parse_route_tables_mapping(
|
|
file_content, mapping
|
|
)
|
|
return mapping
|
|
|
|
self.assertEqual(parse(b""), {})
|
|
self.assertEqual(parse(b"5x"), {})
|
|
self.assertEqual(parse(b"5x x"), {})
|
|
self.assertEqual(parse(b"0x x"), {})
|
|
self.assertEqual(parse(b"-1 x"), {})
|
|
self.assertEqual(parse(b"0x100000000 x"), {})
|
|
self.assertEqual(parse(b"0xF5 x"), {"x": 0xF5})
|
|
self.assertEqual(parse(b"0x5a x"), {"x": 0x5A})
|
|
self.assertEqual(parse(b" 0x5a x"), {"x": 0x5A})
|
|
self.assertEqual(parse(b"0x0 x"), {"x": 0x0})
|
|
self.assertEqual(parse(b"5 x"), {"x": 5})
|
|
self.assertEqual(parse(b" 7 y "), {"y": 7})
|
|
self.assertEqual(parse(b"5 x\n0x4 y"), {"x": 5, "y": 4})
|
|
self.assertEqual(parse(b"5 x #df\n0x4 y"), {"x": 5, "y": 4})
|
|
self.assertEqual(parse(b"5 x #df\n0x4 y\n7\ty"), {"x": 5, "y": 7})
|
|
self.assertEqual(parse(b"-1 x #df\n0x4 y\n5 x"), {"x": 5, "y": 4})
|
|
self.assertEqual(
|
|
parse(b"5 x #df\n0x4 y\n7\t \ty\n\t\t44 7\n 66 a%\n 67 ab"),
|
|
{"x": 5, "y": 7, "7": 44, "ab": 67},
|
|
)
|
|
|
|
# https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/etc/iproute2/rt_tables?id=11e41a635cfab54e8e02fbff2a03715467e77ae9
|
|
self.assertEqual(
|
|
parse(
|
|
b"#\n"
|
|
b"# reserved values\n"
|
|
b"#\n"
|
|
b"255 local\n"
|
|
b"254 main\n"
|
|
b"253 default\n"
|
|
b"0 unspec\n"
|
|
b"#\n"
|
|
b"# local\n"
|
|
b"#\n"
|
|
b"#1 inr.ruhep\n"
|
|
),
|
|
{"local": 255, "main": 254, "default": 253, "unspec": 0},
|
|
)
|
|
|
|
def test_table_found_when_validate_route_tables(self):
|
|
"""
|
|
Test that the `validate_route_tables()` will find the table id mapping from
|
|
`IPRouteUtils.get_route_tables_mapping()`.
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = "custom"
|
|
|
|
self.validator.validate_route_tables(
|
|
self.test_connections[0],
|
|
self.connection_index,
|
|
)
|
|
self.assertEqual(
|
|
self.test_connections[0]["ip"]["route"][0]["table"],
|
|
200,
|
|
)
|
|
|
|
def test_table_not_found_when_validate_route_tables(self):
|
|
"""
|
|
Test that the validation error is raised when the `validate_route_tables()` cannot
|
|
find the table id mapping from `IPRouteUtils.get_route_tables_mapping()`.
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["table"] = "test"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"cannot find route table {0} in `/etc/iproute2/rt_tables` or "
|
|
"`/etc/iproute2/rt_tables.d/`".format(
|
|
self.test_connections[0]["ip"]["route"][0]["table"]
|
|
),
|
|
self.validator.validate_route_tables,
|
|
self.test_connections[0],
|
|
self.connection_index,
|
|
)
|
|
|
|
def test_type_route_with_gateway(self):
|
|
"""
|
|
Test that the route type route can not have a gateway
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["type"] = "blackhole"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"a {0} route can not have a gateway '{1}'".format(
|
|
self.test_connections[0]["ip"]["route"][0]["type"],
|
|
self.test_connections[0]["ip"]["route"][0]["gateway"],
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_route_with_source_address(self):
|
|
"""
|
|
Test setting the route with src address specified
|
|
"""
|
|
self.test_connections[0]["ip"]["route"][0]["src"] = "2001:db8::2"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"conflicting address family between network and src "
|
|
"address {0}".format(
|
|
self.test_connections[0]["ip"]["route"][0]["src"],
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
self.test_connections[0]["ip"]["route"][0]["src"] = "198.51.100.3"
|
|
result = self.validator.validate(self.test_connections)
|
|
self.assertEqual(result[0]["ip"]["route"][0]["src"], "198.51.100.3")
|
|
|
|
|
|
class TestValidatorRoutingRules(Python26CompatTestCase):
|
|
def setUp(self):
|
|
self.test_connections = [
|
|
{
|
|
"name": "eth0",
|
|
"type": "ethernet",
|
|
"ip": {
|
|
"dhcp4": False,
|
|
"address": ["198.51.100.3/26"],
|
|
"route": [
|
|
{
|
|
"network": "198.51.100.128",
|
|
"prefix": 26,
|
|
"gateway": "198.51.100.1",
|
|
"metric": 2,
|
|
"table": 30400,
|
|
},
|
|
],
|
|
"routing_rule": [
|
|
{
|
|
"action": "to-table",
|
|
"priority": 256,
|
|
},
|
|
],
|
|
},
|
|
}
|
|
]
|
|
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
self.old_getter = (
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping
|
|
)
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
|
|
classmethod(
|
|
lambda cls: {
|
|
"custom": 200,
|
|
"eth": 30400,
|
|
}
|
|
)
|
|
)
|
|
# the connection index is 0 because there is only one connection profile
|
|
# defined here
|
|
self.connection_index = 0
|
|
|
|
def tearDown(self):
|
|
network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (
|
|
self.old_getter
|
|
)
|
|
|
|
def test_routing_rule_missing_address_family(self):
|
|
"""
|
|
Test that the address family has to be specified if cannot be derived from src
|
|
or dst address
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["suppress_prefixlength"] = 32
|
|
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"specify the address family 'family'",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_validate_address_family(self):
|
|
"""
|
|
Test that the derived address family and the specified address family should be
|
|
consistent
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv6"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "198.51.100.58/24"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"invalid address family in 'from'",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "2001:db8::2/32"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "198.51.100.60/24"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"invalid address family in 'to'",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "::/0"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "::/0"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "0.0.0.0/0"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "0.0.0.0/0"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_routing_rule_missing_table(self):
|
|
"""
|
|
Test that table has to be defined when the action of the routing rule is
|
|
"to-table"
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"missing 'table' for the routing rule",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_invalid_from_prefix_length(self):
|
|
"""
|
|
Test that the prefix length for from/src cannot be zero when from/src is
|
|
specified
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "198.51.100.58/0"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the prefix length for 'from' cannot be zero",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_invalid_to_prefix_length(self):
|
|
"""
|
|
Test that the prefix length for to/dst cannot be zero when to/dst is specified
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "198.51.100.58/0"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the prefix length for 'to' cannot be zero",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_validate_fwmark(self):
|
|
"""
|
|
Test that fwmark requires fwmask to be specified
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["fwmark"] = 1
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'fwmask' and 'fwmark' must be set together",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_validate_fwmask(self):
|
|
"""
|
|
Test that fwmask requires fwmark to be specified
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["fwmask"] = 1
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'fwmask' and 'fwmark' must be set together",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_invalid_incoming_interface_name(self):
|
|
"""
|
|
Test the invalid incoming interface name specified in the routing rule
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["iif"] = " test "
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the incoming interface '{0}' specified in the routing rule is invalid "
|
|
"interface_name".format(
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["iif"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_invalid_outgoing_interface_name(self):
|
|
"""
|
|
Test the invalid outgoing interface name specified in the routing rule
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["oif"] = " test "
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the outgoing interface '{0}' specified in the routing rule is invalid "
|
|
"interface_name".format(
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["oif"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_validate_uid(self):
|
|
"""
|
|
Test the invalid uid specified in the routing rule
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["uid"] = "2000 - 1000"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the range start cannot be greater than range end",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_routing_rule_validate_suppress_prefixlength(self):
|
|
"""
|
|
Test the invalid suppress_prefixlength setting
|
|
"""
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["suppress_prefixlength"] = 40
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 256
|
|
suppress_prefixlength_val_max = Util.addr_family_prefix_length(
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"]
|
|
)
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"The specified 'suppress_prefixlength' cannot be greater than {0}".format(
|
|
suppress_prefixlength_val_max
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv6"
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["action"] = "blackhole"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"'suppress_prefixlength' is only allowed with the to-table action",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
def test_table_found_when_lookup_named_table(self):
|
|
"""
|
|
Test that the `validate_route_tables()` will find the table id mapping from
|
|
`IPRouteUtils.get_route_tables_mapping()`.
|
|
"""
|
|
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"] = "custom"
|
|
|
|
self.validator.validate_route_tables(
|
|
self.test_connections[0],
|
|
self.connection_index,
|
|
)
|
|
self.assertEqual(
|
|
self.test_connections[0]["ip"]["routing_rule"][0]["table"],
|
|
200,
|
|
)
|
|
|
|
|
|
class TestValidatorDictBond(Python26CompatTestCase):
|
|
def setUp(self):
|
|
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
self.test_connections = [
|
|
{
|
|
"name": "bond0",
|
|
"type": "bond",
|
|
"bond": {
|
|
"mode": "balance-rr",
|
|
},
|
|
},
|
|
]
|
|
|
|
def test_invalid_bond_option_ad(self):
|
|
"""
|
|
Test the ad bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["ad_actor_sys_prio"] = 65535
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option ad_actor_sys_prio is only valid with mode 802.3ad",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "802.3ad"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_packets_per_port(self):
|
|
"""
|
|
Test the packets_per_port bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["mode"] = "802.3ad"
|
|
self.test_connections[0]["bond"]["packets_per_port"] = 2
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option packets_per_port is only valid with mode balance-rr",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "balance-rr"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_arp(self):
|
|
"""
|
|
Test the arp bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["mode"] = "802.3ad"
|
|
self.test_connections[0]["bond"]["arp_interval"] = 2
|
|
self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"
|
|
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option arp_interval is only valid with mode balance-rr, active-backup, balance-xor or broadcast",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "balance-rr"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_tlb_dynamic_lb(self):
|
|
"""
|
|
Test the tlb_dynamic_lb bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["tlb_dynamic_lb"] = True
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option tlb_dynamic_lb is only valid with mode balance-tlb or balance-alb",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "balance-tlb"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_primary(self):
|
|
"""
|
|
Test the primary bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["primary"] = "bond0.0"
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option primary is only valid with mode active-backup, balance-tlb, balance-alb",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "balance-tlb"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_downdelay_updelay(self):
|
|
"""
|
|
Test the downdelay or updelay bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["downdelay"] = 5
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option downdelay or updelay is only valid with miimon enabled",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["miimon"] = 110
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_peer_notif_delay(self):
|
|
"""
|
|
Test the peer_notif_delay bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["miimon"] = 110
|
|
self.test_connections[0]["bond"]["peer_notif_delay"] = 222
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option peer_notif_delay needs miimon enabled and must be miimon multiple",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["peer_notif_delay"] = 220
|
|
self.test_connections[0]["bond"]["arp_interval"] = 110
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option peer_notif_delay needs arp_interval disabled",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["arp_interval"] = 0
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_peer_arp_ip_target_arp_interval(self):
|
|
"""
|
|
Test the arp_ip_target or arp_interval bond option restrictions
|
|
"""
|
|
self.test_connections[0]["bond"]["arp_interval"] = 4
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option arp_interval requires arp_ip_target to be set",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"
|
|
self.test_connections[0]["bond"]["arp_interval"] = 0
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the bond option arp_ip_target requires arp_interval to be set",
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[0]["bond"]["arp_interval"] = 4
|
|
self.validator.validate(self.test_connections)
|
|
|
|
def test_invalid_bond_option_infiniband_port(self):
|
|
"""
|
|
Test that bond only supports infiniband ports in active-backup mode
|
|
"""
|
|
test_connections_with_infiniband_port = [
|
|
{
|
|
"name": "bond0",
|
|
"type": "bond",
|
|
"bond": {
|
|
"mode": "balance-rr",
|
|
},
|
|
},
|
|
{
|
|
"name": "bond0.0",
|
|
"type": "infiniband",
|
|
"controller": "bond0",
|
|
},
|
|
{
|
|
"name": "bond0.1",
|
|
"type": "infiniband",
|
|
"controller": "bond0",
|
|
},
|
|
]
|
|
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"bond only supports infiniband ports in active-backup mode",
|
|
self.validator.validate,
|
|
test_connections_with_infiniband_port,
|
|
)
|
|
self.test_connections[0]["bond"]["mode"] = "active-backup"
|
|
self.validator.validate(self.test_connections)
|
|
|
|
|
|
class TestValidatorDictInfiniband(Python26CompatTestCase):
|
|
def setUp(self):
|
|
self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()
|
|
self.test_connections = [
|
|
{
|
|
"name": "ib0",
|
|
"type": "infiniband",
|
|
"interface_name": "ib0",
|
|
},
|
|
{
|
|
"name": "ib0-10",
|
|
"type": "infiniband",
|
|
"infiniband": {
|
|
"p_key": 10,
|
|
"transport_mode": "datagram",
|
|
},
|
|
"parent": "ib0",
|
|
},
|
|
]
|
|
|
|
def test_invalid_pkey_values(self):
|
|
self.test_connections[1]["infiniband"]["p_key"] = 0x0000
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the pkey value {0} is not allowed as such a pkey value is not "
|
|
"supported by kernel".format(
|
|
self.test_connections[1]["infiniband"]["p_key"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
self.test_connections[1]["infiniband"]["p_key"] = 0x8000
|
|
self.assertRaisesRegex(
|
|
ValidationError,
|
|
"the pkey value {0} is not allowed as such a pkey value is not "
|
|
"supported by kernel".format(
|
|
self.test_connections[1]["infiniband"]["p_key"]
|
|
),
|
|
self.validator.validate,
|
|
self.test_connections,
|
|
)
|
|
|
|
|
|
class TestSysUtils(unittest.TestCase):
|
|
def test_link_read_permaddress(self):
|
|
self.assertEqual(SysUtil._link_read_permaddress("lo"), "00:00:00:00:00:00")
|
|
self.assertEqual(SysUtil._link_read_permaddress("fakeiface"), None)
|
|
self.assertEqual(SysUtil._link_read_permaddress("morethansixteenchars"), None)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|