Newer
Older
openstack-caracal-dc-dc / docs / changelog-20260713-apparmor-libvirt-prereq.md

changelog 2026-07-13 -- fold the AppArmor/libvirt rule into scripts/prereqs

What

New prereq installer scripts/prereqs/install-apparmor-libvirt.sh, wired into install-all.sh (right after install-virtualization, since it edits libvirt's own profile directory) and reported by check-prereqs.sh. Harness extended tests/prereqs/run-tests.sh 24 -> 32 PASS. README updated.

Why

The rule /var/lib/libvirt/vr1/** rwk, in /etc/apparmor.d/local/abstractions/libvirt-qemu gates every VR1 VM boot -- the Office1 edge, the DC edges, and every node VM. libvirt's stock abstractions/libvirt-qemu grants qemu only the DEFAULT pool path (/var/lib/libvirt/images); VR1 uses a custom pool parent, which is not in that abstraction, so AppArmor blocks qemu even with perfect POSIX permissions. The failure is nasty and non-obvious: the domain DEFINES fine, then fails to start with a bare qemu "Permission denied" and nothing in the libvirt error names AppArmor. It cost a session on 2026-07-12 (DOCFIX-186).

It had been applied BY HAND on the vcloud host and existed ONLY as host state. Nothing in the repo carried it -- so a rebuild, or a second host, walked straight back into the identical wall. This closes that gap. It was logged as a PREREQ candidate at the time and never actioned; the ledger collapse surfaced it again.

Design notes

  • Idempotent, and deliberately quiet on a good host. If the rule is already present the script exits 0 having touched nothing -- in particular it does NOT reload apparmor and does NOT bounce libvirtd. The reload/restart happens ONLY on the run that actually adds the rule. (Restarting libvirtd does not stop running domains, but it is a real service action and is gated behind a real change rather than run on every pass.)
  • Writes to local/, not the abstraction itself. local/abstractions/libvirt-qemu is the vendor-sanctioned override include -- it survives package upgrades, which an edit to the shipped abstraction would not.
  • Pool parent is a variable, not a literal. Defaults to /var/lib/libvirt/vr1, overridable via VR1_POOL_PARENT -- per the repo's prefer-dynamic-over-hardcoded rule.
  • Non-AppArmor hosts report N/A and SUCCEED. The rule is unnecessary there, not failed; the script does not manufacture a failure on a system it does not apply to.

Verification

  • tests/prereqs/run-tests.sh: 32/32 PASS (was 24/24). The new cases drive the DETECTION off a pool parent guaranteed absent from the profile, so the negative path is deterministic regardless of what the host has applied: --check must FAIL for an ungranted parent (a false OK here is the whole bug), --dry-run must plan the fix and mutate nothing, and the planned rule must be exactly <parent>/** rwk,.
  • Full gauntlet: ALL GREEN (52 harnesses). repo-lint: 0 fail (1 documented legacy warn).
  • Run live on vcloud: --check reports OK (rule already present), exit 0, and the profile file is unchanged -- confirming the already-satisfied path is a true no-op.

Revert

git revert <this commit>

Removes the installer, its harness cases, the install-all/check-prereqs wiring, and the README rows. Reverting touches NO host state: the rule already live on vcloud was applied by hand long before this commit and is not managed by it.