Implement the QEMU Guest Agent sockets, so that code/scripts on the
hypervisors can communicate with guest operating systems easily.

Signed-off-by: Robin H. Johnson <[email protected]>
---
 lib/hypervisor/hv_kvm/__init__.py | 30 ++++++++++++++++++++++++++++++
 man/gnt-instance.rst              |  7 +++++++
 src/Ganeti/Constants.hs           |  5 +++++
 3 files changed, 42 insertions(+)

diff --git a/lib/hypervisor/hv_kvm/__init__.py 
b/lib/hypervisor/hv_kvm/__init__.py
index f3c1d60..0f1c05d 100644
--- a/lib/hypervisor/hv_kvm/__init__.py
+++ b/lib/hypervisor/hv_kvm/__init__.py
@@ -497,6 +497,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     constants.HV_MIGRATION_BANDWIDTH: hv_base.REQ_NONNEGATIVE_INT_CHECK,
     constants.HV_MIGRATION_DOWNTIME: hv_base.REQ_NONNEGATIVE_INT_CHECK,
     constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
+    constants.HV_USE_GUEST_AGENT: hv_base.NO_CHECK,
     constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
     constants.HV_DISK_CACHE:
       hv_base.ParamInSet(True, constants.HT_VALID_CACHE_TYPES),
@@ -751,6 +752,13 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     """
     return utils.PathJoin(cls._CTRL_DIR, "%s.qmp" % instance_name)
 
+  @classmethod
+  def _InstanceQemuGuestAgentMonitor(cls, instance_name):
+    """Returns the instance serial QEMU Guest Agent socket name
+
+    """
+    return utils.PathJoin(cls._CTRL_DIR, "%s.qga" % instance_name)
+
   @classmethod
   def _InstanceKvmdMonitor(cls, instance_name):
     """Returns the instance kvm daemon socket name
@@ -837,6 +845,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     utils.RemoveFile(cls._InstanceMonitor(instance_name))
     utils.RemoveFile(cls._InstanceSerial(instance_name))
     utils.RemoveFile(cls._InstanceQmpMonitor(instance_name))
+    utils.RemoveFile(cls._InstanceQemuGuestAgentMonitor(instance_name))
     utils.RemoveFile(cls._InstanceKVMRuntime(instance_name))
     utils.RemoveFile(cls._InstanceKeymapFile(instance_name))
     uid_file = cls._InstanceUidFile(instance_name)
@@ -1551,6 +1560,27 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     if self._UUID_RE.search(kvmhelp):
       kvm_cmd.extend(["-uuid", instance.uuid])
 
+    # Add guest agent socket
+    if hvp[constants.HV_USE_GUEST_AGENT]:
+      qga_addr = utils.GetFreeSlot(pci_reservations, reserve=True)
+      qga_pci_info = ",bus=pci.0,addr=%s" % hex(qga_addr)
+      qga_path = self._InstanceQemuGuestAgentMonitor(instance.name)
+      logging.info("KVM: Guest Agent available at %s", path)
+      # The 'qga0' identified can change, but the 'org.qemu.guest_agent.0' 
string is
+      # the default expected by the Guest Agent.
+      kvm_cmd.extend([
+        "-chardev",
+        "socket,path=%s,server,nowait,id=qga0" % qga_path,
+        ])
+      kvm_cmd.extend([
+        "-device",
+        "virtio-serial,id=qga0%s" % qga_pci_info,
+        ])
+      kvm_cmd.extend([
+        "-device",
+        "virtserialport,chardev=qga0,name=org.qemu.guest_agent.0",
+        ])
+
     if hvp[constants.HV_KVM_EXTRA]:
       kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
 
diff --git a/man/gnt-instance.rst b/man/gnt-instance.rst
index 283392c..493ae92 100644
--- a/man/gnt-instance.rst
+++ b/man/gnt-instance.rst
@@ -545,6 +545,13 @@ viridian
     viridian (Hyper-V) for this instance. The default is false,
     disabling viridian support.
 
+use\_guest\_agent
+    Valid for the KVM hypervisor.
+
+    A boolean option that specifies if the hypervisor should enable
+    the QEMU Guest Agent protocol for this instance. By default, the
+    Guest Agent is disabled.
+
 use\_localtime
     Valid for the Xen HVM and KVM hypervisors.
 
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index 1e0b877..ba2b5f2 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -1844,6 +1844,9 @@ hvUsbMouse = "usb_mouse"
 hvUseBootloader :: String
 hvUseBootloader = "use_bootloader"
 
+hvUseGuestAgent :: String
+hvUseGuestAgent = "use_guest_agent"
+
 hvUseLocaltime :: String
 hvUseLocaltime = "use_localtime"
 
@@ -1979,6 +1982,7 @@ hvsParameterTypes = Map.fromList
   , (hvUsbDevices,                      VTypeString)
   , (hvUsbMouse,                        VTypeString)
   , (hvUseBootloader,                   VTypeBool)
+  , (hvUseGuestAgent,                   VTypeBool)
   , (hvUseLocaltime,                    VTypeBool)
   , (hvVga,                             VTypeString)
   , (hvVhostNet,                        VTypeBool)
@@ -4143,6 +4147,7 @@ hvcDefaults =
           , (hvMigrationBandwidth,              PyValueEx (32 :: Int))
           , (hvMigrationDowntime,               PyValueEx (30 :: Int))
           , (hvMigrationMode,                   PyValueEx htMigrationLive)
+          , (hvUseGuestAgent,                   PyValueEx False)
           , (hvUseLocaltime,                    PyValueEx False)
           , (hvDiskCache,                       PyValueEx htCacheDefault)
           , (hvSecurityModel,                   PyValueEx htSmNone)
-- 
2.9.0

Reply via email to