From c0d7bda31d7d7ec3beb7ca174a7343f5419ed83d Mon Sep 17 00:00:00 2001 From: Sergei Petrosian Date: Fri, 27 Oct 2023 15:14:14 +0200 Subject: [PATCH] feat: Initialize a bootloader role Add bootloader_facts.py Add bootloader_settings module to configure settings instead of tasks Add unit tests for bootloader_settings and bootloader_facts --- README.md | 247 +++++++++++++++--- defaults/main.yml | 14 +- examples/simple.yml | 8 - handlers/main.yml | 28 +- library/bootloader_facts.py | 161 ++++++++++++ library/bootloader_settings.py | 193 ++++++++++++++ meta/main.yml | 67 +---- pytest_extra_requirements.txt | 4 +- tasks/main.yml | 83 ++++-- tasks/reboot.yml | 16 ++ templates/bootloader.conf.j2 | 9 - .../linux-system-roles.bootloader/library | 1 + .../linux-system-roles.bootloader/templates | 1 - tests/tests_password.yml | 34 +++ tests/tests_settings.yml | 151 +++++++++++ tests/unit/test_bootloader_facts.py | 107 ++++++++ tests/unit/test_bootloader_settings.py | 167 ++++++++++++ vars/CentOS_6.yml | 7 - vars/CentOS_7.yml | 7 - vars/Fedora.yml | 7 - vars/RedHat_6.yml | 7 - vars/RedHat_7.yml | 7 - vars/main.yml | 11 +- 23 files changed, 1150 insertions(+), 187 deletions(-) delete mode 100644 examples/simple.yml create mode 100644 library/bootloader_facts.py create mode 100644 library/bootloader_settings.py create mode 100644 tasks/reboot.yml delete mode 100644 templates/bootloader.conf.j2 create mode 120000 tests/roles/linux-system-roles.bootloader/library delete mode 120000 tests/roles/linux-system-roles.bootloader/templates create mode 100644 tests/tests_password.yml create mode 100644 tests/tests_settings.yml create mode 100644 tests/unit/test_bootloader_facts.py create mode 100644 tests/unit/test_bootloader_settings.py delete mode 100644 vars/CentOS_6.yml delete mode 100644 vars/CentOS_7.yml delete mode 100644 vars/Fedora.yml delete mode 100644 vars/RedHat_6.yml delete mode 100644 vars/RedHat_7.yml diff --git a/README.md b/README.md index 1fcdfc0..e86c624 100644 --- a/README.md +++ b/README.md @@ -6,66 +6,237 @@ An Ansible role for bootloader and kernel command line management. ## Requirements -Any pre-requisites that may not be covered by Ansible itself or the role should -be mentioned here. For instance, if the role uses the EC2 module, it may be a -good idea to mention in this section that the `boto` package is required. +None ## Role Variables -A description of all input variables (i.e. variables that are defined in -`defaults/main.yml`) for the role should go here as these form an API of the -role. +### bootloader_gather_facts -Variables that are not intended as input, like variables defined in -`vars/main.yml`, variables that are read from other roles and/or the global -scope (ie. hostvars, group vars, etc.) can be also mentioned here but keep in -mind that as these are probably not part of the role API they may change during -the lifetime. +Whether to gather `bootloader_facts` that contain bot information for all kernels. -Example of setting the variables: +Default: `false` + +Type: `bool` + +### bootloader_settings + +With this variable, list kernels and their command line parameters that you want to set. + +Required keys: + +1. `kernel` - with this, specify the kernel to update settings for. +You can specify one or more kernels using the following criteria, you can use only single criteria at a time: + + * `kernel_path` - a specific kernel path, can be a list of paths + * `kernel_index` - a specific kernel index, can be a list of indexes + * `kernel_title` - a specific kernel title, can be a list of titles + * `DEFAULT` - to update the default entry + * `ALL` - to update all of the entries + +2. `options` - with this, specify settings to update + + * `name` - The name of the setting. `name` is omitted when using `replaced`. + * `value` - The value for the setting. You must omit `value` if the setting has no value, e.g. `quiet`. + * `state` - `present` (default) or `absent`. The value `absent` means to remove a setting with `name` name - name must be provided. + * `previous` - Optional - the only value is `replaced` - this is used to specify that the previous settings should be replaced with the given settings. + +Example: ```yaml -bootloader_foo: "oof" -bootloader_bar: "baz" +bootloader_settings: + - kernel: + kernel_path: /boot/vmlinuz-0-rescue-1 + options: + - name: console + value: tty0 + state: present + - previous: replaced + - kernel: + kernel_index: [1, 2, 3] + options: + - name: print-fatal-signals + value: 1 + - kernel: + kernel_title: Red Hat Enterprise Linux (4.1.1.1.el8.x86_64) 8 + options: + - name: no_timer_check + - kernel: + kernel_path: /boot/vmlinuz-0-rescue-1 + options: + - name: console + value: tty0 + - name: print-fatal-signals + value: 1 + - name: no_timer_check + state: present + - previous: replaced + - kernel: ALL + options: + - name: debug + state: present + - kernel: DEFAULT + options: + - name: quiet + state: present ``` +Default: `{}` + +Type: `dict` + +### bootloader_timeout + +With this variable, you can customize the loading time of the GRUB bootloader. + +Default: `5` + +Type: `int` + +### bootloader_password + +With this variable, you can protect boot parameters with a password. + +__WARNING__: Changing bootloader password is not idempotent. + +Boot loader username is always `root`. + +This should come from vault. + +If unset, current configuration is not touched. + +Default: `null` + +Type: `string` + +### bootloader_remove_password + +By setting this variable to `true`, you can remove bootloader password. + +Default: `false` + +Type: `bool` + +### bootloader_reboot_ok + +If `true`, if the role detects that something was changed that requires a reboot to take effect, the role will reboot the managed host. + +If `false`, it is up to you to determine when to reboot the managed host. + +The role will returns the variable `bootloader_reboot_required` (see below) with a value of `true` to indicate that some change has occurred which needs a reboot to take effect. + +Default: `false` + +Type: `bool` + ### Variables Exported by the Role -This section is optional. Some roles may export variables for playbooks to -use later. These are analogous to "return values" in Ansible modules. For -example, if a role performs some action that will require a system reboot, but -the user wants to defer the reboot, the role might set a variable like -`bootloader_reboot_needed: true` that the playbook can use to reboot at a more -convenient time. +The role exports the following variables: -Example: +#### bootloader_reboot_needed -`bootloader_reboot_needed` - default `false` - if `true`, this means -a reboot is needed to apply the changes made by the role +Default `false` - if `true`, this means a reboot is needed to apply the changes made by the role -## Example Playbook +#### bootloader_facts -Including an example of how to use your role (for instance, with variables -passed in as parameters) is always nice for users too: +Contains boot information for all kernels. + +The role returns this variable when you set `bootloader_gather_facts: true`. + +For example: + +```yaml +"bootloader_facts": [ + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet", + "id": "luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet", + "index": "3", + "initrd": "/boot/initramfs-0-rescue-c44543d15b2c4e898912c2497f734e67.img", + "kernel": "/boot/vmlinuz-0-rescue-c44543d15b2c4e898912c2497f734e67", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (0-rescue-c44543d15b2c4e898912c2497f734e67) 36 (Workstation Edition)", + "default": True + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "id": "luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "index": "2", + "initrd": "/boot/initramfs-6.3.12-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.3.12-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.3.12-100.fc37.x86_64) 37 (Workstation Edition)", + "default": False + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "id": "luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "index": "1", + "initrd": "/boot/initramfs-6.4.15-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.4.15-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.4.15-100.fc37.x86_64) 37 (Workstation Edition)", + "default": False + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "id": "luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "index": "0", + "initrd": "/boot/initramfs-6.5.7-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.5.7-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.5.7-100.fc37.x86_64) 37 (Workstation Edition)", + "default": False + } +] +``` + +## Example Playbook ```yaml - hosts: all vars: - bootloader_foo: "foo foo!" - bootloader_bar: "progress bar" - + bootloader_settings: + - kernel: + kernel_path: /boot/vmlinuz-0-rescue-1 + options: + - name: console + value: tty0 + state: present + - previous: replaced + - kernel: + kernel_index: [1, 2, 3] + options: + - name: print-fatal-signals + value: 1 + - kernel: + kernel_title: Red Hat Enterprise Linux (4.1.1.1.el8.x86_64) 8 + options: + - name: no_timer_check + - kernel: + kernel_path: /boot/vmlinuz-0-rescue-1 + options: + - name: console + value: tty0 + - name: print-fatal-signals + value: 1 + - name: no_timer_check + state: present + - previous: replaced + - kernel: ALL + options: + - name: debug + state: present + - kernel: DEFAULT + options: + - name: quiet + state: present + bootloader_timeout: 5 + bootloader_password: null + bootloader_remove_password: false + bootloader_reboot_ok: true roles: - linux-system-roles.bootloader ``` -More examples can be provided in the [`examples/`](examples) directory. These -can be useful especially for documentation. - ## License -Whenever possible, please prefer MIT. - -## Author Information - -An optional section for the role authors to include contact information, or a -website (HTML is not allowed). +MIT diff --git a/defaults/main.yml b/defaults/main.yml index 820e794..d07a753 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,8 +1,10 @@ -# SPDX-License-Identifier: MIT --- -# Here is the right place to put the role's input variables. -# This file also serves as a documentation for such a variables. +bootloader_settings: [] +bootloader_timeout: 5 -# Examples of role input variables: -bootloader_foo: "foo" -bootloader_bar: "bar" +bootloader_password: null +bootloader_remove_password: false + +bootloader_reboot_ok: false + +bootloader_gather_facts: false diff --git a/examples/simple.yml b/examples/simple.yml deleted file mode 100644 index f994e4a..0000000 --- a/examples/simple.yml +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -- name: Example bootloader role invocation - hosts: all - vars: - bootloader_foo: example variable value - roles: - - linux-system-roles.bootloader diff --git a/handlers/main.yml b/handlers/main.yml index 8f99a3f..4d46b2c 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,10 +1,24 @@ # SPDX-License-Identifier: MIT --- -# Put handlers for tasks here. +# EL 7 workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1152027 +- name: Fix default kernel boot parameters + shell: |- + set -o pipefail + grubby --info=DEFAULT | awk '/^args/ {print $0}' + cat {{ __bootloader_default_grub }} + eval $(grubby --info=DEFAULT | awk '/^args/ {print $0}') + sed -i -e "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"$args\"|" \ + {{ __bootloader_default_grub }} + cat {{ __bootloader_default_grub }} + changed_when: true + when: >- + (ansible_distribution in ['CentOS', 'RedHat'] and + ansible_facts.distribution_major_version is version('7', '=')) or + ansible_distribution == 'Fedora' -# Example: -- name: Bootloader handler to restart services - service: - name: "{{ item }}" - state: restarted - loop: "{{ __bootloader_services }}" +- name: Rebuild grub config + command: grub2-mkconfig -o {{ __bootloader_grub_conf }} + changed_when: true + +- name: Reboot system + include_tasks: tasks/reboot.yml diff --git a/library/bootloader_facts.py b/library/bootloader_facts.py new file mode 100644 index 0000000..a423d04 --- /dev/null +++ b/library/bootloader_facts.py @@ -0,0 +1,161 @@ +#!/usr/bin/python + +# Copyright: (c) 2023, Sergei Petrosian +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: bootloader_facts + +short_description: Gather information for kernels as Ansible facts + +version_added: "0.0.1" + +description: + - "WARNING: Do not use this module directly! It is only for role internal use." + - Gather information for kernels as Ansible facts + +author: + - Sergei Petrosian (@spetrosi) +""" + +EXAMPLES = r""" +# Run with no parameters to gather facts +bootloader_facts: +""" + +RETURN = r""" +ansible_facts: + description: Facts to add to ansible_facts. + returned: always + type: complex + contains: + bootloader_facts: + description: Boot information for available kernels + type: list + returned: always + contains: + args: + description: command line arguments passed to the kernel + returned: always + type: str + default: + description: whether this kernel is default + returned: always + type: bool + id: + description: kernel id + returned: always + type: str + index: + description: kernel id + returned: always + type: str + initrd: + description: kernel initrd + returned: always + type: str + kernel: + description: kernel path + returned: always + type: str + root: + description: kernel root + returned: always + type: str + title: + description: kernel title + returned: always + type: str + sample: |- + { + "bootloader_facts": [ + { + "args": "ro rootflags=subvol=root console=tty0 print-fatal-signals=1 no_timer_check quiet debug", + "default": false, + "id": "14339c81a6054561a8effc83d511ce77-6.6.4-100.fc38.x86_64", + "index": "0", + "initrd": "/boot/new_initrd", + "kernel": "/boot/vmlinuz-6.6.4-100.fc38.x86_64", + "root": "UUID=2b95a97a-3f73-4566-b0a3-a11b4e9c3663", + "title": "entry_title" + }, + { + "args": "ro rootflags=subvol=root console=tty0 print-fatal-signals=1 no_timer_check quiet debug", + "default": true, + "id": "890cea0fd7b140cf890eb0145b3caa72-6.6.4-100.fc38.x86_64", + "index": "1", + "initrd": "/boot/initramfs-6.6.4-100.fc38.x86_64.img", + "kernel": "/boot/vmlinuz-6.6.4-100.fc38.x86_64", + "root": "UUID=2b95a97a-3f73-4566-b0a3-a11b4e9c3663", + "title": "Fedora Linux (6.6.4-100.fc38.x86_64) 38 (Cloud Edition)" + } + ] + } +""" + + +import re +from ansible.module_utils.basic import AnsibleModule + + +def get_facts(kernels_info, default_kernel): + kernels_info_lines = kernels_info.strip().split("\n") + kernels = [] + index_count = 0 + for line in kernels_info_lines: + index = re.search(r"index=(\d+)", line) + if index: + is_default = False + index_count += 1 + kernels.append({}) + if index.group(1) == default_kernel.strip(): + is_default = True + search = re.search(r"(.*?)=(.*)", line) + if search: + key = search.group(1).strip('"') + value = search.group(2).strip('"') + kernels[index_count - 1].update({key: value}) + else: + kernels[index_count - 1].update({"kernel": line}) + kernels[index_count - 1].update({"default": is_default}) + return kernels + + +def run_module(): + # define available arguments/parameters a user can pass to the module + module_args = dict() + + # seed the result dict in the object + # we primarily care about changed and state + # changed is if this module effectively modified the target + # state will include any data that you want your module to pass back + # for consumption, for example, in a subsequent task + result = dict(changed=False, ansible_facts=dict(bootloader_facts=dict())) + + # the AnsibleModule object will be our abstraction working with Ansible + # this includes instantiation, a couple of common attr would be the + # args/params passed to the execution, as well as if the module + # supports check mode + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) + + rc, kernels_info, stderr = module.run_command("grubby --info=ALL") + if "Permission denied" in stderr: + module.fail_json(msg="You must run this as sudo", **result) + rc, default_kernel, stderr = module.run_command("grubby --default-index") + result["ansible_facts"]["bootloader_facts"] = get_facts(kernels_info, default_kernel) + + # in the event of a successful module execution, you will want to + # simple AnsibleModule.exit_json(), passing the key/value results + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main() diff --git a/library/bootloader_settings.py b/library/bootloader_settings.py new file mode 100644 index 0000000..8284ea5 --- /dev/null +++ b/library/bootloader_settings.py @@ -0,0 +1,193 @@ +#!/usr/bin/python + +# Copyright: (c) 2023, Sergei Petrosian +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = r""" +--- +module: bootloader_settings + +short_description: Configure grubby boot loader arguments for specified kernels + +version_added: "0.0.1" + +description: + - "WARNING: Do not use this module directly! It is only for role internal use." + - Configure grubby boot loader arguments for specified kernels + +options: + bootloader_settings: + description: List of dict of kernels and their command line parameters that you want to set. + required: true + type: list + elements: dict + +author: + - Sergei Petrosian (@spetrosi) +""" + +EXAMPLES = r""" +- name: Test with a message + bootloader_settings: + bootloader_settings: +""" + +RETURN = r""" +# These are examples of possible return values, and in general should use other names for return values. +# original_message: +# description: The original name param that was passed in. +# type: str +# returned: always +# sample: 'hello world' +# message: +# description: The output message that the test module generates. +# type: str +# returned: always +# sample: 'goodbye' +""" + +import re + +from ansible.module_utils.basic import AnsibleModule + +# import ansible.module_utils.six as ansible_six +import ansible.module_utils.six.moves as ansible_six_moves + + +def escapeval(val): + """make sure val is quoted as in shell""" + return ansible_six_moves.shlex_quote(str(val)) + + +def get_kernels(bootloader_setting_kernel, kernels_keys): + kernels = [] + for kernel_key in kernels_keys: + if ( + kernel_key in bootloader_setting_kernel + and kernel_key != bootloader_setting_kernel + ): + kernel_key_prefix = "" + if kernel_key == "kernel_title": + kernel_key_prefix = "TITLE=" + if not isinstance(bootloader_setting_kernel[kernel_key], list): + kernels.append( + kernel_key_prefix + str(bootloader_setting_kernel[kernel_key]) + ) + else: + for kernel_entry in bootloader_setting_kernel[kernel_key]: + kernels.append(kernel_key_prefix + str(kernel_entry)) + elif kernel_key == bootloader_setting_kernel: + kernels.append(bootloader_setting_kernel) + return kernels + + +def get_boot_args(kernel_info): + args = re.search(r'args="(.*)"', kernel_info) + if args is None: + return "" + return args.group(1).strip() + + +def get_rm_boot_args_cmd(kernel_info, kernel): + bootloader_args = get_boot_args(kernel_info) + if bootloader_args: + return ( + "grubby --update-kernel=" + + kernel + + " --remove-args=" + + escapeval(bootloader_args) + ) + + +def get_mod_boot_args_cmd(bootloader_setting_options, kernel, kernel_info): + boot_absent_args = "" + boot_present_args = "" + boot_mod_args = "" + bootloader_args = get_boot_args(kernel_info) + for kernel_setting in bootloader_setting_options: + if {"previous": "replaced"} == kernel_setting: + continue + if "value" in kernel_setting: + setting_name = kernel_setting["name"] + "=" + str(kernel_setting["value"]) + else: + setting_name = kernel_setting["name"] + if "state" in kernel_setting and kernel_setting["state"] == "absent": + if re.search(r"(^|$| )" + setting_name + r"(^|$| )", bootloader_args): + boot_absent_args += setting_name + " " + else: + if not re.search(r"(^|$| )" + setting_name + r"(^|$| )", bootloader_args): + boot_present_args += setting_name + " " + if boot_absent_args: + boot_mod_args = " --remove-args=" + escapeval(boot_absent_args.strip()) + if len(boot_present_args) > 0: + boot_mod_args += " --args=" + escapeval(boot_present_args.strip()) + if boot_mod_args: + return "grubby --update-kernel=" + kernel + boot_mod_args + + +def run_module(): + # define available arguments/parameters a user can pass to the module + module_args = dict( + bootloader_settings=dict(type="list", required=True, elements="dict") + ) + + # seed the result dict in the object + # we primarily care about changed and state + # changed is if this module effectively modified the target + # state will include any data that you want your module to pass back + # for consumption, for example, in a subsequent task + result = dict(changed=False, actions=list()) + + # the AnsibleModule object will be our abstraction working with Ansible + # this includes instantiation, a couple of common attr would be the + # args/params passed to the execution, as well as if the module + # supports check mode + module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) + kernels_keys = ["kernel_index", "kernel_path", "kernel_title", "DEFAULT", "ALL"] + for bootloader_setting in module.params["bootloader_settings"]: + kernels = get_kernels(bootloader_setting["kernel"], kernels_keys) + if not kernels: + module.fail_json( + msg="bootloader_settings.kernel must contain one of %s" + % ", ".join(kernels_keys), + **result + ) + for kernel in kernels: + kernel = escapeval(kernel) + # Remove all existing boot settings + if {"previous": "replaced"} in bootloader_setting["options"]: + rc, stdout, stderr = module.run_command("grubby --info=" + kernel) + rm_boot_args_cmd = get_rm_boot_args_cmd(stdout, kernel) + if rm_boot_args_cmd: + rc, stdout, stderr = module.run_command(str(rm_boot_args_cmd)) + result["changed"] = True + result["actions"].append(rm_boot_args_cmd) + rc, stdout, stderr = module.run_command("grubby --info=" + kernel) + # Configure boot settings + mod_boot_args_cmd = get_mod_boot_args_cmd( + bootloader_setting["options"], kernel, stdout + ) + if mod_boot_args_cmd: + rc, stdout, stderr = module.run_command(mod_boot_args_cmd) + result["changed"] = True + result["actions"].append(mod_boot_args_cmd) + # if the user is working with this module in only check mode we do not + # want to make any changes to the environment, just return the current + # state with no modifications + # if module.check_mode: + # module.exit_json(**result) + + # in the event of a successful module execution, you will want to + # simple AnsibleModule.exit_json(), passing the key/value results + module.exit_json(**result) + + +def main(): + run_module() + + +if __name__ == "__main__": + main() diff --git a/meta/main.yml b/meta/main.yml index 550ab4d..576519f 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,69 +1,24 @@ # SPDX-License-Identifier: MIT --- galaxy_info: - # Replace with role's author name: - author: John Doe - # Replace with the real description of what is role's purpose: - description: Ansible role for bootloader and kernel command line management - # Replace with the company the role's author is member of: - company: John Doe, Inc. - - # If the issue tracker for your role is not on github, uncomment the next - # line and provide a value - # issue_tracker_url: http://example.com/issue/tracker - - # Some suggested licenses: - # - BSD (default) - # - MIT - # - GPLv2 - # - GPLv3 - # - Apache - # - CC-BY + author: Sergei Petrosian + description: Ansible role for bootloader management + company: Red Hat, Inc. license: MIT - min_ansible_version: "2.9" - - # Optionally specify the branch Galaxy will use when accessing the GitHub - # repo for this role. During role install, if no tags are available, Galaxy - # will use this branch. During import Galaxy will access files on this - # branch. If Travis integration is configured, only notifications for this - # branch will be accepted. Otherwise, in all cases, the repo's default branch - # (usually main) will be used. - # github_branch: - - # - # platforms is a list of platforms, and each platform has a name and a list - # of versions. - # - # platforms: - # - name: Fedora - # versions: - # - all - # - 25 - # - name: SomePlatform - # versions: - # - all - # - 1.0 - # - 7 - # - 99.99 platforms: - # Replace the below with your platform list: - name: Fedora versions: - all - name: EL versions: - - "7" + - "9" - "8" - - galaxy_tags: [] - # List tags for your role here, one per line. A tag is a keyword that - # describes and categorizes the role. Users find roles by searching for tags. - # Be sure to remove the '[]' above, if you add tags to this list. - # - # NOTE: A tag is limited to a single word comprised of alphanumeric - # characters. Maximum 20 tags per role. - + - "7" + galaxy_tags: + - grub + - grubby + - boot + - loader + - bootloader dependencies: [] -# List your role dependencies here, one per line. Be sure to remove the '[]' -# above, if you add dependencies to this list. diff --git a/pytest_extra_requirements.txt b/pytest_extra_requirements.txt index d1e7463..8e11eaa 100644 --- a/pytest_extra_requirements.txt +++ b/pytest_extra_requirements.txt @@ -2,6 +2,6 @@ # Write extra requirements for running pytest here: # If you need ansible then uncomment the following line: -#-ransible_pytest_extra_requirements.txt +-ransible_pytest_extra_requirements.txt # If you need mock then uncomment the following line: -#mock ; python_version < "3.0" +mock ; python_version < "3.0" diff --git a/tasks/main.yml b/tasks/main.yml index 01a8dac..cbf9a0d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,27 +1,76 @@ # SPDX-License-Identifier: MIT --- -# Put the tasks for your role here. - - name: Set platform/version specific variables include_tasks: tasks/set_vars.yml -# Examples of some tasks: - name: Ensure required packages are installed package: name: "{{ __bootloader_packages }}" state: present -- name: Ensure required services are enabled and started - service: - name: "{{ item }}" - state: started - enabled: true - loop: "{{ __bootloader_services }}" - -- name: Generate /etc/{{ __bootloader_foo_config }} - template: - src: "{{ __bootloader_foo_config }}.j2" - dest: /etc/{{ __bootloader_foo_config }} - backup: true - mode: 0400 - notify: Bootloader handler to restart services +- name: Ensure boot loader settings + bootloader_settings: + bootloader_settings: "{{ bootloader_settings }}" + notify: + - Fix default kernel boot parameters + - Reboot system + +- name: Update boot loader timeout configuration + lineinfile: + path: "{{ __bootloader_default_grub }}" + regexp: '^GRUB_TIMEOUT=.*' + line: 'GRUB_TIMEOUT={{ bootloader_timeout }}' + notify: Rebuild grub config + +- name: Determine platform type + stat: + path: /sys/firmware/efi + register: __bootloader_efi_dir + +- name: Set boot loader configuration files + vars: + efi_path: "{{ + ansible_distribution in ['CentOS', 'RedHat'] and + ansible_facts.distribution_major_version | int < 9 and + __bootloader_efi_dir.stat.exists }}" + set_fact: + __bootloader_grub_conf: >- + {{ efi_path | ternary('/boot/efi/EFI/redhat/grub.cfg', + '/boot/grub2/grub.cfg') }} + __bootloader_user_conf: >- + {{ efi_path | ternary('/boot/efi/EFI/redhat/user.cfg', + '/boot/grub2/user.cfg') }} + +- name: Update boot loader password + when: bootloader_password is not none + block: + - name: Generate boot loader password + shell: >- + set -euo pipefail; + ( echo {{ bootloader_password | quote }} ; + echo {{ bootloader_password | quote }} ) + | LC_ALL=C grub2-mkpasswd-pbkdf2 + | grep -v '[eE]nter password:' + | sed -e "s/PBKDF2 hash of your password is //" + register: __bootloader_pass_hash + changed_when: true + no_log: true + + - name: Put boot loader password to {{ __bootloader_user_conf }} + copy: + content: GRUB2_PASSWORD={{ __bootloader_pass_hash.stdout }} + dest: "{{ __bootloader_user_conf }}" + mode: 0600 + changed_when: true + no_log: true + +- name: Remove boot loader password configuration + file: + path: "{{ __bootloader_user_conf }}" + state: absent + when: bootloader_remove_password | bool + +# Keep at the end of tasks to collect latest info +- name: Collect bootloader facts + bootloader_facts: + when: bootloader_gather_facts | bool diff --git a/tasks/reboot.yml b/tasks/reboot.yml new file mode 100644 index 0000000..ad2b730 --- /dev/null +++ b/tasks/reboot.yml @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: MIT +--- +- name: Reboot system when bootloader_reboot_ok is true + reboot: + when: bootloader_reboot_ok | bool + +- name: Notify about reboot + when: not bootloader_reboot_ok + debug: + msg: >- + Boot loader settings have been modified. + A reboot is required in order to apply the changes. + +- name: Set bootloader_reboot_required + set_fact: + bootloader_reboot_required: "{{ not bootloader_reboot_ok }}" diff --git a/templates/bootloader.conf.j2 b/templates/bootloader.conf.j2 deleted file mode 100644 index f0cb29a..0000000 --- a/templates/bootloader.conf.j2 +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# Example of a template of configuration file -# -{{ ansible_managed | comment }} -{{ "system_role:bootloader" | comment(prefix="", postfix="") }} -[foo] -foo = {{ bootloader_foo }} -bar = {{ bootloader_bar }} diff --git a/tests/roles/linux-system-roles.bootloader/library b/tests/roles/linux-system-roles.bootloader/library new file mode 120000 index 0000000..ba40d2f --- /dev/null +++ b/tests/roles/linux-system-roles.bootloader/library @@ -0,0 +1 @@ +../../../library \ No newline at end of file diff --git a/tests/roles/linux-system-roles.bootloader/templates b/tests/roles/linux-system-roles.bootloader/templates deleted file mode 120000 index 0e4c94f..0000000 --- a/tests/roles/linux-system-roles.bootloader/templates +++ /dev/null @@ -1 +0,0 @@ -../../../templates \ No newline at end of file diff --git a/tests/tests_password.yml b/tests/tests_password.yml new file mode 100644 index 0000000..48af347 --- /dev/null +++ b/tests/tests_password.yml @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: MIT +--- +- name: Test bootloader_settings variable + hosts: all + gather_facts: false + tasks: + - name: Set boot loader password + vars: + bootloader_password: test-pass + include_role: + name: linux-system-roles.bootloader + + - name: Get contents of {{ __bootloader_user_conf }} + command: cat {{ __bootloader_user_conf }} + failed_when: >- + not (__bootloader_user_conf_content.stdout | + regex_search('^GRUB2_PASSWORD=grub\.pbkdf2\.sha512\.10000\..*')) + register: __bootloader_user_conf_content + changed_when: false + + - name: Remove boot loader password + vars: + bootloader_remove_password: true + include_role: + name: linux-system-roles.bootloader + + - name: Get stat of {{ __bootloader_user_conf }} + stat: + path: "{{ __bootloader_user_conf }}" + register: __bootloader_user_conf_stat + + - name: Verify that user conf doesn't exist + assert: + that: not __bootloader_user_conf_stat.stat.exists diff --git a/tests/tests_settings.yml b/tests/tests_settings.yml new file mode 100644 index 0000000..653ca30 --- /dev/null +++ b/tests/tests_settings.yml @@ -0,0 +1,151 @@ +# SPDX-License-Identifier: MIT +--- +- name: Test bootloader_settings variable + hosts: all + gather_facts: false + tags: + - tests::reboot + vars: + bootloader_reboot_ok: true + tasks: + - name: Get bootloader_facts + vars: + bootloader_gather_facts: true + include_role: + name: linux-system-roles.bootloader + + - name: Flush handlers + meta: flush_handlers + + - name: Verify that default bootloader is correct in bootloader_gather_facts + vars: + default_bootloader: "{{ + (bootloader_facts | selectattr('index', 'search', '0') | first).kernel + }}" + shell: >- + set -euo pipefail; + grubby --info=DEFAULT; + grubby --info=DEFAULT | + grep -P + 'kernel=("|){{ default_bootloader }}("|)' + changed_when: false + + - name: Replace configuration with settings using kernel_index + vars: + bootloader_gather_facts: true + bootloader_settings: + - kernel: + kernel_index: "{{ + (bootloader_facts | selectattr('index', 'search', '0') | + first).index }}" + options: + - name: console + value: tty0 + - name: print-fatal-signals + value: 1 + - name: no_timer_check + state: present + - name: quiet + - previous: replaced + - kernel: ALL + options: + - name: debug + state: present + bootloader_timeout: 6 + include_role: + name: linux-system-roles.bootloader + + - name: Flush handlers + meta: flush_handlers + + - name: Ensure bootloader_reboot_required is set to false + assert: + that: not (bootloader_reboot_required | d(false)) + + - name: Verify settings + assert: + that: >- + (bootloader_facts | selectattr('index', 'search', '0') | first).args | + regex_search('^.*console=tty0 print-fatal-signals=1 no_timer_check + quiet debug( |)$') + + - name: Verify boot loader timeout configuration + command: cat {{ __bootloader_grub_conf }} + failed_when: >- + not __bootloader_default_grub_content.stdout is regex('set timeout=6') + register: __bootloader_default_grub_content + changed_when: false + + - name: Change some settings using kernel_title + vars: + bootloader_gather_facts: true + bootloader_settings: + - kernel: + kernel_title: "{{ + (bootloader_facts | selectattr('index', 'search', '0') | + first).title }}" + options: + - name: quiet + state: absent + - name: debug + state: absent + bootloader_timeout: 4 + include_role: + name: linux-system-roles.bootloader + + - name: Flush handlers + meta: flush_handlers + + - name: Ensure bootloader_reboot_required is set to false + assert: + that: not (bootloader_reboot_required | d(false)) + + - name: Verify settings + assert: + that: >- + (bootloader_facts | selectattr('index', 'search', '0') | first).args | + regex_search('^.*console=tty0 print-fatal-signals=1 + no_timer_check( |)$') + + - name: Verify boot loader timeout configuration + command: cat {{ __bootloader_grub_conf }} + failed_when: >- + not __bootloader_default_grub_content.stdout is regex('set timeout=4') + register: __bootloader_default_grub_content + changed_when: false + + - name: Set existing variable using kernel_path, should report not changed + vars: + bootloader_settings: + - kernel: + kernel_path: "{{ + (bootloader_facts | selectattr('index', 'search', '0') | + first).kernel }}" + options: + - name: console + value: tty0 + state: present + bootloader_timeout: 4 + include_role: + name: linux-system-roles.bootloader + + - name: Flush handlers + meta: flush_handlers + + - name: Ensure bootloader_reboot_required is not set to true + assert: + that: not bootloader_reboot_required + + - name: Verify settings + assert: + that: >- + (bootloader_facts | selectattr('index', 'search', '0') | first).args + | regex_search('^.*console=tty0 print-fatal-signals=1 + no_timer_check( |)$') + + - name: Verify boot loader timeout configuration + command: cat {{ __bootloader_grub_conf }} + failed_when: >- + not __bootloader_default_grub_content.stdout is regex('set timeout=4') + register: __bootloader_default_grub_content + changed_when: false diff --git a/tests/unit/test_bootloader_facts.py b/tests/unit/test_bootloader_facts.py new file mode 100644 index 0000000..25722c9 --- /dev/null +++ b/tests/unit/test_bootloader_facts.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Sergei Petrosian +# SPDX-License-Identifier: GPL-2.0-or-later +# +""" Unit tests for the bootloader_settings module """ + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import unittest + +import bootloader_facts + +# non linux entry: RHEL 7 might print such a message +INFO = """ +index=0 +kernel="/boot/vmlinuz-6.5.12-100.fc37.x86_64" +args="$tuned_params ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd" +title="Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64" +index=1 +kernel="/boot/vmlinuz-6.5.10-100.fc37.x86_64" +args="ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-6.5.10-100.fc37.x86_64.img $tuned_initrd" +title="Fedora Linux (6.5.10-100.fc37.x86_64) 37 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-6.5.10-100.fc37.x86_64" +index=2 +kernel="/boot/vmlinuz-6.5.7-100.fc37.x86_64" +args="ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-6.5.7-100.fc37.x86_64.img $tuned_initrd" +title="Fedora Linux (6.5.7-100.fc37.x86_64) 37 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-6.5.7-100.fc37.x86_64" +index=3 +kernel="/boot/vmlinuz-0-rescue-c44543d15b2c4e898912c2497f734e67" +args="ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-0-rescue-c44543d15b2c4e898912c2497f734e67.img" +title="Fedora Linux (0-rescue-c44543d15b2c4e898912c2497f734e67) 36 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-0-rescue" +index=4 +non linux entry +""" + +FACTS = [ + { + "args": "$tuned_params ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet", + "id": "c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64", + "index": "0", + "initrd": "/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.5.12-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition)", + "default": False + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "id": "c44543d15b2c4e898912c2497f734e67-6.5.10-100.fc37.x86_64", + "index": "1", + "initrd": "/boot/initramfs-6.5.10-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.5.10-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.5.10-100.fc37.x86_64) 37 (Workstation Edition)", + "default": False + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params", + "id": "c44543d15b2c4e898912c2497f734e67-6.5.7-100.fc37.x86_64", + "index": "2", + "initrd": "/boot/initramfs-6.5.7-100.fc37.x86_64.img $tuned_initrd", + "kernel": "/boot/vmlinuz-6.5.7-100.fc37.x86_64", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (6.5.7-100.fc37.x86_64) 37 (Workstation Edition)", + "default": True + }, + { + "args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet", + "id": "c44543d15b2c4e898912c2497f734e67-0-rescue", + "index": "3", + "initrd": "/boot/initramfs-0-rescue-c44543d15b2c4e898912c2497f734e67.img", + "kernel": "/boot/vmlinuz-0-rescue-c44543d15b2c4e898912c2497f734e67", + "root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285", + "title": "Fedora Linux (0-rescue-c44543d15b2c4e898912c2497f734e67) 36 (Workstation Edition)", + "default": False + }, + { + "index": "4", + "kernel": "non linux entry", + "default": False + }, +] + + +class InputValidator(unittest.TestCase): + """test functions that process bootloader_settings argument""" + + def test_get_facts(self): + kernels = bootloader_facts.get_facts(INFO, "2") + self.assertEqual( + FACTS, + kernels, + ) diff --git a/tests/unit/test_bootloader_settings.py b/tests/unit/test_bootloader_settings.py new file mode 100644 index 0000000..7292ee3 --- /dev/null +++ b/tests/unit/test_bootloader_settings.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Sergei Petrosian +# SPDX-License-Identifier: GPL-2.0-or-later +# +""" Unit tests for the bootloader_settings module """ + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +import unittest + +import bootloader_settings + +OPTIONS = [ + {"name": "arg_with_str_value", "value": "test_value"}, + {"name": "arg_with_int_value", "value": 1, "state": "present"}, + {"name": "arg_without_val", "state": "present"}, + {"name": "arg_with_str_value_absent", "value": "test_value", "state": "absent"}, + {"name": "arg_with_int_value_absent", "value": 1, "state": "absent"}, + {"name": "arg_without_val_absent", "state": "absent"}, + {"previous": "replaced"}, +] + +KERNELS = [ + {"kernel": {"kernel_index": [0, 1]}}, + {"kernel": {"kernel_index": 2}}, + {"kernel": {"kernel_path": ["/path/1", "/path/2"]}}, + {"kernel": {"kernel_path": "/path/3"}}, + { + "kernel": { + "kernel_title": [ + "Fedora Linux (1.1.11-100.fc37.x86_64) 37 (Workstation Edition)", + "Fedora Linux (1.1.11-200.fc37.x86_64) 37 (Workstation Edition)", + ] + }, + }, + { + "kernel": { + "kernel_title": "Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)" + }, + }, + {"kernel": "DEFAULT"}, + {"kernel": "ALL"}, +] + +INFO = """ +index=0 +kernel="/boot/vmlinuz-6.5.12-100.fc37.x86_64" +args="arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd" +title="Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64" +""" + +INFO_RHEL7 = """ +index=0 +kernel=/boot/vmlinuz-6.5.12-100.fc37.x86_64 +args="arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent" +root=UUID=65c70529-e9ad-4778-9001-18fe8c525285 +initrd=/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd +title=Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition) +id=c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64 +""" + +kernels_keys = ["kernel_index", "kernel_path", "kernel_title", "DEFAULT", "ALL"] + + +class InputValidator(unittest.TestCase): + """test functions that process bootloader_settings argument""" + + def test_get_kernels(self): + kernels = bootloader_settings.get_kernels(KERNELS[0]["kernel"], kernels_keys) + self.assertEqual(["0", "1"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[1]["kernel"], kernels_keys) + self.assertEqual(["2"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[2]["kernel"], kernels_keys) + self.assertEqual(["/path/1", "/path/2"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[3]["kernel"], kernels_keys) + self.assertEqual(["/path/3"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[4]["kernel"], kernels_keys) + self.assertEqual( + [ + "TITLE=Fedora Linux (1.1.11-100.fc37.x86_64) 37 (Workstation Edition)", + "TITLE=Fedora Linux (1.1.11-200.fc37.x86_64) 37 (Workstation Edition)", + ], + kernels, + ) + kernels = bootloader_settings.get_kernels(KERNELS[5]["kernel"], kernels_keys) + self.assertEqual( + ["TITLE=Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)"], + kernels, + ) + kernels = bootloader_settings.get_kernels(KERNELS[6]["kernel"], kernels_keys) + self.assertEqual(["DEFAULT"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[7]["kernel"], kernels_keys) + self.assertEqual(["ALL"], kernels) + + def test_get_boot_args(self): + bootloader_args = bootloader_settings.get_boot_args(INFO) + self.assertEqual( + bootloader_args, + "arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent", + ) + bootloader_args = bootloader_settings.get_boot_args(INFO_RHEL7) + self.assertEqual( + bootloader_args, + "arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent", + ) + bootloader_args = bootloader_settings.get_boot_args("") + self.assertEqual(bootloader_args, "") + + def test_get_rm_boot_args_cmd(self): + rm_boot_args_cmd = bootloader_settings.get_rm_boot_args_cmd(INFO, "0") + self.assertEqual( + "grubby --update-kernel=0 --remove-args=" + + "'arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent'", + rm_boot_args_cmd, + ) + + def test_get_mod_boot_args_cmd(self): + args = ( + "--remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent' " + + "--args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'" + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, str(KERNELS[1]["kernel"]["kernel_index"]), INFO + ) + self.assertEqual( + "grubby --update-kernel=2 " + args, + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[3]["kernel"]["kernel_path"], INFO + ) + self.assertEqual( + "grubby --update-kernel=/path/3 " + args, + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, + bootloader_settings.escapeval( + "TITLE=" + KERNELS[5]["kernel"]["kernel_title"] + ), + INFO, + ) + self.assertEqual( + "grubby --update-kernel='TITLE=Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)' " + + args, + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[6]["kernel"], INFO + ) + self.assertEqual( + "grubby --update-kernel=DEFAULT " + args, + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[7]["kernel"], INFO + ) + self.assertEqual( + "grubby --update-kernel=ALL " + args, + mod_boot_args_cmd, + ) diff --git a/vars/CentOS_6.yml b/vars/CentOS_6.yml deleted file mode 100644 index 8309ef0..0000000 --- a/vars/CentOS_6.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 6 specific values. - -# Example: -__bootloader_packages: [] -__bootloader_services: [] diff --git a/vars/CentOS_7.yml b/vars/CentOS_7.yml deleted file mode 100644 index 05b66eb..0000000 --- a/vars/CentOS_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with CentOS 7 specific values. - -# Example: -__bootloader_packages: [] -__bootloader_services: [] diff --git a/vars/Fedora.yml b/vars/Fedora.yml deleted file mode 100644 index 7780fb6..0000000 --- a/vars/Fedora.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Fedora specific values. - -# Example: -__bootloader_packages: [] -__bootloader_services: [] diff --git a/vars/RedHat_6.yml b/vars/RedHat_6.yml deleted file mode 100644 index c5e8383..0000000 --- a/vars/RedHat_6.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 6 specific values. - -# Example: -__bootloader_packages: [] -__bootloader_services: [] diff --git a/vars/RedHat_7.yml b/vars/RedHat_7.yml deleted file mode 100644 index ed78d4c..0000000 --- a/vars/RedHat_7.yml +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: MIT ---- -# Put internal variables here with Red Hat Enterprise Linux 7 specific values. - -# Example: -__bootloader_packages: [] -__bootloader_services: [] diff --git a/vars/main.yml b/vars/main.yml index fd1a957..2b2aa6d 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,13 +1,5 @@ # SPDX-License-Identifier: MIT --- -# Put the role's internal variables here that are not distribution specific. -# You can override these by defining the same variable with a different -# value in a platform/version specific file in vars/ - -# Examples of non-distribution specific (generic) internal variables: -__bootloader_foo_config: "bootloader.conf" -__bootloader_packages: [] -__bootloader_services: [] # ansible_facts required by the role __bootloader_required_facts: - distribution @@ -19,3 +11,6 @@ __bootloader_required_facts: # the 'gather_subset' parameter of the 'setup' module __bootloader_required_facts_subsets: "{{ ['!all', '!min'] + __bootloader_required_facts }}" +__bootloader_packages: + - grubby +__bootloader_default_grub: /etc/default/grub