diff options
Diffstat (limited to 'nixos/modules/services/network-filesystems/moosefs.nix')
-rw-r--r-- | nixos/modules/services/network-filesystems/moosefs.nix | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/nixos/modules/services/network-filesystems/moosefs.nix b/nixos/modules/services/network-filesystems/moosefs.nix new file mode 100644 index 00000000000..88b2ada37e7 --- /dev/null +++ b/nixos/modules/services/network-filesystems/moosefs.nix @@ -0,0 +1,249 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.moosefs; + + mfsUser = if cfg.runAsUser then "moosefs" else "root"; + + settingsFormat = let + listSep = " "; + allowedTypes = with types; [ bool int float str ]; + valueToString = val: + if isList val then concatStringsSep listSep (map (x: valueToString x) val) + else if isBool val then (if val then "1" else "0") + else toString val; + + in { + type = with types; let + valueType = oneOf ([ + (listOf valueType) + ] ++ allowedTypes) // { + description = "Flat key-value file"; + }; + in attrsOf valueType; + + generate = name: value: + pkgs.writeText name ( lib.concatStringsSep "\n" ( + lib.mapAttrsToList (key: val: "${key} = ${valueToString val}") value )); + }; + + + initTool = pkgs.writeShellScriptBin "mfsmaster-init" '' + if [ ! -e ${cfg.master.settings.DATA_PATH}/metadata.mfs ]; then + cp ${pkgs.moosefs}/var/mfs/metadata.mfs.empty ${cfg.master.settings.DATA_PATH} + chmod +w ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty + ${pkgs.moosefs}/bin/mfsmaster -a -c ${masterCfg} start + ${pkgs.moosefs}/bin/mfsmaster -c ${masterCfg} stop + rm ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty + fi + ''; + + # master config file + masterCfg = settingsFormat.generate + "mfsmaster.cfg" cfg.master.settings; + + # metalogger config file + metaloggerCfg = settingsFormat.generate + "mfsmetalogger.cfg" cfg.metalogger.settings; + + # chunkserver config file + chunkserverCfg = settingsFormat.generate + "mfschunkserver.cfg" cfg.chunkserver.settings; + + # generic template for all deamons + systemdService = name: extraConfig: configFile: { + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network.target" "network-online.target" ]; + + serviceConfig = { + Type = "forking"; + ExecStart = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} start"; + ExecStop = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} stop"; + ExecReload = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} reload"; + PIDFile = "${cfg."${name}".settings.DATA_PATH}/.mfs${name}.lock"; + } // extraConfig; + }; + +in { + ###### interface + + options = { + services.moosefs = { + masterHost = mkOption { + type = types.str; + default = null; + description = "IP or DNS name of master host."; + }; + + runAsUser = mkOption { + type = types.bool; + default = true; + example = true; + description = "Run daemons as user moosefs instead of root."; + }; + + client.enable = mkEnableOption "Moosefs client."; + + master = { + enable = mkOption { + type = types.bool; + description = '' + Enable Moosefs master daemon. + + You need to run <literal>mfsmaster-init</literal> on a freshly installed master server to + initialize the <literal>DATA_PATH</literal> direcory. + ''; + default = false; + }; + + exports = mkOption { + type = with types; listOf str; + default = null; + description = "Paths to export (see mfsexports.cfg)."; + example = [ + "* / rw,alldirs,admin,maproot=0:0" + "* . rw" + ]; + }; + + openFirewall = mkOption { + type = types.bool; + description = "Whether to automatically open the necessary ports in the firewall."; + default = false; + }; + + settings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; + + options.DATA_PATH = mkOption { + type = types.str; + default = "/var/lib/mfs"; + description = "Data storage directory."; + }; + }; + + description = "Contents of config file (mfsmaster.cfg)."; + }; + }; + + metalogger = { + enable = mkEnableOption "Moosefs metalogger daemon."; + + settings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; + + options.DATA_PATH = mkOption { + type = types.str; + default = "/var/lib/mfs"; + description = "Data storage directory"; + }; + }; + + description = "Contents of metalogger config file (mfsmetalogger.cfg)."; + }; + }; + + chunkserver = { + enable = mkEnableOption "Moosefs chunkserver daemon."; + + openFirewall = mkOption { + type = types.bool; + description = "Whether to automatically open the necessary ports in the firewall."; + default = false; + }; + + hdds = mkOption { + type = with types; listOf str; + default = null; + description = "Mount points to be used by chunkserver for storage (see mfshdd.cfg)."; + example = [ "/mnt/hdd1" ]; + }; + + settings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; + + options.DATA_PATH = mkOption { + type = types.str; + default = "/var/lib/mfs"; + description = "Directory for lock file."; + }; + }; + + description = "Contents of chunkserver config file (mfschunkserver.cfg)."; + }; + }; + }; + }; + + ###### implementation + + config = mkIf ( cfg.client.enable || cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) { + + warnings = [ ( mkIf (!cfg.runAsUser) "Running moosefs services as root is not recommended.") ]; + + # Service settings + services.moosefs = { + master.settings = mkIf cfg.master.enable { + WORKING_USER = mfsUser; + EXPORTS_FILENAME = toString ( pkgs.writeText "mfsexports.cfg" + (concatStringsSep "\n" cfg.master.exports)); + }; + + metalogger.settings = mkIf cfg.metalogger.enable { + WORKING_USER = mfsUser; + MASTER_HOST = cfg.masterHost; + }; + + chunkserver.settings = mkIf cfg.chunkserver.enable { + WORKING_USER = mfsUser; + MASTER_HOST = cfg.masterHost; + HDD_CONF_FILENAME = toString ( pkgs.writeText "mfshdd.cfg" + (concatStringsSep "\n" cfg.chunkserver.hdds)); + }; + }; + + # Create system user account for daemons + users = mkIf ( cfg.runAsUser && ( cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) ) { + users.moosefs = { + isSystemUser = true; + description = "moosefs daemon user"; + group = "moosefs"; + }; + groups.moosefs = {}; + }; + + environment.systemPackages = + (lib.optional cfg.client.enable pkgs.moosefs) ++ + (lib.optional cfg.master.enable initTool); + + networking.firewall.allowedTCPPorts = + (lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) ++ + (lib.optional cfg.chunkserver.openFirewall 9422); + + # Ensure storage directories exist + systemd.tmpfiles.rules = + optional cfg.master.enable "d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}" + ++ optional cfg.metalogger.enable "d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}" + ++ optional cfg.chunkserver.enable "d ${cfg.chunkserver.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"; + + # Service definitions + systemd.services.mfs-master = mkIf cfg.master.enable + ( systemdService "master" { + TimeoutStartSec = 1800; + TimeoutStopSec = 1800; + Restart = "no"; + } masterCfg ); + + systemd.services.mfs-metalogger = mkIf cfg.metalogger.enable + ( systemdService "metalogger" { Restart = "on-abnormal"; } metaloggerCfg ); + + systemd.services.mfs-chunkserver = mkIf cfg.chunkserver.enable + ( systemdService "chunkserver" { Restart = "on-abnormal"; } chunkserverCfg ); + }; +} |