diff options
Diffstat (limited to 'os_net_config/impl_ifcfg.py')
-rw-r--r-- | os_net_config/impl_ifcfg.py | 230 |
1 files changed, 204 insertions, 26 deletions
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py index 2e99f98..6459bcc 100644 --- a/os_net_config/impl_ifcfg.py +++ b/os_net_config/impl_ifcfg.py @@ -30,15 +30,23 @@ def ifcfg_config_path(name): return "/etc/sysconfig/network-scripts/ifcfg-%s" % name -#NOTE(dprince): added here for testability +# NOTE(dprince): added here for testability def bridge_config_path(name): return ifcfg_config_path(name) +def ivs_config_path(): + return "/etc/sysconfig/ivs" + + def route_config_path(name): return "/etc/sysconfig/network-scripts/route-%s" % name +def route6_config_path(name): + return "/etc/sysconfig/network-scripts/route6-%s" % name + + def cleanup_pattern(): return "/etc/sysconfig/network-scripts/ifcfg-*" @@ -49,12 +57,14 @@ class IfcfgNetConfig(os_net_config.NetConfig): def __init__(self, noop=False, root_dir=''): 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 = {} self.linuxbridge_data = {} self.linuxbond_data = {} self.member_names = {} - self.bond_slaves = {} self.renamed_interfaces = {} self.bond_primary_ifaces = {} logger.info('Ifcfg net config provider created.') @@ -78,14 +88,27 @@ class IfcfgNetConfig(os_net_config.NetConfig): data += "ONBOOT=yes\n" data += "HOTPLUG=no\n" data += "NM_CONTROLLED=no\n" + if not base_opt.dns_servers and not base_opt.use_dhcp: + data += "PEERDNS=no\n" if isinstance(base_opt, objects.Vlan): if not base_opt.ovs_port: # vlans on OVS bridges are internal ports (no device, etc) data += "VLAN=yes\n" if base_opt.device: data += "PHYSDEV=%s\n" % base_opt.device + else: + if base_opt.linux_bond_name: + data += "PHYSDEV=%s\n" % base_opt.linux_bond_name + elif isinstance(base_opt, objects.IvsInterface): + data += "TYPE=IVSIntPort\n" elif re.match('\w+\.\d+$', base_opt.name): data += "VLAN=yes\n" + if base_opt.linux_bond_name: + data += "MASTER=%s\n" % base_opt.linux_bond_name + data += "SLAVE=yes\n" + if base_opt.ivs_bridge_name: + data += "DEVICETYPE=ivs\n" + data += "IVS_BRIDGE=%s\n" % base_opt.ivs_bridge_name if base_opt.ovs_port: data += "DEVICETYPE=ovs\n" if base_opt.bridge_name: @@ -152,14 +175,9 @@ class IfcfgNetConfig(os_net_config.NetConfig): if base_opt.members: members = [member.name for member in base_opt.members] self.member_names[base_opt.name] = members - for member in members: - self.bond_slaves[member] = base_opt.name if base_opt.bonding_options: data += "BONDING_OPTS=\"%s\"\n" % base_opt.bonding_options else: - if base_opt.name in self.bond_slaves: - data += "MASTER=%s\n" % self.bond_slaves[base_opt.name] - data += "SLAVE=yes\n" if base_opt.use_dhcp: data += "BOOTPROTO=dhcp\n" elif not base_opt.addresses: @@ -211,16 +229,31 @@ class IfcfgNetConfig(os_net_config.NetConfig): logger.info('adding custom route for interface: %s' % interface_name) data = "" first_line = "" + data6 = "" + first_line6 = "" for route in routes: - if route.default: - first_line = "default via %s dev %s\n" % (route.next_hop, - interface_name) + if ":" not in route.next_hop: + # Route is an IPv4 route + if route.default: + first_line = "default via %s dev %s\n" % (route.next_hop, + interface_name) + else: + data += "%s via %s dev %s\n" % (route.ip_netmask, + route.next_hop, + interface_name) else: - data += "%s via %s dev %s\n" % (route.ip_netmask, - route.next_hop, - interface_name) + # Route is an IPv6 route + if route.default: + first_line6 = "default via %s dev %s\n" % (route.next_hop, + interface_name) + else: + data6 += "%s via %s dev %s\n" % (route.ip_netmask, + route.next_hop, + interface_name) self.route_data[interface_name] = first_line + data + self.route6_data[interface_name] = first_line6 + data6 logger.debug('route data: %s' % self.route_data[interface_name]) + logger.debug('ipv6 route data: %s' % self.route6_data[interface_name]) def add_interface(self, interface): """Add an Interface object to the net config object. @@ -247,10 +280,22 @@ 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) + def add_ivs_interface(self, ivs_interface): + """Add a ivs_interface object to the net config object. + + :param ivs_interface: The ivs_interface object to add. + """ + logger.info('adding ivs_interface: %s' % ivs_interface.name) + data = self._add_common(ivs_interface) + logger.debug('ivs_interface data: %s' % data) + self.ivsinterface_data[ivs_interface.name] = data + if ivs_interface.routes: + self._add_routes(ivs_interface.name, ivs_interface.routes) + def add_bridge(self, bridge): """Add an OvsBridge object to the net config object. @@ -275,6 +320,18 @@ class IfcfgNetConfig(os_net_config.NetConfig): if bridge.routes: self._add_routes(bridge.name, bridge.routes) + def add_ivs_bridge(self, bridge): + """Add a IvsBridge object to the net config object. + + IVS can only support one virtual switch per node, + using "ivs" as its name. As long as the ivs service + is running, the ivs virtual switch will be there. + It is impossible to add multiple ivs virtual switches + per node. + :param bridge: The IvsBridge object to add. + """ + pass + def add_bond(self, bond): """Add an OvsBond object to the net config object. @@ -295,11 +352,30 @@ 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) + def generate_ivs_config(self, ivs_uplinks, ivs_interfaces): + """Generate configuration content for ivs.""" + + intfs = [] + for intf in ivs_uplinks: + intfs.append(' -u ') + intfs.append(intf) + uplink_str = ''.join(intfs) + + intfs = [] + for intf in ivs_interfaces: + intfs.append(' --internal-port=') + intfs.append(intf) + intf_str = ''.join(intfs) + + data = ("DAEMON_ARGS=\"--hitless --certificate /etc/ivs " + "--inband-vlan 4092%s%s\"" + % (uplink_str, intf_str)) + return data + def apply(self, cleanup=False, activate=True): """Apply the network configuration. @@ -317,65 +393,137 @@ 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 + ivs_interfaces = [] # ivs internal ports for interface_name, iface_data in self.interface_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) + if "IVS_BRIDGE" in iface_data: + ivs_uplinks.append(interface_name) + all_file_names.append(route6_path) if (utils.diff(interface_path, iface_data) or - utils.diff(route_path, route_data)): + utils.diff(route_path, route_data) or + utils.diff(route6_path, route6_data)): restart_interfaces.append(interface_name) 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 interface: %s' % interface_name) + 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)): + restart_interfaces.append(interface_name) + 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, '') bridge_path = self.root_dir + bridge_config_path(bridge_name) - bridge_route_path = self.root_dir + route_config_path(bridge_name) + br_route_path = self.root_dir + route_config_path(bridge_name) + br_route6_path = self.root_dir + route6_config_path(bridge_name) all_file_names.append(bridge_path) - all_file_names.append(bridge_route_path) + all_file_names.append(br_route_path) + all_file_names.append(br_route6_path) if (utils.diff(bridge_path, bridge_data) or - utils.diff(bridge_route_path, route_data)): + utils.diff(br_route_path, route_data) or + utils.diff(br_route6_path, route6_data)): restart_bridges.append(bridge_name) restart_interfaces.extend(self.child_members(bridge_name)) update_files[bridge_path] = bridge_data - update_files[bridge_route_path] = route_data + update_files[br_route_path] = route_data + update_files[br_route6_path] = route6_data + else: logger.info('No changes required for bridge: %s' % bridge_name) for bridge_name, bridge_data in self.linuxbridge_data.iteritems(): route_data = self.route_data.get(bridge_name, '') + route6_data = self.route6_data.get(bridge_name, '') bridge_path = self.root_dir + bridge_config_path(bridge_name) - bridge_route_path = self.root_dir + route_config_path(bridge_name) + br_route_path = self.root_dir + route_config_path(bridge_name) + br_route6_path = self.root_dir + route6_config_path(bridge_name) all_file_names.append(bridge_path) - all_file_names.append(bridge_route_path) + all_file_names.append(br_route_path) + all_file_names.append(br_route6_path) if (utils.diff(bridge_path, bridge_data) or - utils.diff(bridge_route_path, route_data)): + utils.diff(br_route_path, route_data) or + utils.diff(br_route6_path, route6_data)): restart_bridges.append(bridge_name) restart_interfaces.extend(self.child_members(bridge_name)) update_files[bridge_path] = bridge_data - update_files[bridge_route_path] = route_data + update_files[br_route_path] = route_data + update_files[br_route6_path] = route6_data + else: logger.info('No changes required for bridge: %s' % bridge_name) for bond_name, bond_data in self.linuxbond_data.iteritems(): route_data = self.route_data.get(bond_name, '') + route6_data = self.route6_data.get(bond_name, '') bond_path = self.root_dir + bridge_config_path(bond_name) bond_route_path = self.root_dir + route_config_path(bond_name) + bond_route6_path = self.root_dir + route6_config_path(bond_name) all_file_names.append(bond_path) all_file_names.append(bond_route_path) + all_file_names.append(bond_route6_path) if (utils.diff(bond_path, bond_data) or - utils.diff(bond_route_path, route_data)): - restart_interfaces.append(bond_name) + utils.diff(bond_route_path, route_data) or + utils.diff(bond_route6_path, route6_data)): + 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 + update_files[bond_route6_path] = route6_data + else: logger.info('No changes required for linux bond: %s' % bond_name) @@ -390,9 +538,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') @@ -402,7 +556,15 @@ class IfcfgNetConfig(os_net_config.NetConfig): for location, data in update_files.iteritems(): self.write_config(location, data) + if ivs_uplinks or ivs_interfaces: + location = ivs_config_path() + data = self.generate_ivs_config(ivs_uplinks, ivs_interfaces) + 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') @@ -413,4 +575,20 @@ class IfcfgNetConfig(os_net_config.NetConfig): self.ovs_appctl('bond/set-active-slave', bond, self.bond_primary_ifaces[bond]) + if ivs_uplinks or ivs_interfaces: + logger.info("Attach to ivs with " + "uplinks: %s, " + "interfaces: %s" % + (ivs_uplinks, ivs_interfaces)) + for ivs_uplink in ivs_uplinks: + self.ifup(ivs_uplink) + for ivs_interface in ivs_interfaces: + self.ifup(ivs_interface) + msg = "Restart ivs" + self.execute(msg, '/usr/bin/systemctl', + 'restart', 'ivs') + + for vlan in restart_vlans: + self.ifup(vlan) + return update_files |