summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2012-07-31 15:26:50 +0100
committerDaniel P. Berrange <berrange@redhat.com>2012-07-31 15:26:50 +0100
commit804aac46ba4b7a602dd4edd18271815420d98b00 (patch)
treeb9448e2bb9c09bcc87b5203bc9d24636a6a3ebd1
parent76baefee6645a8ec92a4c5a009a218b2b516a4d4 (diff)
Introduce APIs for setting up optimal virt type / os type / arch
-rw-r--r--libvirt-designer/Makefile.am20
-rw-r--r--libvirt-designer/libvirt-designer-domain.c662
-rw-r--r--libvirt-designer/libvirt-designer-domain.h99
-rw-r--r--libvirt-designer/libvirt-designer.h1
-rw-r--r--libvirt-designer/libvirt-designer.sym17
-rw-r--r--libvirt-designer/test-designer-domain.c362
6 files changed, 1161 insertions, 0 deletions
diff --git a/libvirt-designer/Makefile.am b/libvirt-designer/Makefile.am
index 458d48c..cf40419 100644
--- a/libvirt-designer/Makefile.am
+++ b/libvirt-designer/Makefile.am
@@ -21,9 +21,11 @@ DESIGNER_GENERATED_FILES = \
DESIGNER_HEADER_FILES = \
libvirt-designer.h \
libvirt-designer-main.h \
+ libvirt-designer-domain.h \
$(NULL)
DESIGNER_SOURCE_FILES = \
libvirt-designer-main.c \
+ libvirt-designer-domain.c \
$(NULL)
libvirt_designer_1_0_ladir = $(includedir)/libvirt-designer-1.0/libvirt-designer
@@ -78,6 +80,24 @@ libvirt-designer-enum-types.c: $(DESIGNER_HEADER_FILES) libvirt-designer-enum-ty
$(AM_V_GEN) ( $(GLIB_MKENUMS) --template $(srcdir)/libvirt-designer-enum-types.c.template $(DESIGNER_HEADER_FILES:%=$(srcdir)/%) ) | \
sed -e "s/G_TYPE_VIR_CONFIG/GVIR_CONFIG_TYPE/" -e "s/g_vir/gvir/" > libvirt-designer-enum-types.c
+check_PROGRAMS = test-designer-domain
+
+TESTS = $(check_PROGRAMS)
+
+test_designer_domain_CFLAGS = \
+ -I$(top_srcdir) \
+ $(COVERAGE_CFLAGS) \
+ -I$(top_srcdir) \
+ $(LIBOSINFO_CFLAGS) \
+ $(LIBVIRT_GCONFIG_CFLAGS) \
+ $(WARN_CFLAGS2) \
+ $(NULL)
+test_designer_domain_LDADD = \
+ libvirt-designer-1.0.la
+test_designer_domain_LDFLAGS = \
+ $(LIBOSINFO_LIBS) \
+ $(LIBVIRT_GCONFIG_LIBS) \
+ $(COVERAGE_CFLAGS:-f%=-Wc,f%)
if WITH_INTROSPECTION
diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c
new file mode 100644
index 0000000..9b4a7ed
--- /dev/null
+++ b/libvirt-designer/libvirt-designer-domain.c
@@ -0,0 +1,662 @@
+/*
+ * libvirt-designer-domain.c: libvirt domain configuration
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include <config.h>
+#include <sys/utsname.h>
+
+#include "libvirt-designer/libvirt-designer.h"
+
+#define GVIR_DESIGNER_DOMAIN_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), GVIR_DESIGNER_TYPE_DOMAIN, GVirDesignerDomainPrivate))
+
+struct _GVirDesignerDomainPrivate
+{
+ GVirConfigDomain *config;
+ GVirConfigCapabilities *caps;
+ OsinfoOs *os;
+ OsinfoPlatform *platform;
+};
+
+G_DEFINE_TYPE(GVirDesignerDomain, gvir_designer_domain, G_TYPE_OBJECT);
+
+#define GVIR_DESIGNER_DOMAIN_ERROR gvir_designer_domain_error_quark()
+
+static GQuark
+gvir_designer_domain_error_quark(void)
+{
+ return g_quark_from_static_string("gvir-designer-domain");
+}
+
+enum {
+ PROP_0,
+ PROP_CONFIG,
+ PROP_OS,
+ PROP_PLATFORM,
+ PROP_CAPS,
+};
+
+static void gvir_designer_domain_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ g_return_if_fail(GVIR_DESIGNER_IS_DOMAIN(object));
+
+ GVirDesignerDomain *design = GVIR_DESIGNER_DOMAIN(object);
+ GVirDesignerDomainPrivate *priv = design->priv;
+
+ switch (prop_id) {
+ case PROP_CONFIG:
+ g_value_set_object(value, priv->config);
+ break;
+
+ case PROP_OS:
+ g_value_set_object(value, priv->os);
+ break;
+
+ case PROP_PLATFORM:
+ g_value_set_object(value, priv->platform);
+ break;
+
+ case PROP_CAPS:
+ g_value_set_object(value, priv->caps);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+static void gvir_designer_domain_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ g_return_if_fail(GVIR_DESIGNER_IS_DOMAIN(object));
+
+ GVirDesignerDomain *design = GVIR_DESIGNER_DOMAIN(object);
+ GVirDesignerDomainPrivate *priv = design->priv;
+
+ switch (prop_id) {
+ case PROP_OS:
+ if (priv->os)
+ g_object_unref(priv->os);
+ priv->os = g_value_dup_object(value);
+ break;
+
+ case PROP_PLATFORM:
+ if (priv->platform)
+ g_object_unref(priv->platform);
+ priv->platform = g_value_dup_object(value);
+ break;
+
+ case PROP_CAPS:
+ if (priv->caps)
+ g_object_unref(priv->caps);
+ priv->caps = g_value_dup_object(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ }
+}
+
+
+static void gvir_designer_domain_finalize(GObject *object)
+{
+ GVirDesignerDomain *conn = GVIR_DESIGNER_DOMAIN(object);
+ GVirDesignerDomainPrivate *priv = conn->priv;
+
+ g_object_unref(priv->config);
+ g_object_unref(priv->os);
+ g_object_unref(priv->platform);
+ g_object_unref(priv->caps);
+
+ G_OBJECT_CLASS(gvir_designer_domain_parent_class)->finalize(object);
+}
+
+
+static void gvir_designer_domain_class_init(GVirDesignerDomainClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+ object_class->finalize = gvir_designer_domain_finalize;
+
+ object_class->get_property = gvir_designer_domain_get_property;
+ object_class->set_property = gvir_designer_domain_set_property;
+
+ g_object_class_install_property(object_class,
+ PROP_CONFIG,
+ g_param_spec_object("config",
+ "Config",
+ "Domain config",
+ GVIR_CONFIG_TYPE_DOMAIN,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property(object_class,
+ PROP_OS,
+ g_param_spec_object("os",
+ "Os",
+ "Operating system",
+ OSINFO_TYPE_OS,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property(object_class,
+ PROP_PLATFORM,
+ g_param_spec_object("platform",
+ "Platform",
+ "Platform",
+ OSINFO_TYPE_PLATFORM,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property(object_class,
+ PROP_CAPS,
+ g_param_spec_object("capabilities",
+ "Capabilities",
+ "Capabilities",
+ GVIR_CONFIG_TYPE_CAPABILITIES,
+ G_PARAM_READABLE |
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private(klass, sizeof(GVirDesignerDomainPrivate));
+}
+
+
+static void gvir_designer_domain_init(GVirDesignerDomain *design)
+{
+ GVirDesignerDomainPrivate *priv;
+ g_debug("Init GVirDesignerDomain=%p", design);
+
+ priv = design->priv = GVIR_DESIGNER_DOMAIN_GET_PRIVATE(design);
+ priv->config = gvir_config_domain_new();
+}
+
+
+GVirDesignerDomain *gvir_designer_domain_new(OsinfoOs *os,
+ OsinfoPlatform *platform,
+ GVirConfigCapabilities *caps)
+{
+ return GVIR_DESIGNER_DOMAIN(g_object_new(GVIR_DESIGNER_TYPE_DOMAIN,
+ "os", os,
+ "platform", platform,
+ "capabilities", caps,
+ NULL));
+}
+
+
+/**
+ * gvir_designer_domain_get_os:
+ * @design: (transfer none): the domain designer instance
+ *
+ * Retrieves the operating system object associated with the designer.
+ * The object should not be modified by the caller.
+ *
+ * Returns: (transfer none): the operating system
+ */
+OsinfoOs *gvir_designer_domain_get_os(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+ GVirDesignerDomainPrivate *priv = design->priv;
+ return priv->os;
+}
+
+
+/**
+ * gvir_designer_domain_get_platform:
+ * @design: (transfer none): the domain designer instance
+ *
+ * Retrieves the virtualization platform object associated with the designer.
+ * The object should not be modified by the caller.
+ *
+ * Returns: (transfer none): the virtualization platform
+ */
+OsinfoPlatform *gvir_designer_domain_get_platform(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+ GVirDesignerDomainPrivate *priv = design->priv;
+ return priv->platform;
+}
+
+
+/**
+ * gvir_designer_domain_get_capabilities:
+ * @design: (transfer none): the domain designer instance
+ *
+ * Retrieves the capabilities object associated with the designer
+ * The object should not be modified by the caller.
+ *
+ * Returns: (transfer none): the capabilities
+ */
+GVirConfigCapabilities *gvir_designer_domain_get_capabilities(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+ GVirDesignerDomainPrivate *priv = design->priv;
+ return priv->caps;
+}
+
+
+/**
+ * gvir_designer_domain_get_config:
+ * @design: (transfer none): the domain designer instance
+ *
+ * Retrieves the domain config object associated with the designer
+ * The object may be modified by the caller at will, but should
+ * not be freed.
+ *
+ * Returns: (transfer none): the domain config
+ */
+GVirConfigDomain *gvir_designer_domain_get_config(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+ GVirDesignerDomainPrivate *priv = design->priv;
+ return priv->config;
+}
+
+
+static gchar *
+gvir_designer_domain_get_arch_normalized(const gchar *arch)
+{
+ /* Squash i?86 to i686 */
+ if (g_str_equal(arch, "i386") ||
+ g_str_equal(arch, "i486") ||
+ g_str_equal(arch, "i586") ||
+ g_str_equal(arch, "i686"))
+ return g_strdup("i686");
+
+ /* XXX what about Debian amd64 vs Fedora x86_64 */
+ /* XXX any other arch inconsistencies ? */
+
+ return g_strdup(arch);
+}
+
+
+static gchar *
+gvir_designer_domain_get_arch_native(GVirDesignerDomain *design)
+{
+ GVirDesignerDomainPrivate *priv = design->priv;
+ GVirConfigCapabilitiesHost *host =
+ gvir_config_capabilities_get_host(priv->caps);
+ GVirConfigCapabilitiesCpu *cpu = host ?
+ gvir_config_capabilities_host_get_cpu(host) : NULL;
+ const gchar *arch = cpu ?
+ gvir_config_capabilities_cpu_get_arch(cpu) : NULL;
+
+ if (arch) {
+ return gvir_designer_domain_get_arch_normalized(arch);
+ } else {
+ struct utsname ut;
+ uname(&ut);
+ return gvir_designer_domain_get_arch_normalized(ut.machine);
+ }
+}
+
+
+static GVirConfigCapabilitiesGuest *
+gvir_designer_domain_get_guest(GVirDesignerDomain *design,
+ const gchar *wantarch)
+{
+ GVirDesignerDomainPrivate *priv = design->priv;
+ GList *guests = gvir_config_capabilities_get_guests(priv->caps);
+ GList *tmp = guests;
+ GVirConfigCapabilitiesGuest *ret = NULL;
+
+ while (tmp) {
+ GVirConfigCapabilitiesGuest *guest =
+ GVIR_CONFIG_CAPABILITIES_GUEST(tmp->data);
+ GVirConfigCapabilitiesGuestArch *arch =
+ gvir_config_capabilities_guest_get_arch(guest);
+ GVirConfigDomainOsType guestos =
+ gvir_config_capabilities_guest_get_os_type(guest);
+ const gchar *guestarch =
+ gvir_config_capabilities_guest_arch_get_name(arch);
+
+ if (g_str_equal(guestarch, wantarch) &&
+ (guestos == GVIR_CONFIG_DOMAIN_OS_TYPE_HVM ||
+ guestos == GVIR_CONFIG_DOMAIN_OS_TYPE_LINUX ||
+ guestos == GVIR_CONFIG_DOMAIN_OS_TYPE_XEN ||
+ guestos == GVIR_CONFIG_DOMAIN_OS_TYPE_UML)) {
+ ret = g_object_ref(guest);
+ goto cleanup;
+ }
+
+ tmp = tmp->next;
+ }
+
+cleanup:
+ g_list_foreach(guests, (GFunc)g_object_unref, NULL);
+ g_list_free(guests);
+ return ret;
+}
+
+
+static GVirConfigCapabilitiesGuest *
+gvir_designer_domain_get_guest_full(GVirDesignerDomain *design,
+ const gchar *wantarch,
+ GVirConfigDomainOsType ostype)
+{
+ GVirDesignerDomainPrivate *priv = design->priv;
+ GList *guests = gvir_config_capabilities_get_guests(priv->caps);
+ GList *tmp = guests;
+ GVirConfigCapabilitiesGuest *ret = NULL;
+
+ while (tmp) {
+ GVirConfigCapabilitiesGuest *guest =
+ GVIR_CONFIG_CAPABILITIES_GUEST(tmp->data);
+ GVirConfigCapabilitiesGuestArch *arch =
+ gvir_config_capabilities_guest_get_arch(guest);
+ GVirConfigDomainOsType guestos =
+ gvir_config_capabilities_guest_get_os_type(guest);
+ const gchar *guestarch =
+ gvir_config_capabilities_guest_arch_get_name(arch);
+
+ if (g_str_equal(guestarch, wantarch) &&
+ guestos == ostype) {
+ ret = g_object_ref(guest);
+ goto cleanup;
+ }
+
+ tmp = tmp->next;
+ }
+
+cleanup:
+ g_list_foreach(guests, (GFunc)g_object_unref, NULL);
+ g_list_free(guests);
+ return ret;
+}
+
+
+gboolean gvir_designer_domain_supports_machine(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ gchar *hostarch = gvir_designer_domain_get_arch_native(design);
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest(design, hostarch);
+
+ g_free(hostarch);
+ if (guest) {
+ g_object_unref(guest);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+gboolean gvir_designer_domain_supports_machine_full(GVirDesignerDomain *design,
+ const char *arch,
+ GVirConfigDomainOsType ostype)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, arch, ostype);
+
+ if (guest) {
+ g_object_unref(guest);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean gvir_designer_domain_supports_container(GVirDesignerDomain *design)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ gchar *hostarch = gvir_designer_domain_get_arch_native(design);
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, hostarch,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+
+ g_free(hostarch);
+ if (guest) {
+ g_object_unref(guest);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean gvir_designer_domain_supports_container_full(GVirDesignerDomain *design,
+ const char *arch)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, arch,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+
+ if (guest) {
+ g_object_unref(guest);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static GVirConfigCapabilitiesGuestDomain *
+gvir_designer_domain_best_guest_domain(GVirConfigCapabilitiesGuestArch *arch,
+ GError **error)
+{
+ GList *domains =
+ gvir_config_capabilities_guest_arch_get_domains(arch);
+ GList *tmp = domains;
+ GVirConfigCapabilitiesGuestDomain *ret = NULL;
+
+
+ /* At this time "best" basically means pick KVM first.
+ * Other cleverness might be added later... */
+ while (tmp) {
+ GVirConfigCapabilitiesGuestDomain *dom =
+ GVIR_CONFIG_CAPABILITIES_GUEST_DOMAIN(tmp->data);
+
+ if (gvir_config_capabilities_guest_domain_get_virt_type(dom) ==
+ GVIR_CONFIG_DOMAIN_VIRT_KVM) {
+ ret = g_object_ref(dom);
+ goto cleanup;
+ }
+
+ tmp = tmp->next;
+ }
+
+ if (domains) {
+ GVirConfigCapabilitiesGuestDomain *dom =
+ GVIR_CONFIG_CAPABILITIES_GUEST_DOMAIN(domains->data);
+
+ ret = g_object_ref(dom);
+ goto cleanup;
+ }
+
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find any domain for guest arch %s",
+ gvir_config_capabilities_guest_arch_get_name(arch));
+
+cleanup:
+ g_list_foreach(domains, (GFunc)g_object_unref, NULL);
+ g_list_free(domains);
+ return ret;
+}
+
+
+static gboolean
+gvir_designer_domain_setup_guest(GVirDesignerDomain *design,
+ GVirConfigCapabilitiesGuest *guest,
+ GError **error)
+{
+ GVirDesignerDomainPrivate *priv = design->priv;
+ GVirConfigDomainOs *os = gvir_config_domain_os_new();
+ GVirConfigCapabilitiesGuestArch *arch =
+ gvir_config_capabilities_guest_get_arch(guest);
+ GVirConfigCapabilitiesGuestDomain *domain;
+ gboolean ret = FALSE;
+
+ if (!(domain = gvir_designer_domain_best_guest_domain(arch,
+ error)))
+ goto cleanup;
+
+ gvir_config_domain_os_set_os_type(
+ os,
+ gvir_config_capabilities_guest_get_os_type(guest));
+ gvir_config_domain_os_set_arch(
+ os,
+ gvir_config_capabilities_guest_arch_get_name(arch));
+ gvir_config_domain_set_virt_type(
+ priv->config,
+ gvir_config_capabilities_guest_domain_get_virt_type(domain));
+ gvir_config_domain_set_os(priv->config, os);
+
+ ret = TRUE;
+cleanup:
+ g_object_unref(os);
+ return ret;
+}
+
+
+gboolean gvir_designer_domain_setup_machine(GVirDesignerDomain *design,
+ GError **error)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ gchar *hostarch = gvir_designer_domain_get_arch_native(design);
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest(design, hostarch);
+ gboolean ret = FALSE;
+
+ if (!guest) {
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find machine type for architecture %s",
+ hostarch);
+ goto cleanup;
+ }
+
+ if (!gvir_designer_domain_setup_guest(design, guest, error))
+ goto cleanup;
+
+ ret = TRUE;
+cleanup:
+ if (guest)
+ g_object_unref(guest);
+ g_free(hostarch);
+ return ret;
+}
+
+
+gboolean gvir_designer_domain_setup_machine_full(GVirDesignerDomain *design,
+ const char *arch,
+ GVirConfigDomainOsType ostype,
+ GError **error)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, arch, ostype);
+ gboolean ret = FALSE;
+
+ if (!guest) {
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find machine type for architecture %s and ostype %s",
+ arch, "ostype" /* XXX */);
+ goto cleanup;
+ }
+
+ if (!gvir_designer_domain_setup_guest(design, guest, error))
+ goto cleanup;
+
+ ret = TRUE;
+cleanup:
+ if (guest)
+ g_object_unref(guest);
+ return ret;
+}
+
+
+gboolean gvir_designer_domain_setup_container(GVirDesignerDomain *design,
+ GError **error)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ gchar *hostarch = gvir_designer_domain_get_arch_native(design);
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, hostarch,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+ gboolean ret = FALSE;
+
+ if (!guest) {
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find container type for architecture %s",
+ hostarch);
+ goto cleanup;
+ }
+
+ if (!gvir_designer_domain_setup_guest(design, guest, error))
+ goto cleanup;
+
+ ret = TRUE;
+cleanup:
+ if (guest)
+ g_object_unref(guest);
+ g_free(hostarch);
+ return ret;
+}
+
+
+gboolean gvir_designer_domain_setup_container_full(GVirDesignerDomain *design,
+ const char *arch,
+ GError **error)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), FALSE);
+
+ GVirConfigCapabilitiesGuest *guest =
+ gvir_designer_domain_get_guest_full(design, arch,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+ gboolean ret = FALSE;
+
+ if (!guest) {
+ g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0,
+ "Unable to find container type for architecture %s",
+ arch);
+ goto cleanup;
+ }
+
+ if (!gvir_designer_domain_setup_guest(design, guest, error))
+ goto cleanup;
+
+ ret = TRUE;
+cleanup:
+ if (guest)
+ g_object_unref(guest);
+ return ret;
+}
diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h
new file mode 100644
index 0000000..23b5750
--- /dev/null
+++ b/libvirt-designer/libvirt-designer-domain.h
@@ -0,0 +1,99 @@
+/*
+ * libvirt-designer-domain.h: libvirt domain configuration
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#if !defined(__LIBVIRT_DESIGNER_H__) && !defined(LIBVIRT_DESIGNER_BUILD)
+#error "Only <libvirt-designer/libvirt-designer.h> can be included directly."
+#endif
+
+#ifndef __LIBVIRT_DESIGNER_DOMAIN_H__
+#define __LIBVIRT_DESIGNER_DOMAIN_H__
+
+#include <osinfo/osinfo.h>
+#include <libvirt-gconfig/libvirt-gconfig.h>
+
+G_BEGIN_DECLS
+
+#define GVIR_DESIGNER_TYPE_DOMAIN (gvir_designer_domain_get_type ())
+#define GVIR_DESIGNER_DOMAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVIR_DESIGNER_TYPE_DOMAIN, GVirDesignerDomain))
+#define GVIR_DESIGNER_DOMAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVIR_DESIGNER_TYPE_DOMAIN, GVirDesignerDomainClass))
+#define GVIR_DESIGNER_IS_DOMAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVIR_DESIGNER_TYPE_DOMAIN))
+#define GVIR_DESIGNER_IS_DOMAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVIR_DESIGNER_TYPE_DOMAIN))
+#define GVIR_DESIGNER_DOMAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVIR_DESIGNER_TYPE_DOMAIN, GVirDesignerDomainClass))
+
+typedef struct _GVirDesignerDomain GVirDesignerDomain;
+typedef struct _GVirDesignerDomainPrivate GVirDesignerDomainPrivate;
+typedef struct _GVirDesignerDomainClass GVirDesignerDomainClass;
+
+struct _GVirDesignerDomain
+{
+ GObject parent;
+
+ GVirDesignerDomainPrivate *priv;
+
+ /* Do not add fields to this struct */
+};
+
+struct _GVirDesignerDomainClass
+{
+ GObjectClass parent_class;
+
+ gpointer padding[20];
+};
+
+GType gvir_designer_domain_get_type(void);
+
+GVirDesignerDomain *gvir_designer_domain_new(OsinfoOs *os,
+ OsinfoPlatform *platform,
+ GVirConfigCapabilities *caps);
+
+OsinfoOs *gvir_designer_domain_get_os(GVirDesignerDomain *design);
+OsinfoPlatform *gvir_designer_domain_get_platform(GVirDesignerDomain *design);
+GVirConfigCapabilities *gvir_designer_domain_get_capabilities(GVirDesignerDomain *design);
+GVirConfigDomain *gvir_designer_domain_get_config(GVirDesignerDomain *design);
+
+
+gboolean gvir_designer_domain_supports_machine(GVirDesignerDomain *design);
+gboolean gvir_designer_domain_supports_machine_full(GVirDesignerDomain *design,
+ const char *arch,
+ GVirConfigDomainOsType ostype);
+gboolean gvir_designer_domain_supports_container(GVirDesignerDomain *design);
+gboolean gvir_designer_domain_supports_container_full(GVirDesignerDomain *design,
+ const char *arch);
+
+
+gboolean gvir_designer_domain_setup_machine(GVirDesignerDomain *design,
+ GError **error);
+gboolean gvir_designer_domain_setup_machine_full(GVirDesignerDomain *design,
+ const char *arch,
+ GVirConfigDomainOsType ostype,
+ GError **error);
+
+gboolean gvir_designer_domain_setup_container(GVirDesignerDomain *design,
+ GError **error);
+gboolean gvir_designer_domain_setup_container_full(GVirDesignerDomain *design,
+ const char *arch,
+ GError **error);
+
+
+G_END_DECLS
+
+#endif /* __LIBVIRT_DESIGNER_DOMAIN_H__ */
diff --git a/libvirt-designer/libvirt-designer.h b/libvirt-designer/libvirt-designer.h
index 6608940..567acb5 100644
--- a/libvirt-designer/libvirt-designer.h
+++ b/libvirt-designer/libvirt-designer.h
@@ -29,5 +29,6 @@
/* Local includes */
#include <libvirt-designer/libvirt-designer-main.h>
#include <libvirt-designer/libvirt-designer-enum-types.h>
+#include <libvirt-designer/libvirt-designer-domain.h>
#endif /* __LIBVIRT_DESIGNER_H__ */
diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym
index 3dba6ad..2a56a92 100644
--- a/libvirt-designer/libvirt-designer.sym
+++ b/libvirt-designer/libvirt-designer.sym
@@ -3,6 +3,23 @@ LIBVIRT_DESIGNER_0.0.1 {
gvir_designer_init;
gvir_designer_init_check;
+ gvir_designer_domain_new;
+ gvir_designer_domain_get_type;
+ gvir_designer_domain_get_config;
+ gvir_designer_domain_get_os;
+ gvir_designer_domain_get_platform;
+ gvir_designer_domain_get_capabilities;
+
+ gvir_designer_domain_setup_machine;
+ gvir_designer_domain_setup_machine_full;
+ gvir_designer_domain_setup_container;
+ gvir_designer_domain_setup_container_full;
+
+ gvir_designer_domain_supports_machine;
+ gvir_designer_domain_supports_machine_full;
+ gvir_designer_domain_supports_container;
+ gvir_designer_domain_supports_container_full;
+
local:
*;
};
diff --git a/libvirt-designer/test-designer-domain.c b/libvirt-designer/test-designer-domain.c
new file mode 100644
index 0000000..91fa04d
--- /dev/null
+++ b/libvirt-designer/test-designer-domain.c
@@ -0,0 +1,362 @@
+/*
+ * test-designer-domain.c: libvirt domain configuration test case
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include <config.h>
+
+#include <libvirt-designer/libvirt-designer.h>
+
+static const gchar *capsqemuxml =
+ "<capabilities>"
+ " <host>"
+ " <uuid>b9d70ef8-6756-4b51-8901-f0e65af0dcd8</uuid>"
+ " <cpu>"
+ " <arch>x86_64</arch>"
+ " <model>core2duo</model>"
+ " <vendor>Intel</vendor>"
+ " <topology sockets='1' cores='2' threads='1'/>"
+ " </cpu>"
+ " </host>"
+ " <guest>"
+ " <os_type>hvm</os_type>"
+ " <arch name='i686'>"
+ " <wordsize>32</wordsize>"
+ " <emulator>/usr/bin/qemu-system-x86_64</emulator>"
+ " <machine>pc-1.0</machine>"
+ " <machine canonical='pc-1.0'>pc</machine>"
+ " <domain type='qemu'>"
+ " </domain>"
+ " <domain type='kvm'>"
+ " <emulator>/usr/bin/qemu-kvm</emulator>"
+ " <machine>pc-1.0</machine>"
+ " <machine canonical='pc-1.0'>pc</machine>"
+ " </domain>"
+ " </arch>"
+ " <features>"
+ " <cpuselection/>"
+ " <deviceboot/>"
+ " <pae/>"
+ " <nonpae/>"
+ " <acpi default='on' toggle='yes'/>"
+ " <apic default='on' toggle='no'/>"
+ " </features>"
+ " </guest>"
+ " <guest>"
+ " <os_type>hvm</os_type>"
+ " <arch name='x86_64'>"
+ " <wordsize>64</wordsize>"
+ " <emulator>/usr/bin/qemu-system-x86_64</emulator>"
+ " <machine>pc-1.0</machine>"
+ " <machine canonical='pc-1.0'>pc</machine>"
+ " <domain type='qemu'>"
+ " </domain>"
+ " <domain type='kvm'>"
+ " <emulator>/usr/bin/qemu-kvm</emulator>"
+ " <machine>pc-1.0</machine>"
+ " <machine canonical='pc-1.0'>pc</machine>"
+ " <machine>isapc</machine>"
+ " </domain>"
+ " </arch>"
+ " <features>"
+ " <cpuselection/>"
+ " <deviceboot/>"
+ " <acpi default='on' toggle='yes'/>"
+ " <apic default='on' toggle='no'/>"
+ " </features>"
+ " </guest>"
+ " <guest>"
+ " <os_type>hvm</os_type>"
+ " <arch name='mipsel'>"
+ " <wordsize>32</wordsize>"
+ " <emulator>/usr/bin/qemu-system-mipsel</emulator>"
+ " <machine>malta</machine>"
+ " <domain type='qemu'>"
+ " </domain>"
+ " </arch>"
+ " <features>"
+ " <deviceboot/>"
+ " </features>"
+ " </guest>"
+ "</capabilities>";
+
+static const gchar *capslxcxml =
+ "<capabilities>"
+ " <host>"
+ " <uuid>b9d70ef8-6756-4b51-8901-f0e65af0dcd8</uuid>"
+ " <cpu>"
+ " <arch>x86_64</arch>"
+ " </cpu>"
+ " </host>"
+ " <guest>"
+ " <os_type>exe</os_type>"
+ " <arch name='x86_64'>"
+ " <wordsize>64</wordsize>"
+ " <emulator>/usr/libexec/libvirt_lxc</emulator>"
+ " <domain type='lxc'>"
+ " </domain>"
+ " </arch>"
+ " </guest>"
+ " <guest>"
+ " <os_type>exe</os_type>"
+ " <arch name='i686'>"
+ " <wordsize>32</wordsize>"
+ " <emulator>/usr/libexec/libvirt_lxc</emulator>"
+ " <domain type='lxc'>"
+ " </domain>"
+ " </arch>"
+ " </guest>"
+ "</capabilities>";
+
+
+static void test_domain_machine_setup(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ OsinfoOs *os = osinfo_os_new("http://myoperatingsystem/amazing/4.2");
+ OsinfoPlatform *platform = osinfo_platform_new("http://myhypervisor.org/awesome/6.6.6");
+ GVirConfigCapabilities *caps = gvir_config_capabilities_new_from_xml(capsqemuxml, NULL);
+
+ *design = gvir_designer_domain_new(os, platform, caps);
+
+ g_object_unref(os);
+ g_object_unref(platform);
+ g_object_unref(caps);
+}
+
+
+static void test_domain_container_setup(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ OsinfoOs *os = osinfo_os_new("http://myoperatingsystem/amazing/4.2");
+ OsinfoPlatform *platform = osinfo_platform_new("http://myhypervisor.org/awesome/6.6.6");
+ GVirConfigCapabilities *caps = gvir_config_capabilities_new_from_xml(capslxcxml, NULL);
+
+ *design = gvir_designer_domain_new(os, platform, caps);
+
+ g_object_unref(os);
+ g_object_unref(platform);
+ g_object_unref(caps);
+}
+
+
+static void test_domain_machine_host_arch_run(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ GError *error = NULL;
+ gboolean ret;
+ GVirConfigDomain *config;
+ GVirConfigDomainOs *osconfig;
+ gchar *xml;
+
+ g_assert(gvir_designer_domain_supports_machine(*design));
+
+ ret = gvir_designer_domain_setup_machine(*design, &error);
+ if (!ret) {
+ g_test_message("Failed %s", error->message);
+ g_error_free(error);
+ }
+ g_assert(ret);
+
+ config = gvir_designer_domain_get_config(*design);
+ osconfig = gvir_config_domain_get_os(config);
+
+ xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(config));
+ g_test_message("XML %s", xml);
+ g_free(xml);
+
+ g_assert_cmpint(gvir_config_domain_get_virt_type(config),
+ ==,
+ GVIR_CONFIG_DOMAIN_VIRT_KVM);
+ g_assert_cmpint(gvir_config_domain_os_get_os_type(osconfig),
+ ==,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM);
+ g_assert_cmpstr(gvir_config_domain_os_get_arch(osconfig),
+ ==,
+ "x86_64");
+
+ g_object_unref(osconfig);
+}
+
+static void test_domain_machine_alt_arch_run(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ GError *error = NULL;
+ gboolean ret;
+ GVirConfigDomain *config;
+ GVirConfigDomainOs *osconfig;
+ gchar *xml;
+
+ g_assert(gvir_designer_domain_supports_machine_full(*design,
+ "x86_64",
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM));
+ g_assert(gvir_designer_domain_supports_machine_full(*design,
+ "i686",
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM));
+ g_assert(gvir_designer_domain_supports_machine_full(*design,
+ "mipsel",
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM));
+
+ ret = gvir_designer_domain_setup_machine_full(*design,
+ "mipsel",
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM,
+ &error);
+ if (!ret) {
+ g_test_message("Failed %s", error->message);
+ g_error_free(error);
+ }
+ g_assert(ret);
+
+ config = gvir_designer_domain_get_config(*design);
+ osconfig = gvir_config_domain_get_os(config);
+
+ xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(config));
+ g_test_message("XML %s", xml);
+ g_free(xml);
+
+ g_assert_cmpint(gvir_config_domain_get_virt_type(config),
+ ==,
+ GVIR_CONFIG_DOMAIN_VIRT_QEMU);
+ g_assert_cmpint(gvir_config_domain_os_get_os_type(osconfig),
+ ==,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_HVM);
+ g_assert_cmpstr(gvir_config_domain_os_get_arch(osconfig),
+ ==,
+ "mipsel");
+
+ g_object_unref(osconfig);
+}
+
+static void test_domain_container_host_arch_run(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ GError *error = NULL;
+ gboolean ret;
+ GVirConfigDomain *config;
+ GVirConfigDomainOs *osconfig;
+ gchar *xml;
+
+ g_assert(gvir_designer_domain_supports_container(*design));
+
+ ret = gvir_designer_domain_setup_container(*design, &error);
+ if (!ret) {
+ g_test_message("Failed %s", error->message);
+ g_error_free(error);
+ }
+ g_assert(ret);
+
+ config = gvir_designer_domain_get_config(*design);
+ osconfig = gvir_config_domain_get_os(config);
+
+ xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(config));
+ g_test_message("XML %s", xml);
+ g_free(xml);
+
+ g_assert_cmpint(gvir_config_domain_get_virt_type(config),
+ ==,
+ GVIR_CONFIG_DOMAIN_VIRT_LXC);
+ g_assert_cmpint(gvir_config_domain_os_get_os_type(osconfig),
+ ==,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+ g_assert_cmpstr(gvir_config_domain_os_get_arch(osconfig),
+ ==,
+ "x86_64");
+
+ g_object_unref(osconfig);
+}
+
+static void test_domain_container_alt_arch_run(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ GError *error = NULL;
+ gboolean ret;
+ GVirConfigDomain *config;
+ GVirConfigDomainOs *osconfig;
+ gchar *xml;
+
+ g_assert(gvir_designer_domain_supports_container_full(*design,
+ "i686"));
+
+ g_assert(gvir_designer_domain_supports_container_full(*design,
+ "x86_64"));
+
+ ret = gvir_designer_domain_setup_container_full(*design,
+ "i686",
+ &error);
+ if (!ret) {
+ g_test_message("Failed %s", error->message);
+ g_error_free(error);
+ }
+ g_assert(ret);
+
+ config = gvir_designer_domain_get_config(*design);
+ osconfig = gvir_config_domain_get_os(config);
+
+ xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(config));
+ g_test_message("XML %s", xml);
+ g_free(xml);
+
+ g_assert_cmpint(gvir_config_domain_get_virt_type(config),
+ ==,
+ GVIR_CONFIG_DOMAIN_VIRT_LXC);
+ g_assert_cmpint(gvir_config_domain_os_get_os_type(osconfig),
+ ==,
+ GVIR_CONFIG_DOMAIN_OS_TYPE_EXE);
+ g_assert_cmpstr(gvir_config_domain_os_get_arch(osconfig),
+ ==,
+ "i686");
+
+ g_object_unref(osconfig);
+}
+
+static void test_domain_teardown(GVirDesignerDomain **design, gconstpointer opaque)
+{
+ if (*design)
+ g_object_unref(*design);
+ *design = NULL;
+}
+
+int main(int argc, char **argv)
+{
+ GVirDesignerDomain *domain = NULL;
+
+ if (!gvir_designer_init_check(&argc, &argv, NULL))
+ return EXIT_FAILURE;
+
+ g_test_init(&argc, &argv, NULL);
+ g_test_add("/TestDesignerDomain/MachineHostArch",
+ GVirDesignerDomain *,
+ &domain,
+ test_domain_machine_setup,
+ test_domain_machine_host_arch_run,
+ test_domain_teardown);
+ g_test_add("/TestDesignerDomain/MachineAltArch",
+ GVirDesignerDomain *,
+ &domain,
+ test_domain_machine_setup,
+ test_domain_machine_alt_arch_run,
+ test_domain_teardown);
+ g_test_add("/TestDesignerDomain/ContainerHostArch",
+ GVirDesignerDomain *,
+ &domain,
+ test_domain_container_setup,
+ test_domain_container_host_arch_run,
+ test_domain_teardown);
+ g_test_add("/TestDesignerDomain/ContainerAltArch",
+ GVirDesignerDomain *,
+ &domain,
+ test_domain_container_setup,
+ test_domain_container_alt_arch_run,
+ test_domain_teardown);
+ return g_test_run();
+}