boot.initrd.network: Support DHCP

This allows us to use it for EC2 instances.

+88 -48
+52 -15
nixos/modules/system/boot/initrd-network.nix
··· 6 7 cfg = config.boot.initrd.network; 8 9 in 10 11 { ··· 16 type = types.bool; 17 default = false; 18 description = '' 19 - Add network connectivity support to initrd. 20 - 21 - Network options are configured via <literal>ip</literal> kernel 22 - option, according to the kernel documentation. 23 ''; 24 }; 25 ··· 43 copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig 44 ''; 45 46 - boot.initrd.preLVMCommands = '' 47 - # Search for interface definitions in command line 48 - for o in $(cat /proc/cmdline); do 49 - case $o in 50 - ip=*) 51 - ipconfig $o && hasNetwork=1 52 - ;; 53 - esac 54 - done 55 56 - ${cfg.postCommands} 57 - ''; 58 59 }; 60
··· 6 7 cfg = config.boot.initrd.network; 8 9 + udhcpcScript = pkgs.writeScript "udhcp-script" 10 + '' 11 + #! /bin/sh 12 + if [ "$1" = bound ]; then 13 + ip address add "$ip/$mask" dev "$interface" 14 + if [ -n "$router" ]; then 15 + ip route add default via "$router" dev "$interface" 16 + fi 17 + if [ -n "$dns" ]; then 18 + rm -f /etc/resolv.conf 19 + for i in $dns; do 20 + echo "nameserver $dns" >> /etc/resolv.conf 21 + done 22 + fi 23 + fi 24 + ''; 25 + 26 in 27 28 { ··· 33 type = types.bool; 34 default = false; 35 description = '' 36 + Add network connectivity support to initrd. The network may be 37 + configured using the <literal>ip</literal> kernel parameter, 38 + as described in <link 39 + xlink:href="https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt">the 40 + kernel documentation</link>. Otherwise, if 41 + <option>networking.useDHCP</option> is enabled, an IP address 42 + is acquired using DHCP. 43 ''; 44 }; 45 ··· 63 copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig 64 ''; 65 66 + boot.initrd.preLVMCommands = 67 + # Search for interface definitions in command line. 68 + '' 69 + for o in $(cat /proc/cmdline); do 70 + case $o in 71 + ip=*) 72 + ipconfig $o && hasNetwork=1 73 + ;; 74 + esac 75 + done 76 + '' 77 + 78 + # Otherwise, use DHCP. 79 + + optionalString config.networking.useDHCP '' 80 + if [ -z "$hasNetwork" ]; then 81 + 82 + # Bring up all interfaces. 83 + for iface in $(cd /sys/class/net && ls); do 84 + echo "bringing up network interface $iface..." 85 + ip link set "$iface" up 86 + done 87 + 88 + # Acquire a DHCP lease. 89 + echo "acquiring IP address via DHCP..." 90 + udhcpc --quit --now --script ${udhcpcScript} 91 + fi 92 + '' 93 94 + + cfg.postCommands; 95 96 }; 97
+5 -29
nixos/modules/virtualisation/amazon-image.nix
··· 8 9 with lib; 10 11 - let 12 - 13 - cfg = config.ec2; 14 - 15 - udhcpcScript = pkgs.writeScript "udhcp-script" 16 - '' 17 - #! /bin/sh 18 - if [ "$1" = bound ]; then 19 - ip address add "$ip/$mask" dev "$interface" 20 - if [ -n "$router" ]; then 21 - ip route add default via "$router" dev "$interface" 22 - fi 23 - if [ -n "$dns" ]; then 24 - rm -f /etc/resolv.conf 25 - for i in $dns; do 26 - echo "nameserver $dns" >> /etc/resolv.conf 27 - done 28 - fi 29 - fi 30 - ''; 31 - 32 - in 33 34 { 35 imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-grow-partition.nix ./amazon-init.nix ]; ··· 41 autoResize = true; 42 }; 43 44 - boot.initrd.kernelModules = 45 - [ "xen-blkfront" "xen-netfront" 46 - "af_packet" # <- required by udhcpc 47 - ]; 48 boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ]; 49 50 # Prevent the nouveau kernel module from being loaded, as it ··· 67 kill -9 -1 68 ''; 69 70 # Mount all formatted ephemeral disks and activate all swap devices. 71 # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options 72 # because the set of devices is dependent on the instance type ··· 79 boot.initrd.postMountCommands = 80 '' 81 metaDir=$targetRoot/etc/ec2-metadata 82 - mkdir -m 0755 $targetRoot/etc 83 mkdir -m 0700 -p "$metaDir" 84 85 echo "getting EC2 instance metadata..." 86 - ip link set eth0 up 87 - udhcpc --interface eth0 --quit --now --script ${udhcpcScript} 88 89 if ! [ -e "$metaDir/ami-manifest-path" ]; then 90 wget -q -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
··· 8 9 with lib; 10 11 + let cfg = config.ec2; in 12 13 { 14 imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-grow-partition.nix ./amazon-init.nix ]; ··· 20 autoResize = true; 21 }; 22 23 + boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ]; 24 boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ]; 25 26 # Prevent the nouveau kernel module from being loaded, as it ··· 43 kill -9 -1 44 ''; 45 46 + boot.initrd.network.enable = true; 47 + 48 # Mount all formatted ephemeral disks and activate all swap devices. 49 # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options 50 # because the set of devices is dependent on the instance type ··· 57 boot.initrd.postMountCommands = 58 '' 59 metaDir=$targetRoot/etc/ec2-metadata 60 + mkdir -m 0755 -p $targetRoot/etc 61 mkdir -m 0700 -p "$metaDir" 62 63 echo "getting EC2 instance metadata..." 64 65 if ! [ -e "$metaDir/ami-manifest-path" ]; then 66 wget -q -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path
+1
nixos/release.nix
··· 248 tests.ipv6 = callTest tests/ipv6.nix {}; 249 tests.jenkins = callTest tests/jenkins.nix {}; 250 tests.kde4 = callTest tests/kde4.nix {}; 251 tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; }); 252 tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; }; 253 #tests.lightdm = callTest tests/lightdm.nix {};
··· 248 tests.ipv6 = callTest tests/ipv6.nix {}; 249 tests.jenkins = callTest tests/jenkins.nix {}; 250 tests.kde4 = callTest tests/kde4.nix {}; 251 + tests.initrdNetwork = callTest tests/initrd-network.nix {}; 252 tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; }); 253 tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; }; 254 #tests.lightdm = callTest tests/lightdm.nix {};
+8 -4
nixos/tests/ec2.nix
··· 10 inherit system; 11 modules = [ 12 ../maintainers/scripts/ec2/amazon-image.nix 13 - ../../nixos/modules/testing/test-instrumentation.nix 14 - { boot.initrd.kernelModules = [ "virtio" "virtio_blk" "virtio_pci" "virtio_ring" ]; 15 - ec2.hvm = true; 16 17 # Hack to make the partition resizing work in QEMU. 18 boot.initrd.postDeviceCommands = mkBefore ··· 33 ln -s ${pkgs.writeText "userData" userData} $out/2011-01-01/user-data 34 mkdir -p $out/1.0/meta-data 35 echo "${hostname}" > $out/1.0/meta-data/hostname 36 '' + optionalString (sshPublicKey != null) '' 37 mkdir -p $out/1.0/meta-data/public-keys/0 38 ln -s ${pkgs.writeText "sshPublicKey" sshPublicKey} $out/1.0/meta-data/public-keys/0/openssh-key ··· 56 # again when it deletes link-local addresses.) Ideally we'd 57 # turn off the DHCP server, but qemu does not have an option 58 # to do that. 59 - my $startCommand = "qemu-kvm -m 768 -net nic -net 'user,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'"; 60 $startCommand .= " -drive file=$diskImage,if=virtio,werror=report"; 61 $startCommand .= " \$QEMU_OPTS"; 62 ··· 91 $machine->start; 92 $machine->waitForFile("/root/user-data"); 93 $machine->waitForUnit("sshd.service"); 94 95 # We have no keys configured on the client side yet, so this should fail 96 $machine->fail("ssh -o BatchMode=yes localhost exit");
··· 10 inherit system; 11 modules = [ 12 ../maintainers/scripts/ec2/amazon-image.nix 13 + ../modules/testing/test-instrumentation.nix 14 + ../modules/profiles/minimal.nix 15 + ../modules/profiles/qemu-guest.nix 16 + { ec2.hvm = true; 17 18 # Hack to make the partition resizing work in QEMU. 19 boot.initrd.postDeviceCommands = mkBefore ··· 34 ln -s ${pkgs.writeText "userData" userData} $out/2011-01-01/user-data 35 mkdir -p $out/1.0/meta-data 36 echo "${hostname}" > $out/1.0/meta-data/hostname 37 + echo "(unknown)" > $out/1.0/meta-data/ami-manifest-path 38 '' + optionalString (sshPublicKey != null) '' 39 mkdir -p $out/1.0/meta-data/public-keys/0 40 ln -s ${pkgs.writeText "sshPublicKey" sshPublicKey} $out/1.0/meta-data/public-keys/0/openssh-key ··· 58 # again when it deletes link-local addresses.) Ideally we'd 59 # turn off the DHCP server, but qemu does not have an option 60 # to do that. 61 + my $startCommand = "qemu-kvm -m 768 -net nic,vlan=0,model=virtio -net 'user,vlan=0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'"; 62 $startCommand .= " -drive file=$diskImage,if=virtio,werror=report"; 63 $startCommand .= " \$QEMU_OPTS"; 64 ··· 93 $machine->start; 94 $machine->waitForFile("/root/user-data"); 95 $machine->waitForUnit("sshd.service"); 96 + 97 + $machine->succeed("grep unknown /etc/ec2-metadata/ami-manifest-path"); 98 99 # We have no keys configured on the client side yet, so this should fail 100 $machine->fail("ssh -o BatchMode=yes localhost exit");
+22
nixos/tests/initrd-network.nix
···
··· 1 + import ./make-test.nix ({ pkgs, ...} : { 2 + name = "initrd-network"; 3 + 4 + meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ]; 5 + 6 + machine = { config, pkgs, ... }: { 7 + imports = [ ../modules/profiles/minimal.nix ]; 8 + boot.initrd.network.enable = true; 9 + boot.initrd.network.postCommands = 10 + '' 11 + ip addr | grep 10.0.2.15 || exit 1 12 + ping -c1 10.0.2.2 || exit 1 13 + ''; 14 + }; 15 + 16 + testScript = 17 + '' 18 + startAll; 19 + $machine->waitForUnit("multi-user.target"); 20 + $machine->succeed("ip link >&2"); 21 + ''; 22 + })