at master 6.3 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9let 10 cfg = config.services.lvm; 11in 12{ 13 options.services.lvm = { 14 enable = mkEnableOption "lvm2" // { 15 default = true; 16 description = '' 17 Whether to enable lvm2. 18 19 :::{.note} 20 The lvm2 package contains device-mapper udev rules and without those tools like cryptsetup do not fully function! 21 ::: 22 ''; 23 }; 24 25 package = mkOption { 26 type = types.package; 27 default = pkgs.lvm2; 28 internal = true; 29 defaultText = literalExpression "pkgs.lvm2"; 30 description = '' 31 This option allows you to override the LVM package that's used on the system 32 (udev rules, tmpfiles, systemd services). 33 Defaults to pkgs.lvm2, pkgs.lvm2_dmeventd if dmeventd or pkgs.lvm2_vdo if vdo is enabled. 34 ''; 35 }; 36 dmeventd.enable = mkEnableOption "the LVM dmevent daemon"; 37 boot.thin.enable = mkEnableOption "support for booting from ThinLVs"; 38 boot.vdo.enable = mkEnableOption "support for booting from VDOLVs"; 39 }; 40 41 options.boot.initrd.services.lvm.enable = mkEnableOption "booting from LVM2 in the initrd" // { 42 description = '' 43 *This will only be used when systemd is used in stage 1.* 44 45 Whether to enable booting from LVM2 in the initrd. 46 ''; 47 default = config.boot.initrd.systemd.enable && config.services.lvm.enable; 48 defaultText = lib.literalExpression "config.boot.initrd.systemd.enable && config.services.lvm.enable"; 49 }; 50 51 config = mkMerge [ 52 ({ 53 # minimal configuration file to make lvmconfig/lvm2-activation-generator happy 54 environment.etc."lvm/lvm.conf".text = "config {}"; 55 }) 56 (mkIf cfg.enable { 57 systemd.tmpfiles.packages = [ cfg.package.out ]; 58 environment.systemPackages = [ cfg.package ]; 59 systemd.packages = [ cfg.package ]; 60 61 services.udev.packages = [ cfg.package.out ]; 62 }) 63 (mkIf config.boot.initrd.services.lvm.enable { 64 # We need lvm2 for the device-mapper rules 65 boot.initrd.services.udev.packages = [ cfg.package ]; 66 # The device-mapper rules want to call tools from lvm2 67 boot.initrd.systemd.initrdBin = [ cfg.package ]; 68 boot.initrd.services.udev.binPackages = [ cfg.package ]; 69 }) 70 (mkIf cfg.dmeventd.enable { 71 systemd.sockets."dm-event".wantedBy = [ "sockets.target" ]; 72 systemd.services."lvm2-monitor".wantedBy = [ "sysinit.target" ]; 73 74 environment.etc."lvm/lvm.conf".text = '' 75 dmeventd/executable = "${cfg.package}/bin/dmeventd" 76 ''; 77 services.lvm.package = mkDefault pkgs.lvm2_dmeventd; 78 }) 79 (mkIf cfg.boot.thin.enable { 80 boot.initrd = { 81 kernelModules = [ 82 "dm-snapshot" 83 "dm-thin-pool" 84 ]; 85 86 systemd.initrdBin = lib.mkIf config.boot.initrd.services.lvm.enable [ 87 pkgs.thin-provisioning-tools 88 ]; 89 90 extraUtilsCommands = mkIf (!config.boot.initrd.systemd.enable) '' 91 for BIN in ${pkgs.thin-provisioning-tools}/bin/*; do 92 copy_bin_and_libs $BIN 93 done 94 ''; 95 96 extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) '' 97 ls ${pkgs.thin-provisioning-tools}/bin/ | grep -v pdata_tools | while read BIN; do 98 $out/bin/$(basename $BIN) --help > /dev/null 99 done 100 ''; 101 }; 102 103 environment.etc."lvm/lvm.conf".text = 104 concatMapStringsSep "\n" 105 (bin: "global/${bin}_executable = ${pkgs.thin-provisioning-tools}/bin/${bin}") 106 [ 107 "thin_check" 108 "thin_dump" 109 "thin_repair" 110 "cache_check" 111 "cache_dump" 112 "cache_repair" 113 ]; 114 115 environment.systemPackages = [ pkgs.thin-provisioning-tools ]; 116 }) 117 (mkIf cfg.boot.vdo.enable { 118 assertions = [ 119 { 120 assertion = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.9"; 121 message = "boot.vdo.enable requires at least kernel version 6.9"; 122 } 123 ]; 124 125 boot = { 126 initrd = { 127 kernelModules = [ "dm-vdo" ]; 128 129 systemd.initrdBin = lib.mkIf config.boot.initrd.services.lvm.enable [ pkgs.vdo ]; 130 131 extraUtilsCommands = mkIf (!config.boot.initrd.systemd.enable) '' 132 ls ${pkgs.vdo}/bin/ | while read BIN; do 133 copy_bin_and_libs ${pkgs.vdo}/bin/$BIN 134 done 135 substituteInPlace $out/bin/vdorecover --replace "${pkgs.bash}/bin/bash" "/bin/sh" 136 substituteInPlace $out/bin/adaptlvm --replace "${pkgs.bash}/bin/bash" "/bin/sh" 137 ''; 138 139 extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) '' 140 ls ${pkgs.vdo}/bin/ | grep -vE '(adaptlvm|vdorecover)' | while read BIN; do 141 $out/bin/$(basename $BIN) --help > /dev/null 142 done 143 ''; 144 }; 145 }; 146 147 services.lvm.package = mkOverride 999 pkgs.lvm2_vdo; # this overrides mkDefault 148 149 environment.systemPackages = [ pkgs.vdo ]; 150 }) 151 (mkIf (cfg.dmeventd.enable || cfg.boot.thin.enable) { 152 boot.initrd.systemd.contents."/etc/lvm/lvm.conf".text = 153 optionalString (config.boot.initrd.services.lvm.enable && cfg.boot.thin.enable) ( 154 concatMapStringsSep "\n" (bin: "global/${bin}_executable = /bin/${bin}") [ 155 "thin_check" 156 "thin_dump" 157 "thin_repair" 158 "cache_check" 159 "cache_dump" 160 "cache_repair" 161 ] 162 ) 163 + "\n" 164 + optionalString cfg.dmeventd.enable '' 165 dmeventd/executable = /bin/false 166 activation/monitoring = 0 167 ''; 168 169 boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) '' 170 mkdir -p /etc/lvm 171 cat << EOF >> /etc/lvm/lvm.conf 172 ${optionalString cfg.boot.thin.enable ( 173 concatMapStringsSep "\n" (bin: "global/${bin}_executable = $(command -v ${bin})") [ 174 "thin_check" 175 "thin_dump" 176 "thin_repair" 177 "cache_check" 178 "cache_dump" 179 "cache_repair" 180 ] 181 )} 182 ${optionalString cfg.dmeventd.enable '' 183 dmeventd/executable = "$(command -v false)" 184 activation/monitoring = 0 185 ''} 186 EOF 187 ''; 188 }) 189 ]; 190 191}