[libvirt] [libvirt-designer PATCHv3] Handle more devices in GVirDesignerDomain
Hi, Resending once more, only change since v2 is a small fix in 1/9 to avoid calling g_str_has_suffix on a NULL string when no short_id is available. 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 - 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. --- 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 2d4204f..e4f72e6 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -313,6 +313,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 (short_id != NULL && 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; @@ -670,6 +759,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.2.1
On 04.06.2013 16:33, 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 - 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.
I'd argue that majority cases do want a console or don't care about it. So I guess it's okay if a console is added implicitly.
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 2d4204f..e4f72e6 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -313,6 +313,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 (short_id != NULL && 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; @@ -670,6 +759,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)
--- 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 e4f72e6..684c458 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -388,6 +388,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; @@ -932,6 +933,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 d1aa916..0a8b49e 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -20,6 +20,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
--- 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 e4f72e6..684c458 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -388,6 +388,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; @@ -932,6 +933,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;
I think we are returning NULL without @error set here. I can't see where gvir_designer_domain_get_fallback_soundard sets @error esp. when it is not being passed :)
+ + 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 d1aa916..0a8b49e 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -20,6 +20,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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;
--- 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 684c458..36fc8ed 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.2.1
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 228a85c..bad199b 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_CANONICAL_HOST AM_SILENT_RULES([yes]) LIBOSINFO_REQUIRED=0.2.7 -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 36fc8ed..a1914dd 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -348,6 +348,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 0a8b49e..9a73993 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -5,6 +5,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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.2 { 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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
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 228a85c..bad199b 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_CANONICAL_HOST AM_SILENT_RULES([yes])
LIBOSINFO_REQUIRED=0.2.7 -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;
I'd rather let users to choose if they want VNC or SPICE or ...
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 36fc8ed..a1914dd 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -348,6 +348,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 0a8b49e..9a73993 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -5,6 +5,7 @@ LIBVIRT_DESIGNER_0.0.2 {
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.2 { 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;
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 a1914dd..1d37e21 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -69,6 +69,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 { @@ -314,6 +315,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; @@ -349,6 +373,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) @@ -432,6 +515,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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
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 a1914dd..1d37e21 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -69,6 +69,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 { @@ -314,6 +315,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; @@ -349,6 +373,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);
Is this really a critical issue? What about g_warning instead?
+ 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) @@ -432,6 +515,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; }
On Tue, Jun 04, 2013 at 07:11:23PM +0200, Michal Privoznik wrote:
+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);
Is this really a critical issue? What about g_warning instead?
This means the domain XML has a very unexpected content, so I'd tend to tag that as g_critical (which is not much different from g_warning anyway). I don't mind changing it to g_warning. Christophe
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 1d37e21..7466ee9 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) } 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 { @@ -410,12 +411,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); @@ -429,6 +463,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; } @@ -516,7 +552,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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
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 1d37e21..7466ee9 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) }
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 { @@ -410,12 +411,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);
so warn if the list length is greater than 1 ...
+ if (osinfo_list_get_length(OSINFO_LIST(devices)) >= 1) + vioserial_found = TRUE;
... but that's the only way to set vioserial_found to TRUE. Or am I missing something?
+ 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); @@ -429,6 +463,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; }
@@ -516,7 +552,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);
I think we want s/NULL/error/ here.
break; }
On Tue, Jun 04, 2013 at 07:10:57PM +0200, Michal Privoznik wrote:
On 04.06.2013 16:33, Christophe Fergeau wrote:
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 1d37e21..7466ee9 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) }
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 { @@ -410,12 +411,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);
so warn if the list length is greater than 1 ...
+ if (osinfo_list_get_length(OSINFO_LIST(devices)) >= 1) + vioserial_found = TRUE;
... but that's the only way to set vioserial_found to TRUE. Or am I missing something?
Hmm, I think I wanted to get a warning if the list has 2 items or more, as this is very unexpected, but still do something sensible when that happens. In other words, if the list length is 0, then vioserial_found is FALSE, if it's 1, it's TRUE, if it's more than 1, then we warn, but still set it to TRUE. I agree the g_warn_if_fail() should be removed, or that there should be a comment with an explanation.
@@ -516,7 +552,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);
I think we want s/NULL/error/ here.
Not sure about that, if we do that, we would have to return NULL from _add_graphics when adding the channel fails. Some people are using SPICE on xen if I'm not mistaken, adding a spice channel will fail there. Probably a bit far fetched at this point, so we could fail for now until someone comes to us with such a use case ;) Thanks for the review, Christophe
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 7466ee9..ae816e0 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -580,6 +580,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 9a73993..2894dee 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -23,6 +23,8 @@ LIBVIRT_DESIGNER_0.0.2 { 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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
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
s/adds/add/
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; + }
Why 4 times? Moreover, I'd rather see this as optional.
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 7466ee9..ae816e0 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -580,6 +580,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 9a73993..2894dee 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -23,6 +23,8 @@ LIBVIRT_DESIGNER_0.0.2 { 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;
On Tue, Jun 04, 2013 at 07:11:05PM +0200, Michal Privoznik wrote:
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; + }
Why 4 times? Moreover, I'd rather see this as optional.
You need one redir channel per USB device you want to be able to redirect simultaneously, I'll make USB redirection optional indeed, though I'll probably keep a hardcoded '4' for now, this can be tweaked later. Christophe
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 ae816e0..914ac39 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -697,6 +697,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 2894dee..da2cad6 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -22,6 +22,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
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;
Again, this should be optional in my opinion.
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 ae816e0..914ac39 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -697,6 +697,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 2894dee..da2cad6 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -22,6 +22,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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;
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, 177 insertions(+) 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 914ac39..1f52cbf 100644 --- a/libvirt-designer/libvirt-designer-domain.c +++ b/libvirt-designer/libvirt-designer-domain.c @@ -1153,6 +1153,7 @@ gvir_designer_domain_setup_guest(GVirDesignerDomain *design, gvir_designer_domain_add_input(design); ret = TRUE; + cleanup: if (domain != NULL) g_object_unref(domain); @@ -1901,6 +1902,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 da2cad6..96bc656 100644 --- a/libvirt-designer/libvirt-designer.sym +++ b/libvirt-designer/libvirt-designer.sym @@ -25,6 +25,7 @@ LIBVIRT_DESIGNER_0.0.2 { 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.2.1
On 04.06.2013 16:33, Christophe Fergeau wrote:
Hi,
Resending once more, only change since v2 is a small fix in 1/9 to avoid calling g_str_has_suffix on a NULL string when no short_id is available.
Christophe
I think these patches are good. I feel comfortable giving my ACK. However, please see my comments. Michal
participants (2)
-
Christophe Fergeau -
Michal Privoznik