From 4f0a6f2a0fed63aa67d5b13c49a7c08bd691b96c Mon Sep 17 00:00:00 2001 From: jgoutin Date: Thu, 3 Oct 2019 14:49:14 +0200 Subject: [PATCH] Handle reboot if kernel changed. --- README.md | 13 +--------- defaults/main.yml | 3 +++ filter_plugins/main.py | 26 ++++++++++++++++---- handlers/main.yml | 3 +++ molecule/default/playbook.yml | 2 ++ tasks/main.yml | 46 +++++++++++++++++++++++++++++------ 6 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 handlers/main.yml diff --git a/README.md b/README.md index 3effd11..645e21b 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ Requirements The role requires to be run as root on the target host. -The system requires to be rebooted to apply the kernel change. - The specified Kernel version must be supported by OS repositories (This include "Vault" repositories for Red hat based distributions). Role Variables @@ -19,6 +17,7 @@ Role Variables * **install_kernel_headers**: If True, also install matching kernel headers. Default to `true`. * **kernel_version**: Install the most recent kernel version available that start by this value. Default to `''`. +* **reboot_on_kernel_update**: If True, reboot the system if the kernel was updated. Default to `true`. Example Playbook ---------------- @@ -30,16 +29,6 @@ Example Playbook - role: accelize.linux_kernel vars: kernel_version: 3.10.0-693 - - tasks: - # Reboot to apply the kernel change - - name: Ensure system is rebooted - reboot: - # If kernel version is required in a following step, update facts to get - # the new kernel version - - name: Ensure Ansible facts are up to date - setup: - ``` Dependencies diff --git a/defaults/main.yml b/defaults/main.yml index bf333a1..8dc7ce8 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -4,3 +4,6 @@ install_kernel_headers: true # Kernel version to install (Default to latest available) kernel_version: '' + +# Reboot if kernel was updated +reboot_on_kernel_update: true diff --git a/filter_plugins/main.py b/filter_plugins/main.py index 7514462..347dde4 100644 --- a/filter_plugins/main.py +++ b/filter_plugins/main.py @@ -59,7 +59,7 @@ def rhel_repo(packages, kernel_version): return _rhel_kernel_info(packages, kernel_version)['repo'] -def _deb_kernel_info(packages, kernel_version): +def deb_kernel(packages, kernel_version): """ Return best matching kernel version. @@ -133,7 +133,7 @@ def _deb_kernel_package(kernel, dist, arch, name): return '-'.join((name, kernel, suffix)) -def deb_kernel(packages, kernel_version, dist, arch, name): +def deb_kernel_pkg(packages, kernel_version, dist, arch, name): """ Return kernel package to install. @@ -148,7 +148,7 @@ def deb_kernel(packages, kernel_version, dist, arch, name): str: kernel package to install. """ return _deb_kernel_package( - _deb_kernel_info(packages, kernel_version), dist, arch, name) + deb_kernel(packages, kernel_version), dist, arch, name) def deb_installed_kernel(installed, packages, kernel_version): @@ -164,7 +164,7 @@ def deb_installed_kernel(installed, packages, kernel_version): list of str: Kernel packages to remove. """ # Filter installed package to keep - to_keep = _deb_kernel_info(packages, kernel_version) + to_keep = deb_kernel(packages, kernel_version) # Return installed package to remove to_remove = [] @@ -182,6 +182,20 @@ def deb_installed_kernel(installed, packages, kernel_version): return to_remove +def kernel_match(kernel, kernel_spec): + """ + Check if kernel version match. + + Args: + kernel (str): Kernel + kernel_spec (str): Kernel to match. + + Returns: + bool: True if Kernel match. + """ + return kernel.startswith(kernel_spec) + + class FilterModule(object): """Return filter plugin""" @@ -191,4 +205,6 @@ def filters(): return {'rhel_kernel': rhel_kernel, 'rhel_repo': rhel_repo, 'deb_kernel': deb_kernel, - 'deb_installed_kernel': deb_installed_kernel} + 'deb_kernel_pkg': deb_kernel_pkg, + 'deb_installed_kernel': deb_installed_kernel, + 'kernel_match': kernel_match} diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..1e248ce --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,3 @@ +--- +- name: Update facts + setup: diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml index 6e68318..cad68be 100644 --- a/molecule/default/playbook.yml +++ b/molecule/default/playbook.yml @@ -3,3 +3,5 @@ hosts: all roles: - role: ansible-role-linux-kernel + vars: + reboot_on_kernel_update: false diff --git a/tasks/main.yml b/tasks/main.yml index 0318858..e61c3b3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -10,9 +10,13 @@ - ansible_distribution_major_version == "7" register: yum_kernel_list -- name: Install kernel with YUM +- name: Set target YUM kernel version + set_fact: _kernel="{{ yum_kernel_list | rhel_kernel(kernel_version) }}" + when: yum_kernel_list is not skipped + +- name: Ensure kernel packages versions with YUM yum: - name: "{{ item.name }}-{{ yum_kernel_list | rhel_kernel(kernel_version) }}" + name: "{{ item.name }}-{{ _kernel }}" enablerepo: "{{ yum_kernel_list | rhel_repo(kernel_version) }}" allow_downgrade: true when: @@ -37,9 +41,13 @@ - ansible_distribution_major_version != "7" register: dnf_kernel_list -- name: Install kernel with DNF +- name: Set target DNF kernel version + set_fact: _kernel="{{ dnf_kernel_list | rhel_kernel(kernel_version) }}" + when: dnf_kernel_list is not skipped + +- name: Ensure kernel packages versions with DNF dnf: - name: "{{ item.name }}-{{ dnf_kernel_list | rhel_kernel(kernel_version) }}" + name: "{{ item.name }}-{{ _kernel }}" enablerepo: "{{ dnf_kernel_list | rhel_repo(kernel_version) }}" allow_downgrade: true when: @@ -74,9 +82,13 @@ - ansible_os_family == 'Debian' register: apt_packages_list -- name: Install kernel with APT +- name: Set target APT kernel version + set_fact: _kernel="{{ apt_kernel_list | deb_kernel(kernel_version) }}" + when: apt_kernel_list is not skipped + +- name: Ensure kernel packages versions with APT apt: - name: "{{ apt_kernel_list | deb_kernel( + name: "{{ apt_kernel_list | deb_kernel_pkg( kernel_version, ansible_distribution, ansible_architecture, item.name) }}" when: @@ -88,10 +100,30 @@ - name: linux-headers when: install_kernel_headers | bool -- name: Remove previous kernels with APT +- name: Ensure any other kernel packages are removed with APT apt: name: "{{ apt_packages_list | deb_installed_kernel( apt_kernel_list, kernel_version) }}" state: absent purge: true when: ansible_os_family == 'Debian' + +- name: Get /var/run/reboot-required stat + # Note: Should exist on Debian based OS if reboot is required + stat: + path: /var/run/reboot-required + register: reboot_flag + +- name: Notify about Kernel update and reboot requierement + debug: + msg: 'REBOOT REQUIRED, kernel version changed + from {{ ansible_kernel }} to {{ _kernel }}.' + when: + - (not (ansible_kernel | kernel_match(_kernel)) or reboot_flag.stat.exists) + +- name: Ensure the new kernel is enabled by rebooting + reboot: + when: + - reboot_on_kernel_update | bool + - (not (ansible_kernel | kernel_match(_kernel)) or reboot_flag.stat.exists) + notify: 'Update facts'