aboutsummaryrefslogtreecommitdiffstats
path: root/fdio.infra.ansible/roles/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'fdio.infra.ansible/roles/kernel')
-rw-r--r--fdio.infra.ansible/roles/kernel/defaults/main.yaml31
-rw-r--r--fdio.infra.ansible/roles/kernel/filter_plugins/main.py143
-rw-r--r--fdio.infra.ansible/roles/kernel/handlers/main.yaml8
-rw-r--r--fdio.infra.ansible/roles/kernel/tasks/main.yaml9
-rw-r--r--fdio.infra.ansible/roles/kernel/tasks/ubuntu_jammy.yaml62
5 files changed, 253 insertions, 0 deletions
diff --git a/fdio.infra.ansible/roles/kernel/defaults/main.yaml b/fdio.infra.ansible/roles/kernel/defaults/main.yaml
new file mode 100644
index 0000000000..ef628c93f5
--- /dev/null
+++ b/fdio.infra.ansible/roles/kernel/defaults/main.yaml
@@ -0,0 +1,31 @@
+---
+# file: roles/kernel/defaults/main.yaml
+
+# Kernel version to install (Default to any version).
+kernel_version: "{{ kernel_version_by_distro[ansible_distribution|lower][ansible_distribution_release] | join(' ') }}"
+
+kernel_version_by_distro:
+ ubuntu:
+ jammy:
+ - "5.15.0-46"
+
+kernel_packages: "{{ kernel_packages_by_distro[ansible_distribution|lower][ansible_distribution_release] | flatten(levels=1) }}"
+
+kernel_packages_by_distro:
+ ubuntu:
+ jammy:
+ - "linux-image"
+ - "linux-headers"
+ - "linux-modules"
+ - "linux-modules-extra"
+ - "linux-tools"
+
+# Packages to remove in relation to kernel upgrade.
+absent_packages: "{{ absent_packages_by_distro[ansible_distribution|lower][ansible_distribution_release] | flatten(levels=1) }}"
+
+absent_packages_by_distro:
+ ubuntu:
+ jammy:
+ - "amd64-microcode"
+ - "intel-microcode"
+ - "iucode-tool"
diff --git a/fdio.infra.ansible/roles/kernel/filter_plugins/main.py b/fdio.infra.ansible/roles/kernel/filter_plugins/main.py
new file mode 100644
index 0000000000..7d909b90e8
--- /dev/null
+++ b/fdio.infra.ansible/roles/kernel/filter_plugins/main.py
@@ -0,0 +1,143 @@
+
+"""Extra Ansible filters"""
+
+def deb_kernel(packages, kernel_version, current_version):
+ """
+ Return best matching kernel version.
+ Args:
+ packages (dict): apt-cache showpkg output.
+ kernel_version (str): Kernel version to install.
+ current_version (str): Current kernel version.
+ Returns:
+ str: kernel version.
+ """
+ kernels = set()
+
+ # List all available kernel version and associated repository
+ for line in packages['stdout'].splitlines():
+ line = line.strip()
+ if line.startswith('Package: ') and (
+ line.endswith('-common') or # Debian
+ line.endswith('-generic')): # Ubuntu
+ kernel = line.split()[1]
+
+ for string in ('linux-headers-', 'common', 'generic'):
+ kernel = kernel.replace(string, '')
+ kernel = kernel.strip('-')
+
+ if kernel:
+ kernels.add(kernel)
+
+ # Sort Kernel versions
+ versions = {}
+ for kernel in kernels:
+ try:
+ version, build = kernel.split('-', 1)
+ except ValueError:
+ version = kernel
+ build = ''
+ versions[kernel] = list(
+ int(ver) for ver in version.split('.')) + [build]
+ kernels = sorted(versions.keys(), key=versions.get, reverse=True)
+
+ # Return more recent kernel package that match version requirement
+ for kernel in kernels:
+ if kernel.startswith(kernel_version):
+ return kernel
+
+ raise RuntimeError(
+ 'No kernel matching to "%s". Available kernel versions: %s' % (
+ kernel_version, ', '.join(reversed(kernels))))
+
+
+def _deb_kernel_package(kernel, dist, arch, name):
+ """
+ Return kernel package name.
+ Args:
+ kernel (str): Kernel version.
+ dist (str): Distribution.
+ arch (str): Architecture.
+ name (str): Package name.
+ Returns:
+ str: kernel package.
+ """
+ # Define package suffix
+ if dist == 'Ubuntu':
+ suffix = 'generic'
+ elif name == 'linux-image':
+ suffix = arch.replace('x86_64', 'amd64')
+ else:
+ suffix = 'common'
+
+ return '-'.join((name, kernel, suffix))
+
+
+def deb_kernel_pkg(packages, kernel_version, current_version, dist, arch, name):
+ """
+ Return kernel package to install.
+ Args:
+ packages (dict): apt-cache showpkg output.
+ kernel_version (str): Kernel version to install.
+ current_version (str): Current kernel version.
+ dist (str): Distribution.
+ arch (str): Architecture.
+ name (str): Package name.
+ Returns:
+ str: kernel package to install.
+ """
+ return _deb_kernel_package(
+ deb_kernel(packages, kernel_version, current_version), dist, arch, name)
+
+
+def deb_installed_kernel(installed, packages, kernel_version, current_version):
+ """
+ Return old kernel packages to remove.
+ Args:
+ installed (dict): dpkg -l output.
+ packages (dict): apt-cache showpkg output.
+ kernel_version (str): Kernel version to install.
+ current_version (str): Current kernel version.
+ Returns:
+ list of str: Kernel packages to remove.
+ """
+ # Filter installed package to keep
+ to_keep = deb_kernel(packages, kernel_version, current_version)
+
+ # Return installed package to remove
+ to_remove = []
+ for line in installed['stdout'].splitlines():
+ if ' linux-' not in line:
+ continue
+
+ package = line.split()[1]
+ if ((package.startswith('linux-image-') or
+ package.startswith('linux-headers-')) and not (
+ package.startswith('linux-image-' + to_keep) or
+ package.startswith('linux-headers-' + to_keep))):
+ to_remove.append(package)
+
+ 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"""
+
+ @staticmethod
+ def filters():
+ """Return filter"""
+ return {'deb_kernel': deb_kernel,
+ 'deb_kernel_pkg': deb_kernel_pkg,
+ 'deb_installed_kernel': deb_installed_kernel,
+ 'kernel_match': kernel_match}
diff --git a/fdio.infra.ansible/roles/kernel/handlers/main.yaml b/fdio.infra.ansible/roles/kernel/handlers/main.yaml
new file mode 100644
index 0000000000..d0be276a5b
--- /dev/null
+++ b/fdio.infra.ansible/roles/kernel/handlers/main.yaml
@@ -0,0 +1,8 @@
+---
+# file roles/kernel/handlers/main.yaml
+
+- name: Reboot Server
+ ansible.builtin.reboot:
+ reboot_timeout: 3600
+ tags:
+ - reboot-server
diff --git a/fdio.infra.ansible/roles/kernel/tasks/main.yaml b/fdio.infra.ansible/roles/kernel/tasks/main.yaml
new file mode 100644
index 0000000000..431e344fb8
--- /dev/null
+++ b/fdio.infra.ansible/roles/kernel/tasks/main.yaml
@@ -0,0 +1,9 @@
+---
+# file: roles/kernel/tasks/main.yaml
+
+- name: Inst - Prerequisites
+ include_tasks: "{{ ansible_distribution|lower }}_{{ ansible_distribution_release }}.yaml"
+ tags:
+ - kernel-inst-prerequisites
+
+- meta: flush_handlers
diff --git a/fdio.infra.ansible/roles/kernel/tasks/ubuntu_jammy.yaml b/fdio.infra.ansible/roles/kernel/tasks/ubuntu_jammy.yaml
new file mode 100644
index 0000000000..af987d4e5a
--- /dev/null
+++ b/fdio.infra.ansible/roles/kernel/tasks/ubuntu_jammy.yaml
@@ -0,0 +1,62 @@
+---
+# file: roles/kernel/tasks/ubuntu_jammy.yaml
+
+- name: Get Available Kernel Versions
+ ansible.builtin.command: "apt-cache showpkg linux-headers-*"
+ changed_when: false
+ register: apt_kernel_list
+ tags:
+ - kernel-inst
+
+- name: Get installed packages with APT
+ ansible.builtin.command: "dpkg -l"
+ changed_when: false
+ register: apt_packages_list
+ tags:
+ - kernel-inst
+
+- name: Set target APT kernel version
+ ansible.builtin.set_fact:
+ _kernel: "{{ apt_kernel_list | deb_kernel(
+ kernel_version, ansible_kernel) }}"
+ tags:
+ - kernel-inst
+
+- name: Disable APT auto upgrade
+ ansible.builtin.lineinfile:
+ path: "/etc/apt/apt.conf.d/20auto-upgrades"
+ state: "present"
+ regexp: "APT::Periodic::Unattended-Upgrade \"[0-9]\";"
+ line: "APT::Periodic::Unattended-Upgrade \"0\";"
+ create: true
+ mode: 0644
+ tags:
+ - kernel-inst
+
+- name: Ensure Packages Versions
+ ansible.builtin.apt:
+ name: "{{ apt_kernel_list | deb_kernel_pkg(
+ kernel_version, ansible_kernel, ansible_distribution,
+ ansible_architecture, item) }}"
+ loop: "{{ kernel_packages }}"
+ tags:
+ - kernel-inst
+
+- name: Ensure Any Other Kernel Packages Are Removed
+ ansible.builtin.apt:
+ name: "{{ apt_packages_list | deb_installed_kernel(
+ apt_kernel_list, kernel_version, ansible_kernel) }}"
+ state: "absent"
+ purge: true
+ notify:
+ - "Reboot Server"
+ tags:
+ - kernel-inst
+
+- name: Ensure Any Microcode Is Absent
+ ansible.builtin.apt:
+ name: "{{ absent_packages }}"
+ state: "absent"
+ purge: true
+ tags:
+ - kernel-inst