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