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)
{
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;
#include <config.h>
+#include <fcntl.h>
#include <sys/utsname.h>
#include "virerror.h"
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,
.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 */
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:
"tcp",
"unix",
"spicevmc",
- "spiceport")
+ "spiceport",
+ "nmdm")
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
"raw",
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);
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;
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) &&
char *mode = NULL;
char *protocol = NULL;
char *channel = NULL;
+ char *master = NULL;
+ char *slave = NULL;
int remaining = 0;
while (cur != NULL) {
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:
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) {
* <target port="1"/>
* </serial>
*
+ * <serial type="nmdm">
+ * <source master="/dev/nmdm0A" slave="/dev/nmdm0B"/>
+ * <target port="1">
+ * </serial>
+ *
*/
static virDomainChrDefPtr
virDomainChrDefParseXML(xmlXPathContextPtr ctxt,
}
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) {
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
};
struct {
char *path;
} file; /* pty, file, pipe, or device */
+ struct {
+ char *master;
+ char *slave;
+ } nmdm;
struct {
char *host;
char *service;
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;
}
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'"),