From cc925d0506ab2a049d5ee55c1173950073ed307f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 2 Feb 2016 19:03:13 +0100 Subject: [PATCH] boot.initrd.network: Support DHCP This allows us to use it for EC2 instances. --- nixos/modules/system/boot/initrd-network.nix | 67 ++++++++++++++----- nixos/modules/virtualisation/amazon-image.nix | 34 ++-------- nixos/release.nix | 1 + nixos/tests/ec2.nix | 12 ++-- nixos/tests/initrd-network.nix | 22 ++++++ 5 files changed, 88 insertions(+), 48 deletions(-) create mode 100644 nixos/tests/initrd-network.nix diff --git a/nixos/modules/system/boot/initrd-network.nix b/nixos/modules/system/boot/initrd-network.nix index e1e49bce693..abf88734a55 100644 --- a/nixos/modules/system/boot/initrd-network.nix +++ b/nixos/modules/system/boot/initrd-network.nix @@ -6,6 +6,23 @@ let cfg = config.boot.initrd.network; + udhcpcScript = pkgs.writeScript "udhcp-script" + '' + #! /bin/sh + if [ "$1" = bound ]; then + ip address add "$ip/$mask" dev "$interface" + if [ -n "$router" ]; then + ip route add default via "$router" dev "$interface" + fi + if [ -n "$dns" ]; then + rm -f /etc/resolv.conf + for i in $dns; do + echo "nameserver $dns" >> /etc/resolv.conf + done + fi + fi + ''; + in { @@ -16,10 +33,13 @@ in type = types.bool; default = false; description = '' - Add network connectivity support to initrd. - - Network options are configured via ip kernel - option, according to the kernel documentation. + Add network connectivity support to initrd. The network may be + configured using the ip kernel parameter, + as described in the + kernel documentation. Otherwise, if + is enabled, an IP address + is acquired using DHCP. ''; }; @@ -43,18 +63,35 @@ in copy_bin_and_libs ${pkgs.mkinitcpio-nfs-utils}/bin/ipconfig ''; - boot.initrd.preLVMCommands = '' - # Search for interface definitions in command line - for o in $(cat /proc/cmdline); do - case $o in - ip=*) - ipconfig $o && hasNetwork=1 - ;; - esac - done + boot.initrd.preLVMCommands = + # Search for interface definitions in command line. + '' + for o in $(cat /proc/cmdline); do + case $o in + ip=*) + ipconfig $o && hasNetwork=1 + ;; + esac + done + '' - ${cfg.postCommands} - ''; + # Otherwise, use DHCP. + + optionalString config.networking.useDHCP '' + if [ -z "$hasNetwork" ]; then + + # Bring up all interfaces. + for iface in $(cd /sys/class/net && ls); do + echo "bringing up network interface $iface..." + ip link set "$iface" up + done + + # Acquire a DHCP lease. + echo "acquiring IP address via DHCP..." + udhcpc --quit --now --script ${udhcpcScript} + fi + '' + + + cfg.postCommands; }; diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index dd2cdd43f31..7d16206517d 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -8,28 +8,7 @@ with lib; -let - - cfg = config.ec2; - - udhcpcScript = pkgs.writeScript "udhcp-script" - '' - #! /bin/sh - if [ "$1" = bound ]; then - ip address add "$ip/$mask" dev "$interface" - if [ -n "$router" ]; then - ip route add default via "$router" dev "$interface" - fi - if [ -n "$dns" ]; then - rm -f /etc/resolv.conf - for i in $dns; do - echo "nameserver $dns" >> /etc/resolv.conf - done - fi - fi - ''; - -in +let cfg = config.ec2; in { imports = [ ../profiles/headless.nix ./ec2-data.nix ./amazon-grow-partition.nix ./amazon-init.nix ]; @@ -41,10 +20,7 @@ in autoResize = true; }; - boot.initrd.kernelModules = - [ "xen-blkfront" "xen-netfront" - "af_packet" # <- required by udhcpc - ]; + boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ]; boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ]; # Prevent the nouveau kernel module from being loaded, as it @@ -67,6 +43,8 @@ in kill -9 -1 ''; + boot.initrd.network.enable = true; + # Mount all formatted ephemeral disks and activate all swap devices. # We cannot do this with the ‘fileSystems’ and ‘swapDevices’ options # because the set of devices is dependent on the instance type @@ -79,12 +57,10 @@ in boot.initrd.postMountCommands = '' metaDir=$targetRoot/etc/ec2-metadata - mkdir -m 0755 $targetRoot/etc + mkdir -m 0755 -p $targetRoot/etc mkdir -m 0700 -p "$metaDir" echo "getting EC2 instance metadata..." - ip link set eth0 up - udhcpc --interface eth0 --quit --now --script ${udhcpcScript} if ! [ -e "$metaDir/ami-manifest-path" ]; then wget -q -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path diff --git a/nixos/release.nix b/nixos/release.nix index 9c15b1ea074..d9f3e46b27c 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -248,6 +248,7 @@ in rec { tests.ipv6 = callTest tests/ipv6.nix {}; tests.jenkins = callTest tests/jenkins.nix {}; tests.kde4 = callTest tests/kde4.nix {}; + tests.initrdNetwork = callTest tests/initrd-network.nix {}; tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; }); tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; }; #tests.lightdm = callTest tests/lightdm.nix {}; diff --git a/nixos/tests/ec2.nix b/nixos/tests/ec2.nix index 1925ab37419..0a95d6cfeff 100644 --- a/nixos/tests/ec2.nix +++ b/nixos/tests/ec2.nix @@ -10,9 +10,10 @@ let inherit system; modules = [ ../maintainers/scripts/ec2/amazon-image.nix - ../../nixos/modules/testing/test-instrumentation.nix - { boot.initrd.kernelModules = [ "virtio" "virtio_blk" "virtio_pci" "virtio_ring" ]; - ec2.hvm = true; + ../modules/testing/test-instrumentation.nix + ../modules/profiles/minimal.nix + ../modules/profiles/qemu-guest.nix + { ec2.hvm = true; # Hack to make the partition resizing work in QEMU. boot.initrd.postDeviceCommands = mkBefore @@ -33,6 +34,7 @@ let ln -s ${pkgs.writeText "userData" userData} $out/2011-01-01/user-data mkdir -p $out/1.0/meta-data echo "${hostname}" > $out/1.0/meta-data/hostname + echo "(unknown)" > $out/1.0/meta-data/ami-manifest-path '' + optionalString (sshPublicKey != null) '' mkdir -p $out/1.0/meta-data/public-keys/0 ln -s ${pkgs.writeText "sshPublicKey" sshPublicKey} $out/1.0/meta-data/public-keys/0/openssh-key @@ -56,7 +58,7 @@ let # again when it deletes link-local addresses.) Ideally we'd # turn off the DHCP server, but qemu does not have an option # to do that. - 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}'"; + 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}'"; $startCommand .= " -drive file=$diskImage,if=virtio,werror=report"; $startCommand .= " \$QEMU_OPTS"; @@ -92,6 +94,8 @@ in { $machine->waitForFile("/root/user-data"); $machine->waitForUnit("sshd.service"); + $machine->succeed("grep unknown /etc/ec2-metadata/ami-manifest-path"); + # We have no keys configured on the client side yet, so this should fail $machine->fail("ssh -o BatchMode=yes localhost exit"); diff --git a/nixos/tests/initrd-network.nix b/nixos/tests/initrd-network.nix new file mode 100644 index 00000000000..db9f572d3c2 --- /dev/null +++ b/nixos/tests/initrd-network.nix @@ -0,0 +1,22 @@ +import ./make-test.nix ({ pkgs, ...} : { + name = "initrd-network"; + + meta.maintainers = [ pkgs.stdenv.lib.maintainers.eelco ]; + + machine = { config, pkgs, ... }: { + imports = [ ../modules/profiles/minimal.nix ]; + boot.initrd.network.enable = true; + boot.initrd.network.postCommands = + '' + ip addr | grep 10.0.2.15 || exit 1 + ping -c1 10.0.2.2 || exit 1 + ''; + }; + + testScript = + '' + startAll; + $machine->waitForUnit("multi-user.target"); + $machine->succeed("ip link >&2"); + ''; +})