From 032af49e415855895e0408294c4ce9951e4c8096 Mon Sep 17 00:00:00 2001 From: Jonathan Bauer Date: Thu, 3 Aug 2017 11:19:48 +0200 Subject: added systemd-networkd extension module --- .../hooks/parse-kcl-for-networkd.sh | 98 ++++++++++++++++++++++ .../modules.d/systemd-networkd-ext/module-setup.sh | 49 +++++++++++ 2 files changed, 147 insertions(+) create mode 100644 builder/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh create mode 100755 builder/modules.d/systemd-networkd-ext/module-setup.sh (limited to 'builder/modules.d/systemd-networkd-ext') diff --git a/builder/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh b/builder/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh new file mode 100644 index 00000000..cdf080a3 --- /dev/null +++ b/builder/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# +# This script was mostly stolen from 40network/parse-ip-opts.sh. Its +# actions are adapted to write .network files to /etc/systemd/network +# in the initramfs instead o + +command -v getarg >/dev/null || . /lib/dracut-lib.sh + +main_work() { + local IPCONF="$(getarg ip=)" + local BOOTIF="$(getarg BOOTIF=)" + + if [ -z "${IPCONF}" ] && [ -z "${BOOTIF}" ]; then + # No ip= argument(s) given by PXE, TODO try dhcp + return; + fi + + # ip= is expected in following format (syslinux IPAPPEND3): + # ::: + local CLIENT_IP= + local SERVER_IP= + local GATEWAY_IP= + local NETMASK= + read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" ) + + # BOOTIF= contains the MAC address of the boot interface + # and a hardware type prefix of length 2, e.g. "01-" + # So if BOOTIF has 20 chars, then we got the prefix. + # This needs to be stripped to get the MAC address only + [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ] && BOOTIF="${BOOTIF#???}" + BOOTIF="$(tr '-' ':' <<< $BOOTIF)" + + # TODO sanity checks + + # Taken from parse-ip-opts.sh + # Convert the netmask to CIDR notation + if [[ "x$NETMASK" =~ ^x[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + CIDR=$(mask2cidr "$NETMASK") + elif [ -n "$NETMASK" -a "x${NETMASK//[0-9]/}" = 'x' ]; then + # The mask is already a prefix length (uint), so validate it + [[ "x$CLIENT_IP" == x*:*:* && "$NETMASK" -le 128 || "$NETMASK" -le 32 ]] && CIDR=$NETMASK + fi + + + # Generate network and link file for networkd + NETWORK_FILE=/etc/systemd/network/01-boot-lan.network + mkdir -p $(dirname $NETWORK_FILE) + echo '[Match]' > $NETWORK_FILE + echo 'Name=bootnet' >> $NETWORK_FILE + # Hardcode bootnet as our boot interface + [ -n "$BOOTIF" ] && echo "MACAddress=$BOOTIF" >> $NETWORK_FILE + echo '[Network]' >> $NETWORK_FILE + echo 'Bridge=br0' >> $NETWORK_FILE + + ## Boot interface has 'bootnet' as dedicated name + LINK_FILE=/etc/systemd/network/00-boot-lan.link + echo '[Match]' > $LINK_FILE + [ -n "$BOOTIF" ] && echo "MACAddress=$BOOTIF" >> $LINK_FILE + echo '[Link]' >> $LINK_FILE + echo "Name=bootnet" >> $LINK_FILE + + # HACK pro bridge setup + BRIDGE_DEV_CONF=/etc/systemd/network/10-bridge-lan.netdev + echo '[NetDev]' > $BRIDGE_DEV_CONF + echo 'Name=br0' >> $BRIDGE_DEV_CONF + echo 'Kind=bridge' >> $BRIDGE_DEV_CONF + + BRIDGE_IF_CONF=/etc/systemd/network/11-bridge-lan.network + echo '[Match]' > $BRIDGE_IF_CONF + echo "Name=br0" >> $BRIDGE_IF_CONF + echo '[Network]' >> $BRIDGE_IF_CONF + [ -n "$CLIENT_IP" ] && echo "Address=${CLIENT_IP}/${CIDR:-24}" >> $BRIDGE_IF_CONF + [ -n "$GATEWAY_IP" ] && echo "Gateway=${GATEWAY_IP}" >> $BRIDGE_IF_CONF + +} +# from parse-ip-opts.sh +# Takes a netmask and outputs the corresponding CIDR +# e.g. +# mask2cidr 255.255.255.0 +# returns: 24 +function mask2cidr() { + local -i bits=0 + for octet in ${1//./ }; do + for i in {0..8}; do + [ "$octet" -eq $(( 256 - (1 << i) )) ] && bits+=$((8-i)) && break + done + [ $i -eq 8 -a "$octet" -ne 0 ] && warn "Bad netmask $mask" && return + [ $i -gt 0 ] && break + done + echo $bits +} + +main_work + +# HACK to wait for network during udev loop... +touch /lib/dracut/need-initqueue +/sbin/initqueue --finished /bin/busybox timeout -t 10 /lib/systemd/systemd-networkd-wait-online -i br0 + diff --git a/builder/modules.d/systemd-networkd-ext/module-setup.sh b/builder/modules.d/systemd-networkd-ext/module-setup.sh new file mode 100755 index 00000000..3b3aabd6 --- /dev/null +++ b/builder/modules.d/systemd-networkd-ext/module-setup.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# called by dracut +check() { + if ! dracut_module_included "systemd-networkd"; then + derror "systemd-networkd-ext needs systemd-networkd in the initramfs" + return 1 + fi + + return 255 +} + +# called by dracut +depends() { + echo "systemd-networkd" +} + +installkernel() { + return 0 +} + +# called by dracut +install() { + # need initqueue to get a clean network start + dracut_need_initqueue + + inst_multiple -o \ + $systemdutildir/systemd-networkd \ + $systemdutildir/systemd-networkd-wait-online \ + $systemdsystemunitdir/systemd-networkd-wait-online.service \ + $systemdsystemunitdir/systemd-networkd.service \ + $systemdsystemunitdir/systemd-networkd.socket \ + networkctl ip + + # the hook script that will parse the "ip=" kernel command line + # parameter and generate the .link and .network files needed + # by systemd-networkd. + inst_hook cmdline 10 "$moddir/hooks/parse-kcl-for-networkd.sh" + for i in \ + systemd-networkd-wait-online.service \ + systemd-networkd.service \ + systemd-networkd.socket + do + systemctl --root "$initdir" enable "$i" + done + # HACK: disables udev new persitent naming scheme + rm $systemdutildir/network/99-default.link +} + -- cgit v1.2.3-55-g7522