From ac6a01296a6c93cc6e3e349356e92f7c97b3de72 Mon Sep 17 00:00:00 2001 From: sjat Date: Thu, 18 Jun 2026 12:03:44 +0200 Subject: [PATCH] feat(integration_test): KVM/libvirt substrate role on the control node --- playbooks/workstation.yml | 2 ++ roles/integration_test/README.md | 35 +++++++++++++++++++ roles/integration_test/defaults/main.yml | 18 ++++++++++ roles/integration_test/handlers/main.yml | 1 + roles/integration_test/meta/main.yml | 14 ++++++++ .../molecule/default/converge.yml | 7 ++++ .../molecule/default/molecule.yml | 31 ++++++++++++++++ .../molecule/default/verify.yml | 25 +++++++++++++ roles/integration_test/tasks/main.yml | 32 +++++++++++++++++ 9 files changed, 165 insertions(+) create mode 100644 roles/integration_test/README.md create mode 100644 roles/integration_test/defaults/main.yml create mode 100644 roles/integration_test/handlers/main.yml create mode 100644 roles/integration_test/meta/main.yml create mode 100644 roles/integration_test/molecule/default/converge.yml create mode 100644 roles/integration_test/molecule/default/molecule.yml create mode 100644 roles/integration_test/molecule/default/verify.yml create mode 100644 roles/integration_test/tasks/main.yml diff --git a/playbooks/workstation.yml b/playbooks/workstation.yml index 071b7e0..0d0d6d2 100644 --- a/playbooks/workstation.yml +++ b/playbooks/workstation.yml @@ -8,3 +8,5 @@ roles: - role: dev_env tags: [dev_env] + - role: integration_test + tags: [integration_test] diff --git a/roles/integration_test/README.md b/roles/integration_test/README.md new file mode 100644 index 0000000..e978e85 --- /dev/null +++ b/roles/integration_test/README.md @@ -0,0 +1,35 @@ +# integration_test + +Installs the KVM/libvirt substrate on the control node (`ubongo`) so the agent +can boot throwaway Debian VMs for local integration testing (ADR-025). + +This is a **non-service** role — no SECURITY/VERIFY/ACCESS/BACKUP files are +required. It does **not** make ubongo a production hypervisor; it only provides +the tooling needed to spin up short-lived test VMs (see ADR-015). + +## Target group + +`control` (i.e. `ubongo`) + +## What it does + +1. Installs QEMU/KVM, libvirt daemon + clients, `virt-install`, and + cloud-image tools (`cloud-image-utils`, `genisoimage`). +2. Enables and starts `libvirtd`. +3. Adds the configured users (`sjat`, `claude`) to the `libvirt` and `kvm` + groups so VMs can be managed without `sudo`. +4. Creates `/var/lib/boma-integration` (owned `root:libvirt`, mode `2775`) as + the cache directory for golden images and overlays. + +## Defaults + +| Variable | Default | Purpose | +|-------------------------------|-------------------------------|----------------------------------| +| `integration_test__packages` | see `defaults/main.yml` | APT packages to install | +| `integration_test__users` | `[sjat, claude]` | Users granted libvirt/kvm access | +| `integration_test__cache_dir` | `/var/lib/boma-integration` | Image/overlay cache directory | + +## Related decisions + +- [ADR-025](../../docs/decisions/025-integration-testing.md) — local VM integration testing +- [ADR-015](../../docs/decisions/015-control-host.md) — control host scope (ubongo is not a hypervisor) diff --git a/roles/integration_test/defaults/main.yml b/roles/integration_test/defaults/main.yml new file mode 100644 index 0000000..932f99e --- /dev/null +++ b/roles/integration_test/defaults/main.yml @@ -0,0 +1,18 @@ +--- +# integration_test — installs the local KVM/libvirt substrate on the control node +# (ubongo) so the agent can run throwaway VM integration tests (ADR-025). Non-service +# role; applied to the `control` group. Not a production hypervisor (ADR-015). +integration_test__packages: + - qemu-system-x86 # KVM + - qemu-utils # qemu-img (overlays) + - libvirt-daemon-system + - libvirt-clients # virsh + - virt-install # virt-install (trixie: the real pkg; `virtinst` is transitional) + - cloud-image-utils # cloud-localds (NoCloud seed) + - genisoimage # cloud-localds fallback +# Users granted libvirt/kvm access (run VMs without sudo). +integration_test__users: + - sjat + - claude +# Where the golden image + overlays live (outside the repo). +integration_test__cache_dir: "/var/lib/boma-integration" diff --git a/roles/integration_test/handlers/main.yml b/roles/integration_test/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/integration_test/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/integration_test/meta/main.yml b/roles/integration_test/meta/main.yml new file mode 100644 index 0000000..ee87dcf --- /dev/null +++ b/roles/integration_test/meta/main.yml @@ -0,0 +1,14 @@ +--- +galaxy_info: + author: sjat + description: >- + Installs the KVM/libvirt substrate on the control node (ubongo) to enable + local VM integration testing (ADR-025). Non-service role; not a production + hypervisor (ADR-015). + license: MIT + min_ansible_version: "2.17" + platforms: + - name: Debian + versions: + - trixie +dependencies: [] diff --git a/roles/integration_test/molecule/default/converge.yml b/roles/integration_test/molecule/default/converge.yml new file mode 100644 index 0000000..f26090b --- /dev/null +++ b/roles/integration_test/molecule/default/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: all + become: true + gather_facts: true + roles: + - role: integration_test diff --git a/roles/integration_test/molecule/default/molecule.yml b/roles/integration_test/molecule/default/molecule.yml new file mode 100644 index 0000000..b23d8da --- /dev/null +++ b/roles/integration_test/molecule/default/molecule.yml @@ -0,0 +1,31 @@ +--- +dependency: + name: galaxy + options: + requirements-file: ../../requirements.yml + +driver: + name: docker + +platforms: + - name: instance + # Project-owned image built from .docker/molecule-debian13/Dockerfile + # and hosted in the Forgejo container registry. + # Build/push with: make molecule-image / make molecule-image-push + image: forgejo.nyumbani.baobab.band/sjat/molecule-debian13:latest + pre_build_image: true + privileged: true # required for systemd + cgroupns_mode: host + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + command: /lib/systemd/systemd + +provisioner: + name: ansible + inventory: + host_vars: + instance: + ansible_user: root + +verifier: + name: ansible diff --git a/roles/integration_test/molecule/default/verify.yml b/roles/integration_test/molecule/default/verify.yml new file mode 100644 index 0000000..233243b --- /dev/null +++ b/roles/integration_test/molecule/default/verify.yml @@ -0,0 +1,25 @@ +--- +- name: Verify + hosts: all + become: true + gather_facts: false + tasks: + - name: Gather package facts + ansible.builtin.package_facts: + - name: Assert the substrate packages are installed + ansible.builtin.assert: + that: + - "'qemu-system-x86' in ansible_facts.packages" + - "'qemu-utils' in ansible_facts.packages" + - "'libvirt-daemon-system' in ansible_facts.packages" + - "'libvirt-clients' in ansible_facts.packages" + - "'virt-install' in ansible_facts.packages" + - "'cloud-image-utils' in ansible_facts.packages" + - "'genisoimage' in ansible_facts.packages" + - name: Cache dir exists + ansible.builtin.stat: + path: /var/lib/boma-integration + register: _cache + - name: Assert cache dir + ansible.builtin.assert: + that: [_cache.stat.isdir] diff --git a/roles/integration_test/tasks/main.yml b/roles/integration_test/tasks/main.yml new file mode 100644 index 0000000..4a1e2c7 --- /dev/null +++ b/roles/integration_test/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Install the KVM/libvirt substrate + ansible.builtin.apt: + name: "{{ integration_test__packages }}" + state: present + update_cache: true + cache_valid_time: 3600 + tags: [packages] + +- name: Enable and start libvirtd + ansible.builtin.systemd: + name: libvirtd + enabled: true + state: started + tags: [config] + +- name: Grant users libvirt + kvm access + ansible.builtin.user: + name: "{{ item }}" + groups: [libvirt, kvm] + append: true + loop: "{{ integration_test__users }}" + tags: [users] + +- name: Create the integration cache dir + ansible.builtin.file: + path: "{{ integration_test__cache_dir }}" + state: directory + owner: root + group: libvirt + mode: "2775" + tags: [config]