diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index b2099f55..3bfbdce0 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -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: diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py index 08fdb5f6..8fa0a456 100644 --- a/os_net_config/tests/test_impl_ifcfg.py +++ b/os_net_config/tests/test_impl_ifcfg.py @@ -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)