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), }, } }