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)
{
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():
libxl_osevent_register_hooks(priv->ctx, &libxl_event_callbacks, priv);
+ if (!(priv->devs = virChrdevAlloc()))
+ return NULL;
+
return priv;
}
if (priv->deathW)
libxl_evdisable_domain_death(priv->ctx, priv->deathW);
+ virChrdevFree(priv->devs);
libxl_ctx_free(priv->ctx);
}
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)
.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 */