From 2f335a6c47b363189b976d18a8c7633bff4d7a33 Mon Sep 17 00:00:00 2001 From: tdback Date: Tue, 24 Dec 2024 20:08:50 -0500 Subject: add zquota to easily monitor disk usage of zfs datasets --- modules/scripts/zquota/default.nix | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 modules/scripts/zquota/default.nix (limited to 'modules/scripts') diff --git a/modules/scripts/zquota/default.nix b/modules/scripts/zquota/default.nix new file mode 100644 index 0000000..1dc1fbd --- /dev/null +++ b/modules/scripts/zquota/default.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.zquota; + + zquota = let hostname = config.networking.hostName; in + pkgs.writeShellScriptBin "zquota" '' + #!/usr/bin/env bash + + if [ "$#" -ne 2 ]; then + echo "failed to provide both a dataset and quota" >&2 + exit 1 + fi + + DATASET="$1" + QUOTA="$2" + + if [ -n "$(echo "$QUOTA" | tr -d 0-9.)" ]; then + echo "failed to provide a valid quota" >&2 + exit 1 + fi + + USED=$(${getExe pkgs.zfs} list -Hpo used "$DATASET" 2>/dev/null) || { + echo "failed to provide a valid dataset" >&2 + exit 1 + } + + USAGE=$(${getExe pkgs.bc} <<< "scale=2; $NUM / 1024^3") + + DIFF=$(${getExe pkgs.bc} <<< "scale=2; $NUM - $QUOTA") + + (( $(awk '{ print ($1 > $2) }' <<< "$USAGE $QUOTA") )) && + /run/current-system/sw/bin/pushover -t "${hostname} quota exceeded" \ + "dataset $DATASET on ${hostname} has exceeded quota by ''${DIFF}GB" + ''; +in +{ + options = { + services.zquota = { + enable = mkEnableOption "zquota"; + quotas = mkOption { + default = { }; + type = types.attrsOf types.int; + description = "Attribute set of ZFS dataset and disk quota (in GB)."; + }; + dates = mkOption { + default = "daily"; + type = types.str; + description = '' + How often quota checks are performed. + + This value must be a calendar event specified by + {manpage}`systemd.time(7)`. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ zquota ]; + + systemd.services."zquota" = { + description = "Perform and report routine quota checks on ZFS datasets"; + serviceConfig.Type = "oneshot"; + script = strings.concatStringsSep "\n" <| mapAttrsToList ( + dataset: quota: "/run/current-system/sw/bin/zquota ${dataset} ${builtins.toString quota}" + ) cfg.quotas; + }; + systemd.timers."zquota" = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.dates; + Persistent = true; + }; + }; + }; +} -- cgit v1.2.3