libnm-core, core: register NMConnectionError with D-Bus

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.
This commit is contained in:
Dan Winship
2014-10-15 14:55:41 -04:00
parent b1bcfa8fed
commit 9c67b6fb08
7 changed files with 112 additions and 4 deletions

View File

@@ -81,4 +81,6 @@ GPtrArray *_nm_utils_copy_array (const GPtrArray *array,
GDestroyNotify free_func); GDestroyNotify free_func);
GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array); GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
void _nm_dbus_errors_init (void);
#endif #endif

View File

@@ -18,10 +18,43 @@
* Copyright 2004 - 2014 Red Hat, Inc. * Copyright 2004 - 2014 Red Hat, Inc.
*/ */
#include <glib.h> #include <string.h>
#include <gio/gio.h>
#include "nm-errors.h" #include "nm-errors.h"
#include "nm-glib-compat.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-connection-error-quark, nm_connection_error)
G_DEFINE_QUARK (nm-crypto-error-quark, nm_crypto_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);
}

View File

@@ -50,6 +50,11 @@
* *
* Describes errors that may result from operations involving a #NMConnection * Describes errors that may result from operations involving a #NMConnection
* or its #NMSettings. * 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 { typedef enum {
NM_CONNECTION_ERROR_FAILED = 0, /*< nick=Failed >*/ NM_CONNECTION_ERROR_FAILED = 0, /*< nick=Failed >*/

View File

@@ -233,6 +233,8 @@ nm_utils_init (GError **error)
if (!crypto_init (error)) if (!crypto_init (error))
return FALSE; return FALSE;
_nm_dbus_errors_init ();
} }
return TRUE; return TRUE;
} }

View 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 int
main (int argc, char **argv) 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/make_visible", test_make_visible);
g_test_add_func ("/client/remove_connection", test_remove_connection); 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_remove_connection", test_add_remove_connection);
g_test_add_func ("/client/add_bad_connection", test_add_bad_connection);
ret = g_test_run (); ret = g_test_run ();

View File

@@ -1995,9 +1995,9 @@ nm_settings_class_init (NMSettingsClass *class)
dbus_g_error_domain_register (NM_SETTINGS_ERROR, dbus_g_error_domain_register (NM_SETTINGS_ERROR,
NM_DBUS_INTERFACE_SETTINGS, NM_DBUS_INTERFACE_SETTINGS,
NM_TYPE_SETTINGS_ERROR); NM_TYPE_SETTINGS_ERROR);
dbus_g_error_domain_register (NM_CONNECTION_ERROR,
/* And register all the settings errors with D-Bus */ NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
dbus_g_error_domain_register (NM_CONNECTION_ERROR, NULL, NM_TYPE_CONNECTION_ERROR); NM_TYPE_CONNECTION_ERROR);
dbus_g_object_type_install_info (NM_TYPE_SETTINGS, &dbus_glib_nm_settings_object_info); dbus_g_object_type_install_info (NM_TYPE_SETTINGS, &dbus_glib_nm_settings_object_info);

View File

@@ -905,9 +905,31 @@ class NetworkManager(ExportedObj):
################################################################### ###################################################################
IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection' 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): class Connection(dbus.service.Object):
def __init__(self, bus, object_path, settings, remove_func): def __init__(self, bus, object_path, settings, remove_func):
dbus.service.Object.__init__(self, bus, object_path) 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.path = object_path
self.settings = settings self.settings = settings
self.remove_func = remove_func self.remove_func = remove_func