diff --git a/.github/workflows/qemu-kvm-integration-tests.yml b/.github/workflows/qemu-kvm-integration-tests.yml index ad4f26314..12b69b597 100644 --- a/.github/workflows/qemu-kvm-integration-tests.yml +++ b/.github/workflows/qemu-kvm-integration-tests.yml @@ -8,8 +8,6 @@ on: # yamllint disable-line rule:truthy types: - checks_requested push: - branches: - - main workflow_dispatch: permissions: @@ -35,13 +33,6 @@ jobs: # container - { image: "centos-9", env: "container-ansible-core-2.16" } - { image: "centos-9-bootc", env: "container-ansible-core-2.16" } - # broken on non-running dbus - # - { image: "centos-10", env: "container-ansible-core-2.17" } - - { image: "centos-10-bootc", env: "container-ansible-core-2.17" } - - { image: "fedora-41", env: "container-ansible-core-2.17" } - - { image: "fedora-42", env: "container-ansible-core-2.17" } - - { image: "fedora-41-bootc", env: "container-ansible-core-2.17" } - - { image: "fedora-42-bootc", env: "container-ansible-core-2.17" } env: TOX_ARGS: "--skip-tags tests::infiniband,tests::nvme,tests::scsi" diff --git a/defaults/main.yml b/defaults/main.yml index 370c84bc8..717488f71 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -31,8 +31,10 @@ network_provider_os_default: "{{ ansible_distribution_major_version is version('7', '<') else 'nm' }}" # If NetworkManager.service is running, assume that 'nm' is currently in-use, -# otherwise initscripts +# otherwise initscripts. However, in non-booted environments we don't have +# ansible_facts.services, so use the above OS default. __network_provider_current: "{{ + network_provider_os_default if ansible_facts.services is not defined else 'nm' if 'NetworkManager.service' in ansible_facts.services and ansible_facts.services['NetworkManager.service']['state'] == 'running' else 'initscripts' }}" @@ -136,6 +138,9 @@ __network_provider_setup: nm: service_name: "{{ __network_service_name_default_nm }}" packages: "{{ __network_packages_default_nm }}" + nm_offline: + service_name: "{{ __network_service_name_default_nm }}" + packages: "{{ __network_packages_default_nm }}" initscripts: service_name: "{{ __network_service_name_default_initscripts }}" packages: "{{ __network_packages_default_initscripts }}" diff --git a/library/network_connections.py b/library/network_connections.py index 574481e28..e86232910 100644 --- a/library/network_connections.py +++ b/library/network_connections.py @@ -71,6 +71,7 @@ import time import traceback import logging +import stat # pylint: disable=import-error, no-name-in-module from ansible.module_utils.basic import AnsibleModule @@ -1712,7 +1713,7 @@ def __init__(self): self._check_mode = None @property - def ifcfg_header(self): + def managed_file_header(self): return None def log( @@ -1728,7 +1729,7 @@ def log( ): raise NotImplementedError() - def run_command(self, argv, encoding=None): + def run_command(self, argv, encoding=None, check_rc=False): raise NotImplementedError() def _check_mode_changed(self, old_check_mode, new_check_mode, connections): @@ -1780,11 +1781,11 @@ def __init__(self): self.module = module @property - def ifcfg_header(self): + def managed_file_header(self): return self.module.params["__header"] - def run_command(self, argv, encoding=None): - return self.module.run_command(argv, encoding=encoding) + def run_command(self, argv, encoding=None, check_rc=False): + return self.module.run_command(argv, encoding=encoding, check_rc=check_rc) def _run_results_push(self, n_connections): c = [] @@ -1935,8 +1936,8 @@ def __init__( self._is_changed_modified_system = False self._debug_flags = debug_flags - def run_command(self, argv, encoding=None): - return self.run_env.run_command(argv, encoding=encoding) + def run_command(self, argv, encoding=None, check_rc=False): + return self.run_env.run_command(argv, encoding=encoding, check_rc=check_rc) @property def is_changed_modified_system(self): @@ -2030,6 +2031,8 @@ def log(self, idx, severity, msg, warn_traceback=False, force_fail=False): def create(provider, **kwargs): if provider == "nm": return Cmd_nm(**kwargs) + if provider == "nm_offline": + return Cmd_nm_offline(**kwargs) elif provider == "initscripts": return Cmd_initscripts(**kwargs) raise MyError("unsupported provider %s" % (provider)) @@ -2639,6 +2642,519 @@ def run_action_down(self, idx): ############################################################################### +class Cmd_nm_offline(Cmd): + def __init__(self, **kwargs): + Cmd.__init__(self, **kwargs) + self.validate_one_type = ArgValidator_ListConnections.VALIDATE_ONE_MODE_NM + self._checkpoint = None + + def profile_path(self, name): + return os.path.join( + "/etc/NetworkManager/system-connections", name + ".nmconnection" + ) + + def run_prepare(self): + # we can't check any hardware or runtime status, we can just trust the input + pass + + # mirror Cmd_nm.connection_create() + def connection_create(self, connections, idx): + connection = connections[idx] + # global/type independent arguments + if "nm.uuid" not in connection: + connection["nm.uuid"] = Util.create_uuid() + if "nm.exists" not in connection: + connection["nm.exists"] = True + argv = [ + "nmcli", + "--offline", + "connection", + "add", + "ifname", + connection["interface_name"], + "con-name", + connection["name"], + "type", + connection["type"], + "autoconnect", + "yes" if connection["autoconnect"] else "no", + "connection.autoconnect-retries", + str(connection["autoconnect_retries"]), + "connection.uuid", + connection["nm.uuid"], + ] + + if connection["cloned_mac"] != "default": + argv.extend(["cloned-mac", connection["cloned_mac"]]) + + # composite devices + if connection["controller"] is not None: + if connection["port_type"] is None: + self.log_error( + idx, + "connection.port-type must be specified when connection.controller is set", + ) + # must use uuid instead of name for controller here + controller_uuid = ArgUtil.connection_find_controller_uuid( + connection["controller"], connections + ) + + argv.extend( + [ + "connection.controller", + controller_uuid, + "connection.port-type", + connection["port_type"], + ] + ) + + # skip IP and other config for composites + return argv + + c_ip = connection["ip"] + ip4_addrs = [] + ip6_addrs = [] + for address in c_ip["address"]: + addr = "{0}/{1}".format(address["address"], address["prefix"]) + if address["family"] == socket.AF_INET: + ip4_addrs.append(addr) + elif address["family"] == socket.AF_INET6: + ip6_addrs.append(addr) + else: + self.log_error(idx, "unknown address family %s" % (address["family"])) + + argv.extend( + [ + "ipv4.method", + "auto" if c_ip["dhcp4"] else "manual" if ip4_addrs else "disabled", + "ipv4.addresses", + ", ".join(ip4_addrs), + "ipv6.method", + ( + "disabled" + if c_ip["ipv6_disabled"] + else ( + "auto" + if c_ip["auto6"] + else ( + "manual" + if ip6_addrs + else + # online backend uses legacy "ignore", DTRT for this new backend + "ignore" + ) + ) + ), # "link-local", + "ipv6.addresses", + ", ".join(ip6_addrs), + ] + ) + + # gateway + if c_ip["gateway4"]: + argv.extend(["ipv4.gateway", c_ip["gateway4"]]) + if c_ip["gateway6"]: + argv.extend(["ipv6.gateway", c_ip["gateway6"]]) + + # dns* + dns4_addrs = [] + dns6_addrs = [] + for dns in c_ip["dns"]: + if dns["family"] == socket.AF_INET: + dns4_addrs.append(dns["address"]) + elif dns["family"] == socket.AF_INET6: + dns6_addrs.append(dns["address"]) + else: + self.log_error(idx, "unknown DNS address family %s" % (dns["family"])) + if dns4_addrs: + argv.extend(["ipv4.dns", ",".join(dns4_addrs)]) + if dns6_addrs: + argv.extend(["ipv6.dns", ",".join(dns6_addrs)]) + + if c_ip["dns_search"]: + # NM only allows to configure ipvN.dns-search when IPvN is enabled + if c_ip["dhcp4"] or ip4_addrs: + argv.extend(["ipv4.dns-search", " ".join(c_ip["dns_search"])]) + if c_ip["auto6"] or ip6_addrs: + argv.extend(["ipv6.dns-search", " ".join(c_ip["dns_search"])]) + + if c_ip["dns_options"]: + argv.extend( + [ + "ipv4.dns-options", + ",".join(c_ip["dns_options"]), + "ipv6.dns-options", + ",".join(c_ip["dns_options"]), + ] + ) + + if c_ip["dns_priority"] != 0: + argv.extend( + [ + "ipv4.dns-priority", + str(c_ip["dns_priority"]), + "ipv6.dns-priority", + str(c_ip["dns_priority"]), + ] + ) + + if c_ip["ipv4_ignore_auto_dns"] is not None: + argv.extend( + [ + "ipv4.ignore-auto-dns", + "yes" if c_ip["ipv4_ignore_auto_dns"] else "no", + ] + ) + if c_ip["ipv6_ignore_auto_dns"] is not None: + argv.extend( + [ + "ipv6.ignore-auto-dns", + "yes" if c_ip["ipv6_ignore_auto_dns"] else "no", + ] + ) + + # route + if c_ip["route_metric4"] is not None: + argv.extend(["ipv4.route-metric", str(c_ip["route_metric4"])]) + if c_ip["route_metric6"] is not None: + argv.extend(["ipv6.route-metric", str(c_ip["route_metric6"])]) + + # routes + if c_ip.get("route"): + ipv4_routes = [] + ipv6_routes = [] + for route in c_ip["route"]: + route_str = route["network"] + if route.get("prefix"): + route_str += "/" + str(route["prefix"]) + if route.get("gateway"): + route_str += " " + route["gateway"] + if route.get("metric"): + route_str += " " + str(route["metric"]) + if route.get("type"): + route_str += " type=" + route["type"] + if route.get("table"): + route_str += " table=" + str(route["table"]) + if route.get("src"): + route_str += " src=" + route["src"] + + if route["family"] == socket.AF_INET: + ipv4_routes.append(route_str) + elif route["family"] == socket.AF_INET6: + ipv6_routes.append(route_str) + + if ipv4_routes: + argv.extend(["ipv4.routes", ",".join(ipv4_routes)]) + if ipv6_routes: + argv.extend(["ipv6.routes", ",".join(ipv6_routes)]) + + # routing rules + if c_ip.get("routing_rule"): + ipv4_rules = [] + ipv6_rules = [] + for rule in c_ip["routing_rule"]: + rule_parts = [] + if rule.get("priority"): + rule_parts.append("priority " + rule["priority"]) + if rule.get("from"): + rule_parts.append("from " + rule["from"]) + if rule.get("to"): + rule_parts.append("to " + rule["to"]) + if rule.get("table"): + rule_parts.append("table " + rule["table"]) + + if rule_parts: + rule_str = " ".join(rule_parts) + if rule["family"] == socket.AF_INET: + ipv4_rules.append(rule_str) + elif rule["family"] == socket.AF_INET6: + ipv6_rules.append(rule_str) + + if ipv4_rules: + argv.extend(["ipv4.routing-rules", " ".join(ipv4_rules)]) + if ipv6_rules: + argv.extend(["ipv6.routing-rules", " ".join(ipv6_rules)]) + + # DHCP options + if c_ip.get("dhcp4_send_hostname") is not None: + argv.extend( + [ + "ipv4.dhcp-send-hostname", + "yes" if c_ip["dhcp4_send_hostname"] else "no", + ] + ) + if c_ip.get("dhcp6_send_hostname") is not None: + argv.extend( + [ + "ipv6.dhcp-send-hostname", + "yes" if c_ip["dhcp6_send_hostname"] else "no", + ] + ) + + # zone + if connection.get("zone"): + argv.extend(["connection.zone", connection["zone"]]) + + # mac address + if connection.get("mac") and connection["mac"] != "default": + if connection["type"] == "wireless": + argv.extend(["802-11-wireless.mac-address", connection["mac"]]) + else: + argv.extend(["802-3-ethernet.mac-address", connection["mac"]]) + + # mtu + if connection.get("mtu"): + if connection["type"] == "wireless": + argv.extend(["802-11-wireless.mtu", str(connection["mtu"])]) + else: + argv.extend(["802-3-ethernet.mtu", str(connection["mtu"])]) + + # ethernet settings + if connection.get("ethernet"): + eth = connection["ethernet"] + if eth.get("autoneg") is not None: + argv.extend( + ["802-3-ethernet.auto-negotiate", "yes" if eth["autoneg"] else "no"] + ) + if eth.get("speed"): + argv.extend(["802-3-ethernet.speed", str(eth["speed"])]) + if eth.get("duplex"): + argv.extend(["802-3-ethernet.duplex", eth["duplex"]]) + + # type-specific configurations + # bond options[mode, miimon, downdelay, updelay, arp_interval, arp_ip_target, arp_validate, balance-slb, primary, + # primary_reselect, fail_over_mac, use_carrier, ad_select, xmit_hash_policy, resend_igmp, lacp_rate, active_slave, ad_actor_sys_prio, + # ad_actor_system, ad_user_port_key, all_slaves_active, arp_all_targets, min_links, num_grat_arp, num_unsol_na, packets_per_slave, + # tlb_dynamic_lb, lp_interval, peer_notif_delay, arp_missed_max, lacp_active, ns_ip6_target]., + if connection["type"] == "bond": + opts = [] + for key, value in connection["bond"].items(): + if value is not None: + if key in ["all_ports_active", "use_carrier", "tlb_dynamic_lb"]: + value = int(value) + if key in ["all_ports_active", "packets_per_port"]: + # wokeignore:rule=slave + key = key.replace("port", "slave") + opts.append("{0}={1}".format(key, str(value))) + if opts: + argv.extend(["bond.options", ",".join(opts)]) + + elif connection["type"] == "bridge": + if connection.get("bridge"): + bridge = connection["bridge"] + if bridge.get("stp") is not None: + argv.extend(["bridge.stp", "yes" if bridge["stp"] else "no"]) + if bridge.get("priority") is not None: + argv.extend(["bridge.priority", str(bridge["priority"])]) + if bridge.get("forward_delay") is not None: + argv.extend(["bridge.forward-delay", str(bridge["forward_delay"])]) + if bridge.get("hello_time") is not None: + argv.extend(["bridge.hello-time", str(bridge["hello_time"])]) + if bridge.get("max_age") is not None: + argv.extend(["bridge.max-age", str(bridge["max_age"])]) + if bridge.get("ageing_time") is not None: + argv.extend(["bridge.ageing-time", str(bridge["ageing_time"])]) + + elif connection["type"] == "vlan": + if connection.get("vlan") and connection["vlan"].get("id") is not None: + argv.extend(["vlan.id", str(connection["vlan"]["id"])]) + if connection.get("parent"): + argv.extend(["vlan.parent", connection["parent"]]) + + elif connection["type"] == "macvlan": + if connection.get("macvlan"): + macvlan = connection["macvlan"] + if macvlan.get("mode"): + argv.extend(["macvlan.mode", macvlan["mode"]]) + if macvlan.get("promiscuous") is not None: + argv.extend( + [ + "macvlan.promiscuous", + "yes" if macvlan["promiscuous"] else "no", + ] + ) + if macvlan.get("tap") is not None: + argv.extend(["macvlan.tap", "yes" if macvlan["tap"] else "no"]) + if connection.get("parent"): + argv.extend(["macvlan.parent", connection["parent"]]) + + elif connection["type"] == "infiniband": + if connection.get("infiniband"): + ib = connection["infiniband"] + if ib.get("transport_mode"): + argv.extend(["infiniband.transport-mode", ib["transport_mode"]]) + if ib.get("p_key") is not None: + argv.extend(["infiniband.p-key", str(ib["p_key"])]) + if connection.get("parent"): + argv.extend(["infiniband.parent", connection["parent"]]) + + elif connection["type"] == "wireless": + if connection.get("wireless"): + wifi = connection["wireless"] + if wifi.get("ssid"): + argv.extend(["802-11-wireless.ssid", wifi["ssid"]]) + if wifi.get("key_mgmt"): + argv.extend(["802-11-wireless-security.key-mgmt", wifi["key_mgmt"]]) + if wifi.get("password") and wifi["key_mgmt"] in ["wpa-psk", "sae"]: + argv.extend(["802-11-wireless-security.psk", wifi["password"]]) + + elif connection["type"] == "team": + if connection.get("team") and connection["team"].get("config"): + # Team config is typically JSON, pass as-is + argv.extend(["team.config", connection["team"]["config"]]) + + # ethtool settings + if connection.get("ethtool"): + ethtool = connection["ethtool"] + + # ethtool features + if ethtool.get("features"): + for feature, value in ethtool["features"].items(): + if value is not None: + feature_name = feature.replace("_", "-") + if value: + value = "on" + else: + value = "off" + argv.extend(["ethtool.feature-" + feature_name, value]) + + # ethtool coalesce settings + if ethtool.get("coalesce"): + for param, value in ethtool["coalesce"].items(): + if value is not None: + param_name = param.replace("_", "-") + argv.extend(["ethtool.coalesce-" + param_name, str(value)]) + + # ethtool ring settings + if ethtool.get("ring"): + for param, value in ethtool["ring"].items(): + if value is not None: + param_name = param.replace("_", "-") + argv.extend(["ethtool.ring-" + param_name, str(value)]) + + # ieee802_1x settings + if connection.get("ieee802_1x"): + ieee = connection["ieee802_1x"] + if ieee.get("eap"): + argv.extend( + [ + "802-1x.eap", + ( + ",".join(ieee["eap"]) + if isinstance(ieee["eap"], list) + else ieee["eap"] + ), + ] + ) + if ieee.get("identity"): + argv.extend(["802-1x.identity", ieee["identity"]]) + if ieee.get("password"): + argv.extend(["802-1x.password", ieee["password"]]) + if ieee.get("ca_cert"): + argv.extend(["802-1x.ca-cert", ieee["ca_cert"]]) + if ieee.get("client_cert"): + argv.extend(["802-1x.client-cert", ieee["client_cert"]]) + if ieee.get("private_key"): + argv.extend(["802-1x.private-key", ieee["private_key"]]) + if ieee.get("private_key_password"): + argv.extend( + ["802-1x.private-key-password", ieee["private_key_password"]] + ) + + # match settings + if connection.get("match"): + match = connection["match"] + if match.get("path"): + match_paths = ( + match["path"] + if isinstance(match["path"], list) + else [match["path"]] + ) + argv.extend(["match.path", ",".join(match_paths)]) + if match.get("driver"): + match_drivers = ( + match["driver"] + if isinstance(match["driver"], list) + else [match["driver"]] + ) + argv.extend(["match.driver", ",".join(match_drivers)]) + if match.get("interface_name"): + match_names = ( + match["interface_name"] + if isinstance(match["interface_name"], list) + else [match["interface_name"]] + ) + argv.extend(["match.interface-name", ",".join(match_names)]) + + return argv + + def run_action_present(self, idx): + connection = self.connections[idx] + + if not connection.get("type"): + # this is mostly test teardown, nobody uses that in container builds + if connection["state"] == "down": + self.log_info(idx, "nm_offline ignoring 'state: down'") + return + + self.log_error(idx, "Connection 'type' not specified") + return + + # DEBUG, drop for final commit + self.log_info( + idx, "XXX nm_offline provider action_present connection: %r" % connection + ) + + # create the profile + (rc, out, err) = self.run_command( + self.connection_create(self.connections, idx), check_rc=True + ) + # Should Not Happen™, but make sure + if not out.strip(): + self.log_error( + idx, "nmcli --offline returned no output (rc %d); err: %s" % (rc, err) + ) + return + + path = self.profile_path(connection["name"]) + if self.check_mode == CheckMode.REAL_RUN: + with open(path, "w") as f: + f.write(self.run_env.managed_file_header) + f.write(out.decode("UTF-8")) + os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) + os.chown(path, 0, 0) + + # nmcli always generates a new UUID, so comparing with existing file is moot + # always treat as changed, good enough for container builds + self.connections_data_set_changed(idx) + + def run_action_absent(self, idx): + connection = self.connections[idx] + # DEBUG, drop for final commit + self.log_info( + idx, "XXX nm_offline provider action_absent connection: %r" % connection + ) + + try: + os.unlink(self.profile_path(connection["name"])) + self.connections_data_set_changed(idx) + except FileNotFoundError: + self.log_debug( + idx, "nm_offline: profile '%s' already absent" % connection["name"] + ) + + def run_action_up(self, idx): + # no runtime ops in offline provider + pass + + def run_action_down(self, idx): + # no runtime ops in offline provider + pass + + +############################################################################### + + class Cmd_initscripts(Cmd): def __init__(self, **kwargs): Cmd.__init__(self, **kwargs) @@ -2763,7 +3279,7 @@ def run_action_present(self, idx): ) new_content = IfcfgUtil.content_from_dict( - ifcfg_all, header=self.run_env.ifcfg_header + ifcfg_all, header=self.run_env.managed_file_header ) if old_content == new_content: diff --git a/meta/main.yml b/meta/main.yml index 5b75bd14d..add6d55c0 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -18,6 +18,7 @@ galaxy_info: - "9" galaxy_tags: - centos + - containerbuild - el6 - el7 - el8 diff --git a/tasks/main.yml b/tasks/main.yml index 070eeef61..bc3462a6a 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -4,6 +4,13 @@ - name: Ensure ansible_facts used by role include_tasks: tasks/set_facts.yml +- name: Switch to offline NM backend if host is not booted + set_fact: + network_provider: "nm_offline" + when: + - network_provider == "nm" + - not __network_is_booted + - name: Print network provider debug: msg: "Using network provider: {{ network_provider }}" @@ -14,7 +21,7 @@ msg: Only the `nm` provider supports using the `network_state` variable when: - network_state != {} - - network_provider == "initscripts" + - network_provider != "nm" - name: Abort applying the network state configuration if the system version of the managed host is below 8 @@ -151,10 +158,10 @@ - name: Enable and start NetworkManager service: name: "{{ network_service_name }}" - state: started + state: "{{ 'started' if __network_is_booted else omit }}" enabled: true when: - - network_provider == "nm" or network_state != {} + - network_provider in ["nm", "nm_offline"] or network_state != {} no_log: true # If any 802.1x connections are used, the wpa_supplicant @@ -162,10 +169,10 @@ - name: Enable and start wpa_supplicant service: name: wpa_supplicant - state: started + state: "{{ 'started' if __network_is_booted else omit }}" enabled: true when: - - network_provider == "nm" + - network_provider in ["nm", "nm_offline"] - __network_wpa_supplicant_required - name: Enable network service diff --git a/tasks/set_facts.yml b/tasks/set_facts.yml index 424a1a5ad..a3376575f 100644 --- a/tasks/set_facts.yml +++ b/tasks/set_facts.yml @@ -19,6 +19,27 @@ set_fact: __network_is_ostree: "{{ __ostree_booted_stat.stat.exists }}" +- name: Determine if system is booted with systemd + when: __network_is_booted is not defined + block: + - name: Run systemctl + # noqa command-instead-of-module + command: systemctl is-system-running + register: __is_system_running + changed_when: false + check_mode: false + failed_when: false + + - name: Require installed systemd + fail: + msg: "Error: This role requires systemd to be installed." + when: '"No such file or directory" in __is_system_running.msg | d("")' + + - name: Set flag to indicate that systemd runtime operations are available + set_fact: + # see https://www.man7.org/linux/man-pages/man1/systemctl.1.html#:~:text=is-system-running%20output + __network_is_booted: "{{ __is_system_running.stdout != 'offline' }}" + - name: Check which services are running service_facts: no_log: true diff --git a/tests/ansible.cfg b/tests/ansible.cfg index 8b8ffd890..e9225efdc 100644 --- a/tests/ansible.cfg +++ b/tests/ansible.cfg @@ -1,2 +1,2 @@ [defaults] -task_timeout=480 +task_timeout=600 diff --git a/tests/collection-requirements.yml b/tests/collection-requirements.yml new file mode 100644 index 000000000..afc836d72 --- /dev/null +++ b/tests/collection-requirements.yml @@ -0,0 +1,3 @@ +--- +collections: + - name: community.general diff --git a/tests/playbooks/tests_802_1x.yml b/tests/playbooks/tests_802_1x.yml index 8f922aa9b..f0a26514b 100644 --- a/tests/playbooks/tests_802_1x.yml +++ b/tests/playbooks/tests_802_1x.yml @@ -5,21 +5,14 @@ vars: interface: 802-1x-test tasks: - - name: "INIT: 802.1x tests" - debug: - msg: "##################################################" - - name: Include the task 'setup_802.1x.yml' - include_tasks: tasks/setup_802.1x.yml - - name: Test configuring 802.1x authentication - block: - - name: "TEST: 802.1x profile with private key password and ca cert" - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network - vars: - network_connections: + - name: Test setting 802.1x authentication + include_tasks: tasks/run_test.yml + vars: + lsr_description: Test 802.1x authentication + lsr_setup: + - tasks/setup_802.1x.yml + lsr_test: + - network_connections: - name: "{{ interface }}" interface_name: veth2 state: up @@ -38,28 +31,25 @@ - none client_cert: /etc/pki/tls/client.pem ca_cert: /etc/pki/tls/cacert.pem - - name: Ensure ping command is present - package: - name: iputils - state: present - use: "{{ (__network_is_ostree | d(false)) | - ternary('ansible.posix.rhel_rpm_ostree', omit) }}" - - name: "TEST: I can ping the EAP server" - command: ping -c1 203.0.113.1 - changed_when: false - - name: Import network role - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - persistent_state: absent - state: down - - name: >- - TEST: 802.1x profile with unencrypted private key, - domain suffix match, and system ca certs - debug: - msg: "##################################################" + lsr_assert: + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_command: ping -c1 203.0.113.1 + lsr_packages: [iputils] + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted and not __bootc_validation | default(false) }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - tasks/check_network_dns.yml + + - name: Stop test if building image or validation is enabled + meta: end_host + when: ansible_connection | d("") == "buildah" or __bootc_validation | default(false) + + - name: >- + Test 802.1x profile with unencrypted private key, domain suffix match, and system ca certs + block: - name: Copy cacert to system truststore copy: src: cacert.pem diff --git a/tests/playbooks/tests_auto_gateway.yml b/tests/playbooks/tests_auto_gateway.yml index 28f595213..c0da0548a 100644 --- a/tests/playbooks/tests_auto_gateway.yml +++ b/tests/playbooks/tests_auto_gateway.yml @@ -6,145 +6,97 @@ type: veth interface: veth0 tasks: - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml + - name: Test setting auto_gateway to true + include_tasks: tasks/run_test.yml vars: - state: present - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - name: >- - TEST: I can configure an interface with auto_gateway enabled - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + lsr_description: Test auto_gateway setting to true + lsr_setup: + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + auto_gateway: true + dhcp4: false + auto6: false + address: + - "2001:db8::2/64" + - "203.0.113.2/24" + gateway6: "2001:db8::1" + gateway4: "203.0.113.1" + # change the default route metric to higher value so that it will + # not take precedence over other routes or not ignore other + # routes + route_metric4: 65535 + lsr_assert: + - tasks/assert_device_present.yml + - what: tasks/assert_profile_present.yml + profile: "{{ interface }}" + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_command: ip route + lsr_stdout: default via 203.0.113.1 dev {{ interface }} + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted and network_provider == 'nm' }}" + lsr_command: ip -6 route + lsr_stdout: default via 2001:db8::1 dev {{ interface }} + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - what: tasks/manage_test_interface.yml + state: absent + - tasks/check_network_dns.yml + + - name: Stop test if building image or validation is enabled + meta: end_host + when: ansible_connection | d("") == "buildah" or __bootc_validation | default(false) + + - name: Test setting auto_gateway to false + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - auto_gateway: true - dhcp4: false - auto6: false - address: - - "2001:db8::2/64" - - "203.0.113.2/24" - gateway6: "2001:db8::1" - gateway4: "203.0.113.1" - # change the default route metric to higher value so that it will - # not take precedence over other routes or not ignore other - # routes - route_metric4: 65535 - - name: Include the task 'assert_device_present.yml' again - include_tasks: tasks/assert_device_present.yml - - name: Include the task 'assert_profile_present.yml' - include_tasks: tasks/assert_profile_present.yml - vars: - profile: "{{ interface }}" - - name: "Show ipv4 routes" - command: "ip route" - register: ipv4_routes - changed_when: false - - name: "Assert default ipv4 route is present" - assert: - that: __test_str in ipv4_routes.stdout - vars: - __test_str: default via 203.0.113.1 dev {{ interface }} - - name: "Get ipv6 routes" - command: "ip -6 route" - register: ipv6_route - changed_when: false - - name: "Assert default ipv6 route is present" - assert: - that: __test_str in ipv6_route.stdout - vars: - __test_str: default via 2001:db8::1 dev {{ interface }} - when: network_provider == "nm" - - name: "TEARDOWN: remove profiles." - debug: - msg: "##################################################" - - name: Import network role to remove interface - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - persistent_state: absent - state: down - ignore_errors: true # noqa ignore-errors - - name: Include the task 'manage_test_interface.yml' to remove interface - include_tasks: tasks/manage_test_interface.yml - vars: - state: absent - - name: >- - TEST: I can configure an interface with auto_gateway disabled - debug: - msg: "##################################################" - - name: Include the task 'manage_test_interface.yml' to disable auto_gateway - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Import network role to disable auto_gateway - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - auto_gateway: false - dhcp4: false - auto6: false - address: - - "2001:db8::2/64" - - "203.0.113.2/24" - gateway6: "2001:db8::1" - gateway4: "203.0.113.1" - - name: Include the task 'assert_device_present.yml' - 3 - include_tasks: tasks/assert_device_present.yml - - name: Include the task 'assert_profile_present.yml' again - include_tasks: tasks/assert_profile_present.yml - vars: - profile: "{{ interface }}" - - name: "Show ipv4 routes again" - command: "ip route" - register: ipv4_routes - changed_when: false - - name: "Assert default ipv4 route is absent" - assert: - that: __test_str not in ipv4_routes.stdout - vars: - __test_str: default via 203.0.113.1 dev {{ interface }} - - name: "Get ipv6 routes again" - command: "ip -6 route" - register: ipv6_route - changed_when: false - - name: "Assert default ipv6 route is absent" - assert: - that: __test_str not in ipv6_route.stdout - vars: - __test_str: default via 2001:db8::1 dev {{ interface }} - when: network_provider == "nm" - - name: "TEARDOWN: remove profiles. again" - debug: - msg: "##################################################" - - name: Import network role to remove interface again - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - persistent_state: absent - state: down - ignore_errors: true # noqa ignore-errors - - name: Include the task 'manage_test_interface.yml' to remove interface again - include_tasks: tasks/manage_test_interface.yml - vars: - state: absent - - name: Verify network state restored to default - include_tasks: tasks/check_network_dns.yml + lsr_description: Test auto_gateway setting to false + lsr_setup: + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + auto_gateway: false + dhcp4: false + auto6: false + address: + - "2001:db8::2/64" + - "203.0.113.2/24" + gateway6: "2001:db8::1" + gateway4: "203.0.113.1" + lsr_assert: + - tasks/assert_device_present.yml + lsr_assert_when: + - what: tasks/assert_profile_present.yml + profile: "{{ interface }}" + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_command: ip route + lsr_not_stdout: default via 203.0.113.1 dev {{ interface }} + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted and network_provider == 'nm' }}" + lsr_command: ip -6 route + lsr_not_stdout: default via 2001:db8::1 dev {{ interface }} + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - what: tasks/manage_test_interface.yml + state: absent + - tasks/check_network_dns.yml diff --git a/tests/playbooks/tests_bond.yml b/tests/playbooks/tests_bond.yml index 348207783..17307d601 100644 --- a/tests/playbooks/tests_bond.yml +++ b/tests/playbooks/tests_bond.yml @@ -72,26 +72,85 @@ - "{{ controller_profile }}" - "{{ port1_profile }}" - "{{ port2_profile }}" - - name: "** TEST check polling interval" - command: grep 'Polling Interval' - /proc/net/bonding/{{ controller_device }} - register: result - until: "'110' in result.stdout" - changed_when: false - - name: "** TEST check IPv4" - command: ip -4 a s {{ controller_device }} - register: result - until: "'192.0.2' in result.stdout" - retries: 20 - delay: 2 - changed_when: false - - name: "** TEST check IPv6" - command: ip -6 a s {{ controller_device }} - register: result - until: "'2001' in result.stdout" - retries: 20 - delay: 2 - changed_when: false + + - name: Runtime checks for booted systems + when: __network_is_booted | bool + block: + - name: "** TEST check polling interval" + command: grep 'Polling Interval' + /proc/net/bonding/{{ controller_device }} + register: result + until: "'110' in result.stdout" + changed_when: false + - name: "** TEST check IPv4" + command: ip -4 a s {{ controller_device }} + register: result + until: "'192.0.2' in result.stdout" + retries: 20 + delay: 2 + changed_when: false + - name: "** TEST check IPv6" + command: ip -6 a s {{ controller_device }} + register: result + until: "'2001' in result.stdout" + retries: 20 + delay: 2 + changed_when: false + + # These are primarily interesting for non-booted systems; but let's + # check on booted systems too, to ensure the assertions are valid + - name: NM Config file checks + when: + - network_provider != "initscripts" + - ansible_distribution_major_version | int >= 9 + block: + - name: Read controller config + slurp: + src: "/etc/NetworkManager/system-connections/{{ controller_profile }}.nmconnection" + register: controller_config_b64 + + - name: Check controller config + assert: + that: + # [connection] + - "'id=' + controller_profile in controller_config" + - "'type=bond' in controller_config" + - "'interface-name=' + controller_device in controller_config" + # [bond] + - "'mode=active-backup' in controller_config" + - "'miimon=110' in controller_config" + # [ipv4] + - "'method=auto' in controller_config" + - "'route-metric=65535' in controller_config" + fail_msg: "{{ controller_profile }} is bad: {{ controller_config }}" + vars: + controller_config: "{{ controller_config_b64.content | b64decode }}" + + - name: Read port configs + loop: + - { name: "{{ port1_profile }}", iface_name: "{{ dhcp_interface1 }}" } + - { name: "{{ port2_profile }}", iface_name: "{{ dhcp_interface2 }}" } + slurp: + src: "/etc/NetworkManager/system-connections/{{ item.name }}.nmconnection" + register: port1_config_b64 + + - name: Check port configs + loop: "{{ port1_config_b64.results }}" + vars: + port_config: "{{ item.content | b64decode }}" + assert: + that: + # [connection] + - "'id=' + item.item.name in port_config" + - "'type=ethernet' in port_config" + # that points to UUID of controller, a bit cumbersome to match; but let's assume nmcli DTRT + - "'controller=' in port_config" + - "'interface-name=' + item.item.iface_name in port_config" + - "'port-type=bond' in port_config" + - "'[ipv4]' not in port_config" + - "'[ipv6]' not in port_config" + fail_msg: "{{ item.item.name }} is bad: {{ port_config }}" + always: - name: Clean up the test devices and the connection profiles tags: @@ -116,6 +175,7 @@ command: ip link del {{ controller_device }} failed_when: false changed_when: false + when: __network_is_booted | bool - name: Import the task 'remove_test_interfaces_with_dhcp.yml' import_tasks: tasks/remove_test_interfaces_with_dhcp.yml - name: "Restore the /etc/resolv.conf for initscript" @@ -125,3 +185,4 @@ changed_when: false - name: Verify network state restored to default include_tasks: tasks/check_network_dns.yml + when: __network_is_booted | bool diff --git a/tests/playbooks/tests_bond_cloned_mac.yml b/tests/playbooks/tests_bond_cloned_mac.yml index 511ff0e8d..45d3190f3 100644 --- a/tests/playbooks/tests_bond_cloned_mac.yml +++ b/tests/playbooks/tests_bond_cloned_mac.yml @@ -54,54 +54,80 @@ interface_name: "{{ dhcp_interface2 }}" controller: "{{ controller_profile }}" - - name: Verify nmcli cloned-mac-address entry - command: >- - nmcli -f 802-3-ethernet.cloned-mac-address con show {{ item.name }} - register: cloned_mac_address - ignore_errors: true - changed_when: false - loop: - - {name: "{{ controller_profile }}", mac: "12:23:34:45:56:60"} - - {name: "{{ port1_profile }}", mac: "12:23:34:45:56:61"} - - {name: "{{ port2_profile }}", mac: "--"} + - name: Verify nm provider when: network_provider == 'nm' + block: + - name: Verify nmcli cloned-mac-address entry + command: >- + nmcli -f 802-3-ethernet.cloned-mac-address con show {{ item.name }} + register: cloned_mac_address + ignore_errors: true + changed_when: false + loop: + - {name: "{{ controller_profile }}", mac: "12:23:34:45:56:60"} + - {name: "{{ port1_profile }}", mac: "12:23:34:45:56:61"} + - {name: "{{ port2_profile }}", mac: "--"} - - name: > - Assert that cloned-mac-address addresses are configured correctly - assert: - that: - - item.stdout.endswith(item.item.mac) - msg: cloned-mac-address is configured incorrectly - loop: "{{ cloned_mac_address.results }}" - when: network_provider == 'nm' + - name: > + Assert that cloned-mac-address addresses are configured correctly + assert: + that: + - item.stdout.endswith(item.item.mac) + msg: cloned-mac-address is configured incorrectly + loop: "{{ cloned_mac_address.results }}" - - name: Verify the MAC address in {{ controller_profile }} - command: >- - grep 'MACADDR' - /etc/sysconfig/network-scripts/ifcfg-{{ controller_profile }} - register: mac_address_controller - ignore_errors: true - changed_when: false - when: network_provider == 'initscripts' + # mostly interesting for offline provider, but let's cross-check with + # online NM to ensure the conditions are valid - except that on some + # older versions of NM, the connection files are not created, so we + # skip this test on those versions. + - name: Verify NM config files + when: + - network_provider.startswith('nm') + - ansible_facts['distribution_major_version'] | int >= 9 + block: + - name: Read profile config files + slurp: + src: "/etc/NetworkManager/system-connections/{{ item }}.nmconnection" + register: config_b64 + loop: + - "{{ controller_profile }}" + - "{{ port1_profile }}" + - "{{ port2_profile }}" - - name: Verify the MAC address in {{ port1_profile }} - command: >- - grep 'MACADDR' - /etc/sysconfig/network-scripts/ifcfg-{{ port1_profile }} - register: mac_address_port1 - ignore_errors: true - changed_when: false - when: network_provider == 'initscripts' + - name: Check profile config files + assert: + that: + - "'cloned-mac-address=12:23:34:45:56:60' in config_b64.results[0].content | b64decode" + - "'cloned-mac-address=12:23:34:45:56:61' in config_b64.results[1].content | b64decode" + - "'cloned-mac-adress=' not in config_b64.results[2].content | b64decode" - - name: Assert that MAC addresses are configured correctly for bonding - interface - assert: - that: - - mac_address_controller.stdout is search("12:23:34:45:56:60") - - mac_address_port1.stdout is search("12:23:34:45:56:61") - msg: the MAC addresses are configured incorrectly for bonding - interface + - name: Verify initscripts provider when: network_provider == 'initscripts' + block: + - name: Verify the MAC address in {{ controller_profile }} + command: >- + grep 'MACADDR' + /etc/sysconfig/network-scripts/ifcfg-{{ controller_profile }} + register: mac_address_controller + ignore_errors: true + changed_when: false + + - name: Verify the MAC address in {{ port1_profile }} + command: >- + grep 'MACADDR' + /etc/sysconfig/network-scripts/ifcfg-{{ port1_profile }} + register: mac_address_port1 + ignore_errors: true + changed_when: false + + - name: Assert that MAC addresses are configured correctly for bonding + interface + assert: + that: + - mac_address_controller.stdout is search("12:23:34:45:56:60") + - mac_address_port1.stdout is search("12:23:34:45:56:61") + msg: the MAC addresses are configured incorrectly for bonding + interface always: - name: Clean up the test devices and the connection profiles @@ -127,8 +153,10 @@ command: ip link del {{ controller_device }} failed_when: false changed_when: false + when: __network_is_booted | bool - name: Import the task 'remove_test_interfaces_with_dhcp.yml' import_tasks: tasks/remove_test_interfaces_with_dhcp.yml + when: __network_is_booted | bool - name: Restore the /etc/resolv.conf for initscript command: mv -vf /etc/resolv.conf.bak /etc/resolv.conf when: diff --git a/tests/playbooks/tests_bond_options.yml b/tests/playbooks/tests_bond_options.yml index 73bfc2435..dd86cf97d 100644 --- a/tests/playbooks/tests_bond_options.yml +++ b/tests/playbooks/tests_bond_options.yml @@ -11,6 +11,7 @@ dhcp_interface2: test2 lsr_fail_debug: - __network_connections_result + - __install_status bond_options_to_assert: - {key: 'mode', value: '802.3ad'} - {key: 'ad_actor_sys_prio', value: '65535'} @@ -50,7 +51,44 @@ - tasks/create_test_interfaces_with_dhcp.yml - tasks/assert_dhcp_device_present.yml lsr_test: - - tasks/create_bond_profile.yml + - network_connections: + # Create a bond controller + - name: "{{ controller_profile }}" + state: up + type: bond + interface_name: "{{ controller_device }}" + bond: + mode: 802.3ad + ad_actor_sys_prio: 65535 + ad_actor_system: 00:00:5e:00:53:5d + ad_select: stable + ad_user_port_key: 1023 + all_ports_active: true + downdelay: 0 + lacp_rate: slow + lp_interval: 128 + miimon: 110 + min_links: 0 + num_grat_arp: 64 + primary_reselect: better + resend_igmp: 225 + updelay: 0 + use_carrier: true + xmit_hash_policy: encap2+3 + ip: + route_metric4: 65535 + # add an ethernet to the bond + - name: "{{ port1_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface1 }}" + controller: "{{ controller_profile }}" + # add a second ethernet to the bond + - name: "{{ port2_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface2 }}" + controller: "{{ controller_profile }}" lsr_assert: - tasks/assert_controller_device_present.yml - tasks/assert_bond_port_profile_present.yml @@ -59,6 +97,10 @@ - tasks/cleanup_bond_profile+device.yml - tasks/remove_test_interfaces_with_dhcp.yml + - name: Stop test if building image or validation is enabled + meta: end_host + when: ansible_connection | d("") == "buildah" or __bootc_validation | default(false) + - name: "Reset bond options to assert" set_fact: bond_options_to_assert: @@ -83,7 +125,32 @@ - tasks/create_test_interfaces_with_dhcp.yml - tasks/assert_dhcp_device_present.yml lsr_test: - - tasks/create_bond_profile_reconfigure.yml + - network_connections: + # Create a bond controller + - name: "{{ controller_profile }}" + state: up + type: bond + interface_name: "{{ controller_device }}" + bond: + mode: active-backup + arp_interval: 60 + arp_ip_target: 192.0.2.128 + arp_validate: none + primary: "{{ dhcp_interface1 }}" + ip: + route_metric4: 65535 + # add an ethernet to the bond + - name: "{{ port1_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface1 }}" + controller: "{{ controller_profile }}" + # add a second ethernet to the bond + - name: "{{ port2_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface2 }}" + controller: "{{ controller_profile }}" lsr_assert: - tasks/assert_bond_options.yml lsr_cleanup: diff --git a/tests/playbooks/tests_bond_port_match_by_mac.yml b/tests/playbooks/tests_bond_port_match_by_mac.yml index a66616b24..6d69f7d15 100644 --- a/tests/playbooks/tests_bond_port_match_by_mac.yml +++ b/tests/playbooks/tests_bond_port_match_by_mac.yml @@ -29,7 +29,44 @@ - tasks/create_test_interfaces_with_dhcp.yml - tasks/assert_dhcp_device_present.yml lsr_test: - - tasks/create_bond_profile.yml + - network_connections: + # Create a bond controller + - name: "{{ controller_profile }}" + state: up + type: bond + interface_name: "{{ controller_device }}" + bond: + mode: 802.3ad + ad_actor_sys_prio: 65535 + ad_actor_system: 00:00:5e:00:53:5d + ad_select: stable + ad_user_port_key: 1023 + all_ports_active: true + downdelay: 0 + lacp_rate: slow + lp_interval: 128 + miimon: 110 + min_links: 0 + num_grat_arp: 64 + primary_reselect: better + resend_igmp: 225 + updelay: 0 + use_carrier: true + xmit_hash_policy: encap2+3 + ip: + route_metric4: 65535 + # add an ethernet to the bond + - name: "{{ port1_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface1 }}" + controller: "{{ controller_profile }}" + # add a second ethernet to the bond + - name: "{{ port2_profile }}" + state: up + type: ethernet + interface_name: "{{ dhcp_interface2 }}" + controller: "{{ controller_profile }}" - tasks/create_bond_port_match_by_mac.yml lsr_assert: - tasks/assert_controller_device_present.yml diff --git a/tests/playbooks/tests_bridge.yml b/tests/playbooks/tests_bridge.yml index 09f4c8a78..9dbc74253 100644 --- a/tests/playbooks/tests_bridge.yml +++ b/tests/playbooks/tests_bridge.yml @@ -5,51 +5,36 @@ vars: interface: LSR-TST-br31 tasks: - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - - name: Include the task 'assert_device_absent.yml' - include_tasks: tasks/assert_device_absent.yml - - - name: Add test bridge - include_role: - name: linux-system-roles.network + - name: Include the task 'run_test.yml' + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - interface_name: "{{ interface }}" - state: up - type: bridge - ip: - dhcp4: false - auto6: true - - - name: Assert device present - include_tasks: tasks/assert_device_present.yml - - - name: Assert profile present - include_tasks: tasks/assert_profile_present.yml - vars: - profile: "{{ interface }}" - - - name: Include the task 'down_profile+delete_interface.yml' - include_tasks: tasks/down_profile+delete_interface.yml - vars: - profile: "{{ interface }}" - # FIXME: assert profile/device down - - - name: Include the task 'remove_profile.yml' - include_tasks: tasks/remove_profile.yml - vars: - profile: "{{ interface }}" - - - name: Assert profile absent - include_tasks: tasks/assert_profile_absent.yml - vars: - profile: "{{ interface }}" - - - name: Assert device absent - include_tasks: tasks/assert_device_absent.yml - - - name: Verify network state restored to default - include_tasks: tasks/check_network_dns.yml + lsr_description: Test configuring bridges + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/assert_device_absent.yml + condition: "{{ not __bootc_validation | d(false) }}" + lsr_test: + - network_connections: + - name: "{{ interface }}" + interface_name: "{{ interface }}" + state: up + type: bridge + ip: + dhcp4: false + auto6: true + lsr_assert: + - tasks/assert_device_present.yml + - what: tasks/assert_profile_present.yml + profile: "{{ interface }}" + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - what: tasks/remove_profile.yml + profile: "{{ interface }}" + - what: tasks/assert_profile_absent.yml + profile: "{{ interface }}" + - what: tasks/assert_device_absent.yml + profile: "{{ interface }}" + - tasks/check_network_dns.yml diff --git a/tests/playbooks/tests_eth_dns_support.yml b/tests/playbooks/tests_eth_dns_support.yml index 5322370b4..338ddfe47 100644 --- a/tests/playbooks/tests_eth_dns_support.yml +++ b/tests/playbooks/tests_eth_dns_support.yml @@ -6,134 +6,154 @@ type: veth interface: ethtest0 tasks: - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml + - name: Test dns support + include_tasks: tasks/run_test.yml vars: - state: present - - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - - name: Include network role - include_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - interface_name: "{{ interface }}" - state: up - type: ethernet - autoconnect: true - ip: - route_metric4: 100 - dhcp4: false - gateway4: 192.0.2.1 - dns_priority: 9999 - dns: - - 192.0.2.2 - - 198.51.100.5 - - 2001:db8::20 - dns_search: - - example.com - - example.org - dns_options: - - no-aaaa - - rotate - - timeout:1 - - route_metric6: -1 - auto6: false - gateway6: 2001:db8::1 - - address: - - 192.0.2.3/24 - - 198.51.100.3/26 - - 2001:db8::80/7 - - route: - - network: 198.51.100.128 - prefix: 26 - gateway: 198.51.100.1 - metric: 2 - - network: 198.51.100.64 - prefix: 26 - gateway: 198.51.100.6 - metric: 4 - route_append_only: false - rule_append_only: true - - - name: Verify nmcli connection DNS entry for IPv4 - shell: | - set -euxo pipefail - nmcli connection show {{ interface }} | grep ipv4.dns - register: ipv4_dns - ignore_errors: true - changed_when: false - - - name: Verify nmcli connection DNS entry for IPv6 - shell: | - set -euxo pipefail - nmcli connection show {{ interface }} | grep ipv6.dns - register: ipv6_dns - ignore_errors: true - changed_when: false - - - name: "Assert that DNS addresses are configured correctly" - assert: - that: - - "'192.0.2.2' in ipv4_dns.stdout" - - "'198.51.100.5' in ipv4_dns.stdout" - - "'2001:db8::20' in ipv6_dns.stdout" - msg: "DNS addresses are configured incorrectly" - - - name: "Assert that DNS search domains are configured correctly" - assert: - that: - - "'example.com' in ipv4_dns.stdout" - - "'example.org' in ipv4_dns.stdout" - - "'example.com' in ipv6_dns.stdout" - - "'example.org' in ipv6_dns.stdout" - msg: "DNS search domains are configured incorrectly" - - - name: "Assert that DNS options are configured correctly" - assert: - that: - - "'no-aaaa' in ipv4_dns.stdout" - - "'rotate' in ipv4_dns.stdout" - - "'timeout:1' in ipv4_dns.stdout" - - "'no-aaaa' in ipv6_dns.stdout" - - "'rotate' in ipv6_dns.stdout" - - "'timeout:1' in ipv6_dns.stdout" - msg: "DNS options are configured incorrectly" - - - name: "Assert that DNS priority is configured correctly" - assert: - that: - - "'9999' in ipv4_dns.stdout" - - "'9999' in ipv6_dns.stdout" - msg: "DNS priority is configured incorrectly" - - - name: Include the tasks 'down_profile+delete_interface.yml' - include_tasks: tasks/down_profile+delete_interface.yml - vars: - profile: "{{ interface }}" - - # FIXME: assert profile/device down - - name: Include the task 'remove_profile.yml' - include_tasks: tasks/remove_profile.yml - vars: - profile: "{{ interface }}" - - - name: Include the task 'assert_profile_absent.yml' - include_tasks: tasks/assert_profile_absent.yml - vars: - profile: "{{ interface }}" - - - name: Include the task 'assert_device_absent.yml' - include_tasks: tasks/assert_device_absent.yml - - - name: Verify network state restored to default - include_tasks: tasks/check_network_dns.yml + lsr_description: Test dns support + lsr_setup: + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + interface_name: "{{ interface }}" + state: up + type: ethernet + autoconnect: true + ip: + route_metric4: 100 + dhcp4: false + gateway4: 192.0.2.1 + dns_priority: 9999 + dns: + - 192.0.2.2 + - 198.51.100.5 + - 2001:db8::20 + dns_search: + - example.com + - example.org + dns_options: + - no-aaaa + - rotate + - timeout:1 + route_metric6: -1 + auto6: false + gateway6: 2001:db8::1 + address: + - 192.0.2.3/24 + - 198.51.100.3/26 + - 2001:db8::80/7 + route: + - network: 198.51.100.128 + prefix: 26 + gateway: 198.51.100.1 + metric: 2 + - network: 198.51.100.64 + prefix: 26 + gateway: 198.51.100.6 + metric: 4 + route_append_only: false + rule_append_only: true + lsr_assert: + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - section: connection + option: id + value: "{{ interface }}" + - section: connection + option: interface-name + value: "{{ interface }}" + - section: connection + option: type + value: ethernet + nmvalue: 802-3-ethernet + - section: ipv4 + option: route-metric + value: "100" + - section: ipv4 + option: dns + value: 192.0.2.2;198.51.100.5; + nmvalue: 192.0.2.2,198.51.100.5 + - section: ipv4 + option: dns-search + value: example.com;example.org; + nmvalue: example.com,example.org + - section: ipv6 + option: dns + value: 2001:db8::20; + nmvalue: 2001:db8::20 + - section: ipv6 + option: dns-search + value: example.com;example.org; + nmvalue: example.com,example.org + - section: ipv4 + option: dns-options + value: no-aaaa;rotate;timeout:1; + nmvalue: no-aaaa,rotate,timeout:1 + - section: ipv6 + option: dns-options + value: no-aaaa;rotate;timeout:1; + nmvalue: no-aaaa,rotate,timeout:1 + - section: ipv4 + option: dns-priority + value: 9999 + - section: ipv6 + option: dns-priority + value: 9999 + - section: ipv4 + option: method + value: manual + - section: ipv6 + option: method + value: manual + - section: ipv4 + option: address1 + value: 192.0.2.3/24 + nmvalue: false + - section: ipv4 + option: address2 + value: 198.51.100.3/26 + nmvalue: false + - section: ipv4 + option: addresses + nmvalue: 192.0.2.3/24, 198.51.100.3/26 + - section: ipv6 + option: address1 + value: 2001:db8::80/7 + nmvalue: false + - section: ipv6 + option: addresses + nmvalue: 2001:db8::80/7 + - section: ipv4 + option: gateway + value: 192.0.2.1 + - section: ipv6 + option: gateway + value: 2001:db8::1 + - section: ipv4 + option: route1 + value: 198.51.100.128/26,198.51.100.1,2 + nmvalue: false + - section: ipv4 + option: route2 + value: 198.51.100.64/26,198.51.100.6,4 + nmvalue: false + - section: ipv4 + option: routes + nmvalue: 198.51.100.128/26 198.51.100.1 2, 198.51.100.64/26 198.51.100.6 4 + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - what: tasks/remove_profile.yml + profile: "{{ interface }}" + - what: tasks/assert_profile_absent.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + - what: tasks/assert_device_absent.yml + profile: "{{ interface }}" + - tasks/check_network_dns.yml diff --git a/tests/playbooks/tests_ethernet.yml b/tests/playbooks/tests_ethernet.yml index 4c1e89596..5f88a339f 100644 --- a/tests/playbooks/tests_ethernet.yml +++ b/tests/playbooks/tests_ethernet.yml @@ -10,106 +10,79 @@ debug: msg: Inside ethernet tests - - name: Show network_provider - debug: - var: network_provider - - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - - name: Test static interface up - include_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - interface_name: "{{ interface }}" - state: up - type: ethernet - autoconnect: true - ip: - address: 192.0.2.1/24 - - - name: Include the task 'assert_output_in_stderr_without_warnings.yml' - include_tasks: tasks/assert_output_in_stderr_without_warnings.yml - - - name: Show network_provider after running role - debug: - var: network_provider - - - name: Get NM connection file - slurp: - src: "/etc/NetworkManager/system-connections/{{ interface }}.nmconnection" - register: nm_connection_file - when: - - network_provider == 'nm' - # RHEL up to 8 uses initscripts backend - - ansible_distribution_major_version | int >= 9 - - - name: Assert settings in NM connection file - assert: - that: - - "('interface-name=' + interface) in nm_connection_file.content | b64decode" - - "'type=ethernet' in nm_connection_file.content | b64decode" - - "'address1=192.0.2.1/24' in nm_connection_file.content | b64decode" - - "'method=manual' in nm_connection_file.content | b64decode" - when: - - network_provider == 'nm' - # RHEL up to 8 uses initscripts backend - - ansible_distribution_major_version | int >= 9 - - - name: Get NM connection status - command: "nmcli connection show {{ interface }}" - changed_when: false - register: nm_connection_status - when: network_provider == 'nm' - - - name: Assert NM connection status - assert: - that: - - nm_connection_status.stdout is search("ipv4.addresses:\s+192.0.2.1/24") - when: network_provider == 'nm' - - - name: Get initscripts connection file - slurp: - src: "/etc/sysconfig/network-scripts/ifcfg-{{ interface }}" - register: initscripts_connection_file - when: network_provider == 'initscripts' or ansible_distribution_major_version | int < 9 - - - name: Assert settings in initscripts connection file - assert: - that: - - "'TYPE=Ethernet' in initscripts_connection_file.content | b64decode" - - "'DEVICE={{ interface }}' in initscripts_connection_file.content | b64decode" - - "'IPADDR=192.0.2.1' in initscripts_connection_file.content | b64decode" - - "'PREFIX=24' in initscripts_connection_file.content | b64decode" - when: network_provider == 'initscripts' or ansible_distribution_major_version | int < 9 - - - name: Include the tasks 'down_profile+delete_interface.yml' - include_tasks: tasks/down_profile+delete_interface.yml - vars: - profile: "{{ interface }}" - - # FIXME: assert profile/device down - - name: Include the task 'remove_profile.yml' - include_tasks: tasks/remove_profile.yml - vars: - profile: "{{ interface }}" - - - name: Include the task 'assert_profile_absent.yml' - include_tasks: tasks/assert_profile_absent.yml - vars: - profile: "{{ interface }}" - - name: Include the task 'assert_device_absent.yml' - include_tasks: tasks/assert_device_absent.yml - - - name: Verify network state restored to default - include_tasks: tasks/check_network_dns.yml + - name: Test creating the bridge connection + tags: + - tests::states:create + block: + - name: Include the task 'run_test.yml' + include_tasks: tasks/run_test.yml + vars: + lsr_description: I can create a profile + lsr_setup: + - what: tasks/delete_interface.yml + condition: "{{ not __bootc_validation | default(false) }}" + - what: tasks/assert_device_absent.yml + condition: "{{ not __bootc_validation | default(false) }}" + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + interface_name: "{{ interface }}" + state: up + type: ethernet + autoconnect: true + ip: + address: 192.0.2.1/24 + lsr_assert: + - tasks/assert_output_in_stderr_without_warnings.yml + - tasks/assert_device_present.yml + # Device should be present because of autoconnect: true by + # default for NM (this might be considered a bug) + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - section: connection + option: interface-name + value: "{{ interface }}" + - section: connection + option: type + value: ethernet + nmvalue: 802-3-ethernet + - section: ipv4 + option: address1 + value: 192.0.2.1/24 + nmvalue: false + - section: ipv4 + option: addresses + nmvalue: 192.0.2.1/24 + - section: ipv4 + option: method + value: manual + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'initscripts' or ansible_distribution_major_version | int < 9 }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - TYPE=Ethernet + - DEVICE={{ interface }} + - IPADDR=192.0.2.1 + - PREFIX=24 + - what: tasks/assert_nm_connection_status.yml + condition: "{{ network_provider == 'nm' and __network_is_booted }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_output: 'ipv4.addresses:\s+192.0.2.1/24' + lsr_cleanup: + - what: tasks/down_profile+delete_interface.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + lsr_persistent_state: absent + - what: tasks/remove_profile.yml + profile: "{{ interface }}" + - what: tasks/assert_profile_absent.yml + condition: "{{ __network_is_booted }}" + profile: "{{ interface }}" + - what: tasks/assert_device_absent.yml + profile: "{{ interface }}" + - tasks/check_network_dns.yml diff --git a/tests/playbooks/tests_ethtool_coalesce.yml b/tests/playbooks/tests_ethtool_coalesce.yml index d28899117..6ebba69b2 100644 --- a/tests/playbooks/tests_ethtool_coalesce.yml +++ b/tests/playbooks/tests_ethtool_coalesce.yml @@ -12,153 +12,117 @@ tags: - always - - name: "INIT: Ethtool coalesce tests" - debug: - msg: "##################################################" - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - name: Install ethtool (test dependency) - package: - name: ethtool - state: present - use: "{{ (__network_is_ostree | d(false)) | - ternary('ansible.posix.rhel_rpm_ostree', omit) }}" + - name: Include network role vars used by tests + include_role: + name: linux-system-roles.network + tasks_from: set_facts.yml + public: true - - name: Test ethtool coalesce settings + - name: Run tests block: - - name: >- - TEST: I can create a profile without any coalescing option. - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false - - - name: Get profile's coalescing options - command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface }} - register: no_coalesce_nm - when: - - network_provider == "nm" - changed_when: false - - name: "ASSERT: The profile does not contain coalescing options" - assert: - that: no_coalesce_nm.stdout | length == 0 - when: - - network_provider == "nm" - - name: Get profile's coalescing options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: no_coalesce_initscripts - ignore_errors: true + - name: Test creating profile without changing ethtool coalesce settings when: - - network_provider == "initscripts" - changed_when: false - - name: "ASSERT: The profile does not contain coalescing options" - assert: - that: no_coalesce_initscripts.stdout | length == 0 - when: - - network_provider == "initscripts" - - - name: >- - TEST: I can set rx-frames. - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false - ethtool: - coalesce: - rx_frames: 128 - - name: Get profile's coalescing options - command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface }} - register: with_coalesce_nm - when: - - network_provider == "nm" - changed_when: false - - name: Assert coalesce options set in profile - assert: - that: with_coalesce_nm.stdout == '128' - when: - - network_provider == "nm" - - - name: Get profile's coalescing options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: with_coalesce_initscripts - ignore_errors: true - when: - - network_provider == "initscripts" - changed_when: false - - name: Assert coalesce options set in profile - assert: - that: '"rx-frames 128" in with_coalesce_initscripts.stdout' - when: - - network_provider == "initscripts" + lsr_description: Test creating profile without changing ethtool coalesce + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + lsr_assert: # NOTE: Cleanup is done in always at very end of file + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'nm' }}" + lsr_command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface | quote }} + lsr_not_stdout: coalesce + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: cat /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_not_stdout: ETHTOOL + lsr_cleanup: [] - - name: "TEST: I can clear coalescing options" - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + - name: "TEST: I can set rx-frames." + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false + lsr_description: Test setting coalesce option + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + ethtool: + coalesce: + rx_frames: 128 + lsr_assert: + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - section: ethtool + option: coalesce-rx-frames + value: "128" + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'nm' }}" + lsr_command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface | quote }} + lsr_stdout: "128" + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_stdout: rx-frames 128 + lsr_cleanup: [] - - name: Get profile's coalescing options - command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface }} - when: - - network_provider == "nm" - register: clear_coalesce_nm - changed_when: false - - name: "ASSERT: The profile does reset coalescing options" - assert: - that: clear_coalesce_nm.stdout | length == 0 + - name: Test clearing ethtool coalesce settings when: - - network_provider == "nm" - - name: Get profile's coalescing options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: clear_coalesce_initscripts - ignore_errors: true - when: - - network_provider == "initscripts" - changed_when: false - - name: "ASSERT: The profile does reset coalescing options" - assert: - that: clear_coalesce_initscripts.stdout | length == 0 - when: - - network_provider == "initscripts" + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml + vars: + lsr_description: Test creating profile without changing ethtool features + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + lsr_assert: # NOTE: Cleanup is done in always at very end of file + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'nm' }}" + lsr_command: nmcli -g ethtool.coalesce-rx-frames c show {{ interface | quote }} + lsr_not_stdout: coalesce + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: cat /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_not_stdout: ETHTOOL + lsr_cleanup: [] always: - name: Clean up the test device and the connection profile + when: ansible_connection != "buildah" tags: - "tests::cleanup" block: diff --git a/tests/playbooks/tests_ethtool_features.yml b/tests/playbooks/tests_ethtool_features.yml index 3bdc3c4ee..77ee68675 100644 --- a/tests/playbooks/tests_ethtool_features.yml +++ b/tests/playbooks/tests_ethtool_features.yml @@ -12,137 +12,115 @@ tags: - always - - name: "INIT: Ethtool feeatures tests" - debug: - msg: "##################################################" - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - name: Install ethtool (test dependency) - package: - name: ethtool - state: present - use: "{{ (__network_is_ostree | d(false)) | - ternary('ansible.posix.rhel_rpm_ostree', omit) }}" + - name: Include network role vars used by tests + include_role: + name: linux-system-roles.network + tasks_from: set_facts.yml + public: true - - name: Test ethtool features settings + - name: Run tests block: - - name: >- - TEST: I can create a profile without changing the ethtool features. - debug: - msg: "##################################################" - - name: Get current device features - command: "ethtool --show-features {{ interface }}" - register: original_ethtool_features - changed_when: false - - name: Import network role - import_role: - name: linux-system-roles.network + - name: Test creating profile without changing ethtool features + when: + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - state: up - type: ethernet - ip: - dhcp4: "no" - auto6: "no" - - name: Get current device features - command: "ethtool --show-features {{ interface }}" - register: ethtool_features - changed_when: false - - name: "ASSERT: The profile does not change the ethtool features" - assert: - that: - - original_ethtool_features.stdout == ethtool_features.stdout + lsr_description: Test creating profile without changing ethtool features + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + - what: tasks/assert_command_output.yml + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_test: + - network_connections: + - name: "{{ interface }}" + state: up + type: ethernet + ip: + dhcp4: "no" + auto6: "no" + lsr_assert: # NOTE: Cleanup is done in always at very end of file + - what: tasks/assert_command_output.yml + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_stdout: "{{ __previous_command_output.stdout }}" + lsr_cleanup: [] - - name: >- - TEST: I can disable gro and tx-tcp-segmentation and enable gso. - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + - name: Set original ethtool features + when: + - __network_is_booted + - not __bootc_validation | d(false) + set_fact: + original_ethtool_features: "{{ __previous_command_output }}" + + - name: "TEST: I can disable gro and tx-tcp-segmentation and enable gso." + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - state: up - type: ethernet - ip: - dhcp4: "no" - auto6: "no" - ethtool: - features: - gro: "no" - gso: "yes" - tx-tcp-segmentation: "no" - - name: Get current device features - command: "ethtool --show-features {{ interface }}" - register: ethtool_features - changed_when: false - - name: Show ethtool_features - debug: - var: ethtool_features.stdout_lines - - name: Assert device features - assert: - that: - - >- - 'generic-receive-offload: off' in - ethtool_features.stdout_lines - - >- - 'generic-segmentation-offload: on' in - ethtool_features.stdout_lines - - >- - 'tx-tcp-segmentation: off' in - ethtool_features.stdout_lines | map('trim') + lsr_description: Test creating profile without changing ethtool features + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_test: + - network_connections: + - name: "{{ interface }}" + state: up + type: ethernet + ip: + dhcp4: "no" + auto6: "no" + ethtool: + features: + gro: "no" + gso: "yes" + tx-tcp-segmentation: "no" + lsr_assert: + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - section: ethtool + option: feature-gro + value: "false" + nmvalue: "off" + - section: ethtool + option: feature-gso + value: "true" + nmvalue: "on" + - section: ethtool + option: feature-tx-tcp-segmentation + value: "false" + nmvalue: "off" + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_stdout_lines: + - "generic-receive-offload: off" + - "generic-segmentation-offload: on" + - "\ttx-tcp-segmentation: off" # noqa no-tabs + lsr_cleanup: [] - name: >- TEST: I can enable tx_tcp_segmentation (using underscores). - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + when: + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - state: up - type: ethernet - ip: - dhcp4: "no" - auto6: "no" - ethtool: - features: - tx_tcp_segmentation: "yes" - - name: Get current device features - command: "ethtool --show-features {{ interface }}" - register: ethtool_features - changed_when: false - - name: Show ethtool_features - debug: - var: ethtool_features.stdout_lines - - name: Assert device features - assert: - that: - - >- - 'tx-tcp-segmentation: on' in - ethtool_features.stdout_lines | map('trim') - - - name: I cannot change tx_tcp_segmentation and tx-tcp-segmentation at - the same time. - block: - - name: >- - TEST: Change feature with both underscores and dashes. - debug: - msg: "##################################################" - - name: Configure ethtool features setting - network_connections: - provider: "{{ network_provider | mandatory }}" - connections: + lsr_description: Test enabling tx_tcp_segmentation (using underscores) + lsr_setup: [] + lsr_test: + - network_connections: - name: "{{ interface }}" state: up type: ethernet @@ -151,10 +129,41 @@ auto6: "no" ethtool: features: - tx_tcp_segmentation: "no" - tx-tcp-segmentation: "no" - __header: "# Ansible managed test header" - register: __network_connections_result + tx_tcp_segmentation: "yes" + lsr_assert: + - what: tasks/assert_command_output.yml + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_stdout_lines: + - "\ttx-tcp-segmentation: on" # noqa no-tabs + lsr_cleanup: [] + + - name: I cannot change tx_tcp_segmentation and tx-tcp-segmentation at + the same time. + when: + - __network_is_booted + - not __bootc_validation | d(false) + block: + - name: >- + TEST: Change feature with both underscores and dashes. + include_tasks: tasks/run_test.yml + vars: + lsr_description: Test changing feature with both underscores and dashes + lsr_setup: [] + lsr_test: + - network_connections: + - name: "{{ interface }}" + state: up + type: ethernet + ip: + dhcp4: "no" + auto6: "no" + ethtool: + features: + tx_tcp_segmentation: "no" + tx-tcp-segmentation: "no" + lsr_assert: [] + lsr_cleanup: [] rescue: - name: Show network_connections result debug: @@ -168,7 +177,6 @@ fatal error: configuration error: connections[0].ethtool.features: duplicate key 'tx_tcp_segmentation' - always: - name: Check failure debug: @@ -178,32 +186,30 @@ that: __network_connections_result.failed - name: "TEST: I can reset features to their original value." - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - state: up - type: ethernet - ip: - dhcp4: "no" - auto6: "no" - - name: Get current device features - command: "ethtool --show-features {{ interface }}" - register: ethtool_features - changed_when: false - # Resetting the ethtools only works with NetworkManager - - name: "ASSERT: The profile does not change the ethtool features" - assert: - that: - - original_ethtool_features.stdout == ethtool_features.stdout when: - network_provider == 'nm' + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml + vars: + lsr_description: Test resetting features to their original value + lsr_setup: [] + lsr_test: + - network_connections: + - name: "{{ interface }}" + state: up + type: ethernet + ip: + dhcp4: "no" + auto6: "no" + lsr_assert: + - what: tasks/assert_command_output.yml + lsr_packages: [ethtool] + lsr_command: ethtool --show-features {{ interface | quote }} + lsr_stdout: "{{ original_ethtool_features.stdout }}" + lsr_cleanup: [] always: - name: Clean up the test device and the connection profile + when: ansible_connection != "buildah" tags: - "tests::cleanup" block: diff --git a/tests/playbooks/tests_ethtool_ring.yml b/tests/playbooks/tests_ethtool_ring.yml index fdcc263de..f06d93cc8 100644 --- a/tests/playbooks/tests_ethtool_ring.yml +++ b/tests/playbooks/tests_ethtool_ring.yml @@ -12,194 +12,129 @@ tags: - always - - name: "INIT: Ethtool ring tests" - debug: - msg: "##################################################" - - name: Include the task 'show_interfaces.yml' - include_tasks: tasks/show_interfaces.yml - - name: Include the task 'manage_test_interface.yml' - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Include the task 'assert_device_present.yml' - include_tasks: tasks/assert_device_present.yml - - name: Install ethtool (test dependency) - package: - name: ethtool - state: present - use: "{{ (__network_is_ostree | d(false)) | - ternary('ansible.posix.rhel_rpm_ostree', omit) }}" + - name: Include network role vars used by tests + include_role: + name: linux-system-roles.network + tasks_from: set_facts.yml + public: true - - name: Test ethtool ring settings + - name: Run tests block: - - name: >- - TEST: I can create a profile without any ring option. - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network - vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false - - - name: Get profile's ring options - command: nmcli -g ethtool.ring-rx c show {{ interface }} - register: no_ring_nm - when: - - network_provider == "nm" - changed_when: false - - name: "ASSERT: The profile does not contain ring options" - assert: - that: no_ring_nm.stdout | length == 0 + - name: Test creating profile without changing ethtool ring settings when: - - network_provider == "nm" - - name: Get profile's ring options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: no_ring_initscripts - ignore_errors: true - when: - - network_provider == "initscripts" - changed_when: false - - name: "ASSERT: The profile does not contain ring options" - assert: - that: no_ring_initscripts.stdout | length == 0 - when: - - network_provider == "initscripts" - - - name: >- - TEST: I can set rx. - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false - ethtool: - ring: - rx: 128 - rx_jumbo: 128 - rx_mini: 128 - tx: 128 - - - name: Get profile's ethtool.ring-rx options - command: nmcli -g ethtool.ring-rx c show {{ interface }} - register: with_ring_rx - when: - - network_provider == "nm" - changed_when: false - - name: Assert ethtool.ring-rx option set in profile - assert: - that: with_ring_rx.stdout == '128' - when: - - network_provider == "nm" - - name: Get profile's ethtool.ring-rx-jumbo options - command: nmcli -g ethtool.ring-rx-jumbo c show {{ interface }} - register: with_ring_rx_jumbo - when: - - network_provider == "nm" - changed_when: false - - name: Assert ethtool.ring-rx-jumbo option set in profile - assert: - that: with_ring_rx_jumbo.stdout == '128' - when: - - network_provider == "nm" - - name: Get profile's ethtool.ring-rx-mini options - command: nmcli -g ethtool.ring-rx-mini c show {{ interface }} - register: with_ring_rx_mini - when: - - network_provider == "nm" - changed_when: false - - name: Assert ethtool.ring-rx-mini option set in profile - assert: - that: with_ring_rx_mini.stdout == '128' - when: - - network_provider == "nm" - - name: Get profile's ethtool.ring-tx options - command: nmcli -g ethtool.ring-tx c show {{ interface }} - register: with_ring_tx - when: - - network_provider == "nm" - changed_when: false - - name: Assert ethtool.ring-tx option set in profile - assert: - that: with_ring_tx.stdout == '128' - when: - - network_provider == "nm" - - - name: Get profile's ethtool.ring options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: with_ring - ignore_errors: true - when: - - network_provider == "initscripts" - changed_when: false - - name: Assert ethtool.ring option set in profile - assert: - that: - - '"rx 128" in with_ring.stdout' - - '"rx-jumbo 128" in with_ring.stdout' - - '"rx-mini 128" in with_ring.stdout' - - '"tx 128" in with_ring.stdout' - when: - - network_provider == "initscripts" + lsr_description: Test creating profile without changing ethtool ring settings + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + lsr_assert: # NOTE: Cleanup is done in always at very end of file + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'nm' }}" + lsr_command: nmcli -g ethtool.ring-rx c show {{ interface | quote }} + lsr_not_stdout: ring-rx + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: cat /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_not_stdout: ETHTOOL + lsr_cleanup: [] - - name: "TEST: I can clear ring options" - debug: - msg: "##################################################" - - name: Import network role - import_role: - name: linux-system-roles.network + - name: "TEST: I can set rx ring settings." + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface }}" - type: ethernet - state: up - ip: - dhcp4: false - auto6: false + lsr_description: Test setting rx ring settings + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + ethtool: + ring: + rx: 128 + rx_jumbo: 128 + rx_mini: 128 + tx: 128 + lsr_assert: + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface }}" + lsr_connection_settings: + - section: ethtool + option: ring-rx + value: "128" + - section: ethtool + option: ring-rx-jumbo + value: "128" + - section: ethtool + option: ring-rx-mini + value: "128" + - section: ethtool + option: ring-tx + value: "128" + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_stdout_lines: + - rx 128 + - rx-jumbo 128 + - rx-mini 128 + - tx 128 + lsr_cleanup: [] - - name: Get profile's ring options - command: nmcli -g ethtool.ring-rx c show {{ interface }} - register: clear_ring_nm - when: - - network_provider == "nm" - changed_when: false - - name: "ASSERT: The profile does reset ring options" - assert: - that: clear_ring_nm.stdout | length == 0 - when: - - network_provider == "nm" - - name: Get profile's ring options - command: - grep ETHTOOL /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - register: clear_ring_initscripts - ignore_errors: true + - name: Test clearing ethtool ring settings when: - - network_provider == "initscripts" - changed_when: false - - name: "ASSERT: The profile does reset ring options" - assert: - that: clear_ring_initscripts.stdout | length == 0 - when: - - network_provider == "initscripts" + - __network_is_booted + - not __bootc_validation | d(false) + include_tasks: tasks/run_test.yml + vars: + lsr_description: Test clearing ethtool ring settings + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + - tasks/assert_device_present.yml + lsr_test: + - network_connections: + - name: "{{ interface }}" + type: ethernet + state: up + ip: + dhcp4: false + auto6: false + lsr_assert: # NOTE: Cleanup is done in always at very end of file + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'nm' }}" + lsr_command: nmcli -g ethtool.ring-rx c show {{ interface | quote }} + lsr_not_stdout: ring-rx + - what: tasks/assert_command_output.yml + condition: "{{ network_provider == 'initscripts' }}" + lsr_command: cat /etc/sysconfig/network-scripts/ifcfg-{{ interface | quote }} + lsr_not_stdout: ETHTOOL + lsr_cleanup: [] always: - name: Clean up the test device and the connection profile + when: ansible_connection != "buildah" tags: - "tests::cleanup" block: diff --git a/tests/playbooks/tests_ignore_auto_dns.yml b/tests/playbooks/tests_ignore_auto_dns.yml index f191ce8b3..45d422d6e 100644 --- a/tests/playbooks/tests_ignore_auto_dns.yml +++ b/tests/playbooks/tests_ignore_auto_dns.yml @@ -36,27 +36,52 @@ auto6: true address: - 198.51.100.3/24 - - name: Get the nmcli ipv4.ignore-auto-dns setting - command: nmcli -f ipv4.ignore-auto-dns c show {{ interface }} - register: ipv4_ignore_auto_dns - changed_when: false - - name: Get the nmcli ipv6.ignore-auto-dns setting - command: nmcli -f ipv6.ignore-auto-dns c show {{ interface }} - register: ipv6_ignore_auto_dns - changed_when: false + # the nmcli and .nmconnection file formats are very different, so we + # need to do online and offline checks in different code paths + - name: Online check + when: __network_is_booted | bool + block: + - name: Get the nmcli ipv4.ignore-auto-dns setting + command: nmcli -f ipv4.ignore-auto-dns c show {{ interface }} + register: ipv4_ignore_auto_dns + changed_when: false + + - name: Get the nmcli ipv6.ignore-auto-dns setting + command: nmcli -f ipv6.ignore-auto-dns c show {{ interface }} + register: ipv6_ignore_auto_dns + changed_when: false + + - name: Assert that the setting ipv4.ignore-auto-dns is 'no' + assert: + that: + - "'no' in ipv4_ignore_auto_dns.stdout" + msg: "the setting ipv4.ignore-auto-dns is 'yes'" - - name: Assert that the setting ipv4.ignore-auto-dns is 'no' - assert: - that: - - "'no' in ipv4_ignore_auto_dns.stdout" - msg: "the setting ipv4.ignore-auto-dns is 'yes'" + - name: Assert that the setting ipv6.ignore-auto-dns is 'yes' + assert: + that: + - "'yes' in ipv6_ignore_auto_dns.stdout" + msg: "the setting ipv6.ignore-auto-dns is 'no'" + + - name: Offline check + when: not __network_is_booted | bool + block: + # noqa command-instead-of-module + - name: Check that .nmconnection file has no ipv4.ignore-auto-dns setting + command: > + sed -n '/^\[ipv4\]/,/^$/ {/ignore-auto-dns=/p}' /etc/NetworkManager/system-connections/{{ interface }}.nmconnection + changed_when: false + register: ipv4_ignore_auto_dns_file + failed_when: ipv4_ignore_auto_dns_file.stdout | trim != "" - - name: Assert that the setting ipv6.ignore-auto-dns is 'yes' - assert: - that: - - "'yes' in ipv6_ignore_auto_dns.stdout" - msg: "the setting ipv6.ignore-auto-dns is 'no'" + # noqa command-instead-of-module + - name: Check that .nmconnection file has ipv6.ignore-auto-dns setting + command: > + sed -n '/^\[ipv6\]/,/^$/ {/ignore-auto-dns=/p}' /etc/NetworkManager/system-connections/{{ interface }}.nmconnection + changed_when: false + register: ipv6_ignore_auto_dns_file + failed_when: ipv6_ignore_auto_dns_file.stdout | trim != "ignore-auto-dns=true" always: - name: Remove test configuration diff --git a/tests/playbooks/tests_ipv6_disabled.yml b/tests/playbooks/tests_ipv6_disabled.yml index f8aea90f5..7bf2ba506 100644 --- a/tests/playbooks/tests_ipv6_disabled.yml +++ b/tests/playbooks/tests_ipv6_disabled.yml @@ -44,10 +44,13 @@ vars: errmsg: ip.ipv6_disabled is not supported by the running version of NetworkManager - - name: Verify nmcli connection ipv6.method - shell: | - set -euxo pipefail - nmcli connection show {{ interface }} | grep ipv6.method + - name: Verify NM connection ipv6.method + command: >- + {{ + ("nmcli -f ipv6.method connection show " ~ interface) + if __network_is_booted else + ("sed -n '/^\[ipv6\]/,/^$/ {/method=/p}' /etc/NetworkManager/system-connections/" ~ interface ~ ".nmconnection") + }} register: ipv6_method ignore_errors: true changed_when: false diff --git a/tests/playbooks/tests_ipv6_dns_search.yml b/tests/playbooks/tests_ipv6_dns_search.yml index b5828a18e..ae26c36aa 100644 --- a/tests/playbooks/tests_ipv6_dns_search.yml +++ b/tests/playbooks/tests_ipv6_dns_search.yml @@ -21,13 +21,23 @@ - 192.0.2.1/24 state: up - name: Get DNS search entry for IPv4 - command: nmcli -f ipv4.dns-search connection show br-example + command: >- + {{ + "nmcli -f ipv4.dns-search connection show br-example" + if __network_is_booted else + "sed -n '/^\[ipv4\]/,/^$/ {/dns-search=/p}' /etc/NetworkManager/system-connections/br-example.nmconnection" + }} register: ipv4_dns_search ignore_errors: true changed_when: false - name: Get DNS search entry for IPv6 - command: nmcli -f ipv6.dns-search connection show br-example + command: >- + {{ + "nmcli -f ipv6.dns-search connection show br-example" + if __network_is_booted else + "sed -n '/^\[ipv6\]/,/^$/ {/dns-search=/p}' /etc/NetworkManager/system-connections/br-example.nmconnection" + }} register: ipv6_dns_search ignore_errors: true changed_when: false @@ -67,7 +77,12 @@ state: up - name: Get DNS search entry for IPv6 - command: nmcli -f ipv6.dns-search connection show br-example + command: >- + {{ + "nmcli -f ipv6.dns-search connection show br-example" + if __network_is_booted else + "sed -n '/^\[ipv6\]/,/^$/ {/dns-search=/p}' /etc/NetworkManager/system-connections/br-example.nmconnection" + }} register: ipv6_dns_search_static ignore_errors: true changed_when: false @@ -99,7 +114,12 @@ state: up - name: Get DNS search entry for IPv6 - command: nmcli -f ipv6.dns-search connection show br-example + command: >- + {{ + "nmcli -f ipv6.dns-search connection show br-example" + if __network_is_booted else + "sed -n '/^\[ipv6\]/,/^$/ {/dns-search=/p}' /etc/NetworkManager/system-connections/br-example.nmconnection" + }} register: ipv6_dns_search_static_only ignore_errors: true changed_when: false diff --git a/tests/playbooks/tests_network_state.yml b/tests/playbooks/tests_network_state.yml index 5e6260fc0..b51d27aca 100644 --- a/tests/playbooks/tests_network_state.yml +++ b/tests/playbooks/tests_network_state.yml @@ -2,6 +2,9 @@ --- - name: Play for configuring network using network state variable hosts: all + tags: + # this is runtime configuration and checks + - tests::booted vars: type: veth interface0: ethtest0 diff --git a/tests/playbooks/tests_route_device.yml b/tests/playbooks/tests_route_device.yml index 13a4d87e9..c7f5daccc 100644 --- a/tests/playbooks/tests_route_device.yml +++ b/tests/playbooks/tests_route_device.yml @@ -8,111 +8,121 @@ interface1: ethtest1 tasks: - - name: Set type and interface0 - set_fact: - type: "{{ type }}" - interface: "{{ interface0 }}" - - name: Show interfaces - include_tasks: tasks/show_interfaces.yml - - name: Manage test interface - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Assert device is present - include_tasks: tasks/assert_device_present.yml - - name: Set interface1 - set_fact: - interface: "{{ interface1 }}" - - name: Show interfaces again - include_tasks: tasks/show_interfaces.yml - - name: Manage test interface with second interface - include_tasks: tasks/manage_test_interface.yml - vars: - state: present - - name: Assert device is present with second interface - include_tasks: tasks/assert_device_present.yml - name: Test the route or the warning log when configuring the route with or without the interface name block: - - name: Configure the IP addresses and the route with interface name - specified - import_role: - name: linux-system-roles.network + - name: Test the route or the warning log when configuring the route with + or without the interface name + include_tasks: tasks/run_test.yml vars: - network_connections: - - name: "{{ interface0 }}" - interface_name: "{{ interface0 }}" - state: up - type: ethernet - autoconnect: false - ip: - address: - - 198.51.100.3/24 - - 2001:db8::2/32 - route: - - network: 198.51.10.64 - prefix: 26 - gateway: 198.51.100.6 - metric: 4 - - network: 2001:db6::4 - prefix: 128 - gateway: 2001:db8::1 - metric: 2 - - name: "{{ interface1 }}" - interface_name: "{{ interface1 }}" - state: up - type: ethernet - autoconnect: false - ip: - address: - - 198.51.100.6/24 - - 2001:db8::4/32 - route: - - network: 198.51.12.128 - prefix: 26 - gateway: 198.51.100.1 - metric: 2 - - name: Get the IPv4 routes from the route table main - command: ip -4 route - register: route_table_main_ipv4 - changed_when: false - - - name: Assert that the route table main contains the specified IPv4 - routes - assert: - that: - # When running with nm provider, the route will be configured - # with `proto static` - # In RHEL-6.10 managed host, the attribute in the route is not - # equally spaced - - route_table_main_ipv4.stdout is search("198.51.10.64/26 via - 198.51.100.6 dev ethtest0\s+(proto static )?metric 4") - - route_table_main_ipv4.stdout is search("198.51.12.128/26 via - 198.51.100.1 dev ethtest1\s+(proto static )?metric 2") - msg: "the route table main does not contain the specified IPv4 - route" - - - name: Get the IPv6 routes from the route table main - command: ip -6 route - register: route_table_main_ipv6 - changed_when: false + lsr_description: Test the route or the warning log when configuring the route with + or without the interface name + lsr_setup: + - tasks/show_interfaces.yml + - what: tasks/manage_test_interface.yml + state: present + lsr_interface: "{{ interface0 }}" + - what: tasks/assert_device_present.yml + lsr_interface: "{{ interface0 }}" + - what: tasks/manage_test_interface.yml + state: present + lsr_interface: "{{ interface1 }}" + - what: tasks/assert_device_present.yml + lsr_interface: "{{ interface1 }}" + lsr_test: + - network_connections: + - name: "{{ interface0 }}" + interface_name: "{{ interface0 }}" + state: up + type: ethernet + # Set autoconnect to true for buildah connection, otherwise, + # the test will need to start the connection manually + autoconnect: "{{ ansible_connection | d('') == 'buildah'}}" + ip: + address: + - 198.51.100.3/24 + - 2001:db8::2/32 + route: + - network: 198.51.10.64 + prefix: 26 + gateway: 198.51.100.6 + metric: 4 + - network: 2001:db6::4 + prefix: 128 + gateway: 2001:db8::1 + metric: 2 + - name: "{{ interface1 }}" + interface_name: "{{ interface1 }}" + state: up + type: ethernet + # Set autoconnect to true for buildah connection, otherwise, + # the test will need to start the connection manually + autoconnect: "{{ ansible_connection | d('') == 'buildah'}}" + ip: + address: + - 198.51.100.6/24 + - 2001:db8::4/32 + route: + - network: 198.51.12.128 + prefix: 26 + gateway: 198.51.100.1 + metric: 2 + lsr_assert: + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface0 }}" + lsr_connection_settings: + - section: ipv4 + option: route1 + value: 198.51.10.64/26,198.51.100.6,4 + nmvalue: false + ifcfg_route_value: ADDRESS0=198.51.10.64 + - section: ipv4 + option: routes + nmvalue: 198.51.10.64/26 198.51.100.6 4 + - section: ipv6 + option: route1 + value: 2001:db6::4/128,2001:db8::1,2 + nmvalue: false + ifcfg_route6_value: 2001:db6::4/128 via 2001:db8::1 metric 2 + - section: ipv6 + option: routes + nmvalue: 2001:db6::4/128 2001:db8::1 2 + - what: tasks/assert_connection_settings.yml + condition: "{{ network_provider == 'nm' }}" + lsr_connection_name: "{{ interface1 }}" + lsr_connection_settings: + - section: ipv4 + option: route1 + value: 198.51.12.128/26,198.51.100.1,2 + nmvalue: false + - section: ipv4 + option: routes + nmvalue: 198.51.12.128/26 198.51.100.1 2 + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_command: ip -4 route + lsr_stdout_regex_list: + - "198.51.10.64/26 via 198.51.100.6 dev ethtest0\\s+(proto static )?metric 4" + - "198.51.12.128/26 via 198.51.100.1 dev ethtest1\\s+(proto static )?metric 2" + - what: tasks/assert_command_output.yml + condition: "{{ __network_is_booted }}" + lsr_command: ip -6 route + lsr_stdout_regex_list: + - "2001:db6::4 via 2001:db8::1 dev ethtest0\\s+(proto static )?metric 2" + lsr_cleanup: [] - - name: Assert that the route table main contains the specified IPv6 - routes - assert: - that: - - route_table_main_ipv6.stdout is search("2001:db6::4 via - 2001:db8::1 dev ethtest0\s+(proto static )?metric 2") - msg: "the route table main does not contain the specified IPv6 - route" - name: Get the interface1 MAC address command: cat /sys/class/net/{{ interface1 }}/address register: interface1_mac changed_when: false + when: __network_is_booted and not __bootc_validation | d(false) + - name: Configure the IP addresses and the route with only the MAC address specified - import_role: + include_role: name: linux-system-roles.network + when: __network_is_booted and not __bootc_validation | d(false) vars: network_connections: - name: "{{ interface1 }}" @@ -133,28 +143,37 @@ the output device is logged for initscripts provider assert: that: - - __network_connections_result.stderr is search("\[003\] - .0, state.None persistent_state.present, - '{{ interface1 }}'. The connection {{ interface1 }} does not - specify an interface name. Therefore, the route to - 198.58.10.64/26 will be configured without the output device - and the kernel will choose it automatically which might result - in an unwanted device being used. To avoid this, specify - `interface_name` in the connection appropriately.") + - __network_connections_result.stderr is search(__stderr_str) msg: The warning about specifying the route without the output device is not logged for initscripts provider - when: network_provider == "initscripts" + when: + - network_provider == "initscripts" + - __network_is_booted + - not __bootc_validation | d(false) + vars: + __stderr_str: >- + \[003\] .0, state.None persistent_state.present, '{{ interface1 }}'. + The connection {{ interface1 }} does not + specify an interface name. Therefore, the route to + 198.58.10.64/26 will be configured without the output device + and the kernel will choose it automatically which might result + in an unwanted device being used. To avoid this, specify + `interface_name` in the connection appropriately. - name: Assert that no warning is logged for nm provider assert: that: - __network_connections_result.stderr is not search("") msg: The warning is logged for nm provider - when: network_provider == "nm" + when: + - network_provider == "nm" + - __network_is_booted + - not __bootc_validation | d(false) always: - name: Remove test configuration tags: - "tests::cleanup" + when: ansible_connection != "buildah" block: - name: Bring down test devices and profiles include_role: @@ -169,15 +188,20 @@ state: down - name: Delete interface1 include_tasks: tasks/delete_interface.yml + vars: + lsr_interface: "{{ interface1 }}" - name: Assert interface1 is absent include_tasks: tasks/assert_device_absent.yml - - name: Set interface0 - set_fact: - interface: "{{ interface0 }}" + vars: + lsr_interface: "{{ interface1 }}" - name: Delete interface0 include_tasks: tasks/delete_interface.yml + vars: + lsr_interface: "{{ interface0 }}" - name: Assert interface0 is absent include_tasks: tasks/assert_device_absent.yml + vars: + lsr_interface: "{{ interface0 }}" - name: Assert interface0 profile and interface1 profile are absent include_tasks: tasks/assert_profile_absent.yml vars: diff --git a/tests/tasks/activate_profile.yml b/tests/tasks/activate_profile.yml index e3e75bdc3..80e377121 100644 --- a/tests/tasks/activate_profile.yml +++ b/tests/tasks/activate_profile.yml @@ -5,6 +5,6 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" state: up ... diff --git a/tests/tasks/assert_IPv4_present.yml b/tests/tasks/assert_IPv4_present.yml index 1c62c82ae..79518bb21 100644 --- a/tests/tasks/assert_IPv4_present.yml +++ b/tests/tasks/assert_IPv4_present.yml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause --- - name: "** TEST check IPv4" - command: ip -4 a s {{ interface | quote }} + command: ip -4 a s {{ lsr_interface | d(interface) | quote }} register: result until: address in result.stdout retries: 20 diff --git a/tests/tasks/assert_bond_options.yml b/tests/tasks/assert_bond_options.yml index 72d1ca73e..d60171e46 100644 --- a/tests/tasks/assert_bond_options.yml +++ b/tests/tasks/assert_bond_options.yml @@ -9,13 +9,18 @@ loop_control: loop_var: bond_opt changed_when: false + when: __network_is_booted | bool + - name: Include the task 'assert_IPv4_present.yml' include_tasks: assert_IPv4_present.yml vars: - interface: "{{ controller_device }}" + lsr_interface: "{{ controller_device }}" address: '192.0.2' + when: __network_is_booted | bool + - name: Include the task 'assert_IPv6_present.yml' include_tasks: assert_IPv6_present.yml vars: - interface: "{{ controller_device }}" + lsr_interface: "{{ controller_device }}" address: '2001' + when: __network_is_booted | bool diff --git a/tests/tasks/assert_command_output.yml b/tests/tasks/assert_command_output.yml new file mode 100644 index 000000000..2892e1863 --- /dev/null +++ b/tests/tasks/assert_command_output.yml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Inputs: +# lsr_command: The command to run with the "command" module +# command can be either a string or a list +# lsr_shell: The command to run with the "shell" module +# lsr_packages: Any packages that need to be installed first +# to provide the command, if any +# lsr_stdout: The string to look for in the stdout of the command +# lsr_stderr: The string to look for in the stderr of the command +# lsr_not_stdout: This string must not be present in the stdout of the command +# lsr_not_stderr: This string must not be present in the stderr of the command +# Output: +# Will raise an error if command fails +# Will raise an error if stdout/stderr do not match given strings +--- +- name: Ensure test packages are present + package: + name: "{{ lsr_packages }}" + state: present + use: "{{ (__network_is_ostree | d(false)) | + ternary('ansible.posix.rhel_rpm_ostree', omit) }}" + when: lsr_packages | d([]) | length > 0 + +- name: Run command and collect output + command: + cmd: "{{ lsr_command if lsr_command is string else omit }}" + argv: "{{ lsr_command if lsr_command is not string else omit }}" + when: lsr_command | d("") | length > 0 + changed_when: false + register: __cmd_output + +# noqa command-instead-of-shell +- name: Run command and collect output with shell + shell: "{{ lsr_shell }}" + when: lsr_shell | d("") | length > 0 + changed_when: false + register: __shell_output + +- name: Set command output + set_fact: + __command_output: "{{ __cmd_output if lsr_command | d('') | length > 0 else __shell_output }}" + +- name: Set previous command output for before/after comparisons + set_fact: + __previous_command_output: "{{ __command_output }}" + +- name: Assert lsr_stdout is in stdout + assert: + that: lsr_stdout in __command_output.stdout + when: lsr_stdout | d("") | length > 0 + +- name: Assert lsr_stdout_lines is in stdout + assert: + that: lsr_stdout_lines is subset(__command_output.stdout_lines) + when: lsr_stdout_lines | d([]) | length > 0 + +# assert that each regex in the list is in the stdout +- name: Assert lsr_stdout_regex_list is in stdout + assert: + that: __command_output.stdout is search(lsr_stdout_regex_list_item) + loop: "{{ lsr_stdout_regex_list | d([]) }}" + loop_control: + loop_var: lsr_stdout_regex_list_item + +- name: Assert lsr_not_stdout is not in stdout + assert: + that: lsr_not_stdout not in __command_output.stdout + when: lsr_not_stdout | d("") | length > 0 + +- name: Assert lsr_stderr is in stderr + assert: + that: lsr_stderr in __command_output.stderr + when: lsr_stderr | d("") | length > 0 + +- name: Assert lsr_not_stderr is not in stderr + assert: + that: lsr_not_stderr not in __command_output.stderr + when: lsr_not_stderr | d("") | length > 0 diff --git a/tests/tasks/assert_connection_settings.yml b/tests/tasks/assert_connection_settings.yml new file mode 100644 index 000000000..aaf304ff8 --- /dev/null +++ b/tests/tasks/assert_connection_settings.yml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Inputs +# - lsr_connection_name: the connection name +# - network_provider: the network provider +# - lsr_connection_settings: the connection file settings for NM files +--- +- name: Assert NM connection settings + when: + - lsr_connection_name is defined + - lsr_connection_settings | d({}) | length > 0 + - network_provider == "nm" + - ansible_distribution_major_version | int >= 9 + vars: + __nm_connection_file_path: /etc/NetworkManager/system-connections/{{ lsr_connection_name }}.nmconnection + block: + - name: Show connection file + command: cat {{ __nm_connection_file_path | quote }} + changed_when: false + when: ansible_verbosity | int >= 2 + + - name: Stat connection file + stat: + path: "{{ __nm_connection_file_path }}" + register: __nm_connection_file_stat + + - name: Assert settings in NM connection file + community.general.ini_file: + path: "{{ __nm_connection_file_path }}" + section: "{{ __nm_connection_file_item.section }}" + option: "{{ __nm_connection_file_item.option }}" + value: "{{ __nm_connection_file_item.value }}" + state: present + ignore_spaces: true + owner: "{{ __nm_connection_file_stat.stat.pw_name }}" + group: "{{ __nm_connection_file_stat.stat.gr_name }}" + mode: "{{ __nm_connection_file_stat.stat.mode }}" + register: __nm_connection_file + # nm only values do not define value + loop: "{{ lsr_connection_settings | selectattr('value', 'defined') | list }}" + loop_control: + loop_var: __nm_connection_file_item + failed_when: __nm_connection_file is changed + + - name: Get nmcli connection settings + command: nmcli --fields all --terse connection show {{ lsr_connection_name | quote }} + register: __nm_connection_settings + changed_when: false + when: __network_is_booted + + - name: Assert nmcli connection settings + assert: + that: setting in __nm_connection_settings.stdout_lines + loop: "{{ nmitems + items }}" + loop_control: + loop_var: __nm_connection_item + when: __network_is_booted + vars: + nmitems: "{{ lsr_connection_settings | selectattr('nmvalue', 'defined') | selectattr('nmvalue') | list }}" + items: "{{ lsr_connection_settings | rejectattr('nmvalue', 'defined') | list }}" + section: "{{ __nm_connection_item.section }}" + option: "{{ 'addresses' if __nm_connection_item.option == 'address1' else __nm_connection_item.option }}" + value: "{{ __nm_connection_item.nmvalue + if __nm_connection_item.nmvalue is defined and __nm_connection_item.nmvalue + else __nm_connection_item.value }}" + setting: "{{ section ~ '.' ~ option ~ ':' ~ value }}" + +- name: Assert initscripts file settings + when: + - lsr_connection_name is defined + - lsr_connection_settings | d({}) | length > 0 + - network_provider == "initscripts" or ansible_distribution_major_version | int < 9 + vars: + __initscripts_connection_file_path: /etc/sysconfig/network-scripts/ifcfg-{{ lsr_connection_name }} + __initscripts_route_file_path: /etc/sysconfig/network-scripts/route-{{ lsr_connection_name }} + __initscripts_route6_file_path: /etc/sysconfig/network-scripts/route6-{{ lsr_connection_name }} + __check_route: "{{ lsr_connection_settings | selectattr('ifcfg_route_value', 'defined') | selectattr('ifcfg_route_value') | + map(attribute='ifcfg_route_value') | list | length > 0 }}" + __check_route6: "{{ lsr_connection_settings | selectattr('ifcfg_route6_value', 'defined') | selectattr('ifcfg_route6_value') | + map(attribute='ifcfg_route6_value') | list | length > 0 }}" + block: + - name: Show connection file + command: cat {{ __initscripts_connection_file_path | quote }} + changed_when: false + when: ansible_verbosity | int >= 2 + + - name: Slurp connection file + slurp: + src: "{{ __initscripts_connection_file_path }}" + register: __initscripts_connection_file + + - name: Assert settings in initscripts connection file + assert: + that: __initscripts_connection_item in __initscripts_connection_file.content | b64decode + loop: "{{ lsr_connection_settings | selectattr('ifcfg_value', 'defined') | selectattr('ifcfg_value') | + map(attribute='ifcfg_value') | list }}" + loop_control: + loop_var: __initscripts_connection_item + + - name: Slurp route file + when: __check_route + slurp: + src: "{{ __initscripts_route_file_path }}" + register: __initscripts_route_file + + - name: Assert settings in initscripts route file + when: __check_route + assert: + that: __initscripts_route_item in __initscripts_route_file.content | b64decode + loop: "{{ lsr_connection_settings | selectattr('ifcfg_route_value', 'defined') | selectattr('ifcfg_route_value') | + map(attribute='ifcfg_route_value') | list }}" + loop_control: + loop_var: __initscripts_route_item + + - name: Slurp route6 file + when: __check_route6 + slurp: + src: "{{ __initscripts_route6_file_path }}" + register: __initscripts_route6_file + + - name: Assert settings in initscripts route6 file + when: __check_route6 + assert: + that: __initscripts_route6_item in __initscripts_route6_file.content | b64decode + loop: "{{ lsr_connection_settings | selectattr('ifcfg_route6_value', 'defined') | selectattr('ifcfg_route6_value') | + map(attribute='ifcfg_route6_value') | list }}" + loop_control: + loop_var: __initscripts_route6_item diff --git a/tests/tasks/assert_controller_device_present.yml b/tests/tasks/assert_controller_device_present.yml index 7d387cd5a..a5b671d70 100644 --- a/tests/tasks/assert_controller_device_present.yml +++ b/tests/tasks/assert_controller_device_present.yml @@ -3,4 +3,4 @@ - name: Import the task 'assert_device_present.yml' import_tasks: tasks/assert_device_present.yml vars: - interface: "{{ controller_device }}" + lsr_interface: "{{ controller_device }}" diff --git a/tests/tasks/assert_device_absent.yml b/tests/tasks/assert_device_absent.yml index ce4634fe7..1799b06d6 100644 --- a/tests/tasks/assert_device_absent.yml +++ b/tests/tasks/assert_device_absent.yml @@ -2,7 +2,7 @@ --- - name: Include the task 'get_interface_stat.yml' include_tasks: get_interface_stat.yml -- name: "Assert that the interface is absent - '{{ interface }}'" +- name: "Assert that the interface is absent - '{{ lsr_interface | d(interface) }}'" assert: that: not interface_stat.stat.exists - msg: "{{ interface }} exists" + msg: "{{ lsr_interface | d(interface) }} exists" diff --git a/tests/tasks/assert_device_present.yml b/tests/tasks/assert_device_present.yml index 8a2f47cae..29ca2f75b 100644 --- a/tests/tasks/assert_device_present.yml +++ b/tests/tasks/assert_device_present.yml @@ -2,7 +2,9 @@ --- - name: Include the task 'get_interface_stat.yml' include_tasks: get_interface_stat.yml -- name: "Assert that the interface is present - '{{ interface }}'" + when: ansible_connection != 'buildah' +- name: "Assert that the interface is present - '{{ lsr_interface | d(interface) }}'" assert: that: interface_stat.stat.exists - msg: "{{ interface }} does not exist" + msg: "{{ lsr_interface | d(interface) }} does not exist" + when: ansible_connection != 'buildah' diff --git a/tests/tasks/assert_dhcp_device_present.yml b/tests/tasks/assert_dhcp_device_present.yml index 84fb5de6c..909744ba2 100644 --- a/tests/tasks/assert_dhcp_device_present.yml +++ b/tests/tasks/assert_dhcp_device_present.yml @@ -3,8 +3,8 @@ - name: Import the task 'assert_device_present.yml' import_tasks: tasks/assert_device_present.yml vars: - interface: "{{ dhcp_interface1 }}" + lsr_interface: "{{ dhcp_interface1 }}" - name: Import the task 'assert_device_present.yml' import_tasks: tasks/assert_device_present.yml vars: - interface: "{{ dhcp_interface2 }}" + lsr_interface: "{{ dhcp_interface2 }}" diff --git a/tests/tasks/assert_nm_connection_status.yml b/tests/tasks/assert_nm_connection_status.yml new file mode 100644 index 000000000..7fc80e240 --- /dev/null +++ b/tests/tasks/assert_nm_connection_status.yml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Inputs +# - lsr_connection_name: the connection name +# - lsr_connection_output: the output pattern to search for +# - network_provider: the network provider +--- +- name: Assert NM connection status + when: + - lsr_connection_name is defined + - lsr_connection_output is defined + - network_provider == "nm" + - __network_is_booted + block: + - name: Show connection status + command: nmcli connection show {{ lsr_connection_name | quote }} + changed_when: false + register: __lsr_nm_connection_status + + - name: Assert connection status + assert: + that: __lsr_nm_connection_status.stdout is search(lsr_connection_output) diff --git a/tests/tasks/check_network_dns.yml b/tests/tasks/check_network_dns.yml index 0bb3b2428..6f8e39af6 100644 --- a/tests/tasks/check_network_dns.yml +++ b/tests/tasks/check_network_dns.yml @@ -20,6 +20,7 @@ ls -alrtF /etc/resolv.* || : fi changed_when: false + when: __network_is_booted | d(true) | bool - name: Verify DNS and network connectivity shell: | @@ -35,5 +36,7 @@ exit 1 fi done - when: ansible_facts["distribution"] == "CentOS" changed_when: false + when: + - ansible_facts["distribution"] == "CentOS" + - __network_is_booted | d(true) | bool diff --git a/tests/tasks/cleanup_profile+device.yml b/tests/tasks/cleanup_profile+device.yml index 07021e01b..0e8d92bff 100644 --- a/tests/tasks/cleanup_profile+device.yml +++ b/tests/tasks/cleanup_profile+device.yml @@ -2,10 +2,10 @@ --- - name: Cleanup profile and device shell: | - nmcli con delete {{ interface }} - nmcli con load /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - rm -f /etc/sysconfig/network-scripts/ifcfg-{{ interface }} - ip link del {{ interface }} + nmcli con delete {{ lsr_interface | d(interface) }} + nmcli con load /etc/sysconfig/network-scripts/ifcfg-{{ lsr_interface | d(interface) }} + rm -f /etc/sysconfig/network-scripts/ifcfg-{{ lsr_interface | d(interface) }} + ip link del {{ lsr_interface | d(interface) }} ignore_errors: true # noqa ignore-errors changed_when: false ... diff --git a/tests/tasks/cleanup_vlan_and_parent_profile+device.yml b/tests/tasks/cleanup_vlan_and_parent_profile+device.yml index be5bc9043..b0cf4d7d4 100644 --- a/tests/tasks/cleanup_vlan_and_parent_profile+device.yml +++ b/tests/tasks/cleanup_vlan_and_parent_profile+device.yml @@ -19,8 +19,8 @@ persistent_state: absent state: down failed_when: false - - name: Delete the device '{{ interface }}' - command: ip link del {{ interface }} + - name: Delete the device '{{ lsr_interface | d(interface) }}' + command: ip link del {{ lsr_interface | d(interface) }} failed_when: false changed_when: false ... diff --git a/tests/tasks/create_bond_port_match_by_mac.yml b/tests/tasks/create_bond_port_match_by_mac.yml index 5de8133e2..9decd2768 100644 --- a/tests/tasks/create_bond_port_match_by_mac.yml +++ b/tests/tasks/create_bond_port_match_by_mac.yml @@ -2,7 +2,7 @@ --- - name: Retrieve perm_hwaddr using ethtool # wokeignore:rule=slave - command: cat /sys/class/net/{{ interface }}/bonding_slave/perm_hwaddr + command: cat /sys/class/net/{{ lsr_interface | d(interface) }}/bonding_slave/perm_hwaddr register: mac_address_result changed_when: false failed_when: mac_address_result.rc != 0 @@ -11,7 +11,7 @@ mac: "{{ mac_address_result.stdout_lines[-1].split(' ')[-1] }}" - name: Display the retrieved MAC address debug: - msg: "Retrieved MAC address for {{ interface }}: {{ mac }}" + msg: "Retrieved MAC address for {{ lsr_interface | d(interface) }}: {{ mac }}" - name: Test matching the port device based on the perm_hwaddr import_role: name: linux-system-roles.network @@ -20,6 +20,6 @@ - name: "{{ profile }}" state: up type: ethernet - interface_name: "{{ interface }}" + interface_name: "{{ lsr_interface | d(interface) }}" mac: "{{ mac }}" ... diff --git a/tests/tasks/create_bond_profile.yml b/tests/tasks/create_bond_profile.yml deleted file mode 100644 index 3624ec0c2..000000000 --- a/tests/tasks/create_bond_profile.yml +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause ---- -- name: Include network role - include_role: - name: linux-system-roles.network - vars: - network_connections: - # Create a bond controller - - name: "{{ controller_profile }}" - state: up - type: bond - interface_name: "{{ controller_device }}" - bond: - mode: 802.3ad - ad_actor_sys_prio: 65535 - ad_actor_system: 00:00:5e:00:53:5d - ad_select: stable - ad_user_port_key: 1023 - all_ports_active: true - downdelay: 0 - lacp_rate: slow - lp_interval: 128 - miimon: 110 - min_links: 0 - num_grat_arp: 64 - primary_reselect: better - resend_igmp: 225 - updelay: 0 - use_carrier: true - xmit_hash_policy: encap2+3 - ip: - route_metric4: 65535 - - # add an ethernet to the bond - - name: "{{ port1_profile }}" - state: up - type: ethernet - interface_name: "{{ dhcp_interface1 }}" - controller: "{{ controller_profile }}" - # add a second ethernet to the bond - - name: "{{ port2_profile }}" - state: up - type: ethernet - interface_name: "{{ dhcp_interface2 }}" - controller: "{{ controller_profile }}" -- name: Show result - debug: - var: __network_connections_result -... diff --git a/tests/tasks/create_bond_profile_reconfigure.yml b/tests/tasks/create_bond_profile_reconfigure.yml deleted file mode 100644 index 323c2d0ca..000000000 --- a/tests/tasks/create_bond_profile_reconfigure.yml +++ /dev/null @@ -1,36 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause ---- -- name: Reconfigure the bond options - import_role: - name: linux-system-roles.network - vars: - network_connections: - # Create a bond controller - - name: "{{ controller_profile }}" - state: up - type: bond - interface_name: "{{ controller_device }}" - bond: - mode: active-backup - arp_interval: 60 - arp_ip_target: 192.0.2.128 - arp_validate: none - primary: "{{ dhcp_interface1 }}" - ip: - route_metric4: 65535 - # add an ethernet to the bond - - name: "{{ port1_profile }}" - state: up - type: ethernet - interface_name: "{{ dhcp_interface1 }}" - controller: "{{ controller_profile }}" - # add a second ethernet to the bond - - name: "{{ port2_profile }}" - state: up - type: ethernet - interface_name: "{{ dhcp_interface2 }}" - controller: "{{ controller_profile }}" -- name: Show result - debug: - var: __network_connections_result -... diff --git a/tests/tasks/create_bridge_profile.yml b/tests/tasks/create_bridge_profile.yml index 4eb22481b..621f9faab 100644 --- a/tests/tasks/create_bridge_profile.yml +++ b/tests/tasks/create_bridge_profile.yml @@ -5,7 +5,7 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" persistent_state: present type: bridge ip: diff --git a/tests/tasks/create_bridge_profile_no_autoconnect.yml b/tests/tasks/create_bridge_profile_no_autoconnect.yml index f93ec5dba..ceb6fd97b 100644 --- a/tests/tasks/create_bridge_profile_no_autoconnect.yml +++ b/tests/tasks/create_bridge_profile_no_autoconnect.yml @@ -5,7 +5,7 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" autoconnect: false persistent_state: present type: bridge diff --git a/tests/tasks/create_dummy_profile.yml b/tests/tasks/create_dummy_profile.yml index 1e65ac605..93ee6a0e9 100644 --- a/tests/tasks/create_dummy_profile.yml +++ b/tests/tasks/create_dummy_profile.yml @@ -5,7 +5,7 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" autoconnect_retries: "{{ autocon_retries }}" state: up type: dummy diff --git a/tests/tasks/create_mac_address_match.yml b/tests/tasks/create_mac_address_match.yml index 412127bb9..c11053796 100644 --- a/tests/tasks/create_mac_address_match.yml +++ b/tests/tasks/create_mac_address_match.yml @@ -5,12 +5,12 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" state: up persistent_state: present autoconnect: true type: ethernet - interface_name: "{{ interface }}" + interface_name: "{{ lsr_interface | d(interface) }}" mac: "{{ mac }}" ip: dhcp4: false @@ -20,7 +20,7 @@ state: up persistent_state: present type: vlan - parent: "{{ interface }}" + parent: "{{ lsr_interface | d(interface) }}" vlan: id: 3732 autoconnect: true @@ -35,7 +35,7 @@ state: up persistent_state: present type: vlan - parent: "{{ interface }}" + parent: "{{ lsr_interface | d(interface) }}" vlan: id: 120 autoconnect: true diff --git a/tests/tasks/create_team_profile.yml b/tests/tasks/create_team_profile.yml index 5d8ea72d8..d4c94683f 100644 --- a/tests/tasks/create_team_profile.yml +++ b/tests/tasks/create_team_profile.yml @@ -6,7 +6,7 @@ vars: network_allow_restart: true network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" persistent_state: present type: team ip: diff --git a/tests/tasks/create_test_interfaces_with_dhcp.yml b/tests/tasks/create_test_interfaces_with_dhcp.yml index 28d8eef0d..56b548c8e 100644 --- a/tests/tasks/create_test_interfaces_with_dhcp.yml +++ b/tests/tasks/create_test_interfaces_with_dhcp.yml @@ -143,3 +143,17 @@ --dhcp-host 52:54:00:12:34:56,ignore --dhcp-host 52:54:00:12:34:57,ignore fi changed_when: false + when: ansible_connection != "buildah" + +# When doing bootc validation, have to restart NetworkManager services +# to pick up newly created devices +- name: Restart NetworkManager services for testing + service: + name: "{{ item }}" + state: restarted + loop: + - NetworkManager.service + - NetworkManager-wait-online.service + when: + - network_provider == "nm" + - __bootc_validation | d(false) diff --git a/tests/tasks/create_wireless_profile_restart_network.yml b/tests/tasks/create_wireless_profile_restart_network.yml index 6e8505f6d..661c61e57 100644 --- a/tests/tasks/create_wireless_profile_restart_network.yml +++ b/tests/tasks/create_wireless_profile_restart_network.yml @@ -8,7 +8,7 @@ vars: network_allow_restart: '{{ wifi_restart_network }}' network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" type: wireless wireless: ssid: "My WPA2-PSK Network" diff --git a/tests/tasks/delete_interface.yml b/tests/tasks/delete_interface.yml index 228852e7a..47060ce89 100644 --- a/tests/tasks/delete_interface.yml +++ b/tests/tasks/delete_interface.yml @@ -1,7 +1,10 @@ # SPDX-License-Identifier: BSD-3-Clause --- - name: Remove test interface if necessary - command: "ip link del {{ interface }}" - ignore_errors: true # noqa ignore-errors - changed_when: false + command: ip link del {{ lsr_interface | d(interface) | quote }} + changed_when: true + register: __delete_interface_result + failed_when: + - __delete_interface_result.rc != 0 + - __delete_interface_result.stderr is not search("Cannot find device") ... diff --git a/tests/tasks/down_profile.yml b/tests/tasks/down_profile.yml index 25db269e2..f2a55bbc6 100644 --- a/tests/tasks/down_profile.yml +++ b/tests/tasks/down_profile.yml @@ -7,3 +7,4 @@ network_connections: - name: "{{ profile }}" state: down + persistent_state: "{{ lsr_persistent_state | d('present') }}" diff --git a/tests/tasks/find+remove_profile.yml b/tests/tasks/find+remove_profile.yml index fae7a7ac6..574f038af 100644 --- a/tests/tasks/find+remove_profile.yml +++ b/tests/tasks/find+remove_profile.yml @@ -1,15 +1,15 @@ # SPDX-License-Identifier: BSD-3-Clause --- -- name: Get connection profile for '{{ interface }}' +- name: Get connection profile for '{{ lsr_interface | d(interface) }}' shell: executable: /bin/bash cmd: | set -euo pipefail - connection="$(nmcli -g GENERAL.CONNECTION device show {{ interface | quote }})" || : + connection="$(nmcli -g GENERAL.CONNECTION device show {{ lsr_interface | d(interface) | quote }})" || : if [ -z "$connection" ]; then - nmcli device connect {{ interface | quote }} 1>&2 + nmcli device connect {{ lsr_interface | d(interface) | quote }} 1>&2 fi - nmcli -g GENERAL.CONNECTION device show {{ interface | quote }} + nmcli -g GENERAL.CONNECTION device show {{ lsr_interface | d(interface) | quote }} register: connection_name changed_when: false @@ -22,7 +22,7 @@ nmcli device status || : nmcli device show || : nmcli connection show || : - nmcli connection show '{{ interface }}' || : + nmcli connection show '{{ lsr_interface | d(interface) }}' || : ip a echo connection_name: {{ connection_name | to_nice_json | quote }} || : ls -alrtF /etc/sysconfig/network-scripts || : @@ -59,7 +59,7 @@ when: connection_name is failed or connection_name.stdout | length == 0 failed_when: connection_name is failed or connection_name.stdout | length == 0 -- name: Bring down and delete the connection profile for '{{ interface }}' +- name: Bring down and delete the connection profile for '{{ lsr_interface | d(interface) }}' include_role: name: linux-system-roles.network vars: diff --git a/tests/tasks/get_interface_stat.yml b/tests/tasks/get_interface_stat.yml index a8b8e5b91..3ec309ace 100644 --- a/tests/tasks/get_interface_stat.yml +++ b/tests/tasks/get_interface_stat.yml @@ -1,9 +1,9 @@ # SPDX-License-Identifier: BSD-3-Clause --- -- name: "Get stat for interface {{ interface }}" +- name: "Get stat for interface {{ lsr_interface | d(interface) }}" stat: get_attributes: false get_checksum: false get_mime: false - path: "/sys/class/net/{{ interface }}" + path: "/sys/class/net/{{ lsr_interface | d(interface) }}" register: interface_stat diff --git a/tests/tasks/get_profile_stat.yml b/tests/tasks/get_profile_stat.yml index f4f501e18..c609bec10 100644 --- a/tests/tasks/get_profile_stat.yml +++ b/tests/tasks/get_profile_stat.yml @@ -22,8 +22,15 @@ # When certain profile is marked as absent but still up, the `nmcli connection` # still show it with FILENAME starting with /run. Only consider profile exists # when its FILENAME is in /etc folder +# in the non-booted case, we can predict the profile path from nm_offline backend - name: Get NM profile info - shell: nmcli -f NAME,FILENAME connection show |grep {{ profile }} | grep /etc + vars: + nm_profile_cmd: >- + {{ "nmcli -f NAME,FILENAME connection show | grep " ~ profile ~ " | grep /etc" + if __network_is_booted + else "test -s /etc/NetworkManager/system-connections/" ~ profile ~ ".nmconnection" }} + # noqa command-instead-of-shell + shell: "{{ nm_profile_cmd }}" register: nm_profile_exists ignore_errors: true changed_when: false diff --git a/tests/tasks/handle_assert_task.yml b/tests/tasks/handle_assert_task.yml new file mode 100644 index 000000000..d262cd63c --- /dev/null +++ b/tests/tasks/handle_assert_task.yml @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- name: Handle assert task file + include_tasks: "{{ lsr_assert_item }}" + when: lsr_assert_item is string + +- name: Handle assert task with condition and variables + include_tasks: "{{ lsr_assert_item['what'] }}" + when: + - lsr_assert_item is mapping + - lsr_assert_item.get("condition", true) + vars: + lsr_connection_name: "{{ lsr_assert_item.get('lsr_connection_name', '') }}" + lsr_connection_settings: "{{ lsr_assert_item.get('lsr_connection_settings', []) }}" + lsr_connection_output: "{{ lsr_assert_item.get('lsr_connection_output', '') }}" + lsr_packages: "{{ lsr_assert_item.get('lsr_packages', []) }}" + lsr_command: "{{ lsr_assert_item.get('lsr_command', '') }}" + lsr_shell: "{{ lsr_assert_item.get('lsr_shell', '') }}" + lsr_stdout: "{{ lsr_assert_item.get('lsr_stdout', '') }}" + lsr_stdout_lines: "{{ lsr_assert_item.get('lsr_stdout_lines', []) }}" + lsr_stdout_regex_list: "{{ lsr_assert_item.get('lsr_stdout_regex_list', []) }}" + lsr_stderr: "{{ lsr_assert_item.get('lsr_stderr', '') }}" + lsr_not_stdout: "{{ lsr_assert_item.get('lsr_not_stdout', '') }}" + lsr_not_stderr: "{{ lsr_assert_item.get('lsr_not_stderr', '') }}" + profile: "{{ lsr_assert_item.get('profile', '') }}" diff --git a/tests/tasks/handle_cleanup_task.yml b/tests/tasks/handle_cleanup_task.yml new file mode 100644 index 000000000..61354c6f1 --- /dev/null +++ b/tests/tasks/handle_cleanup_task.yml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- name: Handle cleanup task file + include_tasks: "{{ lsr_cleanup_item }}" + when: lsr_cleanup_item is string + +- name: Handle cleanup task with condition and variables + include_tasks: "{{ lsr_cleanup_item['what'] }}" + when: + - lsr_cleanup_item is mapping + - lsr_cleanup_item.get("condition", true) + vars: + profile: "{{ lsr_cleanup_item.get('profile', interface | d('')) }}" + state: "{{ lsr_cleanup_item.get('state', 'present') }}" + lsr_persistent_state: "{{ lsr_cleanup_item.get('lsr_persistent_state', '') }}" diff --git a/tests/tasks/handle_setup_task.yml b/tests/tasks/handle_setup_task.yml new file mode 100644 index 000000000..a41fcff84 --- /dev/null +++ b/tests/tasks/handle_setup_task.yml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- name: Handle setup task file + include_tasks: "{{ lsr_setup_item }}" + when: lsr_setup_item is string + +- name: Handle setup task with condition and variables + include_tasks: "{{ lsr_setup_item['what'] }}" + when: + - lsr_setup_item is mapping + - lsr_setup_item.get("condition", true) + vars: + state: "{{ lsr_setup_item.get('state', 'present') }}" + lsr_interface: "{{ lsr_setup_item.get('lsr_interface', interface | d('')) }}" + lsr_packages: "{{ lsr_setup_item.get('lsr_packages', []) }}" + lsr_command: "{{ lsr_setup_item.get('lsr_command', '') }}" + lsr_shell: "{{ lsr_setup_item.get('lsr_shell', '') }}" + lsr_stdout: "{{ lsr_setup_item.get('lsr_stdout', '') }}" + lsr_stdout_lines: "{{ lsr_setup_item.get('lsr_stdout_lines', []) }}" + lsr_stdout_regex_list: "{{ lsr_setup_item.get('lsr_stdout_regex_list', []) }}" + lsr_stderr: "{{ lsr_setup_item.get('lsr_stderr', '') }}" + lsr_not_stdout: "{{ lsr_setup_item.get('lsr_not_stdout', '') }}" + lsr_not_stderr: "{{ lsr_setup_item.get('lsr_not_stderr', '') }}" diff --git a/tests/tasks/handle_test_task.yml b/tests/tasks/handle_test_task.yml new file mode 100644 index 000000000..c2d246ba1 --- /dev/null +++ b/tests/tasks/handle_test_task.yml @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- name: Handle test task file + include_tasks: "{{ lsr_test_item }}" + when: lsr_test_item is string + +- name: Handle test task with network role + when: + - lsr_test_item is mapping + - lsr_test_item.get("network_connections") is not none + - lsr_test_item.get("condition", true) + block: + - name: Include network role + include_role: + name: linux-system-roles.network + vars: + network_connections: "{{ lsr_test_item['network_connections'] }}" + + - name: Show result + debug: + var: __network_connections_result diff --git a/tests/tasks/manage_test_interface.yml b/tests/tasks/manage_test_interface.yml index fcf7f5281..b397a4c99 100644 --- a/tests/tasks/manage_test_interface.yml +++ b/tests/tasks/manage_test_interface.yml @@ -25,51 +25,73 @@ delay: 10 # veth -- name: Create veth interface {{ interface }} +- name: Create veth interface {{ lsr_interface | d(interface) }} command: "{{ item }}" with_items: - - ip link add {{ interface }} type veth peer name peer{{ interface }} - - ip link set peer{{ interface }} up - - ip link set {{ interface }} up - when: "type == 'veth' and state == 'present' and - interface not in current_interfaces" + - ip link add {{ lsr_interface | d(interface) }} type veth peer name peer{{ lsr_interface | d(interface) }} + - ip link set peer{{ lsr_interface | d(interface) }} up + - ip link set {{ lsr_interface | d(interface) }} up + when: + - ansible_connection != 'buildah' + - type == 'veth' + - state == 'present' + - lsr_interface | d(interface) not in current_interfaces changed_when: false + - name: Set up veth as managed by NetworkManager - command: nmcli d set {{ interface }} managed true + command: nmcli d set {{ lsr_interface | d(interface) }} managed true # The variable for `network_provider` is not exists yet, # just ignore error for initscripts ignore_errors: true # noqa ignore-errors - when: "type == 'veth' and state == 'present'" + when: + - ansible_connection != 'buildah' + - type == 'veth' + - state == 'present' changed_when: false -- name: Delete veth interface {{ interface }} - command: ip link del {{ interface }} type veth - when: "type == 'veth' and state == 'absent' and - interface in current_interfaces" +- name: Delete veth interface {{ lsr_interface | d(interface) }} + command: ip link del {{ lsr_interface | d(interface) }} type veth + when: + - ansible_connection != 'buildah' + - type == 'veth' + - state == 'absent' + - lsr_interface | d(interface) in current_interfaces changed_when: false # dummy -- name: Create dummy interface {{ interface }} - command: ip link add "{{ interface }}" type dummy - when: "type == 'dummy' and state == 'present' and - interface not in current_interfaces" +- name: Create dummy interface {{ lsr_interface | d(interface) }} + command: ip link add "{{ lsr_interface | d(interface) }}" type dummy + when: + - ansible_connection != 'buildah' + - type == 'dummy' + - state == 'present' + - lsr_interface | d(interface) not in current_interfaces changed_when: false -- name: Delete dummy interface {{ interface }} - command: ip link del "{{ interface }}" type dummy - when: "type == 'dummy' and state == 'absent' and - interface in current_interfaces" +- name: Delete dummy interface {{ lsr_interface | d(interface) }} + command: ip link del "{{ lsr_interface | d(interface) }}" type dummy + when: + - ansible_connection != 'buildah' + - type == 'dummy' + - state == 'absent' + - lsr_interface | d(interface) in current_interfaces changed_when: false # tap -- name: Create tap interface {{ interface }} - command: ip tuntap add dev {{ interface }} mode tap - when: "type == 'tap' and state == 'present' - and interface not in current_interfaces" +- name: Create tap interface {{ lsr_interface | d(interface) }} + command: ip tuntap add dev {{ lsr_interface | d(interface) }} mode tap + when: + - ansible_connection != 'buildah' + - type == 'tap' + - state == 'present' + - lsr_interface | d(interface) not in current_interfaces changed_when: false -- name: Delete tap interface {{ interface }} - command: ip tuntap del dev {{ interface }} mode tap - when: "type == 'tap' and state == 'absent' and - interface in current_interfaces" +- name: Delete tap interface {{ lsr_interface | d(interface) }} + command: ip tuntap del dev {{ lsr_interface | d(interface) }} mode tap + when: + - ansible_connection != 'buildah' + - type == 'tap' + - state == 'absent' + - lsr_interface | d(interface) in current_interfaces changed_when: false diff --git a/tests/tasks/remove+down_profile.yml b/tests/tasks/remove+down_profile.yml index 19cbfeea9..322768554 100644 --- a/tests/tasks/remove+down_profile.yml +++ b/tests/tasks/remove+down_profile.yml @@ -5,7 +5,7 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface }}" + - name: "{{ lsr_interface | d(interface) }}" persistent_state: absent state: down ... diff --git a/tests/tasks/remove_package.yml b/tests/tasks/remove_package.yml index 731348a54..429a1eae5 100644 --- a/tests/tasks/remove_package.yml +++ b/tests/tasks/remove_package.yml @@ -4,3 +4,4 @@ package: name: "{{ package }}" state: absent + when: not __network_is_ostree | d(false) diff --git a/tests/tasks/run_test.yml b/tests/tasks/run_test.yml index 61b669b9a..fd07282a1 100644 --- a/tests/tasks/run_test.yml +++ b/tests/tasks/run_test.yml @@ -6,9 +6,16 @@ debug: msg: "########## {{ lsr_description }} ##########" + - name: Include network role vars used by tests + include_role: + name: linux-system-roles.network + tasks_from: set_facts.yml + public: true + when: __network_is_booted is not defined + - name: Show item debug: - var: "{{ item }}" + msg: item {{ item | default("UNDEFINED") | to_nice_json }} loop: - lsr_description - lsr_setup @@ -22,27 +29,50 @@ include_tasks: tasks/show_interfaces.yml - name: Setup - include_tasks: "{{ item }}" + include_tasks: tasks/handle_setup_task.yml loop: "{{ lsr_setup }}" + loop_control: + loop_var: lsr_setup_item tags: - "tests::setup" - name: Test - include_tasks: "{{ item }}" + include_tasks: tasks/handle_test_task.yml loop: "{{ lsr_test }}" + loop_control: + loop_var: lsr_test_item + when: not __bootc_validation | default(false) tags: - "tests::test" - - name: Asserts - include_tasks: "{{ item }}" - loop: "{{ lsr_assert }}" - tags: - - "tests::assert" + # When validation is enabled, we need to load the role variables + # and set the result because we aren't running the role to set + # the network connections - that was already done at build time + - name: Handle case where validation is enabled + when: __bootc_validation | default(false) + block: + - name: Load role variables + include_role: + name: linux-system-roles.network + tasks_from: set_facts.yml + public: true - - name: Conditional asserts - include_tasks: "{{ item['what'] }}" - when: item['condition'] - loop: "{{ lsr_assert_when | default([]) }}" + - name: Set result + set_fact: + __network_connections_result: + failed: false + stderr: "" + stdout: "" + changed: true + stdout_lines: [] + stderr_lines: [] + + # You can use either lsr_assert or lsr_assert_when - but not both + - name: Asserts + include_tasks: tasks/handle_assert_task.yml + loop: "{{ (lsr_assert | default([])) + (lsr_assert_when | default([])) }}" + loop_control: + loop_var: lsr_assert_item - name: "Success in test '{{ lsr_description }}'" debug: @@ -55,7 +85,7 @@ - name: Show item that failed debug: - var: "{{ item }}" + var: "{{ item | d('UNDEFINED') }}" loop: "{{ lsr_fail_debug | default([]) }}" - name: Issue failed message @@ -63,9 +93,19 @@ msg: "!!!!! Failure in test '{{ lsr_description }}' !!!!!" always: + - name: Create QEMU deployment during bootc end-to-end test + delegate_to: localhost + command: "{{ lsr_scriptdir | quote }}/bootc-buildah-qcow.sh {{ ansible_host | quote }}" + changed_when: true + when: ansible_connection == "buildah" + + # skip cleanup if building with buildah - name: Cleanup - include_tasks: "{{ item }}" + include_tasks: tasks/handle_cleanup_task.yml loop: "{{ lsr_cleanup }}" + loop_control: + loop_var: lsr_cleanup_item + when: ansible_connection != "buildah" tags: - "tests::cleanup" ... diff --git a/tests/tasks/setup_802_1x_server.yml b/tests/tasks/setup_802_1x_server.yml index 0041a5a54..605aa3217 100644 --- a/tests/tasks/setup_802_1x_server.yml +++ b/tests/tasks/setup_802_1x_server.yml @@ -3,6 +3,7 @@ - name: Debug debug: msg: facts {{ ansible_facts | to_nice_json }} + when: ansible_verbosity | default(0) >= 3 # This task can be removed once the RHEL-8.5 is not tested anymore - name: Install hostapd via CentOS Stream @@ -66,6 +67,7 @@ # Enable forwarding of EAP 802.1x messages through software bridge "br1". echo 8 > /sys/class/net/br1/bridge/group_fwd_mask changed_when: false + when: __network_is_booted - name: Create hostapd config copy: @@ -98,3 +100,20 @@ - name: Run hostapd in namespace shell: ip netns exec ns1 hostapd -B /etc/hostapd/wired.conf && sleep 5 changed_when: false + when: __network_is_booted + +# Reload test connection - nm tries to start the connection at boot +# but fails because the devices are not created yet - so restart the connection +# here after the devices are created and hostapd is running +- name: Reload test connection + shell: + executable: /bin/bash + cmd: | + set -euo pipefail + exec 1>&2 + nmcli connection down {{ lsr_interface | d(interface) }} || : + nmcli connection up {{ lsr_interface | d(interface) }} + changed_when: false + when: + - network_provider == "nm" + - __bootc_validation | default(false) diff --git a/tests/tasks/show_interfaces.yml b/tests/tasks/show_interfaces.yml index 42874984d..f4f507ede 100644 --- a/tests/tasks/show_interfaces.yml +++ b/tests/tasks/show_interfaces.yml @@ -2,6 +2,8 @@ --- - name: Include the task 'get_current_interfaces.yml' include_tasks: get_current_interfaces.yml + when: ansible_connection != 'buildah' - name: Show current_interfaces debug: msg: "current_interfaces: {{ current_interfaces }}" + when: ansible_connection != 'buildah' diff --git a/tests/tasks/test_802.1x_capath.yml b/tests/tasks/test_802.1x_capath.yml index a8355282c..50e66a460 100644 --- a/tests/tasks/test_802.1x_capath.yml +++ b/tests/tasks/test_802.1x_capath.yml @@ -55,7 +55,7 @@ name: linux-system-roles.network vars: network_connections: - - name: "{{ interface | default('802-1x-test') }}" + - name: "{{ lsr_interface | d(interface | d('802-1x-test')) }}" interface_name: veth2 state: up type: ethernet