Blob Blame History Raw
From 0699afed37343d73c6803cabec466e1c3ca229b0 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Mon, 13 Jun 2022 19:01:32 +0200
Subject: [PATCH] output/create_libvirt_xml: wire up the QEMU guest agent

The intent (even before RHBZ#2028764) has been to install the QEMU guest
agent in the converted domain unconditionally. Therefore, in order for the
GA to be actually accessible from the host side, augment the libvirt
output module with a "guest agent connection" also unconditionally.

For starters, the domain needs a virtio-serial device. Then there must be
a port on the device that (in the guest) the GA identifies by name, and
that (on the host) is exposed as a listening socket (usually in the unix
address family). The adress of that port (usually a pathname, i.e., for a
unix domain socket) is then passed to whatever host-side application wants
to talk to the GA.

The minimal domain XML fragment for that ("minimal" for our purposes) is

  <controller type='virtio-serial' model='virtio'>
  <channel type='unix'>
    <target type='virtio' name='org.qemu.guest_agent.0'/>
  </channel>

The "controller" element is needed because "controller/@model" is where we
regulate "virtio" vs. "virtio-transitional".

Everything else is filled in by libvirt. Notably, libvirt (a) creates and
binds the unix domain socket itself (usually
"/var/lib/libvirt/qemu/channel/target/DOMAIN/org.qemu.guest_agent.0"), (b)
passes the file descriptor to QEMU, and (c) figures out the socket
pathname for commands such as

  virsh domfsinfo DOMAIN
  virsh domhostname DOMAIN --source agent
  virsh domifaddr DOMAIN --source agent
  virsh guestinfo DOMAIN

For QEMU, the corresponding options would be

  -chardev socket,id=agent,server=on,wait=off,path=/tmp/DOMAIN-agent \
  -device virtio-serial-pci,id=vioserial \
  -device virtserialport,bus=vioserial.0,nr=1,chardev=agent,name=org.qemu.guest_agent.0 \

Note the "path=/tmp/DOMAIN-agent" property of "-chardev"; virt-v2v would
have to generate that (in place of the "fd=nnnn" property that libvirt
passes to QEMU).

Omit extending the QEMU output module for now, as the QGA protocol is
based on JSON, and one needs "virsh" or "virt-manager" (or another
management application interface) anyway, for efficiently exchanging
messages with QGA. I don't know of end-user tools that directly connect to
"/tmp/DOMAIN-agent".

Don't modify the RHV and OpenStack outputs either; both of these
management products likely configure the virtio-serial device
automatically, for the agent access.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2028764
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20220613170135.12557-2-lersek@redhat.com>
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
(cherry picked from commit 48c6ea27c5a7053e418622f7450e3f9ef05c923f)
---
 output/create_libvirt_xml.ml | 11 +++++++++++
 tests/test-v2v-i-ova.xml     |  4 ++++
 2 files changed, 15 insertions(+)

diff --git a/output/create_libvirt_xml.ml b/output/create_libvirt_xml.ml
index 68d0a909..531a4f75 100644
--- a/output/create_libvirt_xml.ml
+++ b/output/create_libvirt_xml.ml
@@ -524,6 +524,17 @@ let create_libvirt_xml ?pool source inspect
     e "console" ["type", "pty"] [];
   ];
 
+  (* Given that we install the QEMU Guest Agent for both Linux and Windows
+   * guests unconditionally, create the virtio-serial device that's needed for
+   * communication between the host and the agent.
+   *)
+  List.push_back_list devices [
+    e "controller" ["type", "virtio-serial"; "model", virtio_model] [];
+    e "channel" ["type", "unix"] [
+      e "target" ["type", "virtio"; "name", "org.qemu.guest_agent.0"] []
+    ]
+  ];
+
   List.push_back_list body [
     e "devices" [] !devices;
   ];
diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml
index 6b8cda62..da1db473 100644
--- a/tests/test-v2v-i-ova.xml
+++ b/tests/test-v2v-i-ova.xml
@@ -49,5 +49,9 @@
     <input type='tablet' bus='usb'/>
     <input type='mouse' bus='ps2'/>
     <console type='pty'/>
+    <controller type='virtio-serial' model='virtio'/>
+    <channel type='unix'>
+      <target type='virtio' name='org.qemu.guest_agent.0'/>
+    </channel>
   </devices>
 </domain>