core: track active connection dependencies

Track a master active connection and emit wait/ready/fail when
it changes state.  This signal is intended for devices to
delay their activation until a master device is ready.
This commit is contained in:
Dan Williams
2012-02-26 17:38:41 -06:00
parent d08b33bb01
commit 0b8ff52fdd
4 changed files with 113 additions and 4 deletions

View File

@@ -60,6 +60,9 @@ typedef struct {
gboolean user_requested; gboolean user_requested;
gulong user_uid; gulong user_uid;
NMActiveConnection *dep;
guint dep_state_id;
gboolean shared; gboolean shared;
GSList *share_rules; GSList *share_rules;
@@ -70,6 +73,13 @@ enum {
PROP_MASTER = 2000, PROP_MASTER = 2000,
}; };
enum {
DEP_RESULT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/*******************************************************************/ /*******************************************************************/
typedef struct { typedef struct {
@@ -198,6 +208,27 @@ nm_act_request_get_assumed (NMActRequest *req)
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed; return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
} }
static NMActRequestDependencyResult
ac_state_to_dep_result (NMActiveConnection *ac)
{
NMActiveConnectionState state = nm_active_connection_get_state (ac);
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
return NM_ACT_REQUEST_DEP_RESULT_WAIT;
else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
return NM_ACT_REQUEST_DEP_RESULT_READY;
return NM_ACT_REQUEST_DEP_RESULT_FAILED;
}
NMActRequestDependencyResult
nm_act_request_get_dependency_result (NMActRequest *req)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req);
return priv->dep ? ac_state_to_dep_result (priv->dep) : NM_ACT_REQUEST_DEP_RESULT_READY;
}
/********************************************************************/ /********************************************************************/
static void static void
@@ -351,6 +382,39 @@ device_state_changed (NMDevice *device,
/********************************************************************/ /********************************************************************/
static void
dep_gone (NMActRequest *self, GObject *ignored)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
g_warn_if_fail (G_OBJECT (priv->dep) == ignored);
/* Dependent connection is gone; clean up and fail */
priv->dep = NULL;
priv->dep_state_id = 0;
g_signal_emit (self, signals[DEP_RESULT], 0, NM_ACT_REQUEST_DEP_RESULT_FAILED);
}
static void
dep_state_changed (NMActiveConnection *dep,
GParamSpec *pspec,
NMActRequest *self)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
NMActRequestDependencyResult result;
g_warn_if_fail (priv->dep == dep);
result = ac_state_to_dep_result (priv->dep);
if (result == NM_ACT_REQUEST_DEP_RESULT_FAILED) {
g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, self);
g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
priv->dep = NULL;
priv->dep_state_id = 0;
}
g_signal_emit (self, signals[DEP_RESULT], 0, result);
}
/** /**
* nm_act_request_new: * nm_act_request_new:
* *
@@ -364,8 +428,8 @@ device_state_changed (NMDevice *device,
* @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an * @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
* existing connection made before this instance of NM started * existing connection made before this instance of NM started
* @device: the device/interface to configure according to @connection * @device: the device/interface to configure according to @connection
* @master: if the activation depends on another device (ie, VLAN slave, bond * @dependency: if the activation depends on another device (ie, VLAN slave,
* slave, etc) pass the #NMActiveConnection that this activation request * bond slave, etc) pass the #NMActiveConnection that this activation request
* should wait for before proceeding * should wait for before proceeding
* *
* Begins activation of @device using the given @connection and other details. * Begins activation of @device using the given @connection and other details.
@@ -379,7 +443,7 @@ nm_act_request_new (NMConnection *connection,
gulong user_uid, gulong user_uid,
gboolean assumed, gboolean assumed,
gpointer *device, gpointer *device,
NMActiveConnection *master) NMActiveConnection *dependency)
{ {
GObject *object; GObject *object;
NMActRequestPrivate *priv; NMActRequestPrivate *priv;
@@ -405,6 +469,15 @@ nm_act_request_new (NMConnection *connection,
priv->user_requested = user_requested; priv->user_requested = user_requested;
priv->assumed = assumed; priv->assumed = assumed;
if (dependency) {
priv->dep = dependency;
g_object_weak_ref (G_OBJECT (dependency), (GWeakNotify) dep_gone, object);
priv->dep_state_id = g_signal_connect (dependency,
"notify::" NM_ACTIVE_CONNECTION_STATE,
G_CALLBACK (dep_state_changed),
object);
}
if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object), if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object),
connection, connection,
nm_device_get_path (NM_DEVICE (device)))) { nm_device_get_path (NM_DEVICE (device)))) {
@@ -467,6 +540,13 @@ dispose (GObject *object)
g_object_unref (priv->connection); g_object_unref (priv->connection);
if (priv->dep) {
g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, object);
g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
priv->dep = NULL;
priv->dep_state_id = 0;
}
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object); G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
} }
@@ -491,5 +571,13 @@ nm_act_request_class_init (NMActRequestClass *req_class)
object_class->finalize = finalize; object_class->finalize = finalize;
g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER); g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER);
signals[DEP_RESULT] =
g_signal_new (NM_ACT_REQUEST_DEPENDENCY_RESULT,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
} }

View File

@@ -34,6 +34,15 @@
#define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACT_REQUEST)) #define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_ACT_REQUEST))
#define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass)) #define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass))
typedef enum {
NM_ACT_REQUEST_DEP_RESULT_UNKNOWN,
NM_ACT_REQUEST_DEP_RESULT_WAIT,
NM_ACT_REQUEST_DEP_RESULT_READY,
NM_ACT_REQUEST_DEP_RESULT_FAILED,
} NMActRequestDependencyResult;
#define NM_ACT_REQUEST_DEPENDENCY_RESULT "dependency-result"
typedef struct { typedef struct {
GObject parent; GObject parent;
} NMActRequest; } NMActRequest;
@@ -43,6 +52,8 @@ typedef struct {
/* Signals */ /* Signals */
void (*properties_changed) (NMActRequest *req, GHashTable *properties); void (*properties_changed) (NMActRequest *req, GHashTable *properties);
void (*dependency_result) (NMActRequest *req, NMActRequestDependencyResult result);
} NMActRequestClass; } NMActRequestClass;
GType nm_act_request_get_type (void); GType nm_act_request_get_type (void);
@@ -53,7 +64,7 @@ NMActRequest *nm_act_request_new (NMConnection *connection,
gulong user_uid, gulong user_uid,
gboolean assumed, gboolean assumed,
gpointer *device, /* An NMDevice */ gpointer *device, /* An NMDevice */
NMActiveConnection *master); NMActiveConnection *dependency);
NMConnection *nm_act_request_get_connection (NMActRequest *req); NMConnection *nm_act_request_get_connection (NMActRequest *req);
@@ -71,6 +82,8 @@ GObject * nm_act_request_get_device (NMActRequest *req);
gboolean nm_act_request_get_assumed (NMActRequest *req); gboolean nm_act_request_get_assumed (NMActRequest *req);
NMActRequestDependencyResult nm_act_request_get_dependency_result (NMActRequest *req);
/* Secrets handling */ /* Secrets handling */
typedef void (*NMActRequestSecretsFunc) (NMActRequest *req, typedef void (*NMActRequestSecretsFunc) (NMActRequest *req,

View File

@@ -71,6 +71,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
/****************************************************************/ /****************************************************************/
NMActiveConnectionState
nm_active_connection_get_state (NMActiveConnection *self)
{
return NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->state;
}
void void
nm_active_connection_set_state (NMActiveConnection *self, nm_active_connection_set_state (NMActiveConnection *self,
NMActiveConnectionState new_state) NMActiveConnectionState new_state)

View File

@@ -78,6 +78,8 @@ void nm_active_connection_set_default6 (NMActiveConnection *self,
gboolean nm_active_connection_get_default6 (NMActiveConnection *self); gboolean nm_active_connection_get_default6 (NMActiveConnection *self);
NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *self);
void nm_active_connection_set_state (NMActiveConnection *self, void nm_active_connection_set_state (NMActiveConnection *self,
NMActiveConnectionState state); NMActiveConnectionState state);