From 92fcc3cd4fc50bba1b2b2d95f8bed4e0a5a03136 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Mon, 9 Apr 2018 12:24:09 +0200 Subject: lvm snapshots --- custom/btrfs-snapshots.nix | 4 ++ custom/lvm-snapshots.nix | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 custom/lvm-snapshots.nix (limited to 'custom') diff --git a/custom/btrfs-snapshots.nix b/custom/btrfs-snapshots.nix index 44b08740..9dc3f1f8 100644 --- a/custom/btrfs-snapshots.nix +++ b/custom/btrfs-snapshots.nix @@ -40,6 +40,10 @@ in { config = mkIf cfg.enable { + system.activationScripts."btrfs-snapshots" = '' + mkdir -p ${mountPoint} + ''; + systemd.services."btrfs-snapshot@" = { enable = true; diff --git a/custom/lvm-snapshots.nix b/custom/lvm-snapshots.nix new file mode 100644 index 00000000..67ee2cbd --- /dev/null +++ b/custom/lvm-snapshots.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.lvm-snapshots; + + snapshotMount = name: "${cfg.mountPoint}/${if isNull cfg.snapshots."${name}".mountName then name else cfg.snapshots."${name}".mountName}"; + + snapshotConfig = { + options = { + LV = mkOption { + type = types.str; + }; + + VG = mkOption { + type = types.str; + }; + + mountName = mkOption { + type = types.nullOr types.str; + default = null; + }; + + cowSize = mkOption { + type = types.str; + default = "-l20%ORIGIN"; + }; + + readOnly = mkOption { + type = types.bool; + default = true; + }; + + persist = mkOption { + type = types.bool; + default = false; + }; + }; + }; +in { + options = { + + services.lvm-snapshots = { + snapshots = mkOption { + type = types.attrsOf (types.submodule snapshotConfig); + default = {}; + }; + + mountPoint = mkOption { + type = types.path; + default = "/mnt"; + }; + }; + }; + + + config = mkIf (cfg != {}) { + + system.activationScripts = mapAttrs' (name: scfg: nameValuePair (lvm-mountpoint + name) '' + mkdir -p ${snapshotMount name} + '') cfg.snapshots; + + systemd.services = mapAttrs' (name: scfg: nameValuePair ("lvm-snapshot@" + name) { + enable = true; + + unitConfig = { + StopWhenUnneeded = true; + }; + + serviceConfig = with pkgs; { + Type = "oneshot"; + ExecStart = "${devicemapper}/bin/lvcreate -s ${cfg.cowSize} --name ${name} ${scfg.VG}/${scfg.LV}"; + ExecStop = "${devicemapper}/bin/lvremove ${scfg.VG}/${name}"; + RemainAfterExit = true; + }; + }) cfg.snapshots; + + systemd.mounts = mapAttrsToList (name: scfg: { + enable = true; + + unitConfig = { + AssertPathIsDirectory = snapshotMount name; + StopWhenUnneeded = !scfg.persist; + }; + + bindsTo = "lvm-snapshot@" + name; + + options = mkIf scfg.readOnly "ro"; + + where = snapshotMount name; + what = "/dev/" + scfg.VG + "/" + name; + }) cfg.snapshots; + }; +} -- cgit v1.2.3