[Libvir] PATCH: Explicit detection of KVM version
Daniel P. Berrange
berrange at redhat.com
Thu Sep 20 16:59:37 UTC 2007
On Thu, Sep 20, 2007 at 05:07:30PM +0100, Daniel P. Berrange wrote:
> On Thu, Sep 20, 2007 at 10:45:03AM +0200, Gerd Hoffmann wrote:
> > Daniel P. Berrange wrote:
> > > Before starting any guest, the QEMU driver needs to figure out what version
> > > of QEMU is in use & thus determine whether it supports particular command
> > > line flags. We currently do that just by calling /usr/bin/qemu, since all
> > > the various qemu-system-XXX binaries share the same syntax. The only problem
> > > is that qemu-kvm does not neccessarily match the version of qemu installed.
> > > So we detect QEMU version 0.8.2, but KVM is 0.9.0 based. The result is that
> > > we pass the wrong style VNC argument to KVM & it fails to start. The second
> > > problem is that even if you only ever want to run KVM guests, you still have
> > > to have KVM itself installed.
> >
> > We have the same problem if the domain.xml has
> > "<emulator>/path/to/qemu-foo</emulator>" specified, which I think isn't
> > addressed by this patch ...
>
> Nope it is not addressed. I think maybe instead of detecting once for QEMU
> and KVM for the QEMU driver as whole, I'll move the flags into the per-VM
> data structure. This will have extra overhead, since for each distinct VM
> we'll have todo a test launch of QEMU, but VM creation is not a performance
> bottleneck so I don't think its an issue.
Here is an updated patch which makes the version/flags detection per-VM
in the qemu driver. We still cache the data, but invalidate it whenever
the VM's config is changed.
Tested with KVM when a differeing QEMU version is installed, and when no QEMU
is installed at all & both scenarios now work correctly.
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: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.13
diff -u -p -r1.13 qemu_conf.c
--- src/qemu_conf.c 13 Sep 2007 22:06:54 -0000 1.13
+++ src/qemu_conf.c 20 Sep 2007 16:54:38 -0000
@@ -287,7 +287,6 @@ static const char *qemudDefaultBinaryFor
/* Find the fully qualified path to the binary for an architecture */
static char *qemudLocateBinaryForArch(virConnectPtr conn,
- struct qemud_driver *driver ATTRIBUTE_UNUSED,
int virtType, const char *arch) {
const char *name;
char *path;
@@ -408,14 +407,15 @@ static int qemudExtractVersionInfo(const
}
int qemudExtractVersion(virConnectPtr conn,
- struct qemud_driver *driver) {
+ struct qemud_driver *driver ATTRIBUTE_UNUSED) {
char *binary = NULL;
struct stat sb;
+ int ignored;
if (driver->qemuVersion > 0)
return 0;
- if (!(binary = qemudLocateBinaryForArch(conn, driver, QEMUD_VIRT_QEMU, "i686")))
+ if (!(binary = qemudLocateBinaryForArch(conn, QEMUD_VIRT_QEMU, "i686")))
return -1;
if (stat(binary, &sb) < 0) {
@@ -426,7 +426,7 @@ int qemudExtractVersion(virConnectPtr co
return -1;
}
- if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &driver->qemuCmdFlags) < 0) {
+ if (qemudExtractVersionInfo(binary, &driver->qemuVersion, &ignored) < 0) {
free(binary);
return -1;
}
@@ -1199,7 +1199,7 @@ static struct qemud_vm_def *qemudParseXM
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
- char *tmp = qemudLocateBinaryForArch(conn, driver, def->virtType, def->os.arch);
+ char *tmp = qemudLocateBinaryForArch(conn, def->virtType, def->os.arch);
if (!tmp) {
goto error;
}
@@ -1466,8 +1466,23 @@ int qemudBuildCommandLine(virConnectPtr
struct utsname ut;
int disableKQEMU = 0;
- if (qemudExtractVersion(conn, driver) < 0)
+ /* Make sure the binary we are about to try exec'ing exists.
+ * Technically we could catch the exec() failure, but that's
+ * in a sub-process so its hard to feed back a useful error
+ */
+ if (stat(vm->def->os.binary, &sb) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "Cannot find QEMU binary %s: %s", vm->def->os.binary,
+ strerror(errno));
return -1;
+ }
+
+ if (vm->qemuVersion == 0) {
+ if (qemudExtractVersionInfo(vm->def->os.binary,
+ &(vm->qemuVersion),
+ &(vm->qemuCmdFlags)) < 0)
+ return -1;
+ }
uname(&ut);
@@ -1483,22 +1498,11 @@ int qemudBuildCommandLine(virConnectPtr
* 2. Guest is 'qemu'
* 3. The qemu binary has the -no-kqemu flag
*/
- if ((driver->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
+ if ((vm->qemuCmdFlags & QEMUD_CMD_FLAG_KQEMU) &&
!strcmp(ut.machine, vm->def->os.arch) &&
vm->def->virtType == QEMUD_VIRT_QEMU)
disableKQEMU = 1;
- /* Make sure the binary we are about to try exec'ing exists.
- * Technically we could catch the exec() failure, but that's
- * in a sub-process so its hard to feed back a useful error
- */
- if (stat(vm->def->os.binary, &sb) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- "Cannot find QEMU binary %s: %s", vm->def->os.binary,
- strerror(errno));
- return -1;
- }
-
len = 1 + /* qemu */
2 + /* machine type */
disableKQEMU + /* Disable kqemu */
@@ -1511,7 +1515,7 @@ int qemudBuildCommandLine(virConnectPtr
2 + /* boot device */
2 + /* monitor */
(vm->def->localtime ? 1 : 0) + /* localtime */
- (driver->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
+ (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
vm->def->noReboot ? 1 : 0) + /* no-reboot */
(vm->def->features & QEMUD_FEATURE_ACPI ? 0 : 1) + /* acpi */
(vm->def->os.kernel[0] ? 2 : 0) + /* kernel */
@@ -1567,7 +1571,7 @@ int qemudBuildCommandLine(virConnectPtr
goto no_memory;
}
- if (driver->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
+ if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_NO_REBOOT &&
vm->def->noReboot) {
if (!((*argv)[++n] = strdup("-no-reboot")))
goto no_memory;
@@ -1748,7 +1752,7 @@ int qemudBuildCommandLine(virConnectPtr
if (vm->def->graphicsType == QEMUD_GRAPHICS_VNC) {
char vncdisplay[BR_INET_ADDR_MAXLEN+20];
int ret;
- if (driver->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON)
+ if (vm->qemuCmdFlags & QEMUD_CMD_FLAG_VNC_COLON)
ret = snprintf(vncdisplay, sizeof(vncdisplay), "%s:%d",
vm->def->vncListen,
vm->def->vncActivePort - 5900);
@@ -1885,7 +1889,9 @@ qemudAssignVMDef(virConnectPtr conn,
qemudFreeVMDef(vm->newDef);
vm->newDef = def;
}
-
+ /* Reset version, because the emulator path might have changed */
+ vm->qemuVersion = 0;
+ vm->qemuCmdFlags = 0;
return vm;
}
Index: src/qemu_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.h,v
retrieving revision 1.8
diff -u -p -r1.8 qemu_conf.h
--- src/qemu_conf.h 14 Aug 2007 01:28:47 -0000 1.8
+++ src/qemu_conf.h 20 Sep 2007 16:54:38 -0000
@@ -211,6 +211,9 @@ struct qemud_vm {
int *tapfds;
int ntapfds;
+ int qemuVersion;
+ int qemuCmdFlags; /* values from enum qemud_cmd_flags */
+
char configFile[PATH_MAX];
char autostartLink[PATH_MAX];
char migrateFrom[PATH_MAX];
@@ -272,7 +275,6 @@ struct qemud_network {
/* Main driver state */
struct qemud_driver {
int qemuVersion;
- int qemuCmdFlags; /* values from enum qemud_cmd_flags */
int nactivevms;
int ninactivevms;
struct qemud_vm *vms;
Index: tests/qemuxml2argvtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/qemuxml2argvtest.c,v
retrieving revision 1.4
diff -u -p -r1.4 qemuxml2argvtest.c
--- tests/qemuxml2argvtest.c 13 Sep 2007 22:06:54 -0000 1.4
+++ tests/qemuxml2argvtest.c 20 Sep 2007 16:54:38 -0000
@@ -37,6 +37,10 @@ static int testCompareXMLToArgvFiles(con
vm.def = vmdef;
vm.pid = -1;
vm.id = -1;
+ vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
+ vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
+ QEMUD_CMD_FLAG_NO_REBOOT;
+
vmdef->vncActivePort = vmdef->vncPort;
if (qemudBuildCommandLine(NULL, &driver, &vm, &argv) < 0)
@@ -107,10 +111,6 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- driver.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
- driver.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
- QEMUD_CMD_FLAG_NO_REBOOT;
-
if (virtTestRun("QEMU XML-2-ARGV minimal",
1, testCompareXMLToArgvHelper, "minimal") < 0)
ret = -1;
Index: tests/qemuxml2xmltest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/qemuxml2xmltest.c,v
retrieving revision 1.4
diff -u -p -r1.4 qemuxml2xmltest.c
--- tests/qemuxml2xmltest.c 13 Sep 2007 22:06:54 -0000 1.4
+++ tests/qemuxml2xmltest.c 20 Sep 2007 16:54:38 -0000
@@ -31,6 +31,10 @@ static int testCompareXMLToXMLFiles(cons
vm.def = vmdef;
vm.pid = -1;
vm.id = -1;
+ vm.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
+ vm.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
+ QEMUD_CMD_FLAG_NO_REBOOT;
+
vmdef->vncActivePort = vmdef->vncPort;
if (!(actual = qemudGenerateXML(NULL, &driver, &vm, vmdef, 0)))
@@ -72,10 +76,6 @@ main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- driver.qemuVersion = 0 * 1000 * 100 + (8 * 1000) + 1;
- driver.qemuCmdFlags = QEMUD_CMD_FLAG_VNC_COLON |
- QEMUD_CMD_FLAG_NO_REBOOT;
-
if (virtTestRun("QEMU XML-2-ARGV minimal",
1, testCompareXMLToXMLHelper, "minimal") < 0)
ret = -1;
More information about the libvir-list
mailing list