lol
1{ lib
2, stdenv
3, runCommand
4, fetchurl
5, fetchFromGitHub
6, fetchPypi
7
8# Build time
9, cmake
10, ensureNewerSourcesHook
11, fmt
12, git
13, makeWrapper
14, nasm
15, pkg-config
16, which
17
18# Tests
19, nixosTests
20
21# Runtime dependencies
22, arrow-cpp
23, babeltrace
24, boost179
25, bzip2
26, cryptsetup
27, cunit
28, doxygen
29, gperf
30, graphviz
31, gtest
32, icu
33, libcap
34, libcap_ng
35, libnl
36, libxml2
37, lttng-ust
38, lua
39, lz4
40, oath-toolkit
41, openldap
42, python310
43, rdkafka
44, rocksdb
45, snappy
46, sqlite
47, utf8proc
48, zlib
49, zstd
50
51# Optional Dependencies
52, curl ? null
53, expat ? null
54, fuse ? null
55, libatomic_ops ? null
56, libedit ? null
57, libs3 ? null
58, yasm ? null
59
60# Mallocs
61, gperftools ? null
62, jemalloc ? null
63
64# Crypto Dependencies
65, cryptopp ? null
66, nspr ? null
67, nss ? null
68
69# Linux Only Dependencies
70, linuxHeaders
71, util-linux
72, libuuid
73, udev
74, keyutils
75, rdma-core
76, rabbitmq-c
77, libaio ? null
78, libxfs ? null
79, liburing ? null
80, zfs ? null
81, ...
82}:
83
84# We must have one crypto library
85assert cryptopp != null || (nss != null && nspr != null);
86
87let
88 shouldUsePkg = pkg: if pkg != null && lib.meta.availableOn stdenv.hostPlatform pkg then pkg else null;
89
90 optYasm = shouldUsePkg yasm;
91 optExpat = shouldUsePkg expat;
92 optCurl = shouldUsePkg curl;
93 optFuse = shouldUsePkg fuse;
94 optLibedit = shouldUsePkg libedit;
95 optLibatomic_ops = shouldUsePkg libatomic_ops;
96 optLibs3 = shouldUsePkg libs3;
97
98 optJemalloc = shouldUsePkg jemalloc;
99 optGperftools = shouldUsePkg gperftools;
100
101 optCryptopp = shouldUsePkg cryptopp;
102 optNss = shouldUsePkg nss;
103 optNspr = shouldUsePkg nspr;
104
105 optLibaio = shouldUsePkg libaio;
106 optLibxfs = shouldUsePkg libxfs;
107 optZfs = shouldUsePkg zfs;
108
109 # Downgrade rocksdb, 7.10 breaks ceph
110 rocksdb' = rocksdb.overrideAttrs {
111 version = "7.9.2";
112 src = fetchFromGitHub {
113 owner = "facebook";
114 repo = "rocksdb";
115 rev = "refs/tags/v7.9.2";
116 hash = "sha256-5P7IqJ14EZzDkbjaBvbix04ceGGdlWBuVFH/5dpD5VM=";
117 };
118 };
119
120 hasRadosgw = optExpat != null && optCurl != null && optLibedit != null;
121
122 # Malloc implementation (can be jemalloc, tcmalloc or null)
123 malloc = if optJemalloc != null then optJemalloc else optGperftools;
124
125 # We prefer nss over cryptopp
126 cryptoStr = if optNss != null && optNspr != null then "nss" else
127 if optCryptopp != null then "cryptopp" else "none";
128
129 cryptoLibsMap = {
130 nss = [ optNss optNspr ];
131 cryptopp = [ optCryptopp ];
132 none = [ ];
133 };
134
135 getMeta = description: with lib; {
136 homepage = "https://ceph.io/en/";
137 inherit description;
138 license = with licenses; [ lgpl21 gpl2 bsd3 mit publicDomain ];
139 maintainers = with maintainers; [ adev ak johanot krav ];
140 platforms = [ "x86_64-linux" "aarch64-linux" ];
141 };
142
143 ceph-common = with python.pkgs; buildPythonPackage {
144 pname = "ceph-common";
145 inherit src version;
146
147 sourceRoot = "ceph-${version}/src/python-common";
148
149 propagatedBuildInputs = [
150 pyyaml
151 ];
152
153 nativeCheckInputs = [
154 pytestCheckHook
155 ];
156
157 disabledTests = [
158 # requires network access
159 "test_valid_addr"
160 ];
161
162 meta = getMeta "Ceph common module for code shared by manager modules";
163 };
164
165 # Watch out for python <> boost compatibility
166 python = python310.override {
167 packageOverrides = self: super: {
168 };
169 };
170
171 boost = boost179.override {
172 enablePython = true;
173 inherit python;
174 };
175
176 # TODO: split this off in build and runtime environment
177 ceph-python-env = python.withPackages (ps: with ps; [
178 ceph-common
179
180 # build time
181 cython
182
183 # debian/control
184 bcrypt
185 cherrypy
186 influxdb
187 jinja2
188 kubernetes
189 natsort
190 numpy
191 pecan
192 prettytable
193 pyjwt
194 pyopenssl
195 python-dateutil
196 pyyaml
197 requests
198 routes
199 scikit-learn
200 scipy
201 setuptools
202 sphinx
203 virtualenv
204 werkzeug
205
206 # src/pybind/mgr/requirements-required.txt
207 cryptography
208 jsonpatch
209
210 # src/tools/cephfs/shell/setup.py
211 cmd2
212 colorama
213 ]);
214 inherit (ceph-python-env.python) sitePackages;
215
216 version = "18.2.0";
217 src = fetchurl {
218 url = "https://download.ceph.com/tarballs/ceph-${version}.tar.gz";
219 hash = "sha256:0k9nl6xi5brva51rr14m7ig27mmmd7vrpchcmqc40q3c2khn6ns9";
220 };
221in rec {
222 ceph = stdenv.mkDerivation {
223 pname = "ceph";
224 inherit src version;
225
226 nativeBuildInputs = [
227 cmake
228 fmt
229 git
230 makeWrapper
231 nasm
232 pkg-config
233 python
234 python.pkgs.python # for the toPythonPath function
235 python.pkgs.wrapPython
236 which
237 (ensureNewerSourcesHook { year = "1980"; })
238 # for building docs/man-pages presumably
239 doxygen
240 graphviz
241 ];
242
243 enableParallelBuilding = true;
244
245 buildInputs = cryptoLibsMap.${cryptoStr} ++ [
246 arrow-cpp
247 babeltrace
248 boost
249 bzip2
250 ceph-python-env
251 cryptsetup
252 cunit
253 gperf
254 gtest
255 icu
256 libcap
257 libnl
258 libxml2
259 lttng-ust
260 lua
261 lz4
262 malloc
263 oath-toolkit
264 openldap
265 optLibatomic_ops
266 optLibs3
267 optYasm
268 rdkafka
269 rocksdb'
270 snappy
271 sqlite
272 utf8proc
273 zlib
274 zstd
275 ] ++ lib.optionals stdenv.isLinux [
276 keyutils
277 libcap_ng
278 liburing
279 libuuid
280 linuxHeaders
281 optLibaio
282 optLibxfs
283 optZfs
284 rabbitmq-c
285 rdma-core
286 udev
287 util-linux
288 ] ++ lib.optionals hasRadosgw [
289 optCurl
290 optExpat
291 optFuse
292 optLibedit
293 ];
294
295 pythonPath = [ ceph-python-env "${placeholder "out"}/${ceph-python-env.sitePackages}" ];
296
297 preConfigure =''
298 substituteInPlace src/common/module.c --replace "/sbin/modinfo" "modinfo"
299 substituteInPlace src/common/module.c --replace "/sbin/modprobe" "modprobe"
300 substituteInPlace src/common/module.c --replace "/bin/grep" "grep"
301
302 # install target needs to be in PYTHONPATH for "*.pth support" check to succeed
303 # set PYTHONPATH, so the build system doesn't silently skip installing ceph-volume and others
304 export PYTHONPATH=${ceph-python-env}/${sitePackages}:$lib/${sitePackages}:$out/${sitePackages}
305 patchShebangs src/
306 '';
307
308 cmakeFlags = [
309 "-DCMAKE_INSTALL_DATADIR=${placeholder "lib"}/lib"
310
311 "-DWITH_CEPHFS_SHELL:BOOL=ON"
312 "-DWITH_SYSTEMD:BOOL=OFF"
313 # `WITH_JAEGER` requires `thrift` as a depenedncy (fine), but the build fails with:
314 # CMake Error at src/opentelemetry-cpp-stamp/opentelemetry-cpp-build-Release.cmake:49 (message):
315 # Command failed: 2
316 #
317 # 'make' 'opentelemetry_trace' 'opentelemetry_exporter_jaeger_trace'
318 #
319 # See also
320 #
321 # /build/ceph-18.2.0/build/src/opentelemetry-cpp/src/opentelemetry-cpp-stamp/opentelemetry-cpp-build-*.log
322 # and that file contains:
323 # /build/ceph-18.2.0/src/jaegertracing/opentelemetry-cpp/exporters/jaeger/src/TUDPTransport.cc: In member function 'virtual void opentelemetry::v1::exporter::jaeger::TUDPTransport::close()':
324 # /build/ceph-18.2.0/src/jaegertracing/opentelemetry-cpp/exporters/jaeger/src/TUDPTransport.cc:71:7: error: '::close' has not been declared; did you mean 'pclose'?
325 # 71 | ::THRIFT_CLOSESOCKET(socket_);
326 # | ^~~~~~~~~~~~~~~~~~
327 # Looks like `close()` is somehow not included.
328 # But the relevant code is already removed in `open-telemetry` 1.10: https://github.com/open-telemetry/opentelemetry-cpp/pull/2031
329 # So it's proably not worth trying to fix that for this Ceph version,
330 # and instead just disable Ceph's Jaeger support.
331 "-DWITH_JAEGER:BOOL=OFF"
332 "-DWITH_TESTS:BOOL=OFF"
333
334 # Use our own libraries, where possible
335 "-DWITH_SYSTEM_ARROW:BOOL=ON" # Only used if other options enable Arrow support.
336 "-DWITH_SYSTEM_BOOST:BOOL=ON"
337 "-DWITH_SYSTEM_GTEST:BOOL=ON"
338 "-DWITH_SYSTEM_ROCKSDB:BOOL=ON"
339 "-DWITH_SYSTEM_UTF8PROC:BOOL=ON"
340 "-DWITH_SYSTEM_ZSTD:BOOL=ON"
341
342 # TODO breaks with sandbox, tries to download stuff with npm
343 "-DWITH_MGR_DASHBOARD_FRONTEND:BOOL=OFF"
344 # WITH_XFS has been set default ON from Ceph 16, keeping it optional in nixpkgs for now
345 ''-DWITH_XFS=${if optLibxfs != null then "ON" else "OFF"}''
346 ] ++ lib.optional stdenv.isLinux "-DWITH_SYSTEM_LIBURING=ON";
347
348 postFixup = ''
349 wrapPythonPrograms
350 wrapProgram $out/bin/ceph-mgr --prefix PYTHONPATH ":" "$(toPythonPath ${placeholder "out"}):$(toPythonPath ${ceph-python-env})"
351
352 # Test that ceph-volume exists since the build system has a tendency to
353 # silently drop it with misconfigurations.
354 test -f $out/bin/ceph-volume
355 '';
356
357 outputs = [ "out" "lib" "dev" "doc" "man" ];
358
359 doCheck = false; # uses pip to install things from the internet
360
361 # Takes 7+h to build with 2 cores.
362 requiredSystemFeatures = [ "big-parallel" ];
363
364 meta = getMeta "Distributed storage system";
365
366 passthru = {
367 inherit version;
368 tests = {
369 inherit (nixosTests)
370 ceph-multi-node
371 ceph-single-node
372 ceph-single-node-bluestore;
373 };
374 };
375 };
376
377 ceph-client = runCommand "ceph-client-${version}" {
378 meta = getMeta "Tools needed to mount Ceph's RADOS Block Devices/Cephfs";
379 } ''
380 mkdir -p $out/{bin,etc,${sitePackages},share/bash-completion/completions}
381 cp -r ${ceph}/bin/{ceph,.ceph-wrapped,rados,rbd,rbdmap} $out/bin
382 cp -r ${ceph}/bin/ceph-{authtool,conf,dencoder,rbdnamer,syn} $out/bin
383 cp -r ${ceph}/bin/rbd-replay* $out/bin
384 cp -r ${ceph}/sbin/mount.ceph $out/bin
385 cp -r ${ceph}/sbin/mount.fuse.ceph $out/bin
386 ln -s bin $out/sbin
387 cp -r ${ceph}/${sitePackages}/* $out/${sitePackages}
388 cp -r ${ceph}/etc/bash_completion.d $out/share/bash-completion/completions
389 # wrapPythonPrograms modifies .ceph-wrapped, so lets just update its paths
390 substituteInPlace $out/bin/ceph --replace ${ceph} $out
391 substituteInPlace $out/bin/.ceph-wrapped --replace ${ceph} $out
392 '';
393}