From 8fcb84c0495e364daf65745a9b23b0d6f0a1d51e Mon Sep 17 00:00:00 2001 From: Peter Mikus Date: Fri, 3 Apr 2020 08:14:50 +0000 Subject: [PATCH] Ansible: Kernel installation Signed-off-by: Peter Mikus Change-Id: Iee65272169339ed0e5561cf3dee11567335b12be --- .../ansible/roles/kernel/defaults/main.yaml | 28 ++++ .../ansible/roles/kernel/filter_plugins/main.py | 143 +++++++++++++++++++++ .../ansible/roles/kernel/tasks/main.yaml | 6 + .../ansible/roles/kernel/tasks/ubuntu_bionic.yaml | 44 +++++++ .../ansible/roles/mellanox/defaults/main.yaml | 2 + .../ansible/roles/mellanox/tasks/main.yaml | 8 ++ .../roles/performance_tuning/files/irqbalance | 3 +- .../performance_tuning/filter_plugins/main.py | 29 +++++ .../roles/performance_tuning/tasks/main.yaml | 2 +- resources/tools/testbed-setup/ansible/sut.yaml | 2 + resources/tools/testbed-setup/ansible/tg.yaml | 2 + 11 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 resources/tools/testbed-setup/ansible/roles/kernel/defaults/main.yaml create mode 100644 resources/tools/testbed-setup/ansible/roles/kernel/filter_plugins/main.py create mode 100644 resources/tools/testbed-setup/ansible/roles/kernel/tasks/main.yaml create mode 100644 resources/tools/testbed-setup/ansible/roles/kernel/tasks/ubuntu_bionic.yaml create mode 100644 resources/tools/testbed-setup/ansible/roles/performance_tuning/filter_plugins/main.py diff --git a/resources/tools/testbed-setup/ansible/roles/kernel/defaults/main.yaml b/resources/tools/testbed-setup/ansible/roles/kernel/defaults/main.yaml new file mode 100644 index 0000000000..d84a163487 --- /dev/null +++ b/resources/tools/testbed-setup/ansible/roles/kernel/defaults/main.yaml @@ -0,0 +1,28 @@ +--- +# file: roles/kernel/defaults/main.yaml + +# Kernel version to install (Default to any version). +kernel_version: "{{ kernel_version_by_distro[ansible_distribution | lower] | join(' ') }}" + +kernel_version_by_distro: + ubuntu: + - "4.15.0-72" + +kernel_packages: "{{ kernel_packages_by_distro[ansible_distribution | lower] | flatten(levels=1) }}" + +kernel_packages_by_distro: + ubuntu: + - "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] | flatten(levels=1) }}" + +absent_packages_by_distro: + ubuntu: + - "amd64-microcode" + - "intel-microcode" + - "iucode-tool" diff --git a/resources/tools/testbed-setup/ansible/roles/kernel/filter_plugins/main.py b/resources/tools/testbed-setup/ansible/roles/kernel/filter_plugins/main.py new file mode 100644 index 0000000000..7d909b90e8 --- /dev/null +++ b/resources/tools/testbed-setup/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/resources/tools/testbed-setup/ansible/roles/kernel/tasks/main.yaml b/resources/tools/testbed-setup/ansible/roles/kernel/tasks/main.yaml new file mode 100644 index 0000000000..bf8ea9fa68 --- /dev/null +++ b/resources/tools/testbed-setup/ansible/roles/kernel/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +# file: roles/kernel/tasks/main.yaml + +- name: Kernel - Install distribution - release + include_tasks: '{{ ansible_distribution|lower }}_{{ ansible_distribution_release }}.yaml' + tags: install-kernel diff --git a/resources/tools/testbed-setup/ansible/roles/kernel/tasks/ubuntu_bionic.yaml b/resources/tools/testbed-setup/ansible/roles/kernel/tasks/ubuntu_bionic.yaml new file mode 100644 index 0000000000..c9c561df6f --- /dev/null +++ b/resources/tools/testbed-setup/ansible/roles/kernel/tasks/ubuntu_bionic.yaml @@ -0,0 +1,44 @@ +--- +# file: roles/kernel/tasks/ubuntu_bionic.yaml + +- name: Kernel - Get Available Kernel Versions + command: "apt-cache showpkg linux-headers-*" + changed_when: false + register: apt_kernel_list + tags: install-kernel + +- name: Kernel - Get installed packages with APT + command: "dpkg -l" + changed_when: false + register: apt_packages_list + tags: install-kernel + +- name: Kernel - Set target APT kernel version + set_fact: + _kernel: "{{ apt_kernel_list | deb_kernel( + kernel_version, ansible_kernel) }}" + tags: install-kernel + +- name: Kernel - Ensure Packages Versions + apt: + name: "{{ apt_kernel_list | deb_kernel_pkg( + kernel_version, ansible_kernel, ansible_distribution, + ansible_architecture, item) }}" + loop: "{{ kernel_packages }}" + tags: install-kernel + +- name: Kernel - Ensure Any Other Kernel Packages Are Removed + apt: + name: "{{ apt_packages_list | deb_installed_kernel( + apt_kernel_list, kernel_version, ansible_kernel) }}" + state: absent + purge: true + tags: install-kernel + +- name: Kernel - Ensure Any Microcode Is Absent + apt: + name: "{{ absent_packages }}" + state: absent + purge: true + tags: install-kernel + diff --git a/resources/tools/testbed-setup/ansible/roles/mellanox/defaults/main.yaml b/resources/tools/testbed-setup/ansible/roles/mellanox/defaults/main.yaml index 2b6d3a366e..a77bc67ec7 100644 --- a/resources/tools/testbed-setup/ansible/roles/mellanox/defaults/main.yaml +++ b/resources/tools/testbed-setup/ansible/roles/mellanox/defaults/main.yaml @@ -9,6 +9,8 @@ packages_base: packages_by_distro: ubuntu: - "build-essential" + - "libnl-3-dev" + - "libnl-route-3-dev" packages_by_arch: aarch64: diff --git a/resources/tools/testbed-setup/ansible/roles/mellanox/tasks/main.yaml b/resources/tools/testbed-setup/ansible/roles/mellanox/tasks/main.yaml index 030cf59b66..e91442718e 100644 --- a/resources/tools/testbed-setup/ansible/roles/mellanox/tasks/main.yaml +++ b/resources/tools/testbed-setup/ansible/roles/mellanox/tasks/main.yaml @@ -1,6 +1,14 @@ --- # file: roles/mellanox/tasks/main.yaml +- name: Mellanox Install - Install Distribution - Release - Machine Prerequisites + package: + name: "{{ packages | flatten(levels=1) }}" + state: latest + update_cache: true + tags: + - install-dependencies + - name: Mellanox Install - Check Presence of Mellanox Hardware shell: "lspci | grep Mellanox | awk '{print $1}'" register: mellanox_pcis diff --git a/resources/tools/testbed-setup/ansible/roles/performance_tuning/files/irqbalance b/resources/tools/testbed-setup/ansible/roles/performance_tuning/files/irqbalance index 98ba483b0d..861be02fb3 100644 --- a/resources/tools/testbed-setup/ansible/roles/performance_tuning/files/irqbalance +++ b/resources/tools/testbed-setup/ansible/roles/performance_tuning/files/irqbalance @@ -17,8 +17,7 @@ # corresponding bits set to one in this mask will not have any # irq's assigned to them on rebalance # -IRQBALANCE_BANNED_CPUS=ffffffff,ffffffff,ffffffff,fffffffe - +IRQBALANCE_BANNED_CPUS="{{ ansible_processor_cores | irqbalance_banned_cpu_mask(ansible_processor_count, ansible_processor_threads_per_core) }}" # # IRQBALANCE_ARGS # append any args here to the irqbalance daemon as documented in the man page diff --git a/resources/tools/testbed-setup/ansible/roles/performance_tuning/filter_plugins/main.py b/resources/tools/testbed-setup/ansible/roles/performance_tuning/filter_plugins/main.py new file mode 100644 index 0000000000..d76f6fe166 --- /dev/null +++ b/resources/tools/testbed-setup/ansible/roles/performance_tuning/filter_plugins/main.py @@ -0,0 +1,29 @@ +"""Extra Ansible filters""" + +def irqbalance_banned_cpu_mask( + processor_cores, processor_count, processor_threads_per_core): + """ + Return irqbalance CPU mask. + Args: + processor_cores (int): Physical processor unit. + processor_counts (int): Processors per physical unit. + processor_threads_per_core (int): Threads per physical unit. + Returns: + str: irqbalance_banned_cpus. + """ + mask = int("1" * 128, 2) + + for i in range(processor_count * processor_threads_per_core): + mask &= ~(1 << i * processor_cores) + + import re + return ",".join(re.findall('.{1,8}', str(hex(mask))[2:])) + + +class FilterModule(object): + """Return filter plugin""" + + @staticmethod + def filters(): + """Return filter""" + return {'irqbalance_banned_cpu_mask': irqbalance_banned_cpu_mask} diff --git a/resources/tools/testbed-setup/ansible/roles/performance_tuning/tasks/main.yaml b/resources/tools/testbed-setup/ansible/roles/performance_tuning/tasks/main.yaml index 49a20882b9..67da43b996 100644 --- a/resources/tools/testbed-setup/ansible/roles/performance_tuning/tasks/main.yaml +++ b/resources/tools/testbed-setup/ansible/roles/performance_tuning/tasks/main.yaml @@ -149,7 +149,7 @@ - copy-cpufrequtils - name: Performance Tuning - Copy Irqbalance File - copy: + template: src: "files/irqbalance" dest: "/etc/default/irqbalance" owner: "root" diff --git a/resources/tools/testbed-setup/ansible/sut.yaml b/resources/tools/testbed-setup/ansible/sut.yaml index c44dfe816f..650f100523 100644 --- a/resources/tools/testbed-setup/ansible/sut.yaml +++ b/resources/tools/testbed-setup/ansible/sut.yaml @@ -24,6 +24,8 @@ tags: kernel_vm - role: performance_tuning tags: performance_tuning + - role: kernel + tags: kernel - role: cleanup tags: cleanup - role: calibration diff --git a/resources/tools/testbed-setup/ansible/tg.yaml b/resources/tools/testbed-setup/ansible/tg.yaml index 44e5515e87..172e8a9721 100644 --- a/resources/tools/testbed-setup/ansible/tg.yaml +++ b/resources/tools/testbed-setup/ansible/tg.yaml @@ -24,6 +24,8 @@ tags: mellanox - role: performance_tuning tags: performance_tuning + - role: kernel + tags: kernel - role: cleanup tags: cleanup - role: calibration -- 2.16.6