mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
qemu: convert capabilities to use virCommand
* src/qemu/qemu_capabilities.c (qemuCapsProbeMachineTypes) (qemuCapsProbeCPUModels, qemuCapsParsePCIDeviceStrs) (qemuCapsExtractVersionInfo): Use virCommand rather than virExec.
This commit is contained in:
parent
6935a1e289
commit
221151813c
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* qemu_capabilities.c: QEMU capabilities generation
|
* qemu_capabilities.c: QEMU capabilities generation
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2007, 2009-2010 Red Hat, Inc.
|
* Copyright (C) 2006-2011 Red Hat, Inc.
|
||||||
* Copyright (C) 2006 Daniel P. Berrange
|
* Copyright (C) 2006 Daniel P. Berrange
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
@ -33,6 +33,7 @@
|
|||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
#include "domain_conf.h"
|
#include "domain_conf.h"
|
||||||
#include "qemu_conf.h"
|
#include "qemu_conf.h"
|
||||||
|
#include "command.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -167,52 +168,26 @@ qemuCapsProbeMachineTypes(const char *binary,
|
|||||||
virCapsGuestMachinePtr **machines,
|
virCapsGuestMachinePtr **machines,
|
||||||
int *nmachines)
|
int *nmachines)
|
||||||
{
|
{
|
||||||
const char *const qemuarg[] = { binary, "-M", "?", NULL };
|
|
||||||
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
char *output;
|
char *output;
|
||||||
enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 };
|
int ret = -1;
|
||||||
pid_t child;
|
virCommandPtr cmd;
|
||||||
int newstdout = -1, len;
|
|
||||||
int ret = -1, status;
|
|
||||||
|
|
||||||
if (virExec(qemuarg, qemuenv, NULL,
|
cmd = virCommandNewArgList(binary, "-M", "?", NULL);
|
||||||
&child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
virCommandAddEnvPassCommon(cmd);
|
||||||
return -1;
|
virCommandSetOutputBuffer(cmd, &output);
|
||||||
|
virCommandClearCaps(cmd);
|
||||||
|
|
||||||
len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, &output);
|
if (virCommandRun(cmd, NULL) < 0)
|
||||||
if (len < 0) {
|
|
||||||
virReportSystemError(errno, "%s",
|
|
||||||
_("Unable to read 'qemu -M ?' output"));
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0)
|
if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0)
|
||||||
goto cleanup2;
|
goto cleanup;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup2:
|
|
||||||
VIR_FREE(output);
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (VIR_CLOSE(newstdout) < 0)
|
VIR_FREE(output);
|
||||||
ret = -1;
|
virCommandFree(cmd);
|
||||||
|
|
||||||
rewait:
|
|
||||||
if (waitpid(child, &status, 0) != child) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto rewait;
|
|
||||||
|
|
||||||
VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
|
||||||
WEXITSTATUS(status), (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(status) != 0) {
|
|
||||||
VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
|
||||||
WEXITSTATUS(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -396,21 +371,10 @@ qemuCapsProbeCPUModels(const char *qemu,
|
|||||||
unsigned int *count,
|
unsigned int *count,
|
||||||
const char ***cpus)
|
const char ***cpus)
|
||||||
{
|
{
|
||||||
const char *const qemuarg[] = {
|
|
||||||
qemu,
|
|
||||||
"-cpu", "?",
|
|
||||||
(qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG) ? "-nodefconfig" : NULL,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
enum { MAX_MACHINES_OUTPUT_SIZE = 1024*4 };
|
|
||||||
char *output = NULL;
|
char *output = NULL;
|
||||||
int newstdout = -1;
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
pid_t child;
|
|
||||||
int status;
|
|
||||||
int len;
|
|
||||||
qemuCapsParseCPUModels parse;
|
qemuCapsParseCPUModels parse;
|
||||||
|
virCommandPtr cmd;
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
*count = 0;
|
*count = 0;
|
||||||
@ -424,16 +388,15 @@ qemuCapsProbeCPUModels(const char *qemu,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virExec(qemuarg, qemuenv, NULL,
|
cmd = virCommandNewArgList(qemu, "-cpu", "?", NULL);
|
||||||
&child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
if (qemuCmdFlags & QEMUD_CMD_FLAG_NODEFCONFIG)
|
||||||
return -1;
|
virCommandAddArg(cmd, "-nodefconfig");
|
||||||
|
virCommandAddEnvPassCommon(cmd);
|
||||||
|
virCommandSetOutputBuffer(cmd, &output);
|
||||||
|
virCommandClearCaps(cmd);
|
||||||
|
|
||||||
len = virFileReadLimFD(newstdout, MAX_MACHINES_OUTPUT_SIZE, &output);
|
if (virCommandRun(cmd, NULL) < 0)
|
||||||
if (len < 0) {
|
|
||||||
virReportSystemError(errno, "%s",
|
|
||||||
_("Unable to read QEMU supported CPU models"));
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (parse(output, count, cpus) < 0) {
|
if (parse(output, count, cpus) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -444,25 +407,7 @@ qemuCapsProbeCPUModels(const char *qemu,
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(output);
|
VIR_FREE(output);
|
||||||
if (VIR_CLOSE(newstdout) < 0)
|
virCommandFree(cmd);
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
rewait:
|
|
||||||
if (waitpid(child, &status, 0) != child) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto rewait;
|
|
||||||
|
|
||||||
VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
|
||||||
WEXITSTATUS(status), (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(status) != 0) {
|
|
||||||
VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
|
||||||
WEXITSTATUS(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1091,57 +1036,35 @@ static void
|
|||||||
qemuCapsParsePCIDeviceStrs(const char *qemu,
|
qemuCapsParsePCIDeviceStrs(const char *qemu,
|
||||||
unsigned long long *flags)
|
unsigned long long *flags)
|
||||||
{
|
{
|
||||||
const char *const qemuarg[] = { qemu, "-device", "pci-assign,?", NULL };
|
|
||||||
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
pid_t child;
|
|
||||||
int status;
|
|
||||||
int newstderr = -1;
|
|
||||||
|
|
||||||
if (virExec(qemuarg, qemuenv, NULL,
|
|
||||||
&child, -1, NULL, &newstderr, VIR_EXEC_CLEAR_CAPS) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char *pciassign = NULL;
|
char *pciassign = NULL;
|
||||||
enum { MAX_PCI_OUTPUT_SIZE = 1024*4 };
|
virCommandPtr cmd;
|
||||||
int len = virFileReadLimFD(newstderr, MAX_PCI_OUTPUT_SIZE, &pciassign);
|
|
||||||
if (len < 0) {
|
cmd = virCommandNewArgList(qemu, "-device", "pci-assign,?", NULL);
|
||||||
virReportSystemError(errno,
|
virCommandAddEnvPassCommon(cmd);
|
||||||
_("Unable to read %s pci-assign device output"),
|
/* qemu -help goes to stdout, but qemu -device ? goes to stderr. */
|
||||||
qemu);
|
virCommandSetErrorBuffer(cmd, &pciassign);
|
||||||
|
virCommandClearCaps(cmd);
|
||||||
|
|
||||||
|
if (virCommandRun(cmd, NULL) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (strstr(pciassign, "pci-assign.configfd"))
|
if (strstr(pciassign, "pci-assign.configfd"))
|
||||||
*flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD;
|
*flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_FREE(pciassign);
|
VIR_FREE(pciassign);
|
||||||
VIR_FORCE_CLOSE(newstderr);
|
virCommandFree(cmd);
|
||||||
rewait:
|
|
||||||
if (waitpid(child, &status, 0) != child) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto rewait;
|
|
||||||
|
|
||||||
VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
|
||||||
WEXITSTATUS(status), (unsigned long)child);
|
|
||||||
}
|
|
||||||
if (WEXITSTATUS(status) != 0) {
|
|
||||||
VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
|
||||||
WEXITSTATUS(status));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemuCapsExtractVersionInfo(const char *qemu,
|
int qemuCapsExtractVersionInfo(const char *qemu,
|
||||||
unsigned int *retversion,
|
unsigned int *retversion,
|
||||||
unsigned long long *retflags)
|
unsigned long long *retflags)
|
||||||
{
|
{
|
||||||
const char *const qemuarg[] = { qemu, "-help", NULL };
|
int ret = -1;
|
||||||
const char *const qemuenv[] = { "LC_ALL=C", NULL };
|
|
||||||
pid_t child;
|
|
||||||
int newstdout = -1;
|
|
||||||
int ret = -1, status;
|
|
||||||
unsigned int version, is_kvm, kvm_version;
|
unsigned int version, is_kvm, kvm_version;
|
||||||
unsigned long long flags = 0;
|
unsigned long long flags = 0;
|
||||||
|
char *help = NULL;
|
||||||
|
virCommandPtr cmd;
|
||||||
|
|
||||||
if (retflags)
|
if (retflags)
|
||||||
*retflags = 0;
|
*retflags = 0;
|
||||||
@ -1157,22 +1080,17 @@ int qemuCapsExtractVersionInfo(const char *qemu,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virExec(qemuarg, qemuenv, NULL,
|
cmd = virCommandNewArgList(qemu, "-help", NULL);
|
||||||
&child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
|
virCommandAddEnvPassCommon(cmd);
|
||||||
return -1;
|
virCommandSetOutputBuffer(cmd, &help);
|
||||||
|
virCommandClearCaps(cmd);
|
||||||
|
|
||||||
char *help = NULL;
|
if (virCommandRun(cmd, NULL) < 0)
|
||||||
enum { MAX_HELP_OUTPUT_SIZE = 1024*64 };
|
goto cleanup;
|
||||||
int len = virFileReadLimFD(newstdout, MAX_HELP_OUTPUT_SIZE, &help);
|
|
||||||
if (len < 0) {
|
|
||||||
virReportSystemError(errno,
|
|
||||||
_("Unable to read %s help output"), qemu);
|
|
||||||
goto cleanup2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qemuCapsParseHelpStr(qemu, help, &flags,
|
if (qemuCapsParseHelpStr(qemu, help, &flags,
|
||||||
&version, &is_kvm, &kvm_version) == -1)
|
&version, &is_kvm, &kvm_version) == -1)
|
||||||
goto cleanup2;
|
goto cleanup;
|
||||||
|
|
||||||
if (flags & QEMUD_CMD_FLAG_DEVICE)
|
if (flags & QEMUD_CMD_FLAG_DEVICE)
|
||||||
qemuCapsParsePCIDeviceStrs(qemu, &flags);
|
qemuCapsParsePCIDeviceStrs(qemu, &flags);
|
||||||
@ -1184,27 +1102,9 @@ int qemuCapsExtractVersionInfo(const char *qemu,
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup2:
|
cleanup:
|
||||||
VIR_FREE(help);
|
VIR_FREE(help);
|
||||||
if (VIR_CLOSE(newstdout) < 0)
|
virCommandFree(cmd);
|
||||||
ret = -1;
|
|
||||||
|
|
||||||
rewait:
|
|
||||||
if (waitpid(child, &status, 0) != child) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
goto rewait;
|
|
||||||
|
|
||||||
VIR_ERROR(_("Unexpected exit status from qemu %d pid %lu"),
|
|
||||||
WEXITSTATUS(status), (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(status) != 0) {
|
|
||||||
VIR_WARN("Unexpected exit status '%d', qemu probably failed",
|
|
||||||
WEXITSTATUS(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user