def test_get_ovs_veths_bridge_provision_wl(self): # Bridge needs a veth pair. self._update_context({"provision_wl_net_name": "net3"}) veths = networks.get_ovs_veths(self.context, ["net3"], None) expected = [{ "name": "p-br0-phy", "peer": "p-br0-ovs", "bridge": "br0", "mtu": None, }] self.assertEqual(expected, veths)
def test_get_ovs_veths_bridge_vlan(self): # VLAN on a bridge needs a veth pair. self._update_context({"external_net_names": ["net4"]}) veths = networks.get_ovs_veths(self.context, ["net3", "net4"], None) expected = [{ "name": "p-br0-phy", "peer": "p-br0-ovs", "bridge": "br0", "mtu": None, }] self.assertEqual(expected, veths)
def test_get_ovs_veths_bridge_vlan_mtu(self): # Use the MTU of VLAN on a bridge. self._update_context({ "external_net_names": ["net4"], "net4_mtu": 1400 }) veths = networks.get_ovs_veths(self.context, ["net3", "net4"], None) expected = [{ "name": "p-br0-phy", "peer": "p-br0-ovs", "bridge": "br0", "mtu": 1400, }] self.assertEqual(expected, veths)
def networkd_netdevs(context, names, inventory_hostname=None): """Return a dict representation of networkd NetDev configuration. The format is compatible with the systemd_networkd_netdev variable in the stackhpc.ansible_role_systemd_networkd role. :param context: a Jinja2 Context object. :param names: List of names of networks. :param inventory_hostname: Ansible inventory hostname. :returns: a dict representation of networkd NetDev configuration. """ # Prefix for configuration file names. prefix = utils.get_hostvar(context, "networkd_prefix", inventory_hostname) result = {} # VLANs. for name in networks.net_select_vlan_interfaces(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) netdev = _vlan_netdev(context, name, inventory_hostname) _add_to_result(result, prefix, device, netdev) # Bridges. for name in networks.net_select_bridges(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) netdev = _bridge_netdev(context, name, inventory_hostname) _add_to_result(result, prefix, device, netdev) # Bonds. for name in networks.net_select_bonds(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) netdev = _bond_netdev(context, name, inventory_hostname) _add_to_result(result, prefix, device, netdev) # Virtual Ethernet pairs. veths = networks.get_ovs_veths(context, names, inventory_hostname) for veth in veths: netdev = _veth_netdev(context, veth, inventory_hostname) device = veth['name'] _add_to_result(result, prefix, device, netdev) return result
def networkd_networks(context, names, inventory_hostname=None): """Return a dict representation of networkd network configuration. The format is compatible with the systemd_networkd_network variable in the stackhpc.ansible_role_systemd_networkd role. :param context: a Jinja2 Context object. :param names: List of names of networks. :param inventory_hostname: Ansible inventory hostname. :returns: a dict representation of networkd network configuration. """ # TODO(mgoddard): some attributes are currently not supported for # systemd-networkd: rules, route options, ethtool_opts, zone, # allowed addresses # Build up some useful mappings. bridge_port_to_bridge = {} bond_member_to_bond = {} interface_to_vlans = {} # List of all interfaces. interfaces = [ networks.net_interface(context, name, inventory_hostname) for name in names ] # Map bridge ports to bridges. for name in networks.net_select_bridges(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) for port in networks.net_bridge_ports(context, name, inventory_hostname): bridge_port_to_bridge[port] = device # Map bond members to bonds. for name in networks.net_select_bonds(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) for member in networks.net_bond_slaves(context, name, inventory_hostname): bond_member_to_bond[member] = device # Map interfaces to lists of VLAN subinterfaces. for name in networks.net_select_vlans(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) vlan = networks.net_vlan(context, name, inventory_hostname) mtu = networks.net_mtu(context, name, inventory_hostname) parent = networks.get_vlan_parent(device, vlan) vlan_interfaces = interface_to_vlans.setdefault(parent, []) vlan_interfaces.append({"device": device, "mtu": mtu}) # Prefix for configuration file names. prefix = utils.get_hostvar(context, "networkd_prefix", inventory_hostname) result = {} # Configured networks. for name in names: device = networks.get_and_validate_interface(context, name, inventory_hostname) bridge = bridge_port_to_bridge.get(device) bond = bond_member_to_bond.get(device) vlan_interfaces = interface_to_vlans.get(device, []) net = _network(context, name, inventory_hostname, bridge, bond, [vlan["device"] for vlan in vlan_interfaces]) _add_to_result(result, prefix, device, net) # VLAN parent interfaces that are not in configured networks, bridge ports # or bond members. implied_vlan_parents = (set(interface_to_vlans) - set(interfaces) - set(bridge_port_to_bridge) - set(bond_member_to_bond)) for device in implied_vlan_parents: vlan_interfaces = interface_to_vlans[device] mtu = max([vlan["mtu"] for vlan in vlan_interfaces]) net = _vlan_parent_network( device, mtu, [vlan["device"] for vlan in vlan_interfaces]) _add_to_result(result, prefix, device, net) # Bridge ports that are not in configured networks. for name in networks.net_select_bridges(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) bridge_ports = networks.net_bridge_ports(context, name, inventory_hostname) for port in set(bridge_ports) - set(interfaces): vlan_interfaces = interface_to_vlans.get(port, []) net = _bridge_port_network( context, name, port, inventory_hostname, [vlan["device"] for vlan in vlan_interfaces]) _add_to_result(result, prefix, port, net) # Bond members that are not in configured networks. for name in networks.net_select_bonds(context, names, inventory_hostname): device = networks.get_and_validate_interface(context, name, inventory_hostname) bond_members = networks.net_bond_slaves(context, name, inventory_hostname) for member in set(bond_members) - set(interfaces): vlan_interfaces = interface_to_vlans.get(member, []) net = _bond_member_network( context, name, member, inventory_hostname, [vlan["device"] for vlan in vlan_interfaces]) _add_to_result(result, prefix, member, net) # Virtual Ethernet pairs for Open vSwitch. veths = networks.get_ovs_veths(context, names, inventory_hostname) for veth in veths: net = _veth_network(context, veth, inventory_hostname) device = veth['name'] _add_to_result(result, prefix, device, net) net = _veth_peer_network(context, veth, inventory_hostname) device = veth['peer'] _add_to_result(result, prefix, device, net) return result
def test_get_ovs_veths_eth_vlan(self): # VLAN on Ethernet does not need a veth pair. self._update_context({"external_net_names": ["net2"]}) veths = networks.get_ovs_veths(self.context, ["net2"], None) self.assertEqual([], veths)
def test_get_ovs_veths_empty(self): veths = networks.get_ovs_veths(self.context, [], None) self.assertEqual([], veths)