1import ./make-test.nix ({ pkgs, ... }:
2
3with pkgs.lib;
4
5let
6 ksExt = pkgs.writeText "ks-ext4" ''
7 clearpart --all --initlabel --drives=vdb
8
9 part /boot --recommended --label=boot --fstype=ext2 --ondisk=vdb
10 part swap --recommended --label=swap --fstype=swap --ondisk=vdb
11 part /nix --size=500 --label=nix --fstype=ext3 --ondisk=vdb
12 part / --recommended --label=root --fstype=ext4 --ondisk=vdb
13 '';
14
15 ksBtrfs = pkgs.writeText "ks-btrfs" ''
16 clearpart --all --initlabel --drives=vdb,vdc
17
18 part swap1 --recommended --label=swap1 --fstype=swap --ondisk=vdb
19 part swap2 --recommended --label=swap2 --fstype=swap --ondisk=vdc
20
21 part btrfs.1 --grow --ondisk=vdb
22 part btrfs.2 --grow --ondisk=vdc
23
24 btrfs / --data=0 --metadata=1 --label=root btrfs.1 btrfs.2
25 '';
26
27 ksF2fs = pkgs.writeText "ks-f2fs" ''
28 clearpart --all --initlabel --drives=vdb
29
30 part swap --recommended --label=swap --fstype=swap --ondisk=vdb
31 part /boot --recommended --label=boot --fstype=f2fs --ondisk=vdb
32 part / --recommended --label=root --fstype=f2fs --ondisk=vdb
33 '';
34
35 ksRaid = pkgs.writeText "ks-raid" ''
36 clearpart --all --initlabel --drives=vdb,vdc
37
38 part raid.01 --size=200 --ondisk=vdb
39 part raid.02 --size=200 --ondisk=vdc
40
41 part swap1 --size=500 --label=swap1 --fstype=swap --ondisk=vdb
42 part swap2 --size=500 --label=swap2 --fstype=swap --ondisk=vdc
43
44 part raid.11 --grow --ondisk=vdb
45 part raid.12 --grow --ondisk=vdc
46
47 raid /boot --level=1 --fstype=ext3 --device=md0 raid.01 raid.02
48 raid / --level=1 --fstype=xfs --device=md1 raid.11 raid.12
49 '';
50
51 ksRaidLvmCrypt = pkgs.writeText "ks-lvm-crypt" ''
52 clearpart --all --initlabel --drives=vdb,vdc
53
54 part raid.1 --grow --ondisk=vdb
55 part raid.2 --grow --ondisk=vdc
56
57 raid pv.0 --level=1 --encrypted --passphrase=x --device=md0 raid.1 raid.2
58
59 volgroup nixos pv.0
60
61 logvol /boot --size=200 --fstype=ext3 --name=boot --vgname=nixos
62 logvol swap --size=500 --fstype=swap --name=swap --vgname=nixos
63 logvol / --size=1000 --grow --fstype=ext4 --name=root --vgname=nixos
64 '';
65in {
66 name = "partitiion";
67
68 machine = { config, pkgs, ... }: {
69 environment.systemPackages = [
70 pkgs.pythonPackages.nixpart0
71 pkgs.file pkgs.btrfsProgs pkgs.xfsprogs pkgs.lvm2
72 ];
73 virtualisation.emptyDiskImages = [ 4096 4096 ];
74 };
75
76 testScript = ''
77 my $diskStart;
78 my @mtab;
79
80 sub getMtab {
81 my $mounts = $machine->succeed("cat /proc/mounts");
82 chomp $mounts;
83 return map [split], split /\n/, $mounts;
84 }
85
86 sub parttest {
87 my ($desc, $code) = @_;
88 $machine->start;
89 $machine->waitForUnit("default.target");
90
91 # Gather mounts and superblock
92 @mtab = getMtab;
93 $diskStart = $machine->succeed("dd if=/dev/vda bs=512 count=1");
94
95 subtest($desc, $code);
96 $machine->shutdown;
97 }
98
99 sub ensureSanity {
100 # Check whether the filesystem in /dev/vda is still intact
101 my $newDiskStart = $machine->succeed("dd if=/dev/vda bs=512 count=1");
102 if ($diskStart ne $newDiskStart) {
103 $machine->log("Something went wrong, the partitioner wrote " .
104 "something into the first 512 bytes of /dev/vda!");
105 die;
106 }
107
108 # Check whether nixpart has unmounted anything
109 my @currentMtab = getMtab;
110 for my $mount (@mtab) {
111 my $path = $mount->[1];
112 unless (grep { $_->[1] eq $path } @currentMtab) {
113 $machine->log("The partitioner seems to have unmounted $path.");
114 die;
115 }
116 }
117 }
118
119 sub checkMount {
120 my $mounts = $machine->succeed("cat /proc/mounts");
121
122 }
123
124 sub kickstart {
125 $machine->copyFileFromHost($_[0], "/kickstart");
126 $machine->succeed("nixpart -v /kickstart");
127 ensureSanity;
128 }
129
130 sub ensurePartition {
131 my ($name, $match) = @_;
132 my $path = $name =~ /^\// ? $name : "/dev/disk/by-label/$name";
133 my $out = $machine->succeed("file -Ls $path");
134 my @matches = grep(/^$path: .*$match/i, $out);
135 if (!@matches) {
136 $machine->log("Partition on $path was expected to have a " .
137 "file system that matches $match, but instead has: $out");
138 die;
139 }
140 }
141
142 sub ensureNoPartition {
143 $machine->succeed("test ! -e /dev/$_[0]");
144 }
145
146 sub ensureMountPoint {
147 $machine->succeed("mountpoint $_[0]");
148 }
149
150 sub remountAndCheck {
151 $machine->nest("Remounting partitions:", sub {
152 # XXX: "findmnt -ARunl -oTARGET /mnt" seems to NOT print all mounts!
153 my $getmounts_cmd = "cat /proc/mounts | cut -d' ' -f2 | grep '^/mnt'";
154 # Insert canaries first
155 my $canaries = $machine->succeed($getmounts_cmd . " | while read p;" .
156 " do touch \"\$p/canary\";" .
157 " echo \"\$p/canary\"; done");
158 # Now unmount manually
159 $machine->succeed($getmounts_cmd . " | tac | xargs -r umount");
160 # /mnt should be empty or non-existing
161 my $found = $machine->succeed("find /mnt -mindepth 1");
162 chomp $found;
163 if ($found) {
164 $machine->log("Cruft found in /mnt:\n$found");
165 die;
166 }
167 # Try to remount with nixpart
168 $machine->succeed("nixpart -vm /kickstart");
169 ensureMountPoint("/mnt");
170 # Check if our beloved canaries are dead
171 chomp $canaries;
172 $machine->nest("Checking canaries:", sub {
173 for my $canary (split /\n/, $canaries) {
174 $machine->succeed("test -e '$canary'");
175 }
176 });
177 });
178 }
179
180 parttest "ext2, ext3 and ext4 filesystems", sub {
181 kickstart("${ksExt}");
182 ensurePartition("boot", "ext2");
183 ensurePartition("swap", "swap");
184 ensurePartition("nix", "ext3");
185 ensurePartition("root", "ext4");
186 ensurePartition("/dev/vdb4", "boot sector");
187 ensureNoPartition("vdb6");
188 ensureNoPartition("vdc1");
189 remountAndCheck;
190 ensureMountPoint("/mnt/boot");
191 ensureMountPoint("/mnt/nix");
192 };
193
194 parttest "btrfs filesystem", sub {
195 $machine->succeed("modprobe btrfs");
196 kickstart("${ksBtrfs}");
197 ensurePartition("swap1", "swap");
198 ensurePartition("swap2", "swap");
199 ensurePartition("/dev/vdb2", "btrfs");
200 ensurePartition("/dev/vdc2", "btrfs");
201 ensureNoPartition("vdb3");
202 ensureNoPartition("vdc3");
203 remountAndCheck;
204 };
205
206 parttest "f2fs filesystem", sub {
207 $machine->succeed("modprobe f2fs");
208 kickstart("${ksF2fs}");
209 ensurePartition("swap", "swap");
210 ensurePartition("boot", "f2fs");
211 ensurePartition("root", "f2fs");
212 remountAndCheck;
213 ensureMountPoint("/mnt/boot", "f2fs");
214 };
215
216 parttest "RAID1 with XFS", sub {
217 kickstart("${ksRaid}");
218 ensurePartition("swap1", "swap");
219 ensurePartition("swap2", "swap");
220 ensurePartition("/dev/md0", "ext3");
221 ensurePartition("/dev/md1", "xfs");
222 ensureNoPartition("vdb4");
223 ensureNoPartition("vdc4");
224 ensureNoPartition("md2");
225 remountAndCheck;
226 ensureMountPoint("/mnt/boot");
227 };
228
229 parttest "RAID1 with LUKS and LVM", sub {
230 kickstart("${ksRaidLvmCrypt}");
231 ensurePartition("/dev/vdb1", "data");
232 ensureNoPartition("vdb2");
233 ensurePartition("/dev/vdc1", "data");
234 ensureNoPartition("vdc2");
235
236 ensurePartition("/dev/md0", "luks");
237 ensureNoPartition("md1");
238
239 ensurePartition("/dev/nixos/boot", "ext3");
240 ensurePartition("/dev/nixos/swap", "swap");
241 ensurePartition("/dev/nixos/root", "ext4");
242
243 remountAndCheck;
244 ensureMountPoint("/mnt/boot");
245 };
246 '';
247})