diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c index 5273a260a0..827dfddd6e 100644 --- a/src/libxl/libxl_conf.c +++ b/src/libxl/libxl_conf.c @@ -330,6 +330,92 @@ error: return -1; } +static int +libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf) +{ + virDomainChrSourceDef srcdef = def->source; + const char *type = virDomainChrTypeToString(srcdef.type); + + if (!type) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("unknown chrdev type")); + return -1; + } + + switch (srcdef.type) { + case VIR_DOMAIN_CHR_TYPE_NULL: + case VIR_DOMAIN_CHR_TYPE_STDIO: + case VIR_DOMAIN_CHR_TYPE_VC: + case VIR_DOMAIN_CHR_TYPE_PTY: + if (VIR_STRDUP(*buf, type) < 0) + return -1; + break; + + case VIR_DOMAIN_CHR_TYPE_FILE: + case VIR_DOMAIN_CHR_TYPE_PIPE: + if (virAsprintf(buf, "%s:%s", type, srcdef.data.file.path) < 0) + return -1; + break; + + case VIR_DOMAIN_CHR_TYPE_DEV: + if (VIR_STRDUP(*buf, srcdef.data.file.path) < 0) + return -1; + break; + + case VIR_DOMAIN_CHR_TYPE_UDP: { + const char *connectHost = srcdef.data.udp.connectHost; + const char *bindHost = srcdef.data.udp.bindHost; + const char *bindService = srcdef.data.udp.bindService; + + if (connectHost == NULL) + connectHost = ""; + if (bindHost == NULL) + bindHost = ""; + if (bindService == NULL) + bindService = "0"; + + if (virAsprintf(buf, "udp:%s:%s@%s:%s", + connectHost, + srcdef.data.udp.connectService, + bindHost, + bindService) < 0) + return -1; + break; + } + + case VIR_DOMAIN_CHR_TYPE_TCP: { + const char *prefix; + + if (srcdef.data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET) + prefix = "telnet"; + else + prefix = "tcp"; + + if (virAsprintf(buf, "%s:%s:%s%s", + prefix, + srcdef.data.tcp.host, + srcdef.data.tcp.service, + srcdef.data.tcp.listen ? ",server,nowait" : "") < 0) + return -1; + break; + } + + case VIR_DOMAIN_CHR_TYPE_UNIX: + if (virAsprintf(buf, "unix:%s%s", + srcdef.data.nix.path, + srcdef.data.nix.listen ? ",server,nowait" : "") < 0) + return -1; + break; + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported chardev '%s'"), type); + return -1; + } + + return 0; +} + static int libxlMakeDomBuildInfo(virDomainObjPtr vm, libxl_domain_config *d_config) { @@ -411,6 +497,24 @@ libxlMakeDomBuildInfo(virDomainObjPtr vm, libxl_domain_config *d_config) if (VIR_STRDUP(b_info->u.hvm.boot, bootorder) < 0) goto error; + if (def->nserials) { + if (def->nserials > 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", + _("Only one serial device is supported by libxl")); + goto error; + } + if (libxlMakeChrdevStr(def->serials[0], &b_info->u.hvm.serial) < 0) + goto error; + } + + if (def->nparallels) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", + _("Parallel devices are not supported by libxl")); + goto error; + } + /* * The following comment and calculation were taken directly from * libxenlight's internal function libxl_get_required_shadow_memory(): diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h index 942cdd5acb..aa57710d29 100644 --- a/src/libxl/libxl_conf.h +++ b/src/libxl/libxl_conf.h @@ -34,6 +34,7 @@ # include "configmake.h" # include "virportallocator.h" # include "virobject.h" +# include "virchrdev.h" # define LIBXL_VNC_PORT_MIN 5900 @@ -94,6 +95,8 @@ struct _libxlDomainObjPrivate { /* per domain libxl ctx */ libxl_ctx *ctx; + /* console */ + virChrdevsPtr devs; libxl_evgen_domain_death *deathW; /* list of libxl timeout registrations */ diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index eb252d0c77..9e9bc89afb 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -417,6 +417,9 @@ libxlDomainObjPrivateAlloc(void) libxl_osevent_register_hooks(priv->ctx, &libxl_event_callbacks, priv); + if (!(priv->devs = virChrdevAlloc())) + return NULL; + return priv; } @@ -428,6 +431,7 @@ libxlDomainObjPrivateDispose(void *obj) if (priv->deathW) libxl_evdisable_domain_death(priv->ctx, priv->deathW); + virChrdevFree(priv->devs); libxl_ctx_free(priv->ctx); } @@ -4502,6 +4506,94 @@ cleanup: return ret; } + +static int +libxlDomainOpenConsole(virDomainPtr dom, + const char *dev_name, + virStreamPtr st, + unsigned int flags) +{ + libxlDriverPrivatePtr driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + virDomainChrDefPtr chr = NULL; + libxlDomainObjPrivatePtr priv; + char *console = NULL; + + virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1); + + if (dev_name) { + /* XXX support device aliases in future */ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Named device aliases are not supported")); + goto cleanup; + } + + libxlDriverLock(driver); + vm = virDomainObjListFindByUUID(driver->domains, dom->uuid); + libxlDriverUnlock(driver); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching uuid '%s'"), uuidstr); + 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; + } + + priv = vm->privateData; + + if (vm->def->nserials) + chr = vm->def->serials[0]; + + if (!chr) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot find character device %s"), + NULLSTR(dev_name)); + goto cleanup; + } + + if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("character device %s is not using a PTY"), + NULLSTR(dev_name)); + goto cleanup; + } + + ret = libxl_primary_console_get_tty(priv->ctx, vm->def->id, &console); + if (ret) + goto cleanup; + + if (VIR_STRDUP(chr->source.data.file.path, console) < 0) + goto cleanup; + + /* handle mutually exclusive access to console devices */ + ret = virChrdevOpen(priv->devs, + &chr->source, + st, + (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0); + + if (ret == 1) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("Active console session exists for this domain")); + ret = -1; + } + +cleanup: + VIR_FREE(console); + if (vm) + virObjectUnlock(vm); + return ret; +} + static int libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int nparams) @@ -4884,6 +4976,7 @@ static virDriver libxlDriver = { .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */ .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */ .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */ + .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */ .domainIsActive = libxlDomainIsActive, /* 0.9.0 */ .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */ .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */