mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-14 20:18:39 +00:00
core: add monitor-connection-files=false and ReloadConnections
Add a "monitor-connection-files" config option, which can be set to "false" to disable automatic reloading of connections on file change. To go with this, add a new ReloadConnections method on o.fd.NM.Settings that can be used to manually reload connections, and add an nm-cli command to call it.
This commit is contained in:
parent
4b74009b23
commit
1f81851017
|
@ -205,7 +205,8 @@ usage (void)
|
|||
#endif
|
||||
" down [ id | uuid | path | apath ] <ID>\n\n"
|
||||
" add COMMON_OPTIONS TYPE_SPECIFIC_OPTIONS IP_OPTIONS\n\n"
|
||||
" delete [ id | uuid | path ] <ID>\n\n\n"
|
||||
" delete [ id | uuid | path ] <ID>\n\n"
|
||||
" reload\n\n\n"
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -284,6 +285,7 @@ static const char *real_con_commands[] = {
|
|||
"down",
|
||||
"add",
|
||||
"delete",
|
||||
"reload",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -3221,6 +3223,32 @@ finish:
|
|||
return nmc->return_value;
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
do_connection_reload (NmCli *nmc, int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
nmc->return_value = NMC_RESULT_SUCCESS;
|
||||
nmc->should_wait = FALSE;
|
||||
|
||||
if (!nm_client_get_manager_running (nmc->client)) {
|
||||
g_string_printf (nmc->return_text, _("Error: NetworkManager is not running."));
|
||||
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
if (!nm_remote_settings_reload_connections (nmc->system_settings, &error)) {
|
||||
g_string_printf (nmc->return_text, _("Error: %s."), error->message);
|
||||
if (error->code == NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE)
|
||||
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
|
||||
else
|
||||
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
return nmc->return_value;
|
||||
}
|
||||
|
||||
static NMCResultCode
|
||||
parse_cmd (NmCli *nmc, int argc, char **argv)
|
||||
{
|
||||
|
@ -3263,6 +3291,9 @@ parse_cmd (NmCli *nmc, int argc, char **argv)
|
|||
else if (matches(*argv, "delete") == 0) {
|
||||
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
|
||||
}
|
||||
else if (matches(*argv, "reload") == 0) {
|
||||
nmc->return_value = do_connection_reload (nmc, argc-1, argv+1);
|
||||
}
|
||||
else if (nmc_arg_is_help (*argv)) {
|
||||
usage ();
|
||||
nmc->should_wait = FALSE;
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
|
||||
[main]
|
||||
|
||||
# Normally, NetworkManager reloads connection files on disk any time
|
||||
# they are changed. Setting "monitor-connection-files=false" will
|
||||
# disable this behavior, and NetworkManager will then only read
|
||||
# connection files at startup, and when explicitly requested via
|
||||
# D-Bus.
|
||||
|
||||
#monitor-connection-files=false
|
||||
|
||||
|
||||
# Normally, if there is an ethernet device that is not matched by any
|
||||
# existing configured connection, NetworkManager will create a
|
||||
# "default" connection for that device, using automatic (DHCP/SLAAC)
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
the connection to disk. Secrets may be part of the update request
|
||||
and may sent to a Secret Agent for storage, depending on the the
|
||||
flags associated with each secret.
|
||||
|
||||
Use the 'Save' method to save these changes to disk. Note
|
||||
that unsaved changes will be lost if the connection is
|
||||
reloaded from disk (either automatically on file change or
|
||||
due to an explicit ReloadConnections call).
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_connection_update_unsaved"/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
|
|
|
@ -62,6 +62,11 @@
|
|||
operation does not start the network connection unless (1) device is
|
||||
idle and able to connect to the network described by the new connection,
|
||||
and (2) the connection is allowed to be started automatically.
|
||||
|
||||
Use the 'Save' method on the connection to save these changes
|
||||
to disk. Note that unsaved changes will be lost if the
|
||||
connection is reloaded from disk (either automatically on file
|
||||
change or due to an explicit ReloadConnections call).
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection_unsaved"/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
|
@ -77,6 +82,23 @@
|
|||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="ReloadConnections">
|
||||
<tp:docstring>
|
||||
Tells NetworkManager to reload all connection files from disk,
|
||||
including noticing any added or deleted connection files. By
|
||||
default, connections are re-read automatically any time they
|
||||
change, so you only need to use this command if you have set
|
||||
"monitor-connection-files=false" in NetworkManager.conf.
|
||||
</tp:docstring>
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_reload_connections"/>
|
||||
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||
<arg name="status" type="b" direction="out">
|
||||
<tp:docstring>
|
||||
Success or failure.
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="SaveHostname">
|
||||
<tp:docstring>
|
||||
Save the hostname to persistent configuration.
|
||||
|
|
|
@ -231,6 +231,7 @@ global:
|
|||
nm_remote_settings_new;
|
||||
nm_remote_settings_new_async;
|
||||
nm_remote_settings_new_finish;
|
||||
nm_remote_settings_reload_connections;
|
||||
nm_remote_settings_save_hostname;
|
||||
nm_secret_agent_delete_secrets;
|
||||
nm_secret_agent_error_get_type;
|
||||
|
|
|
@ -629,6 +629,47 @@ nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_remote_settings_reload_connections:
|
||||
* @settings: the #NMRemoteSettings
|
||||
* @error: return location for #GError
|
||||
*
|
||||
* Requests that the remote settings service reload all connection
|
||||
* files from disk, adding, updating, and removing connections until
|
||||
* the in-memory state matches the on-disk state.
|
||||
*
|
||||
* Return value: %TRUE on success, %FALSE on failure
|
||||
*
|
||||
* Since: 0.9.10
|
||||
**/
|
||||
gboolean
|
||||
nm_remote_settings_reload_connections (NMRemoteSettings *settings,
|
||||
GError **error)
|
||||
{
|
||||
NMRemoteSettingsPrivate *priv;
|
||||
gboolean success;
|
||||
|
||||
g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE);
|
||||
|
||||
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
|
||||
|
||||
_nm_remote_settings_ensure_inited (settings);
|
||||
|
||||
if (!priv->service_running) {
|
||||
g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR,
|
||||
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE,
|
||||
"NetworkManager is not running.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dbus_g_proxy_call (priv->proxy, "ReloadConnections", error,
|
||||
G_TYPE_INVALID,
|
||||
G_TYPE_BOOLEAN, &success,
|
||||
G_TYPE_INVALID))
|
||||
return FALSE;
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_one_hash (GHashTable *table)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,8 @@ G_BEGIN_DECLS
|
|||
* was removed before it was completely initialized
|
||||
* @NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE: the #NMRemoteConnection object
|
||||
* is not visible or otherwise unreadable
|
||||
* @NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE: NetworkManager is not running.
|
||||
* (Since 0.9.10)
|
||||
*
|
||||
* Describes errors that may result from operations involving a #NMRemoteSettings.
|
||||
*
|
||||
|
@ -53,6 +55,7 @@ typedef enum {
|
|||
NM_REMOTE_SETTINGS_ERROR_UNKNOWN = 0, /*< nick=UnknownError >*/
|
||||
NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, /*< nick=ConnectionRemoved >*/
|
||||
NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, /*< nick=ConnectionUnavailable >*/
|
||||
NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE, /*< nick=ServiceUnavailable >*/
|
||||
} NMRemoteSettingsError;
|
||||
|
||||
#define NM_REMOTE_SETTINGS_ERROR nm_remote_settings_error_quark ()
|
||||
|
@ -132,6 +135,9 @@ gboolean nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings,
|
|||
NMRemoteSettingsAddConnectionFunc callback,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean nm_remote_settings_reload_connections (NMRemoteSettings *settings,
|
||||
GError **error);
|
||||
|
||||
gboolean nm_remote_settings_save_hostname (NMRemoteSettings *settings,
|
||||
const char *hostname,
|
||||
NMRemoteSettingsSaveHostnameFunc callback,
|
||||
|
|
|
@ -96,6 +96,16 @@ Copyright (C) 2010 - 2013 Red Hat, Inc.
|
|||
connection, the error is returned to the user. See below
|
||||
for available plugins.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>monitor-connection-files</varname></term>
|
||||
<listitem><para>Whether the configured settings plugin(s)
|
||||
should set up file monitors and immediately pick up changes
|
||||
made to connection files while NetworkManager is running. This
|
||||
is enabled by default; if this key is set to
|
||||
'<literal>false</literal>', then NetworkManager will only read
|
||||
the connection files at startup, and when explicitly requested
|
||||
via the ReloadConnections D-Bus call.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>dhcp</varname></term>
|
||||
<listitem><para>This key sets up what DHCP client
|
||||
|
|
|
@ -238,7 +238,7 @@ NetworkManager connections
|
|||
.br
|
||||
Get information about \fINetworkManager\fP connections and manage them.
|
||||
.TP
|
||||
.SS \fICOMMAND\fP := { show | up | down | add | delete }
|
||||
.SS \fICOMMAND\fP := { show | up | down | add | delete | reload }
|
||||
.sp
|
||||
.RS
|
||||
.TP
|
||||
|
@ -501,6 +501,13 @@ its name, UUID or D-Bus path. If <ID> is ambiguous, a keyword \fIid\fP,
|
|||
\fIuuid\fP or \fIpath\fP can be used.
|
||||
.br
|
||||
See \fBshow active\fP above for the description of the <ID>-specifying keywords.
|
||||
.TP
|
||||
.B reload
|
||||
.br
|
||||
Reload all connection files from disk. By default, connections are re-read
|
||||
automatically any time they change, so you only need to use this command when
|
||||
the auto-loading feature is disabled ("monitor-connection-files=false"
|
||||
in NetworkManager.conf).
|
||||
.RE
|
||||
|
||||
.TP
|
||||
|
|
|
@ -43,6 +43,7 @@ typedef struct {
|
|||
GKeyFile *keyfile;
|
||||
|
||||
char **plugins;
|
||||
gboolean monitor_connection_files;
|
||||
char *dhcp_client;
|
||||
char *dns_mode;
|
||||
|
||||
|
@ -81,6 +82,14 @@ nm_config_get_plugins (NMConfig *config)
|
|||
return (const char **) NM_CONFIG_GET_PRIVATE (config)->plugins;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_config_get_monitor_connection_files (NMConfig *config)
|
||||
{
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
|
||||
return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_config_get_dhcp_client (NMConfig *config)
|
||||
{
|
||||
|
@ -434,6 +443,7 @@ nm_config_new (GError **error)
|
|||
GFileInfo *info;
|
||||
GPtrArray *confs;
|
||||
const char *name;
|
||||
char *value;
|
||||
int i;
|
||||
|
||||
g_assert (!singleton);
|
||||
|
@ -492,6 +502,20 @@ nm_config_new (GError **error)
|
|||
g_key_file_set_value (priv->keyfile, "main", "plugins", cli_plugins);
|
||||
priv->plugins = g_key_file_get_string_list (priv->keyfile, "main", "plugins", NULL, NULL);
|
||||
|
||||
value = g_key_file_get_value (priv->keyfile, "main", "monitor-connection-files", NULL);
|
||||
if (value) {
|
||||
if (!strcmp (value, "true") || !strcmp (value, "yes") || !strcmp (value, "on"))
|
||||
priv->monitor_connection_files = TRUE;
|
||||
else if (!strcmp (value, "false") || !strcmp (value, "no") || !strcmp (value, "off"))
|
||||
priv->monitor_connection_files = FALSE;
|
||||
else {
|
||||
g_warning ("Unrecognized value for main.monitor-connection-files: %s. Assuming 'false'", value);
|
||||
priv->monitor_connection_files = FALSE;
|
||||
}
|
||||
g_free (value);
|
||||
} else
|
||||
priv->monitor_connection_files = TRUE;
|
||||
|
||||
priv->dhcp_client = g_key_file_get_value (priv->keyfile, "main", "dhcp", NULL);
|
||||
priv->dns_mode = g_key_file_get_value (priv->keyfile, "main", "dns", NULL);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ NMConfig *nm_config_get (void);
|
|||
|
||||
const char *nm_config_get_path (NMConfig *config);
|
||||
const char **nm_config_get_plugins (NMConfig *config);
|
||||
gboolean nm_config_get_monitor_connection_files (NMConfig *config);
|
||||
const char *nm_config_get_dhcp_client (NMConfig *config);
|
||||
const char *nm_config_get_dns_mode (NMConfig *config);
|
||||
const char *nm_config_get_log_level (NMConfig *config);
|
||||
|
|
|
@ -104,6 +104,9 @@ static void impl_settings_add_connection_unsaved (NMSettings *self,
|
|||
GHashTable *settings,
|
||||
DBusGMethodInvocation *context);
|
||||
|
||||
static void impl_settings_reload_connections (NMSettings *self,
|
||||
DBusGMethodInvocation *context);
|
||||
|
||||
static void impl_settings_save_hostname (NMSettings *self,
|
||||
const char *hostname,
|
||||
DBusGMethodInvocation *context);
|
||||
|
@ -1213,6 +1216,46 @@ impl_settings_add_connection_unsaved (NMSettings *self,
|
|||
impl_settings_add_connection_helper (self, settings, FALSE, context);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_settings_reload_connections (NMSettings *self,
|
||||
DBusGMethodInvocation *context)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
gulong caller_uid;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid)) {
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Unable to determine request UID.");
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
if (caller_uid != 0) {
|
||||
nm_log_warn (LOGD_SETTINGS, "ReloadConnections: permission denied to %lu", caller_uid);
|
||||
error = g_error_new_literal (NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_PERMISSION_DENIED,
|
||||
"Permission denied");
|
||||
dbus_g_method_return_error (context, error);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->connections_loaded) {
|
||||
load_connections (self);
|
||||
} else {
|
||||
for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
|
||||
NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
|
||||
|
||||
nm_system_config_interface_reload_connections (plugin);
|
||||
}
|
||||
}
|
||||
|
||||
dbus_g_method_return (context, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
pk_hostname_cb (NMAuthChain *chain,
|
||||
GError *chain_error,
|
||||
|
|
|
@ -137,6 +137,15 @@ nm_system_config_interface_get_connections (NMSystemConfigInterface *config)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nm_system_config_interface_reload_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
g_return_if_fail (config != NULL);
|
||||
|
||||
if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->reload_connections)
|
||||
NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->reload_connections (config);
|
||||
}
|
||||
|
||||
GSList *
|
||||
nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||
{
|
||||
|
|
|
@ -89,6 +89,11 @@ struct _NMSystemConfigInterface {
|
|||
*/
|
||||
GSList * (*get_connections) (NMSystemConfigInterface *config);
|
||||
|
||||
/* Requests that the plugin reload all connection files from disk,
|
||||
* and emit signals reflecting new, changed, and removed connections.
|
||||
*/
|
||||
void (*reload_connections) (NMSystemConfigInterface *config);
|
||||
|
||||
/*
|
||||
* Return a string list of specifications of devices which NetworkManager
|
||||
* should not manage. Returned list will be freed by the system settings
|
||||
|
@ -137,6 +142,8 @@ void nm_system_config_interface_init (NMSystemConfigInterface *config,
|
|||
|
||||
GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
|
||||
|
||||
void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config);
|
||||
|
||||
GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config);
|
||||
|
||||
NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
|
||||
|
|
|
@ -421,10 +421,9 @@ conf_file_changed (GFileMonitor *monitor,
|
|||
}
|
||||
|
||||
/* This function starts the inotify monitors that watch the plugin's config
|
||||
* file directory for new connections and changes to existing connections.
|
||||
* At this time all plugins are expected to make NM aware of changes on-the-fly
|
||||
* instead of requiring a SIGHUP or SIGUSR1 or some D-Bus method to say
|
||||
* "reload".
|
||||
* file directory for new connections and changes to existing connections
|
||||
* (if not disabled by NetworkManager.conf), and for changes to the plugin's
|
||||
* non-connection config files.
|
||||
*/
|
||||
static void
|
||||
setup_monitoring (NMSystemConfigInterface *config)
|
||||
|
@ -438,6 +437,7 @@ setup_monitoring (NMSystemConfigInterface *config)
|
|||
*/
|
||||
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
||||
|
||||
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||
/* Set up the watch for our config directory */
|
||||
file = g_file_new_for_path (EXAMPLE_DIR);
|
||||
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
|
@ -449,6 +449,7 @@ setup_monitoring (NMSystemConfigInterface *config)
|
|||
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
||||
priv->monitor = monitor;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a watch on our configuration file, basically just for watching
|
||||
* whether the user has changed the unmanaged devices option or the
|
||||
|
|
|
@ -28,6 +28,7 @@ INCLUDES = \
|
|||
-I$(top_srcdir)/src/wifi \
|
||||
-I$(top_srcdir)/src/settings \
|
||||
-I$(top_srcdir)/src/posix-signals \
|
||||
-I$(top_srcdir)/src/config \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/libnm-glib \
|
||||
|
|
|
@ -44,10 +44,12 @@
|
|||
#include "plugin.h"
|
||||
#include "nm-system-config-interface.h"
|
||||
#include "nm-settings-error.h"
|
||||
#include "nm-config.h"
|
||||
|
||||
#include "nm-ifcfg-connection.h"
|
||||
#include "nm-inotify-helper.h"
|
||||
#include "shvar.h"
|
||||
#include "reader.h"
|
||||
#include "writer.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -64,7 +66,8 @@ static gboolean impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
|
|||
|
||||
static void connection_new_or_changed (SCPluginIfcfg *plugin,
|
||||
const char *path,
|
||||
NMIfcfgConnection *existing);
|
||||
NMIfcfgConnection *existing,
|
||||
char **out_old_path);
|
||||
|
||||
static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
|
||||
|
||||
|
@ -109,7 +112,7 @@ connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
|
|||
path = nm_ifcfg_connection_get_path (connection);
|
||||
g_return_if_fail (path != NULL);
|
||||
|
||||
connection_new_or_changed (plugin, path, connection);
|
||||
connection_new_or_changed (plugin, path, connection, NULL);
|
||||
}
|
||||
|
||||
static NMIfcfgConnection *
|
||||
|
@ -173,35 +176,6 @@ _internal_new_connection (SCPluginIfcfg *self,
|
|||
return connection;
|
||||
}
|
||||
|
||||
static void
|
||||
read_connections (SCPluginIfcfg *plugin)
|
||||
{
|
||||
GDir *dir;
|
||||
GError *err = NULL;
|
||||
|
||||
dir = g_dir_open (IFCFG_DIR, 0, &err);
|
||||
if (dir) {
|
||||
const char *item;
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
char *full_path;
|
||||
|
||||
if (utils_should_ignore_file (item, TRUE))
|
||||
continue;
|
||||
|
||||
full_path = g_build_filename (IFCFG_DIR, item, NULL);
|
||||
if (utils_get_ifcfg_name (full_path, TRUE))
|
||||
_internal_new_connection (plugin, full_path, NULL, NULL);
|
||||
g_free (full_path);
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
} else {
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Monitoring */
|
||||
|
||||
static void
|
||||
|
@ -242,10 +216,26 @@ find_by_path (SCPluginIfcfg *self, const char *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static NMIfcfgConnection *
|
||||
find_by_uuid_from_path (SCPluginIfcfg *self, const char *path)
|
||||
{
|
||||
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
|
||||
char *uuid;
|
||||
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
uuid = uuid_from_file (path);
|
||||
if (uuid)
|
||||
return g_hash_table_lookup (priv->connections, uuid);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
connection_new_or_changed (SCPluginIfcfg *self,
|
||||
const char *path,
|
||||
NMIfcfgConnection *existing)
|
||||
NMIfcfgConnection *existing,
|
||||
char **out_old_path)
|
||||
{
|
||||
NMIfcfgConnection *new;
|
||||
GError *error = NULL;
|
||||
|
@ -255,6 +245,21 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (path != NULL);
|
||||
|
||||
if (out_old_path)
|
||||
*out_old_path = NULL;
|
||||
|
||||
if (!existing) {
|
||||
/* See if it's a rename */
|
||||
existing = find_by_uuid_from_path (self, path);
|
||||
if (existing) {
|
||||
const char *old_path = nm_ifcfg_connection_get_path (existing);
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "renaming %s -> %s", old_path, path);
|
||||
if (out_old_path)
|
||||
*out_old_path = g_strdup (old_path);
|
||||
nm_ifcfg_connection_set_path (existing, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!existing) {
|
||||
/* New connection */
|
||||
new = _internal_new_connection (self, path, NULL, NULL);
|
||||
|
@ -371,7 +376,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
|
|||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
/* Update or new */
|
||||
connection_new_or_changed (plugin, ifcfg_path, connection);
|
||||
connection_new_or_changed (plugin, ifcfg_path, connection, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -399,6 +404,65 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_connections (SCPluginIfcfg *plugin)
|
||||
{
|
||||
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
|
||||
GDir *dir;
|
||||
GError *err = NULL;
|
||||
const char *item;
|
||||
GHashTable *oldconns;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
NMIfcfgConnection *connection;
|
||||
|
||||
dir = g_dir_open (IFCFG_DIR, 0, &err);
|
||||
if (!dir) {
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, "Can not read directory '%s': %s", IFCFG_DIR, err->message);
|
||||
g_error_free (err);
|
||||
return;
|
||||
}
|
||||
|
||||
oldconns = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
g_hash_table_insert (oldconns, g_strdup (nm_ifcfg_connection_get_path (value)), value);
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
char *full_path, *old_path;
|
||||
|
||||
if (utils_should_ignore_file (item, TRUE))
|
||||
continue;
|
||||
|
||||
full_path = g_build_filename (IFCFG_DIR, item, NULL);
|
||||
if (!utils_get_ifcfg_name (full_path, TRUE))
|
||||
goto next;
|
||||
|
||||
connection = g_hash_table_lookup (oldconns, full_path);
|
||||
g_hash_table_remove (oldconns, full_path);
|
||||
connection_new_or_changed (plugin, full_path, connection, &old_path);
|
||||
|
||||
if (old_path) {
|
||||
g_hash_table_remove (oldconns, old_path);
|
||||
g_free (old_path);
|
||||
}
|
||||
|
||||
next:
|
||||
g_free (full_path);
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
|
||||
g_hash_table_iter_init (&iter, oldconns);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", (char *)key);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
remove_connection (plugin, value);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (oldconns);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
|
@ -409,6 +473,7 @@ get_connections (NMSystemConfigInterface *config)
|
|||
NMIfcfgConnection *connection;
|
||||
|
||||
if (!priv->initialized) {
|
||||
if (nm_config_get_monitor_connection_files (nm_config_get ()))
|
||||
setup_ifcfg_monitoring (plugin);
|
||||
read_connections (plugin);
|
||||
priv->initialized = TRUE;
|
||||
|
@ -423,6 +488,14 @@ get_connections (NMSystemConfigInterface *config)
|
|||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
|
||||
|
||||
read_connections (plugin);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||
{
|
||||
|
@ -854,6 +927,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
|
|||
/* interface implementation */
|
||||
system_config_interface_class->get_connections = get_connections;
|
||||
system_config_interface_class->add_connection = add_connection;
|
||||
system_config_interface_class->reload_connections = reload_connections;
|
||||
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
||||
system_config_interface_class->init = init;
|
||||
}
|
||||
|
|
|
@ -4251,6 +4251,34 @@ ensure_unmanaged (shvarFile *ifcfg,
|
|||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed");
|
||||
}
|
||||
|
||||
char *
|
||||
uuid_from_file (const char *filename)
|
||||
{
|
||||
const char *ifcfg_name = NULL;
|
||||
shvarFile *ifcfg;
|
||||
char *uuid;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
ifcfg_name = utils_get_ifcfg_name (filename, TRUE);
|
||||
if (!ifcfg_name)
|
||||
return NULL;
|
||||
|
||||
ifcfg = svNewFile (filename);
|
||||
if (!ifcfg)
|
||||
return NULL;
|
||||
|
||||
/* Try for a UUID key before falling back to hashing the file name */
|
||||
uuid = svGetValue (ifcfg, "UUID", FALSE);
|
||||
if (!uuid || !strlen (uuid)) {
|
||||
g_free (uuid);
|
||||
uuid = nm_utils_uuid_generate_from_string (ifcfg->fileName);
|
||||
}
|
||||
|
||||
svCloseFile (ifcfg);
|
||||
return uuid;
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
connection_from_file (const char *filename,
|
||||
const char *network_file, /* for unit tests only */
|
||||
|
|
|
@ -37,4 +37,6 @@ NMConnection *connection_from_file (const char *filename,
|
|||
GError **error,
|
||||
gboolean *ignore_error);
|
||||
|
||||
char *uuid_from_file (const char *filename);
|
||||
|
||||
#endif /* __READER_H__ */
|
||||
|
|
|
@ -66,7 +66,7 @@ typedef struct {
|
|||
|
||||
static void system_config_interface_init (NMSystemConfigInterface *class);
|
||||
|
||||
static void reload_connections (gpointer config);
|
||||
static void reload_connections (NMSystemConfigInterface *config);
|
||||
|
||||
G_DEFINE_TYPE_EXTENDED (SCPluginIfnet, sc_plugin_ifnet, G_TYPE_OBJECT, 0,
|
||||
G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init))
|
||||
|
@ -192,11 +192,14 @@ setup_monitors (NMIfnetConnection * connection, gpointer user_data)
|
|||
priv->hostname_monitor =
|
||||
monitor_file_changes (IFNET_SYSTEM_HOSTNAME_FILE,
|
||||
update_system_hostname, user_data);
|
||||
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||
priv->net_monitor =
|
||||
monitor_file_changes (CONF_NET_FILE, reload_connections, user_data);
|
||||
priv->wpa_monitor =
|
||||
monitor_file_changes (WPA_SUPPLICANT_CONF, reload_connections,
|
||||
monitor_file_changes (CONF_NET_FILE, (FileChangedFn) reload_connections,
|
||||
user_data);
|
||||
priv->wpa_monitor =
|
||||
monitor_file_changes (WPA_SUPPLICANT_CONF, (FileChangedFn) reload_connections,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -220,7 +223,7 @@ cancel_monitors (NMIfnetConnection * connection, gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
reload_connections (gpointer config)
|
||||
reload_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
|
||||
SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
|
||||
|
@ -460,6 +463,7 @@ system_config_interface_init (NMSystemConfigInterface *class)
|
|||
class->get_connections = get_connections;
|
||||
class->get_unmanaged_specs = get_unmanaged_specs;
|
||||
class->add_connection = add_connection;
|
||||
class->reload_connections = reload_connections;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -88,48 +88,6 @@ _internal_new_connection (SCPluginKeyfile *self,
|
|||
return (NMSettingsConnection *) connection;
|
||||
}
|
||||
|
||||
static void
|
||||
read_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
||||
GDir *dir;
|
||||
GError *error = NULL;
|
||||
const char *item;
|
||||
|
||||
dir = g_dir_open (KEYFILE_DIR, 0, &error);
|
||||
if (!dir) {
|
||||
PLUGIN_WARN (KEYFILE_PLUGIN_NAME, "Cannot read directory '%s': (%d) %s",
|
||||
KEYFILE_DIR,
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
NMSettingsConnection *connection;
|
||||
char *full_path;
|
||||
|
||||
if (nm_keyfile_plugin_utils_should_ignore_file (item))
|
||||
continue;
|
||||
|
||||
full_path = g_build_filename (KEYFILE_DIR, item, NULL);
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "parsing %s ... ", item);
|
||||
|
||||
connection = _internal_new_connection (self, full_path, NULL, &error);
|
||||
if (connection) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " read connection '%s'",
|
||||
nm_connection_get_id (NM_CONNECTION (connection)));
|
||||
} else {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
}
|
||||
g_clear_error (&error);
|
||||
g_free (full_path);
|
||||
}
|
||||
g_dir_close (dir);
|
||||
}
|
||||
|
||||
/* Monitoring */
|
||||
|
||||
static void
|
||||
|
@ -137,6 +95,8 @@ remove_connection (SCPluginKeyfile *self, NMKeyfileConnection *connection)
|
|||
{
|
||||
g_return_if_fail (connection != NULL);
|
||||
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "removed %s.", nm_keyfile_connection_get_path (connection));
|
||||
|
||||
/* Removing from the hash table should drop the last reference */
|
||||
g_object_ref (connection);
|
||||
g_hash_table_remove (SC_PLUGIN_KEYFILE_GET_PRIVATE (self)->connections,
|
||||
|
@ -145,6 +105,40 @@ remove_connection (SCPluginKeyfile *self, NMKeyfileConnection *connection)
|
|||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
update_connection (SCPluginKeyfile *self,
|
||||
NMKeyfileConnection *connection,
|
||||
const char *name)
|
||||
{
|
||||
NMKeyfileConnection *tmp;
|
||||
GError *error = NULL;
|
||||
|
||||
tmp = nm_keyfile_connection_new (NULL, name, &error);
|
||||
if (!tmp) {
|
||||
/* Error; remove the connection */
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
remove_connection (self, connection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_connection_compare (NM_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", name);
|
||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
FALSE, /* don't set Unsaved */
|
||||
&error)) {
|
||||
/* Shouldn't ever get here as 'new' was verified by the reader already */
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
}
|
||||
g_object_unref (tmp);
|
||||
}
|
||||
|
||||
static NMKeyfileConnection *
|
||||
find_by_path (SCPluginKeyfile *self, const char *path)
|
||||
{
|
||||
|
@ -162,6 +156,51 @@ find_by_path (SCPluginKeyfile *self, const char *path)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
new_connection (SCPluginKeyfile *self,
|
||||
const char *name,
|
||||
char **out_old_path)
|
||||
{
|
||||
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
||||
NMKeyfileConnection *tmp, *connection;
|
||||
GError *error = NULL;
|
||||
|
||||
if (out_old_path)
|
||||
*out_old_path = NULL;
|
||||
|
||||
tmp = nm_keyfile_connection_new (NULL, name, &error);
|
||||
if (!tmp) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error in connection %s: %s", name,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Connection renames will show as different paths but same UUID */
|
||||
connection = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (NM_CONNECTION (tmp)));
|
||||
if (connection) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "rename %s -> %s",
|
||||
nm_keyfile_connection_get_path (connection), name);
|
||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
FALSE, /* don't set Unsaved */
|
||||
&error)) {
|
||||
/* Shouldn't ever get here as 'tmp' was verified by the reader already */
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
g_object_unref (tmp);
|
||||
if (out_old_path)
|
||||
*out_old_path = g_strdup (nm_keyfile_connection_get_path (connection));
|
||||
nm_keyfile_connection_set_path (connection, name);
|
||||
} else {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "new connection %s", name);
|
||||
g_hash_table_insert (priv->connections,
|
||||
(gpointer) nm_connection_get_uuid (NM_CONNECTION (tmp)),
|
||||
tmp);
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dir_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
|
@ -171,10 +210,8 @@ dir_changed (GFileMonitor *monitor,
|
|||
{
|
||||
NMSystemConfigInterface *config = NM_SYSTEM_CONFIG_INTERFACE (user_data);
|
||||
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
||||
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
||||
NMKeyfileConnection *connection;
|
||||
char *full_path;
|
||||
NMKeyfileConnection *connection, *tmp;
|
||||
GError *error = NULL;
|
||||
|
||||
full_path = g_file_get_path (file);
|
||||
if (nm_keyfile_plugin_utils_should_ignore_file (full_path)) {
|
||||
|
@ -186,67 +223,15 @@ dir_changed (GFileMonitor *monitor,
|
|||
|
||||
switch (event_type) {
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
if (connection) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "removed %s.", full_path);
|
||||
if (connection)
|
||||
remove_connection (SC_PLUGIN_KEYFILE (config), connection);
|
||||
}
|
||||
break;
|
||||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
if (connection) {
|
||||
/* Update */
|
||||
tmp = nm_keyfile_connection_new (NULL, full_path, &error);
|
||||
if (tmp) {
|
||||
if (!nm_connection_compare (NM_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", full_path);
|
||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
FALSE, /* don't set Unsaved */
|
||||
&error)) {
|
||||
/* Shouldn't ever get here as 'new' was verified by the reader already */
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
}
|
||||
g_object_unref (tmp);
|
||||
} else {
|
||||
/* Error; remove the connection */
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
remove_connection (SC_PLUGIN_KEYFILE (config), connection);
|
||||
}
|
||||
} else {
|
||||
/* New */
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, "updating %s", full_path);
|
||||
tmp = nm_keyfile_connection_new (NULL, full_path, &error);
|
||||
if (tmp) {
|
||||
/* Connection renames will show as different paths but same UUID */
|
||||
connection = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (NM_CONNECTION (tmp)));
|
||||
if (connection) {
|
||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection),
|
||||
NM_CONNECTION (tmp),
|
||||
FALSE, /* don't set Unsaved */
|
||||
&error)) {
|
||||
/* Shouldn't ever get here as 'tmp' was verified by the reader already */
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
g_object_unref (tmp);
|
||||
nm_keyfile_connection_set_path (connection, full_path);
|
||||
} else {
|
||||
g_hash_table_insert (priv->connections,
|
||||
(gpointer) nm_connection_get_uuid (NM_CONNECTION (tmp)),
|
||||
tmp);
|
||||
g_signal_emit_by_name (config, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, tmp);
|
||||
}
|
||||
} else {
|
||||
PLUGIN_PRINT (KEYFILE_PLUGIN_NAME, " error: %s",
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
if (connection)
|
||||
update_connection (SC_PLUGIN_KEYFILE (config), connection, full_path);
|
||||
else
|
||||
new_connection (SC_PLUGIN_KEYFILE (config), full_path, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -299,6 +284,7 @@ setup_monitoring (NMSystemConfigInterface *config)
|
|||
GFile *file;
|
||||
GFileMonitor *monitor;
|
||||
|
||||
if (nm_config_get_monitor_connection_files (nm_config_get ())) {
|
||||
file = g_file_new_for_path (KEYFILE_DIR);
|
||||
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_object_unref (file);
|
||||
|
@ -307,6 +293,7 @@ setup_monitoring (NMSystemConfigInterface *config)
|
|||
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config);
|
||||
priv->monitor = monitor;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->conf_file) {
|
||||
file = g_file_new_for_path (priv->conf_file);
|
||||
|
@ -320,6 +307,66 @@ setup_monitoring (NMSystemConfigInterface *config)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
read_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
|
||||
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
|
||||
GDir *dir;
|
||||
GError *error = NULL;
|
||||
const char *item;
|
||||
GHashTable *oldconns;
|
||||
GHashTableIter iter;
|
||||
gpointer data;
|
||||
|
||||
dir = g_dir_open (KEYFILE_DIR, 0, &error);
|
||||
if (!dir) {
|
||||
PLUGIN_WARN (KEYFILE_PLUGIN_NAME, "Cannot read directory '%s': (%d) %s",
|
||||
KEYFILE_DIR,
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
oldconns = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data))
|
||||
g_hash_table_insert (oldconns, g_strdup (nm_keyfile_connection_get_path (data)), data);
|
||||
|
||||
while ((item = g_dir_read_name (dir))) {
|
||||
NMKeyfileConnection *connection;
|
||||
char *full_path, *old_path;
|
||||
|
||||
if (nm_keyfile_plugin_utils_should_ignore_file (item))
|
||||
continue;
|
||||
|
||||
full_path = g_build_filename (KEYFILE_DIR, item, NULL);
|
||||
|
||||
connection = g_hash_table_lookup (oldconns, full_path);
|
||||
if (connection) {
|
||||
g_hash_table_remove (oldconns, full_path);
|
||||
update_connection (self, connection, full_path);
|
||||
} else {
|
||||
new_connection (self, full_path, &old_path);
|
||||
if (old_path) {
|
||||
g_hash_table_remove (oldconns, old_path);
|
||||
g_free (old_path);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (full_path);
|
||||
}
|
||||
g_dir_close (dir);
|
||||
|
||||
g_hash_table_iter_init (&iter, oldconns);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &data)) {
|
||||
g_hash_table_iter_remove (&iter);
|
||||
remove_connection (self, data);
|
||||
}
|
||||
g_hash_table_destroy (oldconns);
|
||||
}
|
||||
|
||||
/* Plugin */
|
||||
|
||||
static GSList *
|
||||
|
@ -342,6 +389,12 @@ get_connections (NMSystemConfigInterface *config)
|
|||
return list;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_connections (NMSystemConfigInterface *config)
|
||||
{
|
||||
read_connections (config);
|
||||
}
|
||||
|
||||
static NMSettingsConnection *
|
||||
add_connection (NMSystemConfigInterface *config,
|
||||
NMConnection *connection,
|
||||
|
@ -634,6 +687,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
|
|||
{
|
||||
/* interface implementation */
|
||||
system_config_interface_class->get_connections = get_connections;
|
||||
system_config_interface_class->reload_connections = reload_connections;
|
||||
system_config_interface_class->add_connection = add_connection;
|
||||
system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue