[virt-tools-list] [PATCH virt-viewer 5/6] remote-viewer: add a --dbus-controller

Eduardo Lima (Etrunko) etrunko at redhat.com
Wed Jun 28 13:54:26 UTC 2017


On 23/06/17 12:30, marcandre.lureau at redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau at redhat.com>
> 
> Allow to set connection details via DBus, and add a Connect method.
> This is intended to replace the Spice controller.
> 
> Sample usage:
> 
> DEST=`remote-viewer --dbus-controller`
> 
> gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
>   --method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
>   host '<string "localhost">'
> gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
>   --method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
>   port '<int32 5900>'
> gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
>   --method org.freedesktop.DBus.Properties.Set org.VirtManager.RemoteViewer.Controller \
>   type '<string "spice">'()
> gdbus call --session --dest $DEST --object-path /org/virt_manager/remote_viewer \
>   --method org.VirtManager.RemoteViewer.Controller.Connect()
> 

Please consider spliting this patch, as I said on my comment on patch 3
of the series.

> Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
> ---
>  src/remote-viewer.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/remote-viewer.h |   1 +
>  2 files changed, 196 insertions(+), 3 deletions(-)
> 
> diff --git a/src/remote-viewer.c b/src/remote-viewer.c
> index fb5376c..f0f9531 100644
> --- a/src/remote-viewer.c
> +++ b/src/remote-viewer.c
> @@ -57,6 +57,7 @@ struct _RemoteViewerPrivate {
>      OvirtForeignMenu *ovirt_foreign_menu;
>  #endif
>      gboolean open_recent_dialog;
> +    VirtViewerFile *dbus_file;
>  };
>  
>  G_DEFINE_TYPE (RemoteViewer, remote_viewer, VIRT_VIEWER_TYPE_APP)
> @@ -137,6 +138,7 @@ remote_viewer_deactivated(VirtViewerApp *app, gboolean connect_error)
>  static gchar **opt_args = NULL;
>  static char *opt_title = NULL;
>  static gboolean opt_controller = FALSE;
> +static gboolean opt_dbus_ctrl = FALSE;
>  
>  static void
>  remote_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group)
> @@ -144,6 +146,8 @@ remote_viewer_add_option_entries(VirtViewerApp *self, GOptionContext *context, G
>      static const GOptionEntry options[] = {
>          { "title", 't', 0, G_OPTION_ARG_STRING, &opt_title,
>            N_("Set window title"), NULL },
> +        { "dbus-controller", '\0', 0, G_OPTION_ARG_NONE, &opt_dbus_ctrl,
> +          N_("Open connection using DBus controller"), NULL },
>  #ifdef HAVE_SPICE_GTK
>          { "spice-controller", '\0', 0, G_OPTION_ARG_NONE, &opt_controller,
>            N_("Open connection using Spice controller communication"), NULL },
> @@ -175,7 +179,17 @@ remote_viewer_local_command_line (GApplication   *gapp,
>      if (ret)
>          goto end;
>  
> -    if (!opt_args) {
> +    if (opt_dbus_ctrl) {
> +        if (opt_args || opt_controller) {
> +            g_printerr(_("\nError: extra arguments given while using --dbus\n\n"));
> +            ret = TRUE;
> +            *status = 1;
> +            goto end;
> +        }
> +        self->priv->dbus_file = virt_viewer_file_new(NULL, NULL);
> +        virt_viewer_app_set_dbus_ctrl(app, TRUE);
> +        return FALSE;
> +    } else if (!opt_args) {
>          self->priv->open_recent_dialog = TRUE;
>      } else {
>          if (g_strv_length(opt_args) > 1) {
> @@ -190,7 +204,7 @@ remote_viewer_local_command_line (GApplication   *gapp,
>  
>  #ifdef HAVE_SPICE_GTK
>      if (opt_controller) {
> -        if (opt_args) {
> +        if (opt_args || opt_dbus_ctrl) {
>              g_printerr(_("\nError: extra arguments given while using Spice controller\n\n"));
>              ret = TRUE;
>              *status = 1;
> @@ -241,6 +255,180 @@ remote_viewer_get_property(GObject *object, guint property_id,
>      }
>  }
>  
> +static void
> +handle_method_call (GDBusConnection       *connection G_GNUC_UNUSED,
> +                    const gchar           *sender G_GNUC_UNUSED,
> +                    const gchar           *object_path G_GNUC_UNUSED,
> +                    const gchar           *interface_name G_GNUC_UNUSED,
> +                    const gchar           *method_name,
> +                    GVariant              *parameters G_GNUC_UNUSED,
> +                    GDBusMethodInvocation *invocation,
> +                    gpointer               user_data)
> +{
> +    RemoteViewer *self = REMOTE_VIEWER(user_data);
> +
> +    if (g_str_equal(method_name, "Connect")) {
> +        GError *error = NULL;
> +        char *type = virt_viewer_file_get_file_type(self->priv->dbus_file);
> +        g_debug("Connect! %s", type);
> +        if (!remote_viewer_initial_connect(self, type, self->priv->dbus_file, &error)) {
> +            g_dbus_method_invocation_return_gerror(invocation, error);
> +            g_clear_error(&error);
> +        } else {
> +            g_dbus_method_invocation_return_value (invocation, NULL);
> +        }
> +    }
> +}
> +
> +
> +static GVariant *
> +handle_get_property (GDBusConnection  *connection G_GNUC_UNUSED,
> +                     const gchar      *sender G_GNUC_UNUSED,
> +                     const gchar      *object_path G_GNUC_UNUSED,
> +                     const gchar      *interface_name G_GNUC_UNUSED,
> +                     const gchar      *property_name,
> +                     GError          **error G_GNUC_UNUSED,
> +                     gpointer          user_data)
> +{
> +    RemoteViewer *self = REMOTE_VIEWER(user_data);
> +    GParamSpec *pspec;
> +    GValue value = G_VALUE_INIT;
> +    GVariant *ret;
> +    const GVariantType *type = NULL;
> +
> +    pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->priv->dbus_file),
> +                                         property_name);
> +    if (!pspec) {
> +        g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown property %s", property_name);
> +        return NULL;
> +    }
> +    if (g_type_is_a(pspec->value_type, G_TYPE_STRING))
> +        type = G_VARIANT_TYPE_STRING;
> +    else if (g_type_is_a(pspec->value_type, G_TYPE_INT))
> +        type = G_VARIANT_TYPE_INT32;
> +    else if (g_type_is_a(pspec->value_type, G_TYPE_BOXED)) {
> +        type = G_VARIANT_TYPE_STRING_ARRAY; /* only type as of writing this */
> +    } else {
> +        g_set_error(error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unhandled type for %s", property_name);
> +        g_return_val_if_reached(NULL);
> +    }
> +
> +    g_value_init(&value, pspec->value_type);
> +    g_object_get_property(G_OBJECT(self->priv->dbus_file), property_name, &value);
> +    ret = g_dbus_gvalue_to_gvariant(&value, type);
> +    g_value_unset(&value);
> +
> +    return ret;
> +}
> +
> +static gboolean
> +handle_set_property (GDBusConnection  *connection G_GNUC_UNUSED,
> +                     const gchar      *sender G_GNUC_UNUSED,
> +                     const gchar      *object_path G_GNUC_UNUSED,
> +                     const gchar      *interface_name G_GNUC_UNUSED,
> +                     const gchar      *property_name,
> +                     GVariant         *variant,
> +                     GError          **error,
> +                     gpointer          user_data)
> +{
> +    RemoteViewer *self = REMOTE_VIEWER(user_data);
> +    GValue value;
> +
> +    g_dbus_gvariant_to_gvalue(variant, &value);
> +    g_object_set_property(G_OBJECT(self->priv->dbus_file), property_name, &value);
> +    g_value_unset(&value);
> +
> +    return *error == NULL; /* error is always non-null */
> +}
> +
> +static const GDBusInterfaceVTable interface_vtable =
> +{
> +    handle_method_call,
> +    handle_get_property,
> +    handle_set_property,
> +    { 0, } /* padding, hmm sucks */
> +};
> +
> +static gboolean
> +remote_viewer_dbus_register (GApplication    *application,
> +                             GDBusConnection *connection,
> +                             const gchar     *object_path,
> +                             GError         **error)
> +{
> +    RemoteViewer *self = REMOTE_VIEWER(application);
> +    RemoteViewerClass *klass = REMOTE_VIEWER_GET_CLASS(REMOTE_VIEWER(application));
> +    guint registration_id;
> +
> +    if (!G_APPLICATION_CLASS(remote_viewer_parent_class)->dbus_register (application,
> +                                                                         connection,
> +                                                                         object_path,
> +                                                                         error))
> +        return FALSE;
> +
> +    if (!klass->introspection_data) {
> +        /* keep in sync with virt-viewer-file */
> +        /* voluntarily removed: color-depth, disable-effects, delete-this-file */
> +        /* TODO: versions - uses a hashtable (replace it with strv?) */
> +        static const gchar introspection_xml[] =
> +            "<node>"
> +            "  <interface name='org.VirtManager.RemoteViewer.Controller'>"
> +            "    <method name='Connect'/>"
> +            "    <property type='s' name='version' access='readwrite'/>"
> +            "    <property type='s' name='newer-version-url' access='readwrite'/>"
> +            "    <property type='s' name='type' access='readwrite'/>"
> +            "    <property type='s' name='host' access='readwrite'/>"
> +            "    <property type='i' name='port' access='readwrite'/>"
> +            "    <property type='i' name='tls-port' access='readwrite'/>"
> +            "    <property type='s' name='username' access='readwrite'/>"
> +            "    <property type='s' name='password' access='readwrite'/>"
> +            "    <property type='as' name='disable-channels' access='readwrite'/>"
> +            "    <property type='s' name='tls-ciphers' access='readwrite'/>"
> +            "    <property type='s' name='ca' access='readwrite'/>"
> +            "    <property type='s' name='host-subject' access='readwrite'/>"
> +            "    <property type='i' name='fullscreen' access='readwrite'/>"
> +            "    <property type='s' name='title' access='readwrite'/>"
> +            "    <property type='s' name='toggle-fullscreen' access='readwrite'/>"
> +            "    <property type='s' name='release-cursor' access='readwrite'/>"
> +            "    <property type='s' name='smartcard-insert' access='readwrite'/>"
> +            "    <property type='s' name='smartcard-remove' access='readwrite'/>"
> +            "    <property type='s' name='secure-attention' access='readwrite'/>"
> +            "    <property type='i' name='enable-smartcard' access='readwrite'/>"
> +            "    <property type='i' name='enable-usbredir' access='readwrite'/>"
> +            "    <property type='i' name='enable-usb-autoshare' access='readwrite'/>"
> +            "    <property type='s' name='usb-filter' access='readwrite'/>"
> +            "    <property type='as' name='secure-channels' access='readwrite'/>"
> +            "    <property type='s' name='proxy' access='readwrite'/>"
> +            "  </interface>"
> +            "</node>";
> +
> +        klass->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
> +        g_assert (klass->introspection_data);
> +    }
> +    registration_id = g_dbus_connection_register_object (connection,
> +                                                         object_path,
> +                                                         klass->introspection_data->interfaces[0],
> +                                                         &interface_vtable,
> +                                                         self,  /* user_data */
> +                                                         NULL,  /* user_data_free_func */
> +                                                         NULL); /* GError** */
> +    g_assert (registration_id > 0);
> +
> +    g_print ("%s", g_dbus_connection_get_unique_name(connection));
> +
> +    return TRUE;
> +}
> +
> +static void
> +remote_viewer_dbus_unregister (GApplication    *application,
> +                               GDBusConnection *connection,
> +                               const gchar     *object_path)
> +{
> +    G_APPLICATION_CLASS(remote_viewer_parent_class)->dbus_unregister (application,
> +                                                                      connection,
> +                                                                      object_path);
> +}
> +
> +
>  static void
>  remote_viewer_class_init (RemoteViewerClass *klass)
>  {
> @@ -255,6 +443,8 @@ remote_viewer_class_init (RemoteViewerClass *klass)
>      object_class->dispose = remote_viewer_dispose;
>  
>      g_app_class->local_command_line = remote_viewer_local_command_line;
> +    g_app_class->dbus_register = remote_viewer_dbus_register;
> +    g_app_class->dbus_unregister = remote_viewer_dbus_unregister;
>  
>      app_class->start = remote_viewer_start;
>      app_class->deactivated = remote_viewer_deactivated;
> @@ -1155,7 +1345,9 @@ remote_viewer_start(VirtViewerApp *app, GError **err)
>          virt_viewer_app_show_status(VIRT_VIEWER_APP(self), _("Setting up Spice session..."));
>      } else
>  #endif
> -    {
> +    if (opt_dbus_ctrl) {
> +        virt_viewer_app_show_status(VIRT_VIEWER_APP(self), _("Waiting on DBus controller..."));
> +    } else {
>  retry_dialog:
>          if (priv->open_recent_dialog) {
>              VirtViewerWindow *main_window = virt_viewer_app_get_main_window(app);
> diff --git a/src/remote-viewer.h b/src/remote-viewer.h
> index 53566fc..09f10c1 100644
> --- a/src/remote-viewer.h
> +++ b/src/remote-viewer.h
> @@ -44,6 +44,7 @@ typedef struct {
>  
>  typedef struct {
>      VirtViewerAppClass parent_class;
> +    GDBusNodeInfo *introspection_data;
>  } RemoteViewerClass;
>  
>  GType remote_viewer_get_type (void);
> 


-- 
Eduardo de Barros Lima (Etrunko)
Software Engineer - RedHat
etrunko at redhat.com




More information about the virt-tools-list mailing list