1import ./make-test.nix ({ pkgs, version ? 4, ... }:
2
3let
4
5 client =
6 { config, pkgs, ... }:
7 { fileSystems = pkgs.lib.mkVMOverride
8 [ { mountPoint = "/data";
9 device = "server:/data";
10 fsType = "nfs";
11 options = [ "vers=${toString version}" ];
12 }
13 ];
14 networking.firewall.enable = false; # FIXME: only open statd
15 };
16
17in
18
19{
20 name = "nfs";
21 meta = with pkgs.stdenv.lib.maintainers; {
22 maintainers = [ eelco chaoflow wkennington ];
23 };
24
25 nodes =
26 { client1 = client;
27 client2 = client;
28
29 server =
30 { config, pkgs, ... }:
31 { services.nfs.server.enable = true;
32 services.nfs.server.exports =
33 ''
34 /data 192.168.1.0/255.255.255.0(rw,no_root_squash,no_subtree_check,fsid=0)
35 '';
36 services.nfs.server.createMountPoints = true;
37 networking.firewall.enable = false; # FIXME: figure out what ports need to be allowed
38 };
39 };
40
41 testScript =
42 ''
43 $server->waitForUnit("nfs-server");
44 $server->succeed("systemctl start network-online.target");
45 $server->waitForUnit("network-online.target");
46
47 startAll;
48
49 $client1->waitForUnit("data.mount");
50 $client1->succeed("echo bla > /data/foo");
51 $server->succeed("test -e /data/foo");
52
53 $client2->waitForUnit("data.mount");
54 $client2->succeed("echo bla > /data/bar");
55 $server->succeed("test -e /data/bar");
56
57 # Test whether restarting ‘nfs-server’ works correctly.
58 $server->succeed("systemctl restart nfs-server");
59 $client2->succeed("echo bla >> /data/bar"); # will take 90 seconds due to the NFS grace period
60
61 # Test whether we can get a lock.
62 $client2->succeed("time flock -n -s /data/lock true");
63
64 # Test locking: client 1 acquires an exclusive lock, so client 2
65 # should then fail to acquire a shared lock.
66 $client1->succeed("flock -x /data/lock -c 'touch locked; sleep 100000' &");
67 $client1->waitForFile("locked");
68 $client2->fail("flock -n -s /data/lock true");
69
70 # Test whether client 2 obtains the lock if we reset client 1.
71 $client2->succeed("flock -x /data/lock -c 'echo acquired; touch locked; sleep 100000' >&2 &");
72 $client1->crash;
73 $client1->start;
74 $client2->waitForFile("locked");
75
76 # Test whether locks survive a reboot of the server.
77 $client1->waitForUnit("data.mount");
78 $server->shutdown;
79 $server->start;
80 $client1->succeed("touch /data/xyzzy");
81 $client1->fail("time flock -n -s /data/lock true");
82
83 # Test whether unmounting during shutdown happens quickly.
84 my $t1 = time;
85 $client1->shutdown;
86 my $duration = time - $t1;
87 die "shutdown took too long ($duration seconds)" if $duration > 30;
88 '';
89})