From fefa51a52f43649e11963d13b8f41c599cee4081 Mon Sep 17 00:00:00 2001
From: Kristian Klausen <kristian@klausen.dk>
Date: Sun, 27 Oct 2024 19:33:37 +0100
Subject: [PATCH] gitlab_runner: Switch to new libvirt-executor image[1] from
 arch-boxes

It makes more sense to build the image in arch-boxes than building it on
each runner, especially considering that arch-boxes already have all the
necessary infrastructure, so we can avoid maintaining similar code in
two repositories and avoid running losetup, mount, arch-chroot etc. (as
root) on the runners.

The arch-boxes MR[1] has a little more context.

[1] https://gitlab.archlinux.org/archlinux/arch-boxes/-/merge_requests/200
---
 .../files/libvirt-executor-fetch-image        | 34 ++++++++++
 .../libvirt-executor-fetch-image.service      |  8 +++
 .../files/libvirt-executor-fetch-image.timer  | 12 ++++
 .../files/libvirt-executor-update-base-image  | 63 -------------------
 ...libvirt-executor-update-base-image.service |  8 ---
 .../libvirt-executor-update-base-image.timer  | 10 ---
 roles/gitlab_runner/tasks/main.yml            | 16 ++---
 7 files changed, 62 insertions(+), 89 deletions(-)
 create mode 100755 roles/gitlab_runner/files/libvirt-executor-fetch-image
 create mode 100644 roles/gitlab_runner/files/libvirt-executor-fetch-image.service
 create mode 100644 roles/gitlab_runner/files/libvirt-executor-fetch-image.timer
 delete mode 100755 roles/gitlab_runner/files/libvirt-executor-update-base-image
 delete mode 100644 roles/gitlab_runner/files/libvirt-executor-update-base-image.service
 delete mode 100644 roles/gitlab_runner/files/libvirt-executor-update-base-image.timer

diff --git a/roles/gitlab_runner/files/libvirt-executor-fetch-image b/roles/gitlab_runner/files/libvirt-executor-fetch-image
new file mode 100755
index 000000000..756717548
--- /dev/null
+++ b/roles/gitlab_runner/files/libvirt-executor-fetch-image
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -o nounset -o errexit -o pipefail
+readonly libvirt_pool="images"
+readonly arch_boxes_signing_key=/usr/local/lib/libvirt-executor/arch-boxes.asc
+readonly arch_boxes_fingerprint=1B9A16984A4E8CB448712D2AE0B78BF4326C6F8F
+
+cleanup() {
+  rm -r "${tmpdir}"
+}
+
+tmpdir="$(mktemp --directory --tmpdir="/var/tmp")"
+trap cleanup EXIT
+
+cd "${tmpdir}"
+
+version="$(curl -sSfL 'https://gitlab.archlinux.org/archlinux/arch-boxes/-/jobs/artifacts/master/raw/build.env?job=build:secure' | awk -F= '$1=="BUILD_VERSION" {print $2}')"
+image_name="Arch-Linux-x86_64-libvirt-executor-${version}.qcow2"
+
+if cmp --quiet <(echo "${image_name}") /usr/local/lib/libvirt-executor/backing-vol-name; then
+  echo "Nothing to do"
+  exit
+fi
+
+curl -sSfL --remote-name-all https://gitlab.archlinux.org/archlinux/arch-boxes/-/jobs/artifacts/master/raw/output/${image_name}{,.sig}?job=build:secure
+rsop verify "${image_name}.sig" "${arch_boxes_signing_key}" < "${image_name}"
+
+virsh vol-create-as "${libvirt_pool}" "${image_name}" 0 --format qcow2
+virsh vol-upload "${image_name}" "${image_name}" "${libvirt_pool}"
+
+echo "${image_name}" > /usr/local/lib/libvirt-executor/backing-vol-name.tmp
+mv /usr/local/lib/libvirt-executor/backing-vol-name{.tmp,}
+
+# Keep one week of images
+virsh vol-list "${libvirt_pool}" | awk '$1~"Arch-Linux-x86_64-libvirt-executor-[0-9]*\\.[0-9]*\\.qcow2" {print $1}' | sort -n -t - -k6,6 | head -n -7 | xargs -I{} --no-run-if-empty virsh vol-delete {} "${libvirt_pool}"
diff --git a/roles/gitlab_runner/files/libvirt-executor-fetch-image.service b/roles/gitlab_runner/files/libvirt-executor-fetch-image.service
new file mode 100644
index 000000000..14ed3cf50
--- /dev/null
+++ b/roles/gitlab_runner/files/libvirt-executor-fetch-image.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Fetch libvirt-executor image
+Wants=network-online.target
+After=network-online.target nss-lookup.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/local/bin/libvirt-executor-fetch-image
diff --git a/roles/gitlab_runner/files/libvirt-executor-fetch-image.timer b/roles/gitlab_runner/files/libvirt-executor-fetch-image.timer
new file mode 100644
index 000000000..8ec6abbf3
--- /dev/null
+++ b/roles/gitlab_runner/files/libvirt-executor-fetch-image.timer
@@ -0,0 +1,12 @@
+[Unit]
+Description=Run libvirt-executor-fetch-image.service daily
+
+[Timer]
+# One hour after the "Nightly build" pipeline
+# https://gitlab.archlinux.org/archlinux/arch-boxes/-/pipeline_schedules
+OnCalendar=06:00 UTC
+Persistent=true
+RandomizedDelaySec=1h
+
+[Install]
+WantedBy=timers.target
diff --git a/roles/gitlab_runner/files/libvirt-executor-update-base-image b/roles/gitlab_runner/files/libvirt-executor-update-base-image
deleted file mode 100755
index d669d16d3..000000000
--- a/roles/gitlab_runner/files/libvirt-executor-update-base-image
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-set -o nounset -o errexit
-readonly libvirt_pool="images"
-readonly arch_boxes_signing_key=/usr/local/lib/libvirt-executor/arch-boxes.asc
-readonly arch_boxes_fingerprint=1B9A16984A4E8CB448712D2AE0B78BF4326C6F8F
-
-loopdev=""
-
-cleanup() {
-  set +o errexit
-
-  if mountpoint -q mnt; then
-    umount -R mnt
-  fi
-  if [[ -n ${loopdev} ]]; then
-    losetup -d "${loopdev}"
-  fi
-  rm -r "${tmpdir}"
-}
-
-tmpdir="$(mktemp --directory --tmpdir="/var/tmp")"
-trap cleanup EXIT
-
-cd "${tmpdir}"
-curl -sSf --remote-name-all https://geo.mirror.pkgbuild.com/images/latest/Arch-Linux-x86_64-basic.qcow2{,.sig}
-rsop verify Arch-Linux-x86_64-basic.qcow2.sig "${arch_boxes_signing_key}" < Arch-Linux-x86_64-basic.qcow2
-
-image=Arch-Linux-x86_64-basic.img
-qemu-img convert -f qcow2 -O raw Arch-Linux-x86_64-basic.qcow2 Arch-Linux-x86_64-basic.img
-
-loopdev="$(losetup --find --partscan --show "${image}")"
-mount --mkdir "${loopdev}p3" mnt
-mount --mkdir --bind -o ro /etc/pacman.d/gnupg mnt/etc/pacman.d/gnupg
-
-arch-chroot mnt systemctl disable systemd-time-wait-sync
-arch-chroot mnt pacman -Sy --noconfirm --needed archlinux-keyring
-arch-chroot mnt pacman -Syu --noconfirm --needed git git-lfs gitlab-runner
-sed -E 's/^#(IgnorePkg *=)/\1 linux/' -i mnt/etc/pacman.conf
-arch-chroot mnt userdel -r arch
-sed 's/^\(GRUB_CMDLINE_LINUX=".*\)"$/\1 lockdown=confidentiality"/' -i mnt/etc/default/grub
-arch-chroot mnt /usr/bin/grub-mkconfig -o /boot/grub/grub.cfg
-# We want to use the transient hostname
-# https://github.com/systemd/systemd/pull/30814
-rm -f mnt/etc/machine-id mnt/etc/hostname
-
-cp -a mnt/boot/{initramfs-linux-fallback.img,initramfs-linux.img}
-
-umount mnt/etc/pacman.d/gnupg
-rmdir mnt/etc/pacman.d/gnupg
-umount mnt
-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 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
-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/gitlab_runner/files/libvirt-executor-update-base-image.service b/roles/gitlab_runner/files/libvirt-executor-update-base-image.service
deleted file mode 100644
index b28f92fc3..000000000
--- a/roles/gitlab_runner/files/libvirt-executor-update-base-image.service
+++ /dev/null
@@ -1,8 +0,0 @@
-[Unit]
-Description=Update libvirt-executor base image
-Wants=network-online.target
-After=network-online.target nss-lookup.target
-
-[Service]
-Type=oneshot
-ExecStart=/usr/local/bin/libvirt-executor-update-base-image
diff --git a/roles/gitlab_runner/files/libvirt-executor-update-base-image.timer b/roles/gitlab_runner/files/libvirt-executor-update-base-image.timer
deleted file mode 100644
index 4cb8f17bb..000000000
--- a/roles/gitlab_runner/files/libvirt-executor-update-base-image.timer
+++ /dev/null
@@ -1,10 +0,0 @@
-[Unit]
-Description=Run libvirt-executor-update-base-image.service daily
-
-[Timer]
-OnCalendar=daily
-Persistent=true
-RandomizedDelaySec=1d
-
-[Install]
-WantedBy=timers.target
diff --git a/roles/gitlab_runner/tasks/main.yml b/roles/gitlab_runner/tasks/main.yml
index b874c277b..60e468c84 100644
--- a/roles/gitlab_runner/tasks/main.yml
+++ b/roles/gitlab_runner/tasks/main.yml
@@ -66,8 +66,8 @@
 - name: Setup libvirt-executor
   when: "'gitlab_vm_runners' in group_names"
   block:
-    - name: Install libvirt-executor-update-base-image dependencies
-      pacman: name=arch-install-scripts,rsop state=present
+    - name: Install libvirt-executor-fetch-image dependencies
+      pacman: name=rsop state=present
 
     - name: Create libvirt-executor data directory
       file: path=/usr/local/lib/libvirt-executor state=directory owner=root group=root mode=0755
@@ -77,16 +77,16 @@
       loop:
         - {src: arch-boxes.asc, dest: /usr/local/lib/libvirt-executor/, mode: 644}
         - {src: libvirt-executor, dest: /usr/local/bin/, mode: 755}
-        - {src: libvirt-executor-update-base-image, dest: /usr/local/bin/, mode: 755}
+        - {src: libvirt-executor-fetch-image, dest: /usr/local/bin/, mode: 755}
 
     - name: Install libvirt-executor domain template
       template: src=domain_template.xml.j2 dest=/usr/local/lib/libvirt-executor/domain_template.xml owner=root group=root mode=0644
 
-    - name: Install libvirt-executor-update-base-image.{service,timer}
+    - name: Install libvirt-executor-fetch-image.{service,timer}
       copy: src={{ item }} dest=/etc/systemd/system/{{ item }} owner=root group=root mode=0644
       loop:
-        - libvirt-executor-update-base-image.service
-        - libvirt-executor-update-base-image.timer
+        - libvirt-executor-fetch-image.service
+        - libvirt-executor-fetch-image.timer
 
-    - name: Enable and start libvirt-executor-update-base-image.timer
-      systemd: name=libvirt-executor-update-base-image.timer state=started enabled=yes daemon_reload=yes
+    - name: Enable and start libvirt-executor-fetch-image.timer
+      systemd: name=libvirt-executor-fetch-image.timer state=started enabled=yes daemon_reload=yes
-- 
GitLab