From cb6f12b218e3865867ac559e83472b72e4e3e6f8 Mon Sep 17 00:00:00 2001 From: Franziska Kunsmann Date: Sat, 9 Sep 2023 18:40:10 +0200 Subject: [PATCH] add bundle:kea-dhcp-server --- bundles/kea-dhcp-server/items.py | 42 +++++++++++++++ bundles/kea-dhcp-server/metadata.py | 83 +++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 bundles/kea-dhcp-server/items.py create mode 100644 bundles/kea-dhcp-server/metadata.py diff --git a/bundles/kea-dhcp-server/items.py b/bundles/kea-dhcp-server/items.py new file mode 100644 index 0000000..921bf78 --- /dev/null +++ b/bundles/kea-dhcp-server/items.py @@ -0,0 +1,42 @@ +kea_config = { + 'Dhcp4': { + **node.metadata.get('kea-dhcp-server/config'), + 'interfaces-config': { + 'interfaces': sorted(node.metadata.get('kea-dhcp-server/subnets', {}).keys()), + }, + 'subnet4': [], + }, + 'Server': { + 'loggers': [{ + 'name': 'kea-dhcp4', + 'output_options': [{ + # -> journal + 'output': 'stdout', + }], + 'severity': 'WARN', + }], + }, +} + +for iface, config in sorted(node.metadata.get('kea-dhcp-server/subnets', {}).items()): + kea_config['Dhcp4']['subnet4'].append({ + 'subnet': config['subnet'], + 'pools': [{ + 'pool': f'{config["lower"]} - {config["higher"]}', + }], + 'option-data': [ + { + 'name': k, + 'data': v, + } for k, v in sorted(config.get('options', {}).items()) + ], + 'reservations': [ + { + 'ip-address': v['ip'], + 'hw-address': v['mac'], + 'hostname': k, + } for k, v in sorted(node.metadata.get(f'kea-dhcp-server/fixed_allocations/{iface}', {}).items()) + ] + }) + +# TODO deploy config diff --git a/bundles/kea-dhcp-server/metadata.py b/bundles/kea-dhcp-server/metadata.py new file mode 100644 index 0000000..7b69f3e --- /dev/null +++ b/bundles/kea-dhcp-server/metadata.py @@ -0,0 +1,83 @@ +from ipaddress import ip_address, ip_network + +defaults = { + 'apt': { + 'packages': { + 'kea-dhcp4-server': {}, + }, + }, + 'kea-dhcp-server': { + 'config': { + 'authoritative': True, + 'rebind-timer': 450, + 'renew-timer': 300, + 'valid-lifetime': 600, + 'expired-leases-processing': { + 'max-reclaim-leases': 0, + 'max-reclaim-time': 0, + }, + 'lease-database': { + 'lfc-interval': 3600, + 'name': '/var/lib/kea/kea-leases4.csv', + 'persist': True, + 'type': 'memfile', + }, + }, + }, +} + + +@metadata_reactor.provides( + 'kea-dhcp-server/fixed_allocations', +) +def get_static_allocations(metadata): + result = {} + mapping = {} + + for iface, config in metadata.get('kea-dhcp-server/subnets', {}).items(): + result[iface] = {} + mapping[iface] = ip_network(config['subnet']) + + for rnode in repo.nodes: + if ( + rnode.metadata.get('location', '') != metadata.get('location', '') + or rnode == node + ): + continue + + for iface_name, iface_config in rnode.metadata.get('interfaces', {}).items(): + if iface_config.get('dhcp', False) and iface_config.get('mac'): + for ip in iface_config.get('ips', set()): + ipaddr = ip_address(ip) + + for kea_iface, kea_subnet in mapping.items(): + if ipaddr in kea_subnet: + result[kea_iface][f'{rnode.name}_{iface_name}'] = { + 'ip': ip, + 'mac': iface_config['mac'], + } + break + + return { + 'kea-dhcp-server': { + 'fixed_allocations': result, + } + } + + +@metadata_reactor.provides( + 'nftables/rules/10-kea-dhcp-server', +) +def nftables(metadata): + rules = set() + for iface in node.metadata.get('kea-dhcp-server/subnets', {}): + rules.add(f'inet filter input udp dport {{ 67, 68 }} iif {iface} accept') + + return { + 'nftables': { + 'rules': { + # can't use port_rules here, because we're generating interface based rules. + '10-kea-dhcp-server': sorted(rules), + }, + } + }