| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  | { config, lib, pkgs, ... }: | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  | # openafsMod, openafsBin, mkCellServDB | 
					
						
							|  |  |  | with import ./lib.nix { inherit config lib pkgs; }; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  | let | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |   inherit (lib) getBin mkOption mkIf optionalString singleton types; | 
					
						
							| 
									
										
										
										
											2009-11-18 13:28:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |   cfg = config.services.openafsClient; | 
					
						
							| 
									
										
										
										
											2009-11-18 13:28:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   cellServDB = pkgs.fetchurl { | 
					
						
							| 
									
										
										
										
											2020-03-31 21:11:51 -04:00
										 |  |  |     url = "http://dl.central.org/dl/cellservdb/CellServDB.2018-05-14"; | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  |     sha256 = "1wmjn6mmyy2r8p10nlbdzs4nrqxy8a9pjyrdciy5nmppg4053rk2"; | 
					
						
							| 
									
										
										
										
											2009-11-18 13:28:16 +00:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |   clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.cellServDB); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-08 11:59:03 +01:00
										 |  |  |   afsConfig = pkgs.runCommand "afsconfig" { preferLocalBuild = true; } ''
 | 
					
						
							| 
									
										
										
										
											2014-06-30 14:56:10 +02:00
										 |  |  |     mkdir -p $out | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |     echo ${cfg.cellName} > $out/ThisCell | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |     cat ${cellServDB} ${clientServDB} > $out/CellServDB | 
					
						
							|  |  |  |     echo "${cfg.mountPoint}:${cfg.cache.directory}:${toString cfg.cache.blocks}" > $out/cacheinfo | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |   '';
 | 
					
						
							| 
									
										
										
										
											2010-02-01 16:29:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  | in | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   ###### interface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   options = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     services.openafsClient = { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       enable = mkOption { | 
					
						
							|  |  |  |         default = false; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         type = types.bool; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |         description = "Whether to enable the OpenAFS client."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       afsdb = mkOption { | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         description = "Resolve cells via AFSDB DNS records."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |       cellName = mkOption { | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         default = ""; | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |         description = "Cell name."; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         example = "grand.central.org"; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       cellServDB = mkOption { | 
					
						
							|  |  |  |         default = []; | 
					
						
							|  |  |  |         type = with types; listOf (submodule { options = cellServDBConfig; }); | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           This cell's database server records, added to the global | 
					
						
							|  |  |  |           CellServDB. See CellServDB(5) man page for syntax. Ignored when | 
					
						
							|  |  |  |           <literal>afsdb</literal> is set to <literal>true</literal>. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |         example = ''
 | 
					
						
							|  |  |  |           [ { ip = "1.2.3.4"; dnsname = "first.afsdb.server.dns.fqdn.org"; } | 
					
						
							|  |  |  |             { ip = "2.3.4.5"; dnsname = "second.afsdb.server.dns.fqdn.org"; } | 
					
						
							|  |  |  |           ] | 
					
						
							|  |  |  |         '';
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       cache = { | 
					
						
							|  |  |  |         blocks = mkOption { | 
					
						
							|  |  |  |           default = 100000; | 
					
						
							|  |  |  |           type = types.int; | 
					
						
							|  |  |  |           description = "Cache size in 1KB blocks."; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         chunksize = mkOption { | 
					
						
							|  |  |  |           default = 0; | 
					
						
							|  |  |  |           type = types.ints.between 0 30; | 
					
						
							|  |  |  |           description = ''
 | 
					
						
							|  |  |  |             Size of each cache chunk given in powers of | 
					
						
							|  |  |  |             2. <literal>0</literal> resets the chunk size to its default | 
					
						
							|  |  |  |             values (13 (8 KB) for memcache, 18-20 (256 KB to 1 MB) for | 
					
						
							|  |  |  |             diskcache). Maximum value is 30. Important performance | 
					
						
							|  |  |  |             parameter. Set to higher values when dealing with large files. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         directory = mkOption { | 
					
						
							|  |  |  |           default = "/var/cache/openafs"; | 
					
						
							|  |  |  |           type = types.str; | 
					
						
							|  |  |  |           description = "Cache directory."; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         diskless = mkOption { | 
					
						
							|  |  |  |           default = false; | 
					
						
							|  |  |  |           type = types.bool; | 
					
						
							|  |  |  |           description = ''
 | 
					
						
							|  |  |  |             Use in-memory cache for diskless machines. Has no real | 
					
						
							|  |  |  |             performance benefit anymore. | 
					
						
							|  |  |  |           '';
 | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-14 14:39:21 +01:00
										 |  |  |       crypt = mkOption { | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         default = true; | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							| 
									
										
										
										
											2014-03-14 14:39:21 +01:00
										 |  |  |         description = "Whether to enable (weak) protocol encryption."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       daemons = mkOption { | 
					
						
							|  |  |  |         default = 2; | 
					
						
							|  |  |  |         type = types.int; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Number of daemons to serve user requests. Numbers higher than 6 | 
					
						
							|  |  |  |           usually do no increase performance. Default is sufficient for up | 
					
						
							|  |  |  |           to five concurrent users. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       fakestat = mkOption { | 
					
						
							| 
									
										
										
										
											2014-03-14 14:39:21 +01:00
										 |  |  |         default = false; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         type = types.bool; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Return fake data on stat() calls. If <literal>true</literal>, | 
					
						
							|  |  |  |           always do so. If <literal>false</literal>, only do so for | 
					
						
							|  |  |  |           cross-cell mounts (as these are potentially expensive). | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       inumcalc = mkOption { | 
					
						
							|  |  |  |         default = "compat"; | 
					
						
							|  |  |  |         type = types.strMatching "compat|md5"; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Inode calculation method. <literal>compat</literal> is | 
					
						
							|  |  |  |           computationally less expensive, but <literal>md5</literal> greatly | 
					
						
							|  |  |  |           reduces the likelihood of inode collisions in larger scenarios | 
					
						
							|  |  |  |           involving multiple cells mounted into one AFS space. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mountPoint = mkOption { | 
					
						
							|  |  |  |         default = "/afs"; | 
					
						
							|  |  |  |         type = types.str; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Mountpoint of the AFS file tree, conventionally | 
					
						
							|  |  |  |           <literal>/afs</literal>. When set to a different value, only | 
					
						
							|  |  |  |           cross-cells that use the same value can be accessed. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  |       packages = { | 
					
						
							|  |  |  |         module = mkOption { | 
					
						
							|  |  |  |           default = config.boot.kernelPackages.openafs; | 
					
						
							| 
									
										
										
										
											2018-10-18 13:11:52 +02:00
										 |  |  |           defaultText = "config.boot.kernelPackages.openafs"; | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  |           type = types.package; | 
					
						
							|  |  |  |           description = "OpenAFS kernel module package. MUST match the userland package!"; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         programs = mkOption { | 
					
						
							|  |  |  |           default = getBin pkgs.openafs; | 
					
						
							| 
									
										
										
										
											2019-02-26 14:49:59 -05:00
										 |  |  |           defaultText = "getBin pkgs.openafs"; | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  |           type = types.package; | 
					
						
							|  |  |  |           description = "OpenAFS programs package. MUST match the kernel module package!"; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       sparse = mkOption { | 
					
						
							|  |  |  |         default = true; | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							| 
									
										
										
										
											2014-03-14 14:39:21 +01:00
										 |  |  |         description = "Minimal cell list in /afs."; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       startDisconnected = mkOption { | 
					
						
							|  |  |  |         default = false; | 
					
						
							|  |  |  |         type = types.bool; | 
					
						
							|  |  |  |         description = ''
 | 
					
						
							|  |  |  |           Start up in disconnected mode.  You need to execute | 
					
						
							|  |  |  |           <literal>fs disco online</literal> (as root) to switch to | 
					
						
							|  |  |  |           connected mode. Useful for roaming devices. | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |     }; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ###### implementation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   config = mkIf cfg.enable { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |     assertions = [ | 
					
						
							|  |  |  |       { assertion = cfg.afsdb || cfg.cellServDB != []; | 
					
						
							|  |  |  |         message = "You should specify all cell-local database servers in config.services.openafsClient.cellServDB or set config.services.openafsClient.afsdb."; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       { assertion = cfg.cellName != ""; | 
					
						
							|  |  |  |         message = "You must specify the local cell name in config.services.openafsClient.cellName."; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-30 00:34:35 +02:00
										 |  |  |     environment.systemPackages = [ openafsBin ]; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     environment.etc = { | 
					
						
							|  |  |  |       clientCellServDB = { | 
					
						
							| 
									
										
										
										
											2018-11-08 11:59:03 +01:00
										 |  |  |         source = pkgs.runCommand "CellServDB" { preferLocalBuild = true; } ''
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |           cat ${cellServDB} ${clientServDB} > $out | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |         target = "openafs/CellServDB"; | 
					
						
							|  |  |  |         mode = "0644"; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       clientCell = { | 
					
						
							|  |  |  |         text = ''
 | 
					
						
							|  |  |  |           ${cfg.cellName} | 
					
						
							|  |  |  |         '';
 | 
					
						
							|  |  |  |         target = "openafs/ThisCell"; | 
					
						
							|  |  |  |         mode = "0644"; | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-06 06:50:18 +00:00
										 |  |  |     systemd.services.afsd = { | 
					
						
							|  |  |  |       description = "AFS client"; | 
					
						
							|  |  |  |       wantedBy = [ "multi-user.target" ]; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       after = singleton (if cfg.startDisconnected then  "network.target" else "network-online.target"); | 
					
						
							| 
									
										
										
										
											2017-03-25 21:18:34 +01:00
										 |  |  |       serviceConfig = { RemainAfterExit = true; }; | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |       restartIfChanged = false; | 
					
						
							| 
									
										
										
										
											2016-01-06 06:50:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       preStart = ''
 | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         mkdir -p -m 0755 ${cfg.mountPoint} | 
					
						
							|  |  |  |         mkdir -m 0700 -p ${cfg.cache.directory} | 
					
						
							|  |  |  |         ${pkgs.kmod}/bin/insmod ${openafsMod}/lib/modules/*/extra/openafs/libafs.ko.xz
 | 
					
						
							|  |  |  |         ${openafsBin}/sbin/afsd \ | 
					
						
							|  |  |  |           -mountdir ${cfg.mountPoint} \ | 
					
						
							|  |  |  |           -confdir ${afsConfig} \ | 
					
						
							|  |  |  |           ${optionalString (!cfg.cache.diskless) "-cachedir ${cfg.cache.directory}"} \ | 
					
						
							|  |  |  |           -blocks ${toString cfg.cache.blocks} \ | 
					
						
							|  |  |  |           -chunksize ${toString cfg.cache.chunksize} \ | 
					
						
							|  |  |  |           ${optionalString cfg.cache.diskless "-memcache"} \ | 
					
						
							|  |  |  |           -inumcalc ${cfg.inumcalc} \ | 
					
						
							|  |  |  |           ${if cfg.fakestat then "-fakestat-all" else "-fakestat"} \ | 
					
						
							|  |  |  |           ${if cfg.sparse then "-dynroot-sparse" else "-dynroot"} \ | 
					
						
							|  |  |  |           ${optionalString cfg.afsdb "-afsdb"} | 
					
						
							|  |  |  |         ${openafsBin}/bin/fs setcrypt ${if cfg.crypt then "on" else "off"} | 
					
						
							|  |  |  |         ${optionalString cfg.startDisconnected "${openafsBin}/bin/fs discon offline"} | 
					
						
							| 
									
										
										
										
											2016-01-06 06:50:18 +00:00
										 |  |  |       '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       # Doing this in preStop, because after these commands AFS is basically | 
					
						
							|  |  |  |       # stopped, so systemd has nothing to do, just noticing it.  If done in | 
					
						
							|  |  |  |       # postStop, then we get a hang + kernel oops, because AFS can't be | 
					
						
							|  |  |  |       # stopped simply by sending signals to processes. | 
					
						
							|  |  |  |       preStop = ''
 | 
					
						
							| 
									
										
										
										
											2020-11-24 10:29:28 -05:00
										 |  |  |         ${pkgs.util-linux}/bin/umount ${cfg.mountPoint} | 
					
						
							| 
									
										
										
										
											2018-01-24 17:28:31 +01:00
										 |  |  |         ${openafsBin}/sbin/afsd -shutdown | 
					
						
							|  |  |  |         ${pkgs.kmod}/sbin/rmmod libafs | 
					
						
							| 
									
										
										
										
											2016-01-06 06:50:18 +00:00
										 |  |  |       '';
 | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2009-11-10 15:22:57 +00:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |