Ejemplo n.º 1
0
def _vlan_netdev(context, name, inventory_hostname):
    """Return a networkd NetDev configuration for a VLAN interface.

    :param context: a Jinja2 Context object.
    :param name: name of the network.
    :param inventory_hostname: Ansible inventory hostname.
    """
    device = networks.net_interface(context, name, inventory_hostname)
    mtu = networks.net_mtu(context, name, inventory_hostname)
    vlan = networks.net_vlan(context, name, inventory_hostname)
    config = [{
        'NetDev': [
            {
                'Name': device
            },
            {
                'Kind': 'vlan'
            },
            {
                'MTUBytes': mtu
            },
        ],
    }, {
        'VLAN': [
            {
                'Id': vlan
            },
        ]
    }]
    return _filter_options(config)
Ejemplo n.º 2
0
def _bond_member_network(context, name, member, inventory_hostname,
                         vlan_interfaces):
    """Return a networkd network configuration for a bond member.

    :param context: a Jinja2 Context object.
    :param name: name of the network.
    :param member: name of the bond member interface.
    :param inventory_hostname: Ansible inventory hostname.
    :param vlan_interfaces: List of VLAN subinterfaces of the interface.
    """
    bond = networks.get_and_validate_interface(context, name,
                                               inventory_hostname)
    mtu = networks.net_mtu(context, name, inventory_hostname)
    config = [{
        'Match': [
            {
                'Name': member
            },
        ]
    }, {
        'Network': [
            {
                'Bond': bond
            },
        ] + [{
            'VLAN': vlan_interface
        } for vlan_interface in vlan_interfaces]
    }, {
        'Link': [
            {
                'MTUBytes': mtu
            },
        ]
    }]
    return _filter_options(config)
Ejemplo n.º 3
0
def _bridge_port_network(context, name, port, inventory_hostname,
                         vlan_interfaces):
    """Return a networkd network configuration for a bridge port.

    :param context: a Jinja2 Context object.
    :param name: name of the network.
    :param port: name of the bridge port interface.
    :param inventory_hostname: Ansible inventory hostname.
    :param vlan_interfaces: List of VLAN subinterfaces of the interface.
    """
    bridge = networks.get_and_validate_interface(context, name,
                                                 inventory_hostname)
    mtu = networks.net_mtu(context, name, inventory_hostname)
    config = [{
        'Match': [
            {
                'Name': port
            },
        ]
    }, {
        'Network': [
            {
                'Bridge': bridge
            },
        ] + [{
            'VLAN': vlan_interface
        } for vlan_interface in vlan_interfaces]
    }, {
        'Link': [
            {
                'MTUBytes': mtu
            },
        ]
    }]
    return _filter_options(config)
Ejemplo n.º 4
0
def _bond_netdev(context, name, inventory_hostname):
    """Return a networkd NetDev configuration for a bond.

    :param context: a Jinja2 Context object.
    :param name: name of the network.
    :param inventory_hostname: Ansible inventory hostname.
    """
    device = networks.net_interface(context, name, inventory_hostname)
    mtu = networks.net_mtu(context, name, inventory_hostname)
    mode = networks.net_bond_mode(context, name, inventory_hostname)
    ad_select = networks.net_bond_ad_select(context, name, inventory_hostname)
    miimon = networks.net_bond_miimon(context, name, inventory_hostname)
    updelay = networks.net_bond_updelay(context, name, inventory_hostname)
    downdelay = networks.net_bond_downdelay(context, name, inventory_hostname)
    xmit_hash_policy = networks.net_bond_xmit_hash_policy(
        context, name, inventory_hostname)
    lacp_rate = networks.net_bond_lacp_rate(context, name, inventory_hostname)
    config = [{
        'NetDev': [
            {
                'Name': device
            },
            {
                'Kind': 'bond'
            },
            {
                'MTUBytes': mtu
            },
        ]
    }, {
        'Bond': [
            {
                'Mode': mode
            },
            {
                'AdSelect': ad_select
            },
            {
                'TransmitHashPolicy': xmit_hash_policy
            },
            {
                'LACPTransmitRate': lacp_rate
            },
            {
                'MIIMonitorSec': _ms_to_s(miimon)
            },
            {
                'UpDelaySec': _ms_to_s(updelay)
            },
            {
                'DownDelaySec': _ms_to_s(downdelay)
            },
        ]
    }]
    return _filter_options(config)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
def _network(context, name, inventory_hostname, bridge, bond, vlan_interfaces):
    """Return a networkd network for an interface.

    :param context: a Jinja2 Context object.
    :param name: name of the network.
    :param inventory_hostname: Ansible inventory hostname.
    :param bridge: Name of a bridge into which the interface is plugged, or
                   None.
    :param bond: Name of a bond of which the interface is a member, or None.
    :param vlan_interfaces: List of VLAN subinterfaces of the interface.
    """
    # FIXME(mgoddard): Currently does not support: ethtool_opts, zone,
    # allowed_addresses.
    device = networks.net_interface(context, name, inventory_hostname)
    ip = networks.net_ip(context, name, inventory_hostname)
    cidr = networks.net_cidr(context, name, inventory_hostname)
    gateway = networks.net_gateway(context, name, inventory_hostname)
    if ip is None:
        gateway = None
    else:
        if not cidr:
            raise errors.AnsibleFilterError(
                "No CIDR attribute configured for '%s' network but it has an "
                "IP address" % (name))
        ip = "%s/%s" % (ip, ipaddress.ip_network(cidr).prefixlen)

    mtu = networks.net_mtu(context, name, inventory_hostname)
    routes = networks.net_routes(context, name, inventory_hostname)
    rules = networks.net_rules(context, name, inventory_hostname)
    bootproto = networks.net_bootproto(context, name, inventory_hostname)
    defroute = networks.net_defroute(context, name, inventory_hostname)
    if defroute is not None:
        defroute = utils.call_bool_filter(context, defroute)
    config = [
        {
            'Match': [
                {
                    'Name': device
                },
            ]
        },
        {
            'Network': [
                {
                    'Address': ip
                },
                {
                    'Gateway': gateway
                },
                {
                    'DHCP': ('yes' if bootproto and bootproto.lower() == 'dhcp'
                             else None)
                },
                {
                    'UseGateway': ('false' if defroute is not None
                                   and not defroute else None)
                },
                {
                    'Bridge': bridge
                },
                {
                    'Bond': bond
                },
            ] + [{
                'VLAN': vlan_interface
            } for vlan_interface in vlan_interfaces]
        },
        {
            'Link': [
                {
                    'MTUBytes': mtu
                },
            ]
        },
    ]

    # NOTE(mgoddard): Systemd-networkd does not support named route tables
    # until v248. Until then, translate names to numeric IDs using the
    # network_route_tables variable.
    route_tables = utils.get_hostvar(context, "network_route_tables",
                                     inventory_hostname)
    route_tables = {table["name"]: table["id"] for table in route_tables}
    config += _network_routes(routes, route_tables)
    config += _network_rules(rules, route_tables)

    return _filter_options(config)