summary refs log tree commit diff
path: root/nixos/modules/tasks/lvm.nix
blob: 59711f90dce3ddf6ab2a7361e14dd6c23144d420 (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
{ config, lib, pkgs, ... }:

with lib;
let
  cfg = config.services.lvm;
in {
  options.services.lvm = {
    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";
  };

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

      # TODO: update once https://github.com/NixOS/nixpkgs/pull/93006 was merged
      services.udev.packages = [ cfg.package.out ];
    })
    (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" ];

        extraUtilsCommands = ''
          for BIN in ${pkgs.thin-provisioning-tools}/bin/*; do
            copy_bin_and_libs $BIN
          done
        '';

        extraUtilsCommandsTest = ''
          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" ];

          extraUtilsCommands = ''
            ls ${pkgs.vdo}/bin/ | grep -v adaptLVMVDO | while read BIN; do
              copy_bin_and_libs ${pkgs.vdo}/bin/$BIN
            done
          '';

          extraUtilsCommandsTest = ''
            ls ${pkgs.vdo}/bin/ | grep -v adaptLVMVDO | 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.preLVMCommands = ''
          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
      '';
    })
  ];

}