145 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from ipaddress import ip_interface
 | 
						|
 | 
						|
defaults = {
 | 
						|
    'network': {},
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@metadata_reactor.provides(
 | 
						|
    'network',
 | 
						|
)
 | 
						|
def dhcp(metadata):
 | 
						|
    networks = {}
 | 
						|
 | 
						|
    for network_name, network_conf in metadata.get('network').items():
 | 
						|
        _interface = ip_interface(network_conf['ipv4'])
 | 
						|
        _ip = _interface.ip
 | 
						|
        _network = _interface.network
 | 
						|
        _hosts = list(_network.hosts())
 | 
						|
 | 
						|
        if network_conf.get('dhcp_server', False):
 | 
						|
            networks[network_name] = {
 | 
						|
                'dhcp_server_config': {
 | 
						|
                    'subnet': str(_network),
 | 
						|
                    'pool_from': str(_hosts[len(_hosts)//2]),
 | 
						|
                    'pool_to': str(_hosts[-3]),
 | 
						|
                    'router': str(_ip),
 | 
						|
                    'domain-name-servers': str(_ip),
 | 
						|
                }
 | 
						|
            }
 | 
						|
    return {
 | 
						|
        'network': networks,
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
@metadata_reactor.provides(
 | 
						|
    'systemd/units',
 | 
						|
    'modules-load',
 | 
						|
)
 | 
						|
def units(metadata):
 | 
						|
    if node.has_bundle('systemd-networkd'):
 | 
						|
        units = {}
 | 
						|
        modules_load = set()
 | 
						|
 | 
						|
        for network_name, network_conf in metadata.get('network').items():
 | 
						|
            interface_type = network_conf.get('type', None)
 | 
						|
 | 
						|
            # network
 | 
						|
 | 
						|
            units[f'{network_name}.network'] = {
 | 
						|
                'Match': {
 | 
						|
                    'Name': network_name if interface_type == 'vlan' else network_conf['interface'],
 | 
						|
                },
 | 
						|
                'Network': {
 | 
						|
                    'DHCP': network_conf.get('dhcp', 'no'),
 | 
						|
                    'IPv6AcceptRA': network_conf.get('IPv6AcceptRA', 'no'),
 | 
						|
                    'VLAN': set(
 | 
						|
                        other_network_name
 | 
						|
                            for other_network_name, other_network_conf in metadata.get('network', {}).items()
 | 
						|
                            if other_network_conf.get('type') == 'vlan' and other_network_conf['vlan_interface'] == network_name
 | 
						|
                    )
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            # type
 | 
						|
 | 
						|
            if interface_type:
 | 
						|
                units[f'{network_name}.network']['Match']['Type'] = interface_type
 | 
						|
 | 
						|
            # ips
 | 
						|
 | 
						|
            for i in [4, 6]:
 | 
						|
                if network_conf.get(f'ipv{i}', None):
 | 
						|
                    units[f'{network_name}.network'].update({
 | 
						|
                        f'Address#ipv{i}': {
 | 
						|
                            'Address': network_conf[f'ipv{i}'],
 | 
						|
                        },
 | 
						|
                    })
 | 
						|
                    if f'gateway{i}' in network_conf:
 | 
						|
                        units[f'{network_name}.network'].update({
 | 
						|
                            f'Route#ipv{i}': {
 | 
						|
                                'Gateway': network_conf[f'gateway{i}'],
 | 
						|
                                'GatewayOnlink': 'yes',
 | 
						|
                            }
 | 
						|
                        })
 | 
						|
 | 
						|
            # as vlan
 | 
						|
 | 
						|
            if interface_type == 'vlan':
 | 
						|
                units[f"{network_name}.netdev"] = {
 | 
						|
                    'NetDev': {
 | 
						|
                        'Name': network_name,
 | 
						|
                        'Kind': 'vlan',
 | 
						|
                    },
 | 
						|
                    'VLAN': {
 | 
						|
                        'Id': network_conf['id'],
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
            # cake WIP
 | 
						|
 | 
						|
            if 'cake' in network_conf:
 | 
						|
                units[f'{network_name}.network']['CAKE'] = network_conf['cake']
 | 
						|
                modules_load.add('sch_cake')
 | 
						|
 | 
						|
        return {
 | 
						|
            'systemd': {
 | 
						|
                'units': units,
 | 
						|
            },
 | 
						|
            'modules-load': modules_load,
 | 
						|
        }
 | 
						|
    else:
 | 
						|
        return {}
 | 
						|
 | 
						|
 | 
						|
@metadata_reactor.provides(
 | 
						|
    'systemd/units',
 | 
						|
)
 | 
						|
def queuing_disciplines(metadata):
 | 
						|
    if node.has_bundle('systemd-networkd'):
 | 
						|
        return {
 | 
						|
            'systemd': {
 | 
						|
                'units': {
 | 
						|
                    f'qdisc-{network_name}.service': {
 | 
						|
                        'Unit': {
 | 
						|
                            'Description': f'setup queuing discipline for interface {network_name}',
 | 
						|
                            'Wants': 'network.target',
 | 
						|
                            'After': 'network.target',
 | 
						|
                            'BindsTo': 'network.target',
 | 
						|
                        },
 | 
						|
                        'Service': {
 | 
						|
                            'Type': 'oneshot',
 | 
						|
                            'ExecStart': f'/sbin/tc qdisc replace root dev {network_name} {network_conf["qdisc"]}',
 | 
						|
                            'RemainAfterExit': 'yes',
 | 
						|
                        },
 | 
						|
                        'Install': {
 | 
						|
                            'WantedBy': 'network-online.target',
 | 
						|
                        },
 | 
						|
                    }
 | 
						|
                        for network_name, network_conf in metadata.get('network').items()
 | 
						|
                        if 'qdisc' in network_conf
 | 
						|
                },
 | 
						|
            },
 | 
						|
        }
 | 
						|
    else:
 | 
						|
        return {}
 |