diff --git a/bundles/systemd-networkd/items.py b/bundles/systemd-networkd/items.py index 364810f..47d421d 100644 --- a/bundles/systemd-networkd/items.py +++ b/bundles/systemd-networkd/items.py @@ -32,6 +32,21 @@ for interface, config in node.metadata['interfaces'].items(): }, } +for type, path in { + 'networks': '/etc/systemd/network/{}.network', + 'netdevs': '/etc/systemd/network/{}.netdev', +}.items(): + for name, config in node.metadata.get(f'systemd-networkd/{type}').items(): + files[path.format(name)] = { + 'content': repo.libs.systemd.generate_unitfile(config), + 'needed_by': { + 'svc_systemd:systemd-networkd', + }, + 'triggers': { + 'svc_systemd:systemd-networkd:restart', + }, + } + svc_systemd = { 'systemd-networkd': {}, } diff --git a/bundles/systemd-networkd/metadata.py b/bundles/systemd-networkd/metadata.py index e8dff0e..e3a857b 100644 --- a/bundles/systemd-networkd/metadata.py +++ b/bundles/systemd-networkd/metadata.py @@ -6,24 +6,8 @@ defaults = { }, }, }, + 'systemd-networkd': { + 'netdevs': {}, + 'networks': {}, + }, } - - -@metadata_reactor.provides( - 'interfaces', -) -def add_vlan_infos_to_interface(metadata): - interfaces = {} - - for iface in metadata.get('interfaces', {}): - if not '.' in iface: - continue - - interface,vlan = iface.split('.') - - interfaces.setdefault(interface, {}).setdefault('vlans', set()) - interfaces[interface]['vlans'].add(vlan) - - return { - 'interfaces': interfaces, - } diff --git a/bundles/wireguard/files/wg0.netdev b/bundles/wireguard/files/wg0.netdev deleted file mode 100644 index f6f2fc3..0000000 --- a/bundles/wireguard/files/wg0.netdev +++ /dev/null @@ -1,26 +0,0 @@ -[NetDev] -Name=wg0 -Kind=wireguard -Description=WireGuard server - -[WireGuard] -PrivateKey=${privatekey} -ListenPort=51820 - -% for peer, config in sorted(peers.items()): -# Peer ${peer} -[WireGuardPeer] -PublicKey=${config['pubkey']} -AllowedIPs=0.0.0.0/0 -% if len(peers) == 1: # FIXME -#AllowedIPs=${network} -% else: -#AllowedIPs=${','.join(sorted(config['ips']))} -% endif -PresharedKey=${config['psk']} -% if 'endpoint' in config: -Endpoint=${config['endpoint']} -% endif -PersistentKeepalive=30 - -% endfor diff --git a/bundles/wireguard/items.py b/bundles/wireguard/items.py index d24ff09..609bddc 100644 --- a/bundles/wireguard/items.py +++ b/bundles/wireguard/items.py @@ -1,21 +1,3 @@ from ipaddress import ip_network repo.libs.tools.require_bundle(node, 'systemd-networkd') - -network = ip_network(node.metadata['wireguard']['my_ip'], strict=False) - -files = { - '/etc/systemd/network/wg0.netdev': { - 'content_type': 'mako', - 'context': { - 'network': f'{network.network_address}/{network.prefixlen}', - **node.metadata['wireguard'], - }, - 'needs': { - 'pkg_apt:wireguard', - }, - 'triggers': { - 'svc_systemd:systemd-networkd:restart', - }, - }, -} diff --git a/bundles/wireguard/metadata.py b/bundles/wireguard/metadata.py index 4f9de05..73ca5e1 100644 --- a/bundles/wireguard/metadata.py +++ b/bundles/wireguard/metadata.py @@ -1,4 +1,4 @@ -from ipaddress import ip_network +from ipaddress import ip_network, ip_interface from bundlewrap.exceptions import NoSuchNode from bundlewrap.metadata import atomic @@ -16,6 +16,70 @@ defaults = { } +@metadata_reactor.provides( + 'systemd-networkd/networks', +) +def systemd_networkd_networks(metadata): + return { + 'systemd-networkd': { + 'networks': { + 'wg0': { + 'Match': { + 'Name': 'wg0', + }, + 'Address': { + 'Address': metadata.get('wireguard/my_ip'), + }, + 'Route': { + 'Destination': str(ip_interface(metadata.get('wireguard/my_ip')).network), + 'GatewayOnlink': 'yes', + }, + 'Network': { + 'DHCP': 'no', + 'IPv6AcceptRA': 'no', + }, + }, + }, + }, + } + + +@metadata_reactor.provides( + 'systemd-networkd/netdevs', +) +def systemd_networkd_netdevs(metadata): + wg0 = { + 'NetDev': { + 'Name': 'wg0', + 'Kind': 'wireguard', + 'Description': 'WireGuard server', + }, + 'WireGuard': { + 'PrivateKey': metadata.get('wireguard/privatekey'), + 'ListenPort': 51820, + }, + } + + for name, config in metadata.get('wireguard/peers').items(): + wg0.update({ + f'WireGuardPeer#{name}': { + 'Endpoint': config['endpoint'], + 'PublicKey': config['pubkey'], + 'PresharedKey': config['psk'], + 'AllowedIPs': '0.0.0.0/0', # FIXME + 'PersistentKeepalive': 30, + } + }) + + return { + 'systemd-networkd': { + 'netdevs': { + 'wg0': wg0, + }, + }, + } + + @metadata_reactor.provides( 'wireguard/peers', ) @@ -94,47 +158,3 @@ def peer_ips_and_endpoints(metadata): 'peers': peers, }, } - - -@metadata_reactor.provides( - 'interfaces/wg0/ips', -) -def interface_ips(metadata): - return { - 'interfaces': { - 'wg0': { - 'ips': { - metadata.get('wireguard/my_ip'), - }, - }, - }, - } - - -@metadata_reactor.provides( - 'interfaces/wg0/routes', -) -def routes(metadata): - network = ip_network(metadata.get('wireguard/my_ip'), strict=False) - ips = { - f'{network.network_address}/{network.prefixlen}', - } - routes = {} - - for _, peer_config in metadata.get('wireguard/peers', {}).items(): - for ip in peer_config['ips']: - ips.add(ip) - - if '0.0.0.0/0' in ips: - ips.remove('0.0.0.0/0') - - for ip in repo.libs.tools.remove_more_specific_subnets(ips): - routes[ip] = {} - - return { - 'interfaces': { - 'wg0': { - 'routes': routes, - }, - }, - } diff --git a/libs/systemd.py b/libs/systemd.py index 01f123e..b52bb88 100644 --- a/libs/systemd.py +++ b/libs/systemd.py @@ -1,9 +1,12 @@ from mako.template import Template template = ''' -% for i, (segment, options) in enumerate(data.items()): +% for segment, options in data.items(): -[${segment}] +% if '#' in segment: +# ${segment.split('#', 2)[1]} +% endif +[${segment.split('#')[0]}] % for option, value in options.items(): % if isinstance(value, dict): % for k, v in value.items(): @@ -13,8 +16,8 @@ ${option}=${k}=${v} % for item in sorted(value): ${option}=${item} % endfor -% elif isinstance(value, str): -${option}=${value} +% else: +${option}=${str(value)} % endif % endfor % endfor