Index: qemud/conf.c =================================================================== RCS file: /data/cvs/libvirt/qemud/conf.c,v retrieving revision 1.28 diff -u -p -r1.28 conf.c --- qemud/conf.c 22 Feb 2007 10:39:38 -0000 1.28 +++ qemud/conf.c 22 Feb 2007 18:20:21 -0000 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -257,6 +258,112 @@ static char *qemudLocateBinaryForArch(st return path; } + +static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) { + int child; + int newstdout[2]; + + *flags = 0; + *version = 0; + + if (pipe(newstdout) < 0) { + return -1; + } + + if ((child = fork()) < 0) { + close(newstdout[0]); + close(newstdout[1]); + 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; + + reread: + if ((got = read(newstdout[0], help, sizeof(help)-1)) < 0) { + if (errno == EINTR) + goto reread; + goto cleanup2; + } + help[got] = '\0'; + + if (sscanf(help, "QEMU PC emulator version %d.%d.%d", &major,&minor, µ) != 3) { + goto cleanup2; + } + + *version = (major * 1000 * 1000) + (minor * 1000) + micro; + if (strstr(help, "-no-kqemu")) + *flags |= QEMUD_CMD_FLAG_KQEMU; + if (*version >= 9000) + *flags |= QEMUD_CMD_FLAG_VNC_COLON; + 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; + + rewait: + if (waitpid(child, &got, 0) != child) { + if (errno == EINTR) { + goto rewait; + } + qemudLog(QEMUD_ERR, "Unexpected exit status from qemu %d pid %d", got, child); + ret = -1; + } + /* Check & log unexpected exit status, but don't fail, + * as there's really no need to throw an error if we did + * actually read a valid version number above */ + if (WEXITSTATUS(got) != 1) { + qemudLog(QEMUD_WARN, "Unexpected exit status '%d', qemu probably failed", got); + } + + return ret; + } +} + +int qemudExtractVersion(struct qemud_server *server) { + char *binary = NULL; + + if (server->qemuVersion > 0) + return 0; + + if (!(binary = qemudLocateBinaryForArch(server, QEMUD_VIRT_QEMU, "i686"))) + return -1; + + if (qemudExtractVersionInfo(binary, &server->qemuVersion, &server->qemuCmdFlags) < 0) { + free(binary); + return -1; + } + + free(binary); + return 0; +} + + /* Parse the XML definition for a disk */ static struct qemud_vm_disk_def *qemudParseDiskXML(struct qemud_server *server, xmlNodePtr node) { @@ -950,9 +1057,13 @@ int qemudBuildCommandLine(struct qemud_s struct qemud_vm_disk_def *disk = vm->def->disks; struct qemud_vm_net_def *net = vm->def->nets; + if (qemudExtractVersion(server) < 0) + return -1; + len = 1 + /* qemu */ 2 + /* machine type */ - (vm->def->virtType == QEMUD_VIRT_QEMU ? 1 : 0) + /* Disable kqemu */ + (((server->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && + (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*/ @@ -977,9 +1088,10 @@ 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->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) && + (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; @@ -996,8 +1108,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++) { @@ -1103,7 +1215,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->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON) ? + ":%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 22 Feb 2007 18:21:15 -0000 @@ -26,6 +26,8 @@ #include "internal.h" +int qemudExtractVersion(struct qemud_server *server); + 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 22 Feb 2007 18:21:15 -0000 @@ -274,6 +274,9 @@ struct qemud_vm *qemudFindVMByName(const } int qemudGetVersion(struct qemud_server *server) { + if (qemudExtractVersion(server) < 0) + return -1; + return server->qemuVersion; } 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 22 Feb 2007 18:21:24 -0000 @@ -152,6 +152,13 @@ enum qemud_vm_grapics_type { QEMUD_GRAPHICS_VNC, }; +/* Internal flags to keep track of qemu command line capabilities */ +enum qemud_cmd_flags { + QEMUD_CMD_FLAG_KQEMU = 1, + QEMUD_CMD_FLAG_VNC_COLON = 2, +}; + + enum qemud_vm_features { QEMUD_FEATURE_ACPI = 1, }; @@ -275,6 +282,7 @@ struct qemud_server { int nsockets; struct qemud_socket *sockets; int qemuVersion; + int qemuCmdFlags; /* values from enum qemud_cmd_flags */ 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 22 Feb 2007 18:21:26 -0000 @@ -417,8 +417,6 @@ static struct qemud_server *qemudInitial 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;