mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
Autodetect QEMU version and adjust command line arg accordingly
This commit is contained in:
parent
66a55a4d48
commit
73048102c0
@ -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
|
||||
|
131
qemud/conf.c
131
qemud/conf.c
@ -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, µ) != 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)))
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user