02cf88bb76
GitOrigin-RevId: c4a0efdd5a728e20791b8d8d2f26f90ac228ee8d
443 lines
14 KiB
Nix
443 lines
14 KiB
Nix
{ config, lib, options, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.slurm;
|
|
opt = options.services.slurm;
|
|
# configuration file can be generated by http://slurm.schedmd.com/configurator.html
|
|
|
|
defaultUser = "slurm";
|
|
|
|
configFile = pkgs.writeTextDir "slurm.conf"
|
|
''
|
|
ClusterName=${cfg.clusterName}
|
|
StateSaveLocation=${cfg.stateSaveLocation}
|
|
SlurmUser=${cfg.user}
|
|
${optionalString (cfg.controlMachine != null) "controlMachine=${cfg.controlMachine}"}
|
|
${optionalString (cfg.controlAddr != null) "controlAddr=${cfg.controlAddr}"}
|
|
${toString (map (x: "NodeName=${x}\n") cfg.nodeName)}
|
|
${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)}
|
|
PlugStackConfig=${plugStackConfig}/plugstack.conf
|
|
ProctrackType=${cfg.procTrackType}
|
|
${cfg.extraConfig}
|
|
'';
|
|
|
|
plugStackConfig = pkgs.writeTextDir "plugstack.conf"
|
|
''
|
|
${optionalString cfg.enableSrunX11 "optional ${pkgs.slurm-spank-x11}/lib/x11.so"}
|
|
${cfg.extraPlugstackConfig}
|
|
'';
|
|
|
|
cgroupConfig = pkgs.writeTextDir "cgroup.conf"
|
|
''
|
|
${cfg.extraCgroupConfig}
|
|
'';
|
|
|
|
slurmdbdConf = pkgs.writeText "slurmdbd.conf"
|
|
''
|
|
DbdHost=${cfg.dbdserver.dbdHost}
|
|
SlurmUser=${cfg.user}
|
|
StorageType=accounting_storage/mysql
|
|
StorageUser=${cfg.dbdserver.storageUser}
|
|
${cfg.dbdserver.extraConfig}
|
|
'';
|
|
|
|
# slurm expects some additional config files to be
|
|
# in the same directory as slurm.conf
|
|
etcSlurm = pkgs.symlinkJoin {
|
|
name = "etc-slurm";
|
|
paths = [ configFile cgroupConfig plugStackConfig ] ++ cfg.extraConfigPaths;
|
|
};
|
|
in
|
|
|
|
{
|
|
|
|
###### interface
|
|
|
|
meta.maintainers = [ maintainers.markuskowa ];
|
|
|
|
options = {
|
|
|
|
services.slurm = {
|
|
|
|
server = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = lib.mdDoc ''
|
|
Whether to enable the slurm control daemon.
|
|
Note that the standard authentication method is "munge".
|
|
The "munge" service needs to be provided with a password file in order for
|
|
slurm to work properly (see `services.munge.password`).
|
|
'';
|
|
};
|
|
};
|
|
|
|
dbdserver = {
|
|
enable = mkEnableOption "SlurmDBD service";
|
|
|
|
dbdHost = mkOption {
|
|
type = types.str;
|
|
default = config.networking.hostName;
|
|
defaultText = literalExpression "config.networking.hostName";
|
|
description = lib.mdDoc ''
|
|
Hostname of the machine where `slurmdbd`
|
|
is running (i.e. name returned by `hostname -s`).
|
|
'';
|
|
};
|
|
|
|
storageUser = mkOption {
|
|
type = types.str;
|
|
default = cfg.user;
|
|
defaultText = literalExpression "config.${opt.user}";
|
|
description = lib.mdDoc ''
|
|
Database user name.
|
|
'';
|
|
};
|
|
|
|
storagePassFile = mkOption {
|
|
type = with types; nullOr str;
|
|
default = null;
|
|
description = lib.mdDoc ''
|
|
Path to file with database password. The content of this will be used to
|
|
create the password for the `StoragePass` option.
|
|
'';
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
type = types.lines;
|
|
default = "";
|
|
description = ''
|
|
Extra configuration for <literal>slurmdbd.conf</literal> See also:
|
|
<citerefentry><refentrytitle>slurmdbd.conf</refentrytitle>
|
|
<manvolnum>8</manvolnum></citerefentry>.
|
|
'';
|
|
};
|
|
};
|
|
|
|
client = {
|
|
enable = mkEnableOption "slurm client daemon";
|
|
};
|
|
|
|
enableStools = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = lib.mdDoc ''
|
|
Whether to provide a slurm.conf file.
|
|
Enable this option if you do not run a slurm daemon on this host
|
|
(i.e. `server.enable` and `client.enable` are `false`)
|
|
but you still want to run slurm commands from this host.
|
|
'';
|
|
};
|
|
|
|
package = mkOption {
|
|
type = types.package;
|
|
default = pkgs.slurm.override { enableX11 = ! cfg.enableSrunX11; };
|
|
defaultText = literalExpression "pkgs.slurm";
|
|
example = literalExpression "pkgs.slurm-full";
|
|
description = lib.mdDoc ''
|
|
The package to use for slurm binaries.
|
|
'';
|
|
};
|
|
|
|
controlMachine = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = null;
|
|
description = lib.mdDoc ''
|
|
The short hostname of the machine where SLURM control functions are
|
|
executed (i.e. the name returned by the command "hostname -s", use "tux001"
|
|
rather than "tux001.my.com").
|
|
'';
|
|
};
|
|
|
|
controlAddr = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = cfg.controlMachine;
|
|
defaultText = literalExpression "config.${opt.controlMachine}";
|
|
example = null;
|
|
description = lib.mdDoc ''
|
|
Name that ControlMachine should be referred to in establishing a
|
|
communications path.
|
|
'';
|
|
};
|
|
|
|
clusterName = mkOption {
|
|
type = types.str;
|
|
default = "default";
|
|
example = "myCluster";
|
|
description = lib.mdDoc ''
|
|
Necessary to distinguish accounting records in a multi-cluster environment.
|
|
'';
|
|
};
|
|
|
|
nodeName = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = literalExpression ''[ "linux[1-32] CPUs=1 State=UNKNOWN" ];'';
|
|
description = lib.mdDoc ''
|
|
Name that SLURM uses to refer to a node (or base partition for BlueGene
|
|
systems). Typically this would be the string that "/bin/hostname -s"
|
|
returns. Note that now you have to write node's parameters after the name.
|
|
'';
|
|
};
|
|
|
|
partitionName = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = literalExpression ''[ "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP" ];'';
|
|
description = lib.mdDoc ''
|
|
Name by which the partition may be referenced. Note that now you have
|
|
to write the partition's parameters after the name.
|
|
'';
|
|
};
|
|
|
|
enableSrunX11 = mkOption {
|
|
default = false;
|
|
type = types.bool;
|
|
description = lib.mdDoc ''
|
|
If enabled srun will accept the option "--x11" to allow for X11 forwarding
|
|
from within an interactive session or a batch job. This activates the
|
|
slurm-spank-x11 module. Note that this option also enables
|
|
{option}`services.openssh.forwardX11` on the client.
|
|
|
|
This option requires slurm to be compiled without native X11 support.
|
|
The default behavior is to re-compile the slurm package with native X11
|
|
support disabled if this option is set to true.
|
|
|
|
To use the native X11 support add `PrologFlags=X11` in {option}`extraConfig`.
|
|
Note that this method will only work RSA SSH host keys.
|
|
'';
|
|
};
|
|
|
|
procTrackType = mkOption {
|
|
type = types.str;
|
|
default = "proctrack/linuxproc";
|
|
description = lib.mdDoc ''
|
|
Plugin to be used for process tracking on a job step basis.
|
|
The slurmd daemon uses this mechanism to identify all processes
|
|
which are children of processes it spawns for a user job step.
|
|
'';
|
|
};
|
|
|
|
stateSaveLocation = mkOption {
|
|
type = types.str;
|
|
default = "/var/spool/slurmctld";
|
|
description = lib.mdDoc ''
|
|
Directory into which the Slurm controller, slurmctld, saves its state.
|
|
'';
|
|
};
|
|
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = defaultUser;
|
|
description = lib.mdDoc ''
|
|
Set this option when you want to run the slurmctld daemon
|
|
as something else than the default slurm user "slurm".
|
|
Note that the UID of this user needs to be the same
|
|
on all nodes.
|
|
'';
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
default = "";
|
|
type = types.lines;
|
|
description = lib.mdDoc ''
|
|
Extra configuration options that will be added verbatim at
|
|
the end of the slurm configuration file.
|
|
'';
|
|
};
|
|
|
|
extraPlugstackConfig = mkOption {
|
|
default = "";
|
|
type = types.lines;
|
|
description = lib.mdDoc ''
|
|
Extra configuration that will be added to the end of `plugstack.conf`.
|
|
'';
|
|
};
|
|
|
|
extraCgroupConfig = mkOption {
|
|
default = "";
|
|
type = types.lines;
|
|
description = lib.mdDoc ''
|
|
Extra configuration for `cgroup.conf`. This file is
|
|
used when `procTrackType=proctrack/cgroup`.
|
|
'';
|
|
};
|
|
|
|
extraConfigPaths = mkOption {
|
|
type = with types; listOf path;
|
|
default = [];
|
|
description = lib.mdDoc ''
|
|
Slurm expects config files for plugins in the same path
|
|
as `slurm.conf`. Add extra nix store
|
|
paths that should be merged into same directory as
|
|
`slurm.conf`.
|
|
'';
|
|
};
|
|
|
|
etcSlurm = mkOption {
|
|
type = types.path;
|
|
internal = true;
|
|
default = etcSlurm;
|
|
defaultText = literalDocBook ''
|
|
Directory created from generated config files and
|
|
<literal>config.${opt.extraConfigPaths}</literal>.
|
|
'';
|
|
description = ''
|
|
Path to directory with slurm config files. This option is set by default from the
|
|
Slurm module and is meant to make the Slurm config file available to other modules.
|
|
'';
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
imports = [
|
|
(mkRemovedOptionModule [ "services" "slurm" "dbdserver" "storagePass" ] ''
|
|
This option has been removed so that the database password is not exposed via the nix store.
|
|
Use services.slurm.dbdserver.storagePassFile to provide the database password.
|
|
'')
|
|
(mkRemovedOptionModule [ "services" "slurm" "dbdserver" "configFile" ] ''
|
|
This option has been removed. Use services.slurm.dbdserver.storagePassFile
|
|
and services.slurm.dbdserver.extraConfig instead.
|
|
'')
|
|
];
|
|
|
|
###### implementation
|
|
|
|
config =
|
|
let
|
|
wrappedSlurm = pkgs.stdenv.mkDerivation {
|
|
name = "wrappedSlurm";
|
|
|
|
builder = pkgs.writeText "builder.sh" ''
|
|
source $stdenv/setup
|
|
mkdir -p $out/bin
|
|
find ${getBin cfg.package}/bin -type f -executable | while read EXE
|
|
do
|
|
exename="$(basename $EXE)"
|
|
wrappername="$out/bin/$exename"
|
|
cat > "$wrappername" <<EOT
|
|
#!/bin/sh
|
|
if [ -z "$SLURM_CONF" ]
|
|
then
|
|
SLURM_CONF="${cfg.etcSlurm}/slurm.conf" "$EXE" "\$@"
|
|
else
|
|
"$EXE" "\$0"
|
|
fi
|
|
EOT
|
|
chmod +x "$wrappername"
|
|
done
|
|
|
|
mkdir -p $out/share
|
|
ln -s ${getBin cfg.package}/share/man $out/share/man
|
|
'';
|
|
};
|
|
|
|
in mkIf ( cfg.enableStools ||
|
|
cfg.client.enable ||
|
|
cfg.server.enable ||
|
|
cfg.dbdserver.enable ) {
|
|
|
|
environment.systemPackages = [ wrappedSlurm ];
|
|
|
|
services.munge.enable = mkDefault true;
|
|
|
|
# use a static uid as default to ensure it is the same on all nodes
|
|
users.users.slurm = mkIf (cfg.user == defaultUser) {
|
|
name = defaultUser;
|
|
group = "slurm";
|
|
uid = config.ids.uids.slurm;
|
|
};
|
|
|
|
users.groups.slurm.gid = config.ids.uids.slurm;
|
|
|
|
systemd.services.slurmd = mkIf (cfg.client.enable) {
|
|
path = with pkgs; [ wrappedSlurm coreutils ]
|
|
++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [
|
|
"systemd-tmpfiles-clean.service"
|
|
"munge.service"
|
|
"network-online.target"
|
|
"remote-fs.target"
|
|
];
|
|
wants = [ "network-online.target" ];
|
|
|
|
serviceConfig = {
|
|
Type = "forking";
|
|
KillMode = "process";
|
|
ExecStart = "${wrappedSlurm}/bin/slurmd";
|
|
PIDFile = "/run/slurmd.pid";
|
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
|
LimitMEMLOCK = "infinity";
|
|
Delegate="Yes";
|
|
};
|
|
};
|
|
|
|
systemd.tmpfiles.rules = mkIf cfg.client.enable [
|
|
"d /var/spool/slurmd 755 root root -"
|
|
];
|
|
|
|
services.openssh.forwardX11 = mkIf cfg.client.enable (mkDefault true);
|
|
|
|
systemd.services.slurmctld = mkIf (cfg.server.enable) {
|
|
path = with pkgs; [ wrappedSlurm munge coreutils ]
|
|
++ lib.optional cfg.enableSrunX11 slurm-spank-x11;
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" "munged.service" ];
|
|
requires = [ "munged.service" ];
|
|
|
|
serviceConfig = {
|
|
Type = "forking";
|
|
ExecStart = "${wrappedSlurm}/bin/slurmctld";
|
|
PIDFile = "/run/slurmctld.pid";
|
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
|
};
|
|
|
|
preStart = ''
|
|
mkdir -p ${cfg.stateSaveLocation}
|
|
chown -R ${cfg.user}:slurm ${cfg.stateSaveLocation}
|
|
'';
|
|
};
|
|
|
|
systemd.services.slurmdbd = let
|
|
# slurm strips the last component off the path
|
|
configPath = "$RUNTIME_DIRECTORY/slurmdbd.conf";
|
|
in mkIf (cfg.dbdserver.enable) {
|
|
path = with pkgs; [ wrappedSlurm munge coreutils ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "network.target" "munged.service" "mysql.service" ];
|
|
requires = [ "munged.service" "mysql.service" ];
|
|
|
|
preStart = ''
|
|
install -m 600 -o ${cfg.user} -T ${slurmdbdConf} ${configPath}
|
|
${optionalString (cfg.dbdserver.storagePassFile != null) ''
|
|
echo "StoragePass=$(cat ${cfg.dbdserver.storagePassFile})" \
|
|
>> ${configPath}
|
|
''}
|
|
'';
|
|
|
|
script = ''
|
|
export SLURM_CONF=${configPath}
|
|
exec ${cfg.package}/bin/slurmdbd -D
|
|
'';
|
|
|
|
serviceConfig = {
|
|
RuntimeDirectory = "slurmdbd";
|
|
Type = "simple";
|
|
PIDFile = "/run/slurmdbd.pid";
|
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
|
};
|
|
};
|
|
|
|
};
|
|
|
|
}
|