[Libvir] PATCH: Autodetect QEMU version
Daniel P. Berrange
berrange at redhat.com
Wed Feb 21 15:45:35 UTC 2007
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 -=|
-------------- next part --------------
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;
}
More information about the libvir-list
mailing list