Run ifup on a bond when a slave interface is restarted

This change adds the bond to the list of interfaces to be
restarted when a slave interface is restarted. On Fedora/CentOS
like systems restart all interface slaves in a bond, the bond
will be left in a downed state. This change runs ifup on the
bond if any slave interfaces are restarted, which insures that
the bond should be up in all cases when os-net-config exits.
Tests were added to ensure that in all cases each interface
or bond will only be restarted once, and that bonds will only
be restarted if the interface modifications require restart.

Change-Id: Ibbe8021afdc4772c6e2017d11d012b8f5c46d907
Closes-bug: 1870608
(cherry picked from commit fe13c4944b)
This commit is contained in:
Dan Sneddon 2020-04-03 23:35:06 -07:00
parent cad5a734ef
commit 8249108167
2 changed files with 45 additions and 2 deletions

View File

@ -1154,6 +1154,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
restart_vlans = [] restart_vlans = []
restart_bridges = [] restart_bridges = []
restart_linux_bonds = [] restart_linux_bonds = []
start_linux_bonds = []
restart_linux_teams = [] restart_linux_teams = []
restart_vpp = False restart_vpp = False
apply_interfaces = [] apply_interfaces = []
@ -1161,6 +1162,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
apply_routes = [] apply_routes = []
update_files = {} update_files = {}
all_file_names = [] all_file_names = []
linux_bond_children = {}
ivs_uplinks = [] # ivs physical uplinks ivs_uplinks = [] # ivs physical uplinks
ivs_interfaces = [] # ivs internal ports ivs_interfaces = [] # ivs internal ports
nfvswitch_interfaces = [] # nfvswitch physical interfaces nfvswitch_interfaces = [] # nfvswitch physical interfaces
@ -1406,11 +1408,12 @@ class IfcfgNetConfig(os_net_config.NetConfig):
all_file_names.append(bond_route_path) all_file_names.append(bond_route_path)
all_file_names.append(bond_route6_path) all_file_names.append(bond_route6_path)
all_file_names.append(bond_rule_path) all_file_names.append(bond_rule_path)
children = self.child_members(bond_name)
linux_bond_children[bond_name] = children
if utils.diff(bond_path, bond_data): if utils.diff(bond_path, bond_data):
if self.ifcfg_requires_restart(bond_path, bond_data): if self.ifcfg_requires_restart(bond_path, bond_data):
restart_linux_bonds.append(bond_name) restart_linux_bonds.append(bond_name)
# Avoid duplicate interface being added to the restart list # Avoid duplicate interface being added to the restart list
children = self.child_members(bond_name)
for child in children: for child in children:
if child not in restart_interfaces: if child not in restart_interfaces:
restart_interfaces.append(child) restart_interfaces.append(child)
@ -1593,6 +1596,10 @@ class IfcfgNetConfig(os_net_config.NetConfig):
for interface in restart_interfaces: for interface in restart_interfaces:
self.ifdown(interface) self.ifdown(interface)
for bond in linux_bond_children:
if interface in linux_bond_children[bond]:
if bond not in restart_linux_bonds:
start_linux_bonds.append(bond)
for linux_bond in restart_linux_bonds: for linux_bond in restart_linux_bonds:
self.ifdown(linux_bond) self.ifdown(linux_bond)
@ -1663,6 +1670,10 @@ class IfcfgNetConfig(os_net_config.NetConfig):
for interface in restart_interfaces: for interface in restart_interfaces:
self.ifup(interface) self.ifup(interface)
for linux_bond in start_linux_bonds:
if linux_bond not in restart_linux_bonds:
restart_linux_bonds.append(linux_bond)
for linux_bond in restart_linux_bonds: for linux_bond in restart_linux_bonds:
self.ifup(linux_bond) self.ifup(linux_bond)

View File

@ -2249,14 +2249,46 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.assertIn('em2', self.ifup_interface_names) self.assertIn('em2', self.ifup_interface_names)
self.assertIn('vlan10', self.ifup_interface_names) self.assertIn('vlan10', self.ifup_interface_names)
def test_linux_bond_ifup_on_child_restart(self):
# if a bond slave is restarted then ifup should be called on the bond
self.ifup_interface_names = []
interface1 = objects.Interface('em1')
bond = objects.LinuxBond('bond0', members=[interface1])
self.provider.add_linux_bond(bond)
self.provider.add_interface(interface1)
self.provider.apply()
self.assertIn('em1', self.ifup_interface_names)
self.assertIn('bond0', self.ifup_interface_names)
self.ifup_interface_names = []
# changing mtu should not require a restart of em1 (or the bond)
interface1.mtu = 9000
self.provider.linuxbond_data = {}
self.provider.interface_data = {}
self.provider.add_linux_bond(bond)
self.provider.add_interface(interface1)
self.provider.apply()
self.assertNotIn('em1', self.ifup_interface_names)
self.assertNotIn('bond0', self.ifup_interface_names)
# changing nm_controlled should require a restart of em1 (and the bond)
interface1.nm_controlled = True
self.provider.add_interface(interface1)
self.provider.apply()
self.assertIn('em1', self.ifup_interface_names)
self.assertIn('bond0', self.ifup_interface_names)
def test_restart_interface_counts(self): def test_restart_interface_counts(self):
interface = objects.Interface('em1') interface = objects.Interface('em1')
self.provider.add_interface(interface)
interface2 = objects.Interface('em2') interface2 = objects.Interface('em2')
bond = objects.LinuxBond('bond0', members=[interface, interface2])
self.provider.add_bond(bond)
self.provider.add_interface(interface)
self.provider.add_interface(interface2) self.provider.add_interface(interface2)
self.provider.apply() self.provider.apply()
self.assertEqual(1, self.ifup_interface_names.count("em1")) self.assertEqual(1, self.ifup_interface_names.count("em1"))
self.assertEqual(1, self.ifup_interface_names.count("em2")) self.assertEqual(1, self.ifup_interface_names.count("em2"))
self.assertEqual(1, self.ifup_interface_names.count("bond0"))
def test_vlan_apply(self): def test_vlan_apply(self):
vlan = objects.Vlan('em1', 5) vlan = objects.Vlan('em1', 5)