From 8b7b0d3fc2604a2cdecb32d97f8cb3ff63a069f0 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Mon, 28 Nov 2016 12:32:03 +0000 Subject: [PATCH] ifcfg-rh: write the master device name even if the master property is an UUID We used MASTER, BRIDGE and TEAM_MASTER keys for a differnet purpose than the network.service did, confusing the legacy tooling. Let's do our best to write compatible configuration files: * Add *_UUID properties that won't clash with initscripts * Ignore non-*_UUID keys on read if *_UUID is present * If the connection.master is an UUID of a connection with a connection.interface-name, write the uuid into the *_UUID key while setting the non-*_UUID key to the interface name for compatibility https://bugzilla.redhat.com/show_bug.cgi?id=1369091 --- libnm-core/nm-setting-connection.c | 14 ++++-- src/nm-manager.c | 24 +++++++++ src/nm-manager.h | 3 ++ .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 18 +++++-- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 49 ++++++++++++------- 5 files changed, 82 insertions(+), 26 deletions(-) diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 63bd0847ac..ebcd69c5e5 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -1696,9 +1696,11 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) **/ /* ---ifcfg-rh--- * property: master - * variable: MASTER, TEAM_MASTER, BRIDGE + * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, BRIDGE, BRIDGE_UUID * description: Reference to master connection. The variable used depends on - * the connection type. + * the connection type and the value. In general, if the *_UUID variant is present, + * the variant without *_UUID is ignored. NetworkManager attempts to write both + * for compatibility with legacy tooling. * ---end--- */ g_object_class_install_property @@ -1719,10 +1721,12 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class) **/ /* ---ifcfg-rh--- * property: slave-type - * variable: MASTER, TEAM_MASTER, DEVICETYPE, BRIDGE + * variable: MASTER, MASTER_UUID, TEAM_MASTER, TEAM_MASTER_UUID, DEVICETYPE, + * BRIDGE, BRIDGE_UUID * description: Slave type doesn't map directly to a variable, but it is - * recognized using different variables. MASTER for bonding, - * TEAM_MASTER and DEVICETYPE for teaming, BRIDGE for bridging. + * recognized using different variables. MASTER and MASTER_UUID for bonding, + * TEAM_MASTER, TEAM_MASTER_UUID and DEVICETYPE for teaming, BRIDGE + * and BRIDGE_UUID for bridging. * ---end--- */ g_object_class_install_property diff --git a/src/nm-manager.c b/src/nm-manager.c index fa3e2f8028..feca5a8de9 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1145,6 +1145,30 @@ nm_manager_get_connection_iface (NMManager *self, return iface; } +/** + * nm_manager_iface_for_uuid: + * @self: the #NMManager + * @uuid: the connection uuid + * + * Gets a link name for the given UUID. Useful for the settings plugins that + * wish to write configuration files compatible with tooling that can't + * interpret our UUIDs. + * + * Returns: An interface name; %NULL if none matches + */ +const char * +nm_manager_iface_for_uuid (NMManager *self, const char *uuid) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + NMSettingsConnection *connection; + + connection = nm_settings_get_connection_by_uuid (priv->settings, uuid); + if (!connection) + return NULL; + + return nm_connection_get_interface_name (NM_CONNECTION (connection)); +} + /** * system_create_virtual_device: * @self: the #NMManager diff --git a/src/nm-manager.h b/src/nm-manager.h index 963e22798c..13cae375be 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -103,6 +103,9 @@ char * nm_manager_get_connection_iface (NMManager *self, NMDevice **out_parent, GError **error); +const char * nm_manager_iface_for_uuid (NMManager *self, + const char *uuid); + NMActiveConnection *nm_manager_activate_connection (NMManager *manager, NMSettingsConnection *connection, NMConnection *applied_connection, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 2b4abffbe5..6f8824d0b2 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -231,7 +231,9 @@ make_connection_setting (const char *file, g_strfreev (items); } - value = svGetValueString (ifcfg, "BRIDGE"); + value = svGetValueString (ifcfg, "BRIDGE_UUID"); + if (!value) + value = svGetValueString (ifcfg, "BRIDGE"); if (value) { const char *old_value; @@ -1670,7 +1672,10 @@ check_if_bond_slave (shvarFile *ifcfg, { char *value; - value = svGetValueString (ifcfg, "MASTER"); + value = svGetValueString (ifcfg, "MASTER_UUID"); + if (!value) + value = svGetValueString (ifcfg, "MASTER"); + if (value) { g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL); g_object_set (s_con, @@ -1690,9 +1695,12 @@ check_if_team_slave (shvarFile *ifcfg, { gs_free char *value = NULL; - value = svGetValueString (ifcfg, "TEAM_MASTER"); + value = svGetValueString (ifcfg, "TEAM_MASTER_UUID"); + if (!value) + value = svGetValueString (ifcfg, "TEAM_MASTER"); if (!value) return FALSE; + g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL); g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_TEAM_SETTING_NAME, NULL); return TRUE; @@ -4646,7 +4654,9 @@ make_bridge_port_setting (shvarFile *ifcfg) g_return_val_if_fail (ifcfg != NULL, FALSE); - value = svGetValueString (ifcfg, "BRIDGE"); + value = svGetValueString (ifcfg, "BRIDGE_UUID"); + if (!value) + value = svGetValueString (ifcfg, "BRIDGE"); if (value) { g_free (value); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index fdeb8cf9a4..aef4cd8807 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -32,6 +32,7 @@ #include #include +#include "nm-manager.h" #include "nm-setting-connection.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" @@ -1741,13 +1742,9 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) { guint32 n, i; GString *str; - const char *master, *type; + const char *master, *master_iface = NULL, *type; char *tmp; gint i_int; - const char *v_master = NULL; - const char *v_slave = NULL; - const char *v_bridge = NULL; - const char *v_team_master = NULL; svSetValueString (ifcfg, "NAME", nm_setting_connection_get_id (s_con)); svSetValueString (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con)); @@ -1815,27 +1812,45 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueString (ifcfg, "ZONE", nm_setting_connection_get_zone(s_con)); + svSetValueString (ifcfg, "MASTER_UUID", NULL); + svSetValueString (ifcfg, "MASTER", NULL); + svSetValueString (ifcfg, "SLAVE", NULL); + svSetValueString (ifcfg, "BRIDGE_UUID", NULL); + svSetValueString (ifcfg, "BRIDGE", NULL); + svSetValueString (ifcfg, "TEAM_MASTER_UUID", NULL); + svSetValueString (ifcfg, "TEAM_MASTER", NULL); + master = nm_setting_connection_get_master (s_con); if (master) { + /* The reader prefers the *_UUID variants, however we still try to resolve + * it into an interface name, so that legacy tooling is not confused. */ + if (!nm_utils_get_testing ()) { + /* This is conditional for easier testing. */ + master_iface = nm_manager_iface_for_uuid (nm_manager_get (), master); + } + if (!master_iface) { + master_iface = master; + master = NULL; + + } + if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BOND_SETTING_NAME)) { - v_master = master; - v_slave = "yes"; - } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)) - v_bridge = master; - else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) { - v_team_master = master; + svSetValueString (ifcfg, "MASTER_UUID", master); + svSetValueString (ifcfg, "MASTER", master_iface); + svSetValueString (ifcfg, "SLAVE", "yes"); + } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)) { + svSetValueString (ifcfg, "BRIDGE_UUID", master); + svSetValueString (ifcfg, "BRIDGE", master_iface); + } else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) { + svSetValueString (ifcfg, "TEAM_MASTER_UUID", master); + svSetValueString (ifcfg, "TEAM_MASTER", master_iface); svUnsetValue (ifcfg, "TYPE"); } } - svSetValueString (ifcfg, "MASTER", v_master); - svSetValueString (ifcfg, "SLAVE", v_slave); - svSetValueString (ifcfg, "BRIDGE", v_bridge); - svSetValueString (ifcfg, "TEAM_MASTER", v_team_master); - if (nm_streq0 (type, NM_SETTING_TEAM_SETTING_NAME)) svSetValueString (ifcfg, "DEVICETYPE", TYPE_TEAM); - else if (master && nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) + else if (master_iface && nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) svSetValueString (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT); else svUnsetValue (ifcfg, "DEVICETYPE");