diff --git a/README.md b/README.md index 06ce7a1..b6a6993 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,12 @@ Variables The `network` role is configured via variables starting with `network_` as the name prefix. List of variables: -* `network_provider` - The `network_provider` variable allows to set a specific - provider (`nm` or `initscripts`) . Setting it to `{{ network_provider_os_default }}`, - the provider is set depending on the operating system. This is usually `nm` - except for RHEL 6 or CentOS 6 systems. +* `network_provider` - The `network_provider` variable allows to set a specific provider + (`nm` or `initscripts`) . Setting it to `{{ network_provider_os_default }}`, the + provider is set depending on the operating system. This is usually `nm` except for + RHEL 6 or CentOS 6 systems. Changing the provider for an existing profile is not + supported. To switch providers, it is recommended to first remove profiles with the + old provider and then create new profiles with the new provider. * `network_connections` - The connection profiles are configured as `network_connections`, which is a list of dictionaries that include specific options. * `network_allow_restart` - Certain configurations require the role to restart network services. diff --git a/library/network_connections.py b/library/network_connections.py index bc13856..e8ee347 100644 --- a/library/network_connections.py +++ b/library/network_connections.py @@ -8,6 +8,7 @@ import os import re import shlex import socket +import subprocess import time import traceback @@ -2340,6 +2341,36 @@ class Cmd_initscripts(Cmd): return None return f + def forget_nm_connection(self, path): + """ + Forget a NetworkManager connection by loading the path of the deleted + profile. This inverts the effect of loading a profile with + `NM_CONTROLLED=no` earlier, which made NetworkManager ignore the + device. + + This does not use the Python libnm bindings because they might not be + present on the system, since the module is currently operating for the + initscripts provider. If it fails, assume that NetworkManager is not + present and did not save any state about the corresponding interface. + """ + try: + subprocess.call( + [ + "busctl", + "--system", + "call", + "org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager/Settings", + "org.freedesktop.NetworkManager.Settings", + "LoadConnections", + "as", + "1", + path, + ] + ) + except Exception: + pass + def run_action_absent(self, idx): n = self.connections[idx]["name"] name = n @@ -2371,6 +2402,7 @@ class Cmd_initscripts(Cmd): if self.check_mode == CheckMode.REAL_RUN: try: os.unlink(path) + self.forget_nm_connection(path) except Exception as e: self.log_error( idx, "delete ifcfg-rh file '%s' failed: %s" % (path, e) diff --git a/tests/ensure_provider_tests.py b/tests/ensure_provider_tests.py index 776803e..eebee4e 100755 --- a/tests/ensure_provider_tests.py +++ b/tests/ensure_provider_tests.py @@ -61,12 +61,16 @@ RUN_PLAYBOOK_WITH_NM = """# SPDX-License-Identifier: BSD-3-Clause MINIMUM_VERSION = "minimum_version" EXTRA_RUN_CONDITION = "extra_run_condition" NM_ONLY_TESTS = { + "playbooks/tests_802_1x_updated.yml": {}, + "playbooks/tests_802_1x.yml": {}, "playbooks/tests_ethtool_features.yml": { MINIMUM_VERSION: "'1.20.0'", "comment": "# NetworkManager 1.20.0 introduced ethtool settings support", }, - "playbooks/tests_802_1x_updated.yml": {}, - "playbooks/tests_802_1x.yml": {}, + "playbooks/tests_provider.yml": { + MINIMUM_VERSION: "'1.20.0'", + "comment": "# NetworKmanager 1.20.0 added support for forgetting profiles", + }, "playbooks/tests_reapply.yml": {}, # mac80211_hwsim (used for tests_wireless) only seems to be available # and working on RHEL/CentOS 7 diff --git a/tests/playbooks/tests_provider.yml b/tests/playbooks/tests_provider.yml new file mode 100644 index 0000000..1db2d08 --- /dev/null +++ b/tests/playbooks/tests_provider.yml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- hosts: all + vars: + interface: testnic1 + profile: "{{ interface }}" + lsr_fail_debug: + - __network_connections_result + tasks: + - debug: + msg: "this is: playbooks/tests_states.yml" + tags: + - always + + + - block: + - include_tasks: tasks/run_test.yml + vars: + state: present + lsr_description: I can manage a veth interface with NM after I + managed it with initscripts. + lsr_setup: + - tasks/setup_test_interface.yml + # run role once with defaults but nm provider to ensure that + # NetworKManager is running + - tasks/provider/default_with_nm.yml + - tasks/provider/create_and_remove_with_initscripts.yml + lsr_test: + - tasks/provider/create_with_nm.yml + lsr_assert: + - tasks/assert_profile_present.yml + lsr_cleanup: + - tasks/cleanup_profile+device.yml + tags: + - tests::provider:initscripts_to_nm diff --git a/tests/tasks/provider/create_and_remove_with_initscripts.yml b/tests/tasks/provider/create_and_remove_with_initscripts.yml new file mode 100644 index 0000000..fd011cb --- /dev/null +++ b/tests/tasks/provider/create_and_remove_with_initscripts.yml @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- include_role: + name: linux-system-roles.network + vars: + network_connections: + - name: "{{ interface }}" + state: up + persistent_state: present + type: ethernet + autoconnect: yes + ip: + address: 192.0.2.1/24 + network_provider: initscripts +- include_role: + name: linux-system-roles.network + vars: + network_connections: + - name: "{{ interface }}" + state: down + persistent_state: absent + network_provider: initscripts +... diff --git a/tests/tasks/provider/create_with_nm.yml b/tests/tasks/provider/create_with_nm.yml new file mode 100644 index 0000000..077841c --- /dev/null +++ b/tests/tasks/provider/create_with_nm.yml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- include_role: + name: linux-system-roles.network + vars: + network_connections: + - name: "{{ interface }}" + state: up + persistent_state: present + type: ethernet + autoconnect: yes + ip: + address: 192.0.2.1/24 + network_provider: nm +... diff --git a/tests/tasks/provider/default_with_nm.yml b/tests/tasks/provider/default_with_nm.yml new file mode 100644 index 0000000..967bb7f --- /dev/null +++ b/tests/tasks/provider/default_with_nm.yml @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- include_role: + name: linux-system-roles.network + vars: + network_connections: [] + network_provider: nm +... diff --git a/tests/tasks/setup_test_interface.yml b/tests/tasks/setup_test_interface.yml new file mode 100644 index 0000000..fb767f3 --- /dev/null +++ b/tests/tasks/setup_test_interface.yml @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: BSD-3-Clause +--- +- include_tasks: tasks/manage_test_interface.yml + vars: + state: present + type: veth +... diff --git a/tests/tests_provider_nm.yml b/tests/tests_provider_nm.yml new file mode 100644 index 0000000..db0c1c6 --- /dev/null +++ b/tests/tests_provider_nm.yml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: BSD-3-Clause +# This file was generated by ensure_provider_tests.py +--- +# set network provider and gather facts +- hosts: all + name: Run playbook 'playbooks/tests_provider.yml' with nm as provider + tasks: + - name: Set network provider to 'nm' + set_fact: + network_provider: nm + tags: + - always + + - block: + - name: Install NetworkManager + package: + name: NetworkManager + state: present + - name: Get NetworkManager version + command: rpm -q --qf "%{version}" NetworkManager + args: + warn: false + register: NetworkManager_version + when: true + when: + - ansible_distribution_major_version != '6' + tags: + - always + + +# workaround for: https://github.com/ansible/ansible/issues/27973 +# There is no way in Ansible to abort a playbook hosts with specific OS +# releases Therefore we include the playbook with the tests only if the hosts +# would support it. +# The test requires or should run with NetworkManager, therefore it cannot run +# on RHEL/CentOS 6 +- import_playbook: playbooks/tests_provider.yml + when: + - ansible_distribution_major_version != '6' + + - NetworkManager_version.stdout is version('1.20.0', '>=')