]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Autodetect QEMU version and adjust command line arg accordingly
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 23 Feb 2007 17:15:18 +0000 (17:15 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 23 Feb 2007 17:15:18 +0000 (17:15 +0000)
ChangeLog
qemud/conf.c
qemud/conf.h
qemud/driver.c
qemud/internal.h
qemud/qemud.c

index 314c155ec36c26749f028056415893379ed8a3d9..2e4ab0dd77928e3b718d8f0c3f59da5776482617 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Feb 23 12:14:34 EST 2007 Daniel P. Berrange <berrange@redhat.com>
+
+       * qemud/driver.c, qemud/internal.h, qemud/qemud.c, qemud/conf.c,
+       qemud/conf.h: Added code to detect QEMU version number. Adapt
+       command line construction code to use correct options for VNC
+       and KQEMU based on version number
+
 Fri Feb 23 10:52:23 EST 2007 Daniel P. Berrange <berrange@redhat.com>
 
        * qemud/Makefile.am: Fix up name of init script in EXTRA_DIST
index 68d32ba814cb4a03874060c1c2ab96d5a8817cc8..54d67f430d21718c95a7c6c20c557d9ac7681fbe 100644 (file)
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <sys/wait.h>
 
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -257,6 +258,112 @@ static char *qemudLocateBinaryForArch(struct qemud_server *server,
     return path;
 }
 
+
+static int qemudExtractVersionInfo(const char *qemu, int *version, int *flags) {
+    pid_t 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, &micro) != 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 flags ? %d",
+                   major, minor, micro, *version, *flags);
+
+    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 %lu", got, (unsigned long)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_server *server,
     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_server *server,
         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_server *server,
         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_server *server,
 
     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 9069ee684203085ce1bd8460d482cc633381c357..60b39f50d716a6bf3febe1a9c7aa515a2a938ab9 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "internal.h"
 
+int         qemudExtractVersion         (struct qemud_server *server);
 int         qemudBuildCommandLine       (struct qemud_server *server,
                                          struct qemud_vm *vm,
                                          char ***argv);
index 1aa3b396a4b07215a32d020e1c26260dce0a353b..6074aa5236fe4f717fa7fafaf9ef4dcc36719a73 100644 (file)
@@ -260,6 +260,9 @@ struct qemud_vm *qemudFindVMByName(const struct qemud_server *server,
 }
 
 int qemudGetVersion(struct qemud_server *server) {
+    if (qemudExtractVersion(server) < 0)
+        return -1;
+
     return server->qemuVersion;
 }
 
index b18aed8fe33c991060dedf4d496b6e7da414a9e2..e2b5b722c42d88356a65389b43a591f4f7f593db 100644 (file)
@@ -161,6 +161,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,
 };
@@ -289,6 +296,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 bcfc613b1d285ead7aeb67ff1c7bd0789cf1abb5..77c104129f82ccbeab3d88b26bba543296ee28df 100644 (file)
@@ -459,8 +459,6 @@ static struct qemud_server *qemudInitialize(int sys, int sigread) {
         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;