libnm, core: fix problems with device activation (bgo 737993)

This commit is contained in:
Dan Winship 2014-10-19 09:27:53 -04:00
commit 7b1aae969d
15 changed files with 750 additions and 296 deletions

View file

@ -362,8 +362,11 @@ nm_active_connection_get_master (NMActiveConnection *connection)
}
static void
nm_active_connection_init (NMActiveConnection *ap)
nm_active_connection_init (NMActiveConnection *connection)
{
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection);
priv->devices = g_ptr_array_new ();
}
static void

View file

@ -173,7 +173,11 @@ get_hw_address (NMDevice *device)
static void
nm_device_bond_init (NMDeviceBond *device)
{
NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device);
_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BOND);
priv->slaves = g_ptr_array_new ();
}
static void

View file

@ -173,7 +173,11 @@ get_hw_address (NMDevice *device)
static void
nm_device_bridge_init (NMDeviceBridge *device)
{
NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BRIDGE);
priv->slaves = g_ptr_array_new ();
}
static void

View file

@ -173,7 +173,11 @@ get_setting_type (NMDevice *device)
static void
nm_device_team_init (NMDeviceTeam *device)
{
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device);
_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_TEAM);
priv->slaves = g_ptr_array_new ();
}
static void

View file

@ -565,12 +565,16 @@ get_hw_address (NMDevice *device)
static void
nm_device_wifi_init (NMDeviceWifi *device)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
_nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_WIFI);
g_signal_connect (device,
"notify::" NM_DEVICE_STATE,
G_CALLBACK (state_changed_cb),
NULL);
priv->aps = g_ptr_array_new ();
}
static void

View file

@ -105,6 +105,8 @@ enum {
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
ACTIVE_CONNECTION_ADDED,
ACTIVE_CONNECTION_REMOVED,
PERMISSION_CHANGED,
LAST_SIGNAL
@ -127,6 +129,8 @@ nm_manager_init (NMManager *manager)
priv->connectivity = NM_CONNECTIVITY_UNKNOWN;
priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal);
priv->devices = g_ptr_array_new ();
priv->active_connections = g_ptr_array_new ();
}
static void
@ -150,8 +154,6 @@ wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
}
static void manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data);
static void active_connections_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data);
static void object_creation_failed_cb (GObject *object, GError *error, char *failed_path);
static void
init_dbus (NMObject *object)
@ -168,7 +170,7 @@ init_dbus (NMObject *object)
{ NM_MANAGER_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled },
{ NM_MANAGER_WIMAX_ENABLED, &priv->wimax_enabled },
{ NM_MANAGER_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled },
{ NM_MANAGER_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_MANAGER_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION, "active-connection" },
{ NM_MANAGER_CONNECTIVITY, &priv->connectivity },
{ NM_MANAGER_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
@ -647,9 +649,6 @@ nm_manager_get_device_by_path (NMManager *manager, const char *object_path)
g_return_val_if_fail (object_path, NULL);
devices = nm_manager_get_devices (manager);
if (!devices)
return NULL;
for (i = 0; i < devices->len; i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) {
@ -672,9 +671,6 @@ nm_manager_get_device_by_iface (NMManager *manager, const char *iface)
g_return_val_if_fail (iface, NULL);
devices = nm_manager_get_devices (manager);
if (!devices)
return NULL;
for (i = 0; i < devices->len; i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
if (!strcmp (nm_device_get_iface (candidate), iface)) {
@ -749,56 +745,56 @@ activate_info_complete (ActivateInfo *info,
g_slice_free (ActivateInfo, info);
}
static NMActiveConnection *
find_active_connection_by_path (NMManager *self, const char *ac_path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
int i;
for (i = 0; i < priv->active_connections->len; i++) {
NMActiveConnection *candidate = g_ptr_array_index (priv->active_connections, i);
const char *candidate_path = nm_object_get_path (NM_OBJECT (candidate));
if (g_strcmp0 (ac_path, candidate_path) == 0)
return candidate;
}
return NULL;
}
static void
recheck_pending_activations (NMManager *self, const char *failed_path, GError *error)
recheck_pending_activations (NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter, *next;
const GPtrArray *active_connections;
gboolean found_in_active = FALSE;
gboolean found_in_pending = FALSE;
ActivateInfo *ainfo = NULL;
int i;
NMActiveConnection *candidate;
const GPtrArray *devices;
NMDevice *device;
active_connections = nm_manager_get_active_connections (self);
/* For each pending activation, look for a active connection that has
* the pending activation's object path, and call pending connection's
* callback.
* If the connection to activate doesn't make it to active_connections,
* due to an error, we have to call the callback for failed_path.
/* For each pending activation, look for an active connection that has the
* pending activation's object path, where the active connection and its
* device have both updated their properties to point to each other, and
* call the pending connection's callback.
*/
for (iter = priv->pending_activations; iter; iter = next) {
ActivateInfo *info = iter->data;
next = g_slist_next (iter);
if (!found_in_pending && failed_path && g_strcmp0 (failed_path, info->active_path) == 0) {
found_in_pending = TRUE;
ainfo = info;
}
candidate = find_active_connection_by_path (self, info->active_path);
if (!candidate)
continue;
for (i = 0; i < active_connections->len; i++) {
NMActiveConnection *active = g_ptr_array_index (active_connections, i);
const char *active_path = nm_object_get_path (NM_OBJECT (active));
/* Check that the AC and device are both ready */
devices = nm_active_connection_get_devices (candidate);
if (devices->len == 0)
continue;
device = devices->pdata[0];
if (nm_device_get_active_connection (device) != candidate)
continue;
if (!found_in_active && failed_path && g_strcmp0 (failed_path, active_path) == 0)
found_in_active = TRUE;
if (g_strcmp0 (info->active_path, active_path) == 0) {
/* Call the pending activation's callback and it all up */
activate_info_complete (info, active, NULL);
break;
}
}
}
if (!found_in_active && found_in_pending) {
/* A newly activated connection failed due to some immediate error
* and disappeared from active connection list. Make sure the
* callback gets called.
*/
activate_info_complete (ainfo, NULL, error);
activate_info_complete (info, candidate, NULL);
break;
}
}
@ -832,7 +828,7 @@ activate_cb (GObject *object,
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager, NULL, NULL);
recheck_pending_activations (info->manager);
} else {
activate_info_complete (info, NULL, error);
g_clear_error (&error);
@ -907,7 +903,7 @@ add_activate_cb (GObject *object,
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager, NULL, NULL);
recheck_pending_activations (info->manager);
} else {
activate_info_complete (info, NULL, error);
g_clear_error (&error);
@ -971,16 +967,71 @@ nm_manager_add_and_activate_connection_finish (NMManager *manager,
}
static void
active_connections_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
{
recheck_pending_activations (NM_MANAGER (object), NULL, NULL);
NMManager *self = user_data;
recheck_pending_activations (self);
}
static void
device_added (NMManager *self, NMDevice *device)
{
g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
G_CALLBACK (device_ac_changed), self);
}
static void
device_removed (NMManager *self, NMDevice *device)
{
g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_ac_changed), self);
}
static void
ac_devices_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
{
NMManager *self = user_data;
recheck_pending_activations (self);
}
static void
active_connection_added (NMManager *self, NMActiveConnection *ac)
{
g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_DEVICES,
G_CALLBACK (ac_devices_changed), self);
recheck_pending_activations (self);
}
static void
active_connection_removed (NMManager *self, NMActiveConnection *ac)
{
g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self);
}
static void
object_creation_failed_cb (GObject *object, GError *error, char *failed_path)
{
if (error)
recheck_pending_activations (NM_MANAGER (object), failed_path, error);
NMManager *self = NM_MANAGER (object);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *iter;
g_return_if_fail (error != NULL);
g_return_if_fail (find_active_connection_by_path (self, failed_path) == NULL);
/* A newly activated connection failed due to some immediate error
* and disappeared from active connection list. Make sure the
* callback gets called.
*/
for (iter = priv->pending_activations; iter; iter = iter->next) {
ActivateInfo *info = iter->data;
if (g_strcmp0 (failed_path, info->active_path) == 0) {
activate_info_complete (info, NULL, error);
return;
}
}
}
gboolean
@ -1097,19 +1148,21 @@ free_active_connections (NMManager *manager, gboolean in_dispose)
return;
active_connections = priv->active_connections;
priv->active_connections = NULL;
if (in_dispose)
priv->active_connections = NULL;
else
priv->active_connections = g_ptr_array_new ();
for (i = 0; i < active_connections->len; i++) {
active_connection = active_connections->pdata[i];
g_signal_emit (manager, signals[ACTIVE_CONNECTION_REMOVED], 0, active_connection);
/* Break circular refs */
g_object_run_dispose (G_OBJECT (active_connection));
}
g_ptr_array_unref (active_connections);
if (!in_dispose) {
priv->active_connections = g_ptr_array_new ();
if (!in_dispose)
g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS);
}
}
static void
@ -1176,9 +1229,6 @@ constructed (GObject *object)
g_signal_connect (object, "notify::" NM_MANAGER_WIRELESS_ENABLED,
G_CALLBACK (wireless_enabled_cb), NULL);
g_signal_connect (object, "notify::" NM_MANAGER_ACTIVE_CONNECTIONS,
G_CALLBACK (active_connections_changed_cb), NULL);
g_signal_connect (object, "object-creation-failed",
G_CALLBACK (object_creation_failed_cb), NULL);
}
@ -1455,6 +1505,11 @@ nm_manager_class_init (NMManagerClass *manager_class)
nm_object_class->init_dbus = init_dbus;
manager_class->device_added = device_added;
manager_class->device_removed = device_removed;
manager_class->active_connection_added = active_connection_added;
manager_class->active_connection_removed = active_connection_removed;
/* properties */
g_object_class_install_property
@ -1574,6 +1629,22 @@ nm_manager_class_init (NMManagerClass *manager_class)
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ACTIVE_CONNECTION_ADDED] =
g_signal_new ("active-connection-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, active_connection_added),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[ACTIVE_CONNECTION_REMOVED] =
g_signal_new ("active-connection-removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, active_connection_removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
G_TYPE_OBJECT);
signals[PERMISSION_CHANGED] =
g_signal_new ("permission-changed",
G_OBJECT_CLASS_TYPE (object_class),

View file

@ -61,6 +61,8 @@ typedef struct {
/* Signals */
void (*device_added) (NMManager *manager, NMDevice *device);
void (*device_removed) (NMManager *manager, NMDevice *device);
void (*active_connection_added) (NMManager *manager, NMActiveConnection *ac);
void (*active_connection_removed) (NMManager *manager, NMActiveConnection *ac);
void (*permission_changed) (NMManager *manager,
NMClientPermission permission,
NMClientPermissionResult result);

View file

@ -736,21 +736,7 @@ create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
NMObjectTypeAsyncData *async_data = user_data;
GError *error = NULL;
if (g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
NMObject *cached;
/* Unlike in the sync case, in the async case we can't cache the object
* until it is completely initialized. But that means someone else might
* have been creating it at the same time, and they might have finished
* before us.
*/
cached = _nm_object_cache_get (nm_object_get_path (NM_OBJECT (object)));
if (cached) {
g_object_unref (object);
object = G_OBJECT (cached);
} else
_nm_object_cache_add (NM_OBJECT (object));
} else {
if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
dbgmsg ("Could not create object for %s: %s",
nm_object_get_path (NM_OBJECT (object)),
error->message);
@ -766,6 +752,17 @@ create_async_got_type (NMObjectTypeAsyncData *async_data, GType type)
{
GObject *object;
/* Ensure we don't have the object already; we may get multiple type
* requests for the same object if there are multiple properties on
* other objects that refer to the object at this path. One of those
* other requests may have already completed.
*/
object = (GObject *) _nm_object_cache_get (async_data->path);
if (object) {
create_async_complete (object, async_data);
return;
}
if (type == G_TYPE_INVALID) {
/* Don't know how to create this object */
create_async_complete (NULL, async_data);
@ -776,6 +773,7 @@ create_async_got_type (NMObjectTypeAsyncData *async_data, GType type)
NM_OBJECT_PATH, async_data->path,
NM_OBJECT_DBUS_CONNECTION, async_data->connection,
NULL);
_nm_object_cache_add (NM_OBJECT (object));
g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT,
NULL, create_async_inited, async_data);
}

View file

@ -652,6 +652,7 @@ nm_remote_settings_init (NMRemoteSettings *self)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
priv->all_connections = g_ptr_array_new ();
priv->visible_connections = g_ptr_array_new ();
}

View file

@ -116,3 +116,70 @@ nm_test_service_cleanup (NMTestServiceInfo *info)
memset (info, 0, sizeof (*info));
g_free (info);
}
typedef struct {
GMainLoop *loop;
const char *ifname;
char *path;
NMDevice *device;
} AddDeviceInfo;
static void
device_added_cb (NMClient *client,
NMDevice *device,
gpointer user_data)
{
AddDeviceInfo *info = user_data;
g_assert (device);
g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, info->path);
g_assert_cmpstr (nm_device_get_iface (device), ==, info->ifname);
info->device = device;
g_main_loop_quit (info->loop);
}
static gboolean
timeout (gpointer user_data)
{
g_assert_not_reached ();
return G_SOURCE_REMOVE;
}
NMDevice *
nm_test_service_add_device (NMTestServiceInfo *sinfo, NMClient *client,
const char *method, const char *ifname)
{
AddDeviceInfo info;
GError *error = NULL;
GVariant *ret;
guint timeout_id;
ret = g_dbus_proxy_call_sync (sinfo->proxy,
method,
g_variant_new ("(s)", ifname),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
g_variant_get (ret, "(o)", &info.path);
g_variant_unref (ret);
/* Wait for libnm to find the device */
info.ifname = ifname;
info.loop = g_main_loop_new (NULL, FALSE);
g_signal_connect (client, "device-added",
G_CALLBACK (device_added_cb), &info);
timeout_id = g_timeout_add_seconds (5, timeout, NULL);
g_main_loop_run (info.loop);
g_source_remove (timeout_id);
g_signal_handlers_disconnect_by_func (client, device_added_cb, &info);
g_free (info.path);
g_main_loop_unref (info.loop);
return info.device;
}

View file

@ -19,6 +19,7 @@
*/
#include <gio/gio.h>
#include <NetworkManager.h>
typedef struct {
GDBusConnection *bus;
@ -29,3 +30,8 @@ typedef struct {
NMTestServiceInfo *nm_test_service_init (void);
void nm_test_service_cleanup (NMTestServiceInfo *info);
NMDevice *nm_test_service_add_device (NMTestServiceInfo *info,
NMClient *client,
const char *method,
const char *ifname);

View file

@ -28,6 +28,8 @@
#include "common.h"
#include "nm-test-utils.h"
static GMainLoop *loop = NULL;
static NMTestServiceInfo *sinfo;
@ -40,65 +42,14 @@ loop_quit (gpointer user_data)
return G_SOURCE_REMOVE;
}
static gboolean
add_device (const char *method, const char *ifname, char **out_path)
{
GError *error = NULL;
GVariant *ret;
ret = g_dbus_proxy_call_sync (sinfo->proxy,
method,
g_variant_new ("(s)", ifname),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
if (out_path)
g_variant_get (ret, "(o)", out_path);
g_variant_unref (ret);
return TRUE;
}
/*******************************************************************/
typedef struct {
GMainLoop *loop;
gboolean signaled;
gboolean notified;
guint quit_count;
guint quit_id;
} DeviceAddedInfo;
static void
device_add_check_quit (DeviceAddedInfo *info)
{
info->quit_count--;
if (info->quit_count == 0) {
g_source_remove (info->quit_id);
info->quit_id = 0;
g_main_loop_quit (info->loop);
}
}
static void
device_added_cb (NMClient *c,
NMDevice *device,
DeviceAddedInfo *info)
{
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
info->signaled = TRUE;
device_add_check_quit (info);
}
static void
devices_notify_cb (NMClient *c,
GParamSpec *pspec,
DeviceAddedInfo *info)
gpointer user_data)
{
gboolean *notified = user_data;
const GPtrArray *devices;
NMDevice *device;
@ -110,9 +61,7 @@ devices_notify_cb (NMClient *c,
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
info->notified = TRUE;
device_add_check_quit (info);
*notified = TRUE;
}
static void
@ -121,7 +70,7 @@ test_device_added (void)
NMClient *client;
const GPtrArray *devices;
NMDevice *device;
DeviceAddedInfo info = { loop, FALSE, FALSE, 0, 0 };
gboolean notified = FALSE;
GError *error = NULL;
sinfo = nm_test_service_init ();
@ -131,30 +80,18 @@ test_device_added (void)
devices = nm_client_get_devices (client);
g_assert (devices->len == 0);
/* Tell the test service to add a new device */
add_device ("AddWiredDevice", "eth0", NULL);
g_signal_connect (client,
"device-added",
(GCallback) device_added_cb,
&info);
info.quit_count++;
g_signal_connect (client,
"notify::devices",
(GCallback) devices_notify_cb,
&info);
info.quit_count++;
&notified);
/* Wait for libnm to find the device */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
g_main_loop_run (loop);
/* Tell the test service to add a new device */
nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
g_assert (info.signaled);
g_assert (info.notified);
while (!notified)
g_main_context_iteration (NULL, TRUE);
g_signal_handlers_disconnect_by_func (client, device_added_cb, &info);
g_signal_handlers_disconnect_by_func (client, devices_notify_cb, &info);
g_signal_handlers_disconnect_by_func (client, devices_notify_cb, &notified);
devices = nm_client_get_devices (client);
g_assert (devices);
@ -193,16 +130,6 @@ wifi_check_quit (WifiApInfo *info)
}
}
static void
wifi_device_added_cb (NMClient *c,
NMDevice *device,
WifiApInfo *info)
{
g_assert_cmpstr (nm_device_get_iface (device), ==, "wlan0");
info->found = TRUE;
wifi_check_quit (info);
}
static void
got_ap_path (WifiApInfo *info, const char *path)
{
@ -288,26 +215,11 @@ test_wifi_ap_added_removed (void)
/*************************************/
/* Add the wifi device */
add_device ("AddWifiDevice", "wlan0", NULL);
g_signal_connect (client,
"device-added",
(GCallback) wifi_device_added_cb,
&info);
info.quit_count = 1;
/* Wait for libnm to find the device */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
g_main_loop_run (loop);
g_assert (info.found);
g_signal_handlers_disconnect_by_func (client, wifi_device_added_cb, &info);
wifi = (NMDeviceWifi *) nm_client_get_device_by_iface (client, "wlan0");
wifi = (NMDeviceWifi *) nm_test_service_add_device (sinfo, client, "AddWifiDevice", "wlan0");
g_assert (NM_IS_DEVICE_WIFI (wifi));
/*************************************/
/* Add the wifi device */
/* Add the wifi AP */
info.signaled = FALSE;
info.notified = FALSE;
info.quit_id = 0;
@ -417,16 +329,6 @@ wimax_check_quit (WimaxNspInfo *info)
}
}
static void
wimax_device_added_cb (NMClient *c,
NMDevice *device,
WimaxNspInfo *info)
{
g_assert_cmpstr (nm_device_get_iface (device), ==, "wmx0");
info->found = TRUE;
wimax_check_quit (info);
}
static void
got_nsp_path (WimaxNspInfo *info, const char *path)
{
@ -512,22 +414,7 @@ test_wimax_nsp_added_removed (void)
/*************************************/
/* Add the wimax device */
add_device ("AddWimaxDevice", "wmx0", NULL);
g_signal_connect (client,
"device-added",
(GCallback) wimax_device_added_cb,
&info);
info.quit_count = 1;
/* Wait for libnm to find the device */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
g_main_loop_run (loop);
g_assert (info.found);
g_signal_handlers_disconnect_by_func (client, wimax_device_added_cb, &info);
wimax = (NMDeviceWimax *) nm_client_get_device_by_iface (client, "wmx0");
wimax = (NMDeviceWimax *) nm_test_service_add_device (sinfo, client, "AddWimaxDevice", "wmx0");
g_assert (NM_IS_DEVICE_WIMAX (wimax));
/*************************************/
@ -637,14 +524,6 @@ da_check_quit (DaInfo *info)
}
}
static void
da_device_added_cb (NMClient *c,
NMDevice *device,
DaInfo *info)
{
da_check_quit (info);
}
static void
da_device_removed_cb (NMClient *c,
NMDevice *device,
@ -700,8 +579,7 @@ test_devices_array (void)
{
NMClient *client = NULL;
DaInfo info = { loop };
char *paths[3] = { NULL, NULL, NULL };
NMDevice *device;
NMDevice *wlan0, *eth0, *eth1, *device;
const GPtrArray *devices;
GError *error = NULL;
GVariant *ret;
@ -715,22 +593,9 @@ test_devices_array (void)
/*************************************/
/* Add some devices */
add_device ("AddWifiDevice", "wlan0", &paths[0]);
add_device ("AddWiredDevice", "eth0", &paths[1]);
add_device ("AddWiredDevice", "eth1", &paths[2]);
info.quit_count = 3;
g_signal_connect (client,
"device-added",
(GCallback) da_device_added_cb,
&info);
/* Wait for libnm to find the device */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
g_main_loop_run (loop);
g_assert_cmpint (info.quit_count, ==, 0);
g_signal_handlers_disconnect_by_func (client, da_device_added_cb, &info);
wlan0 = nm_test_service_add_device (sinfo, client,"AddWifiDevice", "wlan0");
eth0 = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
eth1 = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth1");
/* Ensure the devices now exist */
devices = nm_client_get_devices (client);
@ -739,18 +604,21 @@ test_devices_array (void)
device = nm_client_get_device_by_iface (client, "wlan0");
g_assert (NM_IS_DEVICE_WIFI (device));
g_assert (device == wlan0);
device = nm_client_get_device_by_iface (client, "eth0");
g_assert (NM_IS_DEVICE_ETHERNET (device));
g_assert (device == eth0);
device = nm_client_get_device_by_iface (client, "eth1");
g_assert (NM_IS_DEVICE_ETHERNET (device));
g_assert (device == eth1);
/********************************/
/* Now remove the device in the middle */
ret = g_dbus_proxy_call_sync (sinfo->proxy,
"RemoveDevice",
g_variant_new ("(o)", paths[1]),
g_variant_new ("(o)", nm_object_get_path (NM_OBJECT (eth0))),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
@ -770,7 +638,7 @@ test_devices_array (void)
&info);
info.quit_count = 2;
/* Wait for libnm to find the device */
/* Wait for libnm to notice the changes */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
g_main_loop_run (loop);
@ -785,13 +653,11 @@ test_devices_array (void)
device = nm_client_get_device_by_iface (client, "wlan0");
g_assert (NM_IS_DEVICE_WIFI (device));
g_assert (device == wlan0);
device = nm_client_get_device_by_iface (client, "eth1");
g_assert (NM_IS_DEVICE_ETHERNET (device));
g_free (paths[0]);
g_free (paths[1]);
g_free (paths[2]);
g_assert (device == eth1);
g_object_unref (client);
g_clear_pointer (&sinfo, nm_test_service_cleanup);
@ -866,8 +732,333 @@ test_client_nm_running (void)
g_object_unref (client2);
}
typedef struct {
GMainLoop *loop;
NMActiveConnection *ac;
int remaining;
} TestACInfo;
static void
assert_ac_and_device (NMClient *client)
{
const GPtrArray *devices, *acs, *ac_devices;
NMDevice *device, *ac_device;
NMActiveConnection *ac, *device_ac;
acs = nm_client_get_active_connections (client);
g_assert (acs != NULL);
g_assert_cmpint (acs->len, ==, 1);
devices = nm_client_get_devices (client);
g_assert (devices != NULL);
g_assert_cmpint (devices->len, >=, 1);
ac = acs->pdata[0];
ac_devices = nm_active_connection_get_devices (ac);
g_assert (ac_devices != NULL);
g_assert_cmpint (ac_devices->len, ==, 1);
ac_device = ac_devices->pdata[0];
g_assert (ac_device != NULL);
device = devices->pdata[0];
if (device != ac_device && devices->len > 1)
device = devices->pdata[1];
device_ac = nm_device_get_active_connection (device);
g_assert (device_ac != NULL);
g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, nm_object_get_path (NM_OBJECT (ac_device)));
g_assert (device == ac_device);
g_assert_cmpstr (nm_object_get_path (NM_OBJECT (ac)), ==, nm_object_get_path (NM_OBJECT (device_ac)));
g_assert (ac == device_ac);
}
static void
add_and_activate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient *client = NM_CLIENT (object);
TestACInfo *info = user_data;
GError *error = NULL;
info->ac = nm_client_add_and_activate_connection_finish (client, result, &error);
g_assert_no_error (error);
g_assert (info->ac != NULL);
assert_ac_and_device (client);
info->remaining--;
if (!info->remaining)
g_main_loop_quit (info->loop);
}
static void
client_acs_changed_cb (GObject *client,
GParamSpec *pspec,
gpointer user_data)
{
TestACInfo *info = user_data;
const GPtrArray *acs;
acs = nm_client_get_active_connections (NM_CLIENT (client));
g_assert (acs != NULL);
g_assert_cmpint (acs->len, ==, 1);
info->remaining--;
if (!info->remaining)
g_main_loop_quit (info->loop);
}
static void
device_ac_changed_cb (GObject *device,
GParamSpec *pspec,
gpointer user_data)
{
TestACInfo *info = user_data;
g_assert (nm_device_get_active_connection (NM_DEVICE (device)) != NULL);
info->remaining--;
if (!info->remaining)
g_main_loop_quit (info->loop);
}
static void
test_active_connections (void)
{
NMClient *client;
NMDevice *device;
NMConnection *conn;
TestACInfo info = { loop, NULL, 0 };
GError *error = NULL;
sinfo = nm_test_service_init ();
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
/* Tell the test service to add a new device */
device = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
conn = nmtst_create_minimal_connection ("test-ac", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_client_add_and_activate_connection_async (client, conn, device, NULL,
NULL, add_and_activate_cb, &info);
g_object_unref (conn);
g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
G_CALLBACK (client_acs_changed_cb), &info);
g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
G_CALLBACK (device_ac_changed_cb), &info);
/* Two signals plus activate_cb */
info.remaining = 3;
g_main_loop_run (loop);
g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info);
g_signal_handlers_disconnect_by_func (device, device_ac_changed_cb, &info);
g_assert (info.ac != NULL);
g_object_unref (info.ac);
g_object_unref (client);
/* Ensure that we can correctly resolve the recursive property link between the
* AC and the Device in a newly-created client.
*/
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
assert_ac_and_device (client);
g_object_unref (client);
client = NULL;
nm_client_new_async (NULL, new_client_cb, &client);
g_main_loop_run (loop);
assert_ac_and_device (client);
g_object_unref (client);
g_clear_pointer (&sinfo, nm_test_service_cleanup);
}
static void
client_devices_changed_cb (GObject *client,
GParamSpec *pspec,
gpointer user_data)
{
TestACInfo *info = user_data;
const GPtrArray *devices;
NMDevice *device;
devices = nm_client_get_devices (NM_CLIENT (client));
g_assert (devices != NULL);
g_assert_cmpint (devices->len, ==, 2);
if (NM_IS_DEVICE_VLAN (devices->pdata[0]))
device = devices->pdata[0];
else if (NM_IS_DEVICE_VLAN (devices->pdata[1]))
device = devices->pdata[1];
else
g_assert_not_reached ();
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0.1");
if (nm_device_get_active_connection (device))
info->remaining--;
else {
g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
G_CALLBACK (device_ac_changed_cb), &info);
}
info->remaining--;
if (!info->remaining)
g_main_loop_quit (info->loop);
}
typedef struct {
GMainLoop *loop;
NMRemoteConnection *remote;
} TestConnectionInfo;
static void
add_connection_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
TestConnectionInfo *info = user_data;
GError *error = NULL;
info->remote = nm_client_add_connection_finish (NM_CLIENT (object), result, &error);
g_assert_no_error (error);
g_main_loop_quit (info->loop);
}
static void
activate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient *client = NM_CLIENT (object);
TestACInfo *info = user_data;
GError *error = NULL;
info->ac = nm_client_activate_connection_finish (client, result, &error);
g_assert_no_error (error);
g_assert (info->ac != NULL);
assert_ac_and_device (client);
info->remaining--;
if (!info->remaining)
g_main_loop_quit (info->loop);
}
static void
test_activate_virtual (void)
{
NMClient *client;
NMConnection *conn;
NMSettingConnection *s_con;
NMSettingVlan *s_vlan;
TestACInfo info = { loop, NULL, 0 };
TestConnectionInfo conn_info = { loop, NULL };
GError *error = NULL;
sinfo = nm_test_service_init ();
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
conn = nmtst_create_minimal_connection ("test-ac", NULL, NM_SETTING_VLAN_SETTING_NAME, &s_con);
g_object_set (s_con,
NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0.1",
NULL);
s_vlan = nm_connection_get_setting_vlan (conn);
g_object_set (s_vlan,
NM_SETTING_VLAN_ID, 1,
NM_SETTING_VLAN_PARENT, "eth0",
NULL);
nm_client_add_connection_async (client, conn, TRUE,
NULL, add_connection_cb, &conn_info);
g_main_loop_run (loop);
g_object_unref (conn);
conn = NM_CONNECTION (conn_info.remote);
nm_client_activate_connection_async (client, conn, NULL, NULL,
NULL, activate_cb, &info);
g_object_unref (conn);
g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
G_CALLBACK (client_acs_changed_cb), &info);
g_signal_connect (client, "notify::" NM_CLIENT_DEVICES,
G_CALLBACK (client_devices_changed_cb), &info);
/* As with test_active_connections() above, except that now we're waiting
* for NMClient:devices to change rather than NMDevice:active-connections.
*/
info.remaining = 3;
g_main_loop_run (loop);
g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info);
g_signal_handlers_disconnect_by_func (client, client_devices_changed_cb, &info);
g_assert (info.ac != NULL);
g_object_unref (info.ac);
g_object_unref (client);
g_clear_pointer (&sinfo, nm_test_service_cleanup);
}
static void
activate_failed_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient *client = NM_CLIENT (object);
NMActiveConnection *ac;
GError *error = NULL;
ac = nm_client_activate_connection_finish (client, result, &error);
g_assert (ac == NULL);
g_assert_error (error, NM_OBJECT_ERROR, NM_OBJECT_ERROR_OBJECT_CREATION_FAILURE);
g_clear_error (&error);
g_main_loop_quit (loop);
}
static void
test_activate_failed (void)
{
NMClient *client;
NMDevice *device;
NMConnection *conn;
GError *error = NULL;
sinfo = nm_test_service_init ();
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
device = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
/* Note that test-networkmanager-service.py checks for this exact name */
conn = nmtst_create_minimal_connection ("object-creation-failed-test", NULL,
NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_client_add_and_activate_connection_async (client, conn, device, NULL,
NULL, activate_failed_cb, NULL);
g_test_expect_message ("libnm", G_LOG_LEVEL_WARNING, "*Method*doesn't exist*");
g_main_loop_run (loop);
g_test_assert_expected_messages ();
g_object_unref (conn);
g_object_unref (client);
g_clear_pointer (&sinfo, nm_test_service_cleanup);
}
/*******************************************************************/
NMTST_DEFINE ();
int
main (int argc, char **argv)
{
@ -877,7 +1068,7 @@ main (int argc, char **argv)
g_type_init ();
#endif
g_test_init (&argc, &argv, NULL);
nmtst_init (&argc, &argv, TRUE);
loop = g_main_loop_new (NULL, FALSE);
@ -886,6 +1077,9 @@ main (int argc, char **argv)
g_test_add_func ("/libnm/wimax-nsp-added-removed", test_wimax_nsp_added_removed);
g_test_add_func ("/libnm/devices-array", test_devices_array);
g_test_add_func ("/libnm/client-nm-running", test_client_nm_running);
g_test_add_func ("/libnm/active-connections", test_active_connections);
g_test_add_func ("/libnm/activate-virtual", test_activate_virtual);
g_test_add_func ("/libnm/activate-failed", test_activate_failed);
return g_test_run ();
}

View file

@ -192,7 +192,6 @@ typedef struct {
char *ifname;
char *con_id;
char *devpath;
int secrets_requested;
} TestSecretAgentData;
@ -203,20 +202,6 @@ timeout_assert (gpointer user_data)
g_assert_not_reached ();
}
static void
device_added_cb (NMClient *c,
NMDevice *device,
gpointer user_data)
{
TestSecretAgentData *sadata = user_data;
g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, sadata->ifname);
sadata->device = device;
g_main_loop_quit (sadata->loop);
}
static void
connection_added_cb (GObject *s,
GAsyncResult *result,
@ -261,8 +246,6 @@ test_setup (TestSecretAgentData *sadata, gconstpointer test_data)
GBytes *ssid;
NMSetting *s_wsec;
GError *error = NULL;
GVariant *ret;
gulong handler;
sadata->sinfo = nm_test_service_init ();
sadata->client = nm_client_new (NULL, &error);
@ -276,24 +259,8 @@ test_setup (TestSecretAgentData *sadata, gconstpointer test_data)
counter++;
/* Create the device */
ret = g_dbus_proxy_call_sync (sadata->sinfo->proxy,
"AddWifiDevice",
g_variant_new ("(s)", sadata->ifname),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
&error);
g_assert_no_error (error);
g_assert (ret);
g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
g_variant_get (ret, "(o)", &sadata->devpath);
g_variant_unref (ret);
handler = g_signal_connect (sadata->client, "device-added",
G_CALLBACK (device_added_cb), sadata);
g_main_loop_run (sadata->loop);
g_signal_handler_disconnect (sadata->client, handler);
g_assert (sadata->device);
sadata->device = nm_test_service_add_device (sadata->sinfo, sadata->client,
"AddWifiDevice", sadata->ifname);
/* Create the connection */
connection = nmtst_create_minimal_connection (sadata->con_id, NULL, NM_SETTING_WIRELESS_SETTING_NAME, &s_con);
@ -353,12 +320,9 @@ test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data)
g_object_unref (sadata->agent);
}
g_object_unref (sadata->connection);
g_object_unref (sadata->client);
ret = g_dbus_proxy_call_sync (sadata->sinfo->proxy,
"RemoveDevice",
g_variant_new ("(s)", sadata->devpath),
g_variant_new ("(s)", nm_object_get_path (NM_OBJECT (sadata->device))),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
@ -366,6 +330,9 @@ test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data)
g_assert_no_error (error);
g_variant_unref (ret);
g_object_unref (sadata->connection);
g_object_unref (sadata->client);
nm_test_service_cleanup (sadata->sinfo);
g_source_remove (sadata->timeout_id);
@ -373,7 +340,6 @@ test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data)
g_free (sadata->ifname);
g_free (sadata->con_id);
g_free (sadata->devpath);
}
/*******************************************************************/
@ -531,14 +497,9 @@ connection_activated_good_cb (GObject *c,
GError *error = NULL;
ac = nm_client_activate_connection_finish (sadata->client, result, &error);
g_assert_no_error (error);
/* test-networkmanager-service.py doesn't implement activation, but
* we should at least get as far as the error telling us that (which the
* other tests won't get to).
*/
g_assert (error != NULL);
g_dbus_error_strip_remote_error (error);
g_assert_cmpstr (error->message, ==, "Not yet implemented");
g_object_unref (ac);
g_main_loop_quit (sadata->loop);
}

View file

@ -51,6 +51,7 @@ typedef struct {
gboolean is_default;
gboolean is_default6;
NMActiveConnectionState state;
gboolean state_set;
gboolean vpn;
NMAuthSubject *subject;
@ -138,6 +139,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
old_state = priv->state;
priv->state = new_state;
priv->state_set = TRUE;
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE);
check_master_ready (self);
@ -748,7 +750,14 @@ get_property (GObject *object, guint prop_id,
g_value_take_boxed (value, devices);
break;
case PROP_STATE:
g_value_set_uint (value, priv->state);
if (priv->state_set)
g_value_set_uint (value, priv->state);
else {
/* When the AC has just been created, its externally-visible state should
* be "ACTIVATING", even though internally it is "UNKNOWN".
*/
g_value_set_uint (value, NM_ACTIVE_CONNECTION_STATE_ACTIVATING);
}
break;
case PROP_DEFAULT:
g_value_set_boolean (value, priv->is_default);

View file

@ -37,6 +37,7 @@ NM_DEVICE_STATE_ACTIVATED = 100
NM_DEVICE_STATE_DEACTIVATING = 110
NM_DEVICE_STATE_FAILED = 120
# Device type
NM_DEVICE_TYPE_UNKNOWN = 0
NM_DEVICE_TYPE_ETHERNET = 1
NM_DEVICE_TYPE_WIFI = 2
@ -54,6 +55,13 @@ NM_DEVICE_TYPE_BRIDGE = 13
NM_DEVICE_TYPE_GENERIC = 14
NM_DEVICE_TYPE_TEAM = 15
# AC state
NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0
NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1
NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3
NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4
#########################################################
IFACE_DBUS = 'org.freedesktop.DBus'
@ -171,6 +179,9 @@ class Device(ExportedObj):
def PropertiesChanged(self, changed):
pass
def set_active_connection(self, ac):
self.active_connection = ac
self.__notify(PD_ACTIVE_CONNECTION)
###################################################################
@ -214,6 +225,34 @@ class WiredDevice(Device):
def PropertiesChanged(self, changed):
pass
###################################################################
IFACE_VLAN = 'org.freedesktop.NetworkManager.Device.Vlan'
PV_HW_ADDRESS = "HwAddress"
PV_CARRIER = "Carrier"
PV_VLAN_ID = "VlanId"
class VlanDevice(Device):
def __init__(self, bus, iface):
Device.__init__(self, bus, iface, NM_DEVICE_TYPE_VLAN)
self.add_dbus_interface(IFACE_VLAN, self.__get_props)
self.mac = random_mac()
self.carrier = False
self.vlan_id = 1
# Properties interface
def __get_props(self):
props = {}
props[PV_HW_ADDRESS] = self.mac
props[PV_CARRIER] = self.carrier
props[PV_VLAN_ID] = self.vlan_id
return props
@dbus.service.signal(IFACE_VLAN, signature='a{sv}')
def PropertiesChanged(self, changed):
pass
###################################################################
IFACE_WIFI_AP = 'org.freedesktop.NetworkManager.AccessPoint'
@ -507,6 +546,73 @@ class WimaxDevice(Device):
return
raise NspNotFoundException("NSP %s not found" % path)
###################################################################
IFACE_ACTIVE_CONNECTION = 'org.freedesktop.NetworkManager.Connection.Active'
PAC_CONNECTION = "Connection"
PAC_SPECIFIC_OBJECT = "SpecificObject"
PAC_ID = "Id"
PAC_UUID = "Uuid"
PAC_TYPE = "Type"
PAC_DEVICES = "Devices"
PAC_STATE = "State"
PAC_DEFAULT = "Default"
PAC_IP4CONFIG = "Ip4Config"
PAC_DHCP4CONFIG = "Dhcp4Config"
PAC_DEFAULT6 = "Default6"
PAC_IP6CONFIG = "Ip6Config"
PAC_DHCP6CONFIG = "Dhcp6Config"
PAC_VPN = "Vpn"
PAC_MASTER = "Master"
class ActiveConnection(ExportedObj):
counter = 1
def __init__(self, bus, device, connection, specific_object):
object_path = "/org/freedesktop/NetworkManager/ActiveConnection/%d" % ActiveConnection.counter
ActiveConnection.counter = ActiveConnection.counter + 1
ExportedObj.__init__(self, bus, object_path)
self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props)
self.device = device
self.conn = connection
self.specific_object = specific_object
self.state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN
self.default = False
self.ip4config = None
self.dhcp4config = None
self.default6 = False
self.ip6config = None
self.dhcp6config = None
self.vpn = False
self.master = None
# Properties interface
def __get_props(self):
props = {}
props[PAC_CONNECTION] = to_path(self.conn)
props[PAC_SPECIFIC_OBJECT] = to_path(self.specific_object)
conn_settings = self.conn.GetSettings()
s_con = conn_settings['connection']
props[PAC_ID] = s_con['id']
props[PAC_UUID] = s_con['uuid']
props[PAC_TYPE] = s_con['type']
props[PAC_DEVICES] = to_path_array([self.device])
props[PAC_STATE] = dbus.UInt32(self.state)
props[PAC_DEFAULT] = self.default
props[PAC_IP4CONFIG] = to_path(self.ip4config)
props[PAC_DHCP4CONFIG] = to_path(self.dhcp4config)
props[PAC_DEFAULT6] = self.default6
props[PAC_IP6CONFIG] = to_path(self.ip6config)
props[PAC_DHCP6CONFIG] = to_path(self.dhcp6config)
props[PAC_VPN] = self.vpn
props[PAC_MASTER] = to_path(self.master)
return props
@dbus.service.signal(IFACE_ACTIVE_CONNECTION, signature='a{sv}')
def PropertiesChanged(self, changed):
pass
###################################################################
IFACE_TEST = 'org.freedesktop.NetworkManager.LibnmGlibTest'
IFACE_NM = 'org.freedesktop.NetworkManager'
@ -536,11 +642,15 @@ PM_STATE = 'State'
PM_VERSION = 'Version'
PM_CONNECTIVITY = 'Connectivity'
def set_device_ac_cb(device, ac):
device.set_active_connection(ac)
class NetworkManager(ExportedObj):
def __init__(self, bus, object_path):
ExportedObj.__init__(self, bus, object_path)
self.add_dbus_interface(IFACE_NM, self.__get_props)
self._bus = bus;
self.devices = []
self.active_connections = []
self.primary_connection = None
@ -571,21 +681,27 @@ class NetworkManager(ExportedObj):
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='ooo', out_signature='o')
def ActivateConnection(self, conpath, devpath, specific_object):
device = None
for d in self.devices:
if d.path == devpath:
device = d
break
if not device:
raise UnknownDeviceException("No device found for the requested iface.")
try:
connection = settings.get_connection(conpath)
except Exception as e:
raise UnknownConnectionException("Connection not found")
# See if we need secrets. For the moment, we only support WPA
hash = connection.GetSettings()
s_con = hash['connection']
device = None
for d in self.devices:
if d.path == devpath:
device = d
break
if not device and s_con['type'] == 'vlan':
ifname = s_con['interface-name']
device = VlanDevice(self._bus, ifname)
self.add_device(device)
if not device:
raise UnknownDeviceException("No device found for the requested iface.")
# See if we need secrets. For the moment, we only support WPA
if hash.has_key('802-11-wireless-security'):
s_wsec = hash['802-11-wireless-security']
if (s_wsec['key-mgmt'] == 'wpa-psk' and not s_wsec.has_key('psk')):
@ -598,7 +714,17 @@ class NetworkManager(ExportedObj):
if not s_wsec.has_key('psk'):
raise NoSecretsException("No secrets provided")
raise PermissionDeniedException("Not yet implemented")
ac = ActiveConnection(self._bus, device, connection, None)
self.active_connections.append(ac)
self.__notify(PM_ACTIVE_CONNECTIONS)
if s_con['id'] == 'object-creation-failed-test':
self.active_connections.remove(ac)
ac.remove_from_connection()
else:
GLib.timeout_add(50, set_device_ac_cb, device, ac)
return to_path(ac)
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}oo', out_signature='oo')
def AddAndActivateConnection(self, connection, devpath, specific_object):
@ -610,8 +736,8 @@ class NetworkManager(ExportedObj):
if not device:
raise UnknownDeviceException("No device found for the requested iface.")
conpath = manager.AddConnection(connection)
return self.ActivateConnection(conpath, devpath, specific_object)
conpath = settings.AddConnection(connection)
return (conpath, self.ActivateConnection(conpath, devpath, specific_object))
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='o', out_signature='')
def DeactivateConnection(self, active_connection):