1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-23 21:34:54 +03:00

qemu: assume 'info chardev' is always available

As of QEMU 0.11.0 the 'info chardev' monitor command can be
used to report on allocated chardev paths, so we can drop
support for parsing QEMU stderr to locate the PTY paths.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2015-11-05 11:00:17 +00:00
parent 9cd0fe69cd
commit 932534e85f
3 changed files with 3 additions and 207 deletions

View File

@ -3842,11 +3842,6 @@ virQEMUCapsCacheFree(virQEMUCapsCachePtr cache)
VIR_FREE(cache);
}
bool
virQEMUCapsUsedQMP(virQEMUCapsPtr qemuCaps)
{
return qemuCaps->usedQMP;
}
bool
virQEMUCapsSupportsChardev(virDomainDefPtr def,

View File

@ -427,7 +427,6 @@ int virQEMUCapsParseDeviceStr(virQEMUCapsPtr qemuCaps, const char *str);
VIR_ENUM_DECL(virQEMUCaps);
bool virQEMUCapsUsedQMP(virQEMUCapsPtr qemuCaps);
bool virQEMUCapsSupportsChardev(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
virDomainChrDefPtr chr);

View File

@ -52,7 +52,6 @@
#include "virhook.h"
#include "virfile.h"
#include "virpidfile.h"
#include "c-ctype.h"
#include "nodeinfo.h"
#include "domain_audit.h"
#include "domain_nwfilter.h"
@ -1675,76 +1674,6 @@ qemuProcessReadLog(int fd, char *buf, int buflen, int off, bool skipchar)
return off;
}
typedef int qemuProcessLogHandleOutput(virDomainObjPtr vm,
const char *output,
int fd);
/*
* Returns -1 for error, 0 on success
*/
static int
qemuProcessReadLogOutput(virDomainObjPtr vm,
int fd,
char *buf,
size_t buflen,
qemuProcessLogHandleOutput func,
const char *what,
int timeout)
{
int retries = (timeout*10);
int got = 0;
int ret = -1;
buf[0] = '\0';
while (retries) {
ssize_t func_ret;
bool isdead;
func_ret = func(vm, buf, fd);
isdead = kill(vm->pid, 0) == -1 && errno == ESRCH;
got = qemuProcessReadLog(fd, buf, buflen, got, false);
if (got < 0) {
virReportSystemError(errno,
_("Failure while reading %s log output"),
what);
goto cleanup;
}
if (got == buflen-1) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Out of space while reading %s log output: %s"),
what, buf);
goto cleanup;
}
if (isdead) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Process exited while reading %s log output: %s"),
what, buf);
goto cleanup;
}
if (func_ret <= 0) {
ret = func_ret;
goto cleanup;
}
usleep(100*1000);
retries--;
}
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Timed out while reading %s log output: %s"),
what, buf);
cleanup:
return ret;
}
/*
* Read domain log and probably overwrite error if there's one in
* the domain log file. This function exists to cover the small
@ -1809,54 +1738,6 @@ qemuProcessReadChildErrors(virQEMUDriverPtr driver,
}
/*
* Look at a chunk of data from the QEMU stdout logs and try to
* find a TTY device, as indicated by a line like
*
* char device redirected to /dev/pts/3
*
* Returns -1 for error, 0 success, 1 continue reading
*/
static int
qemuProcessExtractTTYPath(const char *haystack,
size_t *offset,
char **path)
{
static const char needle[] = "char device redirected to";
char *tmp, *dev;
VIR_FREE(*path);
/* First look for our magic string */
if (!(tmp = strstr(haystack + *offset, needle)))
return 1;
tmp += sizeof(needle);
dev = tmp;
/*
* And look for first whitespace character and nul terminate
* to mark end of the pty path
*/
while (*tmp) {
if (c_isspace(*tmp)) {
if (VIR_STRNDUP(*path, dev, tmp - dev) < 0)
return -1;
/* ... now further update offset till we get EOL */
*offset = tmp - haystack;
return 0;
}
tmp++;
}
/*
* We found a path, but didn't find any whitespace,
* so it must be still incomplete - we should at
* least see a \n - indicate that we want to carry
* on trying again
*/
return 1;
}
static int
qemuProcessLookupPTYs(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
@ -1954,72 +1835,6 @@ qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm,
return 0;
}
static int
qemuProcessFindCharDevicePTYs(virDomainObjPtr vm,
const char *output,
int fd ATTRIBUTE_UNUSED)
{
size_t offset = 0;
int ret;
size_t i;
/* The order in which QEMU prints out the PTY paths is
the order in which it procsses its serial and parallel
device args. This code must match that ordering.... */
/* first comes the serial devices */
for (i = 0; i < vm->def->nserials; i++) {
virDomainChrDefPtr chr = vm->def->serials[i];
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
if ((ret = qemuProcessExtractTTYPath(output, &offset,
&chr->source.data.file.path)) != 0)
return ret;
}
}
/* then the parallel devices */
for (i = 0; i < vm->def->nparallels; i++) {
virDomainChrDefPtr chr = vm->def->parallels[i];
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
if ((ret = qemuProcessExtractTTYPath(output, &offset,
&chr->source.data.file.path)) != 0)
return ret;
}
}
/* then the channel devices */
for (i = 0; i < vm->def->nchannels; i++) {
virDomainChrDefPtr chr = vm->def->channels[i];
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY) {
if ((ret = qemuProcessExtractTTYPath(output, &offset,
&chr->source.data.file.path)) != 0)
return ret;
}
}
for (i = 0; i < vm->def->nconsoles; i++) {
virDomainChrDefPtr chr = vm->def->consoles[i];
/* For historical reasons, console[0] can be just an alias
* for serial[0]; That's why we need to update it as well */
if (i == 0 && vm->def->nserials &&
chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
if ((ret = virDomainChrSourceDefCopy(&chr->source,
&((vm->def->serials[0])->source))) != 0)
return ret;
} else {
if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY &&
chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
if ((ret = qemuProcessExtractTTYPath(output, &offset,
&chr->source.data.file.path)) != 0)
return ret;
}
}
}
return 0;
}
static int
qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
@ -2140,15 +1955,6 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
(logfd = qemuDomainOpenLog(driver, vm, pos)) < 0)
return -1;
if (logfd != -1 && !virQEMUCapsUsedQMP(qemuCaps)) {
if (VIR_ALLOC_N(buf, buf_size) < 0)
goto closelog;
if (qemuProcessReadLogOutput(vm, logfd, buf, buf_size,
qemuProcessFindCharDevicePTYs,
"console", 30) < 0)
goto closelog;
}
VIR_DEBUG("Connect monitor to %p '%s'", vm, vm->def->name);
if (qemuConnectMonitor(driver, vm, asyncJob, logfd) < 0)
@ -2180,20 +1986,16 @@ qemuProcessWaitForMonitor(virQEMUDriverPtr driver,
virHashFree(info);
if (pos != -1 && kill(vm->pid, 0) == -1 && errno == ESRCH) {
int len;
/* VM is dead, any other error raised in the interim is probably
* not as important as the qemu cmdline output */
if (virQEMUCapsUsedQMP(qemuCaps)) {
if (VIR_ALLOC_N(buf, buf_size) < 0)
goto closelog;
}
if (VIR_ALLOC_N(buf, buf_size) < 0)
goto closelog;
len = strlen(buf);
/* best effort seek - we need to reset to the original position, so that
* a possible read of the fd in the monitor code doesn't influence this
* error delivery option */
ignore_value(lseek(logfd, pos, SEEK_SET));
qemuProcessReadLog(logfd, buf + len, buf_size - len - 1, 0, true);
qemuProcessReadLog(logfd, buf, buf_size - 1, 0, true);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("process exited while connecting to monitor: %s"),
buf);