From e6ac1e71f8b652fd2e9cf324261f4c6f7b5bd0e1 Mon Sep 17 00:00:00 2001 From: torben Date: Mon, 3 Sep 2018 08:57:37 +0200 Subject: Refactoring for proper file names. --- .../hooks/configure-dhcp-for-newroot.sh | 3 +- ...twork-configuration-to-systemd-service-files.sh | 313 +++++++++++++++++++++ .../hooks/copy-networkd-files-to-newroot.sh | 149 ---------- .../hooks/parse-kcl-for-networkd.sh | 313 --------------------- .../hooks/prepare-network-service-in-newroot.sh | 149 ++++++++++ modules.d/systemd-networkd-ext/module-setup.sh | 4 +- 6 files changed, 466 insertions(+), 465 deletions(-) create mode 100755 modules.d/systemd-networkd-ext/hooks/convert-kcl-network-configuration-to-systemd-service-files.sh delete mode 100755 modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh delete mode 100755 modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh create mode 100755 modules.d/systemd-networkd-ext/hooks/prepare-network-service-in-newroot.sh diff --git a/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh b/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh index 1f0487ec..938fbfaa 100755 --- a/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh +++ b/modules.d/systemd-networkd-ext/hooks/configure-dhcp-for-newroot.sh @@ -5,7 +5,8 @@ source /usr/lib/configure-logging.sh # This hook creates a networkd configuration for the NEWROOT # * DHCP configuration for the boot interface # * Set static hostname via /etc/hostname -# This uses the configuration file generated by the parse-kcl-for-networkd.sh +# This uses the configuration file generated by the +# convert-kcl-network-configuration-to-systemd-service-files.sh # hook Note: on systemd v219, UseDomains is bugged and does not seem to do # anything thus that option is complemented with the KCL's domain to hopefully # guarantee one of these will take effect. diff --git a/modules.d/systemd-networkd-ext/hooks/convert-kcl-network-configuration-to-systemd-service-files.sh b/modules.d/systemd-networkd-ext/hooks/convert-kcl-network-configuration-to-systemd-service-files.sh new file mode 100755 index 00000000..d4c4c109 --- /dev/null +++ b/modules.d/systemd-networkd-ext/hooks/convert-kcl-network-configuration-to-systemd-service-files.sh @@ -0,0 +1,313 @@ +#!/bin/bash +# +# This script was mostly stolen from 40network/parse-ip-opts.sh. It was +# adapted to generate .network files for systemd-networkd using the IP +# configuration from PXE/Syslinux in addition to domain, dns and hostname + +source /usr/lib/configure-logging.sh + +command -v getarg >/dev/null || \ + source /lib/dracut-lib.sh + +# static names for the boot interface and its bridge +declare -rg BOOTIF_NAME=boot0 +declare -rg WIRELESS_BOOTIF_NAME=wireless +declare -rg BRIDGE_NAME=br0 + +# Get all the ip-related arguments from the KCL +parse_kernel_command_line() { + ## KCL "BOOTIF": MAC address of the interface that DHCP'ed during PXE + declare -g BOOTIF="$(getarg BOOTIF=)" + declare -g WIRELESS_BOOTIF="$(getarg WIRELESS_BOOTIF=)" + # Remove the hardware type prefix of BOOTIF if it has 20 chars to get + # the plain MAC address. The hardware type prefix has length 3, e.g. "01-". + [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ] && BOOTIF="${BOOTIF#???}" + BOOTIF="$(tr '-' ':' <<< $BOOTIF)" + readonly BOOTIF + [ -n "${WIRELESS_BOOTIF}" ] && [ ${#WIRELESS_BOOTIF} -eq 20 ] && WIRELESS_BOOTIF="${WIRELESS_BOOTIF#???}" + WIRELESS_BOOTIF="$(tr '-' ':' <<< $WIRELESS_BOOTIF)" + readonly WIRELESS_BOOTIF + + ## KCL "ip": is expected in following format (syslinux IPAPPEND3): + declare -rg IPCONF="$(getarg ip=)" + # ::: + declare -g CLIENT_IP= + declare -g SERVER_IP= + declare -g GATEWAY_IP= + declare -g NETMASK= + read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" ) + readonly CLIENT_IP SERVER_IP GATEWAY_IP NETMASK + + + # Taken from parse-ip-opts.sh: Convert the netmask to CIDR notation + declare -g CIDR + 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 + readonly CIDR + + # KCL "hostname" + declare -rg HOSTNAME="$(getarg hostname=)" + [ -n "$HOSTNAME" ] && echo "$HOSTNAME" > /proc/sys/kernel/hostname + + # KCL "dns" + declare -rg DNS="$(getarg dns=)" + + # KCL "domain" + declare -rg DOMAIN="$(getarg domain=)" + + # VLAN tag + declare -rg VLAN="$(getarg vlan=)" + if [[ "$VLAN" != '' ]]; then + modprobe 8021q || emergency_shell "VLAN mode detected - failed to load 8021q" + fi + + # Bridged mode? + grep -qE '\s+bridged\s+' /proc/cmdline && declare -rg BRIDGED="y" +} + +# Dumps the parsed IP configuration to /run/openslx/pxe-network.conf +# Creates a list of "KEY=value" type variables to source later on +save_ip_config() { + local IP_RUNTIME_CONFIG=/run/openslx/pxe-network.conf + mkdir -p "${IP_RUNTIME_CONFIG%/*}" # dirname a la bash + cat << EOF > "$IP_RUNTIME_CONFIG" +SLX_PXE_CLIENT_IP=$CLIENT_IP +SLX_PXE_SERVER_IP=$SERVER_IP +SLX_PXE_GATEWAY=$GATEWAY_IP +SLX_PXE_DNS=$DNS +SLX_PXE_MAC=$BOOTIF +SLX_WIRELESS_MAC=$WIRELESS_BOOTIF +SLX_PXE_NETIF=$BOOTIF_NAME +SLX_WIRELESS_NETIF=$WIRELESS_BOOTIF_NAME +SLX_BRIDGE=${BRIDGED:+$BRIDGE_NAME} +SLX_BRIDGE_BRIDGED=$BRIDGED +SLX_BRIDGE_NAME=$BRIDGE_NAME +SLX_VLAN_ID=$VLAN +SLX_DNS=$DNS +SLX_HOSTNAME=$HOSTNAME +SLX_NET_DOMAIN=$DOMAIN +EOF +} + +# Helper to echo the static configuration, +# including DNS and Domain, if given per KCL +print_static_ip_conf() { + if (( $# != 2 )); then + echo "Need 2 args: . Given: $*" + return 1 + fi + echo "Address=$1" + echo "Gateway=$2" + [ -n "${DNS}" ] && echo "DNS=${DNS}" + [ -n "${DOMAIN}" ] && echo "Domains=${DOMAIN}" +} + +## Generate network and link file(s) for networkd +# Checks if an IP configuration was forwarded by +generate_networkd_config() { + mkdir --parents /etc/systemd/network + rm --force --recursive /etc/systemd/network/* + if [[ "$BOOTIF" != '' ]] && [[ "$BOOTIF" != false ]]; then + local BOOTIF_NETWORK_CONF="/etc/systemd/network/$BOOTIF_NAME.network" + ( + echo [Match] + echo "MACAddress=${BOOTIF}" + echo 'Path=pci*' + echo + # Currently the boot interface is configured to either: + # * static ip as given by the initial DHCP during PXE + # * bridged + # * vlan-tagged (ethernet interface not configured) + # In particular, configuring both vlan tags and the physical + # interface is not supported (might be needed in some setups) + echo [Network] + if [[ "$BRIDGED" != '' ]]; then + echo "Bridge=${BRIDGE_NAME}" + elif [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then + print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" + elif [[ "$VLAN" != '' ]]; then + echo "VLAN=$BOOTIF_NAME.$VLAN" + else + echo DHCP=ipv4 + fi + echo LinkLocalAddressing=no + ) > "$BOOTIF_NETWORK_CONF" + # NOTE: Declarative version if boot interface renaming. + cat << EOF > "/etc/systemd/network/$BOOTIF_NAME.link" +[Match] +MACAddress=$BOOTIF + +[Link] +Description=Critical wired network device. +Name=$BOOTIF_NAME +EOF + fi + if [ "$WIRELESS_BOOTIF" = '' ] || [ "$WIRELESS_BOOTIF" = false ]; then + if \ + rm \ + --force \ + /usr/lib/systemd/system/network.target.wants/iwd.service \ + &>/dev/null || + rm \ + --force \ + /usr/lib/systemd/system/network.target.wants/wpa_supplicant@* \ + &>/dev/null + then + systemctl daemon-reload + fi + else + local WIRELESS_BOOTIF_NETWORK_CONF="/etc/systemd/network/$WIRELESS_BOOTIF_NAME.network" + ( + echo [Match] + echo "MACAddress=$WIRELESS_BOOTIF" + echo "Path=pci*" + echo + # Currently the boot interface is configured to either: + # * static ip as given by the initial DHCP during PXE + # * bridged + # * vlan-tagged (ethernet interface not configured) + # In particular, configuring both vlan tags and the physical + # interface is not supported (might be needed in some setups) + echo [Network] + if [[ "$BRIDGED" != '' ]]; then + echo "Bridge=$BRIDGE_NAME" + elif [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then + print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" + elif [[ "$VLAN" != '' ]]; then + echo "VLAN=$BOOTIF_NAME.$VLAN" + else + echo DHCP=ipv4 + fi + cat << EOF +LinkLocalAddressing=no +IPv6AcceptRA=no + +[DHCP] +UseDNS=true +UseDomains=true +UseHostname=true +CriticalConnection=true +EOF + ) > "$WIRELESS_BOOTIF_NETWORK_CONF" + cat << EOF > "/etc/systemd/network/$WIRELESS_BOOTIF_NAME.link" +[Match] +MACAddress=$WIRELESS_BOOTIF + +[Link] +Description=Critical wireless network device. +Name=$WIRELESS_BOOTIF_NAME +EOF + fi + if [[ "$VLAN" != '' ]]; then + local VLAN_DEV_CONF="/etc/systemd/network/$BOOTIF_NAME.$VLAN.netdev" + cat << EOF > "$VLAN_DEV_CONF" +[NetDev] +Name=$BOOTIF_NAME.$VLAN +MACAddress=$BOOTIF +Kind=vlan + +[VLAN] +Id=$VLAN +EOF + fi + if [[ "$VLAN" != '' ]]; then + # Configure the vlan tagged interface for DHCPv4, TODO IPv6 + local VLAN_NETWORK_CONF="/etc/systemd/network/$BOOTIF_NAME.$VLAN.network" + cat << EOF > "$VLAN_NETWORK_CONF" +[Match] +Name=$BOOTIF_NAME.$VLAN +Type=vlan + +[Link] +MACAddress=$BOOTIF + +[Network] +DHCP=ipv4 +LinkLocalAddressing=no + +[DHCP] +UseDNS=true +UseDomains=true +UseHostname=true +CriticalConnection=true +EOF + fi + # bridge setup + if [[ "$BRIDGED" != '' ]]; then + local BRIDGE_DEV_CONF="/etc/systemd/network/$BRIDGE_NAME.netdev" + cat << EOF > "$BRIDGE_DEV_CONF" +[NetDev] +Name=$BRIDGE_NAME +Kind=bridge +MACAddress=$BOOTIF +EOF + + local BRIDGE_NETWORK_CONF="/etc/systemd/network/$BRIDGE_NAME.network" + ( + echo [Match] + echo "Name=$BRIDGE_NAME" + echo + echo [Network] + if [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then + print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" + else + # bad/no IP info, fallback to DHCP + echo DHCP=ipv4 + fi + echo LinkLocalAddressing=no + ) > "$BRIDGE_NETWORK_CONF" + fi + return 0 +} +# from parse-ip-opts.sh +# Takes a netmask and outputs the corresponding CIDR +# e.g. +# mask2cidr 255.255.255.0 +# returns: 24 +mask2cidr() { + local -i bits=0 + for octet in ${1//./ }; do + for i in {0..8}; do + if [ "$octet" = $(( 256 - (1 << i) )) ]; then + bits+=$((8-i)) + break + fi + done + if (( $i == 8 )) && (( $octet != 0 )); then + warn Bad netmask $mask + return + fi + if (( $i > 0 )); then + break + fi + done + echo $bits +} + +## MAIN ## +# Get IP config from KCL +parse_kernel_command_line + +# Save IP config for later use +save_ip_config + +# Create the udev rule to rename the boot interface to the declared BOOTIF_NAME +# Create udev rule to rename the PXE boot interface to BOOTIF_NAME +if [[ "$BOOTIF" != '' ]] && [[ "$BOOTIF" != false ]]; then + # priority 70 < 80-net-name-slot.rules. + echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'$BOOTIF'", NAME="'$BOOTIF_NAME'"' \ + > /etc/udev/rules.d/70-pxe-boot-interface.rules +fi +if [[ "$WIRELESS_BOOTIF" != '' ]] && [[ "$WIRELESS_BOOTIF" != false ]]; then + # priority 70 < 80-net-name-slot.rules. + echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'$WIRELESS_BOOTIF'", NAME="'$WIRELESS_BOOTIF_NAME'"' \ + > /etc/udev/rules.d/70-pxe-wireless-boot-interface.rules +fi + +# Generate config files for networkd +generate_networkd_config || \ + emergency_shell "Failed to generate networkd configuration." diff --git a/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh b/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh deleted file mode 100755 index 5ed9a835..00000000 --- a/modules.d/systemd-networkd-ext/hooks/copy-networkd-files-to-newroot.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash - -source /usr/lib/configure-logging.sh -source /run/openslx/pxe-network.conf - -# This hook copies the core systemd-networkd related service -# files to the NEWROOT and activate them in sysinit.target -# to prevent systemd from killing these while pivot_root -NEWROOT_SYSTEMD_DIR="$NEWROOT/usr/lib/systemd/system" -NEWROOT_SYSINIT_TARGET_DIR="$NEWROOT_SYSTEMD_DIR/sysinit.target.wants" -mkdir --parents "$NEWROOT_SYSINIT_TARGET_DIR" - -if $SLX_ONLINE; then - bl.logging.info Remove known network services. - for service_name in \ - systemd-networkd \ - systemd-resolved - do - path="$NEWROOT/etc/systemd/system/multi-user.target.wants/$service_name.service" - if rm "$path" &>/dev/null; then - bl.logging.info \ - Removing known redundant network service from target system at \ - "$path". - fi - done - # NOTE: We remove known target configurations if "$SLX_WIRELESS_MAC" is to - # "false". - if [[ "$SLX_WIRELESS_MAC" != '' ]]; then - path="$NEWROOT/etc/systemd/system/multi-user.target.wants/iwd.service" - if rm "$path" &>/dev/null; then - bl.logging.info \ - Removing known redundant network service from target system \ - at \"$path\". - fi - for service_name in \ - netctl \ - netctl-auto \ - wpa_supplicant - do - path="$NEWROOT/etc/systemd/system/multi-user.target.wants/$service_name"*.service - # NOTE: Do not use quotes here to allow bash expansion. - if rm $path &>/dev/null; then - bl.logging.info \ - Removing knonw redundant device specific service from \ - target system at \"$path\". - fi - done - fi - bl.logging.info Move running network services into new system. - for service_name in \ - systemd-networkd.service \ - systemd-networkd.socket \ - systemd-resolved.service - do - service_file_path="$( - systemctl show --property FragmentPath $service_name | \ - cut --characters 14-)" - mkdir --parents "$NEWROOT/${service_file_path%/*}" - bl.logging.info \ - Copy initramfs service "$service_file_path" to \ - "$NEWROOT/$service_file_path". - cp "$service_file_path" "$NEWROOT/$service_file_path" - bl.logging.info \ - Link service "$service_file_path" to \ - "$NEWROOT_SYSINIT_TARGET_DIR/$service_name". - ln \ - --force \ - --symbolic \ - "$service_file_path" \ - "$NEWROOT_SYSINIT_TARGET_DIR/$service_name" - done - if \ - [[ "$SLX_WIRELESS_MAC" != '' ]] && \ - [[ "$SLX_WIRELESS_MAC" != false ]] - then - service_name=wpa_supplicant@wireless.service - #service_name=iwd.service - service_file_path="$( - systemctl show --property FragmentPath "$service_name" | \ - cut --characters 14-)" - mkdir --parents "$NEWROOT/${service_file_path%/*}" - bl.logging.info \ - Copy initramfs service "$service_file_path" to \ - "$NEWROOT/$service_file_path". - cp "$service_file_path" "$NEWROOT/$service_file_path" - bl.logging.info \ - Copy initramfs service \ - \"/usr/lib/systemd/system/restart-wireless-daemon.service\" to \ - \"$NEWROOT/usr/lib/systemd/system/restart-wireless-daemon.service\". - cp \ - /usr/lib/systemd/system/restart-wireless-daemon.service \ - "$NEWROOT/usr/lib/systemd/system/restart-wireless-daemon.service" - bl.logging.info \ - Link service \"restart-wireless-daemon\" to \ - \"$NEWROOT/usr/lib/systemd/system/multi-user.target.wants/restart-wireless-daemon.service\". - # Systemd version to restart wireless daemon could hang due to its - # concurrent block device input output nature. - #ln \ - # --force \ - # --symbolic \ - # ../restart-wireless-daemon.service \ - # "$NEWROOT/usr/lib/systemd/system/multi-user.target.wants/restart-wireless-daemon.service" - # Login to tty1 version, works: - echo -e "[ ! -f /tmp/wireless-daemon-restarted ] && systemctl start restart-wireless-daemon.service && touch /tmp/wireless-daemon-restarted\n$(cat "$NEWROOT/root/.bash_profile")" \ - > "$NEWROOT/root/.bash_profile" - # Stops daemon at boot yet. - #bl.logging.info \ - # Link service \"$service_file_path\" to \ - # \"$NEWROOT_SYSINIT_TARGET_DIR/$service_name\". - #ln \ - # --force \ - # --symbolic \ - # "$service_file_path" \ - # "$NEWROOT_SYSINIT_TARGET_DIR/$service_name" - # Enable "wpa_supplicant" service to be able to restart after pivot-root. - sed \ - --in-place \ - --regexp-extended \ - 's:(/((usr/(bin|lib))|(etc))[^ ]+):/run/initramfs\1:g' \ - "$NEWROOT/$service_file_path" - sed \ - --in-place \ - --regexp-extended \ - 's:^(ExecStart=.+)$:ExecStartPre=-/run/initramfs/usr/bin/rm /run/wpa_supplicant/%I\n\1\nExecStartPost=/run/initramfs/usr/bin/touch /mnt/slx_writable_device/booted_to_wlan:' \ - "$NEWROOT/$service_file_path" - # Enable "iwd" service to be able to restart after pivot-root. - #sed \ - # --in-place \ - # --regexp-extended \ - # 's:^(ExecStart=)(/usr/bin/.+) (/usr/lib/iwd/iwd$):ExecStartPre=-/run/initramfs/usr/bin/rm /run/iwd/wireless\n\1/run/initramfs\2 /run/initramfs\3\nExecStartPost=/run/initramfs/usr/bin/touch /mnt/slx_writable_device/booted_to_wlan:' \ - # "$NEWROOT/$service_file_path" - fi - rm --force --recursive "$NEWROOT/etc/systemd/network/"* - if [ -f "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service" ]; then - # this drop-in is needed to prevent a pull-in loop sysinit.target <-> basic.target - mkdir --parents "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service.d" - cat << EOF > "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service.d/00-no-default-deps.conf" -[Unit] -DefaultDependencies=no -EOF - # NOTE: Make sure the NEWROOT resolv.conf links to the one managed by - # "systemd-resolved". - ln \ - --force \ - --symbolic \ - /run/systemd/resolve/resolv.conf \ - "$NEWROOT/etc/resolv.conf" - fi -fi diff --git a/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh b/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh deleted file mode 100755 index d4c4c109..00000000 --- a/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/bash -# -# This script was mostly stolen from 40network/parse-ip-opts.sh. It was -# adapted to generate .network files for systemd-networkd using the IP -# configuration from PXE/Syslinux in addition to domain, dns and hostname - -source /usr/lib/configure-logging.sh - -command -v getarg >/dev/null || \ - source /lib/dracut-lib.sh - -# static names for the boot interface and its bridge -declare -rg BOOTIF_NAME=boot0 -declare -rg WIRELESS_BOOTIF_NAME=wireless -declare -rg BRIDGE_NAME=br0 - -# Get all the ip-related arguments from the KCL -parse_kernel_command_line() { - ## KCL "BOOTIF": MAC address of the interface that DHCP'ed during PXE - declare -g BOOTIF="$(getarg BOOTIF=)" - declare -g WIRELESS_BOOTIF="$(getarg WIRELESS_BOOTIF=)" - # Remove the hardware type prefix of BOOTIF if it has 20 chars to get - # the plain MAC address. The hardware type prefix has length 3, e.g. "01-". - [ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ] && BOOTIF="${BOOTIF#???}" - BOOTIF="$(tr '-' ':' <<< $BOOTIF)" - readonly BOOTIF - [ -n "${WIRELESS_BOOTIF}" ] && [ ${#WIRELESS_BOOTIF} -eq 20 ] && WIRELESS_BOOTIF="${WIRELESS_BOOTIF#???}" - WIRELESS_BOOTIF="$(tr '-' ':' <<< $WIRELESS_BOOTIF)" - readonly WIRELESS_BOOTIF - - ## KCL "ip": is expected in following format (syslinux IPAPPEND3): - declare -rg IPCONF="$(getarg ip=)" - # ::: - declare -g CLIENT_IP= - declare -g SERVER_IP= - declare -g GATEWAY_IP= - declare -g NETMASK= - read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" ) - readonly CLIENT_IP SERVER_IP GATEWAY_IP NETMASK - - - # Taken from parse-ip-opts.sh: Convert the netmask to CIDR notation - declare -g CIDR - 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 - readonly CIDR - - # KCL "hostname" - declare -rg HOSTNAME="$(getarg hostname=)" - [ -n "$HOSTNAME" ] && echo "$HOSTNAME" > /proc/sys/kernel/hostname - - # KCL "dns" - declare -rg DNS="$(getarg dns=)" - - # KCL "domain" - declare -rg DOMAIN="$(getarg domain=)" - - # VLAN tag - declare -rg VLAN="$(getarg vlan=)" - if [[ "$VLAN" != '' ]]; then - modprobe 8021q || emergency_shell "VLAN mode detected - failed to load 8021q" - fi - - # Bridged mode? - grep -qE '\s+bridged\s+' /proc/cmdline && declare -rg BRIDGED="y" -} - -# Dumps the parsed IP configuration to /run/openslx/pxe-network.conf -# Creates a list of "KEY=value" type variables to source later on -save_ip_config() { - local IP_RUNTIME_CONFIG=/run/openslx/pxe-network.conf - mkdir -p "${IP_RUNTIME_CONFIG%/*}" # dirname a la bash - cat << EOF > "$IP_RUNTIME_CONFIG" -SLX_PXE_CLIENT_IP=$CLIENT_IP -SLX_PXE_SERVER_IP=$SERVER_IP -SLX_PXE_GATEWAY=$GATEWAY_IP -SLX_PXE_DNS=$DNS -SLX_PXE_MAC=$BOOTIF -SLX_WIRELESS_MAC=$WIRELESS_BOOTIF -SLX_PXE_NETIF=$BOOTIF_NAME -SLX_WIRELESS_NETIF=$WIRELESS_BOOTIF_NAME -SLX_BRIDGE=${BRIDGED:+$BRIDGE_NAME} -SLX_BRIDGE_BRIDGED=$BRIDGED -SLX_BRIDGE_NAME=$BRIDGE_NAME -SLX_VLAN_ID=$VLAN -SLX_DNS=$DNS -SLX_HOSTNAME=$HOSTNAME -SLX_NET_DOMAIN=$DOMAIN -EOF -} - -# Helper to echo the static configuration, -# including DNS and Domain, if given per KCL -print_static_ip_conf() { - if (( $# != 2 )); then - echo "Need 2 args: . Given: $*" - return 1 - fi - echo "Address=$1" - echo "Gateway=$2" - [ -n "${DNS}" ] && echo "DNS=${DNS}" - [ -n "${DOMAIN}" ] && echo "Domains=${DOMAIN}" -} - -## Generate network and link file(s) for networkd -# Checks if an IP configuration was forwarded by -generate_networkd_config() { - mkdir --parents /etc/systemd/network - rm --force --recursive /etc/systemd/network/* - if [[ "$BOOTIF" != '' ]] && [[ "$BOOTIF" != false ]]; then - local BOOTIF_NETWORK_CONF="/etc/systemd/network/$BOOTIF_NAME.network" - ( - echo [Match] - echo "MACAddress=${BOOTIF}" - echo 'Path=pci*' - echo - # Currently the boot interface is configured to either: - # * static ip as given by the initial DHCP during PXE - # * bridged - # * vlan-tagged (ethernet interface not configured) - # In particular, configuring both vlan tags and the physical - # interface is not supported (might be needed in some setups) - echo [Network] - if [[ "$BRIDGED" != '' ]]; then - echo "Bridge=${BRIDGE_NAME}" - elif [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then - print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" - elif [[ "$VLAN" != '' ]]; then - echo "VLAN=$BOOTIF_NAME.$VLAN" - else - echo DHCP=ipv4 - fi - echo LinkLocalAddressing=no - ) > "$BOOTIF_NETWORK_CONF" - # NOTE: Declarative version if boot interface renaming. - cat << EOF > "/etc/systemd/network/$BOOTIF_NAME.link" -[Match] -MACAddress=$BOOTIF - -[Link] -Description=Critical wired network device. -Name=$BOOTIF_NAME -EOF - fi - if [ "$WIRELESS_BOOTIF" = '' ] || [ "$WIRELESS_BOOTIF" = false ]; then - if \ - rm \ - --force \ - /usr/lib/systemd/system/network.target.wants/iwd.service \ - &>/dev/null || - rm \ - --force \ - /usr/lib/systemd/system/network.target.wants/wpa_supplicant@* \ - &>/dev/null - then - systemctl daemon-reload - fi - else - local WIRELESS_BOOTIF_NETWORK_CONF="/etc/systemd/network/$WIRELESS_BOOTIF_NAME.network" - ( - echo [Match] - echo "MACAddress=$WIRELESS_BOOTIF" - echo "Path=pci*" - echo - # Currently the boot interface is configured to either: - # * static ip as given by the initial DHCP during PXE - # * bridged - # * vlan-tagged (ethernet interface not configured) - # In particular, configuring both vlan tags and the physical - # interface is not supported (might be needed in some setups) - echo [Network] - if [[ "$BRIDGED" != '' ]]; then - echo "Bridge=$BRIDGE_NAME" - elif [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then - print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" - elif [[ "$VLAN" != '' ]]; then - echo "VLAN=$BOOTIF_NAME.$VLAN" - else - echo DHCP=ipv4 - fi - cat << EOF -LinkLocalAddressing=no -IPv6AcceptRA=no - -[DHCP] -UseDNS=true -UseDomains=true -UseHostname=true -CriticalConnection=true -EOF - ) > "$WIRELESS_BOOTIF_NETWORK_CONF" - cat << EOF > "/etc/systemd/network/$WIRELESS_BOOTIF_NAME.link" -[Match] -MACAddress=$WIRELESS_BOOTIF - -[Link] -Description=Critical wireless network device. -Name=$WIRELESS_BOOTIF_NAME -EOF - fi - if [[ "$VLAN" != '' ]]; then - local VLAN_DEV_CONF="/etc/systemd/network/$BOOTIF_NAME.$VLAN.netdev" - cat << EOF > "$VLAN_DEV_CONF" -[NetDev] -Name=$BOOTIF_NAME.$VLAN -MACAddress=$BOOTIF -Kind=vlan - -[VLAN] -Id=$VLAN -EOF - fi - if [[ "$VLAN" != '' ]]; then - # Configure the vlan tagged interface for DHCPv4, TODO IPv6 - local VLAN_NETWORK_CONF="/etc/systemd/network/$BOOTIF_NAME.$VLAN.network" - cat << EOF > "$VLAN_NETWORK_CONF" -[Match] -Name=$BOOTIF_NAME.$VLAN -Type=vlan - -[Link] -MACAddress=$BOOTIF - -[Network] -DHCP=ipv4 -LinkLocalAddressing=no - -[DHCP] -UseDNS=true -UseDomains=true -UseHostname=true -CriticalConnection=true -EOF - fi - # bridge setup - if [[ "$BRIDGED" != '' ]]; then - local BRIDGE_DEV_CONF="/etc/systemd/network/$BRIDGE_NAME.netdev" - cat << EOF > "$BRIDGE_DEV_CONF" -[NetDev] -Name=$BRIDGE_NAME -Kind=bridge -MACAddress=$BOOTIF -EOF - - local BRIDGE_NETWORK_CONF="/etc/systemd/network/$BRIDGE_NAME.network" - ( - echo [Match] - echo "Name=$BRIDGE_NAME" - echo - echo [Network] - if [ -n "$CLIENT_IP" -a -n "$GATEWAY_IP" ]; then - print_static_ip_conf "$CLIENT_IP/${CIDR:-24}" "$GATEWAY_IP" - else - # bad/no IP info, fallback to DHCP - echo DHCP=ipv4 - fi - echo LinkLocalAddressing=no - ) > "$BRIDGE_NETWORK_CONF" - fi - return 0 -} -# from parse-ip-opts.sh -# Takes a netmask and outputs the corresponding CIDR -# e.g. -# mask2cidr 255.255.255.0 -# returns: 24 -mask2cidr() { - local -i bits=0 - for octet in ${1//./ }; do - for i in {0..8}; do - if [ "$octet" = $(( 256 - (1 << i) )) ]; then - bits+=$((8-i)) - break - fi - done - if (( $i == 8 )) && (( $octet != 0 )); then - warn Bad netmask $mask - return - fi - if (( $i > 0 )); then - break - fi - done - echo $bits -} - -## MAIN ## -# Get IP config from KCL -parse_kernel_command_line - -# Save IP config for later use -save_ip_config - -# Create the udev rule to rename the boot interface to the declared BOOTIF_NAME -# Create udev rule to rename the PXE boot interface to BOOTIF_NAME -if [[ "$BOOTIF" != '' ]] && [[ "$BOOTIF" != false ]]; then - # priority 70 < 80-net-name-slot.rules. - echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'$BOOTIF'", NAME="'$BOOTIF_NAME'"' \ - > /etc/udev/rules.d/70-pxe-boot-interface.rules -fi -if [[ "$WIRELESS_BOOTIF" != '' ]] && [[ "$WIRELESS_BOOTIF" != false ]]; then - # priority 70 < 80-net-name-slot.rules. - echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="'$WIRELESS_BOOTIF'", NAME="'$WIRELESS_BOOTIF_NAME'"' \ - > /etc/udev/rules.d/70-pxe-wireless-boot-interface.rules -fi - -# Generate config files for networkd -generate_networkd_config || \ - emergency_shell "Failed to generate networkd configuration." diff --git a/modules.d/systemd-networkd-ext/hooks/prepare-network-service-in-newroot.sh b/modules.d/systemd-networkd-ext/hooks/prepare-network-service-in-newroot.sh new file mode 100755 index 00000000..5ed9a835 --- /dev/null +++ b/modules.d/systemd-networkd-ext/hooks/prepare-network-service-in-newroot.sh @@ -0,0 +1,149 @@ +#!/bin/bash + +source /usr/lib/configure-logging.sh +source /run/openslx/pxe-network.conf + +# This hook copies the core systemd-networkd related service +# files to the NEWROOT and activate them in sysinit.target +# to prevent systemd from killing these while pivot_root +NEWROOT_SYSTEMD_DIR="$NEWROOT/usr/lib/systemd/system" +NEWROOT_SYSINIT_TARGET_DIR="$NEWROOT_SYSTEMD_DIR/sysinit.target.wants" +mkdir --parents "$NEWROOT_SYSINIT_TARGET_DIR" + +if $SLX_ONLINE; then + bl.logging.info Remove known network services. + for service_name in \ + systemd-networkd \ + systemd-resolved + do + path="$NEWROOT/etc/systemd/system/multi-user.target.wants/$service_name.service" + if rm "$path" &>/dev/null; then + bl.logging.info \ + Removing known redundant network service from target system at \ + "$path". + fi + done + # NOTE: We remove known target configurations if "$SLX_WIRELESS_MAC" is to + # "false". + if [[ "$SLX_WIRELESS_MAC" != '' ]]; then + path="$NEWROOT/etc/systemd/system/multi-user.target.wants/iwd.service" + if rm "$path" &>/dev/null; then + bl.logging.info \ + Removing known redundant network service from target system \ + at \"$path\". + fi + for service_name in \ + netctl \ + netctl-auto \ + wpa_supplicant + do + path="$NEWROOT/etc/systemd/system/multi-user.target.wants/$service_name"*.service + # NOTE: Do not use quotes here to allow bash expansion. + if rm $path &>/dev/null; then + bl.logging.info \ + Removing knonw redundant device specific service from \ + target system at \"$path\". + fi + done + fi + bl.logging.info Move running network services into new system. + for service_name in \ + systemd-networkd.service \ + systemd-networkd.socket \ + systemd-resolved.service + do + service_file_path="$( + systemctl show --property FragmentPath $service_name | \ + cut --characters 14-)" + mkdir --parents "$NEWROOT/${service_file_path%/*}" + bl.logging.info \ + Copy initramfs service "$service_file_path" to \ + "$NEWROOT/$service_file_path". + cp "$service_file_path" "$NEWROOT/$service_file_path" + bl.logging.info \ + Link service "$service_file_path" to \ + "$NEWROOT_SYSINIT_TARGET_DIR/$service_name". + ln \ + --force \ + --symbolic \ + "$service_file_path" \ + "$NEWROOT_SYSINIT_TARGET_DIR/$service_name" + done + if \ + [[ "$SLX_WIRELESS_MAC" != '' ]] && \ + [[ "$SLX_WIRELESS_MAC" != false ]] + then + service_name=wpa_supplicant@wireless.service + #service_name=iwd.service + service_file_path="$( + systemctl show --property FragmentPath "$service_name" | \ + cut --characters 14-)" + mkdir --parents "$NEWROOT/${service_file_path%/*}" + bl.logging.info \ + Copy initramfs service "$service_file_path" to \ + "$NEWROOT/$service_file_path". + cp "$service_file_path" "$NEWROOT/$service_file_path" + bl.logging.info \ + Copy initramfs service \ + \"/usr/lib/systemd/system/restart-wireless-daemon.service\" to \ + \"$NEWROOT/usr/lib/systemd/system/restart-wireless-daemon.service\". + cp \ + /usr/lib/systemd/system/restart-wireless-daemon.service \ + "$NEWROOT/usr/lib/systemd/system/restart-wireless-daemon.service" + bl.logging.info \ + Link service \"restart-wireless-daemon\" to \ + \"$NEWROOT/usr/lib/systemd/system/multi-user.target.wants/restart-wireless-daemon.service\". + # Systemd version to restart wireless daemon could hang due to its + # concurrent block device input output nature. + #ln \ + # --force \ + # --symbolic \ + # ../restart-wireless-daemon.service \ + # "$NEWROOT/usr/lib/systemd/system/multi-user.target.wants/restart-wireless-daemon.service" + # Login to tty1 version, works: + echo -e "[ ! -f /tmp/wireless-daemon-restarted ] && systemctl start restart-wireless-daemon.service && touch /tmp/wireless-daemon-restarted\n$(cat "$NEWROOT/root/.bash_profile")" \ + > "$NEWROOT/root/.bash_profile" + # Stops daemon at boot yet. + #bl.logging.info \ + # Link service \"$service_file_path\" to \ + # \"$NEWROOT_SYSINIT_TARGET_DIR/$service_name\". + #ln \ + # --force \ + # --symbolic \ + # "$service_file_path" \ + # "$NEWROOT_SYSINIT_TARGET_DIR/$service_name" + # Enable "wpa_supplicant" service to be able to restart after pivot-root. + sed \ + --in-place \ + --regexp-extended \ + 's:(/((usr/(bin|lib))|(etc))[^ ]+):/run/initramfs\1:g' \ + "$NEWROOT/$service_file_path" + sed \ + --in-place \ + --regexp-extended \ + 's:^(ExecStart=.+)$:ExecStartPre=-/run/initramfs/usr/bin/rm /run/wpa_supplicant/%I\n\1\nExecStartPost=/run/initramfs/usr/bin/touch /mnt/slx_writable_device/booted_to_wlan:' \ + "$NEWROOT/$service_file_path" + # Enable "iwd" service to be able to restart after pivot-root. + #sed \ + # --in-place \ + # --regexp-extended \ + # 's:^(ExecStart=)(/usr/bin/.+) (/usr/lib/iwd/iwd$):ExecStartPre=-/run/initramfs/usr/bin/rm /run/iwd/wireless\n\1/run/initramfs\2 /run/initramfs\3\nExecStartPost=/run/initramfs/usr/bin/touch /mnt/slx_writable_device/booted_to_wlan:' \ + # "$NEWROOT/$service_file_path" + fi + rm --force --recursive "$NEWROOT/etc/systemd/network/"* + if [ -f "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service" ]; then + # this drop-in is needed to prevent a pull-in loop sysinit.target <-> basic.target + mkdir --parents "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service.d" + cat << EOF > "$NEWROOT_SYSTEMD_DIR/systemd-resolved.service.d/00-no-default-deps.conf" +[Unit] +DefaultDependencies=no +EOF + # NOTE: Make sure the NEWROOT resolv.conf links to the one managed by + # "systemd-resolved". + ln \ + --force \ + --symbolic \ + /run/systemd/resolve/resolv.conf \ + "$NEWROOT/etc/resolv.conf" + fi +fi diff --git a/modules.d/systemd-networkd-ext/module-setup.sh b/modules.d/systemd-networkd-ext/module-setup.sh index 4dabb8f0..38bb2014 100755 --- a/modules.d/systemd-networkd-ext/module-setup.sh +++ b/modules.d/systemd-networkd-ext/module-setup.sh @@ -391,9 +391,9 @@ EOF # 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" + inst_hook cmdline 10 "$moddir/hooks/convert-kcl-network-configuration-to-systemd-service-files.sh" inst_hook pre-mount 00 "$moddir/hooks/wait-for-network.sh" - inst_hook pre-pivot 10 "$moddir/hooks/copy-networkd-files-to-newroot.sh" + inst_hook pre-pivot 10 "$moddir/hooks/prepare-network-service-in-newroot.sh" inst_hook pre-pivot 20 "$moddir/hooks/configure-dhcp-for-newroot.sh" } -- cgit v1.2.3-55-g7522