diff options
author | Dan Winship <danw@redhat.com> | 2015-01-09 09:45:25 -0500 |
---|---|---|
committer | Dan Winship <danw@redhat.com> | 2015-01-09 09:46:19 -0500 |
commit | 07194fb6a9ec95326a91a91d9abbb247285c94b3 (patch) | |
tree | cb8336ced6e26058a8f8856c1d037af72a103611 | |
parent | c27074bf4394d22e4329faf4acfa99b0b1fed808 (diff) | |
parent | 62d870e1a6dd852e50f39b2a32cd291734766402 (diff) | |
download | NetworkManager-07194fb6a9ec95326a91a91d9abbb247285c94b3.tar.gz |
ifcfg-rh: merge branch danw/devtimeout-rh1171917
https://bugzilla.redhat.com/show_bug.cgi?id=1171917
-rw-r--r-- | src/nm-manager.c | 15 | ||||
-rw-r--r-- | src/settings/nm-settings-connection.c | 35 | ||||
-rw-r--r-- | src/settings/nm-settings-connection.h | 5 | ||||
-rw-r--r-- | src/settings/nm-settings.c | 56 | ||||
-rw-r--r-- | src/settings/nm-settings.h | 11 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c | 112 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/reader.c | 22 | ||||
-rw-r--r-- | src/settings/plugins/ifcfg-rh/reader.h | 2 |
8 files changed, 253 insertions, 5 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 5ed736be33..f1c355281e 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -687,6 +687,11 @@ check_if_startup_complete (NMManager *self) if (!priv->startup) return; + if (!nm_settings_get_startup_complete (priv->settings)) { + nm_log_dbg (LOGD_CORE, "check_if_startup_complete returns FALSE because of NMSettings"); + return; + } + for (iter = priv->devices; iter; iter = iter->next) { NMDevice *dev = iter->data; @@ -722,6 +727,14 @@ device_has_pending_action_changed (NMDevice *device, } static void +settings_startup_complete_changed (NMSettings *settings, + GParamSpec *pspec, + NMManager *self) +{ + check_if_startup_complete (self); +} + +static void remove_device (NMManager *manager, NMDevice *device, gboolean quitting, @@ -4716,6 +4729,8 @@ nm_manager_new (NMSettings *settings, priv->prop_filter_added = TRUE; priv->settings = g_object_ref (settings); + g_signal_connect (priv->settings, "notify::" NM_SETTINGS_STARTUP_COMPLETE, + G_CALLBACK (settings_startup_complete_changed), singleton); priv->state_file = g_strdup (state_file); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 25459c2077..66666ee4d2 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -82,6 +82,7 @@ enum { PROP_0 = 0, PROP_VISIBLE, PROP_UNSAVED, + PROP_READY, PROP_FLAGS, }; @@ -98,6 +99,7 @@ typedef struct { guint session_changed_id; NMSettingsConnectionFlags flags; + gboolean ready; guint updated_idle_id; @@ -2167,6 +2169,25 @@ nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *connectio return NM_FLAGS_HAS (nm_settings_connection_get_flags (connection), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED_ASSUMED); } +gboolean +nm_settings_connection_get_ready (NMSettingsConnection *connection) +{ + return NM_SETTINGS_CONNECTION_GET_PRIVATE (connection)->ready; +} + +void +nm_settings_connection_set_ready (NMSettingsConnection *connection, + gboolean ready) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + + ready = !!ready; + if (priv->ready != ready) { + priv->ready = ready; + g_object_notify (G_OBJECT (connection), NM_SETTINGS_CONNECTION_READY); + } +} + /**************************************************************/ static void @@ -2175,6 +2196,7 @@ nm_settings_connection_init (NMSettingsConnection *self) NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); priv->visible = FALSE; + priv->ready = TRUE; priv->session_changed_id = nm_session_monitor_connect (session_changed_cb, self); @@ -2249,6 +2271,9 @@ get_property (GObject *object, guint prop_id, case PROP_UNSAVED: g_value_set_boolean (value, nm_settings_connection_get_unsaved (self)); break; + case PROP_READY: + g_value_set_boolean (value, nm_settings_connection_get_ready (self)); + break; case PROP_FLAGS: g_value_set_uint (value, nm_settings_connection_get_flags (self)); break; @@ -2265,6 +2290,9 @@ set_property (GObject *object, guint prop_id, NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object); switch (prop_id) { + case PROP_READY: + nm_settings_connection_set_ready (self, g_value_get_boolean (value)); + break; case PROP_FLAGS: nm_settings_connection_set_flags_all (self, g_value_get_uint (value)); break; @@ -2306,6 +2334,13 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class) G_PARAM_STATIC_STRINGS)); g_object_class_install_property + (object_class, PROP_READY, + g_param_spec_boolean (NM_SETTINGS_CONNECTION_READY, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_FLAGS, g_param_spec_uint (NM_SETTINGS_CONNECTION_FLAGS, "", "", NM_SETTINGS_CONNECTION_FLAGS_NONE, diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h index 254e927bfd..cd41c1d5f6 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/settings/nm-settings-connection.h @@ -48,6 +48,7 @@ G_BEGIN_DECLS /* Properties */ #define NM_SETTINGS_CONNECTION_VISIBLE "visible" #define NM_SETTINGS_CONNECTION_UNSAVED "unsaved" +#define NM_SETTINGS_CONNECTION_READY "ready" #define NM_SETTINGS_CONNECTION_FLAGS "flags" @@ -196,6 +197,10 @@ gboolean nm_settings_connection_can_autoconnect (NMSettingsConnection *connectio gboolean nm_settings_connection_get_nm_generated (NMSettingsConnection *connection); gboolean nm_settings_connection_get_nm_generated_assumed (NMSettingsConnection *connection); +gboolean nm_settings_connection_get_ready (NMSettingsConnection *connection); +void nm_settings_connection_set_ready (NMSettingsConnection *connection, + gboolean ready); + G_END_DECLS #endif /* __NETWORKMANAGER_SETTINGS_CONNECTION_H__ */ diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 8ed24e27c1..b28c05f86f 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -151,6 +151,8 @@ typedef struct { GSList *unmanaged_specs; GSList *unrecognized_specs; GSList *get_connections_cache; + + gboolean startup_complete; } NMSettingsPrivate; #define NM_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTINGS, NMSettingsPrivate)) @@ -175,11 +177,43 @@ enum { PROP_HOSTNAME, PROP_CAN_MODIFY, PROP_CONNECTIONS, + PROP_STARTUP_COMPLETE, LAST_PROP }; static void +check_startup_complete (NMSettings *self) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + GHashTableIter iter; + NMSettingsConnection *conn; + + if (priv->startup_complete) + return; + + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn)) { + if (!nm_settings_connection_get_ready (conn)) + return; + } + + priv->startup_complete = TRUE; + g_object_notify (G_OBJECT (self), NM_SETTINGS_STARTUP_COMPLETE); +} + +static void +connection_ready_changed (NMSettingsConnection *conn, + GParamSpec *pspec, + gpointer user_data) +{ + NMSettings *self = NM_SETTINGS (user_data); + + if (nm_settings_connection_get_ready (conn)) + check_startup_complete (self); +} + +static void plugin_connection_added (NMSystemConfigInterface *config, NMSettingsConnection *connection, gpointer user_data) @@ -771,6 +805,7 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated_by_user), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_visibility_changed), self); + g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self); /* Forget about the connection internally */ g_hash_table_remove (NM_SETTINGS_GET_PRIVATE (user_data)->connections, @@ -783,6 +818,8 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_REMOVED, connection); g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTIONS); + check_startup_complete (self); + g_object_unref (connection); } @@ -888,6 +925,11 @@ claim_connection (NMSettings *self, g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_VISIBLE, G_CALLBACK (connection_visibility_changed), self); + if (!priv->startup_complete) { + g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_READY, + G_CALLBACK (connection_ready_changed), + self); + } /* Export the connection over D-Bus */ g_warn_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL); @@ -1778,6 +1820,16 @@ cp_get_connection_by_uuid (NMConnectionProvider *provider, const char *uuid) /***************************************************************/ +gboolean +nm_settings_get_startup_complete (NMSettings *self) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + + return priv->startup_complete; +} + +/***************************************************************/ + NMSettings * nm_settings_new (GError **error) { @@ -1798,6 +1850,7 @@ nm_settings_new (GError **error) } load_connections (self); + check_startup_complete (self); nm_dbus_manager_register_object (priv->dbus_mgr, NM_DBUS_PATH_SETTINGS, self); return self; @@ -1898,6 +1951,9 @@ get_property (GObject *object, guint prop_id, g_ptr_array_add (array, g_strdup (path)); g_value_take_boxed (value, array); break; + case PROP_STARTUP_COMPLETE: + g_value_set_boolean (value, nm_settings_get_startup_complete (self)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 520c4ec34c..9c0a4c835e 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -37,10 +37,11 @@ #define NM_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTINGS)) #define NM_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS, NMSettingsClass)) -#define NM_SETTINGS_UNMANAGED_SPECS "unmanaged-specs" -#define NM_SETTINGS_HOSTNAME "hostname" -#define NM_SETTINGS_CAN_MODIFY "can-modify" -#define NM_SETTINGS_CONNECTIONS "connections" +#define NM_SETTINGS_UNMANAGED_SPECS "unmanaged-specs" +#define NM_SETTINGS_HOSTNAME "hostname" +#define NM_SETTINGS_CAN_MODIFY "can-modify" +#define NM_SETTINGS_CONNECTIONS "connections" +#define NM_SETTINGS_STARTUP_COMPLETE "connections" #define NM_SETTINGS_SIGNAL_CONNECTION_ADDED "connection-added" #define NM_SETTINGS_SIGNAL_CONNECTION_UPDATED "connection-updated" @@ -120,4 +121,6 @@ void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean qu gint nm_settings_sort_connections (gconstpointer a, gconstpointer b); +gboolean nm_settings_get_startup_complete (NMSettings *self); + #endif /* __NM_SETTINGS_H__ */ diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index ec143edd03..b044fe01c4 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -33,6 +33,8 @@ #include <nm-setting-pppoe.h> #include <nm-setting-wireless-security.h> #include <nm-setting-8021x.h> +#include <nm-platform.h> +#include <nm-logging.h> #include "common.h" #include "nm-config.h" @@ -63,6 +65,9 @@ typedef struct { char *unmanaged_spec; char *unrecognized_spec; + + gulong devtimeout_link_changed_handler; + guint devtimeout_timeout_id; } NMIfcfgConnectionPrivate; enum { @@ -80,6 +85,97 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +static gboolean +devtimeout_ready (gpointer user_data) +{ + NMIfcfgConnection *self = user_data; + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + + priv->devtimeout_timeout_id = 0; + nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), TRUE); + return FALSE; +} + +static void +link_changed (NMPlatform *platform, int ifindex, NMPlatformLink *link, + NMPlatformSignalChangeType change_type, NMPlatformReason reason, + NMConnection *self) +{ + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + const char *ifname; + + ifname = nm_connection_get_interface_name (self); + if (g_strcmp0 (link->name, ifname) != 0) + return; + + /* Shouldn't happen, but... */ + if (change_type == NM_PLATFORM_SIGNAL_REMOVED) + return; + + nm_log_info (LOGD_SETTINGS, "Device %s appeared; connection '%s' now ready", + ifname, nm_connection_get_id (self)); + + g_signal_handler_disconnect (platform, priv->devtimeout_link_changed_handler); + priv->devtimeout_link_changed_handler = 0; + g_source_remove (priv->devtimeout_timeout_id); + + /* Don't declare the connection ready right away, since NMManager may not have + * started processing the device yet. + */ + priv->devtimeout_timeout_id = g_idle_add (devtimeout_ready, self); +} + +static gboolean +devtimeout_expired (gpointer user_data) +{ + NMIfcfgConnection *self = user_data; + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + + nm_log_info (LOGD_SETTINGS, "Device for connection '%s' did not appear before timeout", + nm_connection_get_id (NM_CONNECTION (self))); + + g_signal_handler_disconnect (nm_platform_get (), priv->devtimeout_link_changed_handler); + priv->devtimeout_link_changed_handler = 0; + priv->devtimeout_timeout_id = 0; + + nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), TRUE); + return FALSE; +} + +static void +nm_ifcfg_connection_check_devtimeout (NMIfcfgConnection *self) +{ + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); + NMSettingConnection *s_con; + const char *ifname; + guint devtimeout; + + s_con = nm_connection_get_setting_connection (NM_CONNECTION (self)); + + if (!nm_setting_connection_get_autoconnect (s_con)) + return; + ifname = nm_setting_connection_get_interface_name (s_con); + if (!ifname) + return; + devtimeout = devtimeout_from_file (nm_ifcfg_connection_get_path (self)); + if (!devtimeout) + return; + + if (nm_platform_link_get_ifindex (ifname) != 0) + return; + + /* ONBOOT=yes, DEVICE and DEVTIMEOUT are set, but device is not present */ + nm_settings_connection_set_ready (NM_SETTINGS_CONNECTION (self), FALSE); + + nm_log_info (LOGD_SETTINGS, "Waiting %u seconds for %s to appear for connection '%s'", + devtimeout, ifname, nm_connection_get_id (NM_CONNECTION (self))); + + priv->devtimeout_link_changed_handler = + g_signal_connect (nm_platform_get (), NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK (link_changed), self); + priv->devtimeout_timeout_id = g_timeout_add_seconds (devtimeout, devtimeout_expired, self); +} + static void files_changed_cb (NMInotifyHelper *ih, struct inotify_event *evt, @@ -141,8 +237,10 @@ nm_ifcfg_connection_new (NMConnection *source, update_unsaved, error)) { /* Set the path and start monitoring */ - if (full_path) + if (full_path) { nm_ifcfg_connection_set_path (NM_IFCFG_CONNECTION (object), full_path); + nm_ifcfg_connection_check_devtimeout (NM_IFCFG_CONNECTION (object)); + } } else g_clear_object (&object); @@ -368,8 +466,20 @@ get_property (GObject *object, guint prop_id, static void dispose (GObject *object) { + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); + path_watch_stop (NM_IFCFG_CONNECTION (object)); + if (priv->devtimeout_link_changed_handler) { + g_signal_handler_disconnect (nm_platform_get (), + priv->devtimeout_link_changed_handler); + priv->devtimeout_link_changed_handler = 0; + } + if (priv->devtimeout_timeout_id) { + g_source_remove (priv->devtimeout_timeout_id); + priv->devtimeout_timeout_id = 0; + } + G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->dispose (object); } diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 4ecdf1ae54..97ac58aab1 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -4852,3 +4852,25 @@ connection_from_file_test (const char *filename, NULL); } +guint +devtimeout_from_file (const char *filename) +{ + shvarFile *ifcfg; + char *devtimeout_str; + guint devtimeout; + + g_return_val_if_fail (filename != NULL, NULL); + + ifcfg = svOpenFile (filename, NULL); + if (!ifcfg) + return 0; + + devtimeout_str = svGetValue (ifcfg, "DEVTIMEOUT", FALSE); + if (devtimeout_str) { + devtimeout = nm_utils_ascii_str_to_int64 (devtimeout_str, 10, 0, G_MAXUINT, 0); + g_free (devtimeout_str); + } else + devtimeout = 0; + + return devtimeout; +} diff --git a/src/settings/plugins/ifcfg-rh/reader.h b/src/settings/plugins/ifcfg-rh/reader.h index 6a6af167ff..70e9ce4e24 100644 --- a/src/settings/plugins/ifcfg-rh/reader.h +++ b/src/settings/plugins/ifcfg-rh/reader.h @@ -32,6 +32,8 @@ NMConnection *connection_from_file (const char *filename, char *uuid_from_file (const char *filename); +guint devtimeout_from_file (const char *filename); + /* for test-ifcfg-rh */ NMConnection *connection_from_file_test (const char *filename, const char *network_file, |