grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / network-filesystems / moosefs.nix
blob2fef0bec378c27119db5c028153a5ef911002c1f
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.moosefs;
5   mfsUser = if cfg.runAsUser then "moosefs" else "root";
7   settingsFormat = let
8     listSep = " ";
9     allowedTypes = with lib.types; [ bool int float str ];
10     valueToString = val:
11         if lib.isList val then lib.concatStringsSep listSep (map (x: valueToString x) val)
12         else if lib.isBool val then (if val then "1" else "0")
13         else toString val;
15     in {
16       type = with lib.types; let
17         valueType = oneOf ([
18           (listOf valueType)
19         ] ++ allowedTypes) // {
20           description = "Flat key-value file";
21         };
22       in attrsOf valueType;
24       generate = name: value:
25         pkgs.writeText name ( lib.concatStringsSep "\n" (
26           lib.mapAttrsToList (key: val: "${key} = ${valueToString val}") value ));
27     };
30   initTool = pkgs.writeShellScriptBin "mfsmaster-init" ''
31     if [ ! -e ${cfg.master.settings.DATA_PATH}/metadata.mfs ]; then
32       cp ${pkgs.moosefs}/var/mfs/metadata.mfs.empty ${cfg.master.settings.DATA_PATH}
33       chmod +w ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty
34       ${pkgs.moosefs}/bin/mfsmaster -a -c ${masterCfg} start
35       ${pkgs.moosefs}/bin/mfsmaster -c ${masterCfg} stop
36       rm ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty
37     fi
38   '';
40   # master config file
41   masterCfg = settingsFormat.generate
42     "mfsmaster.cfg" cfg.master.settings;
44   # metalogger config file
45   metaloggerCfg = settingsFormat.generate
46     "mfsmetalogger.cfg" cfg.metalogger.settings;
48   # chunkserver config file
49   chunkserverCfg = settingsFormat.generate
50     "mfschunkserver.cfg" cfg.chunkserver.settings;
52   # generic template for all daemons
53   systemdService = name: extraConfig: configFile: {
54     wantedBy = [ "multi-user.target" ];
55     wants = [ "network-online.target" ];
56     after = [ "network.target" "network-online.target" ];
58     serviceConfig = {
59       Type = "forking";
60       ExecStart  = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} start";
61       ExecStop   = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} stop";
62       ExecReload = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} reload";
63       PIDFile = "${cfg."${name}".settings.DATA_PATH}/.mfs${name}.lock";
64     } // extraConfig;
65   };
67 in {
68   ###### interface
70   options = {
71     services.moosefs = {
72       masterHost = lib.mkOption {
73         type = lib.types.str;
74         default = null;
75         description = "IP or DNS name of master host.";
76       };
78       runAsUser = lib.mkOption {
79         type = lib.types.bool;
80         default = true;
81         example = true;
82         description = "Run daemons as user moosefs instead of root.";
83       };
85       client.enable = lib.mkEnableOption "Moosefs client";
87       master = {
88         enable = lib.mkOption {
89           type = lib.types.bool;
90           description = ''
91             Enable Moosefs master daemon.
93             You need to run `mfsmaster-init` on a freshly installed master server to
94             initialize the `DATA_PATH` directory.
95           '';
96           default = false;
97         };
99         exports = lib.mkOption {
100           type = with lib.types; listOf str;
101           default = null;
102           description = "Paths to export (see mfsexports.cfg).";
103           example = [
104             "* / rw,alldirs,admin,maproot=0:0"
105             "* . rw"
106           ];
107         };
109         openFirewall = lib.mkOption {
110           type = lib.types.bool;
111           description = "Whether to automatically open the necessary ports in the firewall.";
112           default = false;
113         };
115         settings = lib.mkOption {
116           type = lib.types.submodule {
117             freeformType = settingsFormat.type;
119             options.DATA_PATH = lib.mkOption {
120               type = lib.types.str;
121               default = "/var/lib/mfs";
122               description = "Data storage directory.";
123             };
124           };
126           description = "Contents of config file (mfsmaster.cfg).";
127         };
128       };
130       metalogger = {
131         enable = lib.mkEnableOption "Moosefs metalogger daemon";
133         settings = lib.mkOption {
134           type = lib.types.submodule {
135             freeformType = settingsFormat.type;
137             options.DATA_PATH = lib.mkOption {
138               type = lib.types.str;
139               default = "/var/lib/mfs";
140               description = "Data storage directory";
141             };
142           };
144           description = "Contents of metalogger config file (mfsmetalogger.cfg).";
145         };
146       };
148       chunkserver = {
149         enable = lib.mkEnableOption "Moosefs chunkserver daemon";
151         openFirewall = lib.mkOption {
152           type = lib.types.bool;
153           description = "Whether to automatically open the necessary ports in the firewall.";
154           default = false;
155         };
157         hdds = lib.mkOption {
158           type = with lib.types; listOf str;
159           default =  null;
160           description = "Mount points to be used by chunkserver for storage (see mfshdd.cfg).";
161           example = [ "/mnt/hdd1" ];
162         };
164         settings = lib.mkOption {
165           type = lib.types.submodule {
166             freeformType = settingsFormat.type;
168             options.DATA_PATH = lib.mkOption {
169               type = lib.types.str;
170               default = "/var/lib/mfs";
171               description = "Directory for lock file.";
172             };
173           };
175           description = "Contents of chunkserver config file (mfschunkserver.cfg).";
176         };
177       };
178     };
179   };
181   ###### implementation
183   config =  lib.mkIf ( cfg.client.enable || cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) {
185     warnings = [ ( lib.mkIf (!cfg.runAsUser) "Running moosefs services as root is not recommended.") ];
187     # Service settings
188     services.moosefs = {
189       master.settings = lib.mkIf cfg.master.enable {
190         WORKING_USER = mfsUser;
191         EXPORTS_FILENAME = toString ( pkgs.writeText "mfsexports.cfg"
192           (lib.concatStringsSep "\n" cfg.master.exports));
193       };
195       metalogger.settings = lib.mkIf cfg.metalogger.enable {
196         WORKING_USER = mfsUser;
197         MASTER_HOST = cfg.masterHost;
198       };
200       chunkserver.settings = lib.mkIf cfg.chunkserver.enable {
201         WORKING_USER = mfsUser;
202         MASTER_HOST = cfg.masterHost;
203         HDD_CONF_FILENAME = toString ( pkgs.writeText "mfshdd.cfg"
204           (lib.concatStringsSep "\n" cfg.chunkserver.hdds));
205       };
206     };
208     # Create system user account for daemons
209     users = lib.mkIf ( cfg.runAsUser && ( cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) ) {
210       users.moosefs = {
211         isSystemUser = true;
212         description = "moosefs daemon user";
213         group = "moosefs";
214       };
215       groups.moosefs = {};
216     };
218     environment.systemPackages =
219       (lib.optional cfg.client.enable pkgs.moosefs) ++
220       (lib.optional cfg.master.enable initTool);
222     networking.firewall.allowedTCPPorts =
223       (lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) ++
224       (lib.optional cfg.chunkserver.openFirewall 9422);
226     # Ensure storage directories exist
227     systemd.tmpfiles.rules =
228          lib.optional cfg.master.enable "d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"
229       ++ lib.optional cfg.metalogger.enable "d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"
230       ++ lib.optional cfg.chunkserver.enable "d ${cfg.chunkserver.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}";
232     # Service definitions
233     systemd.services.mfs-master = lib.mkIf cfg.master.enable
234     ( systemdService "master" {
235       TimeoutStartSec = 1800;
236       TimeoutStopSec = 1800;
237       Restart = "no";
238     } masterCfg );
240     systemd.services.mfs-metalogger = lib.mkIf cfg.metalogger.enable
241       ( systemdService "metalogger" { Restart = "on-abnormal"; } metaloggerCfg );
243     systemd.services.mfs-chunkserver = lib.mkIf cfg.chunkserver.enable
244       ( systemdService "chunkserver" { Restart = "on-abnormal"; } chunkserverCfg );
245     };