Skip to content

Commit 0c85a03

Browse files
committed
Add qemu-guest-agent over vsock for time sync and host-guest features
Install qemu-guest-agent and configure it to listen on vsock port 1234 (matching the constant in containers/podman). The service is gated by a DMI sys_vendor check (ExecCondition) so it only runs on Podman machine providers that expose the vsock channel: vfkit (Apple Inc.), libkrun (Libkrun), and qemu (QEMU). A custom SELinux module allows virt_qemu_ga_t to use vsock sockets. Related PR: podman-container-tools/podman#28527 Replace: #175 Signed-off-by: Jan Rodák <hony.com@seznam.cz>
1 parent 2a292aa commit 0c85a03

6 files changed

Lines changed: 69 additions & 0 deletions

File tree

podman-image/00-podman-machine.preset

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ disable coreos-container-signing-migration-motd.service
1010

1111
# Disable coreos chrony config, we do provide our own.
1212
disable coreos-platform-chrony-config.service
13+
14+
# qemu-guest-agent (vsock) for macOS (vfkit, libkrun) and Linux (qemu); gated by systemd conditions.
15+
enable qemu-guest-agent.service

podman-image/Containerfile.COREOS

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
ARG FCOS_BASE_IMAGE=${FCOS_BASE_IMAGE}
2+
3+
# Compile SELinux in a throwaway stage using the same base as the final image so policy module
4+
# format matches (fedora:latest can emit a newer policydb than FCOS semodule accepts).
5+
FROM ${FCOS_BASE_IMAGE} AS qemu_guest_agent_vsock_selinux
6+
COPY qemu_guest_agent_vsock.te /qemu_guest_agent_vsock.te
7+
RUN dnf install -y checkpolicy policycoreutils && dnf clean all && \
8+
checkmodule -M -m -o /qemu_guest_agent_vsock.mod /qemu_guest_agent_vsock.te && \
9+
semodule_package -o /qemu_guest_agent_vsock.pp -m /qemu_guest_agent_vsock.mod
10+
211
FROM ${FCOS_BASE_IMAGE}
312

413
ARG PODMAN_PR_NUM=${PODMAN_PR_NUM}
@@ -45,3 +54,8 @@ RUN --network=none rm -vf /etc/resolv.conf && rpm -e systemd-resolved
4554
# https://github.com/containers/podman/pull/21670#discussion_r1585790802
4655
COPY rosetta-activation.service /etc/systemd/system/rosetta-activation.service
4756
COPY rosetta-activation.sh /usr/local/bin/rosetta-activation.sh
57+
58+
# qemu-guest-agent over vsock
59+
COPY --from=qemu_guest_agent_vsock_selinux /qemu_guest_agent_vsock.pp /tmp/qemu_guest_agent_vsock.pp
60+
RUN semodule -i /tmp/qemu_guest_agent_vsock.pp && rm -f /tmp/qemu_guest_agent_vsock.pp
61+
COPY qemu-guest-agent.service /etc/systemd/system/qemu-guest-agent.service

podman-image/build_common.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ PACKAGES=(
107107

108108
# git-core for Containerfile `ADD <gitrepo>` clone feature
109109
git-core
110+
111+
# Guest agent (vsock) for time sync and host-guest features (macOS vfkit/libkrun, Linux qemu)
112+
qemu-guest-agent
110113
)
111114

112115
dnf install -y "${PACKAGES[@]}"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[Unit]
2+
Description=QEMU Guest Agent
3+
IgnoreOnIsolate=true
4+
ConditionVirtualization=|kvm
5+
ConditionVirtualization=|apple
6+
ConditionFirmware=|smbios-field(sys_vendor = Libkrun)
7+
8+
[Service]
9+
UMask=0077
10+
ExecStart=/usr/bin/qemu-ga --method=vsock-listen --path=3:1234
11+
Restart=on-failure
12+
RestartSec=5s
13+
14+
[Install]
15+
WantedBy=default.target
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module qemu_guest_agent_vsock 1.0;
2+
3+
require {
4+
type virt_qemu_ga_t;
5+
class vsock_socket { bind create getattr listen accept read write };
6+
}
7+
8+
#============= virt_qemu_ga_t ==============
9+
allow virt_qemu_ga_t self:vsock_socket { bind create getattr listen accept read write };

verify/image_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,31 @@ var _ = Describe("run image tests", Ordered, ContinueOnFailure, func() {
118118
Expect(rosettaSession).To(Exit(0))
119119
Expect(rosettaSession.outputToString()).To(Equal("active"))
120120
})
121+
It("should ship qemu-guest-agent for vsock (FCOS images)", func() {
122+
skipIfVmtype(WSLVirt, "WSL image does not use the CoreOS Containerfile customizations")
123+
rpmCmd := []string{"machine", "ssh", machineName, "rpm", "-q", "qemu-guest-agent"}
124+
rpmSession, err := mb.setCmd(rpmCmd).run()
125+
Expect(err).ToNot(HaveOccurred())
126+
Expect(rpmSession).To(Exit(0))
127+
Expect(rpmSession.outputToString()).To(ContainSubstring("qemu-guest-agent"))
128+
129+
catCmd := []string{"machine", "ssh", machineName, "systemctl", "cat", "qemu-guest-agent.service"}
130+
catSession, err := mb.setCmd(catCmd).run()
131+
Expect(err).ToNot(HaveOccurred())
132+
Expect(catSession).To(Exit(0))
133+
out := catSession.outputToString()
134+
Expect(out).To(ContainSubstring("vsock-listen"))
135+
Expect(out).To(ContainSubstring("--path=3:1234"))
136+
})
137+
It("should have qemu-guest-agent active on Linux and macOS providers", func() {
138+
skipIfVmtype(WSLVirt, "WSL image does not include qemu-guest-agent")
139+
skipIfVmtype(HyperVVirt, "HyperV does not expose a vsock channel for qemu-guest-agent")
140+
cmd := []string{"machine", "ssh", machineName, "systemctl", "-P", "ActiveState", "show", "qemu-guest-agent.service"}
141+
session, err := mb.setCmd(cmd).run()
142+
Expect(err).ToNot(HaveOccurred())
143+
Expect(session).To(Exit(0))
144+
Expect(session.outputToString()).To(Equal("active"))
145+
})
121146
It("should have zero critical error messages journalctl", func() {
122147
skipIfVmtype(LibKrun, "TODO: analyze the error messages in journalctl when using libkrun")
123148
skipIfVmtype(AppleHvVirt, "TODO: analyze the error messages in journalctl when using applehv")

0 commit comments

Comments
 (0)