Blob Blame History Raw
From b28b275c5e6c36bf7b63ed9ab7b99505de61bf98 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
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
(cherry picked from commit 8b7b0d3fc2604a2cdecb32d97f8cb3ff63a069f0)
---
 libnm-core/nm-setting-connection.c     | 14 +++++++-----
 src/nm-manager.c                       | 24 +++++++++++++++++++++
 src/nm-manager.h                       |  3 +++
 src/settings/plugins/ifcfg-rh/reader.c | 18 ++++++++++++----
 src/settings/plugins/ifcfg-rh/writer.c | 39 +++++++++++++++++++++++++---------
 5 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index f6b801c..a0a679e 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -1650,9 +1650,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
@@ -1673,10 +1675,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 c3d65cd..964c18a 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1135,6 +1135,30 @@ nm_manager_get_connection_iface (NMManager *self,
 }
 
 /**
+ * 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
  * @connection: the connection which might require a virtual device
diff --git a/src/nm-manager.h b/src/nm-manager.h
index d7aabff..ce3fa5a 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -99,6 +99,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,
                                                         const char *specific_object,
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index 5a351cf..825d51e 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -227,7 +227,9 @@ make_connection_setting (const char *file,
 		g_strfreev (items);
 	}
 
-	value = svGetValue (ifcfg, "BRIDGE", FALSE);
+	value = svGetValue (ifcfg, "BRIDGE_UUID", FALSE);
+	if (!value)
+		value = svGetValue (ifcfg, "BRIDGE", FALSE);
 	if (value) {
 		const char *old_value;
 
@@ -1607,7 +1609,10 @@ check_if_bond_slave (shvarFile *ifcfg,
 {
 	char *value;
 
-	value = svGetValue (ifcfg, "MASTER", FALSE);
+	value = svGetValue (ifcfg, "MASTER_UUID", FALSE);
+	if (!value)
+		value = svGetValue (ifcfg, "MASTER", FALSE);
+
 	if (value) {
 		g_object_set (s_con, NM_SETTING_CONNECTION_MASTER, value, NULL);
 		g_object_set (s_con,
@@ -1627,9 +1632,12 @@ check_if_team_slave (shvarFile *ifcfg,
 {
 	gs_free char *value = NULL;
 
-	value = svGetValue (ifcfg, "TEAM_MASTER", FALSE);
+	value = svGetValue (ifcfg, "TEAM_MASTER_UUID", FALSE);
+	if (!value)
+		value = svGetValue (ifcfg, "TEAM_MASTER", FALSE);
 	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;
@@ -4563,7 +4571,9 @@ make_bridge_port_setting (shvarFile *ifcfg)
 
 	g_return_val_if_fail (ifcfg != NULL, FALSE);
 
-	value = svGetValue (ifcfg, "BRIDGE", FALSE);
+	value = svGetValue (ifcfg, "BRIDGE_UUID", FALSE);
+	if (!value)
+		value = svGetValue (ifcfg, "BRIDGE", FALSE);
 	if (value) {
 		g_free (value);
 
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index dcc48f2..dff8f1b 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <stdio.h>
 
+#include "nm-manager.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless.h"
@@ -1804,13 +1805,13 @@ 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_master = NULL, *v_master_uuid = NULL;
+	const char *v_bridge = NULL, *v_bridge_uuid = NULL;
+	const char *v_team_master = NULL, *v_team_master_uuid = NULL;
 	const char *v_slave = NULL;
-	const char *v_bridge = NULL;
-	const char *v_team_master = NULL;
 
 	svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
 	svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
@@ -1878,25 +1879,43 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
 
 	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_master_uuid = master;
+			v_master = master_iface;
 			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;
+		} else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME)) {
+			v_bridge_uuid = master;
+			v_bridge = master_iface;
+		} else if (nm_setting_connection_is_slave_type (s_con, NM_SETTING_TEAM_SETTING_NAME)) {
+			v_team_master_uuid = master;
+			v_team_master = master_iface;
 			svSetValue (ifcfg, "TYPE", NULL, FALSE);
 		}
 	}
 
+	svSetValue (ifcfg, "MASTER_UUID", v_master_uuid, FALSE);
 	svSetValue (ifcfg, "MASTER", v_master, FALSE);
 	svSetValue (ifcfg, "SLAVE", v_slave, FALSE);
+	svSetValue (ifcfg, "BRIDGE_UUID", v_bridge_uuid, FALSE);
 	svSetValue (ifcfg, "BRIDGE", v_bridge, FALSE);
+	svSetValue (ifcfg, "TEAM_MASTER_UUID", v_team_master_uuid, FALSE);
 	svSetValue (ifcfg, "TEAM_MASTER", v_team_master, FALSE);
 
 	if (nm_streq0 (type, NM_SETTING_TEAM_SETTING_NAME))
 		svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM, FALSE);
-	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))
 		svSetValue (ifcfg, "DEVICETYPE", TYPE_TEAM_PORT, FALSE);
 	else
 		svSetValue (ifcfg, "DEVICETYPE", NULL, FALSE);
-- 
2.9.3

From f72c54a2cca791d166a7bc37f2c317b6dd6bc204 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 20 Feb 2017 13:32:39 +0100
Subject: [PATCH] tui: generate names for bonds, teams and bridges

This makes it more likely that the user will end up with a master
connection that has connection.interface-name property. This makes it
possible for ifcfg plugin to specify the master in the for of device
name (as opposed to UUID) for compatibility with the legacy network
tooling.

This is equivalent to what nmcli does.

https://bugzilla.redhat.com/show_bug.cgi?id=1369091
(cherry picked from commit ff46158d9ecd153fa4b0be71f679fa61212715f2)
---
 clients/tui/nm-editor-utils.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/clients/tui/nm-editor-utils.c b/clients/tui/nm-editor-utils.c
index 0ec55f3..d5c2fd5 100644
--- a/clients/tui/nm-editor-utils.c
+++ b/clients/tui/nm-editor-utils.c
@@ -308,6 +308,33 @@ get_available_connection_name (const char *format,
 	return cname;
 }
 
+static char *
+get_available_iface_name (const char *try_name,
+                          NMClient   *client)
+{
+	const GPtrArray *connections;
+	NMConnection *connection;
+	char *new_name;
+	unsigned int num = 1;
+	int i = 0;
+	const char *ifname = NULL;
+
+	connections = nm_client_get_connections (client);
+
+	new_name = g_strdup (try_name);
+	while (i < connections->len) {
+		connection = NM_CONNECTION (connections->pdata[i]);
+		ifname = nm_connection_get_interface_name (connection);
+		if (g_strcmp0 (new_name, ifname) == 0) {
+			g_free (new_name);
+			new_name = g_strdup_printf ("%s%d", try_name, num++);
+			i = 0;
+		} else
+			i++;
+	}
+	return new_name;
+}
+
 /**
  * nm_editor_utils_create_connection:
  * @type: the type of the connection's primary #NMSetting
@@ -335,7 +362,7 @@ nm_editor_utils_create_connection (GType         type,
 	NMConnection *connection;
 	NMSettingConnection *s_con;
 	NMSetting *s_hw, *s_slave;
-	char *uuid, *id;
+	char *uuid, *id, *ifname;
 	int i;
 
 	if (master) {
@@ -368,6 +395,15 @@ nm_editor_utils_create_connection (GType         type,
 	s_hw = g_object_new (type, NULL);
 	nm_connection_add_setting (connection, s_hw);
 
+	if (type == NM_TYPE_SETTING_BOND)
+		ifname = get_available_iface_name ("nm-bond", client);
+	else if (type == NM_TYPE_SETTING_TEAM)
+		ifname = get_available_iface_name ("nm-team", client);
+	else if (type == NM_TYPE_SETTING_BRIDGE)
+		ifname = get_available_iface_name ("nm-bridge", client);
+	else
+		ifname = NULL;
+
 	if (slave_setting_type != G_TYPE_INVALID) {
 		s_slave = g_object_new (slave_setting_type, NULL);
 		nm_connection_add_setting (connection, s_slave);
@@ -383,10 +419,12 @@ nm_editor_utils_create_connection (GType         type,
 	              NM_SETTING_CONNECTION_AUTOCONNECT, !type_data->no_autoconnect,
 	              NM_SETTING_CONNECTION_MASTER, master_uuid,
 	              NM_SETTING_CONNECTION_SLAVE_TYPE, master_setting_type,
+	              NM_SETTING_CONNECTION_INTERFACE_NAME, ifname,
 	              NULL);
 
 	g_free (uuid);
 	g_free (id);
+	g_free (ifname);
 
 	if (type_data->connection_setup_func)
 		type_data->connection_setup_func (connection, s_con, s_hw);
-- 
2.9.3