When I tested out the libvirt 0.2.0 in Fedora rawhide I discovered that the syntax for specifying VNC display numbers changes in QEMU 0.9.0. Previously you would use -vnc 7 Now you need to use -vnc :7 For current Fedora RPM I just hacked in a workaround to always add ':', but we need to be able to detect the version properly. So I'm attaching a patch which spawns '/usr/bin/qemu' and groks its command line help to extract the version number. It then uses appropriate VNC argument syntax based on the version. At the same time I also check for whether -no-kqemu is available so we can turn off KQEMU support if it is not available. Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
Index: qemud/conf.c =================================================================== RCS file: /data/cvs/libvirt/qemud/conf.c,v retrieving revision 1.27 diff -u -p -r1.27 conf.c --- qemud/conf.c 20 Feb 2007 19:09:44 -0000 1.27 +++ qemud/conf.c 21 Feb 2007 15:40:41 -0000 @@ -231,8 +231,8 @@ static const char *qemudDefaultBinaryFor } /* Find the fully qualified path to the binary for an architecture */ -static char *qemudLocateBinaryForArch(struct qemud_server *server, - int virtType, const char *arch) { +char *qemudLocateBinaryForArch(struct qemud_server *server, + int virtType, const char *arch) { const char *name; char *path; @@ -551,7 +551,7 @@ static struct qemud_vm_def *qemudParseXM if (!strcmp((char *)prop, "qemu")) def->virtType = QEMUD_VIRT_QEMU; - else if (!strcmp((char *)prop, "kqemu")) + else if (!strcmp((char *)prop, "kqemu") && server->qemuHasKQEMU) def->virtType = QEMUD_VIRT_KQEMU; else if (!strcmp((char *)prop, "kvm")) def->virtType = QEMUD_VIRT_KVM; @@ -949,7 +949,7 @@ int qemudBuildCommandLine(struct qemud_s len = 1 + /* qemu */ 2 + /* machine type */ - (vm->def->virtType == QEMUD_VIRT_QEMU ? 1 : 0) + /* Disable kqemu */ + (server->qemuHasKQEMU && vm->def->virtType == QEMUD_VIRT_QEMU ? 1 : 0) + /* Disable kqemu */ 2 * vm->def->ndisks + /* disks*/ (vm->def->nnets > 0 ? (4 * vm->def->nnets) : 2) + /* networks */ 2 + /* memory*/ @@ -974,9 +974,9 @@ int qemudBuildCommandLine(struct qemud_s goto no_memory; if (!((*argv)[++n] = strdup(vm->def->os.machine))) goto no_memory; - if (vm->def->virtType == QEMUD_VIRT_QEMU) { + if (server->qemuHasKQEMU && vm->def->virtType == QEMUD_VIRT_QEMU) { if (!((*argv)[++n] = strdup("-no-kqemu"))) - goto no_memory; + goto no_memory; } if (!((*argv)[++n] = strdup("-m"))) goto no_memory; @@ -993,8 +993,8 @@ int qemudBuildCommandLine(struct qemud_s goto no_memory; if (!(vm->def->features & QEMUD_FEATURE_ACPI)) { - if (!((*argv)[++n] = strdup("-no-acpi"))) - goto no_memory; + if (!((*argv)[++n] = strdup("-no-acpi"))) + goto no_memory; } for (i = 0 ; i < vm->def->os.nBootDevs ; i++) { @@ -1100,7 +1100,14 @@ int qemudBuildCommandLine(struct qemud_s if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) { char port[10]; - snprintf(port, 10, "%d", vm->def->vncActivePort - 5900); + int ret; + ret = snprintf(port, sizeof(port), + (server->qemuVersion >= 9000 ? + ":%d" : "%d"), + vm->def->vncActivePort - 5900); + if (ret < 0 || ret >= (int)sizeof(port)) + goto error; + if (!((*argv)[++n] = strdup("-vnc"))) goto no_memory; if (!((*argv)[++n] = strdup(port))) Index: qemud/conf.h =================================================================== RCS file: /data/cvs/libvirt/qemud/conf.h,v retrieving revision 1.7 diff -u -p -r1.7 conf.h --- qemud/conf.h 15 Feb 2007 19:04:45 -0000 1.7 +++ qemud/conf.h 21 Feb 2007 15:40:41 -0000 @@ -26,6 +26,8 @@ #include "internal.h" +char *qemudLocateBinaryForArch(struct qemud_server *server, + int virtType, const char *arch); int qemudBuildCommandLine(struct qemud_server *server, struct qemud_vm *vm, char ***argv); Index: qemud/driver.c =================================================================== RCS file: /data/cvs/libvirt/qemud/driver.c,v retrieving revision 1.10 diff -u -p -r1.10 driver.c --- qemud/driver.c 16 Feb 2007 18:30:55 -0000 1.10 +++ qemud/driver.c 21 Feb 2007 15:40:41 -0000 @@ -34,6 +34,7 @@ #include <stdlib.h> #include <unistd.h> #include <errno.h> +#include <sys/wait.h> #include <libvirt/virterror.h> @@ -54,6 +55,75 @@ void qemudReportError(struct qemud_serve } } +int qemudExtractVersion(const char *qemu, int *version, int *hasKQEMU) { + int child; + int newstdout[2]; + + if (pipe(newstdout) < 0) { + return -1; + } + + if ((child = fork()) < 0) { + return -1; + } + + if (child == 0) { /* Kid */ + if (close(STDIN_FILENO) < 0) + goto cleanup1; + if (close(STDERR_FILENO) < 0) + goto cleanup1; + if (close(newstdout[0]) < 0) + goto cleanup1; + if (dup2(newstdout[1], STDOUT_FILENO) < 0) + goto cleanup1; + + /* Just in case QEMU is translated someday.. */ + setenv("LANG", "C", 1); + execl(qemu, qemu, (char*)NULL); + + cleanup1: + _exit(-1); /* Just in case */ + } else { /* Parent */ + char help[4096]; /* Ought to be enough to hold QEMU help screen */ + int got, ret = -1; + int major, minor, micro; + + if (close(newstdout[1]) < 0) + goto cleanup2; + + if ((got = read(newstdout[0], help, sizeof(help)-1)) < 0) + goto cleanup2; + help[got] = '\0'; + + if (sscanf(help, "QEMU PC emulator version %d.%d.%d", &major,&minor, µ) != 3) { + goto cleanup2; + } + + if (strstr(help, "-no-kqemu")) + *hasKQEMU = 1; + else + *hasKQEMU = 0; + *version = (major * 1000 * 1000) + (minor * 1000) + micro; + ret = 0; + + qemudDebug("Version %d %d %d Cooked version: %d, with KQEMU ? %d", + major, minor, micro, *version, *hasKQEMU); + + cleanup2: + if (close(newstdout[0]) < 0) + ret = -1; + + if (waitpid(child, &got, 0) != child || + WEXITSTATUS(got) != 1) { + qemudLog(QEMUD_ERR, "Unexpected exit status from qemu %d pid %d", got, child); + ret = -1; + } + + return ret; + } +} + + int qemudMonitorCommand(struct qemud_server *server ATTRIBUTE_UNUSED, struct qemud_vm *vm, const char *cmd, Index: qemud/driver.h =================================================================== RCS file: /data/cvs/libvirt/qemud/driver.h,v retrieving revision 1.3 diff -u -p -r1.3 driver.h --- qemud/driver.h 14 Feb 2007 16:20:38 -0000 1.3 +++ qemud/driver.h 21 Feb 2007 15:40:41 -0000 @@ -30,6 +30,7 @@ void qemudReportError(struct qemud_server *server, int code, const char *fmt, ...); +int qemudExtractVersion(const char *qemu, int *version, int *hasKQEMU); int qemudGetCPUInfo(unsigned int *cpus, unsigned int *mhz, unsigned int *nodes, unsigned int *sockets, unsigned int *cores, unsigned int *threads); Index: qemud/internal.h =================================================================== RCS file: /data/cvs/libvirt/qemud/internal.h,v retrieving revision 1.12 diff -u -p -r1.12 internal.h --- qemud/internal.h 16 Feb 2007 18:30:55 -0000 1.12 +++ qemud/internal.h 21 Feb 2007 15:40:41 -0000 @@ -275,6 +275,7 @@ struct qemud_server { int nsockets; struct qemud_socket *sockets; int qemuVersion; + int qemuHasKQEMU; int nclients; struct qemud_client *clients; int sigread; Index: qemud/qemud.c =================================================================== RCS file: /data/cvs/libvirt/qemud/qemud.c,v retrieving revision 1.23 diff -u -p -r1.23 qemud.c --- qemud/qemud.c 20 Feb 2007 17:51:41 -0000 1.23 +++ qemud/qemud.c 21 Feb 2007 15:40:42 -0000 @@ -411,20 +411,26 @@ static struct qemud_server *qemudInitial struct qemud_server *server; char sockname[PATH_MAX]; char roSockname[PATH_MAX]; + char *binary = NULL; if (!(server = calloc(1, sizeof(struct qemud_server)))) { qemudLog(QEMUD_ERR, "Failed to allocate struct qemud_server"); return NULL; } - /* XXX extract actual version */ - server->qemuVersion = (0*1000000)+(8*1000)+(0); /* We don't have a dom-0, so start from 1 */ server->nextvmid = 1; server->sigread = sigread; roSockname[0] = '\0'; + if (!(binary = qemudLocateBinaryForArch(server, QEMUD_VIRT_QEMU, "i686"))) + goto cleanup; + if (qemudExtractVersion(binary, &server->qemuVersion, &server->qemuHasKQEMU) < 0) + goto cleanup; + free(binary); + binary = NULL; + if (qemudInitPaths(sys, server->configDir, server->networkConfigDir, sockname, roSockname, PATH_MAX) < 0) goto cleanup; @@ -451,6 +457,8 @@ static struct qemud_server *qemudInitial free(server); } + if (binary) + free(binary); return NULL; }