From 069e0b8d577ce0980588635650539ca73da0fe5b Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Thu, 20 Dec 2018 15:30:29 -0600 Subject: [PATCH] Make modprobe module check for builtins as well (#37150) Without this modprobe always reports changed when modprobe-ing a builtin module. With this, if a kernel module is a builtin, the modprobe module will: - succeed (without incorrectly reporting changed) if ``state`` is ``present``; - fail if ``state`` is ``absent`` The failure will have whatever error message modprobe returns when attempting to remove a builtin module. For example: ``modprobe: ERROR: Module nfs is builtin.`` --- ...obe_module_check_for_builtins_as_well.yaml | 3 +++ .../rst/porting_guides/porting_guide_2.8.rst | 7 ++++++ lib/ansible/modules/system/modprobe.py | 22 +++++++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/37150-make_modprobe_module_check_for_builtins_as_well.yaml diff --git a/changelogs/fragments/37150-make_modprobe_module_check_for_builtins_as_well.yaml b/changelogs/fragments/37150-make_modprobe_module_check_for_builtins_as_well.yaml new file mode 100644 index 0000000000..6c0bf80004 --- /dev/null +++ b/changelogs/fragments/37150-make_modprobe_module_check_for_builtins_as_well.yaml @@ -0,0 +1,3 @@ +--- +bugfixes: +- "modprobe - The modprobe module now detects builtin kernel modules. If a kernel module is builtin the modprobe module will now: succeed (without incorrectly reporting changed) if ``state`` is ``present``; and fail if ``state`` is ``absent`` (with an error message like ``modprobe: ERROR: Module nfs is builtin.``). (https://github.com/ansible/ansible/pull/37150)" diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.8.rst b/docs/docsite/rst/porting_guides/porting_guide_2.8.rst index af622c1e8b..97bda532f7 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.8.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.8.rst @@ -131,6 +131,13 @@ Noteworthy module changes * The ``na_ontap_cluster_peer`` module has replaced ``source_intercluster_lif`` and ``dest_intercluster_lif`` string options with ``source_intercluster_lifs`` and ``dest_intercluster_lifs`` list options +* The ``modprobe`` module now detects kernel builtins. Previously, attempting to remove (with ``state: absent``) + a builtin kernel module succeeded without any error message because ``modprobe`` did not detect the module as + ``present``. Now, ``modprobe`` will fail if a kernel module is builtin and ``state: absent`` (with an error message + from the modprobe binary like ``modprobe: ERROR: Module nfs is builtin.``), and it will succeed without reporting + changed if ``state: present``. Any playbooks that are using ``changed_when: no`` to mask this quirk can safely + remove that workaround. To get the previous behavior when applying ``state: absent`` to a builtin kernel module, + use ``failed_when: false`` or ``ignore_errors: true`` in your playbook. Plugins ======= diff --git a/lib/ansible/modules/system/modprobe.py b/lib/ansible/modules/system/modprobe.py index ca53092185..b102e0c76a 100644 --- a/lib/ansible/modules/system/modprobe.py +++ b/lib/ansible/modules/system/modprobe.py @@ -83,14 +83,22 @@ def main(): # Check if module is present try: - modules = open('/proc/modules') present = False - module_name = name.replace('-', '_') + ' ' - for line in modules: - if line.startswith(module_name): - present = True - break - modules.close() + with open('/proc/modules') as modules: + module_name = name.replace('-', '_') + ' ' + for line in modules: + if line.startswith(module_name): + present = True + break + if not present: + command = [module.get_bin_path('uname', True), '-r'] + rc, uname_kernel_release, err = module.run_command(command) + module_file = '/' + name + '.ko' + with open('/lib/modules/' + uname_kernel_release + '/modules.builtin') as builtins: + for line in builtins: + if line.endswith(module_file): + present = True + break except IOError as e: module.fail_json(msg=to_native(e), exception=traceback.format_exc(), **result)