diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index aef2c2db07..45f098826a 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -30,8 +30,10 @@ #include "virerror.h" #include "virfile.h" #include "viralloc.h" +#include "virstring.h" #include "domain_conf.h" #include "capabilities.h" +#include "domain_capabilities.h" #include "vircommand.h" #include "libxl_capabilities.h" @@ -396,6 +398,109 @@ libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps) return 0; } +static int +libxlMakeDomainOSCaps(const char *machine, + virDomainCapsOSPtr os, + virFirmwarePtr *firmwares, + size_t nfirmwares) +{ + virDomainCapsLoaderPtr capsLoader = &os->loader; + size_t i; + + os->supported = true; + + if (STREQ(machine, "xenpv")) + return 0; + + capsLoader->supported = true; + if (VIR_ALLOC_N(capsLoader->values.values, nfirmwares) < 0) + return -1; + + for (i = 0; i < nfirmwares; i++) { + if (VIR_STRDUP(capsLoader->values.values[capsLoader->values.nvalues], + firmwares[i]->name) < 0) + return -1; + capsLoader->values.nvalues++; + } + + VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->type, + VIR_DOMAIN_LOADER_TYPE_ROM, + VIR_DOMAIN_LOADER_TYPE_PFLASH); + VIR_DOMAIN_CAPS_ENUM_SET(capsLoader->readonly, + VIR_TRISTATE_BOOL_YES); + + return 0; +} + +static int +libxlMakeDomainDeviceDiskCaps(virDomainCapsDeviceDiskPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->diskDevice, + VIR_DOMAIN_DISK_DEVICE_DISK, + VIR_DOMAIN_DISK_DEVICE_CDROM); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->bus, + VIR_DOMAIN_DISK_BUS_IDE, + VIR_DOMAIN_DISK_BUS_SCSI, + VIR_DOMAIN_DISK_BUS_XEN); + + return 0; +} + +static int +libxlMakeDomainDeviceGraphicsCaps(virDomainCapsDeviceGraphicsPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->type, + VIR_DOMAIN_GRAPHICS_TYPE_SDL, + VIR_DOMAIN_GRAPHICS_TYPE_VNC, + VIR_DOMAIN_GRAPHICS_TYPE_SPICE); + + return 0; +} + +static int +libxlMakeDomainDeviceVideoCaps(virDomainCapsDeviceVideoPtr dev) +{ + dev->supported = true; + + VIR_DOMAIN_CAPS_ENUM_SET(dev->modelType, + VIR_DOMAIN_VIDEO_TYPE_VGA, + VIR_DOMAIN_VIDEO_TYPE_CIRRUS, + VIR_DOMAIN_VIDEO_TYPE_XEN); + + return 0; +} + +static int +libxlMakeDomainDeviceHostdevCaps(virDomainCapsDeviceHostdevPtr dev) +{ + dev->supported = true; + /* VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES is for containers only */ + VIR_DOMAIN_CAPS_ENUM_SET(dev->mode, + VIR_DOMAIN_HOSTDEV_MODE_SUBSYS); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->startupPolicy, + VIR_DOMAIN_STARTUP_POLICY_DEFAULT, + VIR_DOMAIN_STARTUP_POLICY_MANDATORY, + VIR_DOMAIN_STARTUP_POLICY_REQUISITE, + VIR_DOMAIN_STARTUP_POLICY_OPTIONAL); + + VIR_DOMAIN_CAPS_ENUM_SET(dev->subsysType, + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI); + + /* No virDomainHostdevCapsType for libxl */ + virDomainCapsEnumClear(&dev->capsType); + + virDomainCapsEnumClear(&dev->pciBackend); + VIR_DOMAIN_CAPS_ENUM_SET(dev->pciBackend, + VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN); + return 0; +} + virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx) { @@ -424,6 +529,41 @@ libxlMakeCapabilities(libxl_ctx *ctx) return NULL; } +/* + * Currently Xen has no interface to report maxvcpus supported + * for the various domain types (PV, HVM, PVH). HVM_MAX_VCPUS + * is defined in $xensrc/xen/include/public/hvm/hvm_info_table.h + * PV has no equivalent and is relunctantly set here until Xen + * can report such capabilities. + */ +#define HVM_MAX_VCPUS 128 +#define PV_MAX_VCPUS 512 + +int +libxlMakeDomainCapabilities(virDomainCapsPtr domCaps, + virFirmwarePtr *firmwares, + size_t nfirmwares) +{ + virDomainCapsOSPtr os = &domCaps->os; + virDomainCapsDeviceDiskPtr disk = &domCaps->disk; + virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics; + virDomainCapsDeviceVideoPtr video = &domCaps->video; + virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; + + if (STREQ(domCaps->machine, "xenfv")) + domCaps->maxvcpus = HVM_MAX_VCPUS; + else + domCaps->maxvcpus = PV_MAX_VCPUS; + + if (libxlMakeDomainOSCaps(domCaps->machine, os, firmwares, nfirmwares) < 0 || + libxlMakeDomainDeviceDiskCaps(disk) < 0 || + libxlMakeDomainDeviceGraphicsCaps(graphics) < 0 || + libxlMakeDomainDeviceVideoCaps(video) < 0 || + libxlMakeDomainDeviceHostdevCaps(hostdev) < 0) + return -1; + return 0; +} + #define LIBXL_QEMU_DM_STR "Options specific to the Xen version:" int diff --git a/src/libxl/libxl_capabilities.h b/src/libxl/libxl_capabilities.h index df1c3270c5..992b780771 100644 --- a/src/libxl/libxl_capabilities.h +++ b/src/libxl/libxl_capabilities.h @@ -27,6 +27,8 @@ # include "virobject.h" # include "capabilities.h" +# include "domain_capabilities.h" +# include "virfirmware.h" # ifndef LIBXL_FIRMWARE_DIR @@ -44,6 +46,11 @@ virCapsPtr libxlMakeCapabilities(libxl_ctx *ctx); +int +libxlMakeDomainCapabilities(virDomainCapsPtr domCaps, + virFirmwarePtr *firmwares, + size_t nfirmwares); + int libxlDomainGetEmulatorType(const virDomainDef *def); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 29b19ef5bd..9e9957e739 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -5526,6 +5526,79 @@ libxlDomainInterfaceAddresses(virDomainPtr dom, } +static char * +libxlConnectGetDomainCapabilities(virConnectPtr conn, + const char *emulatorbin, + const char *arch_str, + const char *machine, + const char *virttype_str, + unsigned int flags) +{ + libxlDriverPrivatePtr driver = conn->privateData; + libxlDriverConfigPtr cfg; + char *ret = NULL; + int virttype = VIR_DOMAIN_VIRT_XEN; + virDomainCapsPtr domCaps = NULL; + int arch = virArchFromHost(); /* virArch */ + + virCheckFlags(0, ret); + + if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0) + return ret; + + cfg = libxlDriverConfigGet(driver); + + if (virttype_str && + (virttype = virDomainVirtTypeFromString(virttype_str)) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown virttype: %s"), + virttype_str); + goto cleanup; + } + + if (virttype != VIR_DOMAIN_VIRT_XEN) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown virttype: %s"), + virttype_str); + goto cleanup; + } + + if (arch_str && (arch = virArchFromString(arch_str)) == VIR_ARCH_NONE) { + virReportError(VIR_ERR_INVALID_ARG, + _("unknown architecture: %s"), + arch_str); + goto cleanup; + } + + if (emulatorbin == NULL) + emulatorbin = "/usr/bin/qemu-system-x86_64"; + + if (machine) { + if (STRNEQ(machine, "xenpv") && STRNEQ(machine, "xenfv")) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Xen only supports 'xenpv' and 'xenfv' machines")); + goto cleanup; + } + } else { + machine = "xenpv"; + } + + if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype))) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, cfg->firmwares, + cfg->nfirmwares) < 0) + goto cleanup; + + ret = virDomainCapsFormat(domCaps); + + cleanup: + virObjectUnref(domCaps); + virObjectUnref(cfg); + return ret; +} + + static virHypervisorDriver libxlHypervisorDriver = { .name = LIBXL_DRIVER_NAME, .connectOpen = libxlConnectOpen, /* 0.9.0 */ @@ -5627,6 +5700,7 @@ static virHypervisorDriver libxlHypervisorDriver = { .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */ .nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */ .domainInterfaceAddresses = libxlDomainInterfaceAddresses, /* 1.3.5 */ + .connectGetDomainCapabilities = libxlConnectGetDomainCapabilities, /* 1.3.6 */ }; static virConnectDriver libxlConnectDriver = { diff --git a/tests/Makefile.am b/tests/Makefile.am index 18ffab6a36..4a1e0f3dcc 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -930,6 +930,11 @@ domaincapstest_SOURCES += testutilsqemu.c testutilsqemu.h domaincapstest_LDADD += $(qemu_LDADDS) $(GNULIB_LIBS) endif WITH_QEMU +if WITH_LIBXL +domaincapstest_SOURCES += testutilsxen.c testutilsxen.h +domaincapstest_LDADD += ../src/libvirt_driver_libxl_impl.la +endif WITH_LIBXL + if WITH_LIBVIRTD libvirtdconftest_SOURCES = \ libvirtdconftest.c testutils.h testutils.c \ diff --git a/tests/domaincapsschemadata/libxl-xenfv.xml b/tests/domaincapsschemadata/libxl-xenfv.xml new file mode 100644 index 0000000000..9436ef89e8 --- /dev/null +++ b/tests/domaincapsschemadata/libxl-xenfv.xml @@ -0,0 +1,68 @@ + + /usr/bin/qemu-system-x86_64 + xen + xenfv + x86_64 + + + + /usr/lib/xen/boot/hvmloader + /usr/lib/xen/boot/ovmf.bin + + rom + pflash + + + yes + + + + + + + disk + cdrom + + + ide + scsi + xen + + + + + sdl + vnc + spice + + + + + + subsystem + + + default + mandatory + requisite + optional + + + pci + + + + xen + + + + + + + diff --git a/tests/domaincapsschemadata/libxl-xenpv.xml b/tests/domaincapsschemadata/libxl-xenpv.xml new file mode 100644 index 0000000000..ab00a28f81 --- /dev/null +++ b/tests/domaincapsschemadata/libxl-xenpv.xml @@ -0,0 +1,58 @@ + + /usr/bin/qemu-system-x86_64 + xen + xenpv + x86_64 + + + + + + + + disk + cdrom + + + ide + scsi + xen + + + + + sdl + vnc + spice + + + + + + subsystem + + + default + mandatory + requisite + optional + + + pci + + + + xen + + + + + + + diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 83ce0e5f37..9fb2c974ec 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -162,10 +162,41 @@ fillQemuCaps(virDomainCapsPtr domCaps, #endif /* WITH_QEMU */ +#ifdef WITH_LIBXL +# include "testutilsxen.h" + +static int +fillXenCaps(virDomainCapsPtr domCaps) +{ + virFirmwarePtr *firmwares; + int ret = -1; + + if (VIR_ALLOC_N(firmwares, 2) < 0) + return ret; + + if (VIR_ALLOC(firmwares[0]) < 0 || VIR_ALLOC(firmwares[1]) < 0) + goto cleanup; + if (VIR_STRDUP(firmwares[0]->name, "/usr/lib/xen/boot/hvmloader") < 0 || + VIR_STRDUP(firmwares[1]->name, "/usr/lib/xen/boot/ovmf.bin") < 0) + goto cleanup; + + if (libxlMakeDomainCapabilities(domCaps, firmwares, 2) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virFirmwareFreeList(firmwares, 2); + return ret; +} +#endif /* WITH_LIBXL */ + + enum testCapsType { CAPS_NONE, CAPS_ALL, CAPS_QEMU, + CAPS_LIBXL, }; struct testData { @@ -211,6 +242,13 @@ test_virDomainCapsFormat(const void *opaque) if (fillQemuCaps(domCaps, data->capsName, data->arch, data->machine, data->capsOpaque) < 0) goto cleanup; +#endif + break; + + case CAPS_LIBXL: +#if WITH_LIBXL + if (fillXenCaps(domCaps) < 0) + goto cleanup; #endif break; } @@ -280,6 +318,20 @@ mymain(void) VIR_FREE(name); \ } while (0) +#define DO_TEST_LIBXL(Name, Emulator, Machine, Arch, Type) \ + do { \ + struct testData data = { \ + .name = Name, \ + .emulator = Emulator, \ + .machine = Machine, \ + .arch = Arch, \ + .type = Type, \ + .capsType = CAPS_LIBXL, \ + }; \ + if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0) \ + ret = -1; \ + } while (0) + DO_TEST("basic", "/bin/emulatorbin", "my-machine-type", "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE); DO_TEST("full", "/bin/emulatorbin", "my-machine-type", @@ -313,6 +365,15 @@ mymain(void) #endif /* WITH_QEMU */ +#if WITH_LIBXL + + DO_TEST_LIBXL("libxl-xenpv", "/usr/bin/qemu-system-x86_64", + "xenpv", "x86_64", VIR_DOMAIN_VIRT_XEN); + DO_TEST_LIBXL("libxl-xenfv", "/usr/bin/qemu-system-x86_64", + "xenfv", "x86_64", VIR_DOMAIN_VIRT_XEN); + +#endif /* WITH_LIBXL */ + return ret; } diff --git a/tests/testutilsxen.h b/tests/testutilsxen.h index c78350d2d6..8b997c3232 100644 --- a/tests/testutilsxen.h +++ b/tests/testutilsxen.h @@ -2,6 +2,7 @@ # define _TESTUTILSXEN_H_ # include "capabilities.h" +# include "libxl/libxl_capabilities.h" virCapsPtr testXenCapsInit(void);