Fix order-of-operations bug in os-net-config restart_interfaces
The current order of operations of bringing up interfaces starts with the bridges, and restarts the members of the bridges. This works well when an OVS bond is part of an OVS bridge, but does not work well when Linux bonding is used with no bridges (such as in the case of the Nuage plugin, which creates the bridges outside of the ifcfg files). This change will ensure that Linux bonds are brought up first, then any bridges are brought up, interfaces are brought up next, and the VLAN interfacs are brought up last. This corrects a race condition where any VLAN which was brought up before the bond would not be active, and the VLAN would have to be brought up by hand. This change also fixes a logging issue where os-net-config would report that no changes were necessary when changes were made. Now, the logging messages indicating that "No changes were necessary" show up when no changes are required, instead of when changes are actually made. Change-Id: I1efee3dfd8e8cef01b054bb57a3085cc7eb60372
This commit is contained in:
parent
ef02752ebf
commit
bfc72bd5ce
@ -58,6 +58,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
super(IfcfgNetConfig, self).__init__(noop, root_dir)
|
||||
self.interface_data = {}
|
||||
self.ivsinterface_data = {}
|
||||
self.vlan_data = {}
|
||||
self.route_data = {}
|
||||
self.route6_data = {}
|
||||
self.bridge_data = {}
|
||||
@ -281,7 +282,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
logger.info('adding vlan: %s' % vlan.name)
|
||||
data = self._add_common(vlan)
|
||||
logger.debug('vlan data: %s' % data)
|
||||
self.interface_data[vlan.name] = data
|
||||
self.vlan_data[vlan.name] = data
|
||||
if vlan.routes:
|
||||
self._add_routes(vlan.name, vlan.routes)
|
||||
|
||||
@ -353,7 +354,6 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
logger.info('adding linux bond: %s' % bond.name)
|
||||
data = self._add_common(bond)
|
||||
logger.debug('bond data: %s' % data)
|
||||
self.interface_data[bond.name] = data
|
||||
self.linuxbond_data[bond.name] = data
|
||||
if bond.routes:
|
||||
self._add_routes(bond.name, bond.routes)
|
||||
@ -395,7 +395,9 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
"""
|
||||
logger.info('applying network configs...')
|
||||
restart_interfaces = []
|
||||
restart_vlans = []
|
||||
restart_bridges = []
|
||||
restart_linux_bonds = []
|
||||
update_files = {}
|
||||
all_file_names = []
|
||||
ivs_uplinks = [] # ivs physical uplinks
|
||||
@ -409,6 +411,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
route6_path = self.root_dir + route6_config_path(interface_name)
|
||||
all_file_names.append(interface_path)
|
||||
all_file_names.append(route_path)
|
||||
all_file_names.append(route6_path)
|
||||
if "IVS_BRIDGE" in iface_data:
|
||||
ivs_uplinks.append(interface_name)
|
||||
all_file_names.append(route6_path)
|
||||
@ -426,10 +429,13 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
|
||||
for interface_name, iface_data in self.ivsinterface_data.iteritems():
|
||||
route_data = self.route_data.get(interface_name, '')
|
||||
route6_data = self.route6_data.get(interface_name, '')
|
||||
interface_path = self.root_dir + ifcfg_config_path(interface_name)
|
||||
route_path = self.root_dir + route_config_path(interface_name)
|
||||
route6_path = self.root_dir + route6_config_path(interface_name)
|
||||
all_file_names.append(interface_path)
|
||||
all_file_names.append(route_path)
|
||||
all_file_names.append(route6_path)
|
||||
ivs_interfaces.append(interface_name)
|
||||
if (utils.diff(interface_path, iface_data) or
|
||||
utils.diff(route_path, route_data)):
|
||||
@ -437,9 +443,31 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
restart_interfaces.extend(self.child_members(interface_name))
|
||||
update_files[interface_path] = iface_data
|
||||
update_files[route_path] = route_data
|
||||
update_files[route6_path] = route6_data
|
||||
else:
|
||||
logger.info('No changes required for ivs interface: %s' %
|
||||
interface_name)
|
||||
|
||||
for vlan_name, vlan_data in self.vlan_data.iteritems():
|
||||
route_data = self.route_data.get(vlan_name, '')
|
||||
route6_data = self.route6_data.get(vlan_name, '')
|
||||
vlan_path = self.root_dir + ifcfg_config_path(vlan_name)
|
||||
vlan_route_path = self.root_dir + route_config_path(vlan_name)
|
||||
vlan_route6_path = self.root_dir + route6_config_path(vlan_name)
|
||||
all_file_names.append(vlan_path)
|
||||
all_file_names.append(vlan_route_path)
|
||||
all_file_names.append(vlan_route6_path)
|
||||
if (utils.diff(vlan_path, vlan_data) or
|
||||
utils.diff(vlan_route_path, route_data)):
|
||||
restart_vlans.append(vlan_name)
|
||||
restart_vlans.extend(self.child_members(vlan_name))
|
||||
update_files[vlan_path] = vlan_data
|
||||
update_files[vlan_route_path] = route_data
|
||||
update_files[vlan_route6_path] = route6_data
|
||||
else:
|
||||
logger.info('No changes required for vlan interface: %s' %
|
||||
vlan_name)
|
||||
|
||||
for bridge_name, bridge_data in self.bridge_data.iteritems():
|
||||
route_data = self.route_data.get(bridge_name, '')
|
||||
route6_data = self.route6_data.get(bridge_name, '')
|
||||
@ -492,7 +520,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
if (utils.diff(bond_path, bond_data) or
|
||||
utils.diff(bond_route_path, route_data) or
|
||||
utils.diff(bond_route6_path, route6_data)):
|
||||
restart_interfaces.append(bond_name)
|
||||
restart_linux_bonds.append(bond_name)
|
||||
restart_interfaces.extend(self.child_members(bond_name))
|
||||
update_files[bond_path] = bond_data
|
||||
update_files[bond_route_path] = route_data
|
||||
@ -512,9 +540,15 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
self.remove_config(ifcfg_file)
|
||||
|
||||
if activate:
|
||||
for vlan in restart_vlans:
|
||||
self.ifdown(vlan)
|
||||
|
||||
for interface in restart_interfaces:
|
||||
self.ifdown(interface)
|
||||
|
||||
for linux_bond in restart_linux_bonds:
|
||||
self.ifdown(linux_bond)
|
||||
|
||||
for bridge in restart_bridges:
|
||||
self.ifdown(bridge, iftype='bridge')
|
||||
|
||||
@ -530,6 +564,9 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
self.write_config(location, data)
|
||||
|
||||
if activate:
|
||||
for linux_bond in restart_linux_bonds:
|
||||
self.ifup(linux_bond)
|
||||
|
||||
for bridge in restart_bridges:
|
||||
self.ifup(bridge, iftype='bridge')
|
||||
|
||||
@ -553,4 +590,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
||||
self.execute(msg, '/usr/bin/systemctl',
|
||||
'restart', 'ivs')
|
||||
|
||||
for vlan in restart_vlans:
|
||||
self.ifup(vlan)
|
||||
|
||||
return update_files
|
||||
|
@ -179,11 +179,11 @@ BOOTPROTO=none
|
||||
"""
|
||||
|
||||
_VLAN_LINUX_BRIDGE = _BASE_VLAN_OVS + """VLAN=yes
|
||||
PHYSDEV=em1
|
||||
BRIDGE=br-ctlplane
|
||||
BOOTPROTO=none
|
||||
"""
|
||||
|
||||
|
||||
_OVS_BOND_DHCP = """# This file is autogenerated by os-net-config
|
||||
DEVICE=bond0
|
||||
ONBOOT=yes
|
||||
@ -246,6 +246,12 @@ class TestIfcfgNetConfig(base.TestCase):
|
||||
def get_interface_config(self, name='em1'):
|
||||
return self.provider.interface_data[name]
|
||||
|
||||
def get_vlan_config(self, name='vlan1'):
|
||||
return self.provider.vlan_data[name]
|
||||
|
||||
def get_linux_bond_config(self, name='bond0'):
|
||||
return self.provider.linuxbond_data[name]
|
||||
|
||||
def get_route_config(self, name='em1'):
|
||||
return self.provider.route_data.get(name, '')
|
||||
|
||||
@ -430,19 +436,19 @@ class TestIfcfgNetConfig(base.TestCase):
|
||||
def test_add_vlan(self):
|
||||
vlan = objects.Vlan('em1', 5)
|
||||
self.provider.add_vlan(vlan)
|
||||
self.assertEqual(_VLAN_NO_IP, self.get_interface_config('vlan5'))
|
||||
self.assertEqual(_VLAN_NO_IP, self.get_vlan_config('vlan5'))
|
||||
|
||||
def test_add_vlan_ovs(self):
|
||||
vlan = objects.Vlan('em1', 5)
|
||||
vlan.ovs_port = True
|
||||
self.provider.add_vlan(vlan)
|
||||
self.assertEqual(_VLAN_OVS, self.get_interface_config('vlan5'))
|
||||
self.assertEqual(_VLAN_OVS, self.get_vlan_config('vlan5'))
|
||||
|
||||
def test_add_vlan_mtu_1500(self):
|
||||
vlan = objects.Vlan('em1', 5, mtu=1500)
|
||||
self.provider.add_vlan(vlan)
|
||||
expected = _VLAN_NO_IP + 'MTU=1500\n'
|
||||
self.assertEqual(expected, self.get_interface_config('vlan5'))
|
||||
self.assertEqual(expected, self.get_vlan_config('vlan5'))
|
||||
|
||||
def test_add_ovs_bridge_with_vlan(self):
|
||||
vlan = objects.Vlan('em1', 5)
|
||||
@ -450,16 +456,15 @@ class TestIfcfgNetConfig(base.TestCase):
|
||||
members=[vlan])
|
||||
self.provider.add_vlan(vlan)
|
||||
self.provider.add_bridge(bridge)
|
||||
self.assertEqual(_VLAN_OVS_BRIDGE, self.get_interface_config('vlan5'))
|
||||
self.assertEqual(_VLAN_OVS_BRIDGE, self.get_vlan_config('vlan5'))
|
||||
|
||||
def test_add_linux_bridge_with_vlan(self):
|
||||
vlan = objects.Vlan(None, 5)
|
||||
vlan = objects.Vlan('em1', 5)
|
||||
bridge = objects.LinuxBridge('br-ctlplane', use_dhcp=True,
|
||||
members=[vlan])
|
||||
self.provider.add_vlan(vlan)
|
||||
self.provider.add_bridge(bridge)
|
||||
self.assertEqual(_VLAN_LINUX_BRIDGE,
|
||||
self.get_interface_config('vlan5'))
|
||||
self.assertEqual(_VLAN_LINUX_BRIDGE, self.get_vlan_config('vlan5'))
|
||||
|
||||
def test_ovs_bond(self):
|
||||
interface1 = objects.Interface('em1')
|
||||
@ -489,7 +494,7 @@ BOOTPROTO=none
|
||||
members=[interface1, interface2])
|
||||
self.provider.add_linux_bond(bond)
|
||||
self.assertEqual(_LINUX_BOND_DHCP,
|
||||
self.get_interface_config('bond0'))
|
||||
self.get_linux_bond_config('bond0'))
|
||||
|
||||
def test_interface_defroute(self):
|
||||
interface1 = objects.Interface('em1')
|
||||
|
Loading…
x
Reference in New Issue
Block a user