mirror of
https://github.com/deepseek-ai/3FS
synced 2025-06-26 18:16:45 +00:00
Merge 16468b0110 into 2db69ced80
This commit is contained in:
commit
666225ccc5
235
README-nix.md
Normal file
235
README-nix.md
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
# 3FS Nix Package and NixOS Module
|
||||||
|
|
||||||
|
This directory contains a Nix flake for building and deploying 3FS (Fire-Flyer File System) on NixOS systems.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Complete Package**: Builds 3FS with all dependencies including RDMA support, FoundationDB integration, and FUSE 3
|
||||||
|
- **NixOS Module**: Provides systemd services for all 3FS components (meta, storage, mgmtd, monitor, fuse)
|
||||||
|
- **Development Shell**: Includes all build tools and dependencies for 3FS development
|
||||||
|
- **Integration Tests**: NixOS VM tests to validate the complete system
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Building the Package
|
||||||
|
|
||||||
|
1. First build (will fail with hash mismatch):
|
||||||
|
```bash
|
||||||
|
nix build .#3fs
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Update the hash in `package.nix` with the correct one from the error message
|
||||||
|
|
||||||
|
3. Rebuild:
|
||||||
|
```bash
|
||||||
|
nix build .#3fs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using in NixOS
|
||||||
|
|
||||||
|
Add to your `flake.nix`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
threefs.url = "github:deepseek-ai/3fs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, threefs, ... }: {
|
||||||
|
nixosConfigurations.myserver = nixpkgs.lib.nixosSystem {
|
||||||
|
modules = [
|
||||||
|
threefs.nixosModules.default
|
||||||
|
{
|
||||||
|
services."3fs" = {
|
||||||
|
enable = true;
|
||||||
|
meta.enable = true;
|
||||||
|
storage.enable = true;
|
||||||
|
mgmtd.enable = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Environment
|
||||||
|
|
||||||
|
Enter the development shell:
|
||||||
|
```bash
|
||||||
|
nix develop
|
||||||
|
```
|
||||||
|
|
||||||
|
This provides:
|
||||||
|
- Clang 14 with C++20 support
|
||||||
|
- CMake and build tools
|
||||||
|
- All 3FS dependencies
|
||||||
|
- Rust toolchain
|
||||||
|
- Debug tools (gdb, valgrind, perf)
|
||||||
|
|
||||||
|
## NixOS Module Options
|
||||||
|
|
||||||
|
### Basic Configuration
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services."3fs" = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# User and group for services
|
||||||
|
user = "threefs";
|
||||||
|
group = "threefs";
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
configDir = "/etc/3fs";
|
||||||
|
dataDir = "/var/lib/3fs";
|
||||||
|
|
||||||
|
# FoundationDB cluster file
|
||||||
|
foundationdb.clusterFile = "/etc/foundationdb/fdb.cluster";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Configuration
|
||||||
|
|
||||||
|
#### Metadata Service
|
||||||
|
```nix
|
||||||
|
services."3fs".meta = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional meta configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Storage Service
|
||||||
|
```nix
|
||||||
|
services."3fs".storage = {
|
||||||
|
enable = true;
|
||||||
|
targets = [
|
||||||
|
"/var/lib/3fs/storage/target1"
|
||||||
|
"/var/lib/3fs/storage/target2"
|
||||||
|
];
|
||||||
|
config = {
|
||||||
|
# Additional storage configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Management Daemon
|
||||||
|
```nix
|
||||||
|
services."3fs".mgmtd = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional mgmtd configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Monitor Collector
|
||||||
|
```nix
|
||||||
|
services."3fs".monitor = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional monitor configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### FUSE Client
|
||||||
|
```nix
|
||||||
|
services."3fs".fuse = {
|
||||||
|
enable = true;
|
||||||
|
mountPoint = "/mnt/3fs";
|
||||||
|
config = {
|
||||||
|
# Additional FUSE configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Run Package Tests
|
||||||
|
```bash
|
||||||
|
./test-build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Integration Tests
|
||||||
|
```bash
|
||||||
|
nix build .#checks.x86_64-linux.integration-test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Testing
|
||||||
|
|
||||||
|
1. Start FoundationDB:
|
||||||
|
```bash
|
||||||
|
sudo systemctl start foundationdb
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Initialize 3FS cluster:
|
||||||
|
```bash
|
||||||
|
3fs-admin init-cluster
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Start 3FS services:
|
||||||
|
```bash
|
||||||
|
sudo systemctl start 3fs-mgmtd
|
||||||
|
sudo systemctl start 3fs-meta
|
||||||
|
sudo systemctl start 3fs-storage
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Mount filesystem:
|
||||||
|
```bash
|
||||||
|
sudo systemctl start 3fs-fuse
|
||||||
|
```
|
||||||
|
|
||||||
|
## Package Contents
|
||||||
|
|
||||||
|
The package includes:
|
||||||
|
|
||||||
|
- **Binaries**:
|
||||||
|
- `admin` - Administrative CLI tool
|
||||||
|
- `meta_main` - Metadata service
|
||||||
|
- `storage_main` - Storage service
|
||||||
|
- `mgmtd_main` - Management daemon
|
||||||
|
- `monitor_collector_main` - Metrics collector
|
||||||
|
- `hf3fs_fuse_main` - FUSE filesystem client
|
||||||
|
|
||||||
|
- **Libraries**: All required shared libraries in `/lib`
|
||||||
|
- **Configuration**: Default configuration files in `/etc/3fs`
|
||||||
|
- **Headers**: Development headers in `/include/3fs`
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Build Issues
|
||||||
|
|
||||||
|
1. **Hash mismatch**: Update the SHA256 hash in `package.nix`
|
||||||
|
2. **Missing dependencies**: Check that all system libraries are available
|
||||||
|
3. **Compilation errors**: Ensure you're using Clang 14 or newer
|
||||||
|
|
||||||
|
### Runtime Issues
|
||||||
|
|
||||||
|
1. **Service fails to start**: Check logs with `journalctl -u 3fs-<service>`
|
||||||
|
2. **FoundationDB connection**: Ensure FDB cluster file is correct
|
||||||
|
3. **FUSE mount fails**: Check that FUSE 3 is installed and kernel module is loaded
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The Nix package handles:
|
||||||
|
|
||||||
|
1. **Complex Dependencies**: Automatically builds custom jemalloc, handles RDMA libraries
|
||||||
|
2. **Third-party Libraries**: Uses system libraries where possible, builds others from source
|
||||||
|
3. **Rust Components**: Properly integrates Cargo builds for Rust components
|
||||||
|
4. **Service Management**: Complete systemd integration with proper dependencies
|
||||||
|
5. **Configuration**: Manages TOML configuration files for all components
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
When modifying the package:
|
||||||
|
|
||||||
|
1. Update version in `package.nix`
|
||||||
|
2. Test build locally
|
||||||
|
3. Run integration tests
|
||||||
|
4. Update documentation
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License (same as 3FS project)
|
||||||
61
flake.lock
Normal file
61
flake.lock
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1748190013,
|
||||||
|
"narHash": "sha256-R5HJFflOfsP5FBtk+zE8FpL8uqE7n62jqOsADvVshhE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "62b852f6c6742134ade1abdd2a21685fd617a291",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
368
flake.nix
Normal file
368
flake.nix
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
{
|
||||||
|
description = "Fire-Flyer File System (3FS) - High-performance distributed file system for AI workloads";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
let
|
||||||
|
overlay = final: prev: {
|
||||||
|
# Build clickhouse-cpp from source if not available in nixpkgs
|
||||||
|
clickhouse-cpp = prev.clickhouse-cpp or (prev.stdenv.mkDerivation rec {
|
||||||
|
pname = "clickhouse-cpp";
|
||||||
|
version = "2.5.1";
|
||||||
|
|
||||||
|
src = prev.fetchFromGitHub {
|
||||||
|
owner = "ClickHouse";
|
||||||
|
repo = "clickhouse-cpp";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-6kqcANO4S9Z1ee4kBPKGCnsPEGDaWPCx2hUi4APPWHU=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ prev.cmake ];
|
||||||
|
buildInputs = [ prev.zlib prev.openssl prev.lz4 ];
|
||||||
|
|
||||||
|
cmakeFlags = [
|
||||||
|
"-DBUILD_SHARED_LIBS=ON"
|
||||||
|
"-DWITH_OPENSSL=ON"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
# Build scnlib from source if not available in nixpkgs
|
||||||
|
scnlib = prev.scnlib or (prev.stdenv.mkDerivation rec {
|
||||||
|
pname = "scnlib";
|
||||||
|
version = "2.0.2";
|
||||||
|
|
||||||
|
src = prev.fetchFromGitHub {
|
||||||
|
owner = "eliaskosunen";
|
||||||
|
repo = "scnlib";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-YWlJiHAKKJd7jWv8Z0GmKqIfXI3HwVqA7AgZiHN2W8I=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ prev.cmake ];
|
||||||
|
|
||||||
|
cmakeFlags = [
|
||||||
|
"-DSCN_TESTS=OFF"
|
||||||
|
"-DSCN_EXAMPLES=OFF"
|
||||||
|
"-DSCN_BENCHMARKS=OFF"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
"3fs" = prev.callPackage ./package.nix {
|
||||||
|
inherit (final) clickhouse-cpp scnlib;
|
||||||
|
libibverbs = prev.rdma-core;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nixosModule = { config, lib, pkgs, ... }:
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.services."3fs";
|
||||||
|
|
||||||
|
# Helper function to create service configuration
|
||||||
|
mkServiceConfig = component: {
|
||||||
|
description = "3FS ${component} service";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
requires = [ "network-online.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${pkgs."3fs"}/bin/${component}_main --launcher_cfg ${cfg.configDir}/${component}_main_launcher.toml --app-cfg ${cfg.configDir}/${component}_main_app.toml";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 5;
|
||||||
|
LimitNOFILE = 1000000;
|
||||||
|
User = cfg.user;
|
||||||
|
Group = cfg.group;
|
||||||
|
} // (if component == "storage" then {
|
||||||
|
LimitMEMLOCK = "infinity";
|
||||||
|
TimeoutStopSec = "5m";
|
||||||
|
} else {});
|
||||||
|
|
||||||
|
environment = {
|
||||||
|
LD_LIBRARY_PATH = "${pkgs."3fs"}/lib:${pkgs.foundationdb}/lib";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services."3fs" = {
|
||||||
|
enable = mkEnableOption "3FS distributed file system";
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "threefs";
|
||||||
|
description = "User under which 3FS services run";
|
||||||
|
};
|
||||||
|
|
||||||
|
group = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "threefs";
|
||||||
|
description = "Group under which 3FS services run";
|
||||||
|
};
|
||||||
|
|
||||||
|
configDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/etc/3fs";
|
||||||
|
description = "Directory containing 3FS configuration files";
|
||||||
|
};
|
||||||
|
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/var/lib/3fs";
|
||||||
|
description = "Directory for 3FS data storage";
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
enable = mkEnableOption "3FS metadata service";
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Additional configuration for meta service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
storage = {
|
||||||
|
enable = mkEnableOption "3FS storage service";
|
||||||
|
|
||||||
|
targets = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ "/var/lib/3fs/storage" ];
|
||||||
|
description = "List of storage target directories";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Additional configuration for storage service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mgmtd = {
|
||||||
|
enable = mkEnableOption "3FS management daemon";
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Additional configuration for management daemon";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
monitor = {
|
||||||
|
enable = mkEnableOption "3FS monitor collector";
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Additional configuration for monitor collector";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
fuse = {
|
||||||
|
enable = mkEnableOption "3FS FUSE client";
|
||||||
|
|
||||||
|
mountPoint = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/mnt/3fs";
|
||||||
|
description = "Mount point for 3FS FUSE filesystem";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Additional configuration for FUSE client";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
foundationdb = {
|
||||||
|
clusterFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
default = "/etc/foundationdb/fdb.cluster";
|
||||||
|
description = "Path to FoundationDB cluster file";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
# Create system user and group
|
||||||
|
users.users.${cfg.user} = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = cfg.group;
|
||||||
|
home = cfg.dataDir;
|
||||||
|
createHome = true;
|
||||||
|
description = "3FS system user";
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${cfg.group} = {};
|
||||||
|
|
||||||
|
# Create necessary directories
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d '${cfg.configDir}' 0755 ${cfg.user} ${cfg.group} -"
|
||||||
|
"d '${cfg.dataDir}' 0755 ${cfg.user} ${cfg.group} -"
|
||||||
|
"d '${cfg.dataDir}/meta' 0755 ${cfg.user} ${cfg.group} -"
|
||||||
|
"d '${cfg.dataDir}/mgmtd' 0755 ${cfg.user} ${cfg.group} -"
|
||||||
|
"d '${cfg.dataDir}/monitor' 0755 ${cfg.user} ${cfg.group} -"
|
||||||
|
] ++ (map (target: "d '${target}' 0755 ${cfg.user} ${cfg.group} -") cfg.storage.targets);
|
||||||
|
|
||||||
|
# Install default configuration files
|
||||||
|
environment.etc = {
|
||||||
|
"3fs/meta_main_launcher.toml".source = "${pkgs."3fs"}/etc/3fs/meta_main_launcher.toml";
|
||||||
|
"3fs/meta_main_app.toml".source = "${pkgs."3fs"}/etc/3fs/meta_main_app.toml";
|
||||||
|
"3fs/storage_main_launcher.toml".source = "${pkgs."3fs"}/etc/3fs/storage_main_launcher.toml";
|
||||||
|
"3fs/storage_main_app.toml".source = "${pkgs."3fs"}/etc/3fs/storage_main_app.toml";
|
||||||
|
"3fs/mgmtd_main_launcher.toml".source = "${pkgs."3fs"}/etc/3fs/mgmtd_main_launcher.toml";
|
||||||
|
"3fs/mgmtd_main_app.toml".source = "${pkgs."3fs"}/etc/3fs/mgmtd_main_app.toml";
|
||||||
|
"3fs/monitor_collector_main.toml".source = "${pkgs."3fs"}/etc/3fs/monitor_collector_main.toml";
|
||||||
|
"3fs/hf3fs_fuse_main_launcher.toml".source = "${pkgs."3fs"}/etc/3fs/hf3fs_fuse_main_launcher.toml";
|
||||||
|
"3fs/hf3fs_fuse_main_app.toml".source = "${pkgs."3fs"}/etc/3fs/hf3fs_fuse_main_app.toml";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Define systemd services
|
||||||
|
systemd.services = {
|
||||||
|
"3fs-meta" = mkIf cfg.meta.enable (mkServiceConfig "meta");
|
||||||
|
"3fs-storage" = mkIf cfg.storage.enable (mkServiceConfig "storage");
|
||||||
|
"3fs-mgmtd" = mkIf cfg.mgmtd.enable (mkServiceConfig "mgmtd");
|
||||||
|
"3fs-monitor" = mkIf cfg.monitor.enable (mkServiceConfig "monitor_collector");
|
||||||
|
|
||||||
|
"3fs-fuse" = mkIf cfg.fuse.enable {
|
||||||
|
description = "3FS FUSE client";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network-online.target" "3fs-meta.service" ];
|
||||||
|
requires = [ "network-online.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
ExecStart = "${pkgs."3fs"}/bin/hf3fs_fuse_main --launcher_cfg ${cfg.configDir}/hf3fs_fuse_main_launcher.toml --app-cfg ${cfg.configDir}/hf3fs_fuse_main_app.toml ${cfg.fuse.mountPoint}";
|
||||||
|
ExecStop = "${pkgs.fuse3}/bin/fusermount3 -u ${cfg.fuse.mountPoint}";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 5;
|
||||||
|
LimitNOFILE = 1000000;
|
||||||
|
User = "root"; # FUSE requires root
|
||||||
|
Group = "root";
|
||||||
|
};
|
||||||
|
|
||||||
|
preStart = ''
|
||||||
|
mkdir -p ${cfg.fuse.mountPoint}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Add 3fs package to system packages
|
||||||
|
environment.systemPackages = [ pkgs."3fs" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ overlay ];
|
||||||
|
};
|
||||||
|
|
||||||
|
isLinux = pkgs.stdenv.isLinux;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = pkgs.lib.optionalAttrs isLinux {
|
||||||
|
default = pkgs."3fs";
|
||||||
|
"3fs" = pkgs."3fs";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Don't export overlays per-system
|
||||||
|
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
inputsFrom = pkgs.lib.optionals isLinux [ pkgs."3fs" ];
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
# Build dependencies that are cross-platform
|
||||||
|
cmake
|
||||||
|
pkg-config
|
||||||
|
boost
|
||||||
|
protobuf
|
||||||
|
grpc
|
||||||
|
gtest
|
||||||
|
glog
|
||||||
|
lz4
|
||||||
|
zlib
|
||||||
|
openssl
|
||||||
|
zstd
|
||||||
|
jemalloc
|
||||||
|
libevent
|
||||||
|
thrift
|
||||||
|
bison
|
||||||
|
flex
|
||||||
|
git
|
||||||
|
which
|
||||||
|
fmt
|
||||||
|
folly
|
||||||
|
rocksdb
|
||||||
|
leveldb
|
||||||
|
arrow-cpp
|
||||||
|
mimalloc
|
||||||
|
tomlplusplus
|
||||||
|
rustc
|
||||||
|
cargo
|
||||||
|
rustfmt
|
||||||
|
clippy
|
||||||
|
rustPlatform.bindgenHook
|
||||||
|
clickhouse-cpp
|
||||||
|
scnlib
|
||||||
|
|
||||||
|
# Additional dev tools
|
||||||
|
clang-tools_14
|
||||||
|
cmake-format
|
||||||
|
cmake-language-server
|
||||||
|
gdb
|
||||||
|
rust-analyzer
|
||||||
|
cargo-watch
|
||||||
|
] ++ pkgs.lib.optionals isLinux [
|
||||||
|
# Linux-only dependencies
|
||||||
|
foundationdb
|
||||||
|
fuse3
|
||||||
|
rdma-core
|
||||||
|
numactl
|
||||||
|
liburing
|
||||||
|
valgrind
|
||||||
|
perf-tools
|
||||||
|
];
|
||||||
|
|
||||||
|
shellHook = ''
|
||||||
|
echo "3FS development environment"
|
||||||
|
${if isLinux then ''
|
||||||
|
echo "Build with: nix build .#3fs"
|
||||||
|
'' else ''
|
||||||
|
echo "Note: 3FS can only be built on Linux systems"
|
||||||
|
''}
|
||||||
|
echo "Enter shell with: nix develop"
|
||||||
|
echo ""
|
||||||
|
echo "To test locally:"
|
||||||
|
echo " 1. Start FoundationDB"
|
||||||
|
echo " 2. Configure and start 3FS services"
|
||||||
|
echo " 3. Mount FUSE filesystem"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
checks = pkgs.lib.optionalAttrs isLinux {
|
||||||
|
# Package build test
|
||||||
|
package = pkgs."3fs";
|
||||||
|
} // pkgs.lib.optionalAttrs isLinux {
|
||||||
|
# Integration test using NixOS VM (Linux only)
|
||||||
|
integration-test = pkgs.nixosTest (import ./nixos-module-test.nix {
|
||||||
|
inherit pkgs self;
|
||||||
|
lib = pkgs.lib;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) // {
|
||||||
|
nixosModules.default = nixosModule;
|
||||||
|
nixosModules."3fs" = nixosModule;
|
||||||
|
|
||||||
|
overlays.default = overlay;
|
||||||
|
|
||||||
|
# Hydra job for CI - only for Linux systems
|
||||||
|
hydraJobs = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (system: {
|
||||||
|
packages = self.packages.${system};
|
||||||
|
tests = self.checks.${system} or {};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
210
nixos-module-test.nix
Normal file
210
nixos-module-test.nix
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
# NixOS VM test for 3FS services
|
||||||
|
# Run with: nix build .#checks.x86_64-linux.3fs-integration-test
|
||||||
|
|
||||||
|
{ pkgs, lib, self, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
# Test configuration for 3FS cluster
|
||||||
|
testConfig = {
|
||||||
|
meta = {
|
||||||
|
port = 6000;
|
||||||
|
dataDir = "/var/lib/3fs/meta";
|
||||||
|
};
|
||||||
|
|
||||||
|
storage = {
|
||||||
|
port = 7000;
|
||||||
|
targets = [
|
||||||
|
"/var/lib/3fs/storage/target1"
|
||||||
|
"/var/lib/3fs/storage/target2"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
mgmtd = {
|
||||||
|
port = 8000;
|
||||||
|
dataDir = "/var/lib/3fs/mgmtd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in {
|
||||||
|
name = "3fs-integration-test";
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
# Master node running all services
|
||||||
|
master = { config, pkgs, ... }: {
|
||||||
|
imports = [ self.nixosModules.default ];
|
||||||
|
|
||||||
|
# Enable 3FS services
|
||||||
|
services."3fs" = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
inherit (testConfig.meta) port dataDir;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
storage = {
|
||||||
|
enable = true;
|
||||||
|
targets = testConfig.storage.targets;
|
||||||
|
config = {
|
||||||
|
inherit (testConfig.storage) port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mgmtd = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
inherit (testConfig.mgmtd) port dataDir;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
monitor = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
port = 9000;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# FoundationDB configuration is handled by the system service
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure FoundationDB
|
||||||
|
services.foundationdb = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.foundationdb;
|
||||||
|
listenAddress = "127.0.0.1:4500";
|
||||||
|
dataDir = "/var/lib/foundationdb";
|
||||||
|
logDir = "/var/log/foundationdb";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open firewall ports
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
|
||||||
|
# Additional test utilities
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
netcat
|
||||||
|
curl
|
||||||
|
jq
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Client node with FUSE mount
|
||||||
|
client = { config, pkgs, ... }: {
|
||||||
|
imports = [ self.nixosModules.default ];
|
||||||
|
|
||||||
|
services."3fs" = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
fuse = {
|
||||||
|
enable = true;
|
||||||
|
mountPoint = "/mnt/3fs";
|
||||||
|
config = {
|
||||||
|
metaServers = [ "master:6000" ];
|
||||||
|
mgmtdServers = [ "master:8000" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# FoundationDB configuration is handled by the system service
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure FoundationDB client
|
||||||
|
services.foundationdb = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.foundationdb;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Write cluster file pointing to master
|
||||||
|
environment.etc."foundationdb/fdb.cluster" = {
|
||||||
|
text = "test:test@master:4500";
|
||||||
|
mode = "0644";
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
fio
|
||||||
|
sysbench
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
# Wait for FoundationDB to be ready
|
||||||
|
master.wait_for_unit("foundationdb.service")
|
||||||
|
master.wait_for_open_port(4500)
|
||||||
|
master.succeed("fdbcli --exec 'status' -C /etc/foundationdb/fdb.cluster")
|
||||||
|
|
||||||
|
# Wait for 3FS services to start
|
||||||
|
master.wait_for_unit("3fs-mgmtd.service")
|
||||||
|
master.wait_for_unit("3fs-meta.service")
|
||||||
|
master.wait_for_unit("3fs-storage.service")
|
||||||
|
master.wait_for_unit("3fs-monitor.service")
|
||||||
|
|
||||||
|
# Check that services are listening on correct ports
|
||||||
|
master.wait_for_open_port(${toString testConfig.meta.port})
|
||||||
|
master.wait_for_open_port(${toString testConfig.storage.port})
|
||||||
|
master.wait_for_open_port(${toString testConfig.mgmtd.port})
|
||||||
|
master.wait_for_open_port(9000) # monitor
|
||||||
|
|
||||||
|
# Check service status
|
||||||
|
master.succeed("systemctl is-active 3fs-mgmtd.service")
|
||||||
|
master.succeed("systemctl is-active 3fs-meta.service")
|
||||||
|
master.succeed("systemctl is-active 3fs-storage.service")
|
||||||
|
master.succeed("systemctl is-active 3fs-monitor.service")
|
||||||
|
|
||||||
|
# Initialize 3FS cluster
|
||||||
|
master.succeed("${pkgs."3fs"}/bin/admin init-cluster --config /etc/foundationdb/fdb.cluster")
|
||||||
|
|
||||||
|
# Register storage nodes
|
||||||
|
master.succeed("${pkgs."3fs"}/bin/admin register-node --type storage --address master:${toString testConfig.storage.port}")
|
||||||
|
|
||||||
|
# Create storage targets
|
||||||
|
for target in ${lib.concatStringsSep " " (map (t: "\"${t}\"") testConfig.storage.targets)}; do
|
||||||
|
master.succeed("${pkgs."3fs"}/bin/admin create-target --path $target")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Wait for client to connect
|
||||||
|
client.wait_for_unit("3fs-fuse.service")
|
||||||
|
client.wait_until_succeeds("mountpoint -q /mnt/3fs")
|
||||||
|
|
||||||
|
# Basic filesystem operations test
|
||||||
|
client.succeed("echo 'Hello 3FS!' > /mnt/3fs/test.txt")
|
||||||
|
client.succeed("cat /mnt/3fs/test.txt | grep 'Hello 3FS!'")
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
client.succeed("mkdir -p /mnt/3fs/test/deep/directory")
|
||||||
|
client.succeed("touch /mnt/3fs/test/deep/directory/file.txt")
|
||||||
|
client.succeed("ls -la /mnt/3fs/test/deep/directory/")
|
||||||
|
|
||||||
|
# Test file operations
|
||||||
|
client.succeed("dd if=/dev/urandom of=/mnt/3fs/random.dat bs=1M count=10")
|
||||||
|
client.succeed("cp /mnt/3fs/random.dat /mnt/3fs/random_copy.dat")
|
||||||
|
client.succeed("cmp /mnt/3fs/random.dat /mnt/3fs/random_copy.dat")
|
||||||
|
|
||||||
|
# Test permissions
|
||||||
|
client.succeed("chmod 755 /mnt/3fs/test")
|
||||||
|
client.succeed("test -d /mnt/3fs/test")
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
client.succeed("rm -rf /mnt/3fs/test*")
|
||||||
|
client.succeed("rm -f /mnt/3fs/random*.dat")
|
||||||
|
|
||||||
|
# Verify cleanup
|
||||||
|
client.succeed("test -z \"$(ls -A /mnt/3fs)\"")
|
||||||
|
|
||||||
|
# Check metrics
|
||||||
|
master.succeed("${pkgs."3fs"}/bin/admin list-nodes")
|
||||||
|
master.succeed("${pkgs."3fs"}/bin/admin list-targets")
|
||||||
|
|
||||||
|
# Test service restart
|
||||||
|
master.succeed("systemctl restart 3fs-storage.service")
|
||||||
|
master.wait_for_unit("3fs-storage.service")
|
||||||
|
|
||||||
|
# Ensure filesystem still works after restart
|
||||||
|
client.succeed("echo 'Still working!' > /mnt/3fs/restart-test.txt")
|
||||||
|
client.succeed("cat /mnt/3fs/restart-test.txt")
|
||||||
|
'';
|
||||||
|
}
|
||||||
102
nixos-test-config.nix
Normal file
102
nixos-test-config.nix
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Example NixOS configuration for testing 3FS
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
# Import the 3FS flake module
|
||||||
|
# In a real system, you would use:
|
||||||
|
# (builtins.getFlake "github:deepseek-ai/3fs").nixosModules.default
|
||||||
|
];
|
||||||
|
|
||||||
|
# Enable 3FS services
|
||||||
|
services."3fs" = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
# Configure user and group
|
||||||
|
user = "threefs";
|
||||||
|
group = "threefs";
|
||||||
|
|
||||||
|
# Configure directories
|
||||||
|
configDir = "/etc/3fs";
|
||||||
|
dataDir = "/var/lib/3fs";
|
||||||
|
|
||||||
|
# Enable metadata service
|
||||||
|
meta = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional meta service configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable storage service
|
||||||
|
storage = {
|
||||||
|
enable = true;
|
||||||
|
targets = [
|
||||||
|
"/var/lib/3fs/storage/target1"
|
||||||
|
"/var/lib/3fs/storage/target2"
|
||||||
|
];
|
||||||
|
config = {
|
||||||
|
# Additional storage service configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable management daemon
|
||||||
|
mgmtd = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional mgmtd configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable monitor collector
|
||||||
|
monitor = {
|
||||||
|
enable = true;
|
||||||
|
config = {
|
||||||
|
# Additional monitor configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable FUSE client
|
||||||
|
fuse = {
|
||||||
|
enable = true;
|
||||||
|
mountPoint = "/mnt/3fs";
|
||||||
|
config = {
|
||||||
|
# Additional FUSE configuration
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# FoundationDB configuration
|
||||||
|
foundationdb = {
|
||||||
|
clusterFile = "/etc/foundationdb/fdb.cluster";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Ensure FoundationDB is also installed and configured
|
||||||
|
services.foundationdb = {
|
||||||
|
enable = true;
|
||||||
|
clusterFile = "/etc/foundationdb/fdb.cluster";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open necessary ports for 3FS services
|
||||||
|
networking.firewall = {
|
||||||
|
allowedTCPPorts = [
|
||||||
|
# Meta service ports
|
||||||
|
6000 6001
|
||||||
|
# Storage service ports
|
||||||
|
7000 7001
|
||||||
|
# Management daemon ports
|
||||||
|
8000 8001
|
||||||
|
# Monitor collector ports
|
||||||
|
9000 9001
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example of how to override package
|
||||||
|
nixpkgs.overlays = [
|
||||||
|
(final: prev: {
|
||||||
|
"3fs" = prev."3fs".overrideAttrs (oldAttrs: {
|
||||||
|
# Custom overrides if needed
|
||||||
|
});
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
||||||
378
package.nix
Normal file
378
package.nix
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
{ stdenv
|
||||||
|
, lib
|
||||||
|
, fetchFromGitHub
|
||||||
|
, runCommand
|
||||||
|
, writeText
|
||||||
|
, makeWrapper
|
||||||
|
, cmake
|
||||||
|
, pkg-config
|
||||||
|
, clang_14
|
||||||
|
, lld_14
|
||||||
|
, rustc
|
||||||
|
, cargo
|
||||||
|
, rustPlatform
|
||||||
|
, autoconf
|
||||||
|
, automake
|
||||||
|
, libtool
|
||||||
|
, python3
|
||||||
|
, boost
|
||||||
|
, libuv
|
||||||
|
, lz4
|
||||||
|
, xz
|
||||||
|
, double-conversion
|
||||||
|
, libdwarf
|
||||||
|
, libunwind
|
||||||
|
, libaio
|
||||||
|
, gflags
|
||||||
|
, glog
|
||||||
|
, gtest
|
||||||
|
, gperftools
|
||||||
|
, openssl
|
||||||
|
, fuse3
|
||||||
|
, foundationdb
|
||||||
|
, rdma-core
|
||||||
|
, libibverbs
|
||||||
|
, zstd
|
||||||
|
, jemalloc
|
||||||
|
, libevent
|
||||||
|
, numactl
|
||||||
|
, liburing
|
||||||
|
, thrift
|
||||||
|
, bison
|
||||||
|
, flex
|
||||||
|
, git
|
||||||
|
, which
|
||||||
|
, fmt
|
||||||
|
, folly
|
||||||
|
, rocksdb
|
||||||
|
, leveldb
|
||||||
|
, arrow-cpp
|
||||||
|
, mimalloc
|
||||||
|
, clickhouse-cpp
|
||||||
|
, tomlplusplus
|
||||||
|
, scnlib
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# Build jemalloc with specific configuration for 3FS
|
||||||
|
jemalloc-custom = jemalloc.overrideAttrs (oldAttrs: {
|
||||||
|
configureFlags = (oldAttrs.configureFlags or []) ++ [
|
||||||
|
"--disable-cxx"
|
||||||
|
"--enable-prof"
|
||||||
|
"--disable-initial-exec-tls"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
# Custom FoundationDB build if needed
|
||||||
|
fdb-version = "7.1.5";
|
||||||
|
|
||||||
|
in stdenv.mkDerivation rec {
|
||||||
|
pname = "3fs";
|
||||||
|
version = "0.1.5";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "deepseek-ai";
|
||||||
|
repo = "3fs";
|
||||||
|
rev = "91bfcf39a9e4b5ded959f7b5c2cb0cf858ebbff5";
|
||||||
|
sha256 = "sha256-0000000000000000000000000000000000000000000="; # To be replaced
|
||||||
|
fetchSubmodules = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
cmake
|
||||||
|
pkg-config
|
||||||
|
clang_14
|
||||||
|
lld_14
|
||||||
|
rustc
|
||||||
|
cargo
|
||||||
|
rustPlatform.cargoSetupHook
|
||||||
|
autoconf
|
||||||
|
automake
|
||||||
|
libtool
|
||||||
|
python3
|
||||||
|
git
|
||||||
|
which
|
||||||
|
bison
|
||||||
|
flex
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
# Core dependencies
|
||||||
|
boost
|
||||||
|
libuv
|
||||||
|
lz4
|
||||||
|
xz
|
||||||
|
double-conversion
|
||||||
|
libdwarf
|
||||||
|
libunwind
|
||||||
|
libaio
|
||||||
|
gflags
|
||||||
|
glog
|
||||||
|
gtest
|
||||||
|
gperftools
|
||||||
|
openssl
|
||||||
|
|
||||||
|
# FUSE 3
|
||||||
|
fuse3
|
||||||
|
|
||||||
|
# FoundationDB
|
||||||
|
foundationdb
|
||||||
|
|
||||||
|
# RDMA/InfiniBand
|
||||||
|
rdma-core
|
||||||
|
libibverbs
|
||||||
|
|
||||||
|
# Additional libraries
|
||||||
|
zstd
|
||||||
|
jemalloc-custom
|
||||||
|
libevent
|
||||||
|
numactl
|
||||||
|
liburing
|
||||||
|
thrift
|
||||||
|
fmt
|
||||||
|
folly
|
||||||
|
rocksdb
|
||||||
|
leveldb
|
||||||
|
mimalloc
|
||||||
|
tomlplusplus
|
||||||
|
|
||||||
|
# Python bindings
|
||||||
|
python3.pkgs.pybind11
|
||||||
|
];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
# Add any necessary patches here
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
# Apply the repository patches
|
||||||
|
patchShebangs ./patches/apply.sh
|
||||||
|
./patches/apply.sh || true
|
||||||
|
|
||||||
|
# Fix CMake to use system libraries
|
||||||
|
substituteInPlace CMakeLists.txt \
|
||||||
|
--replace 'add_link_options(-fuse-ld=lld)' '# add_link_options(-fuse-ld=lld)' \
|
||||||
|
--replace 'set(CMAKE_CXX_FLAGS "$' 'set(CMAKE_CXX_FLAGS "$'
|
||||||
|
|
||||||
|
# Disable bundled third-party libraries
|
||||||
|
for lib in fmt zstd googletest folly leveldb rocksdb scnlib pybind11 toml11 mimalloc clickhouse-cpp liburing-cmake; do
|
||||||
|
substituteInPlace CMakeLists.txt \
|
||||||
|
--replace "add_subdirectory(\"third_party/$lib\"" "#add_subdirectory(\"third_party/$lib\""
|
||||||
|
done
|
||||||
|
|
||||||
|
# Fix jemalloc build
|
||||||
|
substituteInPlace cmake/Jemalloc.cmake \
|
||||||
|
--replace 'ExternalProject_add(' 'return() #ExternalProject_add(' \
|
||||||
|
--replace "\''${JEMALLOC_DIR}/lib/libjemalloc.so.2" "\''${jemalloc-custom}/lib/libjemalloc.so"
|
||||||
|
|
||||||
|
# Fix Apache Arrow build
|
||||||
|
substituteInPlace cmake/ApacheArrow.cmake \
|
||||||
|
--replace 'ExternalProject_Add(' 'return() #ExternalProject_Add('
|
||||||
|
|
||||||
|
# Set up Rust dependencies
|
||||||
|
cd src/client/trash_cleaner
|
||||||
|
cargoDepsCopy="$NIX_BUILD_TOP/cargo-vendor-dir"
|
||||||
|
if [ -d "$cargoDepsCopy" ]; then
|
||||||
|
chmod -R +w "$cargoDepsCopy"
|
||||||
|
fi
|
||||||
|
cd $NIX_BUILD_TOP/source
|
||||||
|
|
||||||
|
# Fix storage chunk_engine Rust build
|
||||||
|
cd src/storage/chunk_engine
|
||||||
|
cargoDepsCopy="$NIX_BUILD_TOP/cargo-vendor-dir"
|
||||||
|
if [ -d "$cargoDepsCopy" ]; then
|
||||||
|
chmod -R +w "$cargoDepsCopy"
|
||||||
|
fi
|
||||||
|
cd $NIX_BUILD_TOP/source
|
||||||
|
'';
|
||||||
|
|
||||||
|
preConfigure = ''
|
||||||
|
# Create necessary directories
|
||||||
|
mkdir -p $TMP/third_party
|
||||||
|
|
||||||
|
# Setup environment
|
||||||
|
export HOME=$TMP
|
||||||
|
export CARGO_HOME=$TMP/.cargo
|
||||||
|
|
||||||
|
# Set up library paths
|
||||||
|
export BOOST_ROOT=${boost}
|
||||||
|
export BOOST_INCLUDEDIR=${boost}/include
|
||||||
|
export BOOST_LIBRARYDIR=${boost}/lib
|
||||||
|
|
||||||
|
# FoundationDB paths
|
||||||
|
export FDB_LIBRARY_DIR=${foundationdb}/lib
|
||||||
|
export FDB_INCLUDE_DIR=${foundationdb}/include
|
||||||
|
|
||||||
|
# Jemalloc paths
|
||||||
|
export JEMALLOC_OVERRIDE=${jemalloc-custom}/lib/libjemalloc.so
|
||||||
|
export JEMALLOC_DIR=${jemalloc-custom}
|
||||||
|
|
||||||
|
# Compiler flags
|
||||||
|
export CXXFLAGS="-I${boost}/include -I${gtest}/include -I${liburing}/include -I${fmt}/include -I${folly}/include"
|
||||||
|
export LDFLAGS="-L${boost}/lib -L${jemalloc-custom}/lib -L${liburing}/lib -L${fmt}/lib -L${folly}/lib"
|
||||||
|
'';
|
||||||
|
|
||||||
|
cmakeFlags = [
|
||||||
|
"-DCMAKE_CXX_COMPILER=${clang_14}/bin/clang++"
|
||||||
|
"-DCMAKE_C_COMPILER=${clang_14}/bin/clang"
|
||||||
|
"-DCMAKE_BUILD_TYPE=RelWithDebInfo"
|
||||||
|
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||||
|
"-DENABLE_FUSE_APPLICATION=ON"
|
||||||
|
"-DOVERRIDE_CXX_NEW_DELETE=OFF"
|
||||||
|
"-DSAVE_ALLOCATE_SIZE=OFF"
|
||||||
|
"-DBoost_USE_STATIC_LIBS=ON"
|
||||||
|
"-DFDB_VERSION=${fdb-version}"
|
||||||
|
|
||||||
|
# System library paths
|
||||||
|
"-DCMAKE_PREFIX_PATH=${boost};${gtest};${liburing};${fmt};${folly}"
|
||||||
|
"-DBoost_DIR=${boost}/lib/cmake/Boost"
|
||||||
|
"-DBoost_INCLUDE_DIR=${boost}/include"
|
||||||
|
"-Dfmt_DIR=${fmt}/lib/cmake/fmt"
|
||||||
|
"-DFolly_DIR=${folly}/lib/cmake/folly"
|
||||||
|
"-DGTest_DIR=${gtest}/lib/cmake/GTest"
|
||||||
|
"-DZSTD_LIBRARY=${zstd}/lib/libzstd.so"
|
||||||
|
"-DZSTD_INCLUDE_DIR=${zstd}/include"
|
||||||
|
"-Djemalloc_INCLUDE_DIR=${jemalloc-custom}/include"
|
||||||
|
"-Djemalloc_LIBRARY=${jemalloc-custom}/lib/libjemalloc.so"
|
||||||
|
"-DJEMALLOC_DIR=${jemalloc-custom}"
|
||||||
|
"-DARROW_INCLUDE_DIR=${arrow-cpp}/include"
|
||||||
|
"-DARROW_LIB_DIR=${arrow-cpp}/lib"
|
||||||
|
"-Darrow_DIR=${arrow-cpp}/lib/cmake/arrow"
|
||||||
|
|
||||||
|
# Initially disable tests to simplify build
|
||||||
|
"-DBUILD_TESTING=OFF"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Custom build phase to handle complex build process
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
# Build with decreasing parallelism if needed
|
||||||
|
cmake --build . -j $NIX_BUILD_CORES || \
|
||||||
|
cmake --build . -j 4 || \
|
||||||
|
cmake --build . -j 1
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
# Create output directories
|
||||||
|
mkdir -p $out/bin $out/lib $out/etc/3fs
|
||||||
|
|
||||||
|
# Install binaries
|
||||||
|
for bin in \
|
||||||
|
src/fuse/hf3fs_fuse \
|
||||||
|
src/client/cli/admin/admin \
|
||||||
|
src/meta/meta \
|
||||||
|
src/mgmtd/mgmtd \
|
||||||
|
src/storage/storage \
|
||||||
|
src/monitor_collector/monitor_collector \
|
||||||
|
src/tools/admin
|
||||||
|
do
|
||||||
|
if [ -f "$bin" ] && [ -x "$bin" ]; then
|
||||||
|
install -D -m755 "$bin" "$out/bin/$(basename $bin)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Rename main binaries to match systemd service expectations
|
||||||
|
[ -f "$out/bin/meta" ] && mv "$out/bin/meta" "$out/bin/meta_main"
|
||||||
|
[ -f "$out/bin/mgmtd" ] && mv "$out/bin/mgmtd" "$out/bin/mgmtd_main"
|
||||||
|
[ -f "$out/bin/storage" ] && mv "$out/bin/storage" "$out/bin/storage_main"
|
||||||
|
[ -f "$out/bin/monitor_collector" ] && mv "$out/bin/monitor_collector" "$out/bin/monitor_collector_main"
|
||||||
|
[ -f "$out/bin/hf3fs_fuse" ] && cp "$out/bin/hf3fs_fuse" "$out/bin/hf3fs_fuse_main"
|
||||||
|
|
||||||
|
# Install libraries
|
||||||
|
find . -name "*.so" -o -name "*.so.*" | while read lib; do
|
||||||
|
if [ -f "$lib" ]; then
|
||||||
|
install -D -m644 "$lib" "$out/lib/$(basename $lib)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install static libraries (optional)
|
||||||
|
find . -name "*.a" | while read lib; do
|
||||||
|
if [ -f "$lib" ] && [[ ! "$lib" =~ third_party ]]; then
|
||||||
|
install -D -m644 "$lib" "$out/lib/$(basename $lib)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install Python modules
|
||||||
|
if [ -d "src/lib/py" ]; then
|
||||||
|
mkdir -p $out/lib/python${python3.pythonVersion}/site-packages
|
||||||
|
cp -r src/lib/py/* $out/lib/python${python3.pythonVersion}/site-packages/
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install configuration files
|
||||||
|
cp -r configs/* $out/etc/3fs/
|
||||||
|
|
||||||
|
# Install headers (for development)
|
||||||
|
mkdir -p $out/include/3fs
|
||||||
|
find src -name "*.h" -o -name "*.hpp" | while read header; do
|
||||||
|
rel_path=$(echo "$header" | sed 's|^src/||')
|
||||||
|
install -D -m644 "$header" "$out/include/3fs/$rel_path"
|
||||||
|
done
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
postFixup = ''
|
||||||
|
# Fix RPATH for all binaries
|
||||||
|
for exe in $out/bin/*; do
|
||||||
|
if [ -f "$exe" ] && [ -x "$exe" ]; then
|
||||||
|
patchelf --set-rpath "$out/lib:${lib.makeLibraryPath buildInputs}" "$exe" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Fix RPATH for all libraries
|
||||||
|
for lib in $out/lib/*.so*; do
|
||||||
|
if [ -f "$lib" ]; then
|
||||||
|
patchelf --set-rpath "$out/lib:${lib.makeLibraryPath buildInputs}" "$lib" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create wrapper scripts if needed
|
||||||
|
for bin in $out/bin/*_main; do
|
||||||
|
if [ -f "$bin" ]; then
|
||||||
|
makeWrapper "$bin" "$bin.wrapped" \
|
||||||
|
--prefix LD_LIBRARY_PATH : "$out/lib:${lib.makeLibraryPath buildInputs}" \
|
||||||
|
--set RUST_BACKTRACE 1
|
||||||
|
mv "$bin.wrapped" "$bin"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Enable parallel building
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
NIX_BUILD_CORES = 8;
|
||||||
|
|
||||||
|
# Set up proper library paths
|
||||||
|
setupHook = writeText "setup-hook" ''
|
||||||
|
export LD_LIBRARY_PATH="$1/lib''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
|
||||||
|
'';
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit jemalloc-custom;
|
||||||
|
tests = {
|
||||||
|
# Add package tests here
|
||||||
|
version = runCommand "3fs-version-test" {} ''
|
||||||
|
${pname}/bin/admin --version
|
||||||
|
touch $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Fire-Flyer File System - High-performance distributed file system for AI workloads";
|
||||||
|
longDescription = ''
|
||||||
|
3FS is a high-performance distributed file system designed to address the challenges
|
||||||
|
of AI training and inference workloads. It leverages modern SSDs and RDMA networks
|
||||||
|
to provide a shared storage layer that simplifies development of distributed applications.
|
||||||
|
'';
|
||||||
|
homepage = "https://github.com/deepseek-ai/3fs";
|
||||||
|
license = licenses.mit;
|
||||||
|
maintainers = with maintainers; [ ];
|
||||||
|
platforms = platforms.linux;
|
||||||
|
mainProgram = "admin";
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user