0
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-07-14 06:00:33 +03:00

Merge pull request #79532 from NixOS/fix-predictable-ifnames-in-initrd

nixos/stage-1: fix predictable interface names in initrd
This commit is contained in:
Maximilian Bosch 2020-03-02 17:14:06 +01:00 committed by GitHub
commit 70325e63d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 39 deletions

View file

@ -6,7 +6,11 @@ let
cfg = config.boot.initrd.network; cfg = config.boot.initrd.network;
dhcpinterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {})); dhcpInterfaces = lib.attrNames (lib.filterAttrs (iface: v: v.useDHCP == true) (config.networking.interfaces or {}));
doDhcp = config.networking.useDHCP || dhcpInterfaces != [];
dhcpIfShellExpr = if config.networking.useDHCP
then "$(ls /sys/class/net/ | grep -v ^lo$)"
else lib.concatMapStringsSep " " lib.escapeShellArg dhcpInterfaces;
udhcpcScript = pkgs.writeScript "udhcp-script" udhcpcScript = pkgs.writeScript "udhcp-script"
'' ''
@ -62,6 +66,16 @@ in
''; '';
}; };
boot.initrd.network.flushBeforeStage2 = mkOption {
type = types.bool;
default = true;
description = ''
Whether to clear the configuration of the interfaces that were set up in
the initrd right before stage 2 takes over. Stage 2 will do the regular network
configuration based on the NixOS networking options.
'';
};
boot.initrd.network.udhcpc.extraArgs = mkOption { boot.initrd.network.udhcpc.extraArgs = mkOption {
default = []; default = [];
type = types.listOf types.str; type = types.listOf types.str;
@ -89,49 +103,45 @@ in
boot.initrd.kernelModules = [ "af_packet" ]; boot.initrd.kernelModules = [ "af_packet" ];
boot.initrd.extraUtilsCommands = '' boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig copy_bin_and_libs ${pkgs.klibc}/lib/klibc/bin.static/ipconfig
''; '';
boot.initrd.preLVMCommands = mkBefore ( boot.initrd.preLVMCommands = mkBefore (
# Search for interface definitions in command line. # Search for interface definitions in command line.
'' ''
ifaces=""
for o in $(cat /proc/cmdline); do for o in $(cat /proc/cmdline); do
case $o in case $o in
ip=*) ip=*)
ipconfig $o && hasNetwork=1 ipconfig $o && ifaces="$ifaces $(echo $o | cut -d: -f6)"
;; ;;
esac esac
done done
'' ''
# Otherwise, use DHCP. # Otherwise, use DHCP.
+ optionalString (config.networking.useDHCP || dhcpinterfaces != []) '' + optionalString doDhcp ''
if [ -z "$hasNetwork" ]; then # Bring up all interfaces.
for iface in ${dhcpIfShellExpr}; do
echo "bringing up network interface $iface..."
ip link set "$iface" up && ifaces="$ifaces $iface"
done
# Bring up all interfaces. # Acquire DHCP leases.
for iface in $(ls /sys/class/net/); do for iface in ${dhcpIfShellExpr}; do
echo "bringing up network interface $iface..." echo "acquiring IP address via DHCP on $iface..."
ip link set "$iface" up udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs}
done done
# Acquire DHCP leases.
for iface in ${ if config.networking.useDHCP then
"$(ls /sys/class/net/ | grep -v ^lo$)"
else
lib.concatMapStringsSep " " lib.escapeShellArg dhcpinterfaces
}; do
echo "acquiring IP address via DHCP on $iface..."
udhcpc --quit --now -i $iface -O staticroutes --script ${udhcpcScript} ${udhcpcArgs} && hasNetwork=1
done
fi
'' ''
+ '' + cfg.postCommands);
if [ -n "$hasNetwork" ]; then
echo "networking is up!" boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
${cfg.postCommands} for iface in $ifaces; do
fi ip address flush "$iface"
''); ip link down "$iface"
done
'';
}; };

View file

@ -210,6 +210,8 @@ done
# Create device nodes in /dev. # Create device nodes in /dev.
@preDeviceCommands@ @preDeviceCommands@
echo "running udev..." echo "running udev..."
mkdir -p /etc/systemd
ln -sfn @linkUnits@ /etc/systemd/network
mkdir -p /etc/udev mkdir -p /etc/udev
ln -sfn @udevRules@ /etc/udev/rules.d ln -sfn @udevRules@ /etc/udev/rules.d
mkdir -p /dev/.mdadm mkdir -p /dev/.mdadm
@ -266,7 +268,7 @@ checkFS() {
return 0 return 0
fi fi
# Device might be already mounted manually # Device might be already mounted manually
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs # e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
if mount | grep -q "^$device on "; then if mount | grep -q "^$device on "; then
echo "skip checking already mounted $device" echo "skip checking already mounted $device"
@ -351,7 +353,7 @@ mountFS() {
elif [ "$fsType" = f2fs ]; then elif [ "$fsType" = f2fs ]; then
echo "resizing $device..." echo "resizing $device..."
fsck.f2fs -fp "$device" fsck.f2fs -fp "$device"
resize.f2fs "$device" resize.f2fs "$device"
fi fi
;; ;;
esac esac

View file

@ -120,6 +120,7 @@ let
# Copy udev. # Copy udev.
copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
copy_bin_and_libs ${udev}/bin/udevadm copy_bin_and_libs ${udev}/bin/udevadm
for BIN in ${udev}/lib/udev/*_id; do for BIN in ${udev}/lib/udev/*_id; do
copy_bin_and_libs $BIN copy_bin_and_libs $BIN
@ -198,6 +199,14 @@ let
''; # */ ''; # */
linkUnits = pkgs.runCommand "link-units" {
allowedReferences = [ extraUtils ];
preferLocalBuild = true;
} ''
mkdir -p $out
cp -v ${udev}/lib/systemd/network/*.link $out/
'';
udevRules = pkgs.runCommand "udev-rules" { udevRules = pkgs.runCommand "udev-rules" {
allowedReferences = [ extraUtils ]; allowedReferences = [ extraUtils ];
preferLocalBuild = true; preferLocalBuild = true;
@ -208,7 +217,9 @@ let
cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/ cp -v ${udev}/lib/udev/rules.d/60-cdrom_id.rules $out/
cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/ cp -v ${udev}/lib/udev/rules.d/60-persistent-storage.rules $out/
cp -v ${udev}/lib/udev/rules.d/75-net-description.rules $out/
cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/ cp -v ${udev}/lib/udev/rules.d/80-drivers.rules $out/
cp -v ${udev}/lib/udev/rules.d/80-net-setup-link.rules $out/
cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/ cp -v ${pkgs.lvm2}/lib/udev/rules.d/*.rules $out/
${config.boot.initrd.extraUdevRulesCommands} ${config.boot.initrd.extraUdevRulesCommands}
@ -222,7 +233,7 @@ let
--replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \ --replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \ --replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \ --replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
--replace ${udev}/bin/udevadm ${extraUtils}/bin/udevadm --replace ${udev} ${extraUtils}
done done
# Work around a bug in QEMU, which doesn't implement the "READ # Work around a bug in QEMU, which doesn't implement the "READ
@ -257,7 +268,7 @@ let
${pkgs.buildPackages.busybox}/bin/ash -n $target ${pkgs.buildPackages.busybox}/bin/ash -n $target
''; '';
inherit udevRules extraUtils modulesClosure; inherit linkUnits udevRules extraUtils modulesClosure;
inherit (config.boot) resumeDevice; inherit (config.boot) resumeDevice;

View file

@ -1,4 +1,4 @@
import ./make-test-python.nix ({ pkgs, ...} : { import ./make-test-python.nix ({ pkgs, lib, ...} : {
name = "initrd-network"; name = "initrd-network";
meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ]; meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ];
@ -8,15 +8,26 @@ import ./make-test-python.nix ({ pkgs, ...} : {
boot.initrd.network.enable = true; boot.initrd.network.enable = true;
boot.initrd.network.postCommands = boot.initrd.network.postCommands =
'' ''
ip addr show
ip route show
ip addr | grep 10.0.2.15 || exit 1 ip addr | grep 10.0.2.15 || exit 1
ping -c1 10.0.2.2 || exit 1 ping -c1 10.0.2.2 || exit 1
''; '';
# Check if cleanup was done correctly
boot.initrd.postMountCommands = lib.mkAfter
''
ip addr show
ip route show
ip addr | grep 10.0.2.15 && exit 1
ping -c1 10.0.2.2 && exit 1
'';
}; };
testScript = testScript =
'' ''
start_all() start_all()
machine.wait_for_unit("multi-user.target") machine.wait_for_unit("multi-user.target")
machine.succeed("ip link >&2") machine.succeed("ip addr show >&2")
machine.succeed("ip route show >&2")
''; '';
}) })

View file

@ -17,6 +17,12 @@ in pkgs.lib.listToAttrs (pkgs.lib.crossLists (predictable: withNetworkd: {
networking.useNetworkd = withNetworkd; networking.useNetworkd = withNetworkd;
networking.dhcpcd.enable = !withNetworkd; networking.dhcpcd.enable = !withNetworkd;
networking.useDHCP = !withNetworkd; networking.useDHCP = !withNetworkd;
# Check if predictable interface names are working in stage-1
boot.initrd.postDeviceCommands = ''
ip link
ip link show eth0 ${if predictable then "&&" else "||"} exit 1
'';
}; };
testScript = '' testScript = ''

View file

@ -1,4 +1,4 @@
{ stdenv, fetchurl, linuxHeaders, perl }: { lib, stdenv, fetchurl, linuxHeaders, perl }:
let let
commonMakeFlags = [ commonMakeFlags = [
@ -9,11 +9,11 @@ in
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
pname = "klibc"; pname = "klibc";
version = "2.0.4"; version = "2.0.7";
src = fetchurl { src = fetchurl {
url = "mirror://kernel/linux/libs/klibc/2.0/klibc-${version}.tar.xz"; url = "mirror://kernel/linux/libs/klibc/2.0/klibc-${version}.tar.xz";
sha256 = "7f9a0850586def7cf4faeeb75e5d0f66e613674c524f6e77b0f4d93a26c801cb"; sha256 = "08li3aj9bvzabrih98jdxi3m19h85cp53s8cr7cqad42r8vjdvxb";
}; };
patches = [ ./no-reinstall-kernel-headers.patch ]; patches = [ ./no-reinstall-kernel-headers.patch ];
@ -35,7 +35,6 @@ stdenv.mkDerivation rec {
dir=$out/lib/klibc/bin.static dir=$out/lib/klibc/bin.static
mkdir $dir mkdir $dir
cp $(find $(find . -name static) -type f ! -name "*.g" -a ! -name ".*") $dir/ cp $(find $(find . -name static) -type f ! -name "*.g" -a ! -name ".*") $dir/
cp usr/dash/sh $dir/
for file in ${linuxHeaders}/include/*; do for file in ${linuxHeaders}/include/*; do
ln -sv $file $out/lib/klibc/include ln -sv $file $out/lib/klibc/include
@ -43,6 +42,10 @@ stdenv.mkDerivation rec {
''; '';
meta = { meta = {
platforms = [ "x86_64-linux" ]; description = "Minimalistic libc subset for initramfs usage";
homepage = "https://kernel.org/pub/linux/libs/klibc/";
maintainers = with lib.maintainers; [ fpletz ];
license = lib.licenses.bsd3;
platforms = lib.platforms.linux;
}; };
} }

View file

@ -5,7 +5,7 @@ diff -Naur klibc-2.0.3-orig/scripts/Kbuild.install klibc-2.0.3/scripts/Kbuild.in
$(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include
$(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)lib $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)lib
$(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)bin $(Q)mkdir -p $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)bin
- $(Q)$(MAKE) -C $(KLIBCKERNELSRC) ARCH=$(KLIBCARCH) INSTALL_HDR_PATH=$(INSTALLROOT)$(INSTALLDIR)/$(KCROSS) headers_install - $(Q)cp -rfL $(KLIBCKERNELSRC)/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/.
$(Q)cp -rf usr/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/. $(Q)cp -rf usr/include/. $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include/.
$(Q)chmod -R a+rX $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include $(Q)chmod -R a+rX $(INSTALLROOT)$(INSTALLDIR)/$(KCROSS)include
$(Q)$(install-data) $(srctree)/klcc/klcc.1 $(INSTALLROOT)$(mandir)/man1/$(KCROSS)klcc.1 $(Q)$(install-data) $(srctree)/klcc/klcc.1 $(INSTALLROOT)$(mandir)/man1/$(KCROSS)klcc.1