mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-14 06:00:33 +03:00
Merge pull request #140891 from markuskowa/os-moosefs
nixos: init moosefs module and test
This commit is contained in:
commit
768dd74738
6 changed files with 350 additions and 0 deletions
|
@ -168,6 +168,13 @@
|
|||
<link linkend="opt-services.baget.enable">services.baget</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://moosefs.com">moosefs</link>, fault
|
||||
tolerant petabyte distributed file system. Available as
|
||||
<link linkend="opt-services.moosefs">moosefs</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://github.com/ThomasLeister/prosody-filer">prosody-filer</link>,
|
||||
|
|
|
@ -51,6 +51,9 @@ In addition to numerous new and upgraded packages, this release has the followin
|
|||
|
||||
- [BaGet](https://loic-sharma.github.io/BaGet/), a lightweight NuGet and symbol server. Available at [services.baget](#opt-services.baget.enable).
|
||||
|
||||
- [moosefs](https://moosefs.com), fault tolerant petabyte distributed file system.
|
||||
Available as [moosefs](#opt-services.moosefs).
|
||||
|
||||
- [prosody-filer](https://github.com/ThomasLeister/prosody-filer), a server for handling XMPP HTTP Upload requests. Available at [services.prosody-filer](#opt-services.prosody-filer.enable).
|
||||
|
||||
- [ethercalc](https://github.com/audreyt/ethercalc), an online collaborative
|
||||
|
|
|
@ -682,6 +682,7 @@
|
|||
./services/network-filesystems/litestream/default.nix
|
||||
./services/network-filesystems/netatalk.nix
|
||||
./services/network-filesystems/nfsd.nix
|
||||
./services/network-filesystems/moosefs.nix
|
||||
./services/network-filesystems/openafs/client.nix
|
||||
./services/network-filesystems/openafs/server.nix
|
||||
./services/network-filesystems/orangefs/server.nix
|
||||
|
|
249
nixos/modules/services/network-filesystems/moosefs.nix
Normal file
249
nixos/modules/services/network-filesystems/moosefs.nix
Normal file
|
@ -0,0 +1,249 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.moosefs;
|
||||
|
||||
mfsUser = if cfg.runAsUser then "moosefs" else "root";
|
||||
|
||||
settingsFormat = let
|
||||
listSep = " ";
|
||||
allowedTypes = with types; [ bool int float str ];
|
||||
valueToString = val:
|
||||
if isList val then concatStringsSep listSep (map (x: valueToString x) val)
|
||||
else if isBool val then (if val then "1" else "0")
|
||||
else toString val;
|
||||
|
||||
in {
|
||||
type = with types; let
|
||||
valueType = oneOf ([
|
||||
(listOf valueType)
|
||||
] ++ allowedTypes) // {
|
||||
description = "Flat key-value file";
|
||||
};
|
||||
in attrsOf valueType;
|
||||
|
||||
generate = name: value:
|
||||
pkgs.writeText name ( lib.concatStringsSep "\n" (
|
||||
lib.mapAttrsToList (key: val: "${key} = ${valueToString val}") value ));
|
||||
};
|
||||
|
||||
|
||||
initTool = pkgs.writeShellScriptBin "mfsmaster-init" ''
|
||||
if [ ! -e ${cfg.master.settings.DATA_PATH}/metadata.mfs ]; then
|
||||
cp ${pkgs.moosefs}/var/mfs/metadata.mfs.empty ${cfg.master.settings.DATA_PATH}
|
||||
chmod +w ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty
|
||||
${pkgs.moosefs}/bin/mfsmaster -a -c ${masterCfg} start
|
||||
${pkgs.moosefs}/bin/mfsmaster -c ${masterCfg} stop
|
||||
rm ${cfg.master.settings.DATA_PATH}/metadata.mfs.empty
|
||||
fi
|
||||
'';
|
||||
|
||||
# master config file
|
||||
masterCfg = settingsFormat.generate
|
||||
"mfsmaster.cfg" cfg.master.settings;
|
||||
|
||||
# metalogger config file
|
||||
metaloggerCfg = settingsFormat.generate
|
||||
"mfsmetalogger.cfg" cfg.metalogger.settings;
|
||||
|
||||
# chunkserver config file
|
||||
chunkserverCfg = settingsFormat.generate
|
||||
"mfschunkserver.cfg" cfg.chunkserver.settings;
|
||||
|
||||
# generic template for all deamons
|
||||
systemdService = name: extraConfig: configFile: {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} start";
|
||||
ExecStop = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} stop";
|
||||
ExecReload = "${pkgs.moosefs}/bin/mfs${name} -c ${configFile} reload";
|
||||
PIDFile = "${cfg."${name}".settings.DATA_PATH}/.mfs${name}.lock";
|
||||
} // extraConfig;
|
||||
};
|
||||
|
||||
in {
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
services.moosefs = {
|
||||
masterHost = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
description = "IP or DNS name of master host.";
|
||||
};
|
||||
|
||||
runAsUser = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = true;
|
||||
description = "Run daemons as user moosefs instead of root.";
|
||||
};
|
||||
|
||||
client.enable = mkEnableOption "Moosefs client.";
|
||||
|
||||
master = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = ''
|
||||
Enable Moosefs master daemon.
|
||||
|
||||
You need to run <literal>mfsmaster-init</literal> on a freshly installed master server to
|
||||
initialize the <literal>DATA_PATH</literal> direcory.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
|
||||
exports = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = null;
|
||||
description = "Paths to export (see mfsexports.cfg).";
|
||||
example = [
|
||||
"* / rw,alldirs,admin,maproot=0:0"
|
||||
"* . rw"
|
||||
];
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
description = "Whether to automatically open the necessary ports in the firewall.";
|
||||
default = false;
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.DATA_PATH = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/mfs";
|
||||
description = "Data storage directory.";
|
||||
};
|
||||
};
|
||||
|
||||
description = "Contents of config file (mfsmaster.cfg).";
|
||||
};
|
||||
};
|
||||
|
||||
metalogger = {
|
||||
enable = mkEnableOption "Moosefs metalogger daemon.";
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.DATA_PATH = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/mfs";
|
||||
description = "Data storage directory";
|
||||
};
|
||||
};
|
||||
|
||||
description = "Contents of metalogger config file (mfsmetalogger.cfg).";
|
||||
};
|
||||
};
|
||||
|
||||
chunkserver = {
|
||||
enable = mkEnableOption "Moosefs chunkserver daemon.";
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
description = "Whether to automatically open the necessary ports in the firewall.";
|
||||
default = false;
|
||||
};
|
||||
|
||||
hdds = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = null;
|
||||
description = "Mount points to be used by chunkserver for storage (see mfshdd.cfg).";
|
||||
example = [ "/mnt/hdd1" ];
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.DATA_PATH = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/mfs";
|
||||
description = "Directory for lock file.";
|
||||
};
|
||||
};
|
||||
|
||||
description = "Contents of chunkserver config file (mfschunkserver.cfg).";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf ( cfg.client.enable || cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) {
|
||||
|
||||
warnings = [ ( mkIf (!cfg.runAsUser) "Running moosefs services as root is not recommended.") ];
|
||||
|
||||
# Service settings
|
||||
services.moosefs = {
|
||||
master.settings = mkIf cfg.master.enable {
|
||||
WORKING_USER = mfsUser;
|
||||
EXPORTS_FILENAME = toString ( pkgs.writeText "mfsexports.cfg"
|
||||
(concatStringsSep "\n" cfg.master.exports));
|
||||
};
|
||||
|
||||
metalogger.settings = mkIf cfg.metalogger.enable {
|
||||
WORKING_USER = mfsUser;
|
||||
MASTER_HOST = cfg.masterHost;
|
||||
};
|
||||
|
||||
chunkserver.settings = mkIf cfg.chunkserver.enable {
|
||||
WORKING_USER = mfsUser;
|
||||
MASTER_HOST = cfg.masterHost;
|
||||
HDD_CONF_FILENAME = toString ( pkgs.writeText "mfshdd.cfg"
|
||||
(concatStringsSep "\n" cfg.chunkserver.hdds));
|
||||
};
|
||||
};
|
||||
|
||||
# Create system user account for daemons
|
||||
users = mkIf ( cfg.runAsUser && ( cfg.master.enable || cfg.metalogger.enable || cfg.chunkserver.enable ) ) {
|
||||
users.moosefs = {
|
||||
isSystemUser = true;
|
||||
description = "moosefs daemon user";
|
||||
group = "moosefs";
|
||||
};
|
||||
groups.moosefs = {};
|
||||
};
|
||||
|
||||
environment.systemPackages =
|
||||
(lib.optional cfg.client.enable pkgs.moosefs) ++
|
||||
(lib.optional cfg.master.enable initTool);
|
||||
|
||||
networking.firewall.allowedTCPPorts =
|
||||
(lib.optionals cfg.master.openFirewall [ 9419 9420 9421 ]) ++
|
||||
(lib.optional cfg.chunkserver.openFirewall 9422);
|
||||
|
||||
# Ensure storage directories exist
|
||||
systemd.tmpfiles.rules =
|
||||
optional cfg.master.enable "d ${cfg.master.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"
|
||||
++ optional cfg.metalogger.enable "d ${cfg.metalogger.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}"
|
||||
++ optional cfg.chunkserver.enable "d ${cfg.chunkserver.settings.DATA_PATH} 0700 ${mfsUser} ${mfsUser}";
|
||||
|
||||
# Service definitions
|
||||
systemd.services.mfs-master = mkIf cfg.master.enable
|
||||
( systemdService "master" {
|
||||
TimeoutStartSec = 1800;
|
||||
TimeoutStopSec = 1800;
|
||||
Restart = "no";
|
||||
} masterCfg );
|
||||
|
||||
systemd.services.mfs-metalogger = mkIf cfg.metalogger.enable
|
||||
( systemdService "metalogger" { Restart = "on-abnormal"; } metaloggerCfg );
|
||||
|
||||
systemd.services.mfs-chunkserver = mkIf cfg.chunkserver.enable
|
||||
( systemdService "chunkserver" { Restart = "on-abnormal"; } chunkserverCfg );
|
||||
};
|
||||
}
|
|
@ -305,6 +305,7 @@ in
|
|||
moodle = handleTest ./moodle.nix {};
|
||||
morty = handleTest ./morty.nix {};
|
||||
mosquitto = handleTest ./mosquitto.nix {};
|
||||
moosefs = handleTest ./moosefs.nix {};
|
||||
mpd = handleTest ./mpd.nix {};
|
||||
mpv = handleTest ./mpv.nix {};
|
||||
mumble = handleTest ./mumble.nix {};
|
||||
|
|
89
nixos/tests/moosefs.nix
Normal file
89
nixos/tests/moosefs.nix
Normal file
|
@ -0,0 +1,89 @@
|
|||
import ./make-test-python.nix ({ pkgs, ... } :
|
||||
|
||||
let
|
||||
master = { pkgs, ... } : {
|
||||
# data base is stored in memory
|
||||
# server crashes with default memory size
|
||||
virtualisation.memorySize = 1024;
|
||||
|
||||
services.moosefs.master = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
exports = [
|
||||
"* / rw,alldirs,admin,maproot=0:0"
|
||||
"* . rw"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
chunkserver = { pkgs, ... } : {
|
||||
virtualisation.emptyDiskImages = [ 4096 ];
|
||||
boot.initrd.postDeviceCommands = ''
|
||||
${pkgs.e2fsprogs}/bin/mkfs.ext4 -L data /dev/vdb
|
||||
'';
|
||||
|
||||
fileSystems = pkgs.lib.mkVMOverride {
|
||||
"/data" = {
|
||||
device = "/dev/disk/by-label/data";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
|
||||
services.moosefs = {
|
||||
masterHost = "master";
|
||||
chunkserver = {
|
||||
openFirewall = true;
|
||||
enable = true;
|
||||
hdds = [ "~/data" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
metalogger = { pkgs, ... } : {
|
||||
services.moosefs = {
|
||||
masterHost = "master";
|
||||
metalogger.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
client = { pkgs, ... } : {
|
||||
services.moosefs.client.enable = true;
|
||||
};
|
||||
|
||||
in {
|
||||
name = "moosefs";
|
||||
|
||||
nodes= {
|
||||
inherit master;
|
||||
inherit metalogger;
|
||||
chunkserver1 = chunkserver;
|
||||
chunkserver2 = chunkserver;
|
||||
client1 = client;
|
||||
client2 = client;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
# prepare master server
|
||||
master.start()
|
||||
master.wait_for_unit("multi-user.target")
|
||||
master.succeed("mfsmaster-init")
|
||||
master.succeed("systemctl restart mfs-master")
|
||||
master.wait_for_unit("mfs-master.service")
|
||||
|
||||
metalogger.wait_for_unit("mfs-metalogger.service")
|
||||
|
||||
for chunkserver in [chunkserver1, chunkserver2]:
|
||||
chunkserver.wait_for_unit("multi-user.target")
|
||||
chunkserver.succeed("chown moosefs:moosefs /data")
|
||||
chunkserver.succeed("systemctl restart mfs-chunkserver")
|
||||
chunkserver.wait_for_unit("mfs-chunkserver.service")
|
||||
|
||||
for client in [client1, client2]:
|
||||
client.wait_for_unit("multi-user.target")
|
||||
client.succeed("mkdir /moosefs")
|
||||
client.succeed("mount -t moosefs master:/ /moosefs")
|
||||
|
||||
client1.succeed("echo test > /moosefs/file")
|
||||
client2.succeed("grep test /moosefs/file")
|
||||
'';
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue