libnm-core, core: register NMConnectionError with D-Bus
authorDan Winship <danw@gnome.org>
Wed, 15 Oct 2014 18:55:41 +0000 (14:55 -0400)
committerDan Winship <danw@gnome.org>
Wed, 22 Oct 2014 12:29:08 +0000 (08:29 -0400)
Register NMConnectionError with D-Bus on both sides, so that, eg,
connection validation failures in the daemon will translate to the
correct error codes in the client.

libnm-core/nm-core-internal.h
libnm-core/nm-errors.c
libnm-core/nm-errors.h
libnm-core/nm-utils.c
libnm/tests/test-remote-settings-client.c
src/settings/nm-settings.c
tools/test-networkmanager-service.py

index f83b486..da40404 100644 (file)
@@ -81,4 +81,6 @@ GPtrArray *_nm_utils_copy_array (const GPtrArray *array,
                                  GDestroyNotify free_func);
 GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
 
+void _nm_dbus_errors_init (void);
+
 #endif
index 9904041..9469740 100644 (file)
  * Copyright 2004 - 2014 Red Hat, Inc.
  */
 
-#include <glib.h>
+#include <string.h>
+#include <gio/gio.h>
 
 #include "nm-errors.h"
 #include "nm-glib-compat.h"
+#include "nm-dbus-interface.h"
+#include "nm-core-internal.h"
 
 G_DEFINE_QUARK (nm-connection-error-quark, nm_connection_error)
 G_DEFINE_QUARK (nm-crypto-error-quark, nm_crypto_error)
+
+static void
+register_error_domain (GQuark domain,
+                       const char *interface,
+                       GType enum_type)
+{
+       GEnumClass *enum_class;
+       GEnumValue *e;
+       char *error_name;
+       int i;
+
+       enum_class = g_type_class_ref (enum_type);
+       for (i = 0; i < enum_class->n_values; i++) {
+               e = &enum_class->values[i];
+               g_assert (strchr (e->value_nick, '-') == NULL);
+               error_name = g_strdup_printf ("%s.%s", interface, e->value_nick);
+               g_dbus_error_register_error (domain, e->value, error_name);
+               g_free (error_name);
+       }
+
+       g_type_class_unref (enum_class);
+}
+
+void
+_nm_dbus_errors_init (void)
+{
+       register_error_domain (NM_CONNECTION_ERROR,
+                              NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
+                              NM_TYPE_CONNECTION_ERROR);
+}
index 7790854..a6b34e3 100644 (file)
  *
  * Describes errors that may result from operations involving a #NMConnection
  * or its #NMSettings.
+ *
+ * These errors may be returned directly from #NMConnection and #NMSetting
+ * methods, or may be returned from D-Bus operations (eg on #NMClient or
+ * #NMDevice), where they correspond to errors in the
+ * "org.freedesktop.NetworkManager.Settings.Connection" namespace.
  */
 typedef enum {
        NM_CONNECTION_ERROR_FAILED = 0,                   /*< nick=Failed >*/
index 913ba4b..d3c3bef 100644 (file)
@@ -233,6 +233,8 @@ nm_utils_init (GError **error)
 
                if (!crypto_init (error))
                        return FALSE;
+
+               _nm_dbus_errors_init ();
        }
        return TRUE;
 }
index ca0f03f..643fdf2 100644 (file)
@@ -415,6 +415,49 @@ test_add_remove_connection (void)
 
 /*******************************************************************/
 
+static void
+add_bad_cb (GObject *s,
+            GAsyncResult *result,
+            gpointer user_data)
+{
+       gboolean *done = user_data;
+       GError *error = NULL;
+
+       remote = nm_client_add_connection_finish (client, result, &error);
+       g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+
+       *done = TRUE;
+}
+
+static void
+test_add_bad_connection (void)
+{
+       NMConnection *connection;
+       time_t start, now;
+       gboolean done = FALSE;
+
+       /* The test daemon doesn't support bond connections */
+       connection = nmtst_create_minimal_connection ("bad connection test", NULL, NM_SETTING_BOND_SETTING_NAME, NULL);
+
+       nm_client_add_connection_async (client,
+                                       connection,
+                                       TRUE,
+                                       NULL,
+                                       add_bad_cb,
+                                       &done);
+       g_object_unref (connection);
+
+       start = time (NULL);
+       do {
+               now = time (NULL);
+               g_main_context_iteration (NULL, FALSE);
+       } while ((done == FALSE) && (now - start < 5));
+       g_assert (done == TRUE);
+       g_assert (remote == NULL);
+}
+
+/*******************************************************************/
+
 int
 main (int argc, char **argv)
 {
@@ -446,6 +489,7 @@ main (int argc, char **argv)
        g_test_add_func ("/client/make_visible", test_make_visible);
        g_test_add_func ("/client/remove_connection", test_remove_connection);
        g_test_add_func ("/client/add_remove_connection", test_add_remove_connection);
+       g_test_add_func ("/client/add_bad_connection", test_add_bad_connection);
 
        ret = g_test_run ();
 
index 558d940..1b33092 100644 (file)
@@ -1995,9 +1995,9 @@ nm_settings_class_init (NMSettingsClass *class)
        dbus_g_error_domain_register (NM_SETTINGS_ERROR,
                                      NM_DBUS_INTERFACE_SETTINGS,
                                      NM_TYPE_SETTINGS_ERROR);
-
-       /* And register all the settings errors with D-Bus */
-       dbus_g_error_domain_register (NM_CONNECTION_ERROR, NULL, NM_TYPE_CONNECTION_ERROR);
+       dbus_g_error_domain_register (NM_CONNECTION_ERROR,
+                                     NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
+                                     NM_TYPE_CONNECTION_ERROR);
 
        dbus_g_object_type_install_info (NM_TYPE_SETTINGS, &dbus_glib_nm_settings_object_info);
 
index d98174c..9be2e85 100755 (executable)
@@ -905,9 +905,31 @@ class NetworkManager(ExportedObj):
 ###################################################################
 IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection'
 
+class InvalidPropertyException(dbus.DBusException):
+    _dbus_error_name = IFACE_CONNECTION + '.InvalidProperty'
+
+class MissingPropertyException(dbus.DBusException):
+    _dbus_error_name = IFACE_CONNECTION + '.MissingProperty'
+
+class InvalidSettingException(dbus.DBusException):
+    _dbus_error_name = IFACE_CONNECTION + '.InvalidSetting'
+
+class MissingSettingException(dbus.DBusException):
+    _dbus_error_name = IFACE_CONNECTION + '.MissingSetting'
+
 class Connection(dbus.service.Object):
     def __init__(self, bus, object_path, settings, remove_func):
         dbus.service.Object.__init__(self, bus, object_path)
+
+        if not settings.has_key('connection'):
+            raise MissingSettingException('connection: setting is required')
+        s_con = settings['connection']
+        if not s_con.has_key('type'):
+            raise MissingPropertyException('connection.type: property is required')
+        type = s_con['type']
+        if not type in ['802-3-ethernet', '802-11-wireless', 'vlan', 'wimax']:
+            raise InvalidPropertyException('connection.type: unsupported connection type')
+
         self.path = object_path
         self.settings = settings
         self.remove_func = remove_func