On Mon, Nov 23, 2009 at 12:30:29PM +0000, Matthew Booth wrote: > This change makes the QEMU driver get pty paths from the output of the monitor > 'info chardev' command. This output is structured, and contains both the name of > the device and the path on the same line. This is considerably more reliable > than parsing the startup log output, which requires the parsing code to know > which order QEMU will print pty information in. > > Note that we still need to parse the log output as the monitor itself may be on > a pty. This should be rare, however, and the new code will replace all pty paths > parsed by the log output method once the monitor is available. > > * src/qemu/qemu_monitor.(c|h) src/qemu_monitor_text.(c|h): Implement > qemuMonitorGetPtyPaths(). > * src/qemu/qemu_driver.c: Get pty path information using > qemuMonitorGetPtyPaths(). > --- > src/qemu/qemu_driver.c | 68 +++++++++++++++++++++++++++++++++++++++- > src/qemu/qemu_monitor.c | 9 +++++ > src/qemu/qemu_monitor.h | 3 ++ > src/qemu/qemu_monitor_text.c | 71 ++++++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_monitor_text.h | 4 ++ > 5 files changed, 153 insertions(+), 2 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index ebf44b0..90dd9cd 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -1239,6 +1239,40 @@ qemudExtractTTYPath(virConnectPtr conn, > } > > static int > +qemudFindCharDevicePTYsMonitor(virConnectPtr conn, > + virDomainObjPtr vm, > + virHashTablePtr paths) > +{ > + int i; > + > +#define LOOKUP_PTYS(array, arraylen, idprefix) \ > + for (i = 0 ; i < (arraylen) ; i++) { \ > + virDomainChrDefPtr chr = (array)[i]; \ > + if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) { \ > + char id[16]; \ > +\ > + if (snprintf(id, sizeof(id), idprefix "%i", i) >= sizeof(id)) \ > + return -1; \ > +\ > + const char *path = (const char *) virHashLookup(paths, id); \ > + if (path == NULL) { \ > + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, \ > + _("no assigned pty for device %s"), id); \ > + return -1; \ > + } \ > +\ > + chr->data.file.path = strdup(path); \ > + } \ > + } Can you indent the \ to they all line up in the right hand side. > + > + LOOKUP_PTYS(vm->def->serials, vm->def->nserials, "serial"); > + LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel"); > + LOOKUP_PTYS(vm->def->channels, vm->def->nchannels, "channel"); > + #undef LOOKUP_PTYS > + return 0; > +} > + > +static int > qemudFindCharDevicePTYs(virConnectPtr conn, > virDomainObjPtr vm, > const char *output, > @@ -1284,6 +1318,11 @@ qemudFindCharDevicePTYs(virConnectPtr conn, > return 0; > } > > +static void qemudFreePtyPath(void *payload, const char *name ATTRIBUTE_UNUSED) > +{ > + free(payload); VIR_FREE > +} > + > static int > qemudWaitForMonitor(virConnectPtr conn, > struct qemud_driver* driver, > @@ -1291,7 +1330,7 @@ qemudWaitForMonitor(virConnectPtr conn, > { > char buf[4096]; /* Plenty of space to get startup greeting */ > int logfd; > - int ret; > + int ret = -1; > > if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos)) > < 0) > @@ -1317,7 +1356,32 @@ qemudWaitForMonitor(virConnectPtr conn, > if (qemuConnectMonitor(vm) < 0) > return -1; > > - return 0; > + /* Try to get the pty path mappings again via the monitor. This is much more > + * reliable if it's available. > + * Note that the monitor itself can be on a pty, so we still need to try the > + * log output method. */ > + virHashTablePtr paths = virHashCreate(0); > + if (paths == NULL) { > + virReportOOMError(NULL); > + goto cleanup; > + } > + > + qemuDomainObjEnterMonitor(vm); This needs to be EnterMonitorWithDriver(driver, vm), since the 'driver' is locked in this context > + qemuDomainObjPrivatePtr priv = vm->privateData; > + ret = qemuMonitorGetPtyPaths(priv->mon, paths); > + qemuDomainObjExitMonitor(vm); And ExitMonitorWithDriver > + > + VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); > + if (ret == 0) { > + ret = qemudFindCharDevicePTYsMonitor(conn, vm, paths); > + } > + > +cleanup: > + if (paths) { > + virHashFree(paths, qemudFreePtyPath); > + } > + > + return ret; > } > + > + > +/* Parse the output of "info chardev" and return a hash of pty paths. > + * > + * Output is: > + * foo: filename=pty:/dev/pts/7 > + * monitor: filename=stdio > + * serial0: filename=vc > + * parallel0: filename=vc > + * > + * Non-pty lines are ignored. In the above example, key is 'foo', value is > + * '/dev/pty/7'. The hash will contain only a single value. > + */ > + > +int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon, > + virHashTablePtr paths) > +{ > + const char *cmd = "info chardev"; > + char *reply = NULL; > + int ret = -1; > + > + if (qemuMonitorCommand(mon, cmd, &reply) < 0) { > + qemudReportError(NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED, > + _("failed to retrieve chardev info in qemu with '%s'"), > + cmd); > + goto cleanup; > + } > + > + char *pos = reply; /* The current start of searching */ > + char *end = pos + strlen(reply); /* The end of the reply string */ > + char *eol; /* The character which ends the current line */ > + > + while (pos < end) { > + /* Split the output into lines */ > + eol = memchr(pos, '\n', end - pos); > + if (eol == NULL) > + eol = end; > + > + /* Look for 'filename=pty:' */ > +#define NEEDLE "filename=pty:" > + char *needle = memmem(pos, eol - pos, NEEDLE, strlen(NEEDLE)); > + > + /* If it's not there we can ignore this line */ > + if (!needle) > + goto next; > + > + /* id is everthing from the beginning of the line to the ':' > + * find ':' and turn it into a terminator */ > + char *colon = memchr(pos, ':', needle - pos); > + if (colon == NULL) > + goto next; > + *colon = '\0'; > + char *id = pos; > + > + /* Path is everything after needle to the end of the line */ > + *eol = '\0'; > + char *path = needle + strlen(NEEDLE); > + > + virHashAddEntry(paths, id, strdup(path)); Not checking OOM on strdup() here, or for failure of virHashAddEntry() > +#undef NEEDLE > + > + next: > + pos = eol + 1; > + } > + > + ret = 0; > + > +cleanup: > + VIR_FREE(reply); > + return ret; > +} Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list