diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index dd6c744a79cea..92330cb335cd5 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1003,6 +1003,7 @@ in { zammad = handleTest ./zammad.nix {}; zeronet-conservancy = handleTest ./zeronet-conservancy.nix {}; zfs = handleTest ./zfs.nix {}; + zfs-tests = discoverTests (import ./zfs-tests.nix); zigbee2mqtt = handleTest ./zigbee2mqtt.nix {}; zoneminder = handleTest ./zoneminder.nix {}; zookeeper = handleTest ./zookeeper.nix {}; diff --git a/nixos/tests/zfs-tests.nix b/nixos/tests/zfs-tests.nix new file mode 100644 index 0000000000000..b27a58e70ea1e --- /dev/null +++ b/nixos/tests/zfs-tests.nix @@ -0,0 +1,193 @@ +let + # Running all tests takes very long (multiple hours) and doesn't work properly. + # We'll just do a quick smoke-test. + + # test run results (no extra text means PASS): + # - chattr + # - checksum + # - deadman + # - devices + # - fallocate + # - snapshot + # - tmpfile + # - upgrade + # - userquota + # - zdb + # - zfs + # - zfs_sysfs + # - zpool_add + # - zpool_reopen + # - compression (4 FAIL) + # - compression/l2arc_compressed_arc + # - compression/l2arc_compressed_arc_disabled + # - compression/l2arc_encrypted + # - compression/l2arc_encrypted_no_compressed_arc + # - events (3 FAIL) + # - events/events_001_pos + # - events/events_002_pos + # - events/zed_rc_filter + # - exec (1 FAIL) + # - exec/exec_001_pos + # - fault (takes very long, doesn't terminate?) + # - large_dnode (1 FAIL) + # - features/large_dnode/large_dnode_006_pos + # - misc (1 FAIL) + # - cli_user/misc/arc_summary_001_pos + # - mmp (14 SKIP) + # - rsend (takes very long, errors out with ENOSPC) + # - user_namespace (1 FAIL) + # - zfs_mount (2 FAIL) + # - cli_root/zfs_mount/zfs_mount_013_pos + # - cli_root/zfs_mount/zfs_multi_mount + # - zfs_share (2 FAIL, 13 SKIP) + # - cli_root/zfs_share/setup + # - zpool_create (1 FAIL) + # - cli_root/zpool_create/zpool_create_014_neg + # - zpool_expand (1 FAIL) + # - cli_root/zpool_expand/zpool_expand_001_pos + # - zpool_split (1 SKIP) + # - cli_root/zpool_split/zpool_split_props + + # TODO + # - io (broken? fio) + # - pool_checkpoint (takes > 15 minutes) + # - cache (fio) + # - trim (fio) + # - l2arc (fio) + # - pam (pamtester) + + tests = [ + # 00:07 + "chattr" + # 01:47 + "checksum" + "compression" + # 01:00 + "deadman" + # 00:04 + "devices" + "events" + "exec" + # 00:02 + "fallocate" + # 01:03 + "snapshot" + # 00:02 + "tmpfile" + # 00:22 + "upgrade" + # 00:58 + "userquota" + # 04:51 + "zdb" + # 00:43 + "zfs" + # 00:04 + "zfs_sysfs" + # 04:54 + "zpool_add" + "zpool_create" + # 03:06 + "zpool_reopen" + ]; + + mkTest = testname: ( + + import ./make-test-python.nix ({ lib, pkgs, ... }: + let + zfsForTesting = pkgs.zfs; + in + { + name = "zfs-tests-${testname}"; + meta = with lib.maintainers; { + maintainers = [ mindavi ]; + }; + + nodes.machine = + { lib, pkgs, config, ... }: + with lib; + { + imports = [ ./common/user-account.nix ]; + # User must be in wheel group, without requiring password entry. + users.users.alice = { isNormalUser = true; group = "wheel"; }; + security.sudo.wheelNeedsPassword = false; + + # The default size of 512 MB was not enough, so bump it to be safe. + # E.g. functional/pool_checkpoint/setup uses quite a bit of harddrive space. + virtualisation.diskSize = 8192; + # ZFS uses quite a bit of RAM. + # This seems like a generous enough amount of memory. + virtualisation.memorySize = 4096; + # TODO(mindavi): Does it help to assign multiple cores? + virtualisation.cores = 6; + + # This prevents that grub is rebuild / included in closure. + # It doesn't seem to be used anyway, because disabling helps :). + boot.loader.grub.enable = false; + + boot.kernelModules = [ "zfs" ]; + boot.supportedFilesystems = [ "zfs" ]; + environment.systemPackages = [ + pkgs.gcc + zfsForTesting + pkgs.ksh + pkgs.util-linux + pkgs.coreutils + pkgs.sudo + pkgs.lvm2 + pkgs.gawk + pkgs.e2fsprogs # mkfs.ext4 + pkgs.gzip # gzip, gunzip + pkgs.procps + pkgs.acl # setfacl, getfacl + pkgs.python3 + pkgs.openssl + pkgs.bc + pkgs.nfs-utils + pkgs.dmidecode + pkgs.lsscsi + pkgs.file + pkgs.sysstat # iostat + pkgs.pax + pkgs.binutils # strings + pkgs.parted + pkgs.linuxPackages.perf + pkgs.samba # net + #pkgs.fio # disable because of kernel crashes... / hangs + # exportfs -> nfs-utils? + pkgs.tree + + pkgs.lvm2 + ]; + networking.hostId = "abcdef01"; + }; + + testScript = '' + start_all() + machine.wait_for_unit("multi-user.target") + print(machine.succeed("modprobe zfs", "zfs version", "id")) + + machine.execute( + "su - alice -- ${zfsForTesting.zfs_tests}/share/zfs/zfs-tests.sh -T ${testname} >> test-results.log", + ) + # Show the last lines of the test results log. + print(machine.execute("tail -n30 test-results.log")[1]) + + print(machine.execute("cat test-results.log")[1]) + print(machine.execute("grep 'Results Summary' -A 8 test-results.log")[1]) + + # These tools are still missing: + # Missing util(s): devname2devid mmap_libaio fio pamtester quotaon umask wait setenforce + print(machine.execute("grep 'Missing util' test-results.log")[1]) + + print(machine.succeed("tree /var/tmp/test_results/")) + print(machine.succeed("cat /var/tmp/test_results/current/**")) + # Test results can be found in /var/tmp/test_results/ + machine.succeed("grep 'Percent passed.*100' test-results.log") + ''; + }) + ); + lib = (import ../../. { }).lib; +in +lib.genAttrs tests mkTest + diff --git a/pkgs/os-specific/linux/zfs/generic.nix b/pkgs/os-specific/linux/zfs/generic.nix index c0ff834cb34ab..8dfa6d7beb64a 100644 --- a/pkgs/os-specific/linux/zfs/generic.nix +++ b/pkgs/os-specific/linux/zfs/generic.nix @@ -5,6 +5,12 @@ let , perl , configFile ? "all" + # Test dependencies + , ksh + , lvm2 + , gzip + , e2fsprogs + # Userspace dependencies , zlib, libuuid, python3, attr, openssl , libtirpc @@ -73,6 +79,33 @@ let --replace '"/usr/bin/env", "umount"' '"${util-linux}/bin/umount", "-n"' \ --replace '"/usr/bin/env", "mount"' '"${util-linux}/bin/mount", "-n"' '' + optionalString buildUser '' + # TODO(Mindavi): Is overriding with /run/current-system/sw/bin acceptable? + substituteInPlace scripts/zfs-tests.sh \ + --replace '$STF_PATH/ksh' ${ksh}/bin/ksh \ + --replace 'LOSETUP=' 'LOSETUP=${util-linux}/bin/losetup #' \ + --replace 'export PATH=$STF_PATH' '#' \ + --replace 'DMSETUP=' 'DMSETUP=${lvm2}/bin/dmsetup #' \ + --replace '$STF_PATH/gzip' '${gzip}/bin/gzip' \ + --replace '$STF_PATH/gunzip' '${gzip}/bin/gunzip' \ + --replace '/sbin/fsck.ext4' '${e2fsprogs}/bin/fsck.ext4' \ + --replace '/sbin/mkfs.ext4' '${e2fsprogs}/bin/mkfs.ext4' \ + --replace '$STF_PATH/awk' '${gawk}/bin/awk' \ + --replace 'SYSTEM_DIRS="/usr/local/bin /usr/local/sbin"' 'SYSTEM_DIRS="/run/current-system/sw/bin"' + substituteInPlace scripts/common.sh.in \ + --replace 'export ZTS_DIR=' 'export ZTS_DIR=${placeholder "zfs_tests"}/share/zfs #' \ + --replace 'export SCRIPT_DIR=' 'export SCRIPT_DIR=${placeholder "zfs_tests"}/share/zfs #' \ + --replace 'export ZDB=' 'export ZDB=${placeholder "out"}/bin/zdb #' \ + --replace 'export ZFS=' 'export ZFS=${placeholder "out"}/bin/zfs #' \ + --replace 'export ZPOOL=' 'export ZPOOL=${placeholder "out"}/bin/zpool #' \ + --replace 'export ZTEST=' 'export ZTEST=${placeholder "out"}/bin/ztest #' \ + --replace 'export ZFS_SH=' 'export ZFS_SH=${placeholder "zfs_tests"}/share/zfs/zfs.sh #' + # Fix ksh paths in test suite. + # patchShebangs doesn't work due to the scripts not being executable. + # It doesn't seem logical to make them executable either. + find -name "*.ksh" -exec sed -i 's,/bin/ksh,${ksh}/bin/ksh,' {} \; + # Patching maybe required for more binaries + # Maybe FHS environment would be better? + substituteInPlace ./lib/libshare/os/linux/nfs.c --replace "/usr/sbin/exportfs" "${ # We don't *need* python support, but we set it like this to minimize closure size: # If it's disabled by default, no need to enable it, even if we have python enabled @@ -181,10 +214,12 @@ let done # Remove tests because they add a runtime dependency on gcc - rm -rf $out/share/zfs/zfs-tests + # TODO(mindavi): Should we optionally remove these? How does that work? + mkdir -p ${placeholder "zfs_tests"}/share/zfs/ + mv ${placeholder "out"}/share/zfs/ ${placeholder "zfs_tests"}/share/ # Add Bash completions. - install -v -m444 -D -t $out/share/bash-completion/completions contrib/bash_completion.d/zfs + install -v -m444 -D -t ${placeholder "out"}/share/bash-completion/completions contrib/bash_completion.d/zfs (cd $out/share/bash-completion/completions; ln -s zfs zpool) ''; @@ -196,7 +231,7 @@ let done ''; - outputs = [ "out" ] ++ optionals buildUser [ "dev" ]; + outputs = [ "out" ] ++ optionals buildUser [ "dev" "zfs_tests" ]; passthru = { inherit enableMail latestCompatibleLinuxPackages kernelModuleAttribute;