lol

Merge pull request #181746 from hercules-ci/nixosTest-erofs

nixos/qemu-vm: Use disposable EROFS for store when writableStore = false

authored by

Robert Hensing and committed by
GitHub
bd3fb406 5c37f7fa

+140 -5
+86
nixos/modules/virtualisation/includes-to-excludes.py
··· 1 + 2 + # Convert a list of strings to a regex that matches everything but those strings 3 + # ... and it had to be a POSIX regex; no negative lookahead :( 4 + # This is a workaround for erofs supporting only exclude regex, not an include list 5 + 6 + import sys 7 + import re 8 + from collections import defaultdict 9 + 10 + # We can configure this script to match in different ways if we need to. 11 + # The regex got too long for the argument list, so we had to truncate the 12 + # hashes and use MATCH_STRING_PREFIX. That's less accurate, and might pick up some 13 + # garbage like .lock files, but only if the sandbox doesn't hide those. Even 14 + # then it should be harmless. 15 + 16 + # Produce the negation of ^a$ 17 + MATCH_EXACTLY = ".+" 18 + # Produce the negation of ^a 19 + MATCH_STRING_PREFIX = "//X" # //X should be epsilon regex instead. Not supported?? 20 + # Produce the negation of ^a/? 21 + MATCH_SUBPATHS = "[^/].*$" 22 + 23 + # match_end = MATCH_SUBPATHS 24 + match_end = MATCH_STRING_PREFIX 25 + # match_end = MATCH_EXACTLY 26 + 27 + def chars_to_inverted_class(letters): 28 + assert len(letters) > 0 29 + letters = list(letters) 30 + 31 + s = "[^" 32 + 33 + if "]" in letters: 34 + s += "]" 35 + letters.remove("]") 36 + 37 + final = "" 38 + if "-" in letters: 39 + final = "-" 40 + letters.remove("-") 41 + 42 + s += "".join(letters) 43 + 44 + s += final 45 + 46 + s += "]" 47 + 48 + return s 49 + 50 + # There's probably at least one bug in here, but it seems to works well enough 51 + # for filtering store paths. 52 + def strings_to_inverted_regex(strings): 53 + s = "(" 54 + 55 + # Match anything that starts with the wrong character 56 + 57 + chars = defaultdict(list) 58 + 59 + for item in strings: 60 + if item != "": 61 + chars[item[0]].append(item[1:]) 62 + 63 + if len(chars) == 0: 64 + s += match_end 65 + else: 66 + s += chars_to_inverted_class(chars) 67 + 68 + # Now match anything that starts with the right char, but then goes wrong 69 + 70 + for char, sub in chars.items(): 71 + s += "|(" + re.escape(char) + strings_to_inverted_regex(sub) + ")" 72 + 73 + s += ")" 74 + return s 75 + 76 + if __name__ == "__main__": 77 + stdin_lines = [] 78 + for line in sys.stdin: 79 + if line.strip() != "": 80 + stdin_lines.append(line.strip()) 81 + 82 + print("^" + strings_to_inverted_regex(stdin_lines)) 83 + 84 + # Test: 85 + # (echo foo; echo fo/; echo foo/; echo foo/ba/r; echo b; echo az; echo az/; echo az/a; echo ab; echo ab/a; echo ab/; echo abc; echo abcde; echo abb; echo ac; echo b) | grep -vE "$((echo ab; echo az; echo foo;) | python includes-to-excludes.py | tee /dev/stderr )" 86 + # should print ab, az, foo and their subpaths
+51 -5
nixos/modules/virtualisation/qemu-vm.nix
··· 17 17 18 18 cfg = config.virtualisation; 19 19 20 + opt = options.virtualisation; 21 + 20 22 qemu = cfg.qemu.package; 21 23 22 24 consoles = lib.concatMapStringsSep " " (c: "console=${c}") cfg.qemu.consoles; ··· 122 124 TMPDIR=$(mktemp -d nix-vm.XXXXXXXXXX --tmpdir) 123 125 fi 124 126 125 - ${lib.optionalString cfg.useNixStoreImage 126 - '' 127 - # Create a writable copy/snapshot of the store image. 128 - ${qemu}/bin/qemu-img create -f qcow2 -F qcow2 -b ${storeImage}/nixos.qcow2 "$TMPDIR"/store.img 129 - ''} 127 + ${lib.optionalString (cfg.useNixStoreImage) 128 + (if cfg.writableStore 129 + then '' 130 + # Create a writable copy/snapshot of the store image. 131 + ${qemu}/bin/qemu-img create -f qcow2 -F qcow2 -b ${storeImage}/nixos.qcow2 "$TMPDIR"/store.img 132 + '' 133 + else '' 134 + ( 135 + cd ${builtins.storeDir} 136 + ${pkgs.erofs-utils}/bin/mkfs.erofs \ 137 + --force-uid=0 \ 138 + --force-gid=0 \ 139 + -U eb176051-bd15-49b7-9e6b-462e0b467019 \ 140 + -T 0 \ 141 + --exclude-regex="$( 142 + <${pkgs.closureInfo { rootPaths = [ config.system.build.toplevel regInfo ]; }}/store-paths \ 143 + sed -e 's^.*/^^g' \ 144 + | cut -c -10 \ 145 + | ${pkgs.python3}/bin/python ${./includes-to-excludes.py} )" \ 146 + "$TMPDIR"/store.img \ 147 + . \ 148 + </dev/null >/dev/null 149 + ) 150 + '' 151 + ) 152 + } 130 153 131 154 # Create a directory for exchanging data with the VM. 132 155 mkdir -p "$TMPDIR/xchg" ··· 746 769 } 747 770 ])); 748 771 772 + warnings = 773 + optional ( 774 + cfg.writableStore && 775 + cfg.useNixStoreImage && 776 + opt.writableStore.highestPrio > lib.modules.defaultPriority) 777 + '' 778 + You have enabled ${opt.useNixStoreImage} = true, 779 + without setting ${opt.writableStore} = false. 780 + 781 + This causes a store image to be written to the store, which is 782 + costly, especially for the binary cache, and because of the need 783 + for more frequent garbage collection. 784 + 785 + If you really need this combination, you can set ${opt.writableStore} 786 + explicitly to false, incur the cost and make this warning go away. 787 + Otherwise, we recommend 788 + 789 + ${opt.writableStore} = false; 790 + ''; 791 + 749 792 # Note [Disk layout with `useBootLoader`] 750 793 # 751 794 # If `useBootLoader = true`, we configure 2 drives: ··· 768 811 else cfg.bootDevice 769 812 ); 770 813 boot.loader.grub.gfxmodeBios = with cfg.resolution; "${toString x}x${toString y}"; 814 + 815 + boot.initrd.kernelModules = optionals (cfg.useNixStoreImage && !cfg.writableStore) [ "erofs" ]; 771 816 772 817 boot.initrd.extraUtilsCommands = lib.mkIf (cfg.useDefaultFilesystems && !config.boot.initrd.systemd.enable) 773 818 '' ··· 905 950 name = "nix-store"; 906 951 file = ''"$TMPDIR"/store.img''; 907 952 deviceExtraOpts.bootindex = if cfg.useBootLoader then "3" else "2"; 953 + driveExtraOpts.format = if cfg.writableStore then "qcow2" else "raw"; 908 954 }]) 909 955 (mkIf cfg.useBootLoader [ 910 956 # The order of this list determines the device names, see
+1
nixos/tests/discourse.nix
··· 30 30 virtualisation.memorySize = 2048; 31 31 virtualisation.cores = 4; 32 32 virtualisation.useNixStoreImage = true; 33 + virtualisation.writableStore = false; 33 34 34 35 imports = [ common/user-account.nix ]; 35 36
+2
nixos/tests/gitlab.nix
··· 38 38 virtualisation.memorySize = if pkgs.stdenv.is64bit then 4096 else 2047; 39 39 virtualisation.cores = 4; 40 40 virtualisation.useNixStoreImage = true; 41 + virtualisation.writableStore = false; 42 + 41 43 systemd.services.gitlab.serviceConfig.Restart = mkForce "no"; 42 44 systemd.services.gitlab-workhorse.serviceConfig.Restart = mkForce "no"; 43 45 systemd.services.gitaly.serviceConfig.Restart = mkForce "no";