defaults = { 'apt': { 'packages': { 'isc-dhcp-server': {}, }, }, 'bash_aliases': { 'leases': 'sudo dhcp-lease-list | tail -n +4 | sort -k 2,2', }, } @metadata_reactor.provides( 'dhcpd/fixed_allocations', ) def get_static_allocations(metadata): allocations = {} for rnode in repo.nodes: if rnode.metadata.get('location', '') != metadata.get('location', ''): continue for iface_name, iface_config in rnode.metadata.get('interfaces', {}).items(): if iface_config.get('dhcp', False): try: allocations[f'{rnode.name}_{iface_name}'] = { 'ipv4': sorted(iface_config['ips'])[0], 'mac': iface_config['mac'], } except KeyError: pass return { 'dhcpd': { 'fixed_allocations': allocations, } } @metadata_reactor.provides( 'dhcpd/listen_interfaces', ) def get_listen_interfaces(metadata): listen_interfaces = [] for _, subnet in node.metadata.get('dhcpd/subnets', {}).items(): listen_interfaces.append(subnet['interface']) return { 'dhcpd': { 'listen_interfaces': ' '.join(sorted(listen_interfaces)), } } @metadata_reactor.provides( 'iptables/bundle_rules/dhcpd', ) def iptables(metadata): rules = set() for subnet in node.metadata.get('dhcpd/subnets', {}).values(): rules.add('iptables -A INPUT -i {} -p udp --dport 67:68 -j ACCEPT'.format(subnet['interface'])) return { 'iptables': { 'bundle_rules': { # can't use port_rules here. We're generating interface based rules here. 'dhcpd': sorted(list(rules)), }, } }