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
This commit is contained in:
Lubomir Rintel 2016-11-28 12:32:03 +00:00
parent 96988f8deb
commit 8b7b0d3fc2
5 changed files with 82 additions and 26 deletions

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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"
@ -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");