about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/tasks/lvm.nix
blob: 325a5aa45b1ec70e86f2dbca64a976a82b54fec2 (plain) (blame)
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
{ config, lib, pkgs, ... }:

with lib;
let
  cfg = config.services.lvm;
in {
  options.services.lvm = {
    enable = mkEnableOption (lib.mdDoc "lvm2") // {
      default = true;
    };

    package = mkOption {
      type = types.package;
      default = pkgs.lvm2;
      internal = true;
      defaultText = literalExpression "pkgs.lvm2";
      description = lib.mdDoc ''
        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 (lib.mdDoc "the LVM dmevent daemon");
    boot.thin.enable = mkEnableOption (lib.mdDoc "support for booting from ThinLVs");
    boot.vdo.enable = mkEnableOption (lib.mdDoc "support for booting from VDOLVs");
  };

  options.boot.initrd.services.lvm.enable = mkEnableOption (lib.mdDoc "booting from LVM2 in the initrd") // {
    description = lib.mdDoc ''
      *This will only be used when systemd is used in stage 1.*

      Whether to enable booting from LVM2 in the initrd.
    '';
  };

  config = mkMerge [
    ({
      # minimal configuration file to make lvmconfig/lvm2-activation-generator happy
      environment.etc."lvm/lvm.conf".text = "config {}";
    })
    (mkIf cfg.enable {
      systemd.tmpfiles.packages = [ cfg.package.out ];
      environment.systemPackages = [ cfg.package ];
      systemd.packages = [ cfg.package ];

      services.udev.packages = [ cfg.package.out ];
    })
    (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 {
      boot = {
        initrd = {
          kernelModules = [ "kvdo" ];

          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/adaptLVMVDO.sh --replace "${pkgs.bash}/bin/bash" "/bin/sh"
          '';

          extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable)''
            ls ${pkgs.vdo}/bin/ | grep -vE '(adaptLVMVDO|vdorecover)' | while read BIN; do
              $out/bin/$(basename $BIN) --help > /dev/null
            done
          '';
        };
        extraModulePackages = [ config.boot.kernelPackages.kvdo ];
      };

      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
      '';
    })
  ];

}