226 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
		
		
			
		
	
	
			226 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| 
								 | 
							
								{ config, lib, pkgs, ...} :
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								with lib;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let
							 | 
						||
| 
								 | 
							
								  cfg = config.services.orangefs.server;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  aliases = mapAttrsToList (alias: url: alias) cfg.servers;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # Maximum handle number is 2^63
							 | 
						||
| 
								 | 
							
								  maxHandle = 9223372036854775806;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  # One range of handles for each meta/data instance
							 | 
						||
| 
								 | 
							
								  handleStep = maxHandle / (length aliases) / 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fileSystems = mapAttrsToList (name: fs: ''
							 | 
						||
| 
								 | 
							
								    <FileSystem>
							 | 
						||
| 
								 | 
							
								      Name ${name}
							 | 
						||
| 
								 | 
							
								      ID ${toString fs.id}
							 | 
						||
| 
								 | 
							
								      RootHandle ${toString fs.rootHandle}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      ${fs.extraConfig}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      <MetaHandleRanges>
							 | 
						||
| 
								 | 
							
								      ${concatStringsSep "\n" (
							 | 
						||
| 
								 | 
							
								          imap0 (i: alias:
							 | 
						||
| 
								 | 
							
								            let
							 | 
						||
| 
								 | 
							
								              begin = i * handleStep + 3;
							 | 
						||
| 
								 | 
							
								              end = begin + handleStep - 1;
							 | 
						||
| 
								 | 
							
								            in "Range ${alias} ${toString begin}-${toString end}") aliases
							 | 
						||
| 
								 | 
							
								       )}
							 | 
						||
| 
								 | 
							
								      </MetaHandleRanges>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      <DataHandleRanges>
							 | 
						||
| 
								 | 
							
								      ${concatStringsSep "\n" (
							 | 
						||
| 
								 | 
							
								          imap0 (i: alias:
							 | 
						||
| 
								 | 
							
								            let
							 | 
						||
| 
								 | 
							
								              begin = i * handleStep + 3 + (length aliases) * handleStep;
							 | 
						||
| 
								 | 
							
								              end = begin + handleStep - 1;
							 | 
						||
| 
								 | 
							
								            in "Range ${alias} ${toString begin}-${toString end}") aliases
							 | 
						||
| 
								 | 
							
								       )}
							 | 
						||
| 
								 | 
							
								      </DataHandleRanges>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      <StorageHints>
							 | 
						||
| 
								 | 
							
								      TroveSyncMeta ${if fs.troveSyncMeta then "yes" else "no"}
							 | 
						||
| 
								 | 
							
								      TroveSyncData ${if fs.troveSyncData then "yes" else "no"}
							 | 
						||
| 
								 | 
							
								      ${fs.extraStorageHints}
							 | 
						||
| 
								 | 
							
								      </StorageHints>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    </FileSystem>
							 | 
						||
| 
								 | 
							
								  '') cfg.fileSystems;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  configFile = ''
							 | 
						||
| 
								 | 
							
								    <Defaults>
							 | 
						||
| 
								 | 
							
								    LogType ${cfg.logType}
							 | 
						||
| 
								 | 
							
								    DataStorageSpace ${cfg.dataStorageSpace}
							 | 
						||
| 
								 | 
							
								    MetaDataStorageSpace ${cfg.metadataStorageSpace}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    BMIModules ${concatStringsSep "," cfg.BMIModules}
							 | 
						||
| 
								 | 
							
								    ${cfg.extraDefaults}
							 | 
						||
| 
								 | 
							
								    </Defaults>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ${cfg.extraConfig}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    <Aliases>
							 | 
						||
| 
								 | 
							
								    ${concatStringsSep "\n" (mapAttrsToList (alias: url: "Alias ${alias} ${url}") cfg.servers)}
							 | 
						||
| 
								 | 
							
								    </Aliases>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    ${concatStringsSep "\n" fileSystems}
							 | 
						||
| 
								 | 
							
								  '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								in {
							 | 
						||
| 
								 | 
							
								  ###### interface
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  options = {
							 | 
						||
| 
								 | 
							
								    services.orangefs.server = {
							 | 
						||
| 
								 | 
							
								      enable = mkEnableOption "OrangeFS server";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      logType = mkOption {
							 | 
						||
| 
								 | 
							
								        type = with types; enum [ "file" "syslog" ];
							 | 
						||
| 
								 | 
							
								        default = "syslog";
							 | 
						||
| 
								 | 
							
								        description = "Destination for log messages.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      dataStorageSpace = mkOption {
							 | 
						||
| 
								 | 
							
								        type = types.str;
							 | 
						||
| 
								 | 
							
								        default = null;
							 | 
						||
| 
								 | 
							
								        example = "/data/storage";
							 | 
						||
| 
								 | 
							
								        description = "Directory for data storage.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      metadataStorageSpace = mkOption {
							 | 
						||
| 
								 | 
							
								        type = types.str;
							 | 
						||
| 
								 | 
							
								        default = null;
							 | 
						||
| 
								 | 
							
								        example = "/data/meta";
							 | 
						||
| 
								 | 
							
								        description = "Directory for meta data storage.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      BMIModules = mkOption {
							 | 
						||
| 
								 | 
							
								        type = with types; listOf str;
							 | 
						||
| 
								 | 
							
								        default = [ "bmi_tcp" ];
							 | 
						||
| 
								 | 
							
								        example = [ "bmi_tcp" "bmi_ib"];
							 | 
						||
| 
								 | 
							
								        description = "List of BMI modules to load.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      extraDefaults = mkOption {
							 | 
						||
| 
								 | 
							
								        type = types.lines;
							 | 
						||
| 
								 | 
							
								        default = "";
							 | 
						||
| 
								 | 
							
								        description = "Extra config for <literal><Defaults></literal> section.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      extraConfig = mkOption {
							 | 
						||
| 
								 | 
							
								        type = types.lines;
							 | 
						||
| 
								 | 
							
								        default = "";
							 | 
						||
| 
								 | 
							
								        description = "Extra config for the global section.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      servers = mkOption {
							 | 
						||
| 
								 | 
							
								        type = with types; attrsOf types.str;
							 | 
						||
| 
								 | 
							
								        default = {};
							 | 
						||
| 
								 | 
							
								        example = ''
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            node1="tcp://node1:3334";
							 | 
						||
| 
								 | 
							
								            node2="tcp://node2:3334";
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								        description = "URLs for storage server including port. The attribute names define the server alias.";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      fileSystems = mkOption {
							 | 
						||
| 
								 | 
							
								        description = ''
							 | 
						||
| 
								 | 
							
								          These options will create the <literal><FileSystem></literal> sections of config file.
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								        default = { orangefs = {}; };
							 | 
						||
| 
								 | 
							
								        defaultText = literalExample "{ orangefs = {}; }";
							 | 
						||
| 
								 | 
							
								        example = literalExample ''
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            fs1 = {
							 | 
						||
| 
								 | 
							
								              id = 101;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            fs2 = {
							 | 
						||
| 
								 | 
							
								              id = 102;
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								        type = with types; attrsOf (submodule ({ ... } : {
							 | 
						||
| 
								 | 
							
								          options = {
							 | 
						||
| 
								 | 
							
								            id = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.int;
							 | 
						||
| 
								 | 
							
								              default = 1;
							 | 
						||
| 
								 | 
							
								              description = "File system ID (must be unique within configuration).";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            rootHandle = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.int;
							 | 
						||
| 
								 | 
							
								              default = 3;
							 | 
						||
| 
								 | 
							
								              description = "File system root ID.";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            extraConfig = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.lines;
							 | 
						||
| 
								 | 
							
								              default = "";
							 | 
						||
| 
								 | 
							
								              description = "Extra config for <literal><FileSystem></literal> section.";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            troveSyncMeta = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.bool;
							 | 
						||
| 
								 | 
							
								              default = true;
							 | 
						||
| 
								 | 
							
								              description = "Sync meta data.";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            troveSyncData = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.bool;
							 | 
						||
| 
								 | 
							
								              default = false;
							 | 
						||
| 
								 | 
							
								              description = "Sync data.";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            extraStorageHints = mkOption {
							 | 
						||
| 
								 | 
							
								              type = types.lines;
							 | 
						||
| 
								 | 
							
								              default = "";
							 | 
						||
| 
								 | 
							
								              description = "Extra config for <literal><StorageHints></literal> section.";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        }));
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ###### implementation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  config = mkIf cfg.enable {
							 | 
						||
| 
								 | 
							
								    environment.systemPackages = [ pkgs.orangefs ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # orangefs daemon will run as user
							 | 
						||
| 
								 | 
							
								    users.users.orangefs.isSystemUser = true;
							 | 
						||
| 
								 | 
							
								    users.groups.orangefs = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    # To format the file system the config file is needed.
							 | 
						||
| 
								 | 
							
								    environment.etc."orangefs/server.conf" = {
							 | 
						||
| 
								 | 
							
								      text = configFile;
							 | 
						||
| 
								 | 
							
								      user = "orangefs";
							 | 
						||
| 
								 | 
							
								      group = "orangefs";
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    systemd.services.orangefs-server = {
							 | 
						||
| 
								 | 
							
								      wantedBy = [ "multi-user.target" ];
							 | 
						||
| 
								 | 
							
								      requires = [ "network-online.target" ];
							 | 
						||
| 
								 | 
							
								      after = [ "network-online.target" ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      serviceConfig = {
							 | 
						||
| 
								 | 
							
								        # Run as "simple" in forground mode.
							 | 
						||
| 
								 | 
							
								        # This is more reliable
							 | 
						||
| 
								 | 
							
								        ExecStart = ''
							 | 
						||
| 
								 | 
							
								          ${pkgs.orangefs}/bin/pvfs2-server -d \
							 | 
						||
| 
								 | 
							
								            /etc/orangefs/server.conf
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								        TimeoutStopSec = "120";
							 | 
						||
| 
								 | 
							
								        User = "orangefs";
							 | 
						||
| 
								 | 
							
								        Group = "orangefs";
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |