diff options
author | Daniel P. Berrange <berrange@redhat.com> | 2012-07-31 15:26:50 +0100 |
---|---|---|
committer | Daniel P. Berrange <berrange@redhat.com> | 2012-07-31 15:26:50 +0100 |
commit | 804aac46ba4b7a602dd4edd18271815420d98b00 (patch) | |
tree | b9448e2bb9c09bcc87b5203bc9d24636a6a3ebd1 | |
parent | 76baefee6645a8ec92a4c5a009a218b2b516a4d4 (diff) |
Introduce APIs for setting up optimal virt type / os type / arch
-rw-r--r-- | libvirt-designer/Makefile.am | 20 | ||||
-rw-r--r-- | libvirt-designer/libvirt-designer-domain.c | 662 | ||||
-rw-r--r-- | libvirt-designer/libvirt-designer-domain.h | 99 | ||||
-rw-r--r-- | libvirt-designer/libvirt-designer.h | 1 | ||||
-rw-r--r-- | libvirt-designer/libvirt-designer.sym | 17 | ||||
-rw-r--r-- | libvirt-designer/test-designer-domain.c | 362 |
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(); +} |