openafs: improve CellServDB options and add test (#424753)
This commit is contained in:
@@ -21,19 +21,28 @@ let
|
||||
|
||||
cfg = config.services.openafsClient;
|
||||
|
||||
cellServDB = pkgs.fetchurl {
|
||||
url = "http://dl.central.org/dl/cellservdb/CellServDB.2018-05-14";
|
||||
sha256 = "1wmjn6mmyy2r8p10nlbdzs4nrqxy8a9pjyrdciy5nmppg4053rk2";
|
||||
};
|
||||
clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellServDB);
|
||||
|
||||
clientServDB = pkgs.writeText "client-cellServDB-${cfg.cellName}" (
|
||||
mkCellServDB cfg.cellName cfg.cellServDB
|
||||
);
|
||||
cellServDB =
|
||||
let
|
||||
localCells = builtins.attrNames cfg.cellServDB;
|
||||
localCellsRegex = lib.concatMapStringsSep "\\|" (lib.replaceStrings [ "." ] [ "\\." ]) localCells;
|
||||
sedExpr = '':x /^>\(${localCellsRegex}\) / { n; :y /^>/! { n; by }; bx }; p'';
|
||||
globalCommand =
|
||||
if cfg.cellServDB != { } then
|
||||
''sed -n -e ${lib.escapeShellArg sedExpr} ${cfg.globalCellServDBFile}''
|
||||
else
|
||||
''cat ${cfg.globalCellServDBFile}'';
|
||||
in
|
||||
pkgs.runCommand "CellServDB" { preferLocalBuild = true; } ''
|
||||
${lib.optionalString (cfg.globalCellServDBFile != null) ''${globalCommand} > $out''}
|
||||
cat ${clientServDB} >> $out
|
||||
'';
|
||||
|
||||
afsConfig = pkgs.runCommand "afsconfig" { preferLocalBuild = true; } ''
|
||||
mkdir -p $out
|
||||
echo ${cfg.cellName} > $out/ThisCell
|
||||
cat ${cellServDB} ${clientServDB} > $out/CellServDB
|
||||
cp ${cellServDB} $out/CellServDB
|
||||
echo "${cfg.mountPoint}:${cfg.cache.directory}:${toString cfg.cache.blocks}" > $out/cacheinfo
|
||||
'';
|
||||
|
||||
@@ -64,28 +73,38 @@ in
|
||||
example = "grand.central.org";
|
||||
};
|
||||
|
||||
globalCellServDBFile = mkOption {
|
||||
default = pkgs.openafs.cellservdb;
|
||||
defaultText = literalExpression "pkgs.openafs.cellservdb";
|
||||
type = types.nullOr types.pathInStore;
|
||||
description = ''
|
||||
Global CellServDB file to be deployed. Set to `null` to only deploy the
|
||||
cells in `cellServDB`. Any cells defined in `cellServDB` will override
|
||||
cells in the global file.
|
||||
'';
|
||||
example = lib.literalExpression "./CellServDB";
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [ ];
|
||||
type =
|
||||
with types;
|
||||
listOf (submodule {
|
||||
options = cellServDBConfig;
|
||||
});
|
||||
default = { };
|
||||
type = cellServDBType cfg.cellName;
|
||||
description = ''
|
||||
This cell's database server records, added to the global
|
||||
CellServDB. See {manpage}`CellServDB(5)` man page for syntax. Ignored when
|
||||
`afsdb` is set to `true`.
|
||||
'';
|
||||
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";
|
||||
}
|
||||
];
|
||||
example = {
|
||||
"dns.fqdn.org" = [
|
||||
{
|
||||
ip = "1.2.3.4";
|
||||
dnsname = "first.afsdb.server.dns.fqdn.org";
|
||||
}
|
||||
{
|
||||
ip = "2.3.4.5";
|
||||
dnsname = "second.afsdb.server.dns.fqdn.org";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
cache = {
|
||||
@@ -223,9 +242,7 @@ in
|
||||
|
||||
environment.etc = {
|
||||
clientCellServDB = {
|
||||
source = pkgs.runCommand "CellServDB" { preferLocalBuild = true; } ''
|
||||
cat ${cellServDB} ${clientServDB} > $out
|
||||
'';
|
||||
source = cellServDB;
|
||||
target = "openafs/CellServDB";
|
||||
mode = "0644";
|
||||
};
|
||||
|
||||
@@ -3,15 +3,32 @@
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
concatMapAttrsStringSep
|
||||
mkOption
|
||||
types
|
||||
optionalString
|
||||
;
|
||||
|
||||
cellServDBMemberType = types.submodule {
|
||||
options = {
|
||||
ip = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "1.2.3.4";
|
||||
description = "IP Address of a database server";
|
||||
};
|
||||
dnsname = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "afs.example.org";
|
||||
description = "DNS full-qualified domain name of a database server";
|
||||
};
|
||||
};
|
||||
};
|
||||
cellServDBCellType = types.listOf cellServDBMemberType;
|
||||
in
|
||||
{
|
||||
|
||||
mkCellServDB =
|
||||
mkCellServDB = concatMapAttrsStringSep "" (
|
||||
cellName: db:
|
||||
''
|
||||
>${cellName}
|
||||
@@ -19,23 +36,15 @@ in
|
||||
+ (concatStringsSep "\n" (
|
||||
map (dbm: optionalString (dbm.ip != "" && dbm.dnsname != "") "${dbm.ip} #${dbm.dnsname}") db
|
||||
))
|
||||
+ "\n";
|
||||
+ "\n"
|
||||
);
|
||||
|
||||
# CellServDB configuration type
|
||||
cellServDBConfig = {
|
||||
ip = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "1.2.3.4";
|
||||
description = "IP Address of a database server";
|
||||
};
|
||||
dnsname = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
example = "afs.example.org";
|
||||
description = "DNS full-qualified domain name of a database server";
|
||||
};
|
||||
};
|
||||
cellServDBType =
|
||||
thisCell:
|
||||
types.coercedTo (types.listOf types.anything) (m: { "${thisCell}" = m; }) (
|
||||
types.attrsOf cellServDBCellType
|
||||
);
|
||||
|
||||
openafsMod = config.services.openafsClient.packages.module;
|
||||
openafsBin = config.services.openafsClient.packages.programs;
|
||||
|
||||
@@ -67,10 +67,10 @@ let
|
||||
null;
|
||||
|
||||
buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (
|
||||
mkCellServDB cfg.cellName cfg.roles.backup.cellServDB
|
||||
mkCellServDB cfg.roles.backup.cellServDB
|
||||
);
|
||||
|
||||
useBuCellServDB = (cfg.roles.backup.cellServDB != [ ]) && (!cfg.roles.backup.enableFabs);
|
||||
useBuCellServDB = (cfg.roles.backup.cellServDB != { }) && (!cfg.roles.backup.enableFabs);
|
||||
|
||||
cfg = config.services.openafsServer;
|
||||
|
||||
@@ -128,9 +128,22 @@ in
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [ ];
|
||||
type = with types; listOf (submodule [ { options = cellServDBConfig; } ]);
|
||||
description = "Definition of all cell-local database server machines.";
|
||||
default = { };
|
||||
type = cellServDBType cfg.cellName;
|
||||
description = ''
|
||||
Definition of all cell-local database server machines. If a single
|
||||
list is provided, it will be used as the servers for `cellName`.
|
||||
'';
|
||||
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";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "openafs" { };
|
||||
@@ -226,8 +239,8 @@ in
|
||||
};
|
||||
|
||||
cellServDB = mkOption {
|
||||
default = [ ];
|
||||
type = with types; listOf (submodule [ { options = cellServDBConfig; } ]);
|
||||
default = { };
|
||||
type = cellServDBType cfg.cellName;
|
||||
description = ''
|
||||
Definition of all cell-local backup database server machines.
|
||||
Use this when your cell uses less backup database servers than
|
||||
@@ -288,9 +301,19 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
warnings =
|
||||
lib.optional ((builtins.attrNames cfg.cellServDB) != [ cfg.cellName ]) ''
|
||||
config.services.openafsServer.cellServDB should normally only contain servers for one cell. It currently contains servers for ${builtins.toString (builtins.attrNames cfg.cellServDB)}.
|
||||
''
|
||||
++
|
||||
lib.optional (useBuCellServDB && (builtins.attrNames cfg.backup.cellServDB) != [ cfg.cellName ])
|
||||
''
|
||||
config.services.openafsServer.backup.cellServDB should normally only contain servers for one cell. It currently contains servers for ${builtins.toString (builtins.attrNames cfg.cellServDB)}.
|
||||
'';
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.cellServDB != [ ];
|
||||
assertion = cfg.cellServDB != { } && (cfg.cellServDB."${cfg.cellName}" or [ ]) != [ ];
|
||||
message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB.";
|
||||
}
|
||||
{
|
||||
@@ -308,7 +331,7 @@ in
|
||||
mode = "0644";
|
||||
};
|
||||
cellServDB = {
|
||||
text = mkCellServDB cfg.cellName cfg.cellServDB;
|
||||
text = mkCellServDB cfg.cellServDB;
|
||||
target = "openafs/server/CellServDB";
|
||||
mode = "0644";
|
||||
};
|
||||
@@ -319,8 +342,9 @@ in
|
||||
};
|
||||
buCellServDB = {
|
||||
enable = useBuCellServDB;
|
||||
text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB;
|
||||
text = mkCellServDB cfg.roles.backup.cellServDB;
|
||||
target = "openafs/backup/CellServDB";
|
||||
mode = "0644";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -336,7 +360,6 @@ in
|
||||
preStart = ''
|
||||
mkdir -m 0755 -p /var/openafs
|
||||
${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"}
|
||||
${optionalString useBuCellServDB "cp ${buCellServDB}"}
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = "${openafsBin}/bin/bosserver -nofork";
|
||||
|
||||
@@ -1155,6 +1155,7 @@ in
|
||||
onlyoffice = runTest ./onlyoffice.nix;
|
||||
open-web-calendar = runTest ./web-apps/open-web-calendar.nix;
|
||||
open-webui = runTest ./open-webui.nix;
|
||||
openafs = runTest ./openafs.nix;
|
||||
openarena = runTest ./openarena.nix;
|
||||
openbao = runTest ./openbao.nix;
|
||||
opencloud = runTest ./opencloud.nix;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
cellName = "cell.com";
|
||||
realmName = lib.toUpper cellName;
|
||||
in
|
||||
{
|
||||
name = "openafs";
|
||||
defaults =
|
||||
{ config, nodes, ... }:
|
||||
let
|
||||
cellServDB = {
|
||||
${cellName} = lib.mapAttrsToList (_: config: {
|
||||
ip = config.networking.primaryIPAddress;
|
||||
dnsname = "${config.networking.hostName}.${config.networking.domain}";
|
||||
}) nodes;
|
||||
};
|
||||
in
|
||||
{
|
||||
config = {
|
||||
virtualisation.vlans = [ 1 ];
|
||||
networking.useDHCP = false; # Disable external connectivity
|
||||
networking.domain = cellName;
|
||||
networking.firewall.enable = false;
|
||||
|
||||
security.krb5 = {
|
||||
enable = true;
|
||||
settings.libdefaults.default_realm = realmName;
|
||||
};
|
||||
services.openafsClient = {
|
||||
enable = true;
|
||||
inherit cellName;
|
||||
cellServDB = cellServDB // {
|
||||
"grand.central.org" = [
|
||||
{
|
||||
ip = "1.1.1.1";
|
||||
dnsname = "one.grand.central.org";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
services.openafsServer = {
|
||||
enable = true;
|
||||
inherit cellName cellServDB;
|
||||
};
|
||||
security.krb5.settings.realms.${realmName} = {
|
||||
admin_server = nodes.a.networking.primaryIPAddress;
|
||||
kdc = [ nodes.a.networking.primaryIPAddress ];
|
||||
};
|
||||
};
|
||||
};
|
||||
nodes.a = {
|
||||
services.kerberos_server = {
|
||||
enable = true;
|
||||
settings.realms."CELL.COM".acl = [
|
||||
{
|
||||
principal = "admin";
|
||||
access = [
|
||||
"add"
|
||||
"cpw"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
nodes.b = { };
|
||||
|
||||
testScript = ''
|
||||
import re
|
||||
|
||||
def setup_kdc(machine):
|
||||
# Set up realm
|
||||
machine.succeed(
|
||||
"kdb5_util create -s -r CELL.COM -P master_key",
|
||||
"systemctl restart kadmind.service kdc.service",
|
||||
)
|
||||
for unit in ["kadmind", "kdc"]:
|
||||
machine.wait_for_unit(f"{unit}.service")
|
||||
# Create admin and afs/ principals
|
||||
machine.succeed(
|
||||
"kadmin.local add_principal -randkey admin",
|
||||
"rm -f /tmp/shared/admin.keytab",
|
||||
"kadmin.local ktadd -k /tmp/shared/admin.keytab admin",
|
||||
"kadmin.local add_principal -randkey -e aes256-cts-hmac-sha1-96:normal,aes128-cts-hmac-sha1-96:normal afs/${cellName}",
|
||||
)
|
||||
# Generate a keytab for afs/
|
||||
out = machine.succeed(
|
||||
"rm -f /tmp/shared/rxkad.keytab",
|
||||
"kadmin.local ktadd -k /tmp/shared/rxkad.keytab -e aes256-cts-hmac-sha1-96:normal,aes128-cts-hmac-sha1-96:normal afs/${cellName}",
|
||||
)
|
||||
m = re.search(r"kvno (\d+)", out)
|
||||
assert m
|
||||
kvno = m.group(1)
|
||||
return kvno
|
||||
|
||||
def setup_afs_daemons(machine, kvno):
|
||||
machine.succeed(
|
||||
"mkdir -p /vicepa",
|
||||
"touch /vicepa/AlwaysAttach",
|
||||
)
|
||||
machine.succeed(*(
|
||||
f"asetkey add rxkad_krb5 {kvno} {enctype} /tmp/shared/rxkad.keytab afs/${cellName}"
|
||||
for enctype in (18, 17)
|
||||
))
|
||||
machine.start_job("openafs-server")
|
||||
machine.wait_until_succeeds("bos adduser localhost admin -localauth")
|
||||
|
||||
start_all()
|
||||
kvno = setup_kdc(a)
|
||||
setup_afs_daemons(a, kvno)
|
||||
setup_afs_daemons(b, kvno)
|
||||
# Create initial 'admin' user
|
||||
# N.B. It can take 60+ seconds before the ptserver has quorum and accepts writes, so try a few times until it succeeds
|
||||
a.wait_until_succeeds("pts createuser -name admin -localauth")
|
||||
a.succeed(
|
||||
"pts adduser admin system:administrators -localauth",
|
||||
)
|
||||
# Create initial volumes
|
||||
a.wait_until_succeeds("vos listvol localhost -localauth")
|
||||
a.succeed(
|
||||
"vos create localhost vicepa root.afs -localauth",
|
||||
"vos create localhost vicepa root.cell -localauth",
|
||||
)
|
||||
# Authenticate and add a file
|
||||
a.succeed(
|
||||
"kinit -k -t /tmp/shared/admin.keytab admin",
|
||||
"aklog",
|
||||
"echo pass > /afs/${cellName}/test.txt",
|
||||
)
|
||||
# Authenticate and read a file
|
||||
b.succeed(
|
||||
"kinit -k -t /tmp/shared/admin.keytab admin",
|
||||
"aklog",
|
||||
)
|
||||
assert b.succeed("cat /afs/${cellName}/test.txt").strip() == "pass"
|
||||
|
||||
# Ensure the global CellServDB can be overridden.
|
||||
assert a.succeed("fs listcells -n | grep grand.central.org").strip() == "Cell grand.central.org on hosts 1.1.1.1."
|
||||
'';
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
callPackage,
|
||||
stdenv,
|
||||
buildPackages,
|
||||
fetchurl,
|
||||
@@ -103,7 +104,7 @@ stdenv.mkDerivation {
|
||||
)
|
||||
''
|
||||
+ optionalString withTsm ''
|
||||
export XBSA_CFLAGS="-Dxbsa -DNEW_XBSA -I${tsm-client}/lib64/sample -DXBSA_TSMLIB=\\\"${tsm-client}/lib64/libApiTSM64.so\\\""
|
||||
export XBSA_CFLAGS="-Dxbsa -DNEW_XBSA -I${tsm-client}/opt/tivoli/tsm/client/api/bin64/sample -DXBSA_TSMLIB=\\\"${tsm-client}/lib64/libApiTSM64.so\\\""
|
||||
'';
|
||||
|
||||
buildFlags = [ "all_nolibafs" ];
|
||||
@@ -143,6 +144,8 @@ stdenv.mkDerivation {
|
||||
done
|
||||
'';
|
||||
|
||||
passthru.cellservdb = callPackage ../cellservdb.nix { };
|
||||
|
||||
meta = {
|
||||
outputsToInstall = [
|
||||
"out"
|
||||
|
||||
@@ -1,18 +1,31 @@
|
||||
diff -ru openafs-1.8.0/src/butc/afsxbsa.c openafs-1.8.0.new/src/butc/afsxbsa.c
|
||||
--- openafs-1.8.0/src/butc/afsxbsa.c 2018-04-06 03:21:12.000000000 +0200
|
||||
+++ openafs-1.8.0.new/src/butc/afsxbsa.c 2018-06-12 16:26:26.272522305 +0200
|
||||
@@ -651,7 +651,7 @@
|
||||
diff -ru openafs-1.8.13.2/src/butc/afsxbsa.c openafs-1.8.13.2.new/src/butc/afsxbsa.c
|
||||
--- openafs-1.8.13.2/src/butc/afsxbsa.c 2025-01-23 12:12:55.000000000 -0500
|
||||
+++ openafs-1.8.13.2.new/src/butc/afsxbsa.c 2025-07-13 19:30:19.513895421 -0400
|
||||
@@ -631,7 +631,7 @@
|
||||
#if defined(AFS_AIX_ENV)
|
||||
dynlib = dlopen("/usr/lib/libApiDS.a(dsmapish.o)", RTLD_NOW | RTLD_LOCAL | RTLD_MEMBER);
|
||||
#elif defined (AFS_AMD64_LINUX26_ENV)
|
||||
#elif defined (AFS_AMD64_LINUX_ENV)
|
||||
- dynlib = dlopen("/usr/lib64/libApiTSM64.so", RTLD_NOW | RTLD_LOCAL);
|
||||
+ dynlib = dlopen(XBSA_TSMLIB, RTLD_NOW | RTLD_LOCAL);
|
||||
#elif defined(AFS_SUN5_ENV) || defined(AFS_LINUX26_ENV)
|
||||
#elif defined(AFS_SUN5_ENV) || defined(AFS_LINUX_ENV)
|
||||
dynlib = dlopen("/usr/lib/libApiDS.so", RTLD_NOW | RTLD_LOCAL);
|
||||
#else
|
||||
diff -ru openafs-1.8.0/src/cf/tivoli.m4 openafs-1.8.0.new/src/cf/tivoli.m4
|
||||
--- openafs-1.8.0/src/cf/tivoli.m4 2018-04-06 03:21:12.000000000 +0200
|
||||
+++ openafs-1.8.0.new/src/cf/tivoli.m4 2018-06-12 16:26:26.072522485 +0200
|
||||
diff -ru openafs-1.8.13.2/src/butc/lwps.c openafs-1.8.13.2.new/src/butc/lwps.c
|
||||
--- openafs-1.8.13.2/src/butc/lwps.c 2025-01-23 12:12:55.000000000 -0500
|
||||
+++ openafs-1.8.13.2.new/src/butc/lwps.c 2025-07-14 01:02:51.409677422 -0400
|
||||
@@ -53,7 +53,7 @@
|
||||
/* XBSA Global Parameters */
|
||||
extern afs_int32 xbsaType;
|
||||
#ifdef xbsa
|
||||
-struct butx_transactionInfo butxInfo;
|
||||
+extern struct butx_transactionInfo butxInfo;
|
||||
#endif
|
||||
|
||||
static struct TapeBlock { /* A 16KB tapeblock */
|
||||
Only in openafs-1.8.13.2.new/src/butc: lwps.c~
|
||||
diff -ru openafs-1.8.13.2/src/cf/tivoli.m4 openafs-1.8.13.2.new/src/cf/tivoli.m4
|
||||
--- openafs-1.8.13.2/src/cf/tivoli.m4 2025-01-23 12:12:55.000000000 -0500
|
||||
+++ openafs-1.8.13.2.new/src/cf/tivoli.m4 2025-07-13 19:30:39.350794275 -0400
|
||||
@@ -1,45 +1,7 @@
|
||||
AC_DEFUN([OPENAFS_TIVOLI_TESTS],[
|
||||
dnl check for tivoli
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
fetchurl,
|
||||
lib,
|
||||
}:
|
||||
let
|
||||
version = "2025-08-16";
|
||||
in
|
||||
fetchurl {
|
||||
pname = "cellservdb";
|
||||
inherit version;
|
||||
url = "https://grand.central.org/dl/cellservdb/CellServDB.${version}";
|
||||
hash = "sha256-Rb6DBb9to7x5ya2ywx+wTls2c9GQmV0v5z9rmZ78dDs=";
|
||||
|
||||
meta = {
|
||||
description = "GRAND.CENTRAL.ORG Public CellServDB";
|
||||
homepage = "https://grand.central.org/csdb.html";
|
||||
maintainers = [
|
||||
lib.maintainers.quentin
|
||||
];
|
||||
# As a database, CellServDB is not copywritten.
|
||||
license = lib.licenses.publicDomain;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user