import ./make-test-python.nix ( { pkgs, ... }: let listenPort = 30123; testString = "It works!"; mkCreateSmallFileService = { path, loop ? false, }: { script = '' ${pkgs.coreutils}/bin/dd if=/dev/zero of=${path} bs=1K count=100 ${pkgs.lib.optionalString loop "${pkgs.util-linux}/bin/losetup --find ${path}"} ''; serviceConfig = { Type = "oneshot"; }; wantedBy = [ "multi-user.target" ]; before = [ "nbd-server.service" ]; }; in { name = "nbd"; nodes = { server = { config, pkgs, ... }: { # Create some small files of zeros to use as the ndb disks ## `vault-pub.disk` is accessible from any IP systemd.services.create-pub-file = mkCreateSmallFileService { path = "/vault-pub.disk"; }; ## `vault-priv.disk` is accessible only from localhost. ## It's also a loopback device to test exporting /dev/... systemd.services.create-priv-file = mkCreateSmallFileService { path = "/vault-priv.disk"; loop = true; }; ## `aaa.disk` is just here because "[aaa]" sorts before ## "[generic]" lexicographically, and nbd-server breaks if ## "[generic]" isn't the first section. systemd.services.create-aaa-file = mkCreateSmallFileService { path = "/aaa.disk"; }; # Needed only for nbd-client used in the tests. environment.systemPackages = [ pkgs.nbd ]; # Open the nbd port in the firewall networking.firewall.allowedTCPPorts = [ listenPort ]; # Run the nbd server and expose the small file created above services.nbd.server = { enable = true; exports = { aaa = { path = "/aaa.disk"; }; vault-pub = { path = "/vault-pub.disk"; }; vault-priv = { path = "/dev/loop0"; allowAddresses = [ "127.0.0.1" "::1" ]; }; }; listenAddress = "0.0.0.0"; listenPort = listenPort; }; }; client = { config, pkgs, ... }: { programs.nbd.enable = true; }; }; testScript = '' testString = "${testString}" start_all() server.wait_for_open_port(${toString listenPort}) # Client: Connect to the server, write a small string to the nbd disk, and cleanly disconnect client.succeed("nbd-client server ${toString listenPort} /dev/nbd0 -name vault-pub -persist") client.succeed(f"echo '{testString}' | dd of=/dev/nbd0 conv=notrunc") client.succeed("nbd-client -d /dev/nbd0") # Server: Check that the string written by the client is indeed in the file foundString = server.succeed(f"dd status=none if=/vault-pub.disk count={len(testString)}")[:len(testString)] if foundString != testString: raise Exception(f"Read the wrong string from nbd disk. Expected: '{testString}'. Found: '{foundString}'") # Client: Fail to connect to the private disk client.fail("nbd-client server ${toString listenPort} /dev/nbd0 -name vault-priv -persist") # Server: Successfully connect to the private disk server.succeed("nbd-client localhost ${toString listenPort} /dev/nbd0 -name vault-priv -persist") server.succeed(f"echo '{testString}' | dd of=/dev/nbd0 conv=notrunc") foundString = server.succeed(f"dd status=none if=/dev/loop0 count={len(testString)}")[:len(testString)] if foundString != testString: raise Exception(f"Read the wrong string from nbd disk. Expected: '{testString}'. Found: '{foundString}'") server.succeed("nbd-client -d /dev/nbd0") # Server: Successfully connect to the aaa disk server.succeed("nbd-client localhost ${toString listenPort} /dev/nbd0 -name aaa -persist") server.succeed(f"echo '{testString}' | dd of=/dev/nbd0 conv=notrunc") foundString = server.succeed(f"dd status=none if=/aaa.disk count={len(testString)}")[:len(testString)] if foundString != testString: raise Exception(f"Read the wrong string from nbd disk. Expected: '{testString}'. Found: '{foundString}'") server.succeed("nbd-client -d /dev/nbd0") ''; } )