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);