mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-29 17:33:09 +00:00
Re-factor qemu version parsing
This patch is purely re-factoring without any functional changes to make way for the next patch. The main thing achieved by the refactoring is that we now have easier access to the parenthesised string that KVM folks seem to delight in changing. Signed-off-by: Mark McLoughlin <markmc@redhat.com>
This commit is contained in:
parent
abed6fca87
commit
56ecebf22d
@ -1,3 +1,7 @@
|
|||||||
|
Thu Jun 11 15:15:02 GMT 2009 Mark McLoughlin <markmc@redhat.com>
|
||||||
|
|
||||||
|
* src/qemu_conf.c: re-factor qemu version parsing.
|
||||||
|
|
||||||
Thu Jun 11 15:14:37 CEST 2009 Daniel Veillard <veillard@redhat.com>
|
Thu Jun 11 15:14:37 CEST 2009 Daniel Veillard <veillard@redhat.com>
|
||||||
|
|
||||||
* configure.in src/libvirt_private.syms src/storage_backend_fs.c
|
* configure.in src/libvirt_private.syms src/storage_backend_fs.c
|
||||||
|
174
src/qemu_conf.c
174
src/qemu_conf.c
@ -412,54 +412,12 @@ virCapsPtr qemudCapsInit(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int qemudComputeCmdFlags(const char *help,
|
||||||
int qemudExtractVersionInfo(const char *qemu,
|
unsigned int version,
|
||||||
unsigned int *retversion,
|
unsigned int kvm_version)
|
||||||
unsigned int *retflags) {
|
{
|
||||||
const char *const qemuarg[] = { qemu, "-help", NULL };
|
|
||||||
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
pid_t child;
|
|
||||||
int newstdout = -1;
|
|
||||||
int ret = -1, status;
|
|
||||||
unsigned int major, minor, micro;
|
|
||||||
unsigned int version, kvm_version;
|
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
|
|
||||||
if (retflags)
|
|
||||||
*retflags = 0;
|
|
||||||
if (retversion)
|
|
||||||
*retversion = 0;
|
|
||||||
|
|
||||||
if (virExec(NULL, qemuarg, qemuenv, NULL,
|
|
||||||
&child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
char *help = NULL;
|
|
||||||
enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
|
|
||||||
int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
|
|
||||||
if (len < 0) {
|
|
||||||
virReportSystemError(NULL, errno, "%s",
|
|
||||||
_("Unable to read QEMU help output"));
|
|
||||||
goto cleanup2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sscanf(help, "QEMU PC emulator version %u.%u.%u (kvm-%u)",
|
|
||||||
&major, &minor, µ, &kvm_version) != 4)
|
|
||||||
kvm_version = 0;
|
|
||||||
|
|
||||||
if (!kvm_version &&
|
|
||||||
sscanf(help, "QEMU PC emulator version %u.%u.%u",
|
|
||||||
&major, &minor, µ) != 3) {
|
|
||||||
char *eol = strchr(help, '\n');
|
|
||||||
if (eol) *eol = '\0';
|
|
||||||
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
_("cannot parse QEMU version number in '%s'"),
|
|
||||||
help);
|
|
||||||
goto cleanup2;
|
|
||||||
}
|
|
||||||
|
|
||||||
version = (major * 1000 * 1000) + (minor * 1000) + micro;
|
|
||||||
|
|
||||||
if (strstr(help, "-no-kqemu"))
|
if (strstr(help, "-no-kqemu"))
|
||||||
flags |= QEMUD_CMD_FLAG_KQEMU;
|
flags |= QEMUD_CMD_FLAG_KQEMU;
|
||||||
if (strstr(help, "-no-kvm"))
|
if (strstr(help, "-no-kvm"))
|
||||||
@ -505,6 +463,125 @@ int qemudExtractVersionInfo(const char *qemu,
|
|||||||
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
|
flags |= QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We parse the output of 'qemu -help' to get the QEMU
|
||||||
|
* version number. The first bit is easy, just parse
|
||||||
|
* 'QEMU PC emulator version x.y.z'.
|
||||||
|
*
|
||||||
|
* With qemu-kvm, however, that is followed by a kvm-XX
|
||||||
|
* string in parenthesis.
|
||||||
|
*/
|
||||||
|
#define QEMU_VERSION_STR "QEMU PC emulator version"
|
||||||
|
#define KVM_VER_PREFIX "(kvm-"
|
||||||
|
|
||||||
|
#define SKIP_BLANKS(p) do { while ((*(p) == ' ') || (*(p) == '\t')) (p)++; } while (0)
|
||||||
|
|
||||||
|
static int qemudParseHelpStr(const char *help,
|
||||||
|
unsigned int *flags,
|
||||||
|
unsigned int *version,
|
||||||
|
unsigned int *kvm_version)
|
||||||
|
{
|
||||||
|
unsigned major, minor, micro;
|
||||||
|
const char *p = help;
|
||||||
|
|
||||||
|
*flags = *version = *kvm_version = 0;
|
||||||
|
|
||||||
|
if (!STRPREFIX(p, QEMU_VERSION_STR))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
p += strlen(QEMU_VERSION_STR);
|
||||||
|
|
||||||
|
SKIP_BLANKS(p);
|
||||||
|
|
||||||
|
major = virParseNumber(&p);
|
||||||
|
if (major == -1 || *p != '.')
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
++p;
|
||||||
|
|
||||||
|
minor = virParseNumber(&p);
|
||||||
|
if (major == -1 || *p != '.')
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
++p;
|
||||||
|
|
||||||
|
micro = virParseNumber(&p);
|
||||||
|
if (major == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SKIP_BLANKS(p);
|
||||||
|
|
||||||
|
if (STRPREFIX(p, KVM_VER_PREFIX)) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
p += strlen(KVM_VER_PREFIX);
|
||||||
|
|
||||||
|
ret = virParseNumber(&p);
|
||||||
|
if (ret == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
*kvm_version = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*version = (major * 1000 * 1000) + (minor * 1000) + micro;
|
||||||
|
|
||||||
|
*flags = qemudComputeCmdFlags(help, *version, *kvm_version);
|
||||||
|
|
||||||
|
qemudDebug("Version %u.%u.%u, cooked version %u, flags %u",
|
||||||
|
major, minor, micro, *version, *flags);
|
||||||
|
if (*kvm_version)
|
||||||
|
qemudDebug("KVM version %u detected", *kvm_version);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
p = strchr(help, '\n');
|
||||||
|
if (p)
|
||||||
|
p = strndup(help, p - help);
|
||||||
|
|
||||||
|
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("cannot parse QEMU version number in '%s'"),
|
||||||
|
p ? p : help);
|
||||||
|
|
||||||
|
VIR_FREE(p);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemudExtractVersionInfo(const char *qemu,
|
||||||
|
unsigned int *retversion,
|
||||||
|
unsigned int *retflags) {
|
||||||
|
const char *const qemuarg[] = { qemu, "-help", NULL };
|
||||||
|
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
||||||
|
pid_t child;
|
||||||
|
int newstdout = -1;
|
||||||
|
int ret = -1, status;
|
||||||
|
unsigned int version, kvm_version;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
|
if (retflags)
|
||||||
|
*retflags = 0;
|
||||||
|
if (retversion)
|
||||||
|
*retversion = 0;
|
||||||
|
|
||||||
|
if (virExec(NULL, qemuarg, qemuenv, NULL,
|
||||||
|
&child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
char *help = NULL;
|
||||||
|
enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
|
||||||
|
int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
|
||||||
|
if (len < 0) {
|
||||||
|
virReportSystemError(NULL, errno, "%s",
|
||||||
|
_("Unable to read QEMU help output"));
|
||||||
|
goto cleanup2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemudParseHelpStr(help, &version, &kvm_version, &flags) == -1)
|
||||||
|
goto cleanup2;
|
||||||
|
|
||||||
if (retversion)
|
if (retversion)
|
||||||
*retversion = version;
|
*retversion = version;
|
||||||
if (retflags)
|
if (retflags)
|
||||||
@ -512,11 +589,6 @@ int qemudExtractVersionInfo(const char *qemu,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
qemudDebug("Version %d %d %d Cooked version: %d, with flags ? %d",
|
|
||||||
major, minor, micro, version, flags);
|
|
||||||
if (kvm_version)
|
|
||||||
qemudDebug("KVM version %d detected", kvm_version);
|
|
||||||
|
|
||||||
cleanup2:
|
cleanup2:
|
||||||
VIR_FREE(help);
|
VIR_FREE(help);
|
||||||
if (close(newstdout) < 0)
|
if (close(newstdout) < 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user