From 6f77a836b546b1e73ff87d26952924a0311ecac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Jeanneret?= Date: Mon, 18 Nov 2024 13:59:07 +0100 Subject: [PATCH] Enable kpatch support for updates This change enables kpatch-patch support, allowing in-place kernel patching for security and bug fixes, provided `kpatch-patch-KERNEL_VERSION` package exists. For more information about kpatch: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_monitoring_and_updating_the_kernel/applying-patches-with-kernel-live-patching_managing-monitoring-and-updating-the-kernel This PR also corrects a potential issue related to the exclide list applied to the package update: if a user were to pass the `edpm_update_exclude_packages` parameter, the subsequent override wouldn't be applied, meaning the `openvswitch` package wouldn't be excluded in the end. Using an "internal var" such as the `_exclude_packages` in order to inject our own content in addition to whatever the user may pass ensures everything is working as expected. Fixes: https://issues.redhat.com/browse/OSPRH-11274 --- roles/edpm_update/defaults/main.yml | 3 + .../edpm_update/molecule/kpatch/converge.yml | 57 +++++++++++++++++++ .../edpm_update/molecule/kpatch/molecule.yml | 27 +++++++++ roles/edpm_update/molecule/kpatch/prepare.yml | 18 ++++++ roles/edpm_update/tasks/kpatch.yml | 29 ++++++++++ roles/edpm_update/tasks/main.yml | 4 ++ roles/edpm_update/tasks/packages.yml | 12 ++-- 7 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 roles/edpm_update/molecule/kpatch/converge.yml create mode 100644 roles/edpm_update/molecule/kpatch/molecule.yml create mode 100644 roles/edpm_update/molecule/kpatch/prepare.yml create mode 100644 roles/edpm_update/tasks/kpatch.yml diff --git a/roles/edpm_update/defaults/main.yml b/roles/edpm_update/defaults/main.yml index 724beab4b..0a78a8407 100644 --- a/roles/edpm_update/defaults/main.yml +++ b/roles/edpm_update/defaults/main.yml @@ -17,6 +17,9 @@ # All variables intended for modification should be placed in this file. +# Toggle to enable/disable kpatch usage +edpm_update_enable_kpatch: false + # Toggle to enable/disable packages updates edpm_update_enable_packages_update: true diff --git a/roles/edpm_update/molecule/kpatch/converge.yml b/roles/edpm_update/molecule/kpatch/converge.yml new file mode 100644 index 000000000..8ae799d44 --- /dev/null +++ b/roles/edpm_update/molecule/kpatch/converge.yml @@ -0,0 +1,57 @@ +--- +# Copyright 2024 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +- name: Converge + hosts: all + gather_facts: false + tasks: + - name: "Call edpm_update role" + ansible.builtin.include_role: + name: osp.edpm.edpm_update + vars: + edpm_update_enable_containers_update: false + edpm_service_types: [] + edpm_update_enable_kpatch: true + + # We have to run the verifications in this play to + # ensure we have access to the internally changed + # facts. + - name: Conduct some verifications + block: + - name: Ensure kernel related packages are excluded + ansible.builtin.assert: + that: + - _exclude_packages is defined + - "'kernel' in _exclude_packages" + - "'kernel-core' in _exclude_packages" + + - name: Gather all installed packages + ansible.builtin.package_facts: + + - name: Check service status if we have kpatch-patch installed + when: + - ansible_facts.packages["kpatch-patch"] is defined + block: + - name: Gather services + ansible.builtin.service_facts: + + - name: Ensure kpatch.service is running + ansible.builtin.assert: + that: + - ansible_facts.services['kpatch.service'] is defined + - ansible_facts.services['kpatch.service'].state == 'running' + - ansible_facts.services['kpatch.service'].status == 'enabled' diff --git a/roles/edpm_update/molecule/kpatch/molecule.yml b/roles/edpm_update/molecule/kpatch/molecule.yml new file mode 100644 index 000000000..e4a784e58 --- /dev/null +++ b/roles/edpm_update/molecule/kpatch/molecule.yml @@ -0,0 +1,27 @@ +--- +dependency: + name: galaxy + options: + role-file: collections.yml +driver: + name: delegated + options: + managed: false + ansible_connection_options: + ansible_connection: local +platforms: + - name: edpm-0.localdomain + groups: + - compute +provisioner: + log: true + name: ansible + +scenario: + test_sequence: + - prepare + - converge + - cleanup + - destroy +verifier: + name: ansible diff --git a/roles/edpm_update/molecule/kpatch/prepare.yml b/roles/edpm_update/molecule/kpatch/prepare.yml new file mode 100644 index 000000000..16404cf35 --- /dev/null +++ b/roles/edpm_update/molecule/kpatch/prepare.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2024 Red Hat, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +- name: Run prepare playbook + ansible.builtin.import_playbook: ../default/prepare.yml diff --git a/roles/edpm_update/tasks/kpatch.yml b/roles/edpm_update/tasks/kpatch.yml new file mode 100644 index 000000000..498105dec --- /dev/null +++ b/roles/edpm_update/tasks/kpatch.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure we know about kernel version + when: + - ansible_facts['kernel'] is undefined + ansible.builtin.setup: + gather_subset: + - '!all,!min' + - 'kernel' + +- name: Ensure kpatch package is installed + become: true + ansible.builtin.package: + name: kpatch + state: present + +- name: Install kpatch-patch if available # noqa: package-latest + failed_when: false + become: true + ansible.builtin.package: + name: "kpatch-patch = {{ ansible_facts['kernel'] }}" + state: latest + +- name: Ensure further update stages will not update kernel + vars: + _kernel: + - kernel + - kernel-core + ansible.builtin.set_fact: + _exclude_packages: "{{ edpm_update_exclude_packages + _kernel }}" diff --git a/roles/edpm_update/tasks/main.yml b/roles/edpm_update/tasks/main.yml index 13bf21642..42f7ad90c 100644 --- a/roles/edpm_update/tasks/main.yml +++ b/roles/edpm_update/tasks/main.yml @@ -17,6 +17,10 @@ # "edpm_update" will search for and load any operating system variable file +- name: Apply kernel patch via kpatch + ansible.builtin.include_tasks: kpatch.yml + when: edpm_update_enable_kpatch + - name: Update packages ansible.builtin.include_tasks: packages.yml when: edpm_update_enable_packages_update diff --git a/roles/edpm_update/tasks/packages.yml b/roles/edpm_update/tasks/packages.yml index fa7b0930b..dc0dccc9c 100644 --- a/roles/edpm_update/tasks/packages.yml +++ b/roles/edpm_update/tasks/packages.yml @@ -9,9 +9,13 @@ - name: Ensure openvswitch is excluded from bulk update ansible.builtin.set_fact: - edpm_update_exclude_packages: "{{ edpm_update_exclude_packages + ['openvswitch'] }}" - when: - "'openvswitch' not in edpm_update_exclude_packages" + _exclude_packages: >- + {{ + _exclude_packages | default([]) + + edpm_update_exclude_packages + + ['openvswitch'] | + ansible.builtin.unique + }} tags: - edpm_update @@ -21,6 +25,6 @@ name: "*" state: latest update_cache: true - exclude: "{{ edpm_update_exclude_packages }}" + exclude: "{{ _exclude_packages }}" tags: - edpm_update