1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.slurm;
8 # configuration file can be generated by http://slurm.schedmd.com/configurator.html
9 configFile = pkgs.writeText "slurm.conf"
10 ''
11 ${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''}
12 ${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''}
13 ${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''}
14 ${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''}
15 ${cfg.extraConfig}
16 '';
17in
18
19{
20
21 ###### interface
22
23 options = {
24
25 services.slurm = {
26
27 server = {
28 enable = mkEnableOption "slurm control daemon";
29
30 };
31
32 client = {
33 enable = mkEnableOption "slurm rlient daemon";
34
35 };
36
37 package = mkOption {
38 type = types.package;
39 default = pkgs.slurm;
40 defaultText = "pkgs.slurm";
41 example = literalExample "pkgs.slurm-full";
42 description = ''
43 The package to use for slurm binaries.
44 '';
45 };
46
47 controlMachine = mkOption {
48 type = types.nullOr types.str;
49 default = null;
50 example = null;
51 description = ''
52 The short hostname of the machine where SLURM control functions are
53 executed (i.e. the name returned by the command "hostname -s", use "tux001"
54 rather than "tux001.my.com").
55 '';
56 };
57
58 controlAddr = mkOption {
59 type = types.nullOr types.str;
60 default = cfg.controlMachine;
61 example = null;
62 description = ''
63 Name that ControlMachine should be referred to in establishing a
64 communications path.
65 '';
66 };
67
68 nodeName = mkOption {
69 type = types.nullOr types.str;
70 default = null;
71 example = "linux[1-32] CPUs=1 State=UNKNOWN";
72 description = ''
73 Name that SLURM uses to refer to a node (or base partition for BlueGene
74 systems). Typically this would be the string that "/bin/hostname -s"
75 returns. Note that now you have to write node's parameters after the name.
76 '';
77 };
78
79 partitionName = mkOption {
80 type = types.nullOr types.str;
81 default = null;
82 example = "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP";
83 description = ''
84 Name by which the partition may be referenced. Note that now you have
85 to write patrition's parameters after the name.
86 '';
87 };
88
89 extraConfig = mkOption {
90 default = "";
91 type = types.lines;
92 description = ''
93 Extra configuration options that will be added verbatim at
94 the end of the slurm configuration file.
95 '';
96 };
97 };
98
99 };
100
101
102 ###### implementation
103
104 config =
105 let
106 wrappedSlurm = pkgs.stdenv.mkDerivation {
107 name = "wrappedSlurm";
108
109 propagatedBuildInputs = [ cfg.package configFile ];
110
111 builder = pkgs.writeText "builder.sh" ''
112 source $stdenv/setup
113 mkdir -p $out/bin
114 find ${getBin cfg.package}/bin -type f -executable | while read EXE
115 do
116 exename="$(basename $EXE)"
117 wrappername="$out/bin/$exename"
118 cat > "$wrappername" <<EOT
119 #!/bin/sh
120 if [ -z "$SLURM_CONF" ]
121 then
122 SLURM_CONF="${configFile}" "$EXE" "\$@"
123 else
124 "$EXE" "\$0"
125 fi
126 EOT
127 chmod +x "$wrappername"
128 done
129 '';
130 };
131
132 in mkIf (cfg.client.enable || cfg.server.enable) {
133
134 environment.systemPackages = [ wrappedSlurm ];
135
136 systemd.services.slurmd = mkIf (cfg.client.enable) {
137 path = with pkgs; [ wrappedSlurm coreutils ];
138
139 wantedBy = [ "multi-user.target" ];
140 after = [ "systemd-tmpfiles-clean.service" ];
141
142 serviceConfig = {
143 Type = "forking";
144 ExecStart = "${wrappedSlurm}/bin/slurmd";
145 PIDFile = "/run/slurmd.pid";
146 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
147 };
148
149 preStart = ''
150 mkdir -p /var/spool
151 '';
152 };
153
154 systemd.services.slurmctld = mkIf (cfg.server.enable) {
155 path = with pkgs; [ wrappedSlurm munge coreutils ];
156
157 wantedBy = [ "multi-user.target" ];
158 after = [ "network.target" "munged.service" ];
159 requires = [ "munged.service" ];
160
161 serviceConfig = {
162 Type = "forking";
163 ExecStart = "${wrappedSlurm}/bin/slurmctld";
164 PIDFile = "/run/slurmctld.pid";
165 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
166 };
167 };
168
169 };
170
171}