Blob Blame History Raw
From b78579503ac16b9f7c71a023532fcb5f1586bc1d Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Mon, 9 Mar 2020 22:16:18 +0800
Subject: [PATCH] nm applier: only create ethernet when explicitly

Creating ethernet configuration when user not requested will
cause two major problems:
    * Adding slave to newly create bridge will cause bridge link down.
    * Cannot switch bond mode from 1(active-backup) to 5(balance-tlb).

To fix the problem, only create ethernet/wired setting when user
explicitly requested.

Remove the xfail of test case for changing bond mode from 1(active-backup)
to 5(balance-tlb).

Remove the workaround in test case for adding slave to newly created
bridge without link state down.

Add test case showing old ethernet configuration will not be removed when
desire state does not include so.

Signed-off-by: Gris Ge <fge@redhat.com>
---
 libnmstate/netapplier.py |  8 +++++---
 libnmstate/nm/applier.py | 31 ++++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/libnmstate/netapplier.py b/libnmstate/netapplier.py
index cc6b6e3..d9d10cf 100644
--- a/libnmstate/netapplier.py
+++ b/libnmstate/netapplier.py
@@ -152,7 +152,9 @@ def _apply_ifaces_state(
                 state2edit = _create_editable_desired_state(
                     desired_state, current_state, new_interfaces
                 )
-                ifaces2edit, ifaces_edit_configs = _edit_interfaces(state2edit)
+                ifaces2edit, ifaces_edit_configs = _edit_interfaces(
+                    state2edit, original_desired_state
+                )
                 nm.applier.set_ifaces_admin_state(
                     ifaces2add + ifaces2edit,
                     con_profiles=ifaces_add_configs + ifaces_edit_configs,
@@ -231,7 +233,7 @@ def _add_interfaces(new_interfaces, desired_state):
     return (ifaces2add, ifaces_configs)
 
 
-def _edit_interfaces(state2edit):
+def _edit_interfaces(state2edit, original_desired_state):
     logging.debug("Editing interfaces: %s", list(state2edit.interfaces))
 
     ifaces2edit = list(state2edit.interfaces.values())
@@ -244,7 +246,7 @@ def _edit_interfaces(state2edit):
     )
     proxy_ifaces = nm.applier.prepare_proxy_ifaces_desired_state(iface2prepare)
     ifaces_configs = nm.applier.prepare_edited_ifaces_configuration(
-        iface2prepare + proxy_ifaces
+        iface2prepare + proxy_ifaces, original_desired_state
     )
     nm.applier.edit_existing_ifaces(ifaces_configs)
 
diff --git a/libnmstate/nm/applier.py b/libnmstate/nm/applier.py
index 77e869e..8d31e35 100644
--- a/libnmstate/nm/applier.py
+++ b/libnmstate/nm/applier.py
@@ -69,7 +69,10 @@ def prepare_new_ifaces_configuration(ifaces_desired_state):
         )
 
     return [
-        _build_connection_profile(iface_desired_state)
+        _build_connection_profile(
+            iface_desired_state,
+            original_desired_iface_state=iface_desired_state,
+        )
         for iface_desired_state in ifaces_desired_state
     ]
 
@@ -89,7 +92,9 @@ def edit_existing_ifaces(con_profiles):
             connection_profile.add(save_to_disk=True)
 
 
-def prepare_edited_ifaces_configuration(ifaces_desired_state):
+def prepare_edited_ifaces_configuration(
+    ifaces_desired_state, original_desired_state
+):
     con_profiles = []
 
     for iface_desired_state in ifaces_desired_state:
@@ -101,8 +106,13 @@ def prepare_edited_ifaces_configuration(ifaces_desired_state):
         if nmdev:
             cur_con_profile = connection.ConnectionProfile()
             cur_con_profile.import_by_device(nmdev)
+        original_desired_iface_state = original_desired_state.interfaces.get(
+            ifname, {}
+        )
         new_con_profile = _build_connection_profile(
-            iface_desired_state, base_con_profile=cur_con_profile
+            iface_desired_state,
+            base_con_profile=cur_con_profile,
+            original_desired_iface_state=original_desired_iface_state,
         )
         if not new_con_profile.devname:
             set_conn = new_con_profile.profile.get_setting_connection()
@@ -366,7 +376,14 @@ def _generate_hash_iface_name(name):
     return name_[:MAXIMUM_INTERFACE_LENGTH].decode()
 
 
-def _build_connection_profile(iface_desired_state, base_con_profile=None):
+def _build_connection_profile(
+    iface_desired_state,
+    base_con_profile=None,
+    original_desired_iface_state=None,
+):
+    if original_desired_iface_state is None:
+        original_desired_iface_state = {}
+
     iface_type = translator.Api2Nm.get_iface_type(
         iface_desired_state[Interface.TYPE]
     )
@@ -401,7 +418,11 @@ def _build_connection_profile(iface_desired_state, base_con_profile=None):
     con_setting.set_master(master, master_type)
     settings.append(con_setting.setting)
 
-    wired_setting = wired.create_setting(iface_desired_state, base_profile)
+    # Only apply wired/ethernet configuration based on original desire
+    # state rather than the merged one.
+    wired_setting = wired.create_setting(
+        original_desired_iface_state, base_profile
+    )
     if wired_setting:
         settings.append(wired_setting)
 
-- 
2.18.2