mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-05 13:30:28 +01:00
settings: add unrecognized-specs, implement in ifcfg-rh
In Fedora, OVS ports are now identified in ifcfg files as "TYPE=OVSPort", which NM doesn't recognize, and so it would ignore those ifcfg files. Unfortunately, this meant that if auto-default wasn't disabled, and there was no other configuration defined for the device, then NM would create an NMDefaultWiredConnection for it and screw things up. So, add an "unrecognized-specs" settings plugin property, which allows a plugin to indicate to NetworkManager that it knows of some non-NetworkManager-supported connection defined for a device. This will suppress default-wired connection creation for that device, similar to the "no-auto-default" config file option, but determined by the plugin instead of by manual configuration. Devices listed in unrecognized-specs may still be managed by NetworkManager, unless they are also listed in unmanaged-specs. https://bugzilla.redhat.com/show_bug.cgi?id=1022256
This commit is contained in:
parent
0d3674a50a
commit
e213707623
11 changed files with 297 additions and 126 deletions
|
|
@ -115,6 +115,7 @@ static void impl_settings_save_hostname (NMSettings *self,
|
|||
#include "nm-settings-glue.h"
|
||||
|
||||
static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data);
|
||||
static void unrecognized_specs_changed (NMSystemConfigInterface *config, gpointer user_data);
|
||||
|
||||
static void connection_provider_init (NMConnectionProvider *cp_class);
|
||||
|
||||
|
|
@ -136,6 +137,7 @@ typedef struct {
|
|||
gboolean connections_loaded;
|
||||
GHashTable *connections;
|
||||
GSList *unmanaged_specs;
|
||||
GSList *unrecognized_specs;
|
||||
GSList *get_connections_cache;
|
||||
} NMSettingsPrivate;
|
||||
|
||||
|
|
@ -201,11 +203,14 @@ load_connections (NMSettings *self)
|
|||
G_CALLBACK (plugin_connection_added), self);
|
||||
g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED,
|
||||
G_CALLBACK (unmanaged_specs_changed), self);
|
||||
g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED,
|
||||
G_CALLBACK (unrecognized_specs_changed), self);
|
||||
}
|
||||
|
||||
priv->connections_loaded = TRUE;
|
||||
|
||||
unmanaged_specs_changed (NULL, self);
|
||||
unrecognized_specs_changed (NULL, self);
|
||||
|
||||
g_signal_emit (self, signals[CONNECTIONS_LOADED], 0);
|
||||
g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTIONS_LOADED);
|
||||
|
|
@ -356,15 +361,6 @@ nm_settings_get_connection_by_path (NMSettings *self, const char *path)
|
|||
return (NMSettingsConnection *) g_hash_table_lookup (priv->connections, path);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_unmanaged_specs (NMSettings *self)
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
g_slist_free_full (priv->unmanaged_specs, g_free);
|
||||
priv->unmanaged_specs = NULL;
|
||||
}
|
||||
|
||||
static char*
|
||||
uscore_to_wincaps (const char *uscore)
|
||||
{
|
||||
|
|
@ -466,16 +462,40 @@ nm_settings_get_hostname (NMSettings *self)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
find_unmanaged_device (NMSettings *self, const char *needle)
|
||||
find_spec (GSList *spec_list, const char *spec)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
for (iter = spec_list; iter; iter = g_slist_next (iter)) {
|
||||
if (!strcmp ((const char *) iter->data, spec))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_specs (NMSettings *self, GSList **specs_ptr,
|
||||
GSList * (*get_specs_func) (NMSystemConfigInterface *))
|
||||
{
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
|
||||
for (iter = priv->unmanaged_specs; iter; iter = g_slist_next (iter)) {
|
||||
if (!strcmp ((const char *) iter->data, needle))
|
||||
return TRUE;
|
||||
g_slist_free_full (*specs_ptr, g_free);
|
||||
*specs_ptr = NULL;
|
||||
|
||||
for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
|
||||
GSList *specs, *specs_iter;
|
||||
|
||||
specs = get_specs_func (NM_SYSTEM_CONFIG_INTERFACE (iter->data));
|
||||
for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) {
|
||||
if (!find_spec (*specs_ptr, (const char *) specs_iter->data)) {
|
||||
*specs_ptr = g_slist_prepend (*specs_ptr, specs_iter->data);
|
||||
} else
|
||||
g_free (specs_iter->data);
|
||||
}
|
||||
|
||||
g_slist_free (specs);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -484,28 +504,23 @@ unmanaged_specs_changed (NMSystemConfigInterface *config,
|
|||
{
|
||||
NMSettings *self = NM_SETTINGS (user_data);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
|
||||
clear_unmanaged_specs (self);
|
||||
|
||||
/* Ask all the plugins for their unmanaged specs */
|
||||
for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
|
||||
GSList *specs, *specs_iter;
|
||||
|
||||
specs = nm_system_config_interface_get_unmanaged_specs (NM_SYSTEM_CONFIG_INTERFACE (iter->data));
|
||||
for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) {
|
||||
if (!find_unmanaged_device (self, (const char *) specs_iter->data)) {
|
||||
priv->unmanaged_specs = g_slist_prepend (priv->unmanaged_specs, specs_iter->data);
|
||||
} else
|
||||
g_free (specs_iter->data);
|
||||
}
|
||||
|
||||
g_slist_free (specs);
|
||||
}
|
||||
|
||||
update_specs (self, &priv->unmanaged_specs,
|
||||
nm_system_config_interface_get_unmanaged_specs);
|
||||
g_object_notify (G_OBJECT (self), NM_SETTINGS_UNMANAGED_SPECS);
|
||||
}
|
||||
|
||||
static void
|
||||
unrecognized_specs_changed (NMSystemConfigInterface *config,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettings *self = NM_SETTINGS (user_data);
|
||||
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
|
||||
|
||||
update_specs (self, &priv->unrecognized_specs,
|
||||
nm_system_config_interface_get_unrecognized_specs);
|
||||
}
|
||||
|
||||
static void
|
||||
hostname_changed (NMSystemConfigInterface *config,
|
||||
GParamSpec *pspec,
|
||||
|
|
@ -1430,6 +1445,10 @@ have_connection_for_device (NMSettings *self, NMDevice *device)
|
|||
}
|
||||
}
|
||||
|
||||
/* See if there's a known non-NetworkManager configuration for the device */
|
||||
if (nm_device_spec_match_list (device, priv->unrecognized_specs))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1698,6 +1717,7 @@ nm_settings_new (GError **error)
|
|||
}
|
||||
|
||||
unmanaged_specs_changed (NULL, self);
|
||||
unrecognized_specs_changed (NULL, self);
|
||||
|
||||
nm_dbus_manager_register_object (priv->dbus_mgr, NM_DBUS_PATH_SETTINGS, self);
|
||||
return self;
|
||||
|
|
@ -1757,7 +1777,8 @@ finalize (GObject *object)
|
|||
g_hash_table_destroy (priv->connections);
|
||||
g_slist_free (priv->get_connections_cache);
|
||||
|
||||
clear_unmanaged_specs (self);
|
||||
g_slist_free_full (priv->unmanaged_specs, g_free);
|
||||
g_slist_free_full (priv->unrecognized_specs, g_free);
|
||||
|
||||
g_slist_free_full (priv->plugins, g_object_unref);
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,14 @@ interface_init (gpointer g_iface)
|
|||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED,
|
||||
iface_type,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMSystemConfigInterface, unrecognized_specs_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
initialized = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -156,6 +164,16 @@ nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
GSList *
|
||||
nm_system_config_interface_get_unrecognized_specs (NMSystemConfigInterface *config)
|
||||
{
|
||||
g_return_val_if_fail (config != NULL, NULL);
|
||||
|
||||
if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unrecognized_specs)
|
||||
return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unrecognized_specs (config);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_system_config_interface_add_connection:
|
||||
* @config: the #NMSystemConfigInterface
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ GObject * nm_system_config_factory (void);
|
|||
#define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname"
|
||||
|
||||
#define NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed"
|
||||
#define NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED "unrecognized-specs-changed"
|
||||
#define NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED "connection-added"
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -100,20 +101,23 @@ struct _NMSystemConfigInterface {
|
|||
* service, and each element must be allocated using g_malloc() or its
|
||||
* variants (g_strdup, g_strdup_printf, etc).
|
||||
*
|
||||
* Each string in the list must follow the format <method>:<data>, where
|
||||
* the method and data are one of the following:
|
||||
*
|
||||
* Method: mac Data: device MAC address formatted with leading zeros and
|
||||
* lowercase letters, like 00:0a:0b:0c:0d:0e
|
||||
*
|
||||
* Method: s390-subchannels Data: string of 2 or 3 s390 subchannels
|
||||
* separated by commas (,) that identify the
|
||||
* device, like "0.0.09a0,0.0.09a1,0.0.09a2".
|
||||
* The string may contain only the following
|
||||
* characters: [a-fA-F0-9,.]
|
||||
* Each string in the list must be in one of the formats recognized by
|
||||
* nm_device_spec_match_list().
|
||||
*/
|
||||
GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config);
|
||||
|
||||
/*
|
||||
* Return a string list of specifications of devices for which at least
|
||||
* one non-NetworkManager-based configuration is defined. Returned list
|
||||
* will be freed by the system settings service, and each element must be
|
||||
* allocated using g_malloc() or its variants (g_strdup, g_strdup_printf,
|
||||
* etc).
|
||||
*
|
||||
* Each string in the list must be in one of the formats recognized by
|
||||
* nm_device_spec_match_list().
|
||||
*/
|
||||
GSList * (*get_unrecognized_specs) (NMSystemConfigInterface *config);
|
||||
|
||||
/*
|
||||
* Initialize the plugin-specific connection and return a new
|
||||
* NMSettingsConnection subclass that contains the same settings as the
|
||||
|
|
@ -134,6 +138,9 @@ struct _NMSystemConfigInterface {
|
|||
|
||||
/* Emitted when the list of unmanaged device specifications changes */
|
||||
void (*unmanaged_specs_changed) (NMSystemConfigInterface *config);
|
||||
|
||||
/* Emitted when the list of devices with unrecognized connections changes */
|
||||
void (*unrecognized_specs_changed) (NMSystemConfigInterface *config);
|
||||
};
|
||||
|
||||
GType nm_system_config_interface_get_type (void);
|
||||
|
|
@ -146,6 +153,7 @@ GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *con
|
|||
void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config);
|
||||
|
||||
GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config);
|
||||
GSList *nm_system_config_interface_get_unrecognized_specs (NMSystemConfigInterface *config);
|
||||
|
||||
NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
|
||||
NMConnection *connection,
|
||||
|
|
|
|||
|
|
@ -61,12 +61,14 @@ typedef struct {
|
|||
char *route6file;
|
||||
int route6file_wd;
|
||||
|
||||
char *unmanaged;
|
||||
char *unmanaged_spec;
|
||||
char *unrecognized_spec;
|
||||
} NMIfcfgConnectionPrivate;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_UNMANAGED,
|
||||
PROP_UNMANAGED_SPEC,
|
||||
PROP_UNRECOGNIZED_SPEC,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
|
|
@ -105,7 +107,8 @@ nm_ifcfg_connection_new (NMConnection *source,
|
|||
{
|
||||
GObject *object;
|
||||
NMConnection *tmp;
|
||||
char *unmanaged = NULL;
|
||||
char *unhandled_spec = NULL;
|
||||
const char *unmanaged_spec = NULL, *unrecognized_spec = NULL;
|
||||
gboolean update_unsaved = TRUE;
|
||||
|
||||
g_assert (source || full_path);
|
||||
|
|
@ -117,7 +120,7 @@ nm_ifcfg_connection_new (NMConnection *source,
|
|||
char *keyfile = NULL, *routefile = NULL, *route6file = NULL;
|
||||
|
||||
tmp = connection_from_file (full_path, NULL, NULL, NULL,
|
||||
&unmanaged,
|
||||
&unhandled_spec,
|
||||
&keyfile,
|
||||
&routefile,
|
||||
&route6file,
|
||||
|
|
@ -133,8 +136,14 @@ nm_ifcfg_connection_new (NMConnection *source,
|
|||
update_unsaved = FALSE;
|
||||
}
|
||||
|
||||
if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unmanaged:"))
|
||||
unmanaged_spec = unhandled_spec + strlen ("unmanaged:");
|
||||
else if (unhandled_spec && g_str_has_prefix (unhandled_spec, "unrecognized:"))
|
||||
unrecognized_spec = unhandled_spec + strlen ("unrecognized:");
|
||||
|
||||
object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION,
|
||||
NM_IFCFG_CONNECTION_UNMANAGED, unmanaged,
|
||||
NM_IFCFG_CONNECTION_UNMANAGED_SPEC, unmanaged_spec,
|
||||
NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec,
|
||||
NULL);
|
||||
if (object) {
|
||||
/* Update our settings with what was read from the file */
|
||||
|
|
@ -152,6 +161,7 @@ nm_ifcfg_connection_new (NMConnection *source,
|
|||
}
|
||||
|
||||
g_object_unref (tmp);
|
||||
g_free (unhandled_spec);
|
||||
return (NMIfcfgConnection *) object;
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +244,15 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self)
|
|||
{
|
||||
g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
|
||||
|
||||
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged;
|
||||
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged_spec;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_IFCFG_CONNECTION (self), NULL);
|
||||
|
||||
return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -344,8 +362,11 @@ set_property (GObject *object, guint prop_id,
|
|||
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UNMANAGED:
|
||||
priv->unmanaged = g_value_dup_string (value);
|
||||
case PROP_UNMANAGED_SPEC:
|
||||
priv->unmanaged_spec = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_UNRECOGNIZED_SPEC:
|
||||
priv->unrecognized_spec = g_value_dup_string (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -360,8 +381,11 @@ get_property (GObject *object, guint prop_id,
|
|||
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UNMANAGED:
|
||||
g_value_set_string (value, priv->unmanaged);
|
||||
case PROP_UNMANAGED_SPEC:
|
||||
g_value_set_string (value, priv->unmanaged_spec);
|
||||
break;
|
||||
case PROP_UNRECOGNIZED_SPEC:
|
||||
g_value_set_string (value, priv->unrecognized_spec);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -386,12 +410,19 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class)
|
|||
|
||||
/* Properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_UNMANAGED,
|
||||
g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED,
|
||||
"Unmanaged",
|
||||
"Unmanaged",
|
||||
(object_class, PROP_UNMANAGED_SPEC,
|
||||
g_param_spec_string (NM_IFCFG_CONNECTION_UNMANAGED_SPEC,
|
||||
"Unmanaged spec",
|
||||
"Unmanaged spec",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_UNRECOGNIZED_SPEC,
|
||||
g_param_spec_string (NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC,
|
||||
"Unrecognized spec",
|
||||
"Unrecognized spec",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
signals[IFCFG_CHANGED] =
|
||||
g_signal_new ("ifcfg-changed",
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ G_BEGIN_DECLS
|
|||
#define NM_IS_IFCFG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IFCFG_CONNECTION))
|
||||
#define NM_IFCFG_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionClass))
|
||||
|
||||
#define NM_IFCFG_CONNECTION_UNMANAGED "unmanaged"
|
||||
#define NM_IFCFG_CONNECTION_UNMANAGED_SPEC "unmanaged-spec"
|
||||
#define NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC "unrecognized-spec"
|
||||
|
||||
typedef struct {
|
||||
NMSettingsConnection parent;
|
||||
|
|
@ -56,6 +57,7 @@ void nm_ifcfg_connection_set_path (NMIfcfgConnection *self,
|
|||
const char *ifcfg_path);
|
||||
|
||||
const char *nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self);
|
||||
const char *nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self);
|
||||
|
||||
gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self,
|
||||
GHashTable *new_settings,
|
||||
|
|
|
|||
|
|
@ -163,6 +163,9 @@ _internal_new_connection (SCPluginIfcfg *self,
|
|||
device_id = spec;
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' / device '%s' "
|
||||
"due to NM_CONTROLLED=no.", cid, device_id);
|
||||
} else if (nm_ifcfg_connection_get_unrecognized_spec (connection)) {
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' "
|
||||
"of unrecognized type.", cid);
|
||||
}
|
||||
|
||||
/* watch changes of ifcfg hardlinks */
|
||||
|
|
@ -178,21 +181,24 @@ static void
|
|||
remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection)
|
||||
{
|
||||
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
|
||||
gboolean managed = FALSE;
|
||||
gboolean unmanaged, unrecognized;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (connection != NULL);
|
||||
|
||||
managed = !nm_ifcfg_connection_get_unmanaged_spec (connection);
|
||||
unmanaged = !!nm_ifcfg_connection_get_unmanaged_spec (connection);
|
||||
unrecognized = !!nm_ifcfg_connection_get_unrecognized_spec (connection);
|
||||
|
||||
g_object_ref (connection);
|
||||
g_hash_table_remove (priv->connections, nm_connection_get_uuid (NM_CONNECTION (connection)));
|
||||
nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection));
|
||||
g_object_unref (connection);
|
||||
|
||||
/* Emit unmanaged changes _after_ removing the connection */
|
||||
if (managed == FALSE)
|
||||
/* Emit changes _after_ removing the connection */
|
||||
if (unmanaged)
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
|
||||
if (unrecognized)
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
|
||||
}
|
||||
|
||||
static NMIfcfgConnection *
|
||||
|
|
@ -238,6 +244,8 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
GError *error = NULL;
|
||||
gboolean ignore_error = FALSE;
|
||||
const char *new_unmanaged = NULL, *old_unmanaged = NULL;
|
||||
const char *new_unrecognized = NULL, *old_unrecognized = NULL;
|
||||
gboolean unmanaged_changed, unrecognized_changed;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (path != NULL);
|
||||
|
|
@ -261,12 +269,12 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
/* New connection */
|
||||
new = _internal_new_connection (self, path, NULL, NULL);
|
||||
if (new) {
|
||||
if (nm_ifcfg_connection_get_unmanaged_spec (new)) {
|
||||
if (nm_ifcfg_connection_get_unmanaged_spec (new))
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
|
||||
} else {
|
||||
/* Only managed connections are announced to the settings service */
|
||||
else if (nm_ifcfg_connection_get_unrecognized_spec (new))
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
|
||||
else
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -289,25 +297,30 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
|
||||
old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (existing));
|
||||
new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new));
|
||||
unmanaged_changed = g_strcmp0 (old_unmanaged, new_unmanaged);
|
||||
|
||||
/* When interface is unmanaged or the connections and unmanaged specs are the same
|
||||
* there's nothing to do */
|
||||
if ( (g_strcmp0 (old_unmanaged, new_unmanaged) == 0 && new_unmanaged != NULL)
|
||||
|| ( nm_connection_compare (NM_CONNECTION (existing),
|
||||
NM_CONNECTION (new),
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
|
||||
&& g_strcmp0 (old_unmanaged, new_unmanaged) == 0)) {
|
||||
old_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (existing));
|
||||
new_unrecognized = nm_ifcfg_connection_get_unrecognized_spec (NM_IFCFG_CONNECTION (new));
|
||||
unrecognized_changed = g_strcmp0 (old_unrecognized, new_unrecognized);
|
||||
|
||||
if ( !unmanaged_changed
|
||||
&& !unrecognized_changed
|
||||
&& nm_connection_compare (NM_CONNECTION (existing),
|
||||
NM_CONNECTION (new),
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS |
|
||||
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) {
|
||||
g_object_unref (new);
|
||||
return;
|
||||
}
|
||||
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path);
|
||||
g_object_set (existing, NM_IFCFG_CONNECTION_UNMANAGED, new_unmanaged, NULL);
|
||||
g_object_set (existing,
|
||||
NM_IFCFG_CONNECTION_UNMANAGED_SPEC, new_unmanaged,
|
||||
NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized,
|
||||
NULL);
|
||||
|
||||
if (new_unmanaged) {
|
||||
if (!old_unmanaged) {
|
||||
if (new_unmanaged || new_unrecognized) {
|
||||
if (!old_unmanaged && !old_unrecognized) {
|
||||
g_object_ref (existing);
|
||||
/* Unexport the connection by telling the settings service it's
|
||||
* been removed.
|
||||
|
|
@ -325,12 +338,16 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
existing);
|
||||
}
|
||||
} else {
|
||||
if (old_unmanaged) { /* now managed */
|
||||
const char *cid = nm_connection_get_id (NM_CONNECTION (new));
|
||||
const char *cid = nm_connection_get_id (NM_CONNECTION (new));
|
||||
|
||||
if (old_unmanaged /* && !new_unmanaged */) {
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' and its "
|
||||
"device because NM_CONTROLLED was true.", cid);
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing);
|
||||
} else if (old_unrecognized /* && !new_unrecognized */) {
|
||||
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' "
|
||||
"because it is now a recognized type.", cid);
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, existing);
|
||||
}
|
||||
|
||||
if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (existing),
|
||||
|
|
@ -343,8 +360,10 @@ connection_new_or_changed (SCPluginIfcfg *self,
|
|||
}
|
||||
g_object_unref (new);
|
||||
|
||||
if (g_strcmp0 (old_unmanaged, new_unmanaged))
|
||||
if (unmanaged_changed)
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
|
||||
if (unrecognized_changed)
|
||||
g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -482,7 +501,8 @@ get_connections (NMSystemConfigInterface *config)
|
|||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) {
|
||||
if (!nm_ifcfg_connection_get_unmanaged_spec (connection))
|
||||
if ( !nm_ifcfg_connection_get_unmanaged_spec (connection)
|
||||
&& !nm_ifcfg_connection_get_unrecognized_spec (connection))
|
||||
list = g_slist_prepend (list, connection);
|
||||
}
|
||||
|
||||
|
|
@ -498,18 +518,19 @@ reload_connections (NMSystemConfigInterface *config)
|
|||
}
|
||||
|
||||
static GSList *
|
||||
get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||
get_unhandled_specs (NMSystemConfigInterface *config,
|
||||
const char *property)
|
||||
{
|
||||
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
|
||||
GSList *list = NULL, *list_iter;
|
||||
GHashTableIter iter;
|
||||
NMIfcfgConnection *connection;
|
||||
const char *spec;
|
||||
gpointer connection;
|
||||
char *spec;
|
||||
gboolean found;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) {
|
||||
spec = nm_ifcfg_connection_get_unmanaged_spec (connection);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &connection)) {
|
||||
g_object_get (connection, property, &spec, NULL);
|
||||
if (spec) {
|
||||
/* Ignore duplicates */
|
||||
for (list_iter = list, found = FALSE; list_iter; list_iter = g_slist_next (list_iter)) {
|
||||
|
|
@ -518,13 +539,27 @@ get_unmanaged_specs (NMSystemConfigInterface *config)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
list = g_slist_prepend (list, g_strdup (spec));
|
||||
if (found)
|
||||
g_free (spec);
|
||||
else
|
||||
list = g_slist_prepend (list, spec);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_unmanaged_specs (NMSystemConfigInterface *config)
|
||||
{
|
||||
return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNMANAGED_SPEC);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_unrecognized_specs (NMSystemConfigInterface *config)
|
||||
{
|
||||
return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC);
|
||||
}
|
||||
|
||||
static NMSettingsConnection *
|
||||
add_connection (NMSystemConfigInterface *config,
|
||||
NMConnection *connection,
|
||||
|
|
@ -678,7 +713,9 @@ impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin,
|
|||
}
|
||||
|
||||
connection = find_by_path (plugin, in_ifcfg);
|
||||
if (!connection || nm_ifcfg_connection_get_unmanaged_spec (connection)) {
|
||||
if ( !connection
|
||||
|| nm_ifcfg_connection_get_unmanaged_spec (connection)
|
||||
|| nm_ifcfg_connection_get_unrecognized_spec (connection)) {
|
||||
g_set_error (error,
|
||||
NM_SETTINGS_ERROR,
|
||||
NM_SETTINGS_ERROR_INVALID_CONNECTION,
|
||||
|
|
@ -930,6 +967,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
|
|||
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->get_unrecognized_specs = get_unrecognized_specs;
|
||||
system_config_interface_class->init = init;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4739,34 +4739,53 @@ vlan_connection_from_ifcfg (const char *file,
|
|||
return connection;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_unmanaged_spec (shvarFile *ifcfg)
|
||||
static NMConnection *
|
||||
create_unhandled_connection (const char *filename, shvarFile *ifcfg,
|
||||
const char *type, char **out_spec)
|
||||
{
|
||||
char *value, *unmanaged;
|
||||
NMConnection *connection;
|
||||
NMSetting *s_con;
|
||||
char *value;
|
||||
|
||||
g_assert (out_spec != NULL);
|
||||
|
||||
connection = nm_connection_new ();
|
||||
|
||||
/* Get NAME, UUID, etc. We need to set a connection type (generic) and add
|
||||
* an empty type-specific setting as well, to make sure it passes
|
||||
* nm_connection_verify() later.
|
||||
*/
|
||||
s_con = make_connection_setting (filename, ifcfg, NM_SETTING_GENERIC_SETTING_NAME,
|
||||
NULL, NULL);
|
||||
nm_connection_add_setting (connection, s_con);
|
||||
|
||||
nm_connection_add_setting (connection, nm_setting_generic_new ());
|
||||
|
||||
/* Get a spec */
|
||||
value = svGetValue (ifcfg, "HWADDR", FALSE);
|
||||
if (value) {
|
||||
char *lower = g_ascii_strdown (value, -1);
|
||||
unmanaged = g_strdup_printf ("mac:%s", lower);
|
||||
*out_spec = g_strdup_printf ("%s:mac:%s", type, lower);
|
||||
g_free (lower);
|
||||
g_free (value);
|
||||
return unmanaged;
|
||||
return connection;
|
||||
}
|
||||
|
||||
value = svGetValue (ifcfg, "SUBCHANNELS", FALSE);
|
||||
if (value) {
|
||||
unmanaged = g_strdup_printf ("s390-subchannels:%s", value);
|
||||
*out_spec = g_strdup_printf ("%s:s390-subchannels:%s", type, value);
|
||||
g_free (value);
|
||||
return unmanaged;
|
||||
return connection;
|
||||
}
|
||||
|
||||
value = svGetValue (ifcfg, "DEVICE", FALSE);
|
||||
if (value) {
|
||||
unmanaged = g_strdup_printf ("interface-name:%s", value);
|
||||
*out_spec = g_strdup_printf ("%s:interface-name:%s", type, value);
|
||||
g_free (value);
|
||||
return unmanaged;
|
||||
return connection;
|
||||
}
|
||||
|
||||
g_object_unref (connection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -4832,7 +4851,7 @@ connection_from_file (const char *filename,
|
|||
const char *network_file, /* for unit tests only */
|
||||
const char *test_type, /* for unit tests only */
|
||||
const char *iscsiadm_path, /* for unit tests only */
|
||||
char **out_unmanaged,
|
||||
char **out_unhandled,
|
||||
char **out_keyfile,
|
||||
char **out_routefile,
|
||||
char **out_route6file,
|
||||
|
|
@ -4846,8 +4865,8 @@ connection_from_file (const char *filename,
|
|||
const char *ifcfg_name = NULL;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
if (out_unmanaged)
|
||||
g_return_val_if_fail (*out_unmanaged == NULL, NULL);
|
||||
if (out_unhandled)
|
||||
g_return_val_if_fail (*out_unhandled == NULL, NULL);
|
||||
if (out_keyfile)
|
||||
g_return_val_if_fail (*out_keyfile == NULL, NULL);
|
||||
if (out_routefile)
|
||||
|
|
@ -4877,22 +4896,11 @@ connection_from_file (const char *filename,
|
|||
}
|
||||
|
||||
if (!svTrueValue (parsed, "NM_CONTROLLED", TRUE)) {
|
||||
NMSetting *s_con;
|
||||
g_assert (out_unhandled != NULL);
|
||||
|
||||
g_assert (out_unmanaged != NULL);
|
||||
|
||||
connection = nm_connection_new ();
|
||||
|
||||
/* Get NAME, UUID, etc. We need to set a connection type (generic) and add
|
||||
* an empty type-specific setting as well, to make sure it passes
|
||||
* nm_connection_verify() later.
|
||||
*/
|
||||
s_con = make_connection_setting (filename, parsed, NM_SETTING_GENERIC_SETTING_NAME,
|
||||
NULL, NULL);
|
||||
nm_connection_add_setting (connection, s_con);
|
||||
nm_connection_add_setting (connection, nm_setting_generic_new ());
|
||||
|
||||
*out_unmanaged = get_unmanaged_spec (parsed);
|
||||
connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled);
|
||||
if (!connection)
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but device was not uniquely identified; device will be managed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -4977,7 +4985,12 @@ connection_from_file (const char *filename,
|
|||
else if (!strcasecmp (type, TYPE_BRIDGE))
|
||||
connection = bridge_connection_from_ifcfg (filename, parsed, error);
|
||||
else {
|
||||
g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Unknown connection type '%s'", type);
|
||||
g_assert (out_unhandled != NULL);
|
||||
|
||||
connection = create_unhandled_connection (filename, parsed, "unrecognized", out_unhandled);
|
||||
if (!connection)
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: connection type was unrecognized but device was not uniquely identified; device may be managed");
|
||||
goto done;
|
||||
}
|
||||
g_free (type);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ NMConnection *connection_from_file (const char *filename,
|
|||
const char *network_file, /* for unit tests only */
|
||||
const char *test_type, /* for unit tests only */
|
||||
const char *iscsiadm_path, /* for unit tests only */
|
||||
char **out_unmanaged,
|
||||
char **out_unhandled,
|
||||
char **out_keyfile,
|
||||
char **out_routefile,
|
||||
char **out_route6file,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ EXTRA_DIST = \
|
|||
ifcfg-test-variables-corner-cases-1 \
|
||||
ifcfg-test-nm-controlled \
|
||||
ifcfg-test-nm-controlled-unrecognized \
|
||||
ifcfg-test-unrecognized \
|
||||
ifcfg-test-wired-static \
|
||||
ifcfg-test-wired-static-bootproto \
|
||||
ifcfg-test-wired-dhcp \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
TYPE=PPP-over-InfiniBand
|
||||
NAME=U Can't Touch This
|
||||
DEVICE=pppoipoib0
|
||||
HWADDR=00:11:22:33
|
||||
BOOTPROTO=dhcp
|
||||
ONBOOT=yes
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ test_read_unmanaged (void)
|
|||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
char *unmanaged = NULL;
|
||||
char *unhandled_spec = NULL;
|
||||
GError *error = NULL;
|
||||
const char *expected_id = "System test-nm-controlled";
|
||||
guint64 expected_timestamp = 0;
|
||||
|
|
@ -301,14 +301,14 @@ test_read_unmanaged (void)
|
|||
|
||||
connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled",
|
||||
NULL, TYPE_ETHERNET, NULL,
|
||||
&unmanaged,
|
||||
&unhandled_spec,
|
||||
NULL, NULL, NULL, &error, NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert (connection);
|
||||
success = nm_connection_verify (connection, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
g_assert_cmpstr (unmanaged, ==, "mac:00:11:22:33:f8:9f");
|
||||
g_assert_cmpstr (unhandled_spec, ==, "unmanaged:mac:00:11:22:33:f8:9f");
|
||||
|
||||
/* ===== CONNECTION SETTING ===== */
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
|
|
@ -317,7 +317,7 @@ test_read_unmanaged (void)
|
|||
g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
|
||||
g_assert (nm_setting_connection_get_autoconnect (s_con));
|
||||
|
||||
g_free (unmanaged);
|
||||
g_free (unhandled_spec);
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
|
|
@ -326,7 +326,7 @@ test_read_unmanaged_unrecognized (void)
|
|||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
char *unmanaged = NULL;
|
||||
char *unhandled_spec = NULL;
|
||||
GError *error = NULL;
|
||||
const char *expected_id = "PigeonNet";
|
||||
guint64 expected_timestamp = 0;
|
||||
|
|
@ -334,14 +334,45 @@ test_read_unmanaged_unrecognized (void)
|
|||
|
||||
connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-nm-controlled-unrecognized",
|
||||
NULL, NULL, NULL,
|
||||
&unmanaged,
|
||||
&unhandled_spec,
|
||||
NULL, NULL, NULL, &error, NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert (connection);
|
||||
success = nm_connection_verify (connection, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
g_assert_cmpstr (unmanaged, ==, "interface-name:ipoac0");
|
||||
g_assert_cmpstr (unhandled_spec, ==, "unmanaged:interface-name:ipoac0");
|
||||
|
||||
/* ===== CONNECTION SETTING ===== */
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
|
||||
g_assert_cmpint (nm_setting_connection_get_timestamp (s_con), ==, expected_timestamp);
|
||||
|
||||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
test_read_unrecognized (void)
|
||||
{
|
||||
NMConnection *connection;
|
||||
NMSettingConnection *s_con;
|
||||
char *unhandled_spec = NULL;
|
||||
GError *error = NULL;
|
||||
const char *expected_id = "U Can't Touch This";
|
||||
guint64 expected_timestamp = 0;
|
||||
gboolean success;
|
||||
|
||||
connection = connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-unrecognized",
|
||||
NULL, NULL, NULL,
|
||||
&unhandled_spec,
|
||||
NULL, NULL, NULL, &error, NULL);
|
||||
g_assert_no_error (error);
|
||||
g_assert (connection);
|
||||
success = nm_connection_verify (connection, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
g_assert_cmpstr (unhandled_spec, ==, "unrecognized:mac:00:11:22:33");
|
||||
|
||||
/* ===== CONNECTION SETTING ===== */
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
|
|
@ -13169,6 +13200,7 @@ int main (int argc, char **argv)
|
|||
|
||||
g_test_add_func (TPATH "unmanaged", test_read_unmanaged);
|
||||
g_test_add_func (TPATH "unmanaged-unrecognized", test_read_unmanaged_unrecognized);
|
||||
g_test_add_func (TPATH "unrecognized", test_read_unrecognized);
|
||||
g_test_add_func (TPATH "basic", test_read_basic);
|
||||
g_test_add_func (TPATH "variables-corner-cases", test_read_variables_corner_cases);
|
||||
g_test_add_data_func (TPATH "no-prefix/8", GUINT_TO_POINTER (8), test_read_wired_static_no_prefix);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue