Best Python code snippet using lisa_python
test_network_connections.py
Source:test_network_connections.py
1#!/usr/bin/env python2""" Tests for network_connections Ansible module """3# SPDX-License-Identifier: BSD-3-Clause4import copy5import itertools6import pprint as pprint_7import socket8import sys9import unittest10try:11 from unittest import mock12 from unittest.mock import MagicMock13except ImportError: # py214 import mock15 from mock import MagicMock16sys.modules["ansible.module_utils.basic"] = mock.Mock()17# pylint: disable=import-error, wrong-import-position18import network_lsr19import network_lsr.argument_validator20from network_connections import IfcfgUtil, NMUtil, SysUtil, Util21from network_lsr.argument_validator import ValidationError22try:23 my_test_skipIf = unittest.skipIf24except AttributeError:25 # python 2.6 workaround26 def my_test_skipIf(condition, reason):27 if condition:28 return lambda x: None29 else:30 return lambda x: x31try:32 nmutil = NMUtil()33 assert nmutil34except Exception:35 # NMUtil is not supported, for example on RHEL 6 or without36 # pygobject.37 nmutil = None38if nmutil:39 NM = Util.NM()40 GObject = Util.GObject()41def pprint(msg, obj):42 print("PRINT: %s\n" % (msg))43 p = pprint_.PrettyPrinter(indent=4)44 p.pprint(obj)45 if nmutil is not None and isinstance(obj, NM.Connection):46 obj.dump()47class Python26CompatTestCase(unittest.TestCase):48 # pylint: disable=no-member49 def assertRaisesRegex(self, exception, regex, *args, **kwargs):50 if sys.version_info[:2] == (2, 6):51 self.assertRaises(exception, *args, **kwargs)52 elif sys.version_info[:2] < (3, 2):53 self.assertRaisesRegexp(exception, regex, *args, **kwargs)54 else:55 super(Python26CompatTestCase, self).assertRaisesRegex(56 exception, regex, *args, **kwargs57 )58ARGS_CONNECTIONS = network_lsr.argument_validator.ArgValidator_ListConnections()59VALIDATE_ONE_MODE_INITSCRIPTS = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_INITSCRIPTS60VALIDATE_ONE_MODE_NM = ARGS_CONNECTIONS.VALIDATE_ONE_MODE_NM61ETHTOOL_FEATURES_DEFAULTS = {62 "esp_hw_offload": None,63 "esp_tx_csum_hw_offload": None,64 "fcoe_mtu": None,65 "gro": None,66 "gso": None,67 "highdma": None,68 "hw_tc_offload": None,69 "l2_fwd_offload": None,70 "loopback": None,71 "lro": None,72 "ntuple": None,73 "rx": None,74 "rx_all": None,75 "rx_fcs": None,76 "rx_gro_hw": None,77 "rx_udp_tunnel_port_offload": None,78 "rx_vlan_filter": None,79 "rx_vlan_stag_filter": None,80 "rx_vlan_stag_hw_parse": None,81 "rxhash": None,82 "rxvlan": None,83 "sg": None,84 "tls_hw_record": None,85 "tls_hw_tx_offload": None,86 "tso": None,87 "tx": None,88 "tx_checksum_fcoe_crc": None,89 "tx_checksum_ip_generic": None,90 "tx_checksum_ipv4": None,91 "tx_checksum_ipv6": None,92 "tx_checksum_sctp": None,93 "tx_esp_segmentation": None,94 "tx_fcoe_segmentation": None,95 "tx_gre_csum_segmentation": None,96 "tx_gre_segmentation": None,97 "tx_gso_partial": None,98 "tx_gso_robust": None,99 "tx_ipxip4_segmentation": None,100 "tx_ipxip6_segmentation": None,101 "tx_nocache_copy": None,102 "tx_scatter_gather": None,103 "tx_scatter_gather_fraglist": None,104 "tx_sctp_segmentation": None,105 "tx_tcp_ecn_segmentation": None,106 "tx_tcp_mangleid_segmentation": None,107 "tx_tcp_segmentation": None,108 "tx_tcp6_segmentation": None,109 "tx_udp_segmentation": None,110 "tx_udp_tnl_csum_segmentation": None,111 "tx_udp_tnl_segmentation": None,112 "tx_vlan_stag_hw_insert": None,113 "txvlan": None,114}115ETHTOOL_COALESCE_DEFAULTS = {116 "adaptive_rx": None,117 "adaptive_tx": None,118 "pkt_rate_high": None,119 "pkt_rate_low": None,120 "rx_frames": None,121 "rx_frames_high": None,122 "rx_frames_irq": None,123 "rx_frames_low": None,124 "rx_usecs": None,125 "rx_usecs_high": None,126 "rx_usecs_irq": None,127 "rx_usecs_low": None,128 "sample_interval": None,129 "stats_block_usecs": None,130 "tx_frames": None,131 "tx_frames_high": None,132 "tx_frames_irq": None,133 "tx_frames_low": None,134 "tx_usecs": None,135 "tx_usecs_high": None,136 "tx_usecs_irq": None,137 "tx_usecs_low": None,138}139ETHTOOL_RING_DEFAULTS = {140 "rx": None,141 "rx_jumbo": None,142 "rx_mini": None,143 "tx": None,144}145ETHTOOL_DEFAULTS = {146 "features": ETHTOOL_FEATURES_DEFAULTS,147 "coalesce": ETHTOOL_COALESCE_DEFAULTS,148 "ring": ETHTOOL_RING_DEFAULTS,149}150ETHERNET_DEFAULTS = {"autoneg": None, "duplex": None, "speed": 0}151class TestValidator(Python26CompatTestCase):152 def setUp(self):153 # default values when "type" is specified and state is not154 self.default_connection_settings = {155 "autoconnect": True,156 "check_iface_exists": True,157 "ethernet": ETHERNET_DEFAULTS,158 "ethtool": ETHTOOL_DEFAULTS,159 "ignore_errors": None,160 "ip": {161 "gateway6": None,162 "gateway4": None,163 "route_metric4": None,164 "auto6": True,165 "ipv6_disabled": False,166 "dhcp4": True,167 "address": [],168 "auto_gateway": None,169 "route_append_only": False,170 "rule_append_only": False,171 "route": [],172 "route_metric6": None,173 "routing_rule": [],174 "dhcp4_send_hostname": None,175 "dns": [],176 "dns_options": [],177 "dns_search": [],178 },179 "mac": None,180 "match": {},181 "controller": None,182 "ieee802_1x": None,183 "wireless": None,184 "mtu": None,185 "name": "5",186 "parent": None,187 "port_type": None,188 "zone": None,189 }190 def assertValidationError(self, v, value):191 self.assertRaises(ValidationError, v.validate, value)192 def assert_nm_connection_routes_expected(self, connection, route_list_expected):193 parser = network_lsr.argument_validator.ArgValidatorIPRoute("route[?]")194 route_list_exp = [parser.validate(r) for r in route_list_expected]195 route_list_new = itertools.chain(196 nmutil.setting_ip_config_get_routes(197 connection.get_setting(NM.SettingIP4Config)198 ),199 nmutil.setting_ip_config_get_routes(200 connection.get_setting(NM.SettingIP6Config)201 ),202 )203 route_list_new = [204 {205 "family": r.get_family(),206 "network": r.get_dest(),207 "prefix": int(r.get_prefix()),208 "gateway": r.get_next_hop(),209 "metric": int(r.get_metric()),210 "table": r.get_attribute("table"),211 }212 for r in route_list_new213 ]214 self.assertEqual(route_list_exp, route_list_new)215 def do_connections_check_invalid(self, input_connections):216 self.assertValidationError(ARGS_CONNECTIONS, input_connections)217 def do_connections_validate_nm(self, input_connections, **kwargs):218 if not nmutil:219 return220 connections = ARGS_CONNECTIONS.validate(input_connections)221 for connection in connections:222 if "type" in connection:223 connection["nm.exists"] = False224 connection["nm.uuid"] = Util.create_uuid()225 mode = VALIDATE_ONE_MODE_NM226 for idx, connection in enumerate(connections):227 try:228 ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)229 except ValidationError:230 continue231 if "type" in connection:232 con_new = nmutil.connection_create(connections, idx)233 self.assertTrue(con_new)234 self.assertTrue(con_new.verify())235 if "nm_route_list_current" in kwargs:236 parser = network_lsr.argument_validator.ArgValidatorIPRoute(237 "route[?]"238 )239 s4 = con_new.get_setting(NM.SettingIP4Config)240 s6 = con_new.get_setting(NM.SettingIP6Config)241 s4.clear_routes()242 s6.clear_routes()243 for r in kwargs["nm_route_list_current"][idx]:244 r = parser.validate(r)245 rr = NM.IPRoute.new(246 r["family"],247 r["network"],248 r["prefix"],249 r["gateway"],250 r["metric"],251 )252 if r["table"]:253 NM.IPRoute.set_attribute(254 rr, "table", Util.GLib().Variant.new_uint32(r["table"])255 )256 if r["family"] == socket.AF_INET:257 s4.add_route(rr)258 else:259 s6.add_route(rr)260 con_new = nmutil.connection_create(261 connections, idx, connection_current=con_new262 )263 self.assertTrue(con_new)264 self.assertTrue(con_new.verify())265 if "nm_route_list_expected" in kwargs:266 self.assert_nm_connection_routes_expected(267 con_new, kwargs["nm_route_list_expected"][idx]268 )269 def do_connections_validate_ifcfg(self, input_connections, **kwargs):270 mode = VALIDATE_ONE_MODE_INITSCRIPTS271 connections = ARGS_CONNECTIONS.validate(input_connections)272 for idx, connection in enumerate(connections):273 try:274 ARGS_CONNECTIONS.validate_connection_one(mode, connections, idx)275 except ValidationError:276 continue277 if "type" not in connection:278 continue279 if (280 connection["type"] in ["macvlan", "wireless"]281 or connection["ieee802_1x"]282 ):283 # initscripts do not support this type. Skip the test.284 continue285 content_current = kwargs.get("initscripts_content_current", None)286 if content_current:287 content_current = content_current[idx]288 c = IfcfgUtil.ifcfg_create(289 connections, idx, content_current=content_current290 )291 # pprint("con[%s] = \"%s\"" % (idx, connections[idx]['name']), c)292 exp = kwargs.get("initscripts_dict_expected", None)293 if exp is not None:294 self.assertEqual(exp[idx], c)295 def do_connections_validate(296 self, expected_connections, input_connections, **kwargs297 ):298 connections = ARGS_CONNECTIONS.validate(input_connections)299 self.assertEqual(expected_connections, connections)300 self.do_connections_validate_nm(input_connections, **kwargs)301 self.do_connections_validate_ifcfg(input_connections, **kwargs)302 def test_validate_str(self):303 v = network_lsr.argument_validator.ArgValidatorStr("state")304 self.assertEqual("a", v.validate("a"))305 self.assertValidationError(v, 1)306 self.assertValidationError(v, None)307 v = network_lsr.argument_validator.ArgValidatorStr("state", required=True)308 self.assertValidationError(v, None)309 v = network_lsr.argument_validator.ArgValidatorStr(310 "test_max_length", max_length=13311 )312 self.assertEqual("less_than_13", v.validate("less_than_13"))313 self.assertValidationError(v, "longer_than_13")314 v = network_lsr.argument_validator.ArgValidatorStr(315 "test_min_length", min_length=13316 )317 self.assertEqual("longer_than_13", v.validate("longer_than_13"))318 self.assertValidationError(v, "less_than_13")319 v = network_lsr.argument_validator.ArgValidatorStr(320 "test_min_max_length", min_length=10, max_length=15321 )322 self.assertEqual("13_characters", v.validate("13_characters"))323 self.assertValidationError(v, "too_short")324 self.assertValidationError(v, "string_is_too_long")325 self.assertRaises(326 ValueError,327 network_lsr.argument_validator.ArgValidatorStr,328 "non_int",329 min_length="string",330 )331 self.assertRaises(332 ValueError,333 network_lsr.argument_validator.ArgValidatorStr,334 "non_int",335 max_length="string",336 )337 self.assertRaises(338 ValueError,339 network_lsr.argument_validator.ArgValidatorStr,340 "negative_int",341 min_length=-5,342 )343 self.assertRaises(344 ValueError,345 network_lsr.argument_validator.ArgValidatorStr,346 "negative_int",347 max_length=-5,348 )349 def test_validate_int(self):350 v = network_lsr.argument_validator.ArgValidatorNum(351 "state", default_value=None, numeric_type=float352 )353 self.assertEqual(1, v.validate(1))354 self.assertEqual(1.5, v.validate(1.5))355 self.assertEqual(1.5, v.validate("1.5"))356 self.assertValidationError(v, None)357 self.assertValidationError(v, "1a")358 v = network_lsr.argument_validator.ArgValidatorNum("state", default_value=None)359 self.assertEqual(1, v.validate(1))360 self.assertEqual(1, v.validate(1.0))361 self.assertEqual(1, v.validate("1"))362 self.assertValidationError(v, None)363 self.assertValidationError(v, None)364 self.assertValidationError(v, 1.5)365 self.assertValidationError(v, "1.5")366 v = network_lsr.argument_validator.ArgValidatorNum("state", required=True)367 self.assertValidationError(v, None)368 self.assertValidationError(v, False)369 self.assertValidationError(v, True)370 def test_validate_range(self):371 v = network_lsr.argument_validator.ArgValidatorRange(372 "range", val_min=0, val_max=65534373 )374 self.assertEqual((1, 1), v.validate(1))375 self.assertEqual((10, 1000), v.validate("10-1000"))376 self.assertEqual((256, 256), v.validate("256"))377 self.assertRaisesRegex(378 ValidationError,379 "the range value True is invalid",380 v.validate,381 True,382 )383 self.assertRaisesRegex(384 ValidationError,385 "the range value 2.5 is invalid",386 v.validate,387 2.5,388 )389 self.assertRaisesRegex(390 ValidationError,391 "the range start cannot be greater than range end",392 v.validate,393 "2000-1000",394 )395 self.assertRaisesRegex(396 ValidationError,397 "upper range value is 65535 but cannot be greater than 65534",398 v.validate,399 "1-65535",400 )401 self.assertRaisesRegex(402 ValidationError,403 "lower range value is -1 but cannot be less than 0",404 v.validate,405 -1,406 )407 def test_validate_bool(self):408 v = network_lsr.argument_validator.ArgValidatorBool("state")409 self.assertEqual(True, v.validate("yes"))410 self.assertEqual(True, v.validate("yeS"))411 self.assertEqual(True, v.validate("Y"))412 self.assertEqual(True, v.validate(True))413 self.assertEqual(True, v.validate("True"))414 self.assertEqual(True, v.validate("1"))415 self.assertEqual(True, v.validate(1))416 self.assertEqual(False, v.validate("no"))417 self.assertEqual(False, v.validate("nO"))418 self.assertEqual(False, v.validate("N"))419 self.assertEqual(False, v.validate(False))420 self.assertEqual(False, v.validate("False"))421 self.assertEqual(False, v.validate("0"))422 self.assertEqual(False, v.validate(0))423 self.assertValidationError(v, 2)424 self.assertValidationError(v, -1)425 self.assertValidationError(v, "Ye")426 self.assertValidationError(v, "")427 self.assertValidationError(v, None)428 v = network_lsr.argument_validator.ArgValidatorBool("state", required=True)429 self.assertValidationError(v, None)430 def test_validate_dict(self):431 v = network_lsr.argument_validator.ArgValidatorDict(432 "dict",433 nested=[434 network_lsr.argument_validator.ArgValidatorNum("i", required=True),435 network_lsr.argument_validator.ArgValidatorStr(436 "s", required=False, default_value="s_default"437 ),438 network_lsr.argument_validator.ArgValidatorStr(439 "l",440 required=False,441 default_value=network_lsr.argument_validator.ArgValidator.MISSING,442 ),443 ],444 )445 self.assertEqual({"i": 5, "s": "s_default"}, v.validate({"i": "5"}))446 self.assertEqual(447 {"i": 5, "s": "s_default", "l": "6"}, v.validate({"i": "5", "l": "6"})448 )449 self.assertValidationError(v, {"k": 1})450 self.assertEqual(v.validate(None), {})451 def test_validate_list(self):452 v = network_lsr.argument_validator.ArgValidatorList(453 "list", nested=network_lsr.argument_validator.ArgValidatorNum("i")454 )455 self.assertEqual([1, 5], v.validate(["1", 5]))456 self.assertValidationError(v, [1, "s"])457 self.assertEqual(v.validate(None), [])458 def test_validate_allow_empty_string_in_list(self):459 """460 Test that when ArgValidatorStr.allow_empty is True, empty string is allowed in461 in ArgValidatorList462 """463 v = network_lsr.argument_validator.ArgValidatorList(464 "list",465 nested=network_lsr.argument_validator.ArgValidatorStr(466 "list[?]", allow_empty=True467 ),468 )469 self.assertEqual(v.validate(["pci-0001:00:00.0", ""]), ["pci-0001:00:00.0", ""])470 def test_validate_disallow_none_in_list(self):471 """472 Test that None is not allowed in ArgValidatorList473 """474 v = network_lsr.argument_validator.ArgValidatorList(475 "list",476 nested=network_lsr.argument_validator.ArgValidatorStr(477 "list[?]", allow_empty=True478 ),479 )480 self.assertRaisesRegex(481 ValidationError,482 "must be a string but is 'None'",483 v.validate,484 ["pci-0001:00:00.0", None],485 )486 def test_validate_list_remove_none_or_empty(self):487 """488 Test that when ArgValidatorStr.remove_none_or_empty is True, None or empty489 string will be removed from ArgValidatorList490 """491 v = network_lsr.argument_validator.ArgValidatorList(492 "list",493 nested=network_lsr.argument_validator.ArgValidatorStr(494 "list[?]", allow_empty=True495 ),496 remove_none_or_empty=True,497 )498 self.assertEqual(v.validate(["pci-0001:00:00.0", ""]), ["pci-0001:00:00.0"])499 self.assertEqual(v.validate(["pci-0001:00:00.0", None]), ["pci-0001:00:00.0"])500 def test_empty(self):501 self.maxDiff = None502 self.do_connections_validate([], [])503 def test_ethernet_two_defaults(self):504 self.maxDiff = None505 self.do_connections_validate(506 [507 {508 "actions": ["present"],509 "autoconnect": True,510 "check_iface_exists": True,511 "ethernet": ETHERNET_DEFAULTS,512 "ethtool": ETHTOOL_DEFAULTS,513 "ignore_errors": None,514 "interface_name": "5",515 "ip": {516 "gateway6": None,517 "gateway4": None,518 "route_metric4": None,519 "auto6": True,520 "ipv6_disabled": False,521 "dhcp4": True,522 "address": [],523 "auto_gateway": None,524 "route_append_only": False,525 "rule_append_only": False,526 "route": [],527 "route_metric6": None,528 "routing_rule": [],529 "dhcp4_send_hostname": None,530 "dns": [],531 "dns_options": [],532 "dns_search": [],533 },534 "mac": None,535 "match": {},536 "controller": None,537 "ieee802_1x": None,538 "wireless": None,539 "mtu": None,540 "name": "5",541 "parent": None,542 "persistent_state": "present",543 "port_type": None,544 "state": None,545 "type": "ethernet",546 "zone": None,547 },548 {549 "actions": ["present"],550 "ignore_errors": None,551 "name": "5",552 "persistent_state": "present",553 "state": None,554 },555 ],556 [{"name": "5", "type": "ethernet"}, {"name": "5"}],557 )558 def test_up_ethernet(self):559 self.maxDiff = None560 self.do_connections_validate(561 [562 {563 "actions": ["present", "up"],564 "autoconnect": True,565 "check_iface_exists": True,566 "ethernet": ETHERNET_DEFAULTS,567 "ethtool": ETHTOOL_DEFAULTS,568 "force_state_change": None,569 "ignore_errors": None,570 "interface_name": "5",571 "ip": {572 "gateway6": None,573 "gateway4": None,574 "route_metric4": None,575 "auto6": True,576 "ipv6_disabled": False,577 "dhcp4": True,578 "address": [],579 "auto_gateway": None,580 "route_append_only": False,581 "rule_append_only": False,582 "route": [],583 "dns": [],584 "dns_options": [],585 "dns_search": [],586 "route_metric6": None,587 "routing_rule": [],588 "dhcp4_send_hostname": None,589 },590 "mac": None,591 "match": {},592 "controller": None,593 "ieee802_1x": None,594 "wireless": None,595 "mtu": None,596 "name": "5",597 "parent": None,598 "persistent_state": "present",599 "port_type": None,600 "state": "up",601 "type": "ethernet",602 "wait": None,603 "zone": None,604 }605 ],606 [{"name": "5", "state": "up", "type": "ethernet"}],607 )608 def test_up_ethernet_no_autoconnect(self):609 self.maxDiff = None610 self.do_connections_validate(611 [612 {613 "actions": ["present", "up"],614 "autoconnect": False,615 "check_iface_exists": True,616 "ethernet": ETHERNET_DEFAULTS,617 "ethtool": ETHTOOL_DEFAULTS,618 "force_state_change": None,619 "ignore_errors": None,620 "interface_name": "5",621 "ip": {622 "gateway6": None,623 "gateway4": None,624 "route_metric4": None,625 "auto6": True,626 "ipv6_disabled": False,627 "dhcp4": True,628 "address": [],629 "auto_gateway": None,630 "route_append_only": False,631 "rule_append_only": False,632 "route": [],633 "dns": [],634 "dns_options": [],635 "dns_search": [],636 "route_metric6": None,637 "routing_rule": [],638 "dhcp4_send_hostname": None,639 },640 "mac": None,641 "match": {},642 "controller": None,643 "ieee802_1x": None,644 "wireless": None,645 "mtu": None,646 "name": "5",647 "parent": None,648 "persistent_state": "present",649 "port_type": None,650 "state": "up",651 "type": "ethernet",652 "wait": None,653 "zone": None,654 }655 ],656 [{"name": "5", "state": "up", "type": "ethernet", "autoconnect": "no"}],657 initscripts_dict_expected=[658 {659 "ifcfg": {660 "BOOTPROTO": "dhcp",661 "IPV6INIT": "yes",662 "IPV6_AUTOCONF": "yes",663 "NM_CONTROLLED": "no",664 "ONBOOT": "no",665 "TYPE": "Ethernet",666 "DEVICE": "5",667 },668 "keys": None,669 "route": None,670 "route6": None,671 "rule": None,672 "rule6": None,673 }674 ],675 )676 def test_invalid_autoconnect(self):677 self.maxDiff = None678 self.do_connections_check_invalid([{"name": "a", "autoconnect": True}])679 def test_absent(self):680 self.maxDiff = None681 self.do_connections_validate(682 [683 {684 "actions": ["absent"],685 "ignore_errors": None,686 "name": "5",687 "persistent_state": "absent",688 "state": None,689 }690 ],691 [{"name": "5", "persistent_state": "absent"}],692 )693 def test_up_ethernet_mac_mtu_static_ip(self):694 self.maxDiff = None695 self.do_connections_validate(696 [697 {698 "actions": ["present", "up"],699 "autoconnect": True,700 "check_iface_exists": True,701 "ethernet": ETHERNET_DEFAULTS,702 "ethtool": ETHTOOL_DEFAULTS,703 "force_state_change": None,704 "ignore_errors": None,705 "interface_name": None,706 "match": {},707 "ip": {708 "dhcp4": False,709 "route_metric6": None,710 "route_metric4": None,711 "dns_options": [],712 "dns_search": [],713 "dhcp4_send_hostname": None,714 "gateway6": None,715 "gateway4": None,716 "auto6": True,717 "ipv6_disabled": False,718 "dns": [],719 "address": [720 {721 "prefix": 24,722 "family": socket.AF_INET,723 "address": "192.168.174.5",724 }725 ],726 "auto_gateway": None,727 "route_append_only": False,728 "rule_append_only": False,729 "route": [],730 "routing_rule": [],731 },732 "mac": "52:54:00:44:9f:ba",733 "controller": None,734 "ieee802_1x": None,735 "wireless": None,736 "mtu": 1450,737 "name": "prod1",738 "parent": None,739 "persistent_state": "present",740 "port_type": None,741 "state": "up",742 "type": "ethernet",743 "wait": None,744 "zone": None,745 }746 ],747 [748 {749 "name": "prod1",750 "state": "up",751 "type": "ethernet",752 "autoconnect": "yes",753 "mac": "52:54:00:44:9f:ba",754 "mtu": 1450,755 "ip": {"address": "192.168.174.5/24"},756 }757 ],758 )759 def test_up_single_v4_dns(self):760 self.maxDiff = None761 # set single IPv4 DNS server762 self.do_connections_validate(763 [764 {765 "actions": ["present", "up"],766 "autoconnect": True,767 "check_iface_exists": True,768 "ethernet": ETHERNET_DEFAULTS,769 "ethtool": ETHTOOL_DEFAULTS,770 "force_state_change": None,771 "ignore_errors": None,772 "interface_name": "prod1",773 "ip": {774 "dhcp4": False,775 "route_metric6": None,776 "route_metric4": None,777 "dns_options": [],778 "dns_search": [],779 "dhcp4_send_hostname": None,780 "gateway6": None,781 "gateway4": None,782 "auto6": True,783 "ipv6_disabled": False,784 "dns": [{"address": "192.168.174.1", "family": socket.AF_INET}],785 "address": [786 {787 "prefix": 24,788 "family": socket.AF_INET,789 "address": "192.168.174.5",790 }791 ],792 "auto_gateway": None,793 "route_append_only": False,794 "rule_append_only": False,795 "route": [],796 "routing_rule": [],797 },798 "mac": None,799 "match": {},800 "controller": None,801 "ieee802_1x": None,802 "wireless": None,803 "mtu": None,804 "name": "prod1",805 "parent": None,806 "persistent_state": "present",807 "port_type": None,808 "state": "up",809 "type": "ethernet",810 "wait": None,811 "zone": None,812 }813 ],814 [815 {816 "name": "prod1",817 "state": "up",818 "type": "ethernet",819 "autoconnect": "yes",820 "ip": {"address": "192.168.174.5/24", "dns": "192.168.174.1"},821 }822 ],823 )824 def test_ipv6_static(self):825 self.maxDiff = None826 self.do_connections_validate(827 [828 {829 "actions": ["present", "up"],830 "autoconnect": True,831 "check_iface_exists": True,832 "ethernet": ETHERNET_DEFAULTS,833 "ethtool": ETHTOOL_DEFAULTS,834 "force_state_change": None,835 "ignore_errors": None,836 "interface_name": "prod1",837 "match": {},838 "ip": {839 "gateway6": "2001:db8::1",840 "gateway4": None,841 "route_metric4": None,842 "auto6": False,843 "ipv6_disabled": False,844 "dhcp4": False,845 "address": [846 {847 "address": "2001:db8::2",848 "family": socket.AF_INET6,849 "prefix": 32,850 },851 {852 "address": "2001:db8::3",853 "family": socket.AF_INET6,854 "prefix": 32,855 },856 {857 "address": "2001:db8::4",858 "family": socket.AF_INET6,859 "prefix": 32,860 },861 ],862 "auto_gateway": None,863 "route_append_only": False,864 "rule_append_only": False,865 "route": [],866 "dns": [],867 "dns_options": [],868 "dns_search": [],869 "route_metric6": None,870 "routing_rule": [],871 "dhcp4_send_hostname": None,872 },873 "mac": None,874 "controller": None,875 "ieee802_1x": None,876 "wireless": None,877 "mtu": None,878 "name": "prod1",879 "parent": None,880 "persistent_state": "present",881 "port_type": None,882 "state": "up",883 "type": "ethernet",884 "wait": None,885 "zone": None,886 }887 ],888 [889 {890 "name": "prod1",891 "state": "up",892 "type": "ethernet",893 "ip": {894 "dhcp4": "no",895 "auto6": "no",896 "address": [897 "2001:db8::2/32",898 "2001:db8::3/32",899 "2001:db8::4/32",900 ],901 "gateway6": "2001:db8::1",902 },903 }904 ],905 initscripts_dict_expected=[906 {907 "ifcfg": {908 "BOOTPROTO": "none",909 "IPV6INIT": "yes",910 "IPV6_AUTOCONF": "no",911 "IPV6ADDR": "2001:db8::2/32",912 "IPV6ADDR_SECONDARIES": "2001:db8::3/32 2001:db8::4/32",913 "IPV6_DEFAULTGW": "2001:db8::1",914 "NM_CONTROLLED": "no",915 "ONBOOT": "yes",916 "TYPE": "Ethernet",917 "DEVICE": "prod1",918 },919 "keys": None,920 "route": None,921 "route6": None,922 "rule": None,923 "rule6": None,924 }925 ],926 )927 def test_routes(self):928 self.maxDiff = None929 self.do_connections_validate(930 [931 {932 "actions": ["present", "up"],933 "autoconnect": True,934 "check_iface_exists": True,935 "ethernet": ETHERNET_DEFAULTS,936 "ethtool": ETHTOOL_DEFAULTS,937 "force_state_change": None,938 "ignore_errors": None,939 "interface_name": None,940 "match": {},941 "ip": {942 "dhcp4": False,943 "auto6": True,944 "ipv6_disabled": False,945 "address": [946 {947 "prefix": 24,948 "family": socket.AF_INET,949 "address": "192.168.176.5",950 },951 {952 "prefix": 24,953 "family": socket.AF_INET,954 "address": "192.168.177.5",955 },956 ],957 "auto_gateway": None,958 "route_append_only": False,959 "rule_append_only": False,960 "route": [],961 "route_metric6": None,962 "route_metric4": None,963 "routing_rule": [],964 "dns_options": [],965 "dns_search": [],966 "dhcp4_send_hostname": None,967 "gateway6": None,968 "gateway4": None,969 "dns": [],970 },971 "mac": "52:54:00:44:9f:ba",972 "controller": None,973 "ieee802_1x": None,974 "wireless": None,975 "mtu": 1450,976 "name": "prod1",977 "parent": None,978 "persistent_state": "present",979 "port_type": None,980 "state": "up",981 "type": "ethernet",982 "wait": None,983 "zone": None,984 },985 {986 "actions": ["present", "up"],987 "autoconnect": True,988 "check_iface_exists": True,989 "ethernet": ETHERNET_DEFAULTS,990 "ethtool": ETHTOOL_DEFAULTS,991 "force_state_change": None,992 "ignore_errors": None,993 "interface_name": "prod.100",994 "match": {},995 "ip": {996 "dhcp4": False,997 "route_metric6": None,998 "route_metric4": None,999 "dns_options": [],1000 "dns_search": [],1001 "dhcp4_send_hostname": None,1002 "gateway6": None,1003 "gateway4": None,1004 "auto6": False,1005 "ipv6_disabled": False,1006 "dns": [],1007 "address": [1008 {1009 "prefix": 24,1010 "family": socket.AF_INET,1011 "address": "192.168.174.5",1012 },1013 {1014 "prefix": 65,1015 "family": socket.AF_INET6,1016 "address": "a:b:c::6",1017 },1018 ],1019 "auto_gateway": None,1020 "route_append_only": False,1021 "rule_append_only": False,1022 "route": [1023 {1024 "family": socket.AF_INET,1025 "network": "192.168.5.0",1026 "prefix": 24,1027 "gateway": None,1028 "metric": -1,1029 "table": None,1030 }1031 ],1032 "routing_rule": [],1033 },1034 "mac": None,1035 "controller": None,1036 "ieee802_1x": None,1037 "wireless": None,1038 "mtu": None,1039 "name": "prod.100",1040 "parent": "prod1",1041 "persistent_state": "present",1042 "port_type": None,1043 "state": "up",1044 "type": "vlan",1045 "vlan": {"id": 100},1046 "wait": None,1047 "zone": None,1048 },1049 ],1050 [1051 {1052 "name": "prod1",1053 "state": "up",1054 "type": "ethernet",1055 "autoconnect": "yes",1056 "mac": "52:54:00:44:9f:ba",1057 "mtu": 1450,1058 "ip": {"address": "192.168.176.5/24 192.168.177.5/24"},1059 },1060 {1061 "name": "prod.100",1062 "state": "up",1063 "type": "vlan",1064 "parent": "prod1",1065 "vlan": {"id": "100"},1066 "ip": {1067 "address": [1068 "192.168.174.5/24",1069 {"address": "a:b:c::6", "prefix": 65},1070 ],1071 "route_append_only": False,1072 "rule_append_only": False,1073 "route": [{"network": "192.168.5.0"}],1074 },1075 },1076 ],1077 )1078 def test_auto_gateway_true(self):1079 self.maxDiff = None1080 self.do_connections_validate(1081 [1082 {1083 "actions": ["present", "up"],1084 "autoconnect": True,1085 "check_iface_exists": True,1086 "ethernet": ETHERNET_DEFAULTS,1087 "ethtool": ETHTOOL_DEFAULTS,1088 "force_state_change": None,1089 "ignore_errors": None,1090 "interface_name": "prod1",1091 "ip": {1092 "dhcp4": True,1093 "route_metric6": None,1094 "route_metric4": None,1095 "dns_options": [],1096 "dns_search": [],1097 "dhcp4_send_hostname": None,1098 "gateway6": None,1099 "gateway4": None,1100 "auto6": True,1101 "ipv6_disabled": False,1102 "dns": [],1103 "address": [],1104 "auto_gateway": True,1105 "route_append_only": False,1106 "rule_append_only": False,1107 "route": [],1108 "routing_rule": [],1109 },1110 "mac": None,1111 "match": {},1112 "controller": None,1113 "ieee802_1x": None,1114 "wireless": None,1115 "mtu": None,1116 "name": "prod1",1117 "parent": None,1118 "persistent_state": "present",1119 "port_type": None,1120 "state": "up",1121 "type": "ethernet",1122 "wait": None,1123 "zone": None,1124 }1125 ],1126 [1127 {1128 "name": "prod1",1129 "state": "up",1130 "type": "ethernet",1131 "ip": {"auto_gateway": True},1132 }1133 ],1134 initscripts_dict_expected=[1135 {1136 "ifcfg": {1137 "BOOTPROTO": "dhcp",1138 "DEFROUTE": "yes",1139 "IPV6INIT": "yes",1140 "IPV6_AUTOCONF": "yes",1141 "NM_CONTROLLED": "no",1142 "ONBOOT": "yes",1143 "DEVICE": "prod1",1144 "TYPE": "Ethernet",1145 },1146 "keys": None,1147 "route": None,1148 "route6": None,1149 "rule": None,1150 "rule6": None,1151 }1152 ],1153 )1154 def test_auto_gateway_false(self):1155 self.maxDiff = None1156 self.do_connections_validate(1157 [1158 {1159 "actions": ["present", "up"],1160 "autoconnect": True,1161 "check_iface_exists": True,1162 "ethernet": ETHERNET_DEFAULTS,1163 "ethtool": ETHTOOL_DEFAULTS,1164 "force_state_change": None,1165 "ignore_errors": None,1166 "interface_name": "prod1",1167 "ip": {1168 "dhcp4": True,1169 "route_metric6": None,1170 "route_metric4": None,1171 "dns_options": [],1172 "dns_search": [],1173 "dhcp4_send_hostname": None,1174 "gateway6": None,1175 "gateway4": None,1176 "auto6": True,1177 "ipv6_disabled": False,1178 "dns": [],1179 "address": [],1180 "auto_gateway": False,1181 "route_append_only": False,1182 "rule_append_only": False,1183 "route": [],1184 "routing_rule": [],1185 },1186 "mac": None,1187 "match": {},1188 "controller": None,1189 "ieee802_1x": None,1190 "wireless": None,1191 "mtu": None,1192 "name": "prod1",1193 "parent": None,1194 "persistent_state": "present",1195 "port_type": None,1196 "state": "up",1197 "type": "ethernet",1198 "wait": None,1199 "zone": None,1200 }1201 ],1202 [1203 {1204 "name": "prod1",1205 "state": "up",1206 "type": "ethernet",1207 "ip": {"auto_gateway": False},1208 }1209 ],1210 initscripts_dict_expected=[1211 {1212 "ifcfg": {1213 "BOOTPROTO": "dhcp",1214 "DEFROUTE": "no",1215 "IPV6INIT": "yes",1216 "IPV6_AUTOCONF": "yes",1217 "NM_CONTROLLED": "no",1218 "ONBOOT": "yes",1219 "DEVICE": "prod1",1220 "TYPE": "Ethernet",1221 },1222 "keys": None,1223 "route": None,1224 "route6": None,1225 "rule": None,1226 "rule6": None,1227 }1228 ],1229 )1230 def test_auto_gateway_no_gateway(self):1231 self.maxDiff = None1232 self.do_connections_check_invalid(1233 [1234 {1235 "name": "eth0",1236 "state": "up",1237 "type": "ethernet",1238 "ip": {1239 "dhcp4": "no",1240 "auto6": "no",1241 "auto_gateway": "true",1242 "address": "192.168.176.5/24",1243 },1244 }1245 ]1246 )1247 def test_vlan(self):1248 self.maxDiff = None1249 self.do_connections_validate(1250 [1251 {1252 "actions": ["present", "up"],1253 "autoconnect": True,1254 "check_iface_exists": True,1255 "ethernet": ETHERNET_DEFAULTS,1256 "ethtool": ETHTOOL_DEFAULTS,1257 "force_state_change": None,1258 "ignore_errors": None,1259 "interface_name": None,1260 "match": {},1261 "ip": {1262 "dhcp4": False,1263 "auto6": True,1264 "address": [1265 {1266 "prefix": 24,1267 "family": socket.AF_INET,1268 "address": "192.168.176.5",1269 },1270 {1271 "prefix": 24,1272 "family": socket.AF_INET,1273 "address": "192.168.177.5",1274 },1275 ],1276 "auto_gateway": None,1277 "route_append_only": False,1278 "rule_append_only": False,1279 "route": [],1280 "route_metric6": None,1281 "route_metric4": None,1282 "routing_rule": [],1283 "dns_options": [],1284 "dns_search": [],1285 "dhcp4_send_hostname": None,1286 "gateway6": None,1287 "gateway4": None,1288 "ipv6_disabled": False,1289 "dns": [],1290 },1291 "mac": "52:54:00:44:9f:ba",1292 "controller": None,1293 "ieee802_1x": None,1294 "wireless": None,1295 "mtu": 1450,1296 "name": "prod1",1297 "parent": None,1298 "persistent_state": "present",1299 "port_type": None,1300 "state": "up",1301 "type": "ethernet",1302 "wait": None,1303 "zone": None,1304 },1305 {1306 "actions": ["present", "up"],1307 "autoconnect": True,1308 "check_iface_exists": True,1309 "ethernet": ETHERNET_DEFAULTS,1310 "ethtool": ETHTOOL_DEFAULTS,1311 "force_state_change": None,1312 "ignore_errors": None,1313 "interface_name": "prod.100",1314 "match": {},1315 "ip": {1316 "dhcp4": False,1317 "route_metric6": None,1318 "route_metric4": None,1319 "dns_options": [],1320 "dns_search": [],1321 "dhcp4_send_hostname": None,1322 "gateway6": None,1323 "gateway4": None,1324 "ipv6_disabled": False,1325 "auto6": False,1326 "dns": [],1327 "address": [1328 {1329 "prefix": 24,1330 "family": socket.AF_INET,1331 "address": "192.168.174.5",1332 },1333 {1334 "prefix": 65,1335 "family": socket.AF_INET6,1336 "address": "a:b:c::6",1337 },1338 ],1339 "auto_gateway": None,1340 "route_append_only": False,1341 "rule_append_only": False,1342 "route": [1343 {1344 "family": socket.AF_INET,1345 "network": "192.168.5.0",1346 "prefix": 24,1347 "gateway": None,1348 "metric": -1,1349 "table": None,1350 }1351 ],1352 "routing_rule": [],1353 },1354 "mac": None,1355 "controller": None,1356 "ieee802_1x": None,1357 "wireless": None,1358 "mtu": None,1359 "name": "prod.100",1360 "parent": "prod1",1361 "persistent_state": "present",1362 "port_type": None,1363 "state": "up",1364 "type": "vlan",1365 "vlan": {"id": 101},1366 "wait": None,1367 "zone": None,1368 },1369 ],1370 [1371 {1372 "name": "prod1",1373 "state": "up",1374 "type": "ethernet",1375 "autoconnect": "yes",1376 "mac": "52:54:00:44:9f:ba",1377 "mtu": 1450,1378 "ip": {"address": "192.168.176.5/24 192.168.177.5/24"},1379 },1380 {1381 "name": "prod.100",1382 "state": "up",1383 "type": "vlan",1384 "parent": "prod1",1385 "vlan_id": 101,1386 "ip": {1387 "address": [1388 "192.168.174.5/24",1389 {"address": "a:b:c::6", "prefix": 65},1390 ],1391 "route_append_only": False,1392 "rule_append_only": False,1393 "route": [{"network": "192.168.5.0"}],1394 },1395 },1396 ],1397 )1398 def test_macvlan(self):1399 self.maxDiff = None1400 self.do_connections_validate(1401 [1402 {1403 "actions": ["present", "up"],1404 "autoconnect": True,1405 "check_iface_exists": True,1406 "ethernet": ETHERNET_DEFAULTS,1407 "ethtool": ETHTOOL_DEFAULTS,1408 "force_state_change": None,1409 "ignore_errors": None,1410 "interface_name": "eth0",1411 "match": {},1412 "ip": {1413 "dhcp4": False,1414 "auto6": False,1415 "address": [1416 {1417 "prefix": 24,1418 "family": socket.AF_INET,1419 "address": "192.168.122.3",1420 }1421 ],1422 "auto_gateway": None,1423 "route_append_only": False,1424 "rule_append_only": False,1425 "route": [],1426 "route_metric6": None,1427 "route_metric4": None,1428 "routing_rule": [],1429 "dns_options": [],1430 "ipv6_disabled": False,1431 "dns_search": [],1432 "dhcp4_send_hostname": None,1433 "gateway6": None,1434 "gateway4": None,1435 "dns": [],1436 },1437 "mac": "33:24:10:24:2f:b9",1438 "controller": None,1439 "ieee802_1x": None,1440 "wireless": None,1441 "mtu": 1450,1442 "name": "eth0-parent",1443 "parent": None,1444 "persistent_state": "present",1445 "port_type": None,1446 "state": "up",1447 "type": "ethernet",1448 "wait": None,1449 "zone": None,1450 },1451 {1452 "actions": ["present", "up"],1453 "autoconnect": True,1454 "check_iface_exists": True,1455 "ethtool": ETHTOOL_DEFAULTS,1456 "force_state_change": None,1457 "ignore_errors": None,1458 "interface_name": "veth0",1459 "match": {},1460 "ip": {1461 "dhcp4": False,1462 "route_metric6": None,1463 "route_metric4": None,1464 "dns_options": [],1465 "ipv6_disabled": False,1466 "dns_search": [],1467 "dhcp4_send_hostname": None,1468 "gateway6": None,1469 "gateway4": None,1470 "auto6": False,1471 "dns": [],1472 "address": [1473 {1474 "prefix": 24,1475 "family": socket.AF_INET,1476 "address": "192.168.244.1",1477 }1478 ],1479 "auto_gateway": None,1480 "route_append_only": False,1481 "rule_append_only": False,1482 "route": [1483 {1484 "family": socket.AF_INET,1485 "network": "192.168.244.0",1486 "prefix": 24,1487 "gateway": None,1488 "metric": -1,1489 "table": None,1490 }1491 ],1492 "routing_rule": [],1493 },1494 "mac": None,1495 "macvlan": {"mode": "bridge", "promiscuous": True, "tap": False},1496 "controller": None,1497 "ieee802_1x": None,1498 "wireless": None,1499 "mtu": None,1500 "name": "veth0.0",1501 "parent": "eth0-parent",1502 "persistent_state": "present",1503 "port_type": None,1504 "state": "up",1505 "type": "macvlan",1506 "wait": None,1507 "zone": None,1508 },1509 {1510 "actions": ["present", "up"],1511 "autoconnect": True,1512 "check_iface_exists": True,1513 "ethtool": ETHTOOL_DEFAULTS,1514 "force_state_change": None,1515 "ignore_errors": None,1516 "interface_name": "veth1",1517 "match": {},1518 "ip": {1519 "dhcp4": False,1520 "route_metric6": None,1521 "route_metric4": None,1522 "dns_options": [],1523 "dns_search": [],1524 "dhcp4_send_hostname": None,1525 "gateway6": None,1526 "gateway4": None,1527 "ipv6_disabled": False,1528 "auto6": False,1529 "dns": [],1530 "address": [1531 {1532 "prefix": 24,1533 "family": socket.AF_INET,1534 "address": "192.168.245.7",1535 }1536 ],1537 "auto_gateway": None,1538 "route_append_only": False,1539 "rule_append_only": False,1540 "route": [1541 {1542 "family": socket.AF_INET,1543 "network": "192.168.245.0",1544 "prefix": 24,1545 "gateway": None,1546 "metric": -1,1547 "table": None,1548 }1549 ],1550 "routing_rule": [],1551 },1552 "mac": None,1553 "macvlan": {"mode": "passthru", "promiscuous": False, "tap": True},1554 "controller": None,1555 "ieee802_1x": None,1556 "wireless": None,1557 "mtu": None,1558 "name": "veth0.1",1559 "parent": "eth0-parent",1560 "persistent_state": "present",1561 "port_type": None,1562 "state": "up",1563 "type": "macvlan",1564 "wait": None,1565 "zone": None,1566 },1567 ],1568 [1569 {1570 "name": "eth0-parent",1571 "state": "up",1572 "type": "ethernet",1573 "autoconnect": "yes",1574 "interface_name": "eth0",1575 "mac": "33:24:10:24:2f:b9",1576 "mtu": 1450,1577 "ip": {"address": "192.168.122.3/24", "auto6": False},1578 },1579 {1580 "name": "veth0.0",1581 "state": "up",1582 "type": "macvlan",1583 "parent": "eth0-parent",1584 "interface_name": "veth0",1585 "macvlan": {"mode": "bridge", "promiscuous": True, "tap": False},1586 "ip": {1587 "address": "192.168.244.1/24",1588 "auto6": False,1589 "route_append_only": False,1590 "rule_append_only": False,1591 "route": [{"network": "192.168.244.0"}],1592 },1593 },1594 {1595 "name": "veth0.1",1596 "state": "up",1597 "type": "macvlan",1598 "parent": "eth0-parent",1599 "interface_name": "veth1",1600 "macvlan": {"mode": "passthru", "promiscuous": False, "tap": True},1601 "ip": {1602 "address": "192.168.245.7/24",1603 "auto6": False,1604 "route_append_only": False,1605 "rule_append_only": False,1606 "route": [{"network": "192.168.245.0"}],1607 },1608 },1609 ],1610 )1611 def test_bridge_no_dhcp4_auto6(self):1612 self.maxDiff = None1613 self.do_connections_validate(1614 [1615 {1616 "actions": ["present", "up"],1617 "autoconnect": True,1618 "check_iface_exists": True,1619 "ethernet": ETHERNET_DEFAULTS,1620 "ethtool": ETHTOOL_DEFAULTS,1621 "force_state_change": None,1622 "ignore_errors": None,1623 "interface_name": "bridge2",1624 "ip": {1625 "address": [],1626 "auto_gateway": None,1627 "auto6": False,1628 "dhcp4": False,1629 "dhcp4_send_hostname": None,1630 "dns": [],1631 "dns_options": [],1632 "dns_search": [],1633 "gateway4": None,1634 "gateway6": None,1635 "ipv6_disabled": False,1636 "route": [],1637 "route_append_only": False,1638 "route_metric4": None,1639 "route_metric6": None,1640 "routing_rule": [],1641 "rule_append_only": False,1642 },1643 "mac": None,1644 "match": {},1645 "controller": None,1646 "ieee802_1x": None,1647 "wireless": None,1648 "mtu": None,1649 "name": "prod2",1650 "parent": None,1651 "persistent_state": "present",1652 "port_type": None,1653 "state": "up",1654 "type": "bridge",1655 "wait": None,1656 "zone": None,1657 },1658 {1659 "actions": ["present", "up"],1660 "autoconnect": True,1661 "check_iface_exists": True,1662 "ethernet": ETHERNET_DEFAULTS,1663 "ethtool": ETHTOOL_DEFAULTS,1664 "force_state_change": None,1665 "ignore_errors": None,1666 "interface_name": "eth1",1667 "ip": {1668 "address": [],1669 "auto_gateway": None,1670 "auto6": True,1671 "dhcp4": True,1672 "dhcp4_send_hostname": None,1673 "dns": [],1674 "dns_options": [],1675 "dns_search": [],1676 "gateway4": None,1677 "gateway6": None,1678 "ipv6_disabled": False,1679 "route": [],1680 "route_append_only": False,1681 "route_metric4": None,1682 "route_metric6": None,1683 "routing_rule": [],1684 "rule_append_only": False,1685 },1686 "mac": None,1687 "match": {},1688 "controller": "prod2",1689 "ieee802_1x": None,1690 "wireless": None,1691 "mtu": None,1692 "name": "prod2-port1",1693 "parent": None,1694 "persistent_state": "present",1695 "port_type": "bridge",1696 "state": "up",1697 "type": "ethernet",1698 "wait": None,1699 "zone": None,1700 },1701 ],1702 [1703 {1704 "name": "prod2",1705 "state": "up",1706 "type": "bridge",1707 "interface_name": "bridge2",1708 "ip": {"dhcp4": False, "auto6": False},1709 },1710 {1711 "name": "prod2-port1",1712 "state": "up",1713 "type": "ethernet",1714 "interface_name": "eth1",1715 "controller": "prod2",1716 },1717 ],1718 )1719 def test_bond(self):1720 self.maxDiff = None1721 self.do_connections_validate(1722 [1723 {1724 "actions": ["present", "up"],1725 "autoconnect": True,1726 "bond": {1727 "mode": "balance-rr",1728 "ad_actor_sys_prio": None,1729 "ad_actor_system": None,1730 "ad_select": None,1731 "ad_user_port_key": None,1732 "all_ports_active": None,1733 "arp_all_targets": None,1734 "arp_interval": None,1735 "arp_ip_target": None,1736 "arp_validate": None,1737 "downdelay": None,1738 "fail_over_mac": None,1739 "lacp_rate": None,1740 "lp_interval": None,1741 "miimon": None,1742 "min_links": None,1743 "num_grat_arp": None,1744 "packets_per_port": None,1745 "peer_notif_delay": None,1746 "primary": None,1747 "primary_reselect": None,1748 "resend_igmp": None,1749 "tlb_dynamic_lb": None,1750 "updelay": None,1751 "use_carrier": None,1752 "xmit_hash_policy": None,1753 },1754 "check_iface_exists": True,1755 "ethernet": ETHERNET_DEFAULTS,1756 "ethtool": ETHTOOL_DEFAULTS,1757 "force_state_change": None,1758 "ignore_errors": None,1759 "interface_name": "bond1",1760 "ip": {1761 "dhcp4": True,1762 "route_metric6": None,1763 "route_metric4": None,1764 "dns_options": [],1765 "dns_search": [],1766 "dhcp4_send_hostname": None,1767 "gateway6": None,1768 "gateway4": None,1769 "auto6": True,1770 "ipv6_disabled": False,1771 "dns": [],1772 "address": [],1773 "auto_gateway": None,1774 "route_append_only": False,1775 "rule_append_only": False,1776 "route": [],1777 "routing_rule": [],1778 },1779 "mac": None,1780 "match": {},1781 "controller": None,1782 "ieee802_1x": None,1783 "wireless": None,1784 "mtu": None,1785 "name": "bond1",1786 "parent": None,1787 "persistent_state": "present",1788 "port_type": None,1789 "state": "up",1790 "type": "bond",1791 "wait": None,1792 "zone": None,1793 }1794 ],1795 [{"name": "bond1", "state": "up", "type": "bond"}],1796 )1797 def test_bond_active_backup(self):1798 self.maxDiff = None1799 self.do_connections_validate(1800 [1801 {1802 "actions": ["present", "up"],1803 "autoconnect": True,1804 "bond": {1805 "mode": "active-backup",1806 "ad_actor_sys_prio": None,1807 "ad_actor_system": None,1808 "ad_select": None,1809 "ad_user_port_key": None,1810 "all_ports_active": None,1811 "arp_all_targets": None,1812 "arp_interval": None,1813 "arp_ip_target": None,1814 "arp_validate": None,1815 "downdelay": None,1816 "fail_over_mac": None,1817 "lacp_rate": None,1818 "lp_interval": None,1819 "miimon": None,1820 "min_links": None,1821 "num_grat_arp": None,1822 "packets_per_port": None,1823 "peer_notif_delay": None,1824 "primary": None,1825 "primary_reselect": None,1826 "resend_igmp": None,1827 "tlb_dynamic_lb": None,1828 "updelay": None,1829 "use_carrier": None,1830 "xmit_hash_policy": None,1831 },1832 "check_iface_exists": True,1833 "ethernet": ETHERNET_DEFAULTS,1834 "ethtool": ETHTOOL_DEFAULTS,1835 "force_state_change": None,1836 "ignore_errors": None,1837 "interface_name": "bond1",1838 "ip": {1839 "dhcp4": True,1840 "route_metric6": None,1841 "route_metric4": None,1842 "dns_options": [],1843 "dns_search": [],1844 "dhcp4_send_hostname": None,1845 "gateway6": None,1846 "gateway4": None,1847 "auto6": True,1848 "ipv6_disabled": False,1849 "dns": [],1850 "address": [],1851 "auto_gateway": None,1852 "route_append_only": False,1853 "rule_append_only": False,1854 "route": [],1855 "routing_rule": [],1856 },1857 "mac": None,1858 "match": {},1859 "controller": None,1860 "ieee802_1x": None,1861 "wireless": None,1862 "mtu": None,1863 "name": "bond1",1864 "parent": None,1865 "persistent_state": "present",1866 "port_type": None,1867 "state": "up",1868 "type": "bond",1869 "wait": None,1870 "zone": None,1871 }1872 ],1873 [1874 {1875 "name": "bond1",1876 "state": "up",1877 "type": "bond",1878 "bond": {"mode": "active-backup"},1879 }1880 ],1881 )1882 def test_invalid_values(self):1883 self.maxDiff = None1884 self.do_connections_check_invalid([{}])1885 self.do_connections_check_invalid([{"name": "b", "xxx": 5}])1886 def test_ethernet_mac_address(self):1887 self.maxDiff = None1888 self.do_connections_validate(1889 [1890 {1891 "actions": ["present"],1892 "autoconnect": True,1893 "check_iface_exists": True,1894 "ethernet": ETHERNET_DEFAULTS,1895 "ethtool": ETHTOOL_DEFAULTS,1896 "ignore_errors": None,1897 "interface_name": None,1898 "ip": {1899 "address": [],1900 "auto_gateway": None,1901 "route_append_only": False,1902 "rule_append_only": False,1903 "route": [],1904 "routing_rule": [],1905 "auto6": True,1906 "ipv6_disabled": False,1907 "dhcp4": True,1908 "dhcp4_send_hostname": None,1909 "gateway4": None,1910 "gateway6": None,1911 "route_metric4": None,1912 "route_metric6": None,1913 "dns": [],1914 "dns_options": [],1915 "dns_search": [],1916 },1917 "mac": "aa:bb:cc:dd:ee:ff",1918 "match": {},1919 "controller": None,1920 "ieee802_1x": None,1921 "wireless": None,1922 "mtu": None,1923 "name": "5",1924 "parent": None,1925 "persistent_state": "present",1926 "port_type": None,1927 "state": None,1928 "type": "ethernet",1929 "zone": None,1930 }1931 ],1932 [{"name": "5", "type": "ethernet", "mac": "AA:bb:cC:DD:ee:FF"}],1933 )1934 def test_ethernet_speed_settings(self):1935 self.maxDiff = None1936 self.do_connections_validate(1937 [1938 {1939 "actions": ["present", "up"],1940 "autoconnect": True,1941 "check_iface_exists": True,1942 "ethernet": {"autoneg": False, "duplex": "half", "speed": 400},1943 "ethtool": ETHTOOL_DEFAULTS,1944 "force_state_change": None,1945 "ignore_errors": None,1946 "interface_name": "5",1947 "ip": {1948 "gateway6": None,1949 "gateway4": None,1950 "route_metric4": None,1951 "auto6": True,1952 "ipv6_disabled": False,1953 "dhcp4": True,1954 "address": [],1955 "auto_gateway": None,1956 "route_append_only": False,1957 "rule_append_only": False,1958 "route": [],1959 "dns": [],1960 "dns_options": [],1961 "dns_search": [],1962 "route_metric6": None,1963 "routing_rule": [],1964 "dhcp4_send_hostname": None,1965 },1966 "mac": None,1967 "match": {},1968 "controller": None,1969 "ieee802_1x": None,1970 "wireless": None,1971 "mtu": None,1972 "name": "5",1973 "parent": None,1974 "persistent_state": "present",1975 "port_type": None,1976 "state": "up",1977 "type": "ethernet",1978 "wait": None,1979 "zone": None,1980 }1981 ],1982 [1983 {1984 "name": "5",1985 "state": "up",1986 "type": "ethernet",1987 "ip": {},1988 "ethernet": {"duplex": "half", "speed": 400},1989 }1990 ],1991 initscripts_dict_expected=[1992 {1993 "ifcfg": {1994 "BOOTPROTO": "dhcp",1995 "ETHTOOL_OPTS": "autoneg off speed 400 duplex half",1996 "IPV6INIT": "yes",1997 "IPV6_AUTOCONF": "yes",1998 "NM_CONTROLLED": "no",1999 "ONBOOT": "yes",2000 "TYPE": "Ethernet",2001 "DEVICE": "5",2002 },2003 "keys": None,2004 "route": None,2005 "route6": None,2006 "rule": None,2007 "rule6": None,2008 }2009 ],2010 )2011 def test_bridge2(self):2012 self.maxDiff = None2013 self.do_connections_validate(2014 [2015 {2016 "actions": ["present", "up"],2017 "autoconnect": True,2018 "check_iface_exists": True,2019 "ethernet": ETHERNET_DEFAULTS,2020 "ethtool": ETHTOOL_DEFAULTS,2021 "force_state_change": None,2022 "ignore_errors": None,2023 "interface_name": "6643-controller",2024 "ip": {2025 "address": [],2026 "auto_gateway": None,2027 "auto6": True,2028 "ipv6_disabled": False,2029 "dhcp4": True,2030 "dhcp4_send_hostname": None,2031 "dns": [],2032 "dns_options": [],2033 "dns_search": [],2034 "gateway4": None,2035 "gateway6": None,2036 "route": [],2037 "route_append_only": False,2038 "route_metric4": None,2039 "route_metric6": None,2040 "routing_rule": [],2041 "rule_append_only": False,2042 },2043 "mac": None,2044 "match": {},2045 "controller": None,2046 "ieee802_1x": None,2047 "wireless": None,2048 "mtu": None,2049 "name": "6643-controller",2050 "parent": None,2051 "persistent_state": "present",2052 "port_type": None,2053 "state": "up",2054 "type": "bridge",2055 "wait": None,2056 "zone": None,2057 },2058 {2059 "actions": ["present", "up"],2060 "autoconnect": True,2061 "check_iface_exists": True,2062 "ethernet": ETHERNET_DEFAULTS,2063 "ethtool": ETHTOOL_DEFAULTS,2064 "force_state_change": None,2065 "ignore_errors": None,2066 "interface_name": "6643",2067 "ip": {2068 "address": [],2069 "auto_gateway": None,2070 "auto6": True,2071 "dhcp4_send_hostname": None,2072 "dhcp4": True,2073 "dns": [],2074 "dns_options": [],2075 "dns_search": [],2076 "gateway4": None,2077 "gateway6": None,2078 "ipv6_disabled": False,2079 "route": [],2080 "route_append_only": False,2081 "route_metric4": None,2082 "route_metric6": None,2083 "routing_rule": [],2084 "rule_append_only": False,2085 },2086 "mac": None,2087 "match": {},2088 "controller": "6643-controller",2089 "ieee802_1x": None,2090 "wireless": None,2091 "mtu": None,2092 "name": "6643",2093 "parent": None,2094 "persistent_state": "present",2095 "port_type": "bridge",2096 "state": "up",2097 "type": "ethernet",2098 "wait": None,2099 "zone": None,2100 },2101 ],2102 [2103 {"name": "6643-controller", "state": "up", "type": "bridge"},2104 {2105 "name": "6643",2106 "state": "up",2107 "type": "ethernet",2108 "controller": "6643-controller",2109 },2110 ],2111 )2112 def test_infiniband(self):2113 self.maxDiff = None2114 self.do_connections_validate(2115 [2116 {2117 "actions": ["present", "up"],2118 "autoconnect": True,2119 "check_iface_exists": True,2120 "ethtool": ETHTOOL_DEFAULTS,2121 "force_state_change": None,2122 "ignore_errors": None,2123 "infiniband": {"p_key": None, "transport_mode": "datagram"},2124 "interface_name": None,2125 "ip": {2126 "address": [],2127 "auto_gateway": None,2128 "auto6": True,2129 "dhcp4": True,2130 "dhcp4_send_hostname": None,2131 "dns": [],2132 "dns_options": [],2133 "dns_search": [],2134 "gateway4": None,2135 "gateway6": None,2136 "ipv6_disabled": False,2137 "route": [],2138 "route_append_only": False,2139 "route_metric4": None,2140 "route_metric6": None,2141 "routing_rule": [],2142 "rule_append_only": False,2143 },2144 "mac": None,2145 "match": {},2146 "controller": None,2147 "ieee802_1x": None,2148 "wireless": None,2149 "mtu": None,2150 "name": "infiniband.1",2151 "parent": None,2152 "persistent_state": "present",2153 "port_type": None,2154 "state": "up",2155 "type": "infiniband",2156 "wait": None,2157 "zone": None,2158 }2159 ],2160 [2161 {2162 "name": "infiniband.1",2163 "interface_name": "",2164 "state": "up",2165 "type": "infiniband",2166 }2167 ],2168 initscripts_dict_expected=[2169 {2170 "ifcfg": {2171 "BOOTPROTO": "dhcp",2172 "CONNECTED_MODE": "no",2173 "IPV6INIT": "yes",2174 "IPV6_AUTOCONF": "yes",2175 "NM_CONTROLLED": "no",2176 "ONBOOT": "yes",2177 "TYPE": "InfiniBand",2178 },2179 "keys": None,2180 "route": None,2181 "route6": None,2182 "rule": None,2183 "rule6": None,2184 }2185 ],2186 )2187 def test_infiniband2(self):2188 self.maxDiff = None2189 self.do_connections_validate(2190 [2191 {2192 "actions": ["present", "up"],2193 "autoconnect": True,2194 "check_iface_exists": True,2195 "ethtool": ETHTOOL_DEFAULTS,2196 "force_state_change": None,2197 "ignore_errors": None,2198 "infiniband": {"p_key": 5, "transport_mode": "datagram"},2199 "interface_name": None,2200 "ip": {2201 "address": [],2202 "auto_gateway": None,2203 "auto6": True,2204 "dhcp4": True,2205 "dhcp4_send_hostname": None,2206 "dns": [],2207 "dns_options": [],2208 "dns_search": [],2209 "gateway4": None,2210 "gateway6": None,2211 "ipv6_disabled": False,2212 "route": [],2213 "route_append_only": False,2214 "route_metric4": None,2215 "route_metric6": None,2216 "routing_rule": [],2217 "rule_append_only": False,2218 },2219 "mac": "11:22:33:44:55:66:77:88:99:00:"2220 "11:22:33:44:55:66:77:88:99:00",2221 "match": {},2222 "controller": None,2223 "ieee802_1x": None,2224 "wireless": None,2225 "mtu": None,2226 "name": "infiniband.2",2227 "parent": None,2228 "persistent_state": "present",2229 "port_type": None,2230 "state": "up",2231 "type": "infiniband",2232 "wait": None,2233 "zone": None,2234 }2235 ],2236 [2237 {2238 "name": "infiniband.2",2239 "state": "up",2240 "type": "infiniband",2241 "mac": "11:22:33:44:55:66:77:88:99:00:"2242 "11:22:33:44:55:66:77:88:99:00",2243 "infiniband_p_key": 5,2244 }2245 ],2246 initscripts_dict_expected=[2247 {2248 "ifcfg": {2249 "BOOTPROTO": "dhcp",2250 "CONNECTED_MODE": "no",2251 "HWADDR": "11:22:33:44:55:66:77:88:99:00:"2252 "11:22:33:44:55:66:77:88:99:00",2253 "IPV6INIT": "yes",2254 "IPV6_AUTOCONF": "yes",2255 "NM_CONTROLLED": "no",2256 "ONBOOT": "yes",2257 "PKEY": "yes",2258 "PKEY_ID": "5",2259 "TYPE": "InfiniBand",2260 },2261 "keys": None,2262 "route": None,2263 "route6": None,2264 "rule": None,2265 "rule6": None,2266 }2267 ],2268 )2269 def test_infiniband3(self):2270 self.maxDiff = None2271 self.do_connections_validate(2272 [2273 {2274 "actions": ["present"],2275 "autoconnect": True,2276 "check_iface_exists": True,2277 "ethtool": ETHTOOL_DEFAULTS,2278 "ignore_errors": None,2279 "infiniband": {"p_key": None, "transport_mode": "datagram"},2280 "interface_name": "ib0",2281 "ip": {2282 "address": [],2283 "auto_gateway": None,2284 "auto6": True,2285 "dhcp4": True,2286 "dhcp4_send_hostname": None,2287 "dns": [],2288 "dns_options": [],2289 "dns_search": [],2290 "gateway4": None,2291 "gateway6": None,2292 "ipv6_disabled": False,2293 "route": [],2294 "route_append_only": False,2295 "route_metric4": None,2296 "route_metric6": None,2297 "routing_rule": [],2298 "rule_append_only": False,2299 },2300 "mac": None,2301 "match": {},2302 "controller": None,2303 "ieee802_1x": None,2304 "wireless": None,2305 "mtu": None,2306 "name": "infiniband.3",2307 "parent": None,2308 "persistent_state": "present",2309 "port_type": None,2310 "state": None,2311 "type": "infiniband",2312 "zone": None,2313 },2314 {2315 "actions": ["present", "up"],2316 "autoconnect": True,2317 "check_iface_exists": True,2318 "ethtool": ETHTOOL_DEFAULTS,2319 "force_state_change": None,2320 "ignore_errors": None,2321 "infiniband": {"p_key": 10, "transport_mode": "datagram"},2322 "interface_name": None,2323 "ip": {2324 "address": [],2325 "auto_gateway": None,2326 "auto6": True,2327 "dhcp4": True,2328 "dhcp4_send_hostname": None,2329 "dns": [],2330 "dns_options": [],2331 "dns_search": [],2332 "gateway4": None,2333 "gateway6": None,2334 "ipv6_disabled": False,2335 "route": [],2336 "route_append_only": False,2337 "route_metric4": None,2338 "route_metric6": None,2339 "routing_rule": [],2340 "rule_append_only": False,2341 },2342 "mac": "11:22:33:44:55:66:77:88:99:00:"2343 "11:22:33:44:55:66:77:88:99:00",2344 "match": {},2345 "controller": None,2346 "ieee802_1x": None,2347 "wireless": None,2348 "mtu": None,2349 "name": "infiniband.3-10",2350 "parent": "infiniband.3",2351 "persistent_state": "present",2352 "port_type": None,2353 "state": "up",2354 "type": "infiniband",2355 "wait": None,2356 "zone": None,2357 },2358 ],2359 [2360 {2361 "name": "infiniband.3",2362 "interface_name": "ib0",2363 "type": "infiniband",2364 },2365 {2366 "name": "infiniband.3-10",2367 "state": "up",2368 "type": "infiniband",2369 "parent": "infiniband.3",2370 "mac": "11:22:33:44:55:66:77:88:99:00:"2371 "11:22:33:44:55:66:77:88:99:00",2372 "infiniband_p_key": 10,2373 },2374 ],2375 initscripts_dict_expected=[2376 {2377 "ifcfg": {2378 "BOOTPROTO": "dhcp",2379 "CONNECTED_MODE": "no",2380 "DEVICE": "ib0",2381 "IPV6INIT": "yes",2382 "IPV6_AUTOCONF": "yes",2383 "NM_CONTROLLED": "no",2384 "ONBOOT": "yes",2385 "TYPE": "InfiniBand",2386 },2387 "keys": None,2388 "route": None,2389 "route6": None,2390 "rule": None,2391 "rule6": None,2392 },2393 {2394 "ifcfg": {2395 "BOOTPROTO": "dhcp",2396 "CONNECTED_MODE": "no",2397 "HWADDR": "11:22:33:44:55:66:77:88:99:00:"2398 "11:22:33:44:55:66:77:88:99:00",2399 "IPV6INIT": "yes",2400 "IPV6_AUTOCONF": "yes",2401 "NM_CONTROLLED": "no",2402 "ONBOOT": "yes",2403 "PHYSDEV": "ib0",2404 "PKEY": "yes",2405 "PKEY_ID": "10",2406 "TYPE": "InfiniBand",2407 },2408 "keys": None,2409 "route": None,2410 "route6": None,2411 "rule": None,2412 "rule6": None,2413 },2414 ],2415 )2416 def test_route_metric_prefix(self):2417 self.maxDiff = None2418 self.do_connections_validate(2419 [2420 {2421 "actions": ["present", "up"],2422 "autoconnect": True,2423 "check_iface_exists": True,2424 "ethernet": ETHERNET_DEFAULTS,2425 "ethtool": ETHTOOL_DEFAULTS,2426 "force_state_change": None,2427 "ignore_errors": None,2428 "interface_name": "555",2429 "ip": {2430 "gateway6": None,2431 "gateway4": None,2432 "route_metric4": None,2433 "auto6": True,2434 "ipv6_disabled": False,2435 "dhcp4": True,2436 "address": [],2437 "auto_gateway": None,2438 "route_append_only": False,2439 "rule_append_only": False,2440 "route": [2441 {2442 "family": socket.AF_INET,2443 "network": "192.168.45.0",2444 "prefix": 24,2445 "gateway": None,2446 "metric": 545,2447 "table": None,2448 },2449 {2450 "family": socket.AF_INET,2451 "network": "192.168.46.0",2452 "prefix": 30,2453 "gateway": None,2454 "metric": -1,2455 "table": None,2456 },2457 ],2458 "routing_rule": [],2459 "dns": [],2460 "dns_options": [],2461 "dns_search": ["aa", "bb"],2462 "route_metric6": None,2463 "dhcp4_send_hostname": None,2464 },2465 "mac": None,2466 "match": {},2467 "controller": None,2468 "ieee802_1x": None,2469 "wireless": None,2470 "mtu": None,2471 "name": "555",2472 "parent": None,2473 "persistent_state": "present",2474 "port_type": None,2475 "state": "up",2476 "type": "ethernet",2477 "wait": None,2478 "zone": None,2479 }2480 ],2481 [2482 {2483 "name": "555",2484 "state": "up",2485 "type": "ethernet",2486 "ip": {2487 "dns_search": ["aa", "bb"],2488 "route": [2489 {"network": "192.168.45.0", "metric": 545},2490 {"network": "192.168.46.0", "prefix": 30},2491 ],2492 },2493 }2494 ],2495 initscripts_dict_expected=[2496 {2497 "ifcfg": {2498 "BOOTPROTO": "dhcp",2499 "DOMAIN": "aa bb",2500 "IPV6INIT": "yes",2501 "IPV6_AUTOCONF": "yes",2502 "NM_CONTROLLED": "no",2503 "ONBOOT": "yes",2504 "TYPE": "Ethernet",2505 "DEVICE": "555",2506 },2507 "keys": None,2508 "route": "192.168.45.0/24 metric 545\n192.168.46.0/30\n",2509 "route6": None,2510 "rule": None,2511 "rule6": None,2512 }2513 ],2514 )2515 def test_route_v6(self):2516 self.maxDiff = None2517 self.do_connections_validate(2518 [2519 {2520 "actions": ["present", "up"],2521 "autoconnect": True,2522 "check_iface_exists": True,2523 "ethernet": ETHERNET_DEFAULTS,2524 "ethtool": ETHTOOL_DEFAULTS,2525 "force_state_change": None,2526 "ignore_errors": None,2527 "interface_name": "e556",2528 "ip": {2529 "gateway6": None,2530 "gateway4": None,2531 "route_metric4": None,2532 "auto6": True,2533 "ipv6_disabled": False,2534 "dhcp4": True,2535 "address": [],2536 "auto_gateway": None,2537 "route_append_only": True,2538 "rule_append_only": False,2539 "route": [2540 {2541 "family": socket.AF_INET,2542 "network": "192.168.45.0",2543 "prefix": 24,2544 "gateway": None,2545 "metric": 545,2546 "table": None,2547 },2548 {2549 "family": socket.AF_INET,2550 "network": "192.168.46.0",2551 "prefix": 30,2552 "gateway": None,2553 "metric": -1,2554 "table": None,2555 },2556 {2557 "family": socket.AF_INET6,2558 "network": "a:b:c:d::",2559 "prefix": 64,2560 "gateway": None,2561 "metric": -1,2562 "table": None,2563 },2564 ],2565 "routing_rule": [],2566 "dns": [],2567 "dns_options": [],2568 "dns_search": ["aa", "bb"],2569 "route_metric6": None,2570 "dhcp4_send_hostname": None,2571 },2572 "mac": None,2573 "match": {},2574 "controller": None,2575 "ieee802_1x": None,2576 "wireless": None,2577 "mtu": None,2578 "name": "e556",2579 "parent": None,2580 "persistent_state": "present",2581 "port_type": None,2582 "state": "up",2583 "type": "ethernet",2584 "wait": None,2585 "zone": "external",2586 }2587 ],2588 [2589 {2590 "name": "e556",2591 "state": "up",2592 "type": "ethernet",2593 "zone": "external",2594 "ip": {2595 "dns_search": ["aa", "bb"],2596 "route_append_only": True,2597 "rule_append_only": False,2598 "route": [2599 {"network": "192.168.45.0", "metric": 545},2600 {"network": "192.168.46.0", "prefix": 30},2601 {"network": "a:b:c:d::"},2602 ],2603 },2604 }2605 ],2606 nm_route_list_current=[2607 [2608 {"network": "192.168.40.0", "prefix": 24, "metric": 545},2609 {"network": "192.168.46.0", "prefix": 30},2610 {"network": "a:b:c:f::"},2611 ]2612 ],2613 nm_route_list_expected=[2614 [2615 {"network": "192.168.40.0", "prefix": 24, "metric": 545},2616 {"network": "192.168.46.0", "prefix": 30},2617 {"network": "192.168.45.0", "prefix": 24, "metric": 545},2618 {"network": "a:b:c:f::"},2619 {"network": "a:b:c:d::"},2620 ]2621 ],2622 initscripts_content_current=[2623 {2624 "ifcfg": "",2625 "keys": None,2626 "route": "192.168.40.0/24 metric 545\n192.168.46.0/30",2627 "route6": "a:b:c:f::/64",2628 "rule": None,2629 "rule6": None,2630 }2631 ],2632 initscripts_dict_expected=[2633 {2634 "ifcfg": {2635 "BOOTPROTO": "dhcp",2636 "DOMAIN": "aa bb",2637 "IPV6INIT": "yes",2638 "IPV6_AUTOCONF": "yes",2639 "NM_CONTROLLED": "no",2640 "ONBOOT": "yes",2641 "TYPE": "Ethernet",2642 "ZONE": "external",2643 "DEVICE": "e556",2644 },2645 "keys": None,2646 "route": "192.168.40.0/24 metric 545\n192.168.46.0/30\n"2647 "192.168.45.0/24 metric 545\n",2648 "route6": "a:b:c:f::/64\na:b:c:d::/64\n",2649 "rule": None,2650 "rule6": None,2651 }2652 ],2653 )2654 def test_802_1x_1(self):2655 """2656 Test private key with password2657 """2658 self.maxDiff = None2659 self.do_connections_validate(2660 [2661 {2662 "actions": ["present", "up"],2663 "autoconnect": True,2664 "check_iface_exists": True,2665 "ethernet": ETHERNET_DEFAULTS,2666 "ethtool": ETHTOOL_DEFAULTS,2667 "force_state_change": None,2668 "ignore_errors": None,2669 "interface_name": "eth0",2670 "ip": {2671 "gateway6": None,2672 "gateway4": None,2673 "route_metric4": None,2674 "auto6": True,2675 "ipv6_disabled": False,2676 "dhcp4": True,2677 "address": [],2678 "auto_gateway": None,2679 "route_append_only": False,2680 "rule_append_only": False,2681 "route": [],2682 "dns": [],2683 "dns_options": [],2684 "dns_search": [],2685 "route_metric6": None,2686 "routing_rule": [],2687 "dhcp4_send_hostname": None,2688 },2689 "mac": None,2690 "match": {},2691 "controller": None,2692 "ieee802_1x": {2693 "identity": "myhost",2694 "eap": "tls",2695 "private_key": "/etc/pki/tls/client.key",2696 "private_key_password": "p@55w0rD",2697 "private_key_password_flags": None,2698 "client_cert": "/etc/pki/tls/client.pem",2699 "ca_cert": "/etc/pki/tls/cacert.pem",2700 "ca_path": None,2701 "system_ca_certs": False,2702 "domain_suffix_match": None,2703 },2704 "wireless": None,2705 "mtu": None,2706 "name": "eth0",2707 "parent": None,2708 "persistent_state": "present",2709 "port_type": None,2710 "state": "up",2711 "type": "ethernet",2712 "wait": None,2713 "zone": None,2714 }2715 ],2716 [2717 {2718 "name": "eth0",2719 "state": "up",2720 "type": "ethernet",2721 "ieee802_1x": {2722 "identity": "myhost",2723 "eap": "tls",2724 "private_key": "/etc/pki/tls/client.key",2725 "private_key_password": "p@55w0rD",2726 "client_cert": "/etc/pki/tls/client.pem",2727 "ca_cert": "/etc/pki/tls/cacert.pem",2728 },2729 }2730 ],2731 )2732 def test_802_1x_2(self):2733 """2734 Test 802.1x profile with unencrypted private key,2735 domain suffix match, and system ca certs2736 """2737 self.maxDiff = None2738 self.do_connections_validate(2739 [2740 {2741 "actions": ["present", "up"],2742 "autoconnect": True,2743 "check_iface_exists": True,2744 "ethernet": ETHERNET_DEFAULTS,2745 "ethtool": ETHTOOL_DEFAULTS,2746 "force_state_change": None,2747 "ignore_errors": None,2748 "interface_name": "eth0",2749 "ip": {2750 "gateway6": None,2751 "gateway4": None,2752 "route_metric4": None,2753 "auto6": True,2754 "ipv6_disabled": False,2755 "dhcp4": True,2756 "address": [],2757 "auto_gateway": None,2758 "route_append_only": False,2759 "rule_append_only": False,2760 "route": [],2761 "dns": [],2762 "dns_options": [],2763 "dns_search": [],2764 "route_metric6": None,2765 "routing_rule": [],2766 "dhcp4_send_hostname": None,2767 },2768 "mac": None,2769 "match": {},2770 "controller": None,2771 "ieee802_1x": {2772 "identity": "myhost",2773 "eap": "tls",2774 "private_key": "/etc/pki/tls/client.key",2775 "private_key_password": None,2776 "private_key_password_flags": ["not-required"],2777 "client_cert": "/etc/pki/tls/client.pem",2778 "ca_cert": None,2779 "ca_path": None,2780 "system_ca_certs": True,2781 "domain_suffix_match": "example.com",2782 },2783 "wireless": None,2784 "mtu": None,2785 "name": "eth0",2786 "parent": None,2787 "persistent_state": "present",2788 "port_type": None,2789 "state": "up",2790 "type": "ethernet",2791 "wait": None,2792 "zone": None,2793 }2794 ],2795 [2796 {2797 "name": "eth0",2798 "state": "up",2799 "type": "ethernet",2800 "ieee802_1x": {2801 "identity": "myhost",2802 "eap": "tls",2803 "private_key": "/etc/pki/tls/client.key",2804 "client_cert": "/etc/pki/tls/client.pem",2805 "private_key_password_flags": ["not-required"],2806 "system_ca_certs": True,2807 "domain_suffix_match": "example.com",2808 },2809 }2810 ],2811 )2812 def test_802_1x_3(self):2813 """2814 Test 802.1x profile with unencrypted private key and ca_path2815 """2816 self.maxDiff = None2817 self.do_connections_validate(2818 [2819 {2820 "actions": ["present", "up"],2821 "autoconnect": True,2822 "check_iface_exists": True,2823 "ethernet": ETHERNET_DEFAULTS,2824 "ethtool": ETHTOOL_DEFAULTS,2825 "force_state_change": None,2826 "ignore_errors": None,2827 "interface_name": "eth0",2828 "ip": {2829 "gateway6": None,2830 "gateway4": None,2831 "route_metric4": None,2832 "auto6": True,2833 "ipv6_disabled": False,2834 "dhcp4": True,2835 "address": [],2836 "auto_gateway": None,2837 "route_append_only": False,2838 "rule_append_only": False,2839 "route": [],2840 "dns": [],2841 "dns_options": [],2842 "dns_search": [],2843 "route_metric6": None,2844 "routing_rule": [],2845 "dhcp4_send_hostname": None,2846 },2847 "mac": None,2848 "match": {},2849 "controller": None,2850 "ieee802_1x": {2851 "identity": "myhost",2852 "eap": "tls",2853 "private_key": "/etc/pki/tls/client.key",2854 "private_key_password": None,2855 "private_key_password_flags": ["not-required"],2856 "client_cert": "/etc/pki/tls/client.pem",2857 "ca_cert": None,2858 "ca_path": "/etc/pki/tls/my_ca_certs",2859 "system_ca_certs": False,2860 "domain_suffix_match": None,2861 },2862 "wireless": None,2863 "mtu": None,2864 "name": "eth0",2865 "parent": None,2866 "persistent_state": "present",2867 "port_type": None,2868 "state": "up",2869 "type": "ethernet",2870 "wait": None,2871 "zone": None,2872 }2873 ],2874 [2875 {2876 "name": "eth0",2877 "state": "up",2878 "type": "ethernet",2879 "ieee802_1x": {2880 "identity": "myhost",2881 "eap": "tls",2882 "private_key": "/etc/pki/tls/client.key",2883 "client_cert": "/etc/pki/tls/client.pem",2884 "private_key_password_flags": ["not-required"],2885 "ca_path": "/etc/pki/tls/my_ca_certs",2886 },2887 }2888 ],2889 )2890 def test_wireless_psk(self):2891 """2892 Test wireless connection with wpa-psk auth2893 """2894 self.maxDiff = None2895 self.do_connections_validate(2896 [2897 {2898 "actions": ["present", "up"],2899 "autoconnect": True,2900 "check_iface_exists": True,2901 "ethtool": ETHTOOL_DEFAULTS,2902 "force_state_change": None,2903 "ignore_errors": None,2904 "interface_name": "wireless1",2905 "ip": {2906 "gateway6": None,2907 "gateway4": None,2908 "route_metric4": None,2909 "auto6": True,2910 "ipv6_disabled": False,2911 "dhcp4": True,2912 "address": [],2913 "auto_gateway": None,2914 "route_append_only": False,2915 "rule_append_only": False,2916 "route": [],2917 "dns": [],2918 "dns_options": [],2919 "dns_search": [],2920 "route_metric6": None,2921 "routing_rule": [],2922 "dhcp4_send_hostname": None,2923 },2924 "mac": None,2925 "match": {},2926 "controller": None,2927 "ieee802_1x": None,2928 "wireless": {2929 "ssid": "test wireless network",2930 "key_mgmt": "wpa-psk",2931 "password": "p@55w0rD",2932 },2933 "mtu": None,2934 "name": "wireless1",2935 "parent": None,2936 "persistent_state": "present",2937 "port_type": None,2938 "state": "up",2939 "type": "wireless",2940 "wait": None,2941 "zone": None,2942 }2943 ],2944 [2945 {2946 "name": "wireless1",2947 "state": "up",2948 "type": "wireless",2949 "wireless": {2950 "ssid": "test wireless network",2951 "key_mgmt": "wpa-psk",2952 "password": "p@55w0rD",2953 },2954 }2955 ],2956 )2957 def test_wireless_eap(self):2958 """2959 Test wireless connection with wpa-eap2960 """2961 self.maxDiff = None2962 self.do_connections_validate(2963 [2964 {2965 "actions": ["present", "up"],2966 "autoconnect": True,2967 "check_iface_exists": True,2968 "ethtool": ETHTOOL_DEFAULTS,2969 "force_state_change": None,2970 "ignore_errors": None,2971 "interface_name": "wireless1",2972 "ip": {2973 "gateway6": None,2974 "gateway4": None,2975 "route_metric4": None,2976 "auto6": True,2977 "ipv6_disabled": False,2978 "dhcp4": True,2979 "address": [],2980 "auto_gateway": None,2981 "route_append_only": False,2982 "rule_append_only": False,2983 "route": [],2984 "dns": [],2985 "dns_options": [],2986 "dns_search": [],2987 "route_metric6": None,2988 "routing_rule": [],2989 "dhcp4_send_hostname": None,2990 },2991 "mac": None,2992 "match": {},2993 "controller": None,2994 "ieee802_1x": {2995 "identity": "myhost",2996 "eap": "tls",2997 "private_key": "/etc/pki/tls/client.key",2998 "private_key_password": "p@55w0rD",2999 "private_key_password_flags": None,3000 "client_cert": "/etc/pki/tls/client.pem",3001 "ca_cert": "/etc/pki/tls/cacert.pem",3002 "ca_path": None,3003 "system_ca_certs": False,3004 "domain_suffix_match": None,3005 },3006 "wireless": {3007 "ssid": "test wireless network",3008 "password": None,3009 "key_mgmt": "wpa-eap",3010 },3011 "mtu": None,3012 "name": "wireless1",3013 "parent": None,3014 "persistent_state": "present",3015 "port_type": None,3016 "state": "up",3017 "type": "wireless",3018 "wait": None,3019 "zone": None,3020 }3021 ],3022 [3023 {3024 "name": "wireless1",3025 "state": "up",3026 "type": "wireless",3027 "wireless": {3028 "ssid": "test wireless network",3029 "key_mgmt": "wpa-eap",3030 },3031 "ieee802_1x": {3032 "identity": "myhost",3033 "eap": "tls",3034 "private_key": "/etc/pki/tls/client.key",3035 "private_key_password": "p@55w0rD",3036 "client_cert": "/etc/pki/tls/client.pem",3037 "ca_cert": "/etc/pki/tls/cacert.pem",3038 },3039 }3040 ],3041 )3042 def test_invalid_cert_path(self):3043 """3044 should fail if a relative path is used for 802.1x certs/keys3045 """3046 self.maxDiff = None3047 self.do_connections_check_invalid(3048 [3049 {3050 "name": "eth0",3051 "state": "up",3052 "type": "ethernet",3053 "ieee802_1x": {3054 "identity": "myhost",3055 "eap": "tls",3056 "private_key": "client.key",3057 "client_cert": "client.pem",3058 "private_key_password_flags": ["not-required"],3059 "system_ca_certs": True,3060 },3061 }3062 ]3063 )3064 def test_invalid_password_flag(self):3065 """3066 should fail if an invalid private key password flag is set3067 """3068 self.maxDiff = None3069 self.do_connections_check_invalid(3070 [3071 {3072 "name": "eth0",3073 "state": "up",3074 "type": "ethernet",3075 "ieee802_1x": {3076 "identity": "myhost",3077 "eap": "tls",3078 "private_key": "/etc/pki/tls/client.key",3079 "client_cert": "/etc/pki/tls/client.pem",3080 "private_key_password_flags": ["bad-flag"],3081 "system_ca_certs": True,3082 },3083 }3084 ]3085 )3086 def test_802_1x_ca_path_and_system_ca_certs(self):3087 """3088 should fail if ca_path and system_ca_certs are used together3089 """3090 self.maxDiff = None3091 self.do_connections_check_invalid(3092 [3093 {3094 "name": "eth0",3095 "state": "up",3096 "type": "ethernet",3097 "ieee802_1x": {3098 "identity": "myhost",3099 "eap": "tls",3100 "private_key": "/etc/pki/tls/client.key",3101 "client_cert": "/etc/pki/tls/client.pem",3102 "private_key_password_flags": ["not-required"],3103 "ca_path": "/etc/pki/my_ca_certs",3104 "system_ca_certs": True,3105 },3106 }3107 ]3108 )3109 def test_802_1x_initscripts(self):3110 """3111 should fail to create ieee802_1x connection with initscripts3112 """3113 input_connections = [3114 {3115 "name": "eth0",3116 "state": "up",3117 "type": "ethernet",3118 "ieee802_1x": {3119 "identity": "myhost",3120 "eap": "tls",3121 "private_key": "/etc/pki/tls/client.key",3122 "client_cert": "/etc/pki/tls/client.pem",3123 "private_key_password_flags": ["not-required"],3124 "system_ca_certs": True,3125 },3126 }3127 ]3128 connections = ARGS_CONNECTIONS.validate(input_connections)3129 self.assertRaises(3130 ValidationError,3131 ARGS_CONNECTIONS.validate_connection_one,3132 VALIDATE_ONE_MODE_INITSCRIPTS,3133 connections,3134 0,3135 )3136 def test_802_1x_unsupported_type(self):3137 """3138 should fail if a non ethernet/wireless connection has 802.1x settings defined3139 """3140 self.do_connections_check_invalid(3141 [3142 {3143 "name": "bond0",3144 "state": "up",3145 "type": "bond",3146 "ieee802_1x": {3147 "identity": "myhost",3148 "eap": "tls",3149 "private_key": "/etc/pki/tls/client.key",3150 "client_cert": "/etc/pki/tls/client.pem",3151 "private_key_password_flags": ["not-required"],3152 "system_ca_certs": True,3153 },3154 }3155 ]3156 )3157 def test_wireless_initscripts(self):3158 """3159 should fail to create wireless connection with initscripts3160 """3161 input_connections = [3162 {3163 "name": "wireless1",3164 "state": "up",3165 "type": "wireless",3166 "wireless": {3167 "ssid": "test wireless network",3168 "key_mgmt": "wpa-psk",3169 "password": "p@55w0rD",3170 },3171 }3172 ]3173 connections = ARGS_CONNECTIONS.validate(input_connections)3174 self.assertRaises(3175 ValidationError,3176 ARGS_CONNECTIONS.validate_connection_one,3177 VALIDATE_ONE_MODE_INITSCRIPTS,3178 connections,3179 0,3180 )3181 def test_wireless_unsupported_type(self):3182 """3183 should fail if a non wireless connection has wireless settings defined3184 """3185 self.do_connections_check_invalid(3186 [3187 {3188 "name": "wireless-bond",3189 "state": "up",3190 "type": "bond",3191 "wireless": {3192 "ssid": "test wireless network",3193 "key_mgmt": "wpa-psk",3194 "password": "p@55w0rD",3195 },3196 }3197 ]3198 )3199 def test_wireless_ssid_too_long(self):3200 """3201 should fail if ssid longer than 32 bytes3202 """3203 self.do_connections_check_invalid(3204 [3205 {3206 "name": "wireless1",3207 "state": "up",3208 "type": "wireless",3209 "wireless": {3210 "ssid": "test wireless network with ssid too long",3211 "key_mgmt": "wpa-psk",3212 "password": "p@55w0rD",3213 },3214 }3215 ]3216 )3217 def test_wireless_no_password(self):3218 """3219 should fail if wpa-psk is selected and no password provided3220 """3221 self.do_connections_check_invalid(3222 [3223 {3224 "name": "wireless1",3225 "state": "up",3226 "type": "wireless",3227 "wireless": {3228 "ssid": "test wireless network",3229 "key_mgmt": "wpa-psk",3230 },3231 }3232 ]3233 )3234 def test_wireless_password_too_long(self):3235 """3236 should fail if wpa-psk is selected and no password provided3237 """3238 self.do_connections_check_invalid(3239 [3240 {3241 "name": "wireless1",3242 "state": "up",3243 "type": "wireless",3244 "wireless": {3245 "ssid": "test wireless network",3246 "key_mgmt": "wpa-psk",3247 "password": "This password is too long and should "3248 "not be able to validate properly",3249 },3250 }3251 ]3252 )3253 def test_wireless_no_802_1x_for_wpa_eap(self):3254 """3255 should fail if no 802.1x parameters are defined for a wireless3256 connection with key_mgmt=wpa-eap3257 """3258 self.do_connections_check_invalid(3259 [3260 {3261 "name": "wireless1",3262 "state": "up",3263 "type": "wireless",3264 "wireless": {3265 "ssid": "test wireless network",3266 "key_mgmt": "wpa-eap",3267 },3268 }3269 ]3270 )3271 def test_wireless_no_options_defined(self):3272 """3273 should fail if a connection of type='wireless' does not3274 have any 'wireless' settings defined3275 """3276 self.do_connections_check_invalid(3277 [{"name": "wireless1", "state": "up", "type": "wireless"}]3278 )3279 def test_invalid_mac(self):3280 self.maxDiff = None3281 self.do_connections_check_invalid(3282 [{"name": "b", "type": "ethernet", "mac": "aa:b"}]3283 )3284 def test_interface_name_ethernet_default(self):3285 """Use the profile name as interface_name for ethernet profiles"""3286 cons_without_interface_name = [{"name": "eth0", "type": "ethernet"}]3287 connections = ARGS_CONNECTIONS.validate(cons_without_interface_name)3288 self.assertTrue(connections[0]["interface_name"] == "eth0")3289 def test_interface_name_ethernet_mac(self):3290 """Do not set interface_name when mac is specified"""3291 cons_without_interface_name = [3292 {"name": "eth0", "type": "ethernet", "mac": "3b:0b:88:16:6d:1a"}3293 ]3294 connections = ARGS_CONNECTIONS.validate(cons_without_interface_name)3295 self.assertTrue(connections[0]["interface_name"] is None)3296 def test_interface_name_ethernet_empty(self):3297 """Allow not to restrict the profile to an interface"""3298 network_connections = [3299 {"name": "internal_network", "type": "ethernet", "interface_name": ""}3300 ]3301 connections = ARGS_CONNECTIONS.validate(network_connections)3302 self.assertTrue(connections[0]["interface_name"] is None)3303 def test_interface_name_ethernet_None(self):3304 """Check that interface_name cannot be None"""3305 network_connections = [3306 {"name": "internal_network", "type": "ethernet", "interface_name": None}3307 ]3308 self.assertRaises(3309 ValidationError, ARGS_CONNECTIONS.validate, network_connections3310 )3311 def test_interface_name_ethernet_explicit(self):3312 """Use the explicitly provided interface name"""3313 network_connections = [3314 {"name": "internal", "type": "ethernet", "interface_name": "eth0"}3315 ]3316 connections = ARGS_CONNECTIONS.validate(network_connections)3317 self.assertEqual(connections[0]["interface_name"], "eth0")3318 def test_interface_name_ethernet_invalid_profile(self):3319 """Require explicit interface_name when the profile name is not a3320 valid interface_name"""3321 network_connections = [{"name": "internal:main", "type": "ethernet"}]3322 self.assertRaises(3323 ValidationError, ARGS_CONNECTIONS.validate, network_connections3324 )3325 network_connections = [3326 {"name": "internal:main", "type": "ethernet", "interface_name": "eth0"}3327 ]3328 connections = ARGS_CONNECTIONS.validate(network_connections)3329 self.assertTrue(connections[0]["interface_name"] == "eth0")3330 def test_interface_name_ethernet_invalid_interface_name(self):3331 network_connections = [3332 {"name": "internal", "type": "ethernet", "interface_name": "invalid:name"}3333 ]3334 self.assertRaises(3335 ValidationError, ARGS_CONNECTIONS.validate, network_connections3336 )3337 def test_interface_name_bond_empty_interface_name(self):3338 network_connections = [3339 {"name": "internal", "type": "bond", "interface_name": "invalid:name"}3340 ]3341 self.assertRaises(3342 ValidationError, ARGS_CONNECTIONS.validate, network_connections3343 )3344 def test_interface_name_bond_profile_as_interface_name(self):3345 network_connections = [{"name": "internal", "type": "bond"}]3346 connections = ARGS_CONNECTIONS.validate(network_connections)3347 self.assertEqual(connections[0]["interface_name"], "internal")3348 def check_connection(self, connection, expected):3349 reduced_connection = {}3350 for setting in expected:3351 reduced_connection[setting] = connection[setting]3352 self.assertEqual(reduced_connection, expected)3353 def check_partial_connection_zero(self, network_config, expected):3354 connections = ARGS_CONNECTIONS.validate([network_config])3355 self.check_connection(connections[0], expected)3356 def check_one_connection_with_defaults(3357 self, network_config, expected_changed_settings3358 ):3359 self.maxDiff = None3360 expected = self.default_connection_settings3361 expected.update(expected_changed_settings)3362 self.do_connections_validate([expected], [network_config])3363 def test_default_states(self):3364 self.check_partial_connection_zero(3365 {"name": "eth0"},3366 {"actions": ["present"], "persistent_state": "present", "state": None},3367 )3368 def test_invalid_persistent_state_up(self):3369 network_connections = [{"name": "internal", "persistent_state": "up"}]3370 self.assertRaises(3371 ValidationError, ARGS_CONNECTIONS.validate, network_connections3372 )3373 def test_invalid_persistent_state_down(self):3374 network_connections = [{"name": "internal", "persistent_state": "down"}]3375 self.assertRaises(3376 ValidationError, ARGS_CONNECTIONS.validate, network_connections3377 )3378 def test_invalid_state_test(self):3379 network_connections = [{"name": "internal", "state": "test"}]3380 self.assertRaises(3381 ValidationError, ARGS_CONNECTIONS.validate, network_connections3382 )3383 def test_default_states_type(self):3384 self.check_partial_connection_zero(3385 {"name": "eth0", "type": "ethernet"},3386 {"actions": ["present"], "persistent_state": "present", "state": None},3387 )3388 def test_persistent_state_present(self):3389 self.check_partial_connection_zero(3390 {"name": "eth0", "persistent_state": "present", "type": "ethernet"},3391 {"actions": ["present"], "persistent_state": "present", "state": None},3392 )3393 def test_state_present(self):3394 self.check_partial_connection_zero(3395 {"name": "eth0", "state": "present", "type": "ethernet"},3396 {"actions": ["present"], "persistent_state": "present", "state": None},3397 )3398 def test_state_absent(self):3399 self.check_partial_connection_zero(3400 {"name": "eth0", "state": "absent"},3401 {"actions": ["absent"], "persistent_state": "absent", "state": None},3402 )3403 def test_persistent_state_absent(self):3404 self.check_partial_connection_zero(3405 {"name": "eth0", "persistent_state": "absent"},3406 {"actions": ["absent"], "persistent_state": "absent", "state": None},3407 )3408 def test_state_present_up(self):3409 self.check_partial_connection_zero(3410 {3411 "name": "eth0",3412 "persistent_state": "present",3413 "state": "up",3414 "type": "ethernet",3415 },3416 {3417 "actions": ["present", "up"],3418 "persistent_state": "present",3419 "state": "up",3420 },3421 )3422 def test_state_present_down(self):3423 self.check_partial_connection_zero(3424 {3425 "name": "eth0",3426 "persistent_state": "present",3427 "state": "down",3428 "type": "ethernet",3429 },3430 {3431 "actions": ["present", "down"],3432 "persistent_state": "present",3433 "state": "down",3434 },3435 )3436 def test_state_absent_up_no_type(self):3437 self.check_partial_connection_zero(3438 {"name": "eth0", "persistent_state": "absent", "state": "up"},3439 {"actions": ["absent", "up"], "persistent_state": "absent", "state": "up"},3440 )3441 def test_state_absent_up_type(self):3442 # if type is specified, present should happen, too3443 self.check_partial_connection_zero(3444 {3445 "name": "eth0",3446 "persistent_state": "absent",3447 "state": "up",3448 "type": "ethernet",3449 },3450 {3451 "actions": ["present", "absent", "up"],3452 "persistent_state": "absent",3453 "state": "up",3454 },3455 )3456 def test_state_absent_down(self):3457 # if type is specified, present should happen, too3458 self.check_partial_connection_zero(3459 {"name": "eth0", "persistent_state": "absent", "state": "down"},3460 {3461 "actions": ["absent", "down"],3462 "persistent_state": "absent",3463 "state": "down",3464 },3465 )3466 def test_state_up_no_type(self):3467 self.check_partial_connection_zero(3468 {"name": "eth0", "state": "up"},3469 {3470 "actions": ["present", "up"],3471 "persistent_state": "present",3472 "state": "up",3473 },3474 )3475 def test_state_up_type(self):3476 self.check_partial_connection_zero(3477 {"name": "eth0", "state": "up", "type": "ethernet"},3478 {3479 "actions": ["present", "up"],3480 "persistent_state": "present",3481 "state": "up",3482 },3483 )3484 def test_state_down_no_type(self):3485 self.check_partial_connection_zero(3486 {"name": "eth0", "state": "down"},3487 {3488 "actions": ["present", "down"],3489 "persistent_state": "present",3490 "state": "down",3491 },3492 )3493 def test_full_state_present_no_type(self):3494 self.maxDiff = None3495 self.do_connections_validate(3496 [3497 {3498 "actions": ["present"],3499 "ignore_errors": None,3500 "name": "eth0",3501 "state": None,3502 "persistent_state": "present",3503 }3504 ],3505 [{"name": "eth0", "persistent_state": "present"}],3506 )3507 def test_full_state_present_type_defaults(self):3508 self.check_one_connection_with_defaults(3509 {"name": "eth0", "type": "ethernet", "persistent_state": "present"},3510 {3511 "actions": ["present"],3512 "interface_name": "eth0",3513 "name": "eth0",3514 "persistent_state": "present",3515 "state": None,3516 "type": "ethernet",3517 },3518 )3519 def test_full_state_absent_no_type(self):3520 self.maxDiff = None3521 self.do_connections_validate(3522 [3523 {3524 "actions": ["absent"],3525 "ignore_errors": None,3526 "name": "eth0",3527 "state": None,3528 "persistent_state": "absent",3529 }3530 ],3531 [{"name": "eth0", "persistent_state": "absent"}],3532 )3533 def test_full_state_absent_defaults(self):3534 self.maxDiff = None3535 self.check_one_connection_with_defaults(3536 {"name": "eth0", "persistent_state": "absent", "type": "ethernet"},3537 {3538 "actions": ["absent"],3539 "ignore_errors": None,3540 "name": "eth0",3541 "state": None,3542 "persistent_state": "absent",3543 "type": "ethernet",3544 "interface_name": "eth0",3545 },3546 )3547 def _test_ethtool_changes(self, input_ethtool, expected_ethtool):3548 """3549 When passing a dictionary 'input_features' with each feature and their3550 value to change, and a dictionary 'expected_features' with the expected3551 result in the configuration, the expected and resulting connection are3552 created and validated.3553 """3554 expected_ethtool_full = copy.deepcopy(ETHTOOL_DEFAULTS)3555 for key in list(expected_ethtool_full):3556 if key in expected_ethtool:3557 expected_ethtool_full[key].update(expected_ethtool[key])3558 input_connection = {3559 "ethtool": input_ethtool,3560 "name": "5",3561 "persistent_state": "present",3562 "type": "ethernet",3563 }3564 expected_connection = {3565 "actions": ["present"],3566 "ethtool": expected_ethtool_full,3567 "interface_name": "5",3568 "persistent_state": "present",3569 "state": None,3570 "type": "ethernet",3571 }3572 self.check_one_connection_with_defaults(input_connection, expected_connection)3573 def test_set_ethtool_feature(self):3574 """3575 When passing the name of an non-deprecated ethtool feature, their3576 current version is updated.3577 """3578 input_ethtool = {"features": {"tx_tcp_segmentation": "yes"}}3579 expected_ethtool = {"features": {"tx_tcp_segmentation": True}}3580 self._test_ethtool_changes(input_ethtool, expected_ethtool)3581 def test_set_deprecated_ethtool_feature(self):3582 """3583 When passing a deprecated name, their current version is updated.3584 """3585 input_ethtool = {"features": {"esp-hw-offload": "yes"}}3586 expected_ethtool = {"features": {"esp_hw_offload": True}}3587 self._test_ethtool_changes(input_ethtool, expected_ethtool)3588 def test_invalid_ethtool_settings(self):3589 """3590 When both the deprecated and current version of a feature are stated,3591 a Validation Error is raised.3592 """3593 input_features = {"tx-tcp-segmentation": "yes", "tx_tcp_segmentation": "yes"}3594 features_validator = (3595 network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures()3596 )3597 self.assertValidationError(features_validator, input_features)3598 def test_deprecated_ethtool_names(self):3599 """3600 Test that for each validator in3601 ArgValidator_DictEthtoolFeatures.nested there is another non-deprecated3602 validator that has the name from the deprecated_by attribute"3603 """3604 validators = (3605 network_lsr.argument_validator.ArgValidator_DictEthtoolFeatures().nested3606 )3607 for name, validator in validators.items():3608 if isinstance(3609 validator, network_lsr.argument_validator.ArgValidatorDeprecated3610 ):3611 assert validator.deprecated_by in validators.keys()3612 def test_valid_persistent_state(self):3613 """3614 Test that when persistent_state is present and state is set to present3615 or absent, a ValidationError raises.3616 """3617 validator = network_lsr.argument_validator.ArgValidator_DictConnection()3618 input_connection = {3619 "name": "test",3620 "persistent_state": "present",3621 "state": "present",3622 "type": "ethernet",3623 }3624 self.assertValidationError(validator, input_connection)3625 input_connection.update({"state": "absent"})3626 self.assertValidationError(validator, input_connection)3627 def test_dns_options_argvalidator(self):3628 """3629 Test that argvalidator for validating dns_options value is correctly defined.3630 """3631 validator = network_lsr.argument_validator.ArgValidator_DictIP()3632 false_testcase_1 = {3633 "dns_options": ["attempts:01"],3634 }3635 false_testcase_2 = {3636 "dns_options": ["debug$"],3637 }3638 false_testcase_3 = {3639 "dns_options": ["edns00"],3640 }3641 false_testcase_4 = {3642 "dns_options": ["ndots:"],3643 }3644 false_testcase_5 = {3645 "dns_options": ["no-check-name"],3646 }3647 false_testcase_6 = {3648 "dns_options": ["no-rel0ad"],3649 }3650 false_testcase_7 = {3651 "dns_options": ["bugno-tld-query"],3652 }3653 false_testcase_8 = {3654 "dns_options": ["etator"],3655 }3656 false_testcase_9 = {3657 "dns_options": ["singlerequest"],3658 }3659 false_testcase_10 = {3660 "dns_options": ["single-request-reopen:2"],3661 }3662 false_testcase_11 = {3663 "dns_options": ["timeout"],3664 }3665 false_testcase_12 = {3666 "dns_options": ["*trust-ad*"],3667 }3668 false_testcase_13 = {3669 "dns_options": ["use1-vc2-use-vc"],3670 }3671 self.assertValidationError(validator, false_testcase_1)3672 self.assertValidationError(validator, false_testcase_2)3673 self.assertValidationError(validator, false_testcase_3)3674 self.assertValidationError(validator, false_testcase_4)3675 self.assertValidationError(validator, false_testcase_5)3676 self.assertValidationError(validator, false_testcase_6)3677 self.assertValidationError(validator, false_testcase_7)3678 self.assertValidationError(validator, false_testcase_8)3679 self.assertValidationError(validator, false_testcase_9)3680 self.assertValidationError(validator, false_testcase_10)3681 self.assertValidationError(validator, false_testcase_11)3682 self.assertValidationError(validator, false_testcase_12)3683 self.assertValidationError(validator, false_testcase_13)3684 true_testcase_1 = {3685 "dns_options": ["attempts:3"],3686 }3687 true_testcase_2 = {3688 "dns_options": ["debug"],3689 }3690 true_testcase_3 = {3691 "dns_options": ["ndots:3", "single-request-reopen"],3692 }3693 true_testcase_4 = {3694 "dns_options": ["ndots:2", "timeout:3"],3695 }3696 true_testcase_5 = {3697 "dns_options": ["no-check-names"],3698 }3699 true_testcase_6 = {3700 "dns_options": ["no-reload"],3701 }3702 true_testcase_7 = {3703 "dns_options": ["no-tld-query"],3704 }3705 true_testcase_8 = {3706 "dns_options": ["rotate"],3707 }3708 true_testcase_9 = {3709 "dns_options": ["single-request"],3710 }3711 true_testcase_10 = {3712 "dns_options": ["single-request-reopen"],3713 }3714 true_testcase_11 = {3715 "dns_options": ["trust-ad"],3716 }3717 true_testcase_12 = {3718 "dns_options": ["use-vc"],3719 }3720 self.assertEqual(3721 validator.validate(true_testcase_1)["dns_options"], ["attempts:3"]3722 )3723 self.assertEqual(validator.validate(true_testcase_2)["dns_options"], ["debug"])3724 self.assertEqual(3725 validator.validate(true_testcase_3)["dns_options"],3726 ["ndots:3", "single-request-reopen"],3727 )3728 self.assertEqual(3729 validator.validate(true_testcase_4)["dns_options"], ["ndots:2", "timeout:3"]3730 )3731 self.assertEqual(3732 validator.validate(true_testcase_5)["dns_options"], ["no-check-names"]3733 )3734 self.assertEqual(3735 validator.validate(true_testcase_6)["dns_options"], ["no-reload"]3736 )3737 self.assertEqual(3738 validator.validate(true_testcase_7)["dns_options"], ["no-tld-query"]3739 )3740 self.assertEqual(validator.validate(true_testcase_8)["dns_options"], ["rotate"])3741 self.assertEqual(3742 validator.validate(true_testcase_9)["dns_options"], ["single-request"]3743 )3744 self.assertEqual(3745 validator.validate(true_testcase_10)["dns_options"],3746 ["single-request-reopen"],3747 )3748 self.assertEqual(3749 validator.validate(true_testcase_11)["dns_options"], ["trust-ad"]3750 )3751 self.assertEqual(3752 validator.validate(true_testcase_12)["dns_options"], ["use-vc"]3753 )3754 def test_ipv4_dns_without_ipv4_config(self):3755 """3756 Test that configuring IPv4 DNS is not allowed when IPv4 is disabled.3757 """3758 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3759 ipv4_dns_without_ipv4_config = [3760 {3761 "name": "test_ipv4_dns",3762 "type": "ethernet",3763 "ip": {3764 "auto6": True,3765 "dhcp4": False,3766 "dns": ["198.51.100.5"],3767 },3768 }3769 ]3770 self.assertRaises(3771 ValidationError,3772 validator.validate_connection_one,3773 "nm",3774 validator.validate(ipv4_dns_without_ipv4_config),3775 0,3776 )3777 def test_ipv6_dns_with_ipv6_disabled(self):3778 """3779 Test that configuring IPv6 DNS is not allowed when IPv6 is disabled.3780 """3781 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3782 ipv6_dns_with_ipv6_disabled = [3783 {3784 "name": "test_ipv6_dns",3785 "type": "ethernet",3786 "ip": {3787 "ipv6_disabled": True,3788 "dhcp4": True,3789 "dns": ["2001:db8::20"],3790 },3791 }3792 ]3793 old_util_nm = Util.NM3794 Util.NM = MagicMock(spec=["SETTING_IP6_CONFIG_METHOD_DISABLED"])3795 self.assertRaisesRegex(3796 ValidationError,3797 "IPv6 needs to be enabled to support IPv6 nameservers.",3798 validator.validate_connection_one,3799 "nm",3800 validator.validate(ipv6_dns_with_ipv6_disabled),3801 0,3802 )3803 Util.NM = old_util_nm3804 def test_ipv6_dns_with_static_ipv6_configuration(self):3805 """3806 Test that configuring IPv6 DNS is allowed when static IPv6 is configured.3807 """3808 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3809 ipv6_dns_with_static_ipv6_configuration = [3810 {3811 "name": "test_ipv6_dns",3812 "type": "ethernet",3813 "ip": {3814 "dhcp4": False,3815 "auto6": False,3816 "dns": ["2001:db8::20"],3817 "address": ["2001:db8::2/32"],3818 },3819 }3820 ]3821 # the connection index is 0 because there is only one connection profile3822 # defined here3823 connection_index = 03824 self.assertEqual(3825 validator.validate_connection_one(3826 "nm",3827 validator.validate(ipv6_dns_with_static_ipv6_configuration),3828 connection_index,3829 ),3830 None,3831 )3832 def test_ipv6_dns_without_ipv6_configuration(self):3833 """3834 Test that configuring IPv6 DNS is not allowed when IPv6 is not configured.3835 """3836 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3837 ipv6_dns_without_ipv6_configuration = [3838 {3839 "name": "test_ipv6_dns",3840 "type": "ethernet",3841 "ip": {3842 "dhcp4": False,3843 "auto6": False,3844 "dns": ["2001:db8::20"],3845 },3846 }3847 ]3848 self.assertRaisesRegex(3849 ValidationError,3850 "IPv6 needs to be enabled to support IPv6 nameservers.",3851 validator.validate_connection_one,3852 "nm",3853 validator.validate(ipv6_dns_without_ipv6_configuration),3854 0,3855 )3856 def test_ipv6_dns_options_without_ipv6_config(self):3857 """3858 Test that configuring IPv6 DNS options is not allowed when IPv6 is disabled.3859 """3860 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3861 ipv6_dns_options_without_ipv6_config = [3862 {3863 "name": "test_ipv6_dns",3864 "type": "ethernet",3865 "ip": {3866 "ipv6_disabled": True,3867 "dhcp4": True,3868 "dns_options": ["ip6-bytestring"],3869 },3870 }3871 ]3872 old_util_nm = Util.NM3873 Util.NM = MagicMock(spec=["SETTING_IP6_CONFIG_METHOD_DISABLED"])3874 self.assertRaises(3875 ValidationError,3876 validator.validate_connection_one,3877 "nm",3878 validator.validate(ipv6_dns_options_without_ipv6_config),3879 0,3880 )3881 Util.NM = old_util_nm3882 def test_dns_search_without_ipv4_and_ipv6_configuration(self):3883 """3884 Test that configuring DNS search setting is not allowed when both IPv4 and3885 IPv6 are not configured.3886 """3887 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3888 dns_search_without_ipv4_and_ipv6_configuration = [3889 {3890 "name": "test_dns_search",3891 "type": "ethernet",3892 "ip": {3893 "dhcp4": False,3894 "auto6": False,3895 "dns_search": ["example.com"],3896 },3897 }3898 ]3899 self.assertRaisesRegex(3900 ValidationError,3901 "Setting 'dns_search' or 'dns_options' is not allowed when IPv4 is "3902 "disabled and IPv6 is not configured",3903 validator.validate_connection_one,3904 "nm",3905 validator.validate(dns_search_without_ipv4_and_ipv6_configuration),3906 0,3907 )3908 def test_auto6_enabled_ipv6_disabled(self):3909 """3910 Test that enabling `auto6` and disabling IPv6 are mutually exclusive.3911 """3912 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3913 auto6_enabled_ipv6_disabled = [3914 {3915 "name": "test_ipv6_method",3916 "type": "ethernet",3917 "ip": {3918 "ipv6_disabled": True,3919 "auto6": True,3920 },3921 }3922 ]3923 self.assertRaisesRegex(3924 ValidationError,3925 "'auto6' and 'ipv6_disabled' are mutually exclusive",3926 validator.validate,3927 auto6_enabled_ipv6_disabled,3928 )3929 def test_static_ipv6_configured_ipv6_disabled(self):3930 """3931 Test that configuring static IPv6 and disabling IPv6 are mutually exclusive.3932 """3933 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3934 static_ipv6_configured_ipv6_disabled = [3935 {3936 "name": "test_ipv6_method",3937 "type": "ethernet",3938 "ip": {3939 "ipv6_disabled": True,3940 "address": ["2001:db8::2/32"],3941 },3942 }3943 ]3944 self.assertRaisesRegex(3945 ValidationError,3946 "'ipv6_disabled' and static IPv6 addresses are mutually exclusive",3947 validator.validate,3948 static_ipv6_configured_ipv6_disabled,3949 )3950 def test_gateway6_configured_ipv6_disabled(self):3951 """3952 Test that configuring `gateway6` and disabling IPv6 are mutually exclusive.3953 """3954 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3955 gateway6_configured_ipv6_disabled = [3956 {3957 "name": "test_ipv6_method",3958 "type": "ethernet",3959 "ip": {3960 "ipv6_disabled": True,3961 "gateway6": "2001:db8::1",3962 },3963 }3964 ]3965 self.assertRaisesRegex(3966 ValidationError,3967 "'ipv6_disabled' and 'gateway6' are mutually exclusive",3968 validator.validate,3969 gateway6_configured_ipv6_disabled,3970 )3971 def test_route_metric6_configured_ipv6_disabled(self):3972 """3973 Test that configuring `route_metric6` and disabling IPv6 are mutually3974 exclusive.3975 """3976 validator = network_lsr.argument_validator.ArgValidator_ListConnections()3977 route_metric6_configured_ipv6_disabled = [3978 {3979 "name": "test_ipv6_method",3980 "type": "ethernet",3981 "ip": {3982 "ipv6_disabled": True,3983 "route_metric6": -1,3984 },3985 }3986 ]3987 self.assertRaisesRegex(3988 ValidationError,3989 "'ipv6_disabled' and 'route_metric6' are mutually exclusive",3990 validator.validate,3991 route_metric6_configured_ipv6_disabled,3992 )3993 def test_set_deprecated_master(self):3994 """3995 When passing the deprecated "master" it is updated to "controller".3996 """3997 input_connections = [3998 {3999 "name": "prod2",4000 "state": "up",4001 "type": "bridge",4002 },4003 {4004 "name": "prod2-port1",4005 "state": "up",4006 "type": "ethernet",4007 "interface_name": "eth1",4008 "master": "prod2",4009 },4010 ]4011 connections = ARGS_CONNECTIONS.validate(input_connections)4012 self.assertTrue(len(connections) == 2)4013 for connection in connections:4014 self.assertTrue("controller" in connection)4015 self.assertTrue("master" not in connection)4016 def test_set_deprecated_slave_type(self):4017 """4018 When passing the deprecated "slave_type" it is updated to "port_type".4019 """4020 input_connections = [4021 {4022 "name": "prod2",4023 "state": "up",4024 "type": "bridge",4025 },4026 {4027 "name": "prod2-port1",4028 "state": "up",4029 "type": "ethernet",4030 "interface_name": "eth1",4031 "controller": "prod2",4032 "slave_type": "bridge",4033 },4034 ]4035 connections = ARGS_CONNECTIONS.validate(input_connections)4036 self.assertTrue(len(connections) == 2)4037 for connection in connections:4038 self.assertTrue("port_type" in connection)4039 self.assertTrue("slave_type" not in connection)4040@my_test_skipIf(nmutil is None, "no support for NM (libnm via pygobject)")4041class TestNM(unittest.TestCase):4042 def test_connection_ensure_setting(self):4043 con = NM.SimpleConnection.new()4044 self.assertIsNotNone(con)4045 self.assertTrue(GObject.type_is_a(con, NM.Connection))4046 s = nmutil.connection_ensure_setting(con, NM.SettingWired)4047 self.assertIsNotNone(s)4048 self.assertTrue(GObject.type_is_a(s, NM.SettingWired))4049 s2 = nmutil.connection_ensure_setting(con, NM.SettingWired)4050 self.assertIsNotNone(s2)4051 self.assertIs(s, s2)4052 self.assertTrue(GObject.type_is_a(s, NM.SettingWired))4053 def test_connection_list(self):4054 connections = nmutil.connection_list()4055 self.assertIsNotNone(connections)4056 def test_path_to_glib_bytes(self):4057 result = Util.path_to_glib_bytes("/my/test/path")4058 self.assertIsInstance(result, Util.GLib().Bytes)4059 self.assertEqual(result.get_data(), b"file:///my/test/path\x00")4060class TestValidatorMatch(Python26CompatTestCase):4061 def setUp(self):4062 self.test_profile = {4063 "name": "test",4064 "type": "ethernet",4065 "ip": {4066 "dhcp4": False,4067 "address": "192.168.245.7/24",4068 },4069 "match": None,4070 }4071 self.validator = network_lsr.argument_validator.ArgValidator_DictConnection()4072 def test_match_path_empty_list(self):4073 """4074 Test that 'match.path' setting can be defined as None, [], [""], [None] or ""4075 and such a setting will be normalized into []4076 """4077 for disabled_path in [None, [], [""], [None], ""]:4078 self.test_profile["match"] = {"path": disabled_path}4079 result = self.validator.validate(self.test_profile)4080 self.assertEqual(result["match"], {"path": []})4081 def test_match_path_setting_normalization(self):4082 """4083 Test that 'match.path' setting ["", "usb123", None] will be normalized into4084 ["usb123"]4085 """4086 self.test_profile["match"] = {"path": ["", "usb123", None]}4087 result = self.validator.validate(self.test_profile)4088 self.assertEqual(result["match"], {"path": ["usb123"]})4089 def test_match_path_valid_setting(self):4090 """4091 Test that values like ["pci-0000:00:03.0"] and ["&!pci-0000:00:0[1-3].0"] are4092 valid values for 'match.path' setting4093 """4094 self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}4095 result1 = self.validator.validate(self.test_profile)4096 self.assertEqual(result1["match"], {"path": ["pci-0000:00:03.0"]})4097 self.test_profile["match"] = {"path": ["&!pci-0000:00:0[1-3].0"]}4098 result2 = self.validator.validate(self.test_profile)4099 self.assertEqual(result2["match"], {"path": ["&!pci-0000:00:0[1-3].0"]})4100 def test_match_path_invalid_setting(self):4101 """4102 Test that values like ["&"] and ["|"] are invalid values for 'match.path'4103 setting4104 """4105 self.test_profile["match"] = {"path": ["&", ""]}4106 self.assertRaisesRegex(4107 ValidationError,4108 "['&'] will only match the devices that have no PCI path",4109 self.validator.validate,4110 self.test_profile,4111 )4112 self.test_profile["match"] = {"path": ["|", None]}4113 self.assertRaisesRegex(4114 ValidationError,4115 "['|'] will only match the devices that have no PCI path",4116 self.validator.validate,4117 self.test_profile,4118 )4119 def test_match_path_invalid_connection_type(self):4120 """4121 Test that when 'match.path' setting is correctly defined but the connection4122 type is neither ethernet nor infiniband, a ValidationError raises.4123 """4124 self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}4125 result = self.validator.validate(self.test_profile)4126 self.assertEqual(result["match"], {"path": ["pci-0000:00:03.0"]})4127 self.test_profile["type"] = "dummy"4128 self.assertRaisesRegex(4129 ValidationError,4130 "'match.path' settings are only supported for type 'ethernet' or 'infiniband'",4131 self.validator.validate,4132 self.test_profile,4133 )4134 def test_interface_name_when_match_not_specified(self):4135 """4136 Test that when 'match' setting is not specified, interface name should be4137 profile name.4138 """4139 result = self.validator.validate(self.test_profile)4140 self.assertEqual(result["interface_name"], "test")4141 def test_interface_name_and_match_when_match_is_None(self):4142 """4143 Test that when 'match' setting is None, interface name should be profile name4144 and 'match' setting will be normalized into {}.4145 """4146 self.test_profile["match"] = None4147 result = self.validator.validate(self.test_profile)4148 self.assertEqual(result["match"], {})4149 self.assertEqual(result["interface_name"], "test")4150 def test_interface_name_when_match_path_is_empty_list(self):4151 """4152 Test that when 'match.path' setting is empty list, interface name should be4153 profile name.4154 """4155 self.test_profile["match"] = {"path": []}4156 result = self.validator.validate(self.test_profile)4157 self.assertEqual(result["interface_name"], "test")4158 def test_interface_name_when_match_path_is_valid(self):4159 """4160 Test that when 'match.path' setting contains interface path, interface name4161 should be unset.4162 """4163 self.test_profile["match"] = {"path": ["pci-0000:00:03.0"]}4164 result = self.validator.validate(self.test_profile)4165 self.assertEqual(result["interface_name"], None)4166class TestUtils(unittest.TestCase):4167 def test_mac_ntoa(self):4168 mac_bytes = b"\xaa\xbb\xcc\xdd\xee\xff"4169 self.assertEqual(Util.mac_ntoa(mac_bytes), "aa:bb:cc:dd:ee:ff")4170 def test_convert_passwd_flags_nm(self):4171 test_cases = [4172 ([], 0),4173 (["none"], 0),4174 (["agent-owned"], 1),4175 (["not-saved"], 2),4176 (["agent-owned", "not-saved"], 3),4177 (4178 ["not-required"],4179 4,4180 ),4181 (["agent-owned", "not-required"], 5),4182 (["not-saved", "not-required"], 6),4183 (["agent-owned", "not-saved", "not-required"], 7),4184 ]4185 for test_case in test_cases:4186 result = Util.convert_passwd_flags_nm(test_case[0])4187 self.assertEqual(result, test_case[1])4188class TestValidatorRouteTable(Python26CompatTestCase):4189 def setUp(self):4190 self.test_connections = [4191 {4192 "name": "eth0",4193 "type": "ethernet",4194 "ip": {4195 "dhcp4": False,4196 "address": ["198.51.100.3/26"],4197 "route": [4198 {4199 "network": "198.51.100.128",4200 "prefix": 26,4201 "gateway": "198.51.100.1",4202 "metric": 2,4203 "table": 30400,4204 },4205 ],4206 "routing_rule": [],4207 },4208 }4209 ]4210 self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()4211 self.rt_parsing = network_lsr.argument_validator.IPRouteUtils()4212 self.old_getter = (4213 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping4214 )4215 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (4216 classmethod(4217 lambda cls: {4218 "custom": 200,4219 "eth": 30400,4220 }4221 )4222 )4223 # the connection index is 0 because there is only one connection profile4224 # defined here4225 self.connection_index = 04226 def tearDown(self):4227 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (4228 self.old_getter4229 )4230 def test_valid_numeric_route_tables(self):4231 """4232 Test that the value between 1 and 4294967295 are the valid value for numeric4233 route tables and the value will not be normalized4234 """4235 self.validator.validate_route_tables(4236 self.validator.validate(self.test_connections)[0],4237 self.connection_index,4238 )4239 self.assertEqual(4240 self.test_connections[0]["ip"]["route"][0]["table"],4241 30400,4242 )4243 self.test_connections[0]["ip"]["route"][0]["table"] = 2004244 self.validator.validate_route_tables(4245 self.validator.validate(self.test_connections)[0],4246 self.connection_index,4247 )4248 self.assertEqual(4249 self.test_connections[0]["ip"]["route"][0]["table"],4250 200,4251 )4252 def test_invalid_numeric_route_tables(self):4253 """4254 Test that the value less than 1 or greater than 4294967295 are the invalid4255 value for numeric route tables4256 """4257 self.test_connections[0]["ip"]["route"][0]["table"] = 04258 val_min = 14259 val_max = 0xFFFFFFFF4260 self.assertRaisesRegex(4261 ValidationError,4262 "route table value is {0} but cannot be less than {1}".format(4263 self.test_connections[0]["ip"]["route"][0]["table"],4264 val_min,4265 ),4266 self.validator.validate,4267 self.test_connections,4268 )4269 self.test_connections[0]["ip"]["route"][0]["table"] = 42949672964270 self.assertRaisesRegex(4271 ValidationError,4272 "route table value is {0} but cannot be greater than {1}".format(4273 self.test_connections[0]["ip"]["route"][0]["table"],4274 val_max,4275 ),4276 self.validator.validate,4277 self.test_connections,4278 )4279 def test_empty_route_table_name(self):4280 """4281 Test that empty string is invalid value for route table name4282 """4283 self.test_connections[0]["ip"]["route"][0]["table"] = ""4284 self.assertRaisesRegex(4285 ValidationError,4286 "route table name cannot be empty string",4287 self.validator.validate,4288 self.test_connections,4289 )4290 def test_invalid_value_types_for_route_tables(self):4291 """4292 Test that the value types apart from string type and integer type are all4293 invalid value types for route tables4294 """4295 self.test_connections[0]["ip"]["route"][0]["table"] = False4296 self.assertRaisesRegex(4297 ValidationError,4298 "route table must be the named or numeric tables but is {0}".format(4299 self.test_connections[0]["ip"]["route"][0]["table"]4300 ),4301 self.validator.validate,4302 self.test_connections,4303 )4304 self.test_connections[0]["ip"]["route"][0]["table"] = 2.54305 self.assertRaisesRegex(4306 ValidationError,4307 "route table must be the named or numeric tables but is {0}".format(4308 self.test_connections[0]["ip"]["route"][0]["table"]4309 ),4310 self.validator.validate,4311 self.test_connections,4312 )4313 def test_invalid_route_table_names(self):4314 """4315 Test that the route table names should not be composed from the characters4316 which are not contained within the benign set r"^[a-zA-Z0-9_.-]+$"4317 """4318 self.test_connections[0]["ip"]["route"][0]["table"] = "test*"4319 self.assertRaisesRegex(4320 ValidationError,4321 "route table name contains invalid characters",4322 self.validator.validate,4323 self.test_connections,4324 )4325 self.test_connections[0]["ip"]["route"][0]["table"] = "!!!"4326 self.assertRaisesRegex(4327 ValidationError,4328 "route table name contains invalid characters",4329 self.validator.validate,4330 self.test_connections,4331 )4332 def test_parse_rt_tables(self):4333 """4334 Test that the `IPRouteUtils._parse_route_tables_mapping()` will create the4335 route tables mapping dictionary when feeding the proper route table file4336 content4337 """4338 def parse(file_content):4339 mapping = {}4340 network_lsr.argument_validator.IPRouteUtils._parse_route_tables_mapping(4341 file_content, mapping4342 )4343 return mapping4344 self.assertEqual(parse(b""), {})4345 self.assertEqual(parse(b"5x"), {})4346 self.assertEqual(parse(b"0xF5 x"), {"x": 0xF5})4347 self.assertEqual(parse(b"0x5a x"), {"x": 0x5A})4348 self.assertEqual(parse(b" 0x5a x"), {"x": 0x5A})4349 self.assertEqual(parse(b"0x0 x"), {"x": 0x0})4350 self.assertEqual(parse(b"0x x"), {})4351 self.assertEqual(parse(b"5 x"), {"x": 5})4352 self.assertEqual(parse(b" 7 y "), {"y": 7})4353 self.assertEqual(parse(b"5 x\n0x4 y"), {"x": 5, "y": 4})4354 self.assertEqual(parse(b"5 x #df\n0x4 y"), {"x": 5, "y": 4})4355 self.assertEqual(parse(b"5 x #df\n0x4 y\n7\ty"), {"x": 5, "y": 7})4356 self.assertEqual(parse(b"-1 x #df\n0x4 y\n5 x"), {"x": 5, "y": 4})4357 self.assertEqual(4358 parse(b"5 x #df\n0x4 y\n7\t \ty\n\t\t44 7\n 66 a%\n 67 ab"),4359 {"x": 5, "y": 7, "7": 44, "ab": 67},4360 )4361 # https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/etc/iproute2/rt_tables?id=11e41a635cfab54e8e02fbff2a03715467e77ae94362 self.assertEqual(4363 parse(4364 b"#\n"4365 b"# reserved values\n"4366 b"#\n"4367 b"255 local\n"4368 b"254 main\n"4369 b"253 default\n"4370 b"0 unspec\n"4371 b"#\n"4372 b"# local\n"4373 b"#\n"4374 b"#1 inr.ruhep\n"4375 ),4376 {"local": 255, "main": 254, "default": 253, "unspec": 0},4377 )4378 def test_table_found_when_validate_route_tables(self):4379 """4380 Test that the `validate_route_tables()` will find the table id mapping from4381 `IPRouteUtils.get_route_tables_mapping()`.4382 """4383 self.test_connections[0]["ip"]["route"][0]["table"] = "custom"4384 self.validator.validate_route_tables(4385 self.test_connections[0],4386 self.connection_index,4387 )4388 self.assertEqual(4389 self.test_connections[0]["ip"]["route"][0]["table"],4390 200,4391 )4392 def test_table_not_found_when_validate_route_tables(self):4393 """4394 Test that the validation error is raised when the `validate_route_tables()` cannot4395 find the table id mapping from `IPRouteUtils.get_route_tables_mapping()`.4396 """4397 self.test_connections[0]["ip"]["route"][0]["table"] = "test"4398 self.assertRaisesRegex(4399 ValidationError,4400 "cannot find route table {0} in `/etc/iproute2/rt_tables` or "4401 "`/etc/iproute2/rt_tables.d/`".format(4402 self.test_connections[0]["ip"]["route"][0]["table"]4403 ),4404 self.validator.validate_route_tables,4405 self.test_connections[0],4406 self.connection_index,4407 )4408class TestValidatorRoutingRules(Python26CompatTestCase):4409 def setUp(self):4410 self.test_connections = [4411 {4412 "name": "eth0",4413 "type": "ethernet",4414 "ip": {4415 "dhcp4": False,4416 "address": ["198.51.100.3/26"],4417 "route": [4418 {4419 "network": "198.51.100.128",4420 "prefix": 26,4421 "gateway": "198.51.100.1",4422 "metric": 2,4423 "table": 30400,4424 },4425 ],4426 "routing_rule": [4427 {4428 "action": "to-table",4429 "priority": 256,4430 },4431 ],4432 },4433 }4434 ]4435 self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()4436 self.old_getter = (4437 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping4438 )4439 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (4440 classmethod(4441 lambda cls: {4442 "custom": 200,4443 "eth": 30400,4444 }4445 )4446 )4447 # the connection index is 0 because there is only one connection profile4448 # defined here4449 self.connection_index = 04450 def tearDown(self):4451 network_lsr.argument_validator.IPRouteUtils.get_route_tables_mapping = (4452 self.old_getter4453 )4454 def test_routing_rule_missing_address_family(self):4455 """4456 Test that the address family has to be specified if cannot be derived from src4457 or dst address4458 """4459 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564460 self.test_connections[0]["ip"]["routing_rule"][0]["suppress_prefixlength"] = 324461 self.assertRaisesRegex(4462 ValidationError,4463 "specify the address family 'family'",4464 self.validator.validate,4465 self.test_connections,4466 )4467 def test_routing_rule_validate_address_family(self):4468 """4469 Test that the derived address family and the specified address family should be4470 consistent4471 """4472 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564473 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv6"4474 self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "198.51.100.58/24"4475 self.assertRaisesRegex(4476 ValidationError,4477 "invalid address family in 'from'",4478 self.validator.validate,4479 self.test_connections,4480 )4481 self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "2001:db8::2/32"4482 self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "198.51.100.60/24"4483 self.assertRaisesRegex(4484 ValidationError,4485 "invalid address family in 'to'",4486 self.validator.validate,4487 self.test_connections,4488 )4489 def test_routing_rule_missing_table(self):4490 """4491 Test that table has to be defined when the action of the routing rule is4492 "to-table"4493 """4494 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4495 self.assertRaisesRegex(4496 ValidationError,4497 "missing 'table' for the routing rule",4498 self.validator.validate,4499 self.test_connections,4500 )4501 def test_routing_rule_invalid_from_prefix_length(self):4502 """4503 Test that the prefix length for from/src cannot be zero when from/src is4504 specified4505 """4506 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564507 self.test_connections[0]["ip"]["routing_rule"][0]["from"] = "198.51.100.58/0"4508 self.assertRaisesRegex(4509 ValidationError,4510 "the prefix length for 'from' cannot be zero",4511 self.validator.validate,4512 self.test_connections,4513 )4514 def test_routing_rule_invalid_to_prefix_length(self):4515 """4516 Test that the prefix length for to/dst cannot be zero when to/dst is specified4517 """4518 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564519 self.test_connections[0]["ip"]["routing_rule"][0]["to"] = "198.51.100.58/0"4520 self.assertRaisesRegex(4521 ValidationError,4522 "the prefix length for 'to' cannot be zero",4523 self.validator.validate,4524 self.test_connections,4525 )4526 def test_routing_rule_validate_fwmark(self):4527 """4528 Test that fwmark requires fwmask to be specified4529 """4530 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564531 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4532 self.test_connections[0]["ip"]["routing_rule"][0]["fwmark"] = 14533 self.assertRaisesRegex(4534 ValidationError,4535 "'fwmask' and 'fwmark' must be set together",4536 self.validator.validate,4537 self.test_connections,4538 )4539 def test_routing_rule_validate_fwmask(self):4540 """4541 Test that fwmask requires fwmark to be specified4542 """4543 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564544 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4545 self.test_connections[0]["ip"]["routing_rule"][0]["fwmask"] = 14546 self.assertRaisesRegex(4547 ValidationError,4548 "'fwmask' and 'fwmark' must be set together",4549 self.validator.validate,4550 self.test_connections,4551 )4552 def test_routing_rule_invalid_incoming_interface_name(self):4553 """4554 Test the invalid incoming interface name specified in the routing rule4555 """4556 self.test_connections[0]["ip"]["routing_rule"][0]["iif"] = " test "4557 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4558 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564559 self.assertRaisesRegex(4560 ValidationError,4561 "the incoming interface '{0}' specified in the routing rule is invalid "4562 "interface_name".format(4563 self.test_connections[0]["ip"]["routing_rule"][0]["iif"]4564 ),4565 self.validator.validate,4566 self.test_connections,4567 )4568 def test_routing_rule_invalid_outgoing_interface_name(self):4569 """4570 Test the invalid outgoing interface name specified in the routing rule4571 """4572 self.test_connections[0]["ip"]["routing_rule"][0]["oif"] = " test "4573 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4574 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564575 self.assertRaisesRegex(4576 ValidationError,4577 "the outgoing interface '{0}' specified in the routing rule is invalid "4578 "interface_name".format(4579 self.test_connections[0]["ip"]["routing_rule"][0]["oif"]4580 ),4581 self.validator.validate,4582 self.test_connections,4583 )4584 def test_routing_rule_validate_uid(self):4585 """4586 Test the invalid uid specified in the routing rule4587 """4588 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564589 self.test_connections[0]["ip"]["routing_rule"][0]["uid"] = "2000 - 1000"4590 self.assertRaisesRegex(4591 ValidationError,4592 "the range start cannot be greater than range end",4593 self.validator.validate,4594 self.test_connections,4595 )4596 def test_routing_rule_validate_suppress_prefixlength(self):4597 """4598 Test the invalid suppress_prefixlength setting4599 """4600 self.test_connections[0]["ip"]["routing_rule"][0]["suppress_prefixlength"] = 404601 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv4"4602 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = 2564603 suppress_prefixlength_val_max = Util.addr_family_prefix_length(4604 self.test_connections[0]["ip"]["routing_rule"][0]["family"]4605 )4606 self.assertRaisesRegex(4607 ValidationError,4608 "The specified 'suppress_prefixlength' cannot be greater than {0}".format(4609 suppress_prefixlength_val_max4610 ),4611 self.validator.validate,4612 self.test_connections,4613 )4614 self.test_connections[0]["ip"]["routing_rule"][0]["family"] = "ipv6"4615 self.test_connections[0]["ip"]["routing_rule"][0]["action"] = "blackhole"4616 self.assertRaisesRegex(4617 ValidationError,4618 "'suppress_prefixlength' is only allowed with the to-table action",4619 self.validator.validate,4620 self.test_connections,4621 )4622 def test_table_found_when_lookup_named_table(self):4623 """4624 Test that the `validate_route_tables()` will find the table id mapping from4625 `IPRouteUtils.get_route_tables_mapping()`.4626 """4627 self.test_connections[0]["ip"]["routing_rule"][0]["table"] = "custom"4628 self.validator.validate_route_tables(4629 self.test_connections[0],4630 self.connection_index,4631 )4632 self.assertEqual(4633 self.test_connections[0]["ip"]["routing_rule"][0]["table"],4634 200,4635 )4636class TestValidatorDictBond(Python26CompatTestCase):4637 def setUp(self):4638 self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()4639 self.test_connections = [4640 {4641 "name": "bond0",4642 "type": "bond",4643 "bond": {4644 "mode": "balance-rr",4645 },4646 },4647 ]4648 def test_invalid_bond_option_ad(self):4649 """4650 Test the ad bond option restrictions4651 """4652 self.test_connections[0]["bond"]["ad_actor_sys_prio"] = 655354653 self.assertRaisesRegex(4654 ValidationError,4655 "the bond option ad_actor_sys_prio is only valid with mode 802.3ad",4656 self.validator.validate,4657 self.test_connections,4658 )4659 self.test_connections[0]["bond"]["mode"] = "802.3ad"4660 self.validator.validate(self.test_connections)4661 def test_invalid_bond_option_packets_per_port(self):4662 """4663 Test the packets_per_port bond option restrictions4664 """4665 self.test_connections[0]["bond"]["mode"] = "802.3ad"4666 self.test_connections[0]["bond"]["packets_per_port"] = 24667 self.assertRaisesRegex(4668 ValidationError,4669 "the bond option packets_per_port is only valid with mode balance-rr",4670 self.validator.validate,4671 self.test_connections,4672 )4673 self.test_connections[0]["bond"]["mode"] = "balance-rr"4674 self.validator.validate(self.test_connections)4675 def test_invalid_bond_option_arp(self):4676 """4677 Test the arp bond option restrictions4678 """4679 self.test_connections[0]["bond"]["mode"] = "802.3ad"4680 self.test_connections[0]["bond"]["arp_interval"] = 24681 self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"4682 self.assertRaisesRegex(4683 ValidationError,4684 "the bond option arp_interval is only valid with mode balance-rr, active-backup, balance-xor or broadcast",4685 self.validator.validate,4686 self.test_connections,4687 )4688 self.test_connections[0]["bond"]["mode"] = "balance-rr"4689 self.validator.validate(self.test_connections)4690 def test_invalid_bond_option_tlb_dynamic_lb(self):4691 """4692 Test the tlb_dynamic_lb bond option restrictions4693 """4694 self.test_connections[0]["bond"]["tlb_dynamic_lb"] = True4695 self.assertRaisesRegex(4696 ValidationError,4697 "the bond option tlb_dynamic_lb is only valid with mode balance-tlb or balance-alb",4698 self.validator.validate,4699 self.test_connections,4700 )4701 self.test_connections[0]["bond"]["mode"] = "balance-tlb"4702 self.validator.validate(self.test_connections)4703 def test_invalid_bond_option_primary(self):4704 """4705 Test the primary bond option restrictions4706 """4707 self.test_connections[0]["bond"]["primary"] = "bond0.0"4708 self.assertRaisesRegex(4709 ValidationError,4710 "the bond option primary is only valid with mode active-backup, balance-tlb, balance-alb",4711 self.validator.validate,4712 self.test_connections,4713 )4714 self.test_connections[0]["bond"]["mode"] = "balance-tlb"4715 self.validator.validate(self.test_connections)4716 def test_invalid_bond_option_downdelay_updelay(self):4717 """4718 Test the downdelay or updelay bond option restrictions4719 """4720 self.test_connections[0]["bond"]["downdelay"] = 54721 self.assertRaisesRegex(4722 ValidationError,4723 "the bond option downdelay or updelay is only valid with miimon enabled",4724 self.validator.validate,4725 self.test_connections,4726 )4727 self.test_connections[0]["bond"]["miimon"] = 1104728 self.validator.validate(self.test_connections)4729 def test_invalid_bond_option_peer_notif_delay(self):4730 """4731 Test the peer_notif_delay bond option restrictions4732 """4733 self.test_connections[0]["bond"]["miimon"] = 1104734 self.test_connections[0]["bond"]["peer_notif_delay"] = 2224735 self.assertRaisesRegex(4736 ValidationError,4737 "the bond option peer_notif_delay needs miimon enabled and must be miimon multiple",4738 self.validator.validate,4739 self.test_connections,4740 )4741 self.test_connections[0]["bond"]["peer_notif_delay"] = 2204742 self.test_connections[0]["bond"]["arp_interval"] = 1104743 self.assertRaisesRegex(4744 ValidationError,4745 "the bond option peer_notif_delay needs arp_interval disabled",4746 self.validator.validate,4747 self.test_connections,4748 )4749 self.test_connections[0]["bond"]["arp_interval"] = 04750 self.validator.validate(self.test_connections)4751 def test_invalid_bond_option_peer_arp_ip_target_arp_interval(self):4752 """4753 Test the arp_ip_target or arp_interval bond option restrictions4754 """4755 self.test_connections[0]["bond"]["arp_interval"] = 44756 self.assertRaisesRegex(4757 ValidationError,4758 "the bond option arp_interval requires arp_ip_target to be set",4759 self.validator.validate,4760 self.test_connections,4761 )4762 self.test_connections[0]["bond"]["arp_ip_target"] = "198.51.100.3"4763 self.test_connections[0]["bond"]["arp_interval"] = 04764 self.assertRaisesRegex(4765 ValidationError,4766 "the bond option arp_ip_target requires arp_interval to be set",4767 self.validator.validate,4768 self.test_connections,4769 )4770 self.test_connections[0]["bond"]["arp_interval"] = 44771 self.validator.validate(self.test_connections)4772 def test_invalid_bond_option_infiniband_port(self):4773 """4774 Test that bond only supports infiniband ports in active-backup mode4775 """4776 test_connections_with_infiniband_port = [4777 {4778 "name": "bond0",4779 "type": "bond",4780 "bond": {4781 "mode": "balance-rr",4782 },4783 },4784 {4785 "name": "bond0.0",4786 "type": "infiniband",4787 "controller": "bond0",4788 },4789 {4790 "name": "bond0.1",4791 "type": "infiniband",4792 "controller": "bond0",4793 },4794 ]4795 self.assertRaisesRegex(4796 ValidationError,4797 "bond only supports infiniband ports in active-backup mode",4798 self.validator.validate,4799 test_connections_with_infiniband_port,4800 )4801 self.test_connections[0]["bond"]["mode"] = "active-backup"4802 self.validator.validate(self.test_connections)4803class TestValidatorDictInfiniband(Python26CompatTestCase):4804 def setUp(self):4805 self.validator = network_lsr.argument_validator.ArgValidator_ListConnections()4806 self.test_connections = [4807 {4808 "name": "ib0",4809 "type": "infiniband",4810 "interface_name": "ib0",4811 },4812 {4813 "name": "ib0-10",4814 "type": "infiniband",4815 "infiniband": {4816 "p_key": 10,4817 "transport_mode": "datagram",4818 },4819 "parent": "ib0",4820 },4821 ]4822 def test_invalid_pkey_values(self):4823 self.test_connections[1]["infiniband"]["p_key"] = 0x00004824 self.assertRaisesRegex(4825 ValidationError,4826 "the pkey value {0} is not allowed as such a pkey value is not "4827 "supported by kernel".format(4828 self.test_connections[1]["infiniband"]["p_key"]4829 ),4830 self.validator.validate,4831 self.test_connections,4832 )4833 self.test_connections[1]["infiniband"]["p_key"] = 0x80004834 self.assertRaisesRegex(4835 ValidationError,4836 "the pkey value {0} is not allowed as such a pkey value is not "4837 "supported by kernel".format(4838 self.test_connections[1]["infiniband"]["p_key"]4839 ),4840 self.validator.validate,4841 self.test_connections,4842 )4843class TestSysUtils(unittest.TestCase):4844 def test_link_read_permaddress(self):4845 self.assertEqual(SysUtil._link_read_permaddress("lo"), "00:00:00:00:00:00")4846 self.assertEqual(SysUtil._link_read_permaddress("fakeiface"), None)4847 self.assertEqual(SysUtil._link_read_permaddress("morethansixteenchars"), None)4848if __name__ == "__main__":...
tilemap_hex.py
Source:tilemap_hex.py
1import pygame2import math3import random4from pygame.locals import *5#setup6background_colour = (0,43,66)7(width, height) = (1000, 600)8screen = pygame.display.set_mode((width, height))#,pygame.FULLSCREEN)9fake_screen = pygame.Surface((1000,700))10#fake_screen.fill(background_colour)11pygame.display.set_caption('Let there be Tiles')12pygame.font.init()13myfont = pygame.font.SysFont("monospace", 20)14clock = pygame.time.Clock()15tile_size = 20016#draw tile i,j at position x,y17def draw_tile(i,j,x,y):18 offset = 019 cropRect = (i*tile_size + offset, j*tile_size + offset, tile_size - 2*offset, tile_size - 2*offset)20 tile = pygame.Surface([tile_size, tile_size])21 tile.blit(tiles, [-i*tile_size,-j*tile_size])22 tile.convert_alpha()23 tile.set_colorkey((255,255,255)) 24 pygame.draw.polygon(tile, [255,255,255,0], [[0,0], [0.25*tile_size,0], [0,0.5*tile_size]])25 pygame.draw.polygon(tile, [255,255,255,0], [[0.75*tile_size,0], [tile_size,0], [tile_size,0.5*tile_size]])26 pygame.draw.polygon(tile, [255,255,255,0], [[0,tile_size], [0.25*tile_size,tile_size], [0,0.5*tile_size]])27 pygame.draw.polygon(tile, [255,255,255,0], [[0.75*tile_size,tile_size], [tile_size,tile_size], [tile_size,0.5*tile_size]])28 w = x*0.75*tile_size + 2529 h = y*tile_size30 if x % 2 == 0:31 h = (y + 0.5)*tile_size32 fake_screen.blit(tile,(int(w), int(h)))33 #screen.blit(tiles,(int(x*tile_size), int(y*tile_size)),cropRect)34def tesselate(test_connections, tiles_placed, i, j):35 if i == 0:36 if test_connections[4] == 1 or test_connections[5] == 1:37 return False38 if j == 0:39 if test_connections[0] == 1:40 return False41 if i == cols-1:42 if test_connections[1] == 1 or test_connections[2] == 1:43 return False44 if j == rows-1:45 if test_connections[3] == 1:46 return False47 if i % 2 == 1:48 if i > 0:49 if tiles_placed[i-1][j][1] != test_connections[4]:50 return False51 if j > 0:52 if tiles_placed[i-1][j-1][2] != test_connections[5]:53 return False54 else:55 if i > 0:56 if tiles_placed[i-1][j][2] != test_connections[5]:57 return False58 if j < rows-1:59 if tiles_placed[i-1][j+1][1] != test_connections[4]:60 return False61 if j > 0:62 if tiles_placed[i][j-1][3] != test_connections[0]:63 return False64 return True65 66connections = [[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 1], [0, 0, 0, 1, 0, 0], [0, 0, 0, 1, 0, 1], [0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1]], [[0, 0, 1, 0, 0, 0], [0, 0, 1, 0, 0, 1], [0, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 1], [0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 1], [0, 0, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1]], [[0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1], [0, 1, 0, 0, 1, 0], [0, 1, 0, 0, 1, 1], [0, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1], [0, 1, 0, 1, 1, 0], [0, 1, 0, 1, 1, 1]], [[0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1], [0, 1, 1, 0, 1, 0], [0, 1, 1, 0, 1, 1], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 1], [0, 1, 1, 1, 1, 0], [0, 1, 1, 1, 1, 1]], [[1, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 1, 1], [1, 0, 0, 1, 0, 0], [1, 0, 0, 1, 0, 1], [1, 0, 0, 1, 1, 0], [1, 0, 0, 1, 1, 1]], [[1, 0, 1, 0, 0, 0], [1, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0], [1, 0, 1, 0, 1, 1], [1, 0, 1, 1, 0, 0], [1, 0, 1, 1, 0, 1], [1, 0, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1]], [[1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1], [1, 1, 0, 0, 1, 0], [1, 1, 0, 0, 1, 1], [1, 1, 0, 1, 0, 0], [1, 1, 0, 1, 0, 1], [1, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 1]], [[1, 1, 1, 0, 0, 0], [1, 1, 1, 0, 0, 1], [1, 1, 1, 0, 1, 0], [1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 0, 1], [1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1]]]67tiles_placed = []68tiles = pygame.image.load("tiles_hex_drawn.png").convert_alpha()69#screen.blit(tiles, [0,0])70cols = 671rows = 372def reset():73 screen.fill([0,0,0])74 global tiles_placed75 tiles_placed = []76 for i in range(cols):77 tiles_placed.append([])78 for j in range(rows):79 while 1:80 k = random.randint(0,7)81 l = random.randint(0,7)82 test_connections = connections[k][l][:]83 if tesselate(test_connections, tiles_placed, i, j):84 tiles_placed[i].append(test_connections)85 draw_tile(k,l,i,j)86 break87 #use flood fill to get all connected tiles88 if True:89 stack = [[0,0]]90 processed = []91 while len(stack) > 0:92 for s in reversed(stack):93 if s[0] >= 0 and s[0] < cols and s[1] >= 0 and s[1] < rows:94 tile = tiles_placed[s[0]][s[1]]95 print("tile = ", tile)96 if tile[0] == 1:97 neighbour = [s[0],s[1]-1]98 if neighbour not in stack and neighbour not in processed:99 stack.append(neighbour)100 if tile[1] == 1:101 neighbour = [s[0]+1,s[1]-1]102 if s[0] % 2 == 0:103 neighbour = [s[0]+1,s[1]]104 if neighbour not in stack and neighbour not in processed:105 stack.append(neighbour)106 if tile[2] == 1:107 neighbour = [s[0]+1,s[1]]108 if s[0] % 2 == 0:109 neighbour = [s[0]+1,s[1]+1]110 if neighbour not in stack and neighbour not in processed:111 stack.append(neighbour)112 if tile[3] == 1:113 neighbour = [s[0],s[1]+1]114 if neighbour not in stack and neighbour not in processed:115 stack.append(neighbour)116 if tile[4] == 1:117 neighbour = [s[0]-1,s[1]]118 if s[0] % 2 == 0:119 neighbour = [s[0]-1,s[1]+1]120 if neighbour not in stack and neighbour not in processed:121 stack.append(neighbour)122 if tile[5] == 1:123 neighbour = [s[0]-1,s[1]-1]124 if s[0] % 2 == 0:125 neighbour = [s[0]-1,s[1]]126 if neighbour not in stack and neighbour not in processed:127 stack.append(neighbour)128 if s not in processed:129 processed.append(s)130 stack.remove(s)131 print("stack = ", stack)132 print("processed = ", processed)133 #if not all tiles are connected try again134 done = True135 for i in range(cols):136 for j in range(rows):137 if [i,j] not in processed and tiles_placed[i][j] != [0,0,0,0]:138 done = False139 if done == False:140 print("disconnected")141 reset()142 screen.blit(pygame.transform.scale(fake_screen, (1000,600)), (0, 0))143print(tiles_placed)144reset()145running = True146while running:147 for event in pygame.event.get():148 if event.type == pygame.QUIT:149 running = False150 elif event.type == KEYDOWN:151 if event.key == K_ESCAPE:152 running = False153 if event.key == K_SPACE:154 reset()155 156 #screen.fill(background_colour)157 pygame.display.flip()158 159 ...
caexplosiontest.py
Source:caexplosiontest.py
1'''2Created on 12/03/201034@author: Ezequiel5'''6import unittest7import caexplosion89test_nodes={'A': (1.5,1.5),10 'B':(1.5,2.5),11 'C': (2.5,1.5),12 'D': (2.5,2.5)}13test_connections=[('A', 'B'),('B', 'D'),('C','A'),('D','C')]14con_param_labels=('connection_area','permeability')15connection_parameters=[(1.0,0.1),(2.0,0.5),(1.5,4.2)]16default_connection_parameters=(1.0,1.0)1718def distance(a,b):19 '''Returns the distance between a and b'''20 from math import sqrt21 return sqrt((a[0]-b[0])**2, (a[1]-b[1])**2)22 23class SimpleMeshCreationTestCase(unittest.TestCase):24 def setUp(self):25 '''26 Grafo: A, B, C, D 27 A: ubicado en (1.5, 1.5) 28 B: ubicado en (1.5, 2.5) 29 C: ubicado en (2.5, 1.5) 30 D: ubicado en (2.5, 2.5) 31 Conexiones: 32 A<->B 33 A<->C 34 C<->D 35 B<->D36 ''' 37 self.exp_subs=caexplosion.CAExplosion()38 def tearDown(self):39 self.exp_subs=None40 41 def testCreateEmptyMesh(self):42 self.mesh=self.exp_subs.Mesh()43 self.assertEqual(self.mesh.size(),0)44 45 def testBuildNodes(self):46 #Builds nodes47 for tag, pos in test_nodes.iteritems():48 new_node=self.mesh.Node()49 returned_tag=self.mesh.add(tag, new_node, pos)50 self.assertEqual(returned_tag, tag)51 self.assertEqual(self.mesh.get_position(tag), pos)52 53 54 self.assertEqual(self.mesh.order(), len(test_nodes))55 56 def testRepeatedTags(self):57 #Checks that nodes can't have the same tag58 for tag, pos in test_nodes.iteritems():59 new_node=self.mesh.Node()60 self.assertRaises(caexplosion.ExistingNodeError, self.mesh.add, args=(tag, new_node, pos) )61 62 #checks no new node was added63 self.assertEqual(self.mesh.size(), len(test_nodes))64 65 def testConnectNodesUsingTags(self):66 connect_iter=iter(test_connections)67 def_params=dict(zip(con_param_labels, default_connection_parameters))68 69 for param in connection_parameters:70 connect=connect_iter.next()71 kwparam=dict(zip(con_param_labels, param))72 edge=self.mesh.connect(*connect, **kwparam)73 d=distance(test_nodes[connect[0]], test_nodes[connect[1]])74 self.assertAlmostEqual(edge.length, d, 5)75 76 #test given parameters are correctly set77 for key, value in kwparam.iteritems():78 self.assertEqual(edge.__dict__[key], value)79 80 #Set remaining connections assuming default parameters81 for connect in connect_iter:82 edge=self.mesh.connect(*connect)83 84 d=distance(test_nodes[connect[0]], test_nodes[connect[1]])85 self.assertAlmostEqual(edge.length, d, 5) 86 #test default parameters are correctly set87 kwparam=dict(zip(con_param_labels, default_connection_parameters))88 for key, value in kwparam.iteritems():89 self.assertEqual(edge.__dict__[key], value)90 91 92 self.assertEqual(self.mesh.size(), len(test_connections))93 94 def testRepeatedEdges(self):95 for connection in test_connections:96 #We can't add the same connection again97 self.assertRaises(caexplosion.ExistingEdgeError, self.mesh.connect, args=(connection[0], connection[1]))98 #We can't add the transposed connection because it is undirected graph99 self.assertRaises(caexplosion.ExistingEdgeError, self.mesh.connect, args=(connection[1], connection[0]))100 101 #No edge was added102 self.assertEqual(self.mesh.size(), len(test_connections))103104 105106if __name__ == "__main__":107 #import sys;sys.argv = ['', 'Test.testName']
...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!