diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-05-07 17:00:46 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-05-07 17:53:57 +0200 |
commit | 6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa (patch) | |
tree | c4ced63774765a3b7476d958e1d52c59b7be7cd1 /nixos/modules/virtualisation | |
parent | 810680bcae1f8ca23744544e87fbf03b705e9493 (diff) | |
download | nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar.gz nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar.bz2 nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar.lz nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar.xz nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.tar.zst nixlib-6f7aaf10a5beb6cc10ebe75674d9c8664bd187fa.zip |
Containers: Use systemd-nspawn's --network-veth flag
Note that this causes the name of the host-side interface to change from c-<name> to ve-<name>.
Diffstat (limited to 'nixos/modules/virtualisation')
-rw-r--r-- | nixos/modules/virtualisation/containers.nix | 93 | ||||
-rw-r--r-- | nixos/modules/virtualisation/run-in-netns.c | 50 |
2 files changed, 45 insertions, 98 deletions
diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 7a8c8a4594b5..08c234b94133 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -4,16 +4,6 @@ with lib; let - runInNetns = pkgs.stdenv.mkDerivation { - name = "run-in-netns"; - unpackPhase = "true"; - buildPhase = '' - mkdir -p $out/bin - gcc ${./run-in-netns.c} -o $out/bin/run-in-netns - ''; - installPhase = "true"; - }; - nixos-container = pkgs.substituteAll { name = "nixos-container"; dir = "bin"; @@ -23,6 +13,28 @@ let inherit (pkgs) socat; }; + # The container's init script, a small wrapper around the regular + # NixOS stage-2 init script. + containerInit = pkgs.writeScript "container-init" + '' + #! ${pkgs.stdenv.shell} -e + + # Initialise the container side of the veth pair. + if [ "$PRIVATE_NETWORK" = 1 ]; then + ip link set host0 name eth0 + ip link set dev eth0 up + if [ -n "$HOST_ADDRESS" ]; then + ip route add $HOST_ADDRESS dev eth0 + ip route add default via $HOST_ADDRESS + fi + if [ -n "$LOCAL_ADDRESS" ]; then + ip addr add $LOCAL_ADDRESS dev eth0 + fi + fi + + exec "$1" + ''; + system = config.nixpkgs.system; in @@ -70,7 +82,7 @@ in Whether to give the container its own private virtual Ethernet interface. The interface is called <literal>eth0</literal>, and is hooked up to the interface - <literal>c-<replaceable>container-name</replaceable></literal> + <literal>ve-<replaceable>container-name</replaceable></literal> on the host. If this option is not set, then the container shares the network interfaces of the host, and can bind to any port on any interface. @@ -176,39 +188,8 @@ in "/nix/var/nix/profiles/per-container/$INSTANCE" \ "/nix/var/nix/gcroots/per-container/$INSTANCE" - if [ -f "/etc/containers/$INSTANCE.conf" ]; then - . "/etc/containers/$INSTANCE.conf" - fi - - # Cleanup from last time. - ifaceHost=c-$INSTANCE - ifaceCont=ctmp-$INSTANCE - ns=net-$INSTANCE - ip netns del $ns 2> /dev/null || true - ip link del $ifaceHost 2> /dev/null || true - ip link del $ifaceCont 2> /dev/null || true - if [ "$PRIVATE_NETWORK" = 1 ]; then - # Create a pair of virtual ethernet devices. On the host, - # we get ‘c-<container-name’, and on the guest, we get - # ‘eth0’. - ip link add $ifaceHost type veth peer name $ifaceCont - ip netns add $ns - ip link set $ifaceCont netns $ns - ip netns exec $ns ip link set $ifaceCont name eth0 - ip netns exec $ns ip link set dev eth0 up - ip link set dev $ifaceHost up - if [ -n "$HOST_ADDRESS" ]; then - ip addr add $HOST_ADDRESS dev $ifaceHost - ip netns exec $ns ip route add $HOST_ADDRESS dev eth0 - ip netns exec $ns ip route add default via $HOST_ADDRESS - fi - if [ -n "$LOCAL_ADDRESS" ]; then - ip netns exec $ns ip addr add $LOCAL_ADDRESS dev eth0 - ip route add $LOCAL_ADDRESS dev $ifaceHost - fi - runInNetNs="${runInNetns}/bin/run-in-netns $ns" - extraFlags="--capability=CAP_NET_ADMIN" + extraFlags="--network-veth" fi # If the host is 64-bit and the container is 32-bit, add a @@ -219,7 +200,7 @@ in fi ''} - exec $runInNetNs ${config.systemd.package}/bin/systemd-nspawn \ + exec ${config.systemd.package}/bin/systemd-nspawn \ --keep-unit \ -M "$INSTANCE" -D "$root" $extraFlags \ --bind-ro=/nix/store \ @@ -227,7 +208,11 @@ in --bind-ro=/nix/var/nix/daemon-socket \ --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ - "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init" + --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ + --setenv HOST_ADDRESS="$HOST_ADDRESS" \ + --setenv LOCAL_ADDRESS="$LOCAL_ADDRESS" \ + --setenv PATH="$PATH" \ + ${containerInit} "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init" ''; postStart = @@ -237,6 +222,17 @@ in # until the start timeout expires if systemd-nspawn exits. read x < $root/var/lib/startup-done rm -f $root/var/lib/startup-done + + if [ "$PRIVATE_NETWORK" = 1 ]; then + ifaceHost=ve-$INSTANCE + ip link set dev $ifaceHost up + if [ -n "$HOST_ADDRESS" ]; then + ip addr add $HOST_ADDRESS dev $ifaceHost + fi + if [ -n "$LOCAL_ADDRESS" ]; then + ip route add $LOCAL_ADDRESS dev $ifaceHost + fi + fi ''; preStop = @@ -251,14 +247,13 @@ in '' #! ${pkgs.stdenv.shell} -e SYSTEM_PATH=/nix/var/nix/profiles/system - if [ -f "/etc/containers/$INSTANCE.conf" ]; then - . "/etc/containers/$INSTANCE.conf" - fi echo $SYSTEM_PATH/bin/switch-to-configuration test | \ ${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket - ''; serviceConfig.SyslogIdentifier = "container %i"; + + serviceConfig.EnvironmentFile = "-/etc/containers/%i.conf"; }; # Generate a configuration file in /etc/containers for each @@ -288,6 +283,8 @@ in ${cfg.localAddress} ${name}.containers '') config.containers); + networking.dhcpcd.denyInterfaces = [ "ve-*" ]; + environment.systemPackages = [ nixos-container ]; }; diff --git a/nixos/modules/virtualisation/run-in-netns.c b/nixos/modules/virtualisation/run-in-netns.c deleted file mode 100644 index d375bddf2e6b..000000000000 --- a/nixos/modules/virtualisation/run-in-netns.c +++ /dev/null @@ -1,50 +0,0 @@ -#define _GNU_SOURCE - -#include <stdio.h> -#include <string.h> -#include <errno.h> - -#include <unistd.h> -#include <sched.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mount.h> -#include <fcntl.h> -#include <linux/limits.h> - -int main(int argc, char * * argv) -{ - if (argc < 3) { - fprintf(stderr, "%s: missing arguments\n", argv[0]); - return 1; - } - - char nsPath[PATH_MAX]; - - sprintf(nsPath, "/run/netns/%s", argv[1]); - - int fd = open(nsPath, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "%s: opening network namespace: %s\n", argv[0], strerror(errno)); - return 1; - } - - if (setns(fd, CLONE_NEWNET) == -1) { - fprintf(stderr, "%s: setting network namespace: %s\n", argv[0], strerror(errno)); - return 1; - } - - umount2(nsPath, MNT_DETACH); - if (unlink(nsPath) == -1) { - fprintf(stderr, "%s: unlinking network namespace: %s\n", argv[0], strerror(errno)); - return 1; - } - - /* FIXME: Remount /sys so that /sys/class/net reflects the - interfaces visible in the network namespace. This requires - bind-mounting /sys/fs/cgroups etc. */ - - execv(argv[2], argv + 2); - fprintf(stderr, "%s: running command: %s\n", argv[0], strerror(errno)); - return 1; -} |