]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
bhyve: add console support through nmdm device
authorRoman Bogorodskiy <bogorodskiy@gmail.com>
Sat, 15 Mar 2014 12:30:01 +0000 (16:30 +0400)
committerRoman Bogorodskiy <bogorodskiy@gmail.com>
Sat, 5 Apr 2014 15:12:18 +0000 (19:12 +0400)
nmdm is a FreeBSD driver which allows to create a pair of tty
devices one of which is passed to the guest and second is used
by the client.

This patch adds new 'nmdm' character device type. Its definition
looks this way:

<serial type='nmdm'>
  <source master='/dev/nmdm0A' slave='/dev/nmdm0B'/>
</serial>

Master is passed to the hypervisior and slave is used for client
connection.

Also implement domainOpenConsole() for bhyve driver based on that.

src/bhyve/bhyve_command.c
src/bhyve/bhyve_driver.c
src/conf/domain_audit.c
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_command.c
src/qemu/qemu_monitor_json.c

index 139c7e2c575ca94301f07c85533abed37647d305..a2da34ac2aea3066a428bbbd5437b98f654ecddf 100644 (file)
@@ -115,6 +115,38 @@ bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd)
     return 0;
 }
 
+static int
+bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd)
+{
+
+    virDomainChrDefPtr chr = NULL;
+
+    if (!def->nserials)
+        return 0;
+
+    chr = def->serials[0];
+
+    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_NMDM) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("only nmdm console types are supported"));
+        return -1;
+    }
+
+    /* bhyve supports only two ports: com1 and com2 */
+    if (chr->target.port > 2) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("only two serial ports are supported"));
+        return -1;
+    }
+
+    virCommandAddArgList(cmd, "-s", "31,lpc", NULL);
+    virCommandAddArg(cmd, "-l");
+    virCommandAddArgFormat(cmd, "com%d,%s",
+                           chr->target.port + 1, chr->source.data.file.path);
+
+    return 0;
+}
+
 static int
 bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd)
 {
@@ -210,6 +242,8 @@ virBhyveProcessBuildBhyveCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED,
         goto error;
     if (bhyveBuildDiskArgStr(vm->def, cmd) < 0)
         goto error;
+    if (bhyveBuildConsoleArgStr(vm->def, cmd) < 0)
+        goto error;
     virCommandAddArg(cmd, vm->def->name);
 
     return cmd;
index eec598dd159d7ba8dda3efa7da719417db919c17..461a0707a9a54f00d57283e0b38f85ad41fa0bed 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <config.h>
 
+#include <fcntl.h>
 #include <sys/utsname.h>
 
 #include "virerror.h"
@@ -748,6 +749,49 @@ bhyveDomainDestroy(virDomainPtr dom)
     return ret;
 }
 
+static int
+bhyveDomainOpenConsole(virDomainPtr dom,
+                       const char *dev_name ATTRIBUTE_UNUSED,
+                       virStreamPtr st,
+                       unsigned int flags)
+{
+    virDomainObjPtr vm = NULL;
+    virDomainChrDefPtr chr = NULL;
+    int ret = -1;
+
+    virCheckFlags(0, -1);
+
+    if (!(vm = bhyveDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("domain is not running"));
+        goto cleanup;
+    }
+
+    if (!vm->def->nserials) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("no console devices available"));
+        goto cleanup;
+    }
+
+    chr = vm->def->serials[0];
+
+    if (virFDStreamOpenPTY(st, chr->source.data.nmdm.slave,
+                           0, 0, O_RDWR) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virObjectUnlock(vm);
+    return ret;
+}
+
 static int
 bhyveNodeGetCPUStats(virConnectPtr conn,
                      int cpuNum,
@@ -964,6 +1008,7 @@ static virDriver bhyveDriver = {
     .domainIsPersistent = bhyveDomainIsPersistent, /* 1.2.2 */
     .domainGetAutostart = bhyveDomainGetAutostart, /* 1.2.4 */
     .domainSetAutostart = bhyveDomainSetAutostart, /* 1.2.4 */
+    .domainOpenConsole = bhyveDomainOpenConsole, /* 1.2.4 */
     .nodeGetCPUStats = bhyveNodeGetCPUStats, /* 1.2.2 */
     .nodeGetMemoryStats = bhyveNodeGetMemoryStats, /* 1.2.2 */
     .nodeGetInfo = bhyveNodeGetInfo, /* 1.2.3 */
index 5b97b82b3a319e115e2b83bb5bf61b7add277ac3..e26b8db3646ec25ae5925e8a913d9bbe6af4ab19 100644 (file)
@@ -72,6 +72,7 @@ virDomainAuditChardevPath(virDomainChrSourceDefPtr chr)
     case VIR_DOMAIN_CHR_TYPE_DEV:
     case VIR_DOMAIN_CHR_TYPE_FILE:
     case VIR_DOMAIN_CHR_TYPE_PIPE:
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
         return chr->data.file.path;
 
     case VIR_DOMAIN_CHR_TYPE_UNIX:
index 0c5c7abfb58dadcdf84b46527057e5cd4e5c806c..26202572356da0af872beecc43026bdcc67b8864 100644 (file)
@@ -413,7 +413,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
               "tcp",
               "unix",
               "spicevmc",
-              "spiceport")
+              "spiceport",
+              "nmdm")
 
 VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
               "raw",
@@ -1403,6 +1404,11 @@ virDomainChrSourceDefClear(virDomainChrSourceDefPtr def)
         VIR_FREE(def->data.file.path);
         break;
 
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+        VIR_FREE(def->data.nmdm.master);
+        VIR_FREE(def->data.nmdm.slave);
+        break;
+
     case VIR_DOMAIN_CHR_TYPE_UDP:
         VIR_FREE(def->data.udp.bindHost);
         VIR_FREE(def->data.udp.bindService);
@@ -1471,6 +1477,14 @@ virDomainChrSourceDefCopy(virDomainChrSourceDefPtr dest,
         if (VIR_STRDUP(dest->data.nix.path, src->data.nix.path) < 0)
             return -1;
         break;
+
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+        if (VIR_STRDUP(dest->data.nmdm.master, src->data.nmdm.master) < 0)
+            return -1;
+        if (VIR_STRDUP(dest->data.nmdm.slave, src->data.nmdm.slave) < 0)
+            return -1;
+
+        break;
     }
 
     dest->type = src->type;
@@ -1509,6 +1523,10 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src,
     case VIR_DOMAIN_CHR_TYPE_PIPE:
         return STREQ_NULLABLE(src->data.file.path, tgt->data.file.path);
         break;
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+        return STREQ_NULLABLE(src->data.nmdm.master, tgt->data.nmdm.master) &&
+            STREQ_NULLABLE(src->data.nmdm.slave, tgt->data.nmdm.slave);
+        break;
     case VIR_DOMAIN_CHR_TYPE_UDP:
         return STREQ_NULLABLE(src->data.udp.bindHost, tgt->data.udp.bindHost) &&
             STREQ_NULLABLE(src->data.udp.bindService, tgt->data.udp.bindService) &&
@@ -7148,6 +7166,8 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
     char *mode = NULL;
     char *protocol = NULL;
     char *channel = NULL;
+    char *master = NULL;
+    char *slave = NULL;
     int remaining = 0;
 
     while (cur != NULL) {
@@ -7197,6 +7217,13 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
                         channel = virXMLPropString(cur, "channel");
                     break;
 
+                case VIR_DOMAIN_CHR_TYPE_NMDM:
+                    if (!master)
+                        master = virXMLPropString(cur, "master");
+                    if (!slave)
+                        slave = virXMLPropString(cur, "slave");
+                    break;
+
                 case VIR_DOMAIN_CHR_TYPE_LAST:
                 case VIR_DOMAIN_CHR_TYPE_NULL:
                 case VIR_DOMAIN_CHR_TYPE_VC:
@@ -7253,6 +7280,25 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
         path = NULL;
         break;
 
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+        if (!master) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Missing master path attribute for nmdm device"));
+            goto error;
+        }
+
+        if (!slave) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Missing slave path attribute for nmdm device"));
+            goto error;
+        }
+
+        def->data.nmdm.master = master;
+        def->data.nmdm.slave = slave;
+        master = NULL;
+        slave = NULL;
+        break;
+
     case VIR_DOMAIN_CHR_TYPE_TCP:
         if (!mode || STREQ(mode, "connect")) {
             if (!connectHost) {
@@ -7423,6 +7469,11 @@ virDomainChrDefNew(void)
  *   <target port="1"/>
  * </serial>
  *
+ * <serial type="nmdm">
+ *   <source master="/dev/nmdm0A" slave="/dev/nmdm0B"/>
+ *   <target port="1">
+ * </serial>
+ *
  */
 static virDomainChrDefPtr
 virDomainChrDefParseXML(xmlXPathContextPtr ctxt,
@@ -15760,6 +15811,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
         }
         break;
 
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
+        virBufferAsprintf(buf, "<source master='%s' slave='%s'/>\n",
+                          def->data.nmdm.master,
+                          def->data.nmdm.slave);
+        break;
+
     case VIR_DOMAIN_CHR_TYPE_UDP:
         if (def->data.udp.bindService &&
             def->data.udp.bindHost) {
index 2f874c57972acb1f7dc460ee79296b7ff116d986..c01f482e30978e7126cf8a38a78f5f0d015df753 100644 (file)
@@ -980,6 +980,7 @@ enum virDomainChrType {
     VIR_DOMAIN_CHR_TYPE_UNIX,
     VIR_DOMAIN_CHR_TYPE_SPICEVMC,
     VIR_DOMAIN_CHR_TYPE_SPICEPORT,
+    VIR_DOMAIN_CHR_TYPE_NMDM,
 
     VIR_DOMAIN_CHR_TYPE_LAST
 };
@@ -1011,6 +1012,10 @@ struct _virDomainChrSourceDef {
         struct {
             char *path;
         } file; /* pty, file, pipe, or device */
+        struct {
+            char *master;
+            char *slave;
+        } nmdm;
         struct {
             char *host;
             char *service;
index 37841d1596bbf404634e9959c4b48f736bf13c85..1723ebfeeb4f904b950468772b02b9327a9c7a60 100644 (file)
@@ -6095,6 +6095,7 @@ qemuBuildChrArgStr(virDomainChrSourceDefPtr dev, const char *prefix)
 
     case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
     case VIR_DOMAIN_CHR_TYPE_LAST:
         break;
     }
index a692a07e51a11bf06f0ac1f2edc8de2ab4109715..f8ab975695108f3585dfdd869f52b1996e737994 100644 (file)
@@ -5423,6 +5423,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID,
     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
     case VIR_DOMAIN_CHR_TYPE_PIPE:
     case VIR_DOMAIN_CHR_TYPE_STDIO:
+    case VIR_DOMAIN_CHR_TYPE_NMDM:
     case VIR_DOMAIN_CHR_TYPE_LAST:
         virReportError(VIR_ERR_OPERATION_FAILED,
                        _("Unsupported char device type '%d'"),