/** * virQEMUDriverGetCapabilities: * * Get a reference to the virCapsPtr instance for the * driver. If @refresh is true, the capabilities will be * rebuilt first * * The caller must release the reference with virObjetUnref * * Returns: a reference to a virCapsPtr instance or NULL */ virCapsPtr virQEMUDriverGetCapabilities(virQEMUDriverPtr driver, bool refresh) { virCapsPtr ret = NULL; if (refresh) { virCapsPtr caps = NULL; if ((caps = virQEMUDriverCreateCapabilities(driver)) == NULL) return NULL; qemuDriverLock(driver); virObjectUnref(driver->caps); driver->caps = caps; } else { qemuDriverLock(driver); } if (driver->caps->nguests == 0 && !refresh) { VIR_DEBUG("Capabilities didn't detect any guests. Forcing a " "refresh."); qemuDriverUnlock(driver); return virQEMUDriverGetCapabilities(driver, true); } ret = virObjectRef(driver->caps); qemuDriverUnlock(driver); return ret; }
int qemuSetupCgroup(virQEMUDriverPtr driver, virDomainObjPtr vm, virBitmapPtr nodemask) { qemuDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps = NULL; int ret = -1; if (!vm->pid) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot setup cgroups until process is started")); return -1; } if (qemuInitCgroup(driver, vm) < 0) return -1; if (!priv->cgroup) return 0; if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; if (qemuSetupDevicesCgroup(driver, vm) < 0) goto cleanup; if (qemuSetupBlkioCgroup(vm) < 0) goto cleanup; if (qemuSetupMemoryCgroup(vm) < 0) goto cleanup; if (qemuSetupCpuCgroup(vm) < 0) goto cleanup; if (qemuSetupCpusetCgroup(vm, nodemask, caps) < 0) goto cleanup; ret = 0; cleanup: virObjectUnref(caps); return ret; }
static int testQemuHotplug(const void *data) { int ret = -1; struct qemuHotplugTestData *test = (struct qemuHotplugTestData *) data; char *domain_filename = NULL; char *device_filename = NULL; char *result_filename = NULL; char *domain_xml = NULL; char *device_xml = NULL; char *result_xml = NULL; const char *const *tmp; bool fail = test->fail; bool keep = test->keep; unsigned int device_parse_flags = 0; virDomainObjPtr vm = NULL; virDomainDeviceDefPtr dev = NULL; virCapsPtr caps = NULL; qemuMonitorTestPtr test_mon = NULL; qemuDomainObjPrivatePtr priv = NULL; if (virAsprintf(&domain_filename, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", abs_srcdir, test->domain_filename) < 0 || virAsprintf(&device_filename, "%s/qemuhotplugtestdata/qemuhotplug-%s.xml", abs_srcdir, test->device_filename) < 0 || virAsprintf(&result_filename, "%s/qemuhotplugtestdata/qemuhotplug-%s+%s.xml", abs_srcdir, test->domain_filename, test->device_filename) < 0) goto cleanup; if (virtTestLoadFile(domain_filename, &domain_xml) < 0 || virtTestLoadFile(device_filename, &device_xml) < 0) goto cleanup; if (test->action != UPDATE && virtTestLoadFile(result_filename, &result_xml) < 0) goto cleanup; if (!(caps = virQEMUDriverGetCapabilities(&driver, false))) goto cleanup; if (test->vm) { vm = test->vm; } else { if (qemuHotplugCreateObjects(driver.xmlopt, &vm, domain_xml, test->deviceDeletedEvent, test->domain_filename) < 0) goto cleanup; } if (test->action == ATTACH) device_parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE; if (!(dev = virDomainDeviceDefParse(device_xml, vm->def, caps, driver.xmlopt, device_parse_flags))) goto cleanup; /* Now is the best time to feed the spoofed monitor with predefined * replies. */ if (!(test_mon = qemuMonitorTestNew(true, driver.xmlopt, vm, &driver, NULL))) goto cleanup; tmp = test->mon; while (tmp && *tmp) { const char *command_name; const char *response; if (!(command_name = *tmp++) || !(response = *tmp++)) break; if (qemuMonitorTestAddItem(test_mon, command_name, response) < 0) goto cleanup; } priv = vm->privateData; priv->mon = qemuMonitorTestGetMonitor(test_mon); priv->monJSON = true; /* XXX We need to unlock the monitor here, as * qemuDomainObjEnterMonitorInternal (called from qemuDomainChangeGraphics) * tries to lock it again */ virObjectUnlock(priv->mon); switch (test->action) { case ATTACH: ret = testQemuHotplugAttach(vm, dev); if (ret == 0) { /* vm->def stolen dev->data.* so we just need to free the dev * envelope */ VIR_FREE(dev); } if (ret == 0 || fail) ret = testQemuHotplugCheckResult(vm, result_xml, result_filename, fail); break; case DETACH: ret = testQemuHotplugDetach(vm, dev); if (ret == 0 || fail) ret = testQemuHotplugCheckResult(vm, domain_xml, domain_filename, fail); break; case UPDATE: ret = testQemuHotplugUpdate(vm, dev); } cleanup: VIR_FREE(domain_filename); VIR_FREE(device_filename); VIR_FREE(result_filename); VIR_FREE(domain_xml); VIR_FREE(device_xml); VIR_FREE(result_xml); /* don't dispose test monitor with VM */ if (priv) priv->mon = NULL; if (keep) { test->vm = vm; } else { virObjectUnref(vm); test->vm = NULL; } virDomainDeviceDefFree(dev); virObjectUnref(caps); qemuMonitorTestFree(test_mon); return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1; }
static int qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig, virQEMUDriverPtr driver, xmlDocPtr doc, xmlXPathContextPtr ctxt, unsigned int flags) { char uuidstr[VIR_UUID_STRING_BUFLEN]; char *tmp = NULL; xmlNodePtr *nodes = NULL; size_t i; int n; virCapsPtr caps = NULL; if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto error; /* We don't store the uuid, name, hostname, or hostuuid * values. We just compare them to local data to do some * sanity checking on migration operation */ /* Extract domain name */ if (!(tmp = virXPathString("string(./name[1])", ctxt))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing name element in migration data")); goto error; } if (STRNEQ(tmp, mig->name)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Incoming cookie data had unexpected name %s vs %s"), tmp, mig->name); goto error; } VIR_FREE(tmp); /* Extract domain uuid */ tmp = virXPathString("string(./uuid[1])", ctxt); if (!tmp) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing uuid element in migration data")); goto error; } virUUIDFormat(mig->uuid, uuidstr); if (STRNEQ(tmp, uuidstr)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Incoming cookie data had unexpected UUID %s vs %s"), tmp, uuidstr); goto error; } VIR_FREE(tmp); /* Check & forbid "localhost" migration */ if (!(mig->remoteHostname = virXPathString("string(./hostname[1])", ctxt))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing hostname element in migration data")); goto error; } if (STREQ(mig->remoteHostname, mig->localHostname)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempt to migrate guest to the same host %s"), mig->remoteHostname); goto error; } if (!(tmp = virXPathString("string(./hostuuid[1])", ctxt))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing hostuuid element in migration data")); goto error; } if (virUUIDParse(tmp, mig->remoteHostuuid) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed hostuuid element in migration data")); goto error; } if (memcmp(mig->remoteHostuuid, mig->localHostuuid, VIR_UUID_BUFLEN) == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempt to migrate guest to the same host %s"), tmp); goto error; } VIR_FREE(tmp); /* Check to ensure all mandatory features from XML are also * present in 'flags' */ if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) < 0) goto error; for (i = 0; i < n; i++) { int val; char *str = virXMLPropString(nodes[i], "name"); if (!str) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing feature name")); goto error; } if ((val = qemuMigrationCookieFlagTypeFromString(str)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown migration cookie feature %s"), str); VIR_FREE(str); goto error; } if ((flags & (1 << val)) == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unsupported migration cookie feature %s"), str); VIR_FREE(str); goto error; } VIR_FREE(str); } VIR_FREE(nodes); if ((flags & QEMU_MIGRATION_COOKIE_GRAPHICS) && virXPathBoolean("count(./graphics) > 0", ctxt) && (!(mig->graphics = qemuMigrationCookieGraphicsXMLParse(ctxt)))) goto error; if ((flags & QEMU_MIGRATION_COOKIE_LOCKSTATE) && virXPathBoolean("count(./lockstate) > 0", ctxt)) { mig->lockDriver = virXPathString("string(./lockstate[1]/@driver)", ctxt); if (!mig->lockDriver) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Missing lock driver name in migration cookie")); goto error; } mig->lockState = virXPathString("string(./lockstate[1]/leases[1])", ctxt); if (mig->lockState && STREQ(mig->lockState, "")) VIR_FREE(mig->lockState); } if ((flags & QEMU_MIGRATION_COOKIE_PERSISTENT) && virXPathBoolean("count(./domain) > 0", ctxt)) { if ((n = virXPathNodeSet("./domain", ctxt, &nodes)) > 1) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Too many domain elements in " "migration cookie: %d"), n); goto error; } mig->persistent = virDomainDefParseNode(doc, nodes[0], caps, driver->xmlopt, NULL, VIR_DOMAIN_DEF_PARSE_INACTIVE | VIR_DOMAIN_DEF_PARSE_ABI_UPDATE_MIGRATION | VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE); if (!mig->persistent) { /* virDomainDefParseNode already reported * an error for us */ goto error; } VIR_FREE(nodes); } if ((flags & QEMU_MIGRATION_COOKIE_NETWORK) && virXPathBoolean("count(./network) > 0", ctxt) && (!(mig->network = qemuMigrationCookieNetworkXMLParse(ctxt)))) goto error; if (flags & QEMU_MIGRATION_COOKIE_NBD && virXPathBoolean("boolean(./nbd)", ctxt) && (!(mig->nbd = qemuMigrationCookieNBDXMLParse(ctxt)))) goto error; if (flags & QEMU_MIGRATION_COOKIE_STATS && virXPathBoolean("boolean(./statistics)", ctxt) && (!(mig->jobInfo = qemuMigrationCookieStatisticsXMLParse(ctxt)))) goto error; if (flags & QEMU_MIGRATION_COOKIE_CPU && virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &mig->cpu) < 0) goto error; if (flags & QEMU_MIGRATION_COOKIE_ALLOW_REBOOT && qemuDomainObjPrivateXMLParseAllowReboot(ctxt, &mig->allowReboot) < 0) goto error; virObjectUnref(caps); return 0; error: VIR_FREE(tmp); VIR_FREE(nodes); virObjectUnref(caps); return -1; }