mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-31 18:15:25 +00:00
Allow multiple consoles per virtual guest
While Xen only has a single paravirt console, UML, and QEMU both support multiple paravirt consoles. The LXC driver can also be trivially made to support multiple consoles. This patch extends the XML to allow multiple <console> elements in the XML. It also makes the UML and QEMU drivers support this config. * src/conf/domain_conf.c, src/conf/domain_conf.h: Allow multiple <console> devices * src/lxc/lxc_driver.c, src/xen/xen_driver.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for internal API changes * src/security/security_selinux.c, src/security/virt-aa-helper.c: Only label consoles that aren't a copy of the serial device * src/qemu/qemu_command.c, src/qemu/qemu_driver.c, src/qemu/qemu_process.c, src/uml/uml_conf.c, src/uml/uml_driver.c: Support multiple console devices * tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV for all console /channel tests * tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args, tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update for correct chardev syntax * tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args, tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New test file
This commit is contained in:
parent
b0a510ad2a
commit
0873b688c6
@ -2681,12 +2681,29 @@ qemu-kvm -net nic,model=? /dev/null
|
||||
<h6><a name="elementCharConsole">Console</a></h6>
|
||||
|
||||
<p>
|
||||
This represents the primary console. This can be the paravirtualized
|
||||
console with Xen guests, virtio console for QEMU/KVM, or duplicates
|
||||
the primary serial port for fully virtualized guests without a
|
||||
paravirtualized console.
|
||||
The console element is used to represent interactive consoles. Depending
|
||||
on the type of guest in use, the consoles might be paravirtualized devices,
|
||||
or they might be a clone of a serial device, according to the following
|
||||
rules:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>If no <code>targetType</code> attribue is set, then the default
|
||||
device type is according to the hypervisor's rules. The default
|
||||
type will be added when re-querying the XML fed into libvirt.
|
||||
For fully virtualized guests, the default device type will usually
|
||||
be a serial port.</li>
|
||||
<li>If the <code>targetType</code> attribute is <code>serial</code>,
|
||||
then if no <code><serial></code> element exists, the console
|
||||
element will be copied to the serial element. If a <code><serial></code>
|
||||
element does already exist, the console element will be ignored.</li>
|
||||
<li>If the <code>targetType</code> attribute is not <code>serial</code>,
|
||||
it will be treated normally.</li>
|
||||
<li>Only the first <code>console</code> element may use a <code>targetType</code>
|
||||
of <code>serial</code>. Secondary consoles must all be paravirtualized.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
A virtio console device is exposed in the
|
||||
guest as /dev/hvc[0-7] (for more information, see
|
||||
|
@ -1227,7 +1227,9 @@ void virDomainDefFree(virDomainDefPtr def)
|
||||
virDomainChrDefFree(def->channels[i]);
|
||||
VIR_FREE(def->channels);
|
||||
|
||||
virDomainChrDefFree(def->console);
|
||||
for (i = 0 ; i < def->nconsoles ; i++)
|
||||
virDomainChrDefFree(def->consoles[i]);
|
||||
VIR_FREE(def->consoles);
|
||||
|
||||
for (i = 0 ; i < def->nsounds ; i++)
|
||||
virDomainSoundDefFree(def->sounds[i]);
|
||||
@ -1618,6 +1620,9 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
|
||||
for (i = 0; i < def->nchannels ; i++)
|
||||
if (cb(def, &def->channels[i]->info, opaque) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < def->nconsoles ; i++)
|
||||
if (cb(def, &def->consoles[i]->info, opaque) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < def->ninputs ; i++)
|
||||
if (cb(def, &def->inputs[i]->info, opaque) < 0)
|
||||
return -1;
|
||||
@ -1630,9 +1635,6 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
|
||||
if (def->memballoon)
|
||||
if (cb(def, &def->memballoon->info, opaque) < 0)
|
||||
return -1;
|
||||
if (def->console)
|
||||
if (cb(def, &def->console->info, opaque) < 0)
|
||||
return -1;
|
||||
for (i = 0; i < def->nhubs ; i++)
|
||||
if (cb(def, &def->hubs[i]->info, opaque) < 0)
|
||||
return -1;
|
||||
@ -7203,20 +7205,46 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
if ((node = virXPathNode("./devices/console[1]", ctxt)) != NULL) {
|
||||
if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("cannot extract console devices"));
|
||||
goto error;
|
||||
}
|
||||
if (n && VIR_ALLOC_N(def->consoles, n) < 0)
|
||||
goto no_memory;
|
||||
|
||||
for (i = 0 ; i < n ; i++) {
|
||||
virDomainChrDefPtr chr = virDomainChrDefParseXML(caps,
|
||||
node,
|
||||
nodes[i],
|
||||
flags);
|
||||
if (!chr)
|
||||
goto error;
|
||||
|
||||
chr->target.port = 0;
|
||||
/*
|
||||
* For HVM console actually created a serial device
|
||||
* while for non-HVM it was a parvirt console
|
||||
* Some really crazy backcompat stuff for consoles
|
||||
*
|
||||
* Historically the first (and only) '<console>'
|
||||
* element in an HVM guest was treated as being
|
||||
* an alias for a <serial> device.
|
||||
*
|
||||
* So if we see that this console device should
|
||||
* be a serial device, then we move the config
|
||||
* over to def->serials[0] (or discard it if
|
||||
* that already exists
|
||||
*
|
||||
* We then fill def->consoles[0] with a stub
|
||||
* just so we get sequencing correct for consoles
|
||||
* > 0
|
||||
*/
|
||||
if (STREQ(def->os.type, "hvm") &&
|
||||
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
|
||||
(chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)) {
|
||||
if (i != 0) {
|
||||
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only the first console can be a serial port"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Either discard or move this chr to the serial config */
|
||||
if (def->nserials != 0) {
|
||||
virDomainChrDefFree(chr);
|
||||
} else {
|
||||
@ -7224,14 +7252,24 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
||||
virDomainChrDefFree(chr);
|
||||
goto no_memory;
|
||||
}
|
||||
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
||||
def->nserials = 1;
|
||||
def->serials[0] = chr;
|
||||
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
|
||||
chr->target.port = 0;
|
||||
}
|
||||
} else {
|
||||
def->console = chr;
|
||||
|
||||
/* And create a stub placeholder */
|
||||
if (VIR_ALLOC(chr) < 0)
|
||||
goto no_memory;
|
||||
chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
|
||||
}
|
||||
|
||||
chr->target.port = i;
|
||||
|
||||
def->consoles[def->nconsoles++] = chr;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
if ((n = virXPathNodeSet("./devices/channel", ctxt, &nodes)) < 0) {
|
||||
goto error;
|
||||
@ -8677,14 +8715,17 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src,
|
||||
if (!virDomainChannelDefCheckABIStability(src->channels[i], dst->channels[i]))
|
||||
goto cleanup;
|
||||
|
||||
if ((!src->console && dst->console) ||
|
||||
(src->console && !dst->console)) {
|
||||
if (src->nconsoles != dst->nconsoles) {
|
||||
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Target domain console count %d does not match source %d"),
|
||||
dst->console ? 1 : 0, src->console ? 1 : 0);
|
||||
dst->nconsoles, src->nconsoles);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < src->nconsoles ; i++)
|
||||
if (!virDomainConsoleDefCheckABIStability(src->consoles[i], dst->consoles[i]))
|
||||
goto cleanup;
|
||||
|
||||
if (src->nhubs != dst->nhubs) {
|
||||
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("Target domain hub device count %d does not match source %d"),
|
||||
@ -8696,9 +8737,6 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src,
|
||||
if (!virDomainHubDefCheckABIStability(src->hubs[i], dst->hubs[i]))
|
||||
goto cleanup;
|
||||
|
||||
if (src->console &&
|
||||
!virDomainConsoleDefCheckABIStability(src->console, dst->console))
|
||||
goto cleanup;
|
||||
|
||||
if ((!src->watchdog && dst->watchdog) ||
|
||||
(src->watchdog && !dst->watchdog)) {
|
||||
@ -8820,8 +8858,8 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
|
||||
}
|
||||
}
|
||||
|
||||
if (def->console) {
|
||||
virDomainChrDefPtr console = def->console;
|
||||
for (i = 0 ; i < def->nconsoles ; i++) {
|
||||
virDomainChrDefPtr console = def->consoles[i];
|
||||
|
||||
if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
|
||||
int idx = 0;
|
||||
@ -11079,15 +11117,27 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
||||
if (virDomainChrDefFormat(buf, def->parallels[n], flags) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* If there's a PV console that's preferred.. */
|
||||
if (def->console) {
|
||||
if (virDomainChrDefFormat(buf, def->console, flags) < 0)
|
||||
goto cleanup;
|
||||
} else if (def->nserials != 0) {
|
||||
/* ..else for legacy compat duplicate the first serial device as a
|
||||
* console */
|
||||
for (n = 0 ; n < def->nconsoles ; n++) {
|
||||
virDomainChrDef console;
|
||||
memcpy(&console, def->serials[0], sizeof(console));
|
||||
/* Back compat, ignore the console element for hvm guests
|
||||
* if it is type == serial
|
||||
*/
|
||||
if (STREQ(def->os.type, "hvm") &&
|
||||
(def->consoles[n]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) &&
|
||||
(n < def->nserials)) {
|
||||
memcpy(&console, def->serials[n], sizeof(console));
|
||||
console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
} else {
|
||||
memcpy(&console, def->consoles[n], sizeof(console));
|
||||
}
|
||||
if (virDomainChrDefFormat(buf, &console, flags) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (STREQ(def->os.type, "hvm") &&
|
||||
def->nconsoles == 0 &&
|
||||
def->nserials > 0) {
|
||||
virDomainChrDef console;
|
||||
memcpy(&console, def->serials[n], sizeof(console));
|
||||
console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
if (virDomainChrDefFormat(buf, &console, flags) < 0)
|
||||
goto cleanup;
|
||||
@ -12690,9 +12740,9 @@ int virDomainChrDefForeach(virDomainDefPtr def,
|
||||
if (abortOnError && rc != 0)
|
||||
goto done;
|
||||
}
|
||||
if (def->console) {
|
||||
for (i = 0 ; i < def->nconsoles ; i++) {
|
||||
if ((iter)(def,
|
||||
def->console,
|
||||
def->consoles[i],
|
||||
opaque) < 0)
|
||||
rc = -1;
|
||||
|
||||
|
@ -1455,6 +1455,9 @@ struct _virDomainDef {
|
||||
int nchannels;
|
||||
virDomainChrDefPtr *channels;
|
||||
|
||||
int nconsoles;
|
||||
virDomainChrDefPtr *consoles;
|
||||
|
||||
size_t nleases;
|
||||
virDomainLeaseDefPtr *leases;
|
||||
|
||||
@ -1462,7 +1465,6 @@ struct _virDomainDef {
|
||||
virDomainHubDefPtr *hubs;
|
||||
|
||||
/* Only 1 */
|
||||
virDomainChrDefPtr console;
|
||||
virSecurityLabelDef seclabel;
|
||||
virDomainWatchdogDefPtr watchdog;
|
||||
virDomainMemballoonDefPtr memballoon;
|
||||
|
@ -1680,10 +1680,18 @@ static int lxcVmStart(virConnectPtr conn,
|
||||
_("Failed to allocate tty"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (vm->def->console &&
|
||||
vm->def->console->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
|
||||
VIR_FREE(vm->def->console->source.data.file.path);
|
||||
vm->def->console->source.data.file.path = parentTtyPath;
|
||||
if (vm->def->nconsoles) {
|
||||
if (vm->def->nconsoles > 1) {
|
||||
lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Only one console supported"));
|
||||
goto cleanup;
|
||||
}
|
||||
if (vm->def->consoles[0]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
|
||||
VIR_FREE(vm->def->consoles[0]->source.data.file.path);
|
||||
vm->def->consoles[0]->source.data.file.path = parentTtyPath;
|
||||
} else {
|
||||
VIR_FREE(parentTtyPath);
|
||||
}
|
||||
} else {
|
||||
VIR_FREE(parentTtyPath);
|
||||
}
|
||||
@ -3026,8 +3034,8 @@ lxcDomainOpenConsole(virDomainPtr dom,
|
||||
_("Named device aliases are not supported"));
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (vm->def->console)
|
||||
chr = vm->def->console;
|
||||
if (vm->def->nconsoles)
|
||||
chr = vm->def->consoles[0];
|
||||
else if (vm->def->nserials)
|
||||
chr = vm->def->serials[0];
|
||||
}
|
||||
|
@ -716,16 +716,16 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps)
|
||||
if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
for (i = 0; i < def->nsmartcards ; i++) {
|
||||
if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0)
|
||||
for (i = 0; i < def->nconsoles ; i++) {
|
||||
if (virAsprintf(&def->consoles[i]->info.alias, "console%d", i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
for (i = 0; i < def->nhubs ; i++) {
|
||||
if (virAsprintf(&def->hubs[i]->info.alias, "hub%d", i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
if (def->console) {
|
||||
if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
|
||||
for (i = 0; i < def->nsmartcards ; i++) {
|
||||
if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0)
|
||||
goto no_memory;
|
||||
}
|
||||
if (def->watchdog) {
|
||||
@ -4498,8 +4498,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
|
||||
/* Explicit console devices */
|
||||
if (def->console) {
|
||||
virDomainChrDefPtr console = def->console;
|
||||
for (i = 0 ; i < def->nconsoles ; i++) {
|
||||
virDomainChrDefPtr console = def->consoles[i];
|
||||
char *devstr;
|
||||
|
||||
switch(console->targetType) {
|
||||
|
@ -10519,9 +10519,11 @@ qemuDomainOpenConsole(virDomainPtr dom,
|
||||
}
|
||||
|
||||
if (dev_name) {
|
||||
if (vm->def->console &&
|
||||
STREQ(dev_name, vm->def->console->info.alias))
|
||||
chr = vm->def->console;
|
||||
for (i = 0 ; !chr && i < vm->def->nconsoles ; i++) {
|
||||
if (vm->def->consoles[i]->info.alias &&
|
||||
STREQ(dev_name, vm->def->consoles[i]->info.alias))
|
||||
chr = vm->def->consoles[i];
|
||||
}
|
||||
for (i = 0 ; !chr && i < vm->def->nserials ; i++) {
|
||||
if (STREQ(dev_name, vm->def->serials[i]->info.alias))
|
||||
chr = vm->def->serials[i];
|
||||
@ -10531,8 +10533,8 @@ qemuDomainOpenConsole(virDomainPtr dom,
|
||||
chr = vm->def->parallels[i];
|
||||
}
|
||||
} else {
|
||||
if (vm->def->console)
|
||||
chr = vm->def->console;
|
||||
if (vm->def->nconsoles)
|
||||
chr = vm->def->consoles[0];
|
||||
else if (vm->def->nserials)
|
||||
chr = vm->def->serials[0];
|
||||
}
|
||||
|
@ -1112,8 +1112,8 @@ qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm,
|
||||
paths, chardevfmt) < 0)
|
||||
return -1;
|
||||
|
||||
if (vm->def->console &&
|
||||
qemuProcessLookupPTYs(&vm->def->console, 1, paths, chardevfmt) < 0)
|
||||
if (qemuProcessLookupPTYs(vm->def->consoles, vm->def->nconsoles,
|
||||
paths, chardevfmt) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
@ -1161,8 +1161,8 @@ qemuProcessFindCharDevicePTYs(virDomainObjPtr vm,
|
||||
}
|
||||
}
|
||||
|
||||
if (vm->def->console) {
|
||||
virDomainChrDefPtr chr = vm->def->console;
|
||||
for (i = 0 ; i < vm->def->nconsoles ; i++) {
|
||||
virDomainChrDefPtr chr = vm->def->consoles[i];
|
||||
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
|
||||
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
|
||||
if ((ret = qemuProcessExtractTTYPath(output, &offset,
|
||||
|
@ -888,6 +888,11 @@ SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||
{
|
||||
virDomainObjPtr vm = opaque;
|
||||
|
||||
/* This is taken care of by processing of def->serials */
|
||||
if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
||||
dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
|
||||
return 0;
|
||||
|
||||
return SELinuxRestoreSecurityChardevLabel(vm, &dev->source);
|
||||
}
|
||||
|
||||
@ -1228,6 +1233,11 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
||||
{
|
||||
virDomainObjPtr vm = opaque;
|
||||
|
||||
/* This is taken care of by processing of def->serials */
|
||||
if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
|
||||
dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
|
||||
return 0;
|
||||
|
||||
return SELinuxSetSecurityChardevLabel(vm, &dev->source);
|
||||
}
|
||||
|
||||
|
@ -925,12 +925,16 @@ get_files(vahControl * ctl)
|
||||
ctl->def->serials[i]->source.type) != 0)
|
||||
goto clean;
|
||||
|
||||
if (ctl->def->console && ctl->def->console->source.data.file.path)
|
||||
if (vah_add_file_chardev(&buf,
|
||||
ctl->def->console->source.data.file.path,
|
||||
"rw",
|
||||
ctl->def->console->source.type) != 0)
|
||||
goto clean;
|
||||
for (i = 0; i < ctl->def->nconsoles; i++)
|
||||
if (ctl->def->consoles[i] &&
|
||||
(ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY ||
|
||||
ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV ||
|
||||
ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE ||
|
||||
ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) &&
|
||||
ctl->def->consoles[i]->source.data.file.path)
|
||||
if (vah_add_file(&buf,
|
||||
ctl->def->consoles[i]->source.data.file.path, "rw") != 0)
|
||||
goto clean;
|
||||
|
||||
for (i = 0 ; i < ctl->def->nparallels; i++)
|
||||
if (ctl->def->parallels[i] &&
|
||||
|
@ -466,9 +466,13 @@ virCommandPtr umlBuildCommandLine(virConnectPtr conn,
|
||||
}
|
||||
|
||||
for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) {
|
||||
virDomainChrDefPtr chr = NULL;
|
||||
char *ret = NULL;
|
||||
if (i == 0 && vm->def->console)
|
||||
ret = umlBuildCommandLineChr(vm->def->console, "con", cmd);
|
||||
for (j = 0 ; j < vm->def->nconsoles ; j++)
|
||||
if (vm->def->consoles[j]->target.port == i)
|
||||
chr = vm->def->consoles[j];
|
||||
if (chr)
|
||||
ret = umlBuildCommandLineChr(chr, "con", cmd);
|
||||
if (!ret)
|
||||
if (virAsprintf(&ret, "con%d=none", i) < 0)
|
||||
goto no_memory;
|
||||
|
@ -248,10 +248,10 @@ umlIdentifyChrPTY(struct uml_driver *driver,
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dom->def->console &&
|
||||
dom->def->console->source.type == VIR_DOMAIN_CHR_TYPE_PTY)
|
||||
for (i = 0 ; i < dom->def->nserials; i++)
|
||||
if (dom->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY)
|
||||
if (umlIdentifyOneChrPTY(driver, dom,
|
||||
dom->def->console, "con") < 0)
|
||||
dom->def->consoles[i], "con") < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0 ; i < dom->def->nserials; i++)
|
||||
@ -2390,8 +2390,8 @@ umlDomainOpenConsole(virDomainPtr dom,
|
||||
_("Named device aliases are not supported"));
|
||||
goto cleanup;
|
||||
} else {
|
||||
if (vm->def->console)
|
||||
chr = vm->def->console;
|
||||
if (vm->def->nconsoles)
|
||||
chr = vm->def->consoles[0];
|
||||
else if (vm->def->nserials)
|
||||
chr = vm->def->serials[0];
|
||||
}
|
||||
|
@ -2136,8 +2136,8 @@ xenUnifiedDomainOpenConsole(virDomainPtr dom,
|
||||
if (!def)
|
||||
goto cleanup;
|
||||
|
||||
if (def->console)
|
||||
chr = def->console;
|
||||
if (def->nconsoles)
|
||||
chr = def->consoles[0];
|
||||
else if (def->nserials)
|
||||
chr = def->serials[0];
|
||||
|
||||
|
@ -202,7 +202,6 @@ xenParseSxprChar(const char *value,
|
||||
}
|
||||
}
|
||||
|
||||
/* Compat with legacy <console tty='/dev/pts/5'/> syntax */
|
||||
switch (def->source.type) {
|
||||
case VIR_DOMAIN_CHR_TYPE_PTY:
|
||||
if (tty != NULL &&
|
||||
@ -1395,12 +1394,15 @@ xenParseSxpr(const struct sexpr *root,
|
||||
def->parallels[def->nparallels++] = chr;
|
||||
}
|
||||
} else {
|
||||
def->nconsoles = 1;
|
||||
if (VIR_ALLOC_N(def->consoles, 1) < 0)
|
||||
goto no_memory;
|
||||
/* Fake a paravirt console, since that's not in the sexpr */
|
||||
if (!(def->console = xenParseSxprChar("pty", tty)))
|
||||
if (!(def->consoles[0] = xenParseSxprChar("pty", tty)))
|
||||
goto error;
|
||||
def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
def->console->target.port = 0;
|
||||
def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
|
||||
def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
def->consoles[0]->target.port = 0;
|
||||
def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
|
||||
}
|
||||
VIR_FREE(tty);
|
||||
|
||||
@ -1613,6 +1615,11 @@ xenFormatSxprChr(virDomainChrDefPtr def,
|
||||
if (def->source.data.nix.listen)
|
||||
virBufferAddLit(buf, ",server,nowait");
|
||||
break;
|
||||
|
||||
default:
|
||||
XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
_("unsupported chr device type '%s'"), type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virBufferError(buf)) {
|
||||
|
@ -1066,11 +1066,14 @@ xenParseXM(virConfPtr conf, int xendConfigVersion,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(def->console = xenParseSxprChar("pty", NULL)))
|
||||
def->nconsoles = 1;
|
||||
if (VIR_ALLOC_N(def->consoles, 1) < 0)
|
||||
goto no_memory;
|
||||
if (!(def->consoles[0] = xenParseSxprChar("pty", NULL)))
|
||||
goto cleanup;
|
||||
def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
def->console->target.port = 0;
|
||||
def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
|
||||
def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||
def->consoles[0]->target.port = 0;
|
||||
def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
|
||||
}
|
||||
|
||||
if (hvm) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
|
||||
unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \
|
||||
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \
|
||||
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \
|
||||
virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x3 \
|
||||
-device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -device \
|
||||
virtio-serial-pci,id=virtio-serial2,bus=pci.0,addr=0x4 -hda \
|
||||
|
@ -1,6 +1,7 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
|
||||
unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \
|
||||
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \
|
||||
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \
|
||||
virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda \
|
||||
/dev/HostVG/QEMUGuest1 -chardev pty,id=charchannel0 -device virtserialport,\
|
||||
bus=virtio-serial1.0,nr=3,chardev=charchannel0,id=channel0,\
|
||||
|
12
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args
Normal file
12
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args
Normal file
@ -0,0 +1,12 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \
|
||||
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \
|
||||
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \
|
||||
virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 -hda \
|
||||
/dev/HostVG/QEMUGuest1 -chardev pty,id=charserial0 \
|
||||
-device isa-serial,chardev=charserial0,id=serial0 -chardev pty,id=charconsole1 \
|
||||
-device virtconsole,chardev=charconsole1,id=console1 -chardev \
|
||||
pty,id=charconsole2 -device virtconsole,chardev=charconsole2,id=console2 \
|
||||
-chardev pty,id=charconsole3 -device virtconsole,chardev=charconsole3,\
|
||||
id=console3 -usb -device virtio-balloon-pci,id=balloon0,\
|
||||
bus=pci.0,addr=0x4
|
41
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml
Normal file
41
tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<domain type='qemu'>
|
||||
<name>QEMUGuest1</name>
|
||||
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||
<memory>219100</memory>
|
||||
<currentMemory>219100</currentMemory>
|
||||
<vcpu cpuset='1-4,8-20,525'>1</vcpu>
|
||||
<os>
|
||||
<type arch='i686' machine='pc'>hvm</type>
|
||||
<boot dev='hd'/>
|
||||
</os>
|
||||
<clock offset='utc'/>
|
||||
<on_poweroff>destroy</on_poweroff>
|
||||
<on_reboot>restart</on_reboot>
|
||||
<on_crash>destroy</on_crash>
|
||||
<devices>
|
||||
<emulator>/usr/bin/qemu</emulator>
|
||||
<disk type='block' device='disk'>
|
||||
<source dev='/dev/HostVG/QEMUGuest1'/>
|
||||
<target dev='hda' bus='ide'/>
|
||||
<address type='drive' controller='0' bus='0' unit='0'/>
|
||||
</disk>
|
||||
<controller type='ide' index='0'/>
|
||||
<controller type='virtio-serial' index='0'/>
|
||||
<serial type='pty'>
|
||||
<target port='0'/>
|
||||
</serial>
|
||||
<console type='pty'>
|
||||
<target type='serial' port='0'/>
|
||||
</console>
|
||||
<console type='pty'>
|
||||
<target type='virtio' port='1'/>
|
||||
</console>
|
||||
<console type='pty'>
|
||||
<target type='virtio' port='2'/>
|
||||
</console>
|
||||
<console type='pty'>
|
||||
<target type='virtio' port='3'/>
|
||||
</console>
|
||||
<memballoon model='virtio'/>
|
||||
</devices>
|
||||
</domain>
|
@ -1,6 +1,7 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
|
||||
unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \
|
||||
pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \
|
||||
socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \
|
||||
chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \
|
||||
virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 -hda \
|
||||
/dev/HostVG/QEMUGuest1 -chardev pty,id=charconsole0 -device virtconsole,\
|
||||
chardev=charconsole0,id=console0 -usb -device virtio-balloon-pci,id=balloon0,\
|
||||
|
@ -474,11 +474,13 @@ mymain(void)
|
||||
DO_TEST("channel-guestfwd", false,
|
||||
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||
DO_TEST("channel-virtio", false,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
|
||||
DO_TEST("channel-virtio-auto", false,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
|
||||
DO_TEST("console-virtio", false,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
|
||||
DO_TEST("console-virtio-many", false,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG);
|
||||
DO_TEST("channel-spicevmc", false,
|
||||
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||
QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEVMC);
|
||||
|
@ -174,6 +174,7 @@ mymain(void)
|
||||
DO_TEST("serial-many");
|
||||
DO_TEST("parallel-tcp");
|
||||
DO_TEST("console-compat");
|
||||
DO_TEST("console-virtio-many");
|
||||
DO_TEST("channel-guestfwd");
|
||||
DO_TEST("channel-virtio");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user