1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

Remove probing of flags when launching QEMU guests

Remove all use of the existing APIs for querying QEMU
capability flags. Instead obtain a qemuCapsPtr object
from the global cache. This avoids the execution of
'qemu -help' (and related commands) when launching new
guests.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2012-08-22 15:39:54 +01:00
parent 494e2f5cc2
commit 15ee6614f7
8 changed files with 81 additions and 202 deletions

View File

@ -1471,79 +1471,6 @@ qemuCapsParseDeviceStr(const char *str, qemuCapsPtr caps)
return 0;
}
int qemuCapsExtractVersionInfo(const char *qemu,
const char *arch,
bool check_yajl,
unsigned int *retversion,
qemuCapsPtr *retcaps)
{
int ret = -1;
unsigned int version, is_kvm, kvm_version;
qemuCapsPtr caps = NULL;
char *help = NULL;
virCommandPtr cmd;
if (retcaps)
*retcaps = NULL;
if (retversion)
*retversion = 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 it's hard to feed back a useful error.
*/
if (!virFileIsExecutable(qemu)) {
virReportSystemError(errno, _("Cannot find QEMU binary %s"), qemu);
return -1;
}
cmd = qemuCapsProbeCommand(qemu, NULL);
virCommandAddArgList(cmd, "-help", NULL);
virCommandSetOutputBuffer(cmd, &help);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
if (!(caps = qemuCapsNew()) ||
qemuCapsParseHelpStr(qemu, help, caps,
&version, &is_kvm, &kvm_version,
check_yajl) == -1)
goto cleanup;
/* Currently only x86_64 and i686 support PCI-multibus. */
if (STREQLEN(arch, "x86_64", 6) ||
STREQLEN(arch, "i686", 4)) {
qemuCapsSet(caps, QEMU_CAPS_PCI_MULTIBUS);
}
/* S390 and probably other archs do not support no-acpi -
maybe the qemu option parsing should be re-thought. */
if (STRPREFIX(arch, "s390"))
qemuCapsClear(caps, QEMU_CAPS_NO_ACPI);
/* qemuCapsExtractDeviceStr will only set additional caps if qemu
* understands the 0.13.0+ notion of "-device driver,". */
if (qemuCapsGet(caps, QEMU_CAPS_DEVICE) &&
strstr(help, "-device driver,?") &&
qemuCapsExtractDeviceStr(qemu, caps) < 0)
goto cleanup;
if (retversion)
*retversion = version;
if (retcaps) {
*retcaps = caps;
caps = NULL;
}
ret = 0;
cleanup:
VIR_FREE(help);
virCommandFree(cmd);
virObjectUnref(caps);
return ret;
}
static void
uname_normalize (struct utsname *ut)
@ -1559,12 +1486,13 @@ uname_normalize (struct utsname *ut)
ut->machine[1] = '6';
}
int qemuCapsExtractVersion(virCapsPtr caps,
unsigned int *version)
int qemuCapsGetDefaultVersion(virCapsPtr caps,
qemuCapsCachePtr capsCache,
unsigned int *version)
{
const char *binary;
struct stat sb;
struct utsname ut;
qemuCapsPtr qemucaps;
if (*version > 0)
return 0;
@ -1579,17 +1507,11 @@ int qemuCapsExtractVersion(virCapsPtr caps,
return -1;
}
if (stat(binary, &sb) < 0) {
virReportSystemError(errno,
_("Cannot find QEMU binary %s"), binary);
if (!(qemucaps = qemuCapsCacheLookup(capsCache, binary)))
return -1;
}
if (qemuCapsExtractVersionInfo(binary, ut.machine, false,
version, NULL) < 0) {
return -1;
}
*version = qemuCapsGetVersion(qemucaps);
virObjectUnref(qemucaps);
return 0;
}

View File

@ -27,6 +27,7 @@
# include "virobject.h"
# include "capabilities.h"
# include "command.h"
# include "virobject.h"
/* Internal flags to keep track of qemu command line capabilities */
enum qemuCapsFlags {
@ -211,13 +212,9 @@ int qemuCapsProbeCPUModels(const char *qemu,
size_t *count,
const char ***cpus);
int qemuCapsExtractVersion(virCapsPtr caps,
unsigned int *version);
int qemuCapsExtractVersionInfo(const char *qemu,
const char *arch,
bool check_yajl,
unsigned int *version,
qemuCapsPtr *retcaps);
int qemuCapsGetDefaultVersion(virCapsPtr caps,
qemuCapsCachePtr capsCache,
unsigned int *version);
int qemuCapsParseHelpStr(const char *qemu,
const char *str,

View File

@ -810,33 +810,13 @@ qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def,
}
static int
static void
qemuDomainAssignS390Addresses(virDomainDefPtr def, qemuCapsPtr caps)
{
int ret = -1;
qemuCapsPtr localCaps = NULL;
if (!caps) {
/* need to get information from real environment */
if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch,
false, NULL,
&localCaps) < 0)
goto cleanup;
caps = localCaps;
}
if (qemuCapsGet(caps, QEMU_CAPS_VIRTIO_S390)) {
/* deal with legacy virtio-s390 */
/* deal with legacy virtio-s390 */
if (qemuCapsGet(caps, QEMU_CAPS_VIRTIO_S390))
qemuDomainPrimeS390VirtioDevices(
def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390);
}
ret = 0;
cleanup:
virObjectUnref(localCaps);
return ret;
}
static int
@ -863,7 +843,7 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
unsigned long long default_reg)
{
bool user_reg;
int rc;
int ret;
if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO)
return 0;
@ -875,8 +855,8 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
info->addr.spaprvio.has_reg = true;
}
rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
while (rc != 0) {
ret = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
while (ret != 0) {
if (user_reg) {
virReportError(VIR_ERR_XML_ERROR,
_("spapr-vio address %#llx already in use"),
@ -886,7 +866,7 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
/* We assigned the reg, so try a new value */
info->addr.spaprvio.reg += 0x1000;
rc = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
ret = virDomainDeviceInfoIterate(def, qemuSpaprVIOFindByReg, info);
}
return 0;
@ -895,45 +875,32 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
qemuCapsPtr caps)
{
int i, rc = -1;
int i, ret = -1;
int model;
qemuCapsPtr localCaps = NULL;
/* Default values match QEMU. See spapr_(llan|vscsi|vty).c */
if (!caps) {
/* need to get information from real environment */
if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch,
false, NULL,
&localCaps) < 0)
goto cleanup;
caps = localCaps;
}
for (i = 0 ; i < def->nnets; i++) {
if (def->nets[i]->model &&
STREQ(def->nets[i]->model, "spapr-vlan"))
def->nets[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
rc = qemuAssignSpaprVIOAddress(def, &def->nets[i]->info,
0x1000ul);
if (rc)
if (qemuAssignSpaprVIOAddress(def, &def->nets[i]->info,
0x1000ul) < 0)
goto cleanup;
}
for (i = 0 ; i < def->ncontrollers; i++) {
model = def->controllers[i]->model;
if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
rc = qemuSetScsiControllerModel(def, caps, &model);
if (rc)
if (qemuSetScsiControllerModel(def, caps, &model) < 0)
goto cleanup;
}
if (model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI &&
def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
def->controllers[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
rc = qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info,
0x2000ul);
if (rc)
if (qemuAssignSpaprVIOAddress(def, &def->controllers[i]->info,
0x2000ul) < 0)
goto cleanup;
}
@ -943,19 +910,17 @@ int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
STREQ(def->os.arch, "ppc64") &&
STREQ(def->os.machine, "pseries"))
def->serials[i]->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO;
rc = qemuAssignSpaprVIOAddress(def, &def->serials[i]->info,
0x30000000ul);
if (rc)
if (qemuAssignSpaprVIOAddress(def, &def->serials[i]->info,
0x30000000ul) < 0)
goto cleanup;
}
/* No other devices are currently supported on spapr-vio */
rc = 0;
ret = 0;
cleanup:
virObjectUnref(localCaps);
return rc;
return ret;
}
#define QEMU_PCI_ADDRESS_LAST_SLOT 31
@ -1070,20 +1035,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
virDomainObjPtr obj)
{
int ret = -1;
qemuCapsPtr localCaps = NULL;
qemuDomainPCIAddressSetPtr addrs = NULL;
qemuDomainObjPrivatePtr priv = NULL;
if (!caps) {
/* need to get information from real environment */
if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch,
false,
NULL,
&localCaps) < 0)
goto cleanup;
caps = localCaps;
}
if (qemuCapsGet(caps, QEMU_CAPS_DEVICE)) {
if (!(addrs = qemuDomainPCIAddressSetCreate(def)))
goto cleanup;
@ -1108,7 +1062,6 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
ret = 0;
cleanup:
virObjectUnref(localCaps);
qemuDomainPCIAddressSetFree(addrs);
return ret;
@ -1124,9 +1077,7 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
if (rc)
return rc;
rc = qemuDomainAssignS390Addresses(def, caps);
if (rc)
return rc;
qemuDomainAssignS390Addresses(def, caps);
return qemuDomainAssignPCIAddresses(def, caps, obj);
}

View File

@ -188,7 +188,8 @@ virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps,
int qemuDomainAssignAddresses(virDomainDefPtr def,
qemuCapsPtr caps,
virDomainObjPtr);
virDomainObjPtr obj)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
qemuCapsPtr caps);

View File

@ -1475,7 +1475,9 @@ static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
int ret = -1;
qemuDriverLock(driver);
if (qemuCapsExtractVersion(driver->caps, &driver->qemuVersion) < 0)
if (qemuCapsGetDefaultVersion(driver->caps,
driver->capsCache,
&driver->qemuVersion) < 0)
goto cleanup;
*version = driver->qemuVersion;
@ -1517,6 +1519,7 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
virDomainEventPtr event = NULL;
virDomainEventPtr event2 = NULL;
unsigned int start_flags = VIR_QEMU_PROCESS_START_COLD;
qemuCapsPtr caps = NULL;
virCheckFlags(VIR_DOMAIN_START_PAUSED |
VIR_DOMAIN_START_AUTODESTROY, NULL);
@ -1538,10 +1541,13 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
goto cleanup;
if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator)))
goto cleanup;
if (qemudCanonicalizeMachine(driver, def) < 0)
goto cleanup;
if (qemuDomainAssignAddresses(def, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(def, caps, NULL) < 0)
goto cleanup;
if (!(vm = virDomainAssignDef(driver->caps,
@ -1595,6 +1601,7 @@ cleanup:
if (event2)
qemuDomainEventQueue(driver, event2);
}
virObjectUnref(caps);
qemuDriverUnlock(driver);
return dom;
}
@ -5208,6 +5215,9 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
if (!def)
goto cleanup;
if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator)))
goto cleanup;
/* Since we're just exporting args, we can't do bridge/network/direct
* setups, since libvirt will normally create TAP/macvtap devices
* directly. We convert those configs into generic 'ethernet'
@ -5276,12 +5286,6 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
net->info.bootIndex = bootIndex;
}
if (qemuCapsExtractVersionInfo(def->emulator, def->os.arch,
false,
NULL,
&caps) < 0)
goto cleanup;
monitor_json = qemuCapsGet(caps, QEMU_CAPS_MONITOR_JSON);
if (qemuProcessPrepareMonitorChr(driver, &monConfig, def->name) < 0)
@ -5575,6 +5579,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
virDomainObjPtr vm = NULL;
virDomainPtr dom = NULL;
virDomainEventPtr event = NULL;
qemuCapsPtr caps = NULL;
int dupVM;
qemuDriverLock(driver);
@ -5589,10 +5594,13 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
goto cleanup;
if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator)))
goto cleanup;
if (qemudCanonicalizeMachine(driver, def) < 0)
goto cleanup;
if (qemuDomainAssignAddresses(def, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(def, caps, NULL) < 0)
goto cleanup;
/* We need to differentiate two cases:
@ -5655,6 +5663,7 @@ cleanup:
virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
virObjectUnref(caps);
qemuDriverUnlock(driver);
return dom;
}
@ -6073,7 +6082,8 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm,
}
static int
qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
qemuDomainAttachDeviceConfig(qemuCapsPtr caps,
virDomainDefPtr vmdef,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk;
@ -6099,7 +6109,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO)
if (virDomainDefAddImplicitControllers(vmdef) < 0)
return -1;
if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(vmdef, caps, NULL) < 0)
return -1;
break;
@ -6118,7 +6128,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
return -1;
}
dev->data.net = NULL;
if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(vmdef, caps, NULL) < 0)
return -1;
break;
@ -6134,7 +6144,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
return -1;
}
dev->data.hostdev = NULL;
if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(vmdef, caps, NULL) < 0)
return -1;
break;
@ -6166,7 +6176,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef,
return -1;
dev->data.controller = NULL;
if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(vmdef, caps, NULL) < 0)
return -1;
break;
@ -6259,7 +6269,8 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef,
}
static int
qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
qemuDomainUpdateDeviceConfig(qemuCapsPtr caps,
virDomainDefPtr vmdef,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr orig, disk;
@ -6319,7 +6330,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
vmdef->nets[pos] = net;
dev->data.net = NULL;
if (qemuDomainAssignAddresses(vmdef, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(vmdef, caps, NULL) < 0)
return -1;
break;
@ -6350,6 +6361,8 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
bool force = (flags & VIR_DOMAIN_DEVICE_MODIFY_FORCE) != 0;
int ret = -1;
unsigned int affect;
qemuCapsPtr caps = NULL;
qemuDomainObjPrivatePtr priv;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG |
@ -6367,6 +6380,7 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
priv = vm->privateData;
if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
goto cleanup;
@ -6408,6 +6422,11 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
goto endjob;
}
if (priv->caps)
caps = virObjectRef(priv->caps);
else if (!(caps = qemuCapsCacheLookup(driver->capsCache, vm->def->emulator)))
goto cleanup;
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
if (virDomainDefCompatibleDevice(vm->def, dev) < 0)
goto endjob;
@ -6418,13 +6437,13 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
goto endjob;
switch (action) {
case QEMU_DEVICE_ATTACH:
ret = qemuDomainAttachDeviceConfig(vmdef, dev);
ret = qemuDomainAttachDeviceConfig(caps, vmdef, dev);
break;
case QEMU_DEVICE_DETACH:
ret = qemuDomainDetachDeviceConfig(vmdef, dev);
break;
case QEMU_DEVICE_UPDATE:
ret = qemuDomainUpdateDeviceConfig(vmdef, dev);
ret = qemuDomainUpdateDeviceConfig(caps, vmdef, dev);
break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
@ -6484,6 +6503,7 @@ endjob:
vm = NULL;
cleanup:
virObjectUnref(caps);
virDomainDefFree(vmdef);
if (dev != dev_copy)
virDomainDeviceDefFree(dev_copy);
@ -12260,6 +12280,7 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn,
bool monJSON = false;
pid_t pid = pid_value;
char *pidfile = NULL;
qemuCapsPtr caps = NULL;
virCheckFlags(0, NULL);
@ -12289,13 +12310,16 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn,
goto cleanup;
}
if (!(caps = qemuCapsCacheLookup(driver->capsCache, def->emulator)))
goto cleanup;
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
goto cleanup;
if (qemudCanonicalizeMachine(driver, def) < 0)
goto cleanup;
if (qemuDomainAssignAddresses(def, NULL, NULL) < 0)
if (qemuDomainAssignAddresses(def, caps, NULL) < 0)
goto cleanup;
if (!(vm = virDomainAssignDef(driver->caps,
@ -12327,6 +12351,7 @@ endjob:
cleanup:
virDomainDefFree(def);
virObjectUnref(caps);
virDomainChrSourceDefFree(monConfig);
if (vm)
virDomainObjUnlock(vm);

View File

@ -3092,10 +3092,8 @@ qemuProcessReconnect(void *opaque)
* caps in the domain status, so re-query them
*/
if (!priv->caps &&
qemuCapsExtractVersionInfo(obj->def->emulator, obj->def->os.arch,
false,
NULL,
&priv->caps) < 0)
!(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache,
obj->def->emulator)))
goto error;
/* In case the domain shutdown while we were not running,
@ -3492,11 +3490,8 @@ int qemuProcessStart(virConnectPtr conn,
VIR_DEBUG("Determining emulator version");
virObjectUnref(priv->caps);
priv->caps = NULL;
if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch,
true,
NULL,
&priv->caps) < 0)
if (!(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache,
vm->def->emulator)))
goto cleanup;
if (qemuAssignDeviceAliases(vm->def, priv->caps) < 0)
@ -4206,12 +4201,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
VIR_DEBUG("Determining emulator version");
virObjectUnref(priv->caps);
priv->caps = NULL;
if (qemuCapsExtractVersionInfo(vm->def->emulator,
vm->def->os.arch,
false,
NULL,
&priv->caps) < 0)
if (!(priv->caps = qemuCapsCacheLookupCopy(driver->capsCache,
vm->def->emulator)))
goto cleanup;
VIR_DEBUG("Preparing monitor state");

View File

@ -157,10 +157,6 @@ static int testCompareXMLToArgvFiles(const char *xml,
VIR_FREE(log);
virResetLastError();
/* We do not call qemuCapsExtractVersionInfo() before calling
* qemuBuildCommandLine(), so we should set QEMU_CAPS_PCI_MULTIBUS for
* x86_64 and i686 architectures here.
*/
if (STREQLEN(vmdef->os.arch, "x86_64", 6) ||
STREQLEN(vmdef->os.arch, "i686", 4)) {
qemuCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS);

View File

@ -102,10 +102,6 @@ static int testCompareXMLToArgvFiles(const char *xml,
VIR_FREE(log);
virResetLastError();
/* We do not call qemuCapsExtractVersionInfo() before calling
* qemuBuildCommandLine(), so we should set QEMU_CAPS_PCI_MULTIBUS for
* x86_64 and i686 architectures here.
*/
if (STREQLEN(vmdef->os.arch, "x86_64", 6) ||
STREQLEN(vmdef->os.arch, "i686", 4)) {
qemuCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS);