From b51b06ecebb64ced574122158337f61420d847a9 Mon Sep 17 00:00:00 2001
From: Praveen K Paladugu <praveenkpaladugu@gmail.com>
Date: Tue, 5 Mar 2024 14:57:04 -0600
Subject: [PATCH] ch: Add support for `Unix` mode to serial port dev

With Unix mode, pass a socket path to cloud-hypervisor.
Cloud-Hypervisor will attach guest's serial port to this socket path.
Users can connect to the serial port using one of the following commands:

`socat -,crnl UNIX-CONNECT:<path/to/socket>`

OR

`minicom --device unix#<path/to/socket>`

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
---
 src/ch/ch_monitor.c | 33 +++++++++++++++++++++++----------
 src/ch/ch_process.c |  7 +++++++
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 62ba72bb82..fefbf7e67a 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -89,21 +89,34 @@ virCHMonitorBuildCPUJson(virJSONValue *content, virDomainDef *vmdef)
 }
 
 static int
-virCHMonitorBuildPTYJson(virJSONValue *content, virDomainDef *vmdef)
+virCHMonitorBuildConsoleJson(virJSONValue *content,
+                             virDomainDef *vmdef)
 {
-    if (vmdef->nconsoles) {
-        g_autoptr(virJSONValue) pty = virJSONValueNewObject();
-        if (virJSONValueObjectAppendString(pty, "mode", "Pty") < 0)
+    g_autoptr(virJSONValue) console = virJSONValueNewObject();
+    g_autoptr(virJSONValue) serial = virJSONValueNewObject();
+
+    if (vmdef->nconsoles &&
+        vmdef->consoles[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+        if (virJSONValueObjectAppendString(console, "mode", "Pty") < 0)
             return -1;
-        if (virJSONValueObjectAppend(content, "console", &pty) < 0)
+        if (virJSONValueObjectAppend(content, "console", &console) < 0)
             return -1;
     }
 
     if (vmdef->nserials) {
-        g_autoptr(virJSONValue) pty = virJSONValueNewObject();
-        if (virJSONValueObjectAppendString(pty, "mode", "Pty") < 0)
-            return -1;
-        if (virJSONValueObjectAppend(content, "serial", &pty) < 0)
+        if (vmdef->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_PTY) {
+            if (virJSONValueObjectAppendString(serial, "mode", "Pty") < 0)
+                return -1;
+        } else if (vmdef->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
+            if (virJSONValueObjectAppendString(serial, "mode", "Socket") < 0)
+                return -1;
+            if (virJSONValueObjectAppendString(serial,
+                                               "socket",
+                                               vmdef->serials[0]->source->data.file.path) < 0)
+                return -1;
+        }
+
+        if (virJSONValueObjectAppend(content, "serial", &serial) < 0)
             return -1;
     }
 
@@ -415,7 +428,7 @@ virCHMonitorBuildVMJson(virCHDriver *driver, virDomainDef *vmdef,
         return -1;
     }
 
-    if (virCHMonitorBuildPTYJson(content, vmdef) < 0)
+    if (virCHMonitorBuildConsoleJson(content, vmdef) < 0)
         return -1;
 
     if (virCHMonitorBuildCPUJson(content, vmdef) < 0)
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index 3bde9d9dcf..b371181fb2 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -69,6 +69,13 @@ virCHProcessUpdateConsoleDevice(virDomainObj *vm,
     if (!config)
         return;
 
+    /* This method is used to extract pty info from cloud-hypervisor and capture
+     * it in domain configuration. This step can be skipped for serial devices
+     * with unix backend.*/
+    if (STREQ(device, "serial") &&
+        vm->def->serials[0]->source->type == VIR_DOMAIN_CHR_TYPE_UNIX)
+        return;
+
     dev = virJSONValueObjectGet(config, device);
     if (!dev) {
         virReportError(VIR_ERR_INTERNAL_ERROR,