aboutsummaryrefslogtreecommitdiff
path: root/modules/system/raid0.nix
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2016-09-29 13:51:44 +0300
committerIgor Pashev <pashev.igor@gmail.com>2016-09-29 13:51:44 +0300
commit62f28d30a069135f9c48678507203958adfc334f (patch)
tree7f38af0c8d3f445ee8cc50906a639baec7011127 /modules/system/raid0.nix
parent1af9e6589bdd18e6ba7eeabf073aa7d710020cdd (diff)
downloadnixsap-62f28d30a069135f9c48678507203958adfc334f.tar.gz
Moved everything into ./modules
Diffstat (limited to 'modules/system/raid0.nix')
-rw-r--r--modules/system/raid0.nix134
1 files changed, 134 insertions, 0 deletions
diff --git a/modules/system/raid0.nix b/modules/system/raid0.nix
new file mode 100644
index 0000000..d260e29
--- /dev/null
+++ b/modules/system/raid0.nix
@@ -0,0 +1,134 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+with lib.types;
+with builtins;
+
+let
+ groups = filterAttrs (n: _: n != "_module") config.nixsap.system.lvm.raid0;
+
+ createLV = vg: lv: s: opts:
+ let
+ new = toString s;
+ stripes = toString opts.stripes;
+ sizeSpec = if opts.units == "%"
+ then "--extents ${new}%VG"
+ else "--size ${new}${opts.units}";
+ scale = {
+ "%" = "* 100 / $(vgs --unit b --noheadings --nosuffix --options vg_size ${vg})";
+ "M" = "/ ${toString (1000 * 1000)}";
+ "m" = "/ ${toString (1024 * 1024)}";
+ "G" = "/ ${toString (1000 * 1000 * 1000)}";
+ "g" = "/ ${toString (1024 * 1024 * 1024)}";
+ "T" = "/ ${toString (1000 * 1000 * 1000 * 1000)}";
+ "t" = "/ ${toString (1024 * 1024 * 1024 * 1024)}";
+ };
+ in pkgs.writeBashScript "raid0-create-${vg}-${lv}" ''
+ set -eu
+ device=/dev/${vg}/${lv}
+
+ lv_size=$(lvs --unit b --noheadings --nosuffix --options lv_size "$device" || echo 0)
+ old=$(( lv_size ${scale."${opts.units}"} ))
+
+ if (( ${new} == old )) ; then
+ exit 0
+ elif (( old == 0 )); then
+ lvcreate ${vg} --name ${lv} ${sizeSpec} --stripes ${stripes}
+ elif (( ${new} < old )) ; then
+ echo "Cannot shrink volume $device from $old ${opts.units} to ${new} ${opts.units}" >&2
+ exit 1
+ else
+ lvextend "$device" ${sizeSpec}
+ resize2fs "$device"
+ fi
+ '';
+
+ createVG = vg: pv: pkgs.writeBashScript "raid0-create-vg-${vg}" ''
+ set -eu
+ for pv in ${toString pv}; do
+ type=$(blkid -p -s TYPE -o value "$pv" || true)
+ if [ "$type" != LVM2_member ]; then
+ pvcreate "$pv"
+ if ! vgs ${vg}; then
+ vgcreate ${vg} "$pv"
+ else
+ vgextend ${vg} "$pv"
+ fi
+ fi
+ done
+ '';
+
+ mkRaidService = vg: opts:
+ let
+ ExecStart = pkgs.writeBashScript "raid0-${vg}" ''
+ set -eu
+ ${createVG vg opts.physical}
+ ${concatStringsSep "\n" (
+ mapAttrsToList (v: s:
+ "${createLV vg (baseNameOf v) s opts}")
+ opts.fileSystems
+ )}
+ vgchange -ay ${vg}
+ udevadm trigger --action=add
+ '';
+
+ in nameValuePair "raid0-${vg}" rec {
+ wantedBy = map (v: "dev-${vg}-${baseNameOf v}.device") (attrNames opts.fileSystems);
+ requires = map (pv: replaceStrings ["/"] ["-"] (removePrefix "/" pv) + ".device") opts.physical;
+ after = requires;
+ before = wantedBy;
+ unitConfig.DefaultDependencies = false;
+ path = with pkgs; [ utillinux lvm2 e2fsprogs ];
+ serviceConfig = {
+ inherit ExecStart;
+ RemainAfterExit = true;
+ Type = "oneshot";
+ };
+ };
+
+in {
+ options.nixsap.system = {
+ lvm.raid0 = mkOption {
+ description = "Set of LVM2 volume groups";
+ default = {};
+ type = attrsOf (submodule {
+ options = {
+ stripes = mkOption {
+ description = "Number of stripes";
+ type = int;
+ example = 2;
+ };
+ physical = mkOption {
+ description = "List of physical devices (must be even for stripes)";
+ example = [ "/dev/sdb" "/dev/sdc" ];
+ type = listOf path;
+ };
+ fileSystems = mkOption {
+ description = "Filesystems and their sizes";
+ type = attrsOf int;
+ example = { "/mariadb/db" = 100; };
+ };
+ units = mkOption {
+ description = "Units of size";
+ type = enum [ "%" "m" "g" "t" "M" "G" "T"];
+ };
+ };
+ });
+ };
+ };
+
+ config = {
+ systemd.services = mapAttrs' mkRaidService groups;
+
+ fileSystems = foldl (a: b: a//b) {} (
+ mapAttrsToList (vg: opts: genAttrs (attrNames opts.fileSystems)
+ (fs: {
+ fsType = "ext4";
+ autoFormat = true;
+ device = "/dev/${vg}/${baseNameOf fs}";
+ })
+ ) groups
+ );
+ };
+}
+