Marcin Mirecki has uploaded a new change for review.

Change subject: supervdsm: moving nics between bonds
......................................................................

supervdsm: moving nics between bonds

This patch fixes an problem where a slave removed from
one bond could sometimes not be assigned to another
bond in the same request.
This happened because removing, editing and adding of
slaves to a bond was done bond by bond, so if a nic
was added to a bond which was handled before the bond
from which the nic was removed the operation failed.
Example:
bond0: nic0, nic1   => nic2, nic3
bond1: nic2, nic3   => nic0, nic1
In this situation first bond0 is processed: nic0 and
nic1 will be removed, but nic2 and nic3 can not yet
be removed as they are part of bond1 (validation fails).
Processing of bond1 will introduce errors, as nic2 and
nic3 will be removed (already assigned to bond0),
which will in effect reset their ifcfg files, and cause
the previous attachement to bond0 to be undone.

The patch changes the validation to check if a slave
added to a bond is deleted from another bond.
Also the removing of slaves from all bonds is done
before any other bond operation.

Bug-Url: https://bugzilla.redhat.com/1269175
Change-Id: Ia43fbfe90d1335ed4a740a1bc4f09610da2ecdce
Signed-off-by: Marcin Mirecki <mmire...@redhat.com>
---
M lib/vdsm/network/api.py
M lib/vdsm/network/configurators/ifcfg.py
M lib/vdsm/network/models.py
3 files changed, 43 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/96/50596/1

diff --git a/lib/vdsm/network/api.py b/lib/vdsm/network/api.py
index c3d82d4..d70b39f 100755
--- a/lib/vdsm/network/api.py
+++ b/lib/vdsm/network/api.py
@@ -680,10 +680,14 @@
         else:
             addition.append((name, attrs))
 
+    _handle_removed_slaves(edition, _netinfo, configurator, bondings)
+
     for name, attrs in edition:
         bond = Bond.objectivize(name, configurator, attrs.get('options'),
-                                attrs.get('nics'), mtu=None, _netinfo=_netinfo,
-                                destroyOnMasterRemoval='remove' in attrs)
+                                attrs.get('nics'), mtu=None,
+                                _netinfo=_netinfo,
+                                destroyOnMasterRemoval='remove' in attrs,
+                                modified_bondings=bondings)
         if len(bond.slaves) == 0:
             raise ConfigNetworkError(ne.ERR_BAD_PARAMS, 'Missing required nics'
                                      ' for bonding device.')
@@ -700,6 +704,16 @@
         configurator.configureBond(bond)
 
 
+def _handle_removed_slaves(edited_bonds, _netinfo, configurator,
+                           modified_bondings):
+    for name, attrs in edited_bonds:
+        removed_slaves = []
+        for slave_name in _netinfo.bondings[name]['slaves']:
+            if slave_name not in attrs.get('nics'):
+                removed_slaves.append(slave_name)
+        configurator.remove_slaves(removed_slaves, _netinfo)
+
+
 def _buildBondOptions(bondName, bondings, _netinfo):
     logger = logging.getLogger("_buildBondOptions")
 
diff --git a/lib/vdsm/network/configurators/ifcfg.py 
b/lib/vdsm/network/configurators/ifcfg.py
index f169400..6d49c61 100644
--- a/lib/vdsm/network/configurators/ifcfg.py
+++ b/lib/vdsm/network/configurators/ifcfg.py
@@ -126,6 +126,11 @@
                 bond.name, {'options': bond.options,
                             'nics': [slave.name for slave in bond.slaves]})
 
+    def remove_slaves(self, removed_slaves, _netinfo):
+        for nic in removed_slaves:
+            ifdown(nic)  # So that no users will be detected for it.
+            Nic(nic, self, _netinfo=_netinfo).remove()
+
     def editBonding(self, bond, _netinfo):
         """
         Modifies the bond so that the bond in the system ends up with the
@@ -148,10 +153,6 @@
                 bond.master = Bridge(bridgeName, self, port=bond)
             self.configApplier.addBonding(bond)
             bondIfcfgWritten = True
-
-        for nic in currentNics - nicsToSet:
-            ifdown(nic)  # So that no users will be detected for it.
-            Nic(nic, self, _netinfo=_netinfo).remove()
 
         for slave in bond.slaves:
             if slave.name in nicsToAdd:
diff --git a/lib/vdsm/network/models.py b/lib/vdsm/network/models.py
index a5609fd..9305a4d 100644
--- a/lib/vdsm/network/models.py
+++ b/lib/vdsm/network/models.py
@@ -257,13 +257,31 @@
         self.configurator.removeBond(self)
 
     @classmethod
-    def _objectivizeSlaves(cls, name, configurator, nics, mtu, _netinfo):
+    def is_slave_used(cls, new_bond_name, existing_bond_name, slave_name,
+                      modified_bondings):
+        if not existing_bond_name or new_bond_name == existing_bond_name:
+            return False
+        if not modified_bondings:
+            return False
+        if existing_bond_name in modified_bondings:
+            bond = modified_bondings[existing_bond_name]
+            if 'remove' in bond and bond['remove'] == 'true':
+                    return False
+            if 'nics' in bond and slave_name not in bond['nics']:
+                    return False
+        return True
+
+    @classmethod
+    def _objectivizeSlaves(cls, name, configurator, nics, mtu, _netinfo,
+                           modified_bondings):
         slaves = []
         for nic in nics:
             nicVlans = tuple(_netinfo.getVlansForIface(nic))
             nicNet = _netinfo.getNetworkForIface(nic)
             nicBond = _netinfo.getBondingForNic(nic)
-            if nicVlans or nicNet or nicBond and nicBond != name:
+            is_slave_in_bond = cls.is_slave_used(name, nicBond, nic,
+                                                 modified_bondings)
+            if nicVlans or nicNet or is_slave_in_bond:
                 raise ConfigNetworkError(
                     ne.ERR_USED_NIC, 'nic %s already used by %s' %
                     (nic, nicVlans or nicNet or nicBond))
@@ -273,11 +291,11 @@
 
     @classmethod
     def objectivize(cls, name, configurator, options, nics, mtu, _netinfo,
-                    destroyOnMasterRemoval=None):
+                    destroyOnMasterRemoval=None, modified_bondings=None):
 
         if nics:  # New bonding or edit bonding.
             slaves = cls._objectivizeSlaves(name, configurator, _nicSort(nics),
-                                            mtu, _netinfo)
+                                            mtu, _netinfo, modified_bondings)
             if name in _netinfo.bondings:
                 if _netinfo.ifaceUsers(name):
                     mtu = max(mtu, mtus.getMtu(name))


-- 
To view, visit https://gerrit.ovirt.org/50596
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia43fbfe90d1335ed4a740a1bc4f09610da2ecdce
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Marcin Mirecki <mmire...@redhat.com>
_______________________________________________
vdsm-patches mailing list
vdsm-patches@lists.fedorahosted.org
https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches

Reply via email to