1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.services.mesos.slave;
7
8 mkAttributes =
9 attrs: concatStringsSep ";" (mapAttrsToList
10 (k: v: "${k}:${v}")
11 (filterAttrs (k: v: v != null) attrs));
12 attribsArg = optionalString (cfg.attributes != {})
13 "--attributes=${mkAttributes cfg.attributes}";
14
15 containerizersArg = concatStringsSep "," (
16 lib.unique (
17 cfg.containerizers ++ (optional cfg.withDocker "docker")
18 )
19 );
20
21 imageProvidersArg = concatStringsSep "," (
22 lib.unique (
23 cfg.imageProviders ++ (optional cfg.withDocker "docker")
24 )
25 );
26
27 isolationArg = concatStringsSep "," (
28 lib.unique (
29 cfg.isolation ++ (optionals cfg.withDocker [ "filesystem/linux" "docker/runtime"])
30 )
31 );
32
33in {
34
35 options.services.mesos = {
36 slave = {
37 enable = mkOption {
38 description = "Whether to enable the Mesos Slave.";
39 default = false;
40 type = types.bool;
41 };
42
43 ip = mkOption {
44 description = "IP address to listen on.";
45 default = "0.0.0.0";
46 type = types.str;
47 };
48
49 port = mkOption {
50 description = "Port to listen on.";
51 default = 5051;
52 type = types.int;
53 };
54
55 advertiseIp = mkOption {
56 description = "IP address advertised to reach this agent.";
57 default = null;
58 type = types.nullOr types.str;
59 };
60
61 advertisePort = mkOption {
62 description = "Port advertised to reach this agent.";
63 default = null;
64 type = types.nullOr types.int;
65 };
66
67 containerizers = mkOption {
68 description = ''
69 List of containerizer implementations to compose in order to provide
70 containerization. Available options are mesos and docker.
71 The order the containerizers are specified is the order they are tried.
72 '';
73 default = [ "mesos" ];
74 type = types.listOf types.str;
75 };
76
77 imageProviders = mkOption {
78 description = "List of supported image providers, e.g., APPC,DOCKER.";
79 default = [ ];
80 type = types.listOf types.str;
81 };
82
83 imageProvisionerBackend = mkOption {
84 description = ''
85 Strategy for provisioning container rootfs from images,
86 e.g., aufs, bind, copy, overlay.
87 '';
88 default = "copy";
89 type = types.str;
90 };
91
92 isolation = mkOption {
93 description = ''
94 Isolation mechanisms to use, e.g., posix/cpu,posix/mem, or
95 cgroups/cpu,cgroups/mem, or network/port_mapping, or `gpu/nvidia` for nvidia
96 specific gpu isolation.
97 '';
98 default = [ "posix/cpu" "posix/mem" ];
99 type = types.listOf types.str;
100 };
101
102 master = mkOption {
103 description = ''
104 May be one of:
105 zk://host1:port1,host2:port2,.../path
106 zk://username:password@host1:port1,host2:port2,.../path
107 '';
108 type = types.str;
109 };
110
111 withHadoop = mkOption {
112 description = "Add the HADOOP_HOME to the slave.";
113 default = false;
114 type = types.bool;
115 };
116
117 withDocker = mkOption {
118 description = "Enable the docker containerizer.";
119 default = config.virtualisation.docker.enable;
120 type = types.bool;
121 };
122
123 dockerRegistry = mkOption {
124 description = ''
125 The default url for pulling Docker images.
126 It could either be a Docker registry server url,
127 or a local path in which Docker image archives are stored.
128 '';
129 default = null;
130 type = types.nullOr (types.either types.str types.path);
131 };
132
133 workDir = mkOption {
134 description = "The Mesos work directory.";
135 default = "/var/lib/mesos/slave";
136 type = types.str;
137 };
138
139 extraCmdLineOptions = mkOption {
140 description = ''
141 Extra command line options for Mesos Slave.
142
143 See https://mesos.apache.org/documentation/latest/configuration/
144 '';
145 default = [ "" ];
146 type = types.listOf types.str;
147 example = [ "--gc_delay=3days" ];
148 };
149
150 logLevel = mkOption {
151 description = ''
152 The logging level used. Possible values:
153 'INFO', 'WARNING', 'ERROR'
154 '';
155 default = "INFO";
156 type = types.str;
157 };
158
159 attributes = mkOption {
160 description = ''
161 Machine attributes for the slave instance.
162
163 Use caution when changing this; you may need to manually reset slave
164 metadata before the slave can re-register.
165 '';
166 default = {};
167 type = types.attrsOf types.str;
168 example = { rack = "aa";
169 host = "aabc123";
170 os = "nixos"; };
171 };
172
173 executorEnvironmentVariables = mkOption {
174 description = ''
175 The environment variables that should be passed to the executor, and thus subsequently task(s).
176 '';
177 default = {
178 PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
179 };
180 type = types.attrsOf types.str;
181 };
182 };
183
184 };
185
186 config = mkIf cfg.enable {
187 systemd.services.mesos-slave = {
188 description = "Mesos Slave";
189 wantedBy = [ "multi-user.target" ];
190 after = [ "network.target" ];
191 path = [ pkgs.stdenv.shellPackage ];
192 serviceConfig = {
193 ExecStart = ''
194 ${pkgs.mesos}/bin/mesos-slave \
195 --containerizers=${containerizersArg} \
196 --image_providers=${imageProvidersArg} \
197 --image_provisioner_backend=${cfg.imageProvisionerBackend} \
198 --isolation=${isolationArg} \
199 --ip=${cfg.ip} \
200 --port=${toString cfg.port} \
201 ${optionalString (cfg.advertiseIp != null) "--advertise_ip=${cfg.advertiseIp}"} \
202 ${optionalString (cfg.advertisePort != null) "--advertise_port=${toString cfg.advertisePort}"} \
203 --master=${cfg.master} \
204 --work_dir=${cfg.workDir} \
205 --logging_level=${cfg.logLevel} \
206 ${attribsArg} \
207 ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \
208 ${optionalString cfg.withDocker "--docker=${pkgs.docker}/libexec/docker/docker"} \
209 ${optionalString (cfg.dockerRegistry != null) "--docker_registry=${cfg.dockerRegistry}"} \
210 --executor_environment_variables=${lib.escapeShellArg (builtins.toJSON cfg.executorEnvironmentVariables)} \
211 ${toString cfg.extraCmdLineOptions}
212 '';
213 PermissionsStartOnly = true;
214 };
215 preStart = ''
216 mkdir -m 0700 -p ${cfg.workDir}
217 '';
218 };
219 };
220
221}