From cc6195f3a249c62bb7c2a7abe640b567cffd4bd5 Mon Sep 17 00:00:00 2001 From: Kristian Klausen <kristian@klausen.dk> Date: Sun, 27 Oct 2024 16:11:46 +0100 Subject: [PATCH] gitlab_runner: Remove tight coupling to libvirt filesystem pool All libvirt volume management is now handled through virsh instead of direct file system access. As a volume cannot be uploaded in an atomic way, the current active volume is now tracked in a file on disk. This may allow us to run the script with less privileges and use polkit for libvirt access control[1]. [1] https://libvirt.org/aclpolkit.html --- roles/gitlab_runner/files/libvirt-executor | 15 +++++++-------- .../files/libvirt-executor-update-base-image | 13 ++++++++----- roles/libvirt/files/images.xml | 6 ++++++ roles/libvirt/tasks/main.yml | 18 ++++++++++++++++++ 4 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 roles/libvirt/files/images.xml diff --git a/roles/gitlab_runner/files/libvirt-executor b/roles/gitlab_runner/files/libvirt-executor index a51a14f69..91f1423de 100755 --- a/roles/gitlab_runner/files/libvirt-executor +++ b/roles/gitlab_runner/files/libvirt-executor @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -o nounset -o errexit -o pipefail -readonly libvirt_default_pool_path="/var/lib/libvirt/images" +readonly libvirt_pool="images" ssh() { command ssh \ @@ -50,15 +50,15 @@ wait_for_ssh() { prepare() { # shellcheck disable=SC2064 trap "exit ${SYSTEM_FAILURE_EXIT_CODE:-1}" ERR - local base_image - base_image="$(compgen -G "${libvirt_default_pool_path}/runner-base-*.qcow2" | sort -n -t - -k3,3 | tail -n 1)" - if [[ -z ${base_image} ]]; then - echo 'Base image not found...' + if [[ ! -f /usr/local/lib/libvirt-executor/backing-vol-name ]]; then + echo 'Backing volume not found...' exit "${SYSTEM_FAILURE_EXIT_CODE:-1}" fi + local backing_volume + backing_volume="$(</usr/local/lib/libvirt-executor/backing-vol-name)" - qemu-img create -f qcow2 -b "${base_image}" -F qcow2 "${libvirt_default_pool_path}/$(vm_name).qcow2" + virsh vol-create-as "${libvirt_pool}" "$(vm_name).qcow2" 0 --format qcow2 --backing-vol "${backing_volume}" --backing-vol-format qcow2 virsh define <(sed "s/\$vm_name/$(vm_name)/" /usr/local/lib/libvirt-executor/domain_template.xml) virsh start "$(vm_name)" @@ -81,8 +81,7 @@ run() { # https://docs.gitlab.com/runner/executors/custom.html#cleanup cleanup() { virsh destroy "$(vm_name)" || true - rm "${libvirt_default_pool_path}/$(vm_name).qcow2" - virsh undefine "$(vm_name)" + virsh undefine --remove-all-storage "$(vm_name)" } case "${1:-}" in diff --git a/roles/gitlab_runner/files/libvirt-executor-update-base-image b/roles/gitlab_runner/files/libvirt-executor-update-base-image index 1f96ecaff..9a743c871 100755 --- a/roles/gitlab_runner/files/libvirt-executor-update-base-image +++ b/roles/gitlab_runner/files/libvirt-executor-update-base-image @@ -1,6 +1,6 @@ #!/bin/bash set -o nounset -o errexit -readonly libvirt_default_pool_path="/var/lib/libvirt/images" +readonly libvirt_pool="images" readonly arch_boxes_signing_key=/usr/local/lib/libvirt-executor/arch-boxes.asc readonly arch_boxes_fingerprint=1B9A16984A4E8CB448712D2AE0B78BF4326C6F8F @@ -56,9 +56,12 @@ losetup -d "${loopdev}" loopdev="" qemu-img convert -f raw -O qcow2 Arch-Linux-x86_64-basic.img Arch-Linux-x86_64-basic.qcow2 -printf -v image_path '%s/runner-base-%(%s)T.qcow2' "${libvirt_default_pool_path}" -cp Arch-Linux-x86_64-basic.qcow2 "${image_path}.tmp" -mv "${image_path}"{.tmp,} +printf -v vol_name 'runner-base-%(%s)T.qcow2' +virsh vol-create-as "${libvirt_pool}" "${vol_name}" 0 --format qcow2 +virsh vol-upload "${vol_name}" Arch-Linux-x86_64-basic.qcow2 "${libvirt_pool}" + +echo "${vol_name}" > /usr/local/lib/libvirt-executor/backing-vol-name.tmp +mv /usr/local/lib/libvirt-executor/backing-vol-name{.tmp,} # Keep one week of base images -compgen -G "${libvirt_default_pool_path}/runner-base-*.qcow2" | sort -n -t - -k3,3 | head -n -7 | xargs --no-run-if-empty rm -vf +virsh vol-list "${libvirt_pool}" | awk '$1~"runner-base-[0-9]*\\.qcow2" {print $1}' | sort -n -t - -k3,3 | head -n -7 | xargs -I{} --no-run-if-empty virsh vol-delete {} "${libvirt_pool}" diff --git a/roles/libvirt/files/images.xml b/roles/libvirt/files/images.xml new file mode 100644 index 000000000..6222186e1 --- /dev/null +++ b/roles/libvirt/files/images.xml @@ -0,0 +1,6 @@ +<pool type='dir'> + <name>images</name> + <target> + <path>/var/lib/libvirt/images</path> + </target> +</pool> diff --git a/roles/libvirt/tasks/main.yml b/roles/libvirt/tasks/main.yml index ae8863b51..9307576fb 100644 --- a/roles/libvirt/tasks/main.yml +++ b/roles/libvirt/tasks/main.yml @@ -12,6 +12,8 @@ - qemu-base - qemu-hw-display-virtio-gpu - qemu-hw-display-virtio-vga + - libvirt-python + - python-lxml register: result - name: Reload firewalld @@ -23,3 +25,19 @@ - name: Start and enable libvirtd systemd: name=libvirtd enabled=yes state=started daemon_reload=yes + +- name: Define the images storage pool + community.libvirt.virt_pool: + command: define + name: images + xml: "{{ lookup('file', 'images.xml') }}" + +- name: Start the image storage pool + community.libvirt.virt_pool: + state: active + name: images + +- name: Start the image storage pool at boot + community.libvirt.virt_pool: + autostart: true + name: images -- GitLab