[libvirt] [libvirt-designer PATCHv2 0/9] Handle more devices in GVirDesignerDomain

This goes on top of v2 of the "Improve disk bus type generation" series. Diff with the previous version is that it's rebased against latest master, and I've reworked "Implement gvir_designer_domain_add_sound()" patch to address danpb's comments (gvir_designer_domain_add_sound() is now a public method that must be called explicitly rather than being implicitly called on domain creation. Christophe

Add various devices/configuration to libvirt XML config when creating the VM. This configuration is generic enough that it should be useful on all created VMs, that's why no public API is added to set them up. However, they are split in several helpers that can easily be exported if needed. What this commit adds is: - clock - sound card - input device (a tablet which will act as a mouse) - a console (Boxes is adding one, not sure if it's required...) For maximum flexibility, we may want to make the last 2 public. I'm undecided on sound card, I don't think it's terribly interesting to configure, but I wouldn't mind exposing this publicly either. In addition to these devices, gvir_designer_domain_setup_guest() now disables power management, and sets the domain to stop on power off/crash, and to restart on reboots. --- libvirt-designer/libvirt-designer-domain.c | 95 ++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 01e48ae..ed47d60 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -314,6 +314,95 @@ end: } +static void gvir_designer_domain_add_clock(GVirDesignerDomain *design) +{ + GVirConfigDomainClock *clock; + GVirConfigDomainTimer *timer; + GVirConfigDomainClockOffset offset; + + clock = gvir_config_domain_clock_new(); + offset = GVIR_CONFIG_DOMAIN_CLOCK_UTC; + if (design->priv->os != NULL) { + const gchar *short_id; + + short_id = osinfo_product_get_short_id(OSINFO_PRODUCT(design->priv->os)); + if (g_str_has_suffix(short_id, "win")) { + offset = GVIR_CONFIG_DOMAIN_CLOCK_LOCALTIME; + } + } + gvir_config_domain_clock_set_offset(clock, offset); + + timer = GVIR_CONFIG_DOMAIN_TIMER(gvir_config_domain_timer_rtc_new()); + gvir_config_domain_timer_set_tick_policy(timer, + GVIR_CONFIG_DOMAIN_TIMER_TICK_POLICY_CATCHUP); + gvir_config_domain_clock_add_timer(clock, timer); + g_object_unref(G_OBJECT(timer)); + + timer = GVIR_CONFIG_DOMAIN_TIMER(gvir_config_domain_timer_pit_new()); + gvir_config_domain_timer_set_tick_policy(timer, + GVIR_CONFIG_DOMAIN_TIMER_TICK_POLICY_DELAY); + gvir_config_domain_clock_add_timer(clock, timer); + g_object_unref(G_OBJECT(timer)); + + gvir_config_domain_set_clock(design->priv->config, clock); + g_object_unref(G_OBJECT(clock)); +} + +static void gvir_designer_domain_add_power_management(GVirDesignerDomain *design) +{ + GVirConfigDomainPowerManagement *pm; + + pm = gvir_config_domain_power_management_new(); + gvir_config_domain_power_management_set_mem_suspend_enabled(pm, FALSE); + gvir_config_domain_power_management_set_disk_suspend_enabled(pm, FALSE); + + gvir_config_domain_set_power_management(design->priv->config, pm); + g_object_unref(G_OBJECT(pm)); +} + +static void gvir_designer_domain_set_lifecycle(GVirDesignerDomain *design) +{ + gvir_config_domain_set_lifecycle(design->priv->config, + GVIR_CONFIG_DOMAIN_LIFECYCLE_ON_POWEROFF, + GVIR_CONFIG_DOMAIN_LIFECYCLE_DESTROY); + gvir_config_domain_set_lifecycle(design->priv->config, + GVIR_CONFIG_DOMAIN_LIFECYCLE_ON_REBOOT, + GVIR_CONFIG_DOMAIN_LIFECYCLE_RESTART); + gvir_config_domain_set_lifecycle(design->priv->config, + GVIR_CONFIG_DOMAIN_LIFECYCLE_ON_CRASH, + GVIR_CONFIG_DOMAIN_LIFECYCLE_DESTROY); +} + +static void gvir_designer_domain_add_console(GVirDesignerDomain *design) +{ + GVirConfigDomainConsole *console; + GVirConfigDomainChardevSourcePty *pty; + + console = gvir_config_domain_console_new(); + pty = gvir_config_domain_chardev_source_pty_new(); + gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(console), + GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(pty)); + g_object_unref(G_OBJECT(pty)); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(console)); + g_object_unref(G_OBJECT(console)); +} + +static void gvir_designer_domain_add_input(GVirDesignerDomain *design) +{ + GVirConfigDomainInput *input; + + input = gvir_config_domain_input_new(); + gvir_config_domain_input_set_device_type(input, + GVIR_CONFIG_DOMAIN_INPUT_DEVICE_TABLET); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(input)); + g_object_unref(G_OBJECT(input)); +} + + static void gvir_designer_domain_init(GVirDesignerDomain *design) { GVirDesignerDomainPrivate *priv; @@ -671,6 +760,12 @@ gvir_designer_domain_setup_guest(GVirDesignerDomain *design, gvir_config_capabilities_guest_domain_get_virt_type(domain)); gvir_config_domain_set_os(priv->config, os); + gvir_designer_domain_add_clock(design); + gvir_designer_domain_add_power_management(design); + gvir_designer_domain_set_lifecycle(design); + gvir_designer_domain_add_console(design); + gvir_designer_domain_add_input(design); + ret = TRUE; cleanup: if (domain != NULL) -- 1.8.1.4

On Thu, Apr 18, 2013 at 06:12:25PM +0200, Christophe Fergeau wrote:
Add various devices/configuration to libvirt XML config when creating the VM. This configuration is generic enough that it should be useful on all created VMs, that's why no public API is added to set them up. However, they are split in several helpers that can easily be exported if needed.
What this commit adds is: - clock - sound card - input device (a tablet which will act as a mouse) - a console (Boxes is adding one, not sure if it's required...)
For maximum flexibility, we may want to make the last 2 public. I'm undecided on sound card, I don't think it's terribly interesting to configure, but I wouldn't mind exposing this publicly either.
Commit message is outdated - you're not adding sound cards anymore. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Thu, Apr 18, 2013 at 05:18:55PM +0100, Daniel P. Berrange wrote:
On Thu, Apr 18, 2013 at 06:12:25PM +0200, Christophe Fergeau wrote:
Add various devices/configuration to libvirt XML config when creating the VM. This configuration is generic enough that it should be useful on all created VMs, that's why no public API is added to set them up. However, they are split in several helpers that can easily be exported if needed.
What this commit adds is: - clock - sound card - input device (a tablet which will act as a mouse) - a console (Boxes is adding one, not sure if it's required...)
For maximum flexibility, we may want to make the last 2 public. I'm undecided on sound card, I don't think it's terribly interesting to configure, but I wouldn't mind exposing this publicly either.
Commit message is outdated - you're not adding sound cards anymore.
Thanks, I've changed it to: Improve VM skeleton created by gvir_designer_domain_setup_guest() Add various devices/configuration to libvirt XML config when creating the VM. This configuration is generic enough that it should be useful on all created VMs, that's why no public API is added to set them up. However, they are split in several helpers that can easily be exported if needed. What this commit adds is: - clock - input device (a tablet which will act as a mouse) - a console (Boxes is adding one, not sure if it's required...) For maximum flexibility, we may want to let applications decide whether they want a console or not. In addition to these devices, gvir_designer_domain_setup_guest() now disables power management, and sets the domain to stop on power off/crash, and to restart on reboots. Christophe

--- examples/virtxml.c | 3 + libvirt-designer/libvirt-designer-domain.c | 131 +++++++++++++++++++++++++++++ libvirt-designer/libvirt-designer-domain.h | 2 + libvirt-designer/libvirt-designer.sym | 1 + 4 files changed, 137 insertions(+) diff --git a/examples/virtxml.c b/examples/virtxml.c index 6fb0551..d127406 100644 --- a/examples/virtxml.c +++ b/examples/virtxml.c @@ -642,6 +642,9 @@ main(int argc, char *argv[]) gvir_designer_domain_setup_machine(domain, &error); CHECK_ERROR; + g_object_unref(gvir_designer_domain_add_sound(domain, &error)); + CHECK_ERROR; + if (arch_str) { gvir_designer_domain_setup_container_full(domain, arch_str, &error); CHECK_ERROR; diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index ed47d60..c5105cd 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -389,6 +389,7 @@ static void gvir_designer_domain_add_console(GVirDesignerDomain *design) g_object_unref(G_OBJECT(console)); } + static void gvir_designer_domain_add_input(GVirDesignerDomain *design) { GVirConfigDomainInput *input; @@ -933,6 +934,136 @@ cleanup: } +static OsinfoDevice * +gvir_designer_domain_get_preferred_soundcard(GVirDesignerDomain *design, + GError **error) +{ + OsinfoDevice *device = NULL; + OsinfoDeviceLink *dev_link; + + dev_link = gvir_designer_domain_get_preferred_device(design, + "audio", + error); + if (dev_link == NULL) + goto cleanup; + + device = osinfo_devicelink_get_target(dev_link); + +cleanup: + if (dev_link != NULL) + g_object_unref(dev_link); + + return device; +} + +static OsinfoDeviceList * +gvir_designer_domain_get_fallback_devices(GVirDesignerDomain *design, + const char *class, + GError **error) +{ + OsinfoDeviceList *devices = NULL; + OsinfoFilter *filter; + + filter = osinfo_filter_new(); + osinfo_filter_add_constraint(filter, OSINFO_DEVICE_PROP_CLASS, class); + devices = gvir_designer_domain_get_supported_devices(design, filter); + g_object_unref(G_OBJECT(filter)); + + if ((devices == NULL) || + (osinfo_list_get_length(OSINFO_LIST(devices)) == 0)) { + goto cleanup; + } + + return devices; + +cleanup: + if (devices != NULL) + g_object_unref(devices); + + return NULL; +} + + +static OsinfoDevice * +gvir_designer_domain_get_fallback_soundcard(GVirDesignerDomain *domain, + GError **error) +{ + OsinfoEntity *dev = NULL; + OsinfoDeviceList *devices = NULL; + + devices = gvir_designer_domain_get_fallback_devices(domain, "audio", error); + if (devices == NULL) + goto cleanup; + + dev = osinfo_list_get_nth(OSINFO_LIST(devices), 0); + g_object_ref(G_OBJECT(dev)); + +cleanup: + if (devices != NULL) + g_object_unref(G_OBJECT(devices)); + + return OSINFO_DEVICE(dev); +} + + +static GVirConfigDomainSoundModel +gvir_designer_sound_model_from_soundcard(OsinfoDevice *soundcard) +{ + const char *name; + + name = osinfo_device_get_name(soundcard); + if (g_strcmp0(name, "ac97") == 0) { + return GVIR_CONFIG_DOMAIN_SOUND_MODEL_AC97; + } else if (g_strcmp0(name, "ich6") == 0) { + return GVIR_CONFIG_DOMAIN_SOUND_MODEL_ICH6; + } else if (g_strcmp0(name, "es1370") == 0) { + return GVIR_CONFIG_DOMAIN_SOUND_MODEL_ES1370; + } else if (g_strcmp0(name, "sb16") == 0) { + return GVIR_CONFIG_DOMAIN_SOUND_MODEL_SB16; + } else { + g_warning("Unknown soundcard %s, falling back to PC speaker", name); + return GVIR_CONFIG_DOMAIN_SOUND_MODEL_PCSPK; + } +} + + +/** + * gvir_designer_domain_add_sound: + * @design: (transfer none): the domain designer instance + * @error: return location for a #GError, or NULL + * + * Add a new soundcard to the domain. + * + * Returns: (transfer full): the pointer to the new soundcard. + * If something fails NULL is returned and @error is set. + */ +GVirConfigDomainSound * +gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error) +{ + GVirConfigDomainSound *sound; + OsinfoDevice *soundcard; + GVirConfigDomainSoundModel model; + + g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL); + + soundcard = gvir_designer_domain_get_preferred_soundcard(design, NULL); + if (soundcard == NULL) + soundcard = gvir_designer_domain_get_fallback_soundcard(design, NULL); + + if (soundcard == NULL) + return NULL; + + sound = gvir_config_domain_sound_new(); + model = gvir_designer_sound_model_from_soundcard(soundcard); + gvir_config_domain_sound_set_model(sound, model); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(sound)); + + return sound; +} + + static gchar * gvir_designer_domain_next_disk_target(GVirDesignerDomain *design, GVirConfigDomainDiskBus bus) diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h index c7b0e5c..c0d06e8 100644 --- a/libvirt-designer/libvirt-designer-domain.h +++ b/libvirt-designer/libvirt-designer-domain.h @@ -125,6 +125,8 @@ GVirConfigDomainInterface *gvir_designer_domain_add_interface_network(GVirDesign const char *network, GError **error); +GVirConfigDomainSound *gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error); + gboolean gvir_designer_domain_setup_resources(GVirDesignerDomain *design, GVirDesignerDomainResources req, GError **error); diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym index 1dab447..5edc3d1 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -20,6 +20,7 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_add_floppy_file; gvir_designer_domain_add_floppy_device; gvir_designer_domain_add_interface_network; + gvir_designer_domain_add_sound; gvir_designer_domain_setup_resources; gvir_designer_domain_resources_get_type; -- 1.8.1.4

--- libvirt-designer/libvirt-designer-domain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index c5105cd..0b70dfb 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -1,7 +1,7 @@ /* * libvirt-designer-domain.c: libvirt domain configuration * - * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2012-2013 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 @@ -20,6 +20,7 @@ * Authors: * Daniel P. Berrange <berrange@redhat.com> * Michal Privoznik <mprivozn@redhat.com> + * Christophe Fergeau <cfergeau@redhat.com> */ #include <config.h> -- 1.8.1.4

This allows to choose between SPICE, VNC or a local display, which will go through SDL or 'desktop' depending on the hypervisor. --- configure.ac | 2 +- examples/virtxml.c | 4 ++ libvirt-designer/libvirt-designer-domain.c | 111 +++++++++++++++++++++++++++++ libvirt-designer/libvirt-designer-domain.h | 10 +++ libvirt-designer/libvirt-designer.sym | 2 + 5 files changed, 128 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f03e36d..3e9ce44 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_CANONICAL_HOST AM_SILENT_RULES([yes]) LIBOSINFO_REQUIRED=0.2.6 -LIBVIRT_GCONFIG_REQUIRED=0.0.9 +LIBVIRT_GCONFIG_REQUIRED=0.1.7 LIBVIRT_GOBJECT_REQUIRED=0.1.3 GOBJECT_INTROSPECTION_REQUIRED=0.10.8 diff --git a/examples/virtxml.c b/examples/virtxml.c index d127406..46fb551 100644 --- a/examples/virtxml.c +++ b/examples/virtxml.c @@ -641,6 +641,10 @@ main(int argc, char *argv[]) gvir_designer_domain_setup_machine(domain, &error); CHECK_ERROR; + g_object_unref(gvir_designer_domain_add_graphics(domain, + GVIR_DESIGNER_DOMAIN_GRAPHICS_SPICE, + &error)); + CHECK_ERROR; g_object_unref(gvir_designer_domain_add_sound(domain, &error)); CHECK_ERROR; diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 0b70dfb..2b0ddca 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -349,6 +349,117 @@ static void gvir_designer_domain_add_clock(GVirDesignerDomain *design) g_object_unref(G_OBJECT(clock)); } + +static GVirConfigDomainGraphics * +gvir_designer_domain_create_graphics_desktop(GVirDesignerDomain *design, + GError **error) +{ + int virt_type; + + virt_type = gvir_config_domain_get_virt_type(design->priv->config); + + switch (virt_type) { + case GVIR_CONFIG_DOMAIN_VIRT_QEMU: + case GVIR_CONFIG_DOMAIN_VIRT_KQEMU: + case GVIR_CONFIG_DOMAIN_VIRT_KVM: { + GVirConfigDomainGraphicsSdl *sdl; + sdl = gvir_config_domain_graphics_sdl_new(); + return GVIR_CONFIG_DOMAIN_GRAPHICS(sdl); + } + case GVIR_CONFIG_DOMAIN_VIRT_VBOX: { + GVirConfigDomainGraphicsDesktop *desktop; + desktop = gvir_config_domain_graphics_desktop_new(); + return GVIR_CONFIG_DOMAIN_GRAPHICS(desktop); + } + default: + g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0, + "Virt type %d does not support this graphics output", + virt_type); + return NULL; + } +} + +/** + * gvir_designer_domain_add_graphics: + * @design: (transfer none): the domain designer instance + * @error: return location for a #GError, or NULL + * + * Add a new graphical framebuffer to @design. This allows + * to see what the VM displays. + * Remote display protocols will only be listening on localhost, and the + * port will be automatically allocated when the VM starts (usually + * starting at 5900). You can manipulate further the returned + * #GVirConfigDomainGraphics if you want a different behaviour. + * When setting up a SPICE display, the SPICE agent channel will be + * automatically added to the VM if it's supported and not already + * present. + * + * Returns: (transfer full): the pointer to the new graphical framebuffer + * configuration object. + */ +GVirConfigDomainGraphics * +gvir_designer_domain_add_graphics(GVirDesignerDomain *design, + GVirDesignerDomainGraphics type, + GError **error) +{ + GVirConfigDomainGraphics *graphics; + + g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL); + g_return_val_if_fail(!error_is_set(error), NULL); + + switch (type) { + case GVIR_DESIGNER_DOMAIN_GRAPHICS_DESKTOP: { + graphics = gvir_designer_domain_create_graphics_desktop(design, error); + if (graphics == NULL) + return NULL; + } + + case GVIR_DESIGNER_DOMAIN_GRAPHICS_RDP: { + GVirConfigDomainGraphicsRdp *rdp; + + rdp = gvir_config_domain_graphics_rdp_new(); + gvir_config_domain_graphics_rdp_set_autoport(rdp, TRUE); + graphics = GVIR_CONFIG_DOMAIN_GRAPHICS(rdp); + + break; + } + + case GVIR_DESIGNER_DOMAIN_GRAPHICS_SPICE: { + GVirConfigDomainGraphicsSpice *spice; + + spice = gvir_config_domain_graphics_spice_new(); + gvir_config_domain_graphics_spice_set_autoport(spice, TRUE); + /* FIXME: Should only be done for local domains */ + gvir_config_domain_graphics_spice_set_image_compression(spice, + GVIR_CONFIG_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF); + graphics = GVIR_CONFIG_DOMAIN_GRAPHICS(spice); + + break; + } + + case GVIR_DESIGNER_DOMAIN_GRAPHICS_VNC: { + GVirConfigDomainGraphicsVnc *vnc; + + vnc = gvir_config_domain_graphics_vnc_new(); + gvir_config_domain_graphics_vnc_set_autoport(vnc, TRUE); + graphics = GVIR_CONFIG_DOMAIN_GRAPHICS(vnc); + + break; + } + + default: + g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0, + "Unknown graphics type: %d", type); + g_return_val_if_reached(NULL); + } + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(graphics)); + + return graphics; +} + + static void gvir_designer_domain_add_power_management(GVirDesignerDomain *design) { GVirConfigDomainPowerManagement *pm; diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h index c0d06e8..1399bd4 100644 --- a/libvirt-designer/libvirt-designer-domain.h +++ b/libvirt-designer/libvirt-designer-domain.h @@ -44,6 +44,13 @@ typedef enum { GVIR_DESIGNER_DOMAIN_RESOURCES_RECOMMENDED, } GVirDesignerDomainResources; +typedef enum { + GVIR_DESIGNER_DOMAIN_GRAPHICS_DESKTOP, + GVIR_DESIGNER_DOMAIN_GRAPHICS_RDP, + GVIR_DESIGNER_DOMAIN_GRAPHICS_SPICE, + GVIR_DESIGNER_DOMAIN_GRAPHICS_VNC, +} GVirDesignerDomainGraphics; + typedef struct _GVirDesignerDomain GVirDesignerDomain; typedef struct _GVirDesignerDomainPrivate GVirDesignerDomainPrivate; typedef struct _GVirDesignerDomainClass GVirDesignerDomainClass; @@ -125,6 +132,9 @@ GVirConfigDomainInterface *gvir_designer_domain_add_interface_network(GVirDesign const char *network, GError **error); +GVirConfigDomainGraphics *gvir_designer_domain_add_graphics(GVirDesignerDomain *design, + GVirDesignerDomainGraphics type, + GError **error); GVirConfigDomainSound *gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error); gboolean gvir_designer_domain_setup_resources(GVirDesignerDomain *design, diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym index 5edc3d1..eb8419e 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -5,6 +5,7 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_new; gvir_designer_domain_get_type; + gvir_designer_domain_graphics_get_type; gvir_designer_domain_get_config; gvir_designer_domain_get_os; gvir_designer_domain_get_platform; @@ -19,6 +20,7 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_add_disk_device; gvir_designer_domain_add_floppy_file; gvir_designer_domain_add_floppy_device; + gvir_designer_domain_add_graphics; gvir_designer_domain_add_interface_network; gvir_designer_domain_add_sound; gvir_designer_domain_setup_resources; -- 1.8.1.4

When the user sets up the graphical framebuffer to use SPICE, we now add automatically the SPICE agent channel if it's not present already. --- libvirt-designer/libvirt-designer-domain.c | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 2b0ddca..0757527 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -70,6 +70,7 @@ static gboolean error_is_set(GError **error) return ((error != NULL) && (*error != NULL)); } +static const char GVIR_DESIGNER_SPICE_CHANNEL_NAME[] = "com.redhat.spice.0"; static const char GVIR_DESIGNER_VIRTIO_BLOCK_DEVICE_ID[] = "http://pciids.sourceforge.net/v2.2/pci.ids/1af4/1001"; enum { @@ -315,6 +316,29 @@ end: } +static GList * +gvir_designer_domain_get_device_by_type(GVirDesignerDomain *design, GType type) +{ + GList *devices; + GList *it; + GList *matched_devices = NULL; + + devices = gvir_config_domain_get_devices(design->priv->config); + for (it = devices; it != NULL; it = it->next) { + GType device_type = G_OBJECT_TYPE(it->data); + + if (g_type_is_a(device_type, type)) { + matched_devices = g_list_prepend(matched_devices, + g_object_ref(G_OBJECT(it->data))); + } + + } + g_list_free_full(devices, g_object_unref); + + return g_list_reverse(matched_devices); +} + + static void gvir_designer_domain_add_clock(GVirDesignerDomain *design) { GVirConfigDomainClock *clock; @@ -350,6 +374,65 @@ static void gvir_designer_domain_add_clock(GVirDesignerDomain *design) } +static gboolean +gvir_designer_domain_has_spice_channel(GVirDesignerDomain *design) +{ + GList *devices; + GList *it; + gboolean has_spice = FALSE; + + devices = gvir_designer_domain_get_device_by_type(design, + GVIR_CONFIG_TYPE_DOMAIN_CHANNEL); + for (it = devices; it != NULL; it = it->next) { + GVirConfigDomainChannel *channel; + const char *target_name; + channel = GVIR_CONFIG_DOMAIN_CHANNEL(it->data); + target_name = gvir_config_domain_channel_get_target_name(channel); + if (g_strcmp0(target_name, GVIR_DESIGNER_SPICE_CHANNEL_NAME) == 0) { + /* FIXME could do more sanity checks (check if the channel + * source has the 'spicevmc' type) + */ + GVirConfigDomainChannelTargetType target_type; + target_type = gvir_config_domain_channel_get_target_type(channel); + if (target_type == GVIR_CONFIG_DOMAIN_CHANNEL_TARGET_VIRTIO) { + has_spice = TRUE; + } else { + g_critical("Inconsistent SPICE channel, target type is wrong (%d)", + target_type); + has_spice = FALSE; + } + + break; + } + } + g_list_free_full(devices, g_object_unref); + + return has_spice; +} + + +static void gvir_designer_domain_add_spice_channel(GVirDesignerDomain *design) +{ + /* FIXME: error out if there is no support for the vioserial device */ + GVirConfigDomainChannel *channel; + GVirConfigDomainChardevSourceSpiceVmc *vmc; + + channel = gvir_config_domain_channel_new(); + gvir_config_domain_channel_set_target_type(channel, + GVIR_CONFIG_DOMAIN_CHANNEL_TARGET_VIRTIO); + gvir_config_domain_channel_set_target_name(channel, + GVIR_DESIGNER_SPICE_CHANNEL_NAME); + vmc = gvir_config_domain_chardev_source_spicevmc_new(); + gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(channel), + GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(vmc)); + g_object_unref(G_OBJECT(vmc)); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(channel)); + g_object_unref(G_OBJECT(channel)); +} + + static GVirConfigDomainGraphics * gvir_designer_domain_create_graphics_desktop(GVirDesignerDomain *design, GError **error) @@ -433,6 +516,8 @@ gvir_designer_domain_add_graphics(GVirDesignerDomain *design, gvir_config_domain_graphics_spice_set_image_compression(spice, GVIR_CONFIG_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF); graphics = GVIR_CONFIG_DOMAIN_GRAPHICS(spice); + if (!gvir_designer_domain_has_spice_channel(design)) + gvir_designer_domain_add_spice_channel(design); break; } -- 1.8.1.4

This makes use of the new gvir_designer_domain_get_supported_devices() method. --- libvirt-designer/libvirt-designer-domain.c | 42 +++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 0757527..1a622bf 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -71,6 +71,7 @@ static gboolean error_is_set(GError **error) } static const char GVIR_DESIGNER_SPICE_CHANNEL_NAME[] = "com.redhat.spice.0"; +static const char GVIR_DESIGNER_SPICE_CHANNEL_DEVICE_ID[] = "http://pciids.sourceforge.net/v2.2/pci.ids/1af4/1003"; static const char GVIR_DESIGNER_VIRTIO_BLOCK_DEVICE_ID[] = "http://pciids.sourceforge.net/v2.2/pci.ids/1af4/1001"; enum { @@ -411,12 +412,45 @@ gvir_designer_domain_has_spice_channel(GVirDesignerDomain *design) } -static void gvir_designer_domain_add_spice_channel(GVirDesignerDomain *design) +static gboolean +gvir_designer_domain_supports_spice_channel(GVirDesignerDomain *design) +{ + OsinfoDeviceList *devices; + OsinfoFilter *filter; + gboolean vioserial_found = FALSE; + + filter = osinfo_filter_new(); + osinfo_filter_add_constraint(filter, + OSINFO_ENTITY_PROP_ID, + GVIR_DESIGNER_SPICE_CHANNEL_DEVICE_ID); + devices = gvir_designer_domain_get_supported_devices(design, filter); + if (devices) { + g_warn_if_fail(osinfo_list_get_length(OSINFO_LIST(devices)) <= 1); + if (osinfo_list_get_length(OSINFO_LIST(devices)) >= 1) + vioserial_found = TRUE; + g_object_unref(G_OBJECT(devices)); + } + if (filter) + g_object_unref(G_OBJECT(filter)); + + return vioserial_found; +} + + +static gboolean gvir_designer_domain_add_spice_channel(GVirDesignerDomain *design, + GError **error) { - /* FIXME: error out if there is no support for the vioserial device */ GVirConfigDomainChannel *channel; GVirConfigDomainChardevSourceSpiceVmc *vmc; + if (!gvir_designer_domain_supports_spice_channel(design)) { + g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0, + "OS and/or hypervisor don't support virtio-serial" + " which is required by the SPICE channel"); + g_debug("SPICE channel not supported"); + return FALSE; + } + channel = gvir_config_domain_channel_new(); gvir_config_domain_channel_set_target_type(channel, GVIR_CONFIG_DOMAIN_CHANNEL_TARGET_VIRTIO); @@ -430,6 +464,8 @@ static void gvir_designer_domain_add_spice_channel(GVirDesignerDomain *design) gvir_config_domain_add_device(design->priv->config, GVIR_CONFIG_DOMAIN_DEVICE(channel)); g_object_unref(G_OBJECT(channel)); + + return TRUE; } @@ -517,7 +553,7 @@ gvir_designer_domain_add_graphics(GVirDesignerDomain *design, GVIR_CONFIG_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF); graphics = GVIR_CONFIG_DOMAIN_GRAPHICS(spice); if (!gvir_designer_domain_has_spice_channel(design)) - gvir_designer_domain_add_spice_channel(design); + gvir_designer_domain_add_spice_channel(design, NULL); break; } -- 1.8.1.4

This will add an USB redirection channel to the VM. This can be called multiple times to redirect several USB devices at once. This will also adds the needed controllers if they are not already present in the VM. The current code has 2 shortcomings: - USB redirection is only supported with SPICE, but this is not checked for - the USB controller added to the VM are hardcoded, no check if they are supported by the OS, hypervisor, ... --- examples/virtxml.c | 5 ++ libvirt-designer/libvirt-designer-domain.c | 117 +++++++++++++++++++++++++++++ libvirt-designer/libvirt-designer-domain.h | 1 + libvirt-designer/libvirt-designer.sym | 2 + 4 files changed, 125 insertions(+) diff --git a/examples/virtxml.c b/examples/virtxml.c index 46fb551..bd3bfb3 100644 --- a/examples/virtxml.c +++ b/examples/virtxml.c @@ -566,6 +566,7 @@ main(int argc, char *argv[]) static char *resources_str = NULL; GVirDesignerDomainResources resources; GOptionContext *context = NULL; + unsigned int i; static GOptionEntry entries[] = { @@ -645,6 +646,10 @@ main(int argc, char *argv[]) GVIR_DESIGNER_DOMAIN_GRAPHICS_SPICE, &error)); CHECK_ERROR; + for (i = 0; i < 4; i++) { + g_object_unref(gvir_designer_domain_add_usb_redir(domain, &error)); + CHECK_ERROR; + } g_object_unref(gvir_designer_domain_add_sound(domain, &error)); CHECK_ERROR; diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 1a622bf..e6db016 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -581,6 +581,123 @@ gvir_designer_domain_add_graphics(GVirDesignerDomain *design, } +static gboolean +gvir_designer_domain_supports_usb(GVirDesignerDomain *design) +{ + GList *devices; + devices = gvir_designer_domain_get_device_by_type(design, + GVIR_CONFIG_TYPE_DOMAIN_CONTROLLER_USB); + g_list_free_full(devices, g_object_unref); + + return (devices != NULL); +} + + +static GVirConfigDomainControllerUsb * +gvir_designer_domain_create_usb_controller(GVirDesignerDomain *design, + GVirConfigDomainControllerUsbModel model, + guint indx, + GVirConfigDomainControllerUsb *master, + guint start_port) +{ + GVirConfigDomainControllerUsb *controller; + + controller = gvir_config_domain_controller_usb_new(); + gvir_config_domain_controller_usb_set_model(controller, model); + gvir_config_domain_controller_set_index(GVIR_CONFIG_DOMAIN_CONTROLLER(controller), indx); + if (master) + gvir_config_domain_controller_usb_set_master(controller, master, start_port); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(controller)); + + return controller; +} + + +static void +gvir_designer_domain_add_usb_controllers(GVirDesignerDomain *design) +{ + GVirConfigDomainControllerUsb *master; + GVirConfigDomainControllerUsb *controller; + + g_debug("Adding USB controllers"); + + master = gvir_designer_domain_create_usb_controller(design, + GVIR_CONFIG_DOMAIN_CONTROLLER_USB_MODEL_ICH9_EHCI1, + 0, + NULL, + 0); + controller = gvir_designer_domain_create_usb_controller(design, + GVIR_CONFIG_DOMAIN_CONTROLLER_USB_MODEL_ICH9_UHCI1, + 0, + master, + 0); + g_object_unref(G_OBJECT(controller)); + controller = gvir_designer_domain_create_usb_controller(design, + GVIR_CONFIG_DOMAIN_CONTROLLER_USB_MODEL_ICH9_UHCI2, + 0, + master, + 2); + g_object_unref(G_OBJECT(controller)); + controller = gvir_designer_domain_create_usb_controller(design, + GVIR_CONFIG_DOMAIN_CONTROLLER_USB_MODEL_ICH9_UHCI3, + 0, + master, + 4); + g_object_unref(G_OBJECT(controller)); + g_object_unref(G_OBJECT(master)); +} + + +/** + * gvir_designer_domain_add_usb_redir: + * @design: (transfer none): the domain designer instance + * @error: return location for a #GError, or NULL + * + * Add a new usb redirection channel into @design. This allows to redirect + * an USB device from the SPICE client to the guest. One USB device + * can be redirected per redirection channel, this function can + * be called multiple times if you need to redirect multiple devices + * simultaneously. An USB2 EHCI controller and USB1 UHCI controllers + * will be automatically added to @design if @design does not have + * USB controllers yet. + * + * Returns: (transfer full): the pointer to the new USB redir channel + */ +GVirConfigDomainRedirdev * +gvir_designer_domain_add_usb_redir(GVirDesignerDomain *design, GError **error) +{ + /* FIXME: check if OS/hypervisor support USB + * check if SPICE is being used + */ + GVirConfigDomainRedirdev *redirdev; + GVirConfigDomainChardevSourceSpiceVmc *vmc; + + g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL); + g_return_val_if_fail(!error_is_set(error), NULL); + + redirdev = gvir_config_domain_redirdev_new(); + gvir_config_domain_redirdev_set_bus(redirdev, + GVIR_CONFIG_DOMAIN_REDIRDEV_BUS_USB); + vmc = gvir_config_domain_chardev_source_spicevmc_new(); + gvir_config_domain_chardev_set_source(GVIR_CONFIG_DOMAIN_CHARDEV(redirdev), + GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(vmc)); + g_object_unref(G_OBJECT(vmc)); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(redirdev)); + + if (!gvir_designer_domain_supports_usb(design)) { + gvir_designer_domain_add_usb_controllers(design); + } else { + g_debug("USB controllers are already present"); + } + + return redirdev; +} + + static void gvir_designer_domain_add_power_management(GVirDesignerDomain *design) { GVirConfigDomainPowerManagement *pm; diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h index 1399bd4..981fd2e 100644 --- a/libvirt-designer/libvirt-designer-domain.h +++ b/libvirt-designer/libvirt-designer-domain.h @@ -136,6 +136,7 @@ GVirConfigDomainGraphics *gvir_designer_domain_add_graphics(GVirDesignerDomain * GVirDesignerDomainGraphics type, GError **error); GVirConfigDomainSound *gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error); +GVirConfigDomainRedirdev *gvir_designer_domain_add_usb_redir(GVirDesignerDomain *design, GError **error); gboolean gvir_designer_domain_setup_resources(GVirDesignerDomain *design, GVirDesignerDomainResources req, diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym index eb8419e..15faac1 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -23,6 +23,8 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_add_graphics; gvir_designer_domain_add_interface_network; gvir_designer_domain_add_sound; + gvir_designer_domain_add_usb_redir; + gvir_designer_domain_setup_resources; gvir_designer_domain_resources_get_type; -- 1.8.1.4

This setups smartcard redirection to the guest. I'm not yet fully sure what users could want to tweak there (there are various ways of setting up the smartcard redirection), so this code may need to be made more flexible. The current code is also not checking whether the hypervisor supports this kind of redirection or not. --- examples/virtxml.c | 2 ++ libvirt-designer/libvirt-designer-domain.c | 36 ++++++++++++++++++++++++++++++ libvirt-designer/libvirt-designer-domain.h | 1 + libvirt-designer/libvirt-designer.sym | 1 + 4 files changed, 40 insertions(+) diff --git a/examples/virtxml.c b/examples/virtxml.c index bd3bfb3..941c9a9 100644 --- a/examples/virtxml.c +++ b/examples/virtxml.c @@ -650,6 +650,8 @@ main(int argc, char *argv[]) g_object_unref(gvir_designer_domain_add_usb_redir(domain, &error)); CHECK_ERROR; } + g_object_unref(gvir_designer_domain_add_smartcard(domain, &error)); + CHECK_ERROR; g_object_unref(gvir_designer_domain_add_sound(domain, &error)); CHECK_ERROR; diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index e6db016..7aec002 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -698,6 +698,42 @@ gvir_designer_domain_add_usb_redir(GVirDesignerDomain *design, GError **error) } +/** + * gvir_designer_domain_add_smartcard: + * @design: (transfer none): the domain designer instance + * @error: return location for a #GError, or NULL + * + * Add a new virtual smartcard reader to @design. This will allow to + * share a smartcard reader between the guest and the host. + * + * Returns: (transfer full): the pointer to the new smartcard device + */ +GVirConfigDomainSmartcard * +gvir_designer_domain_add_smartcard(GVirDesignerDomain *design, GError **error) +{ + /* FIXME: check if OS/hypervisor support smartcard, might need + * libosinfo improvements + */ + GVirConfigDomainSmartcardPassthrough *smartcard; + GVirConfigDomainChardevSourceSpiceVmc *vmc; + GVirConfigDomainChardevSource *source; + + g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL); + g_return_val_if_fail(!error_is_set(error), NULL); + + smartcard = gvir_config_domain_smartcard_passthrough_new(); + vmc = gvir_config_domain_chardev_source_spicevmc_new(); + source = GVIR_CONFIG_DOMAIN_CHARDEV_SOURCE(vmc); + gvir_config_domain_smartcard_passthrough_set_source(smartcard, source); + g_object_unref(G_OBJECT(vmc)); + + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(smartcard)); + + return GVIR_CONFIG_DOMAIN_SMARTCARD(smartcard); +} + + static void gvir_designer_domain_add_power_management(GVirDesignerDomain *design) { GVirConfigDomainPowerManagement *pm; diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h index 981fd2e..643e3bf 100644 --- a/libvirt-designer/libvirt-designer-domain.h +++ b/libvirt-designer/libvirt-designer-domain.h @@ -135,6 +135,7 @@ GVirConfigDomainInterface *gvir_designer_domain_add_interface_network(GVirDesign GVirConfigDomainGraphics *gvir_designer_domain_add_graphics(GVirDesignerDomain *design, GVirDesignerDomainGraphics type, GError **error); +GVirConfigDomainSmartcard *gvir_designer_domain_add_smartcard(GVirDesignerDomain *design, GError **error); GVirConfigDomainSound *gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error); GVirConfigDomainRedirdev *gvir_designer_domain_add_usb_redir(GVirDesignerDomain *design, GError **error); diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym index 15faac1..91c70f4 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -22,6 +22,7 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_add_floppy_device; gvir_designer_domain_add_graphics; gvir_designer_domain_add_interface_network; + gvir_designer_domain_add_smartcard; gvir_designer_domain_add_sound; gvir_designer_domain_add_usb_redir; -- 1.8.1.4

This takes into account the devices specified by the deployment, if this fails, consider the intersection of devices supported by the OS and by the platform, and if this still fails, falls back to a hardcoded hypervisor type -> video model mapping. --- examples/virtxml.c | 2 + libvirt-designer/libvirt-designer-domain.c | 172 ++++++++++++++++++++++++++++- libvirt-designer/libvirt-designer-domain.h | 2 + libvirt-designer/libvirt-designer.sym | 1 + 4 files changed, 176 insertions(+), 1 deletion(-) diff --git a/examples/virtxml.c b/examples/virtxml.c index 941c9a9..170795b 100644 --- a/examples/virtxml.c +++ b/examples/virtxml.c @@ -652,6 +652,8 @@ main(int argc, char *argv[]) } g_object_unref(gvir_designer_domain_add_smartcard(domain, &error)); CHECK_ERROR; + g_object_unref(gvir_designer_domain_add_video(domain, &error)); + CHECK_ERROR; g_object_unref(gvir_designer_domain_add_sound(domain, &error)); CHECK_ERROR; diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 7aec002..73dbc8d 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -1153,7 +1153,6 @@ gvir_designer_domain_setup_guest(GVirDesignerDomain *design, gvir_designer_domain_add_console(design); gvir_designer_domain_add_input(design); - ret = TRUE; cleanup: if (domain != NULL) g_object_unref(domain); @@ -1902,6 +1901,177 @@ gvir_designer_domain_add_interface_network(GVirDesignerDomain *design, return ret; } +static GVirConfigDomainVideoModel +gvir_designer_domain_video_model_str_to_enum(const char *model_str, + GError **error) +{ + GVirConfigDomainVideoModel model; + + if (g_str_equal(model_str, "vga")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VGA; + } else if (g_str_equal(model_str, "cirrus")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_CIRRUS; + } else if (g_str_equal(model_str, "vmvga")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VMVGA; + } else if (g_str_equal(model_str, "xen")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_XEN; + } else if (g_str_equal(model_str, "vbox")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VBOX; + } else if (g_str_equal(model_str, "qxl")) { + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_QXL; + } else { + g_debug("unsupported video model type '%s'", model_str); + g_set_error(error, GVIR_DESIGNER_DOMAIN_ERROR, 0, + "unsupported video model type '%s'", model_str); + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VGA; + } + + return model; +} + +/* FIXME: belongs in platform descriptions, maybe useful as a last resort */ +static GVirConfigDomainVideoModel +gvir_designer_domain_video_model_from_virt_type(GVirDesignerDomain *design) +{ + GVirConfigDomainVirtType virt_type; + GVirConfigDomainVideoModel model; + + virt_type = gvir_config_domain_get_virt_type(design->priv->config); + switch (virt_type) { + case GVIR_CONFIG_DOMAIN_VIRT_QEMU: + case GVIR_CONFIG_DOMAIN_VIRT_KQEMU: + case GVIR_CONFIG_DOMAIN_VIRT_KVM: + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_QXL; + break; + case GVIR_CONFIG_DOMAIN_VIRT_XEN: + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_XEN; + break; + case GVIR_CONFIG_DOMAIN_VIRT_VMWARE: + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VMVGA; + break; + case GVIR_CONFIG_DOMAIN_VIRT_VBOX: + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VBOX; + break; + case GVIR_CONFIG_DOMAIN_VIRT_LXC: + case GVIR_CONFIG_DOMAIN_VIRT_UML: + case GVIR_CONFIG_DOMAIN_VIRT_OPENVZ: + case GVIR_CONFIG_DOMAIN_VIRT_VSERVER: + case GVIR_CONFIG_DOMAIN_VIRT_LDOM: + case GVIR_CONFIG_DOMAIN_VIRT_TEST: + case GVIR_CONFIG_DOMAIN_VIRT_HYPERV: + case GVIR_CONFIG_DOMAIN_VIRT_ONE: + case GVIR_CONFIG_DOMAIN_VIRT_PHYP: + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VGA; + break; + default: + g_warn_if_reached(); + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VGA; + break; + } + + return model; +} + +static const gchar * +gvir_designer_domain_get_preferred_video_model(GVirDesignerDomain *design, + GError **error) +{ + const gchar *ret = NULL; + OsinfoDeviceLink *dev_link = NULL; + OsinfoDevice *dev; + + dev_link = gvir_designer_domain_get_preferred_device(design, "video", error); + if (!dev_link) + goto cleanup; + + dev = osinfo_devicelink_get_target(dev_link); + if (dev) + ret = osinfo_device_get_name(dev); + +cleanup: + if (dev_link) + g_object_unref(dev_link); + return ret; +} + +static GVirConfigDomainVideoModel +gvir_designer_domain_get_fallback_video_model(GVirDesignerDomain *design) +{ + OsinfoDeviceList *supported_devices = NULL; + OsinfoFilter *filter = NULL; + OsinfoDevice *device = NULL; + const char *model_str; + GVirConfigDomainVideoModel model; + GError *error = NULL; + + model = GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VGA; + + filter = osinfo_filter_new(); + osinfo_filter_add_constraint(filter, OSINFO_DEVICE_PROP_CLASS, "video"); + supported_devices = gvir_designer_domain_get_supported_devices(design, filter); + if ((supported_devices == NULL) || osinfo_list_get_length(OSINFO_LIST(supported_devices)) == 0) + goto fallback; + + device = OSINFO_DEVICE(osinfo_list_get_nth(OSINFO_LIST(supported_devices), 0)); + model_str = osinfo_device_get_name(device); + model = gvir_designer_domain_video_model_str_to_enum(model_str, + &error); + if (error != NULL) { + g_clear_error(&error); + goto fallback; + } + goto end; + +fallback: + model = gvir_designer_domain_video_model_from_virt_type(design); + +end: + if (filter != NULL) + g_object_unref(G_OBJECT(filter)); + if (supported_devices != NULL) + g_object_unref(G_OBJECT(supported_devices)); + + return model; +} + +/** + * gvir_designer_domain_add_video: + * @design: (transfer none): the domain designer instance + * @error: return location for a #GError, or NULL + * + * Add a new video device into @design. + * + * Returns: (transfer full): the pointer to the new video device. + */ +GVirConfigDomainVideo * +gvir_designer_domain_add_video(GVirDesignerDomain *design, GError **error) +{ + GVirConfigDomainVideo *video; + const gchar *model_str = NULL; + GVirConfigDomainVideoModel model; + + g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL); + g_return_val_if_fail(!error_is_set(error), NULL); + + model_str = gvir_designer_domain_get_preferred_video_model(design, NULL); + if (model_str != NULL) { + model = gvir_designer_domain_video_model_str_to_enum(model_str, error); + if (error_is_set(error)) { + g_clear_error(error); + model = gvir_designer_domain_get_fallback_video_model(design); + } + } else { + model = gvir_designer_domain_get_fallback_video_model(design); + } + + video = gvir_config_domain_video_new(); + gvir_config_domain_video_set_model(video, model); + gvir_config_domain_add_device(design->priv->config, + GVIR_CONFIG_DOMAIN_DEVICE(video)); + + return video; +} + static void gvir_designer_domain_get_resources(OsinfoResourcesList *res_list, diff --git a/libvirt-designer/libvirt-designer-domain.h b/libvirt-designer/libvirt-designer-domain.h index 643e3bf..85dce97 100644 --- a/libvirt-designer/libvirt-designer-domain.h +++ b/libvirt-designer/libvirt-designer-domain.h @@ -138,6 +138,8 @@ GVirConfigDomainGraphics *gvir_designer_domain_add_graphics(GVirDesignerDomain * GVirConfigDomainSmartcard *gvir_designer_domain_add_smartcard(GVirDesignerDomain *design, GError **error); GVirConfigDomainSound *gvir_designer_domain_add_sound(GVirDesignerDomain *design, GError **error); GVirConfigDomainRedirdev *gvir_designer_domain_add_usb_redir(GVirDesignerDomain *design, GError **error); +GVirConfigDomainVideo *gvir_designer_domain_add_video(GVirDesignerDomain *design, + GError **error); gboolean gvir_designer_domain_setup_resources(GVirDesignerDomain *design, GVirDesignerDomainResources req, diff --git a/libvirt-designer/libvirt-designer.sym b/libvirt-designer/libvirt-designer.sym index 91c70f4..7b1a2a3 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -25,6 +25,7 @@ LIBVIRT_DESIGNER_0.0.1 { gvir_designer_domain_add_smartcard; gvir_designer_domain_add_sound; gvir_designer_domain_add_usb_redir; + gvir_designer_domain_add_video; gvir_designer_domain_setup_resources; gvir_designer_domain_resources_get_type; -- 1.8.1.4

On Thu, Apr 18, 2013 at 06:12:33PM +0200, Christophe Fergeau wrote:
diff --git a/libvirt-designer/libvirt-designer-domain.c b/libvirt-designer/libvirt-designer-domain.c index 7aec002..73dbc8d 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -1153,7 +1153,6 @@ gvir_designer_domain_setup_guest(GVirDesignerDomain *design, gvir_designer_domain_add_console(design); gvir_designer_domain_add_input(design);
- ret = TRUE;
This is actually bogus and breaks make check, I don't know how it ended up being removed. I've dropped this hunk from my local copy. Christophe

On Thu, Apr 18, 2013 at 06:12:24PM +0200, Christophe Fergeau wrote:
This goes on top of v2 of the "Improve disk bus type generation" series. Diff with the previous version is that it's rebased against latest master, and I've reworked "Implement gvir_designer_domain_add_sound()" patch to address danpb's comments (gvir_designer_domain_add_sound() is now a public method that must be called explicitly rather than being implicitly called on domain creation.
Any more comments/reviews on that series? Christophe
participants (2)
-
Christophe Fergeau
-
Daniel P. Berrange