提交 6c91134d 编写于 作者: R Roman Bogorodskiy

bhyve: add console support through nmdm device

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.
上级 6318a801
......@@ -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;
......
......@@ -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 */
......
......@@ -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:
......
......@@ -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) {
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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'"),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册