char * virDomainCapsFormat(virDomainCapsPtr const caps) { virBuffer buf = VIR_BUFFER_INITIALIZER; const char *virttype_str = virDomainVirtTypeToString(caps->virttype); const char *arch_str = virArchToString(caps->arch); virBufferAddLit(&buf, "<domainCapabilities>\n"); virBufferAdjustIndent(&buf, 2); virBufferEscapeString(&buf, "<path>%s</path>\n", caps->path); virBufferAsprintf(&buf, "<domain>%s</domain>\n", virttype_str); if (caps->machine) virBufferAsprintf(&buf, "<machine>%s</machine>\n", caps->machine); virBufferAsprintf(&buf, "<arch>%s</arch>\n", arch_str); if (caps->maxvcpus) virBufferAsprintf(&buf, "<vcpu max='%d'/>\n", caps->maxvcpus); FORMAT_SINGLE("iothreads", caps->iothreads); virDomainCapsOSFormat(&buf, &caps->os); virDomainCapsCPUFormat(&buf, &caps->cpu); virBufferAddLit(&buf, "<devices>\n"); virBufferAdjustIndent(&buf, 2); virDomainCapsDeviceDiskFormat(&buf, &caps->disk); virDomainCapsDeviceGraphicsFormat(&buf, &caps->graphics); virDomainCapsDeviceVideoFormat(&buf, &caps->video); virDomainCapsDeviceHostdevFormat(&buf, &caps->hostdev); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</devices>\n"); virBufferAddLit(&buf, "<features>\n"); virBufferAdjustIndent(&buf, 2); virDomainCapsFeatureGICFormat(&buf, &caps->gic); FORMAT_SINGLE("vmcoreinfo", caps->vmcoreinfo); FORMAT_SINGLE("genid", caps->genid); virDomainCapsFeatureSEVFormat(&buf, caps->sev); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</features>\n"); virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</domainCapabilities>\n"); virBufferCheckError(&buf); return virBufferContentAndReset(&buf); }
static int virDomainCapsFormatInternal(virBufferPtr buf, virDomainCapsPtr const caps) { const char *virttype_str = virDomainVirtTypeToString(caps->virttype); const char *arch_str = virArchToString(caps->arch); virBufferAddLit(buf, "<domainCapabilities>\n"); virBufferAdjustIndent(buf, 2); virBufferEscapeString(buf, "<path>%s</path>\n", caps->path); virBufferAsprintf(buf, "<domain>%s</domain>\n", virttype_str); virBufferAsprintf(buf, "<machine>%s</machine>\n", caps->machine); virBufferAsprintf(buf, "<arch>%s</arch>\n", arch_str); if (caps->maxvcpus) virBufferAsprintf(buf, "<vcpu max='%d'/>\n", caps->maxvcpus); virDomainCapsOSFormat(buf, &caps->os); virDomainCapsCPUFormat(buf, &caps->cpu); virBufferAddLit(buf, "<devices>\n"); virBufferAdjustIndent(buf, 2); virDomainCapsDeviceDiskFormat(buf, &caps->disk); virDomainCapsDeviceGraphicsFormat(buf, &caps->graphics); virDomainCapsDeviceVideoFormat(buf, &caps->video); virDomainCapsDeviceHostdevFormat(buf, &caps->hostdev); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</devices>\n"); virBufferAddLit(buf, "<features>\n"); virBufferAdjustIndent(buf, 2); virDomainCapsFeatureGICFormat(buf, &caps->gic); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</features>\n"); virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</domainCapabilities>\n"); return 0; }
/* Functions */ virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver) { virCapsPtr caps; virCapsGuestPtr guest; virArch altArch; char *lxc_path = NULL; if ((caps = virCapabilitiesNew(virArchFromHost(), false, false)) == NULL) goto error; /* Some machines have problematic NUMA toplogy causing * unexpected failures. We don't want to break the lxc * driver in this scenario, so log errors & carry on */ if (nodeCapsInitNUMA(caps) < 0) { virCapabilitiesFreeNUMAInfo(caps); VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities"); } /* Only probe for power management capabilities in the driver, * not in the emulator */ if (driver && virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0) VIR_WARN("Failed to get host power management capabilities"); if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } if (!(lxc_path = virFileFindResource("libvirt_lxc", abs_topbuilddir "/src", LIBEXECDIR))) goto error; if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, caps->host.arch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; /* On 64-bit hosts, we can use personality() to request a 32bit process */ if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) { if ((guest = virCapabilitiesAddGuest(caps, VIR_DOMAIN_OSTYPE_EXE, altArch, lxc_path, NULL, 0, NULL)) == NULL) goto error; if (virCapabilitiesAddGuestDomain(guest, VIR_DOMAIN_VIRT_LXC, NULL, NULL, 0, NULL) == NULL) goto error; } VIR_FREE(lxc_path); if (driver) { /* Security driver data */ const char *doi, *model, *label, *type; doi = virSecurityManagerGetDOI(driver->securityManager); model = virSecurityManagerGetModel(driver->securityManager); label = virSecurityManagerGetBaseLabel(driver->securityManager, VIR_DOMAIN_VIRT_LXC); type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC); /* Allocate the primary security driver for LXC. */ if (VIR_ALLOC(caps->host.secModels) < 0) goto error; caps->host.nsecModels = 1; if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0) goto error; if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0) goto error; if (label && virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0], type, label) < 0) goto error; VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } else { VIR_INFO("No driver, not initializing security driver"); } return caps; error: VIR_FREE(lxc_path); virObjectUnref(caps); return NULL; }
virCapsPtr virQEMUDriverCreateCapabilities(virQEMUDriverPtr driver) { size_t i, j; virCapsPtr caps; virSecurityManagerPtr *sec_managers = NULL; /* Security driver data */ const char *doi, *model, *lbl, *type; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); const int virtTypes[] = {VIR_DOMAIN_VIRT_KVM, VIR_DOMAIN_VIRT_QEMU,}; /* Basic host arch / guest machine capabilities */ if (!(caps = virQEMUCapsInit(driver->qemuCapsCache))) goto error; if (virGetHostUUID(caps->host.host_uuid)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot get the host uuid")); goto error; } /* access sec drivers and create a sec model for each one */ if (!(sec_managers = virSecurityManagerGetNested(driver->securityManager))) goto error; /* calculate length */ for (i = 0; sec_managers[i]; i++) ; caps->host.nsecModels = i; if (VIR_ALLOC_N(caps->host.secModels, caps->host.nsecModels) < 0) goto error; for (i = 0; sec_managers[i]; i++) { virCapsHostSecModelPtr sm = &caps->host.secModels[i]; doi = virSecurityManagerGetDOI(sec_managers[i]); model = virSecurityManagerGetModel(sec_managers[i]); if (VIR_STRDUP(sm->model, model) < 0 || VIR_STRDUP(sm->doi, doi) < 0) goto error; for (j = 0; j < ARRAY_CARDINALITY(virtTypes); j++) { lbl = virSecurityManagerGetBaseLabel(sec_managers[i], virtTypes[j]); type = virDomainVirtTypeToString(virtTypes[j]); if (lbl && virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0) goto error; } VIR_DEBUG("Initialized caps for security driver \"%s\" with " "DOI \"%s\"", model, doi); } VIR_FREE(sec_managers); virObjectUnref(cfg); return caps; error: VIR_FREE(sec_managers); virObjectUnref(caps); virObjectUnref(cfg); return NULL; }
/** * virCapabilitiesFormatXML: * @caps: capabilities to format * * Convert the capabilities object into an XML representation * * Returns the XML document as a string */ char * virCapabilitiesFormatXML(virCapsPtr caps) { virBuffer buf = VIR_BUFFER_INITIALIZER; size_t i, j, k; char host_uuid[VIR_UUID_STRING_BUFLEN]; virBufferAddLit(&buf, "<capabilities>\n\n"); virBufferAdjustIndent(&buf, 2); virBufferAddLit(&buf, "<host>\n"); virBufferAdjustIndent(&buf, 2); if (virUUIDIsValid(caps->host.host_uuid)) { virUUIDFormat(caps->host.host_uuid, host_uuid); virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", host_uuid); } virBufferAddLit(&buf, "<cpu>\n"); virBufferAdjustIndent(&buf, 2); if (caps->host.arch) virBufferAsprintf(&buf, "<arch>%s</arch>\n", virArchToString(caps->host.arch)); if (caps->host.nfeatures) { virBufferAddLit(&buf, "<features>\n"); virBufferAdjustIndent(&buf, 2); for (i = 0; i < caps->host.nfeatures; i++) { virBufferAsprintf(&buf, "<%s/>\n", caps->host.features[i]); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</features>\n"); } virCPUDefFormatBuf(&buf, caps->host.cpu, false); for (i = 0; i < caps->host.nPagesSize; i++) { virBufferAsprintf(&buf, "<pages unit='KiB' size='%u'/>\n", caps->host.pagesSize[i]); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</cpu>\n"); /* The PM query was successful. */ if (caps->host.powerMgmt) { /* The host supports some PM features. */ unsigned int pm = caps->host.powerMgmt; virBufferAddLit(&buf, "<power_management>\n"); virBufferAdjustIndent(&buf, 2); while (pm) { int bit = ffs(pm) - 1; virBufferAsprintf(&buf, "<%s/>\n", virCapsHostPMTargetTypeToString(bit)); pm &= ~(1U << bit); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</power_management>\n"); } else { /* The host does not support any PM feature. */ virBufferAddLit(&buf, "<power_management/>\n"); } if (caps->host.offlineMigrate) { virBufferAddLit(&buf, "<migration_features>\n"); virBufferAdjustIndent(&buf, 2); if (caps->host.liveMigrate) virBufferAddLit(&buf, "<live/>\n"); if (caps->host.nmigrateTrans) { virBufferAddLit(&buf, "<uri_transports>\n"); virBufferAdjustIndent(&buf, 2); for (i = 0; i < caps->host.nmigrateTrans; i++) { virBufferAsprintf(&buf, "<uri_transport>%s</uri_transport>\n", caps->host.migrateTrans[i]); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</uri_transports>\n"); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</migration_features>\n"); } if (caps->host.nnumaCell && virCapabilitiesFormatNUMATopology(&buf, caps->host.nnumaCell, caps->host.numaCell) < 0) return NULL; for (i = 0; i < caps->host.nsecModels; i++) { virBufferAddLit(&buf, "<secmodel>\n"); virBufferAdjustIndent(&buf, 2); virBufferAsprintf(&buf, "<model>%s</model>\n", caps->host.secModels[i].model); virBufferAsprintf(&buf, "<doi>%s</doi>\n", caps->host.secModels[i].doi); for (j = 0; j < caps->host.secModels[i].nlabels; j++) { virBufferAsprintf(&buf, "<baselabel type='%s'>%s</baselabel>\n", caps->host.secModels[i].labels[j].type, caps->host.secModels[i].labels[j].label); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</secmodel>\n"); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</host>\n\n"); for (i = 0; i < caps->nguests; i++) { virBufferAddLit(&buf, "<guest>\n"); virBufferAdjustIndent(&buf, 2); virBufferAsprintf(&buf, "<os_type>%s</os_type>\n", virDomainOSTypeToString(caps->guests[i]->ostype)); if (caps->guests[i]->arch.id) virBufferAsprintf(&buf, "<arch name='%s'>\n", virArchToString(caps->guests[i]->arch.id)); virBufferAdjustIndent(&buf, 2); virBufferAsprintf(&buf, "<wordsize>%d</wordsize>\n", caps->guests[i]->arch.wordsize); if (caps->guests[i]->arch.defaultInfo.emulator) virBufferAsprintf(&buf, "<emulator>%s</emulator>\n", caps->guests[i]->arch.defaultInfo.emulator); if (caps->guests[i]->arch.defaultInfo.loader) virBufferAsprintf(&buf, "<loader>%s</loader>\n", caps->guests[i]->arch.defaultInfo.loader); for (j = 0; j < caps->guests[i]->arch.defaultInfo.nmachines; j++) { virCapsGuestMachinePtr machine = caps->guests[i]->arch.defaultInfo.machines[j]; virBufferAddLit(&buf, "<machine"); if (machine->canonical) virBufferAsprintf(&buf, " canonical='%s'", machine->canonical); if (machine->maxCpus > 0) virBufferAsprintf(&buf, " maxCpus='%d'", machine->maxCpus); virBufferAsprintf(&buf, ">%s</machine>\n", machine->name); } for (j = 0; j < caps->guests[i]->arch.ndomains; j++) { virBufferAsprintf(&buf, "<domain type='%s'", virDomainVirtTypeToString(caps->guests[i]->arch.domains[j]->type)); if (!caps->guests[i]->arch.domains[j]->info.emulator && !caps->guests[i]->arch.domains[j]->info.loader && !caps->guests[i]->arch.domains[j]->info.nmachines) { virBufferAddLit(&buf, "/>\n"); continue; } virBufferAddLit(&buf, ">\n"); virBufferAdjustIndent(&buf, 2); if (caps->guests[i]->arch.domains[j]->info.emulator) virBufferAsprintf(&buf, "<emulator>%s</emulator>\n", caps->guests[i]->arch.domains[j]->info.emulator); if (caps->guests[i]->arch.domains[j]->info.loader) virBufferAsprintf(&buf, "<loader>%s</loader>\n", caps->guests[i]->arch.domains[j]->info.loader); for (k = 0; k < caps->guests[i]->arch.domains[j]->info.nmachines; k++) { virCapsGuestMachinePtr machine = caps->guests[i]->arch.domains[j]->info.machines[k]; virBufferAddLit(&buf, "<machine"); if (machine->canonical) virBufferAsprintf(&buf, " canonical='%s'", machine->canonical); if (machine->maxCpus > 0) virBufferAsprintf(&buf, " maxCpus='%d'", machine->maxCpus); virBufferAsprintf(&buf, ">%s</machine>\n", machine->name); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</domain>\n"); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</arch>\n"); if (caps->guests[i]->nfeatures) { virBufferAddLit(&buf, "<features>\n"); virBufferAdjustIndent(&buf, 2); for (j = 0; j < caps->guests[i]->nfeatures; j++) { if (STREQ(caps->guests[i]->features[j]->name, "pae") || STREQ(caps->guests[i]->features[j]->name, "nonpae") || STREQ(caps->guests[i]->features[j]->name, "ia64_be") || STREQ(caps->guests[i]->features[j]->name, "cpuselection") || STREQ(caps->guests[i]->features[j]->name, "deviceboot")) { virBufferAsprintf(&buf, "<%s/>\n", caps->guests[i]->features[j]->name); } else { virBufferAsprintf(&buf, "<%s default='%s' toggle='%s'/>\n", caps->guests[i]->features[j]->name, caps->guests[i]->features[j]->defaultOn ? "on" : "off", caps->guests[i]->features[j]->toggle ? "yes" : "no"); } } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</features>\n"); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</guest>\n\n"); } virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</capabilities>\n"); if (virBufferCheckError(&buf) < 0) return NULL; return virBufferContentAndReset(&buf); }
static virCapsDomainDataPtr virCapabilitiesDomainDataLookupInternal(virCapsPtr caps, int ostype, virArch arch, int domaintype, const char *emulator, const char *machinetype) { virCapsGuestPtr foundguest = NULL; virCapsGuestDomainPtr founddomain = NULL; virCapsGuestMachinePtr foundmachine = NULL; virCapsDomainDataPtr ret = NULL; size_t i, j, k; for (i = 0; i < caps->nguests; i++) { virCapsGuestPtr guest = caps->guests[i]; for (j = 0; j < guest->arch.ndomains; j++) { virCapsGuestDomainPtr domain = guest->arch.domains[j]; virCapsGuestMachinePtr *machinelist; int nmachines; if (domain->info.nmachines) { nmachines = domain->info.nmachines; machinelist = domain->info.machines; } else { nmachines = guest->arch.defaultInfo.nmachines; machinelist = guest->arch.defaultInfo.machines; } for (k = 0; k < nmachines; k++) { virCapsGuestMachinePtr machine = machinelist[k]; if (!virCapsDomainDataCompare(guest, domain, machine, ostype, arch, domaintype, emulator, machinetype)) continue; foundmachine = machine; break; } if (!foundmachine) { if (!virCapsDomainDataCompare(guest, domain, NULL, ostype, arch, domaintype, emulator, machinetype)) continue; } founddomain = domain; break; } if (!founddomain) { if (!virCapsDomainDataCompare(guest, NULL, NULL, ostype, arch, domaintype, emulator, machinetype)) continue; } foundguest = guest; break; } /* XXX check default_emulator, see how it uses this */ if (!foundguest) { virBuffer buf = VIR_BUFFER_INITIALIZER; if (ostype) virBufferAsprintf(&buf, "ostype=%s ", virDomainOSTypeToString(ostype)); if (arch) virBufferAsprintf(&buf, "arch=%s ", virArchToString(arch)); if (domaintype != -1) virBufferAsprintf(&buf, "domaintype=%s ", virDomainVirtTypeToString(domaintype)); if (emulator) virBufferEscapeString(&buf, "emulator=%s ", emulator); if (machinetype) virBufferEscapeString(&buf, "machine=%s ", machinetype); if (virBufferCurrentContent(&buf) && !virBufferCurrentContent(&buf)[0]) virBufferAsprintf(&buf, "%s", _("any configuration")); if (virBufferCheckError(&buf) < 0) { virBufferFreeAndReset(&buf); goto error; } virReportError(VIR_ERR_INVALID_ARG, _("could not find capabilities for %s"), virBufferCurrentContent(&buf)); virBufferFreeAndReset(&buf); goto error; } if (VIR_ALLOC(ret) < 0) goto error; ret->ostype = foundguest->ostype; ret->arch = foundguest->arch.id; if (founddomain) { ret->domaintype = founddomain->type; ret->emulator = founddomain->info.emulator; } if (!ret->emulator) ret->emulator = foundguest->arch.defaultInfo.emulator; if (foundmachine) ret->machinetype = foundmachine->name; error: return ret; }