libxl: refactor capabilities code

Cleanup the libxl capabilities code to be a bit more extensible,
splitting out the creation of host and guest capabilities.  This
should make it easier to implement additional capabilities in the
future, such as NUMA topology reporting.
This commit is contained in:
Jim Fehlig 2013-08-12 14:15:25 -06:00
parent 7a7cb0934e
commit aeab0243e1

View File

@ -64,126 +64,62 @@ static const char *xen_cap_re = "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(x86_32|x
static regex_t xen_cap_rec; static regex_t xen_cap_rec;
static virCapsPtr static int
libxlBuildCapabilities(virArch hostarch, libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps)
int host_pae,
struct guest_arch *guest_archs,
int nr_guest_archs)
{ {
virCapsPtr caps; int err;
size_t i; libxl_physinfo phy_info;
int host_pae;
if ((caps = virCapabilitiesNew(hostarch, 1, 1)) == NULL) err = regcomp(&xen_cap_rec, xen_cap_re, REG_EXTENDED);
goto no_memory; if (err != 0) {
char error[100];
if (host_pae && regerror(err, &xen_cap_rec, error, sizeof(error));
virCapabilitiesAddHostFeature(caps, "pae") < 0) regfree(&xen_cap_rec);
goto no_memory; virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to compile regex %s"), error);
for (i = 0; i < nr_guest_archs; ++i) { return -1;
virCapsGuestPtr guest;
char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
virCapsGuestMachinePtr *machines;
if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
goto no_memory;
if ((guest = virCapabilitiesAddGuest(caps,
guest_archs[i].hvm ? "hvm" : "xen",
guest_archs[i].arch,
((hostarch == VIR_ARCH_X86_64) ?
"/usr/lib64/xen/bin/qemu-dm" :
"/usr/lib/xen/bin/qemu-dm"),
(guest_archs[i].hvm ?
"/usr/lib/xen/boot/hvmloader" :
NULL),
1,
machines)) == NULL) {
virCapabilitiesFreeMachines(machines, 1);
goto no_memory;
}
machines = NULL;
if (virCapabilitiesAddGuestDomain(guest,
"xen",
NULL,
NULL,
0,
NULL) == NULL)
goto no_memory;
if (guest_archs[i].pae &&
virCapabilitiesAddGuestFeature(guest,
"pae",
1,
0) == NULL)
goto no_memory;
if (guest_archs[i].nonpae &&
virCapabilitiesAddGuestFeature(guest,
"nonpae",
1,
0) == NULL)
goto no_memory;
if (guest_archs[i].ia64_be &&
virCapabilitiesAddGuestFeature(guest,
"ia64_be",
1,
0) == NULL)
goto no_memory;
if (guest_archs[i].hvm) {
if (virCapabilitiesAddGuestFeature(guest,
"acpi",
1,
1) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestFeature(guest, "apic",
1,
0) == NULL)
goto no_memory;
if (virCapabilitiesAddGuestFeature(guest,
"hap",
0,
1) == NULL)
goto no_memory;
}
} }
return caps; if (libxl_get_physinfo(ctx, &phy_info) != 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
no_memory: _("Failed to get node physical info from libxenlight"));
virObjectUnref(caps); return -1;
return NULL; }
}
static virCapsPtr
libxlMakeCapabilitiesInternal(virArch hostarch,
libxl_physinfo *phy_info,
char *capabilities)
{
char *str, *token;
regmatch_t subs[4];
char *saveptr = NULL;
size_t i;
int host_pae = 0;
struct guest_arch guest_archs[32];
int nr_guest_archs = 0;
virCapsPtr caps = NULL;
memset(guest_archs, 0, sizeof(guest_archs));
/* hw_caps is an array of 32-bit words whose meaning is listed in /* hw_caps is an array of 32-bit words whose meaning is listed in
* xen-unstable.hg/xen/include/asm-x86/cpufeature.h. Each feature * xen-unstable.hg/xen/include/asm-x86/cpufeature.h. Each feature
* is defined in the form X*32+Y, corresponding to the Y'th bit in * is defined in the form X*32+Y, corresponding to the Y'th bit in
* the X'th 32-bit word of hw_cap. * the X'th 32-bit word of hw_cap.
*/ */
host_pae = phy_info->hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK; host_pae = phy_info.hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK;
if (host_pae &&
virCapabilitiesAddHostFeature(caps, "pae") < 0)
return -1;
return 0;
}
static int
libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
{
const libxl_version_info *ver_info;
char *str, *token;
regmatch_t subs[4];
char *saveptr = NULL;
size_t i;
virArch hostarch = caps->host.arch;
struct guest_arch guest_archs[32];
int nr_guest_archs = 0;
memset(guest_archs, 0, sizeof(guest_archs));
if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Failed to get version info from libxenlight"));
return -1;
}
/* Format of capabilities string is documented in the code in /* Format of capabilities string is documented in the code in
* xen-unstable.hg/xen/arch/.../setup.c. * xen-unstable.hg/xen/arch/.../setup.c.
* *
@ -209,7 +145,7 @@ libxlMakeCapabilitiesInternal(virArch hostarch,
/* Split capabilities string into tokens. strtok_r is OK here because /* Split capabilities string into tokens. strtok_r is OK here because
* we "own" the buffer. Parse out the features from each token. * we "own" the buffer. Parse out the features from each token.
*/ */
for (str = capabilities, nr_guest_archs = 0; for (str = ver_info->capabilities, nr_guest_archs = 0;
nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0]) nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
&& (token = strtok_r(str, " ", &saveptr)) != NULL; && (token = strtok_r(str, " ", &saveptr)) != NULL;
str = NULL) { str = NULL) {
@ -273,17 +209,80 @@ libxlMakeCapabilitiesInternal(virArch hostarch,
} }
} }
if ((caps = libxlBuildCapabilities(hostarch, for (i = 0; i < nr_guest_archs; ++i) {
host_pae, virCapsGuestPtr guest;
guest_archs, char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
nr_guest_archs)) == NULL) virCapsGuestMachinePtr *machines;
goto error;
return caps; if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
return -1;
error: if ((guest = virCapabilitiesAddGuest(caps,
virObjectUnref(caps); guest_archs[i].hvm ? "hvm" : "xen",
return NULL; guest_archs[i].arch,
((hostarch == VIR_ARCH_X86_64) ?
"/usr/lib64/xen/bin/qemu-dm" :
"/usr/lib/xen/bin/qemu-dm"),
(guest_archs[i].hvm ?
"/usr/lib/xen/boot/hvmloader" :
NULL),
1,
machines)) == NULL) {
virCapabilitiesFreeMachines(machines, 1);
return -1;
}
machines = NULL;
if (virCapabilitiesAddGuestDomain(guest,
"xen",
NULL,
NULL,
0,
NULL) == NULL)
return -1;
if (guest_archs[i].pae &&
virCapabilitiesAddGuestFeature(guest,
"pae",
1,
0) == NULL)
return -1;
if (guest_archs[i].nonpae &&
virCapabilitiesAddGuestFeature(guest,
"nonpae",
1,
0) == NULL)
return -1;
if (guest_archs[i].ia64_be &&
virCapabilitiesAddGuestFeature(guest,
"ia64_be",
1,
0) == NULL)
return -1;
if (guest_archs[i].hvm) {
if (virCapabilitiesAddGuestFeature(guest,
"acpi",
1,
1) == NULL)
return -1;
if (virCapabilitiesAddGuestFeature(guest, "apic",
1,
0) == NULL)
return -1;
if (virCapabilitiesAddGuestFeature(guest,
"hap",
0,
1) == NULL)
return -1;
}
}
return 0;
} }
static int static int
@ -873,35 +872,22 @@ error:
virCapsPtr virCapsPtr
libxlMakeCapabilities(libxl_ctx *ctx) libxlMakeCapabilities(libxl_ctx *ctx)
{ {
int err; virCapsPtr caps;
libxl_physinfo phy_info;
const libxl_version_info *ver_info;
err = regcomp(&xen_cap_rec, xen_cap_re, REG_EXTENDED); if ((caps = virCapabilitiesNew(virArchFromHost(), 1, 1)) == NULL)
if (err != 0) {
char error[100];
regerror(err, &xen_cap_rec, error, sizeof(error));
regfree(&xen_cap_rec);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to compile regex %s"), error);
return NULL; return NULL;
}
if (libxl_get_physinfo(ctx, &phy_info) != 0) { if (libxlCapsInitHost(ctx, caps) < 0)
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", goto error;
_("Failed to get node physical info from libxenlight"));
return NULL;
}
if ((ver_info = libxl_get_version_info(ctx)) == NULL) { if (libxlCapsInitGuests(ctx, caps) < 0)
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", goto error;
_("Failed to get version info from libxenlight"));
return NULL;
}
return libxlMakeCapabilitiesInternal(virArchFromHost(), return caps;
&phy_info,
ver_info->capabilities); error:
virObjectUnref(caps);
return NULL;
} }
int int