Fix - restart VLAN interface on underlying device change
When a change is needed on bond, os-net-config write the
configuration and restart nic and bond. But it does not
restart vlan on top of the bond. The results is that all
routes for vlan interfaces are lost.
This moves the processing of VLAN's so that it run's
after any interfaces, bridges, bonds etc. Then
concatenates the restart lists from other interfaces and
do a check if 'PHYSDEV' of a VLAN interface is being
restarted.
Closes-Bug: #1806027
Related: RHBZ#1654987
Change-Id: I246da54cf02d06466f52d210f89d82ca9e2a6ef2
(cherry picked from commit 19067b4e77
)
This commit is contained in:
parent
6429384f23
commit
0743c2c803
|
@ -15,6 +15,7 @@
|
|||
# under the License.
|
||||
|
||||
import glob
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
@ -121,6 +122,18 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
|||
self.bond_primary_ifaces = {}
|
||||
logger.info('Ifcfg net config provider created.')
|
||||
|
||||
def parse_ifcfg(self, ifcfg_data):
|
||||
"""Break out the key/value pairs from ifcfg_data
|
||||
|
||||
Return the keys and values without quotes.
|
||||
"""
|
||||
ifcfg_values = {}
|
||||
for line in ifcfg_data.split("\n"):
|
||||
if not line.startswith("#") and line.find("=") > 0:
|
||||
k, v = line.split("=", 1)
|
||||
ifcfg_values[k] = v.strip("\"'")
|
||||
return ifcfg_values
|
||||
|
||||
def child_members(self, name):
|
||||
children = set()
|
||||
try:
|
||||
|
@ -792,26 +805,6 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
|||
logger.info('No changes required for nfvswitch interface: %s' %
|
||||
iface_name)
|
||||
|
||||
for vlan_name, vlan_data in self.vlan_data.items():
|
||||
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.items():
|
||||
route_data = self.route_data.get(bridge_name, '')
|
||||
route6_data = self.route6_data.get(bridge_name, '')
|
||||
|
@ -924,6 +917,40 @@ class IfcfgNetConfig(os_net_config.NetConfig):
|
|||
logger.info('No changes required for InfiniBand iface: %s' %
|
||||
interface_name)
|
||||
|
||||
# NOTE(hjensas): Process the VLAN's last so that we know if the vlan's
|
||||
# parent interface is being restarted.
|
||||
for vlan_name, vlan_data in self.vlan_data.items():
|
||||
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)
|
||||
restarts_concatenated = itertools.chain(restart_interfaces,
|
||||
restart_bridges,
|
||||
restart_linux_bonds,
|
||||
restart_linux_teams)
|
||||
if (self.parse_ifcfg(vlan_data).get('PHYSDEV') in
|
||||
restarts_concatenated):
|
||||
if vlan_name not in restart_vlans:
|
||||
restart_vlans.append(vlan_name)
|
||||
update_files[vlan_path] = vlan_data
|
||||
update_files[vlan_path] = vlan_data
|
||||
update_files[vlan_route_path] = route_data
|
||||
update_files[vlan_route6_path] = route6_data
|
||||
elif (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)
|
||||
|
||||
if cleanup:
|
||||
for ifcfg_file in glob.iglob(cleanup_pattern()):
|
||||
if ifcfg_file not in all_file_names:
|
||||
|
|
|
@ -1184,6 +1184,32 @@ class TestIfcfgNetConfigApply(base.TestCase):
|
|||
self.assertIn('em1', self.ifup_interface_names)
|
||||
self.assertIn('em2', self.ifup_interface_names)
|
||||
|
||||
def test_restart_vlans_on_bond_change(self):
|
||||
self.ifup_interface_names = []
|
||||
interface1 = objects.Interface('em1')
|
||||
interface2 = objects.Interface('em2')
|
||||
bond = objects.LinuxBond('bond0', members=[interface1, interface2])
|
||||
vlan = objects.Vlan('bond0', 10)
|
||||
self.provider.add_interface(interface1)
|
||||
self.provider.add_interface(interface2)
|
||||
self.provider.add_linux_bond(bond)
|
||||
self.provider.add_vlan(vlan)
|
||||
self.provider.apply()
|
||||
self.assertIn('bond0', self.ifup_interface_names)
|
||||
self.assertIn('em1', self.ifup_interface_names)
|
||||
self.assertIn('em2', self.ifup_interface_names)
|
||||
self.assertIn('vlan10', self.ifup_interface_names)
|
||||
|
||||
# Change the bond configuration
|
||||
self.ifup_interface_names = []
|
||||
bond.bonding_options = 'mode=1 miimon=100'
|
||||
self.provider.add_linux_bond(bond)
|
||||
self.provider.apply()
|
||||
self.assertIn('bond0', self.ifup_interface_names)
|
||||
self.assertIn('em1', self.ifup_interface_names)
|
||||
self.assertIn('em2', self.ifup_interface_names)
|
||||
self.assertIn('vlan10', self.ifup_interface_names)
|
||||
|
||||
def test_restart_interface_counts(self):
|
||||
interface = objects.Interface('em1')
|
||||
self.provider.add_interface(interface)
|
||||
|
|
Loading…
Reference in New Issue