nix-required-mounts: init
This commit is contained in:
@@ -243,6 +243,7 @@
|
|||||||
./programs/nh.nix
|
./programs/nh.nix
|
||||||
./programs/nix-index.nix
|
./programs/nix-index.nix
|
||||||
./programs/nix-ld.nix
|
./programs/nix-ld.nix
|
||||||
|
./programs/nix-required-mounts.nix
|
||||||
./programs/nm-applet.nix
|
./programs/nm-applet.nix
|
||||||
./programs/nncp.nix
|
./programs/nncp.nix
|
||||||
./programs/noisetorch.nix
|
./programs/noisetorch.nix
|
||||||
|
|||||||
85
nixos/modules/programs/nix-required-mounts.nix
Normal file
85
nixos/modules/programs/nix-required-mounts.nix
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.nix-required-mounts;
|
||||||
|
hook =
|
||||||
|
pkgs.nix-required-mounts.override { inherit (cfg) allowedPatterns; };
|
||||||
|
|
||||||
|
patternType = with lib.types; submodule ({ config, name, ... }: {
|
||||||
|
options.onFeatures = lib.mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
description = "Which requiredSystemFeatures should trigger relaxation of the sandbox";
|
||||||
|
default = [ name ];
|
||||||
|
};
|
||||||
|
options.paths = lib.mkOption {
|
||||||
|
type = listOf path;
|
||||||
|
description = "A list of glob patterns, indicating which paths to expose to the sandbox";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
defaults = {
|
||||||
|
opengl.onFeatures = [ "opengl" ];
|
||||||
|
opengl.paths = [
|
||||||
|
"/dev/video*"
|
||||||
|
"/dev/dri"
|
||||||
|
|
||||||
|
pkgs.addOpenGLRunpath.driverLink
|
||||||
|
# /run/opengl-driver/lib only contains symlinks
|
||||||
|
config.hardware.opengl.package
|
||||||
|
] ++ config.hardware.opengl.extraPackages;
|
||||||
|
cuda.onFeatures = [ "cuda" ];
|
||||||
|
cuda.paths = defaults.opengl.paths ++ [ "/dev/nvidia*" ];
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
meta.maintainers = with lib.maintainers; [ SomeoneSerge ];
|
||||||
|
options.programs.nix-required-mounts = {
|
||||||
|
enable = lib.mkEnableOption
|
||||||
|
"Expose extra paths to the sandbox depending on derivations' requiredSystemFeatures";
|
||||||
|
presets.opengl.enable = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = config.hardware.opengl.enable;
|
||||||
|
defaultText = lib.literalExpression "hardware.opengl.enable";
|
||||||
|
description = ''
|
||||||
|
Expose OpenGL drivers to derivations marked with requiredSystemFeatures = [ "opengl" ]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
presets.cuda.enable = lib.mkEnableOption ''
|
||||||
|
Expose CUDA drivers and GPUs to derivations marked with requiredSystemFeatures = [ "cuda" ]
|
||||||
|
'';
|
||||||
|
allowedPatterns = with lib.types;
|
||||||
|
lib.mkOption rec {
|
||||||
|
type = attrsOf patternType;
|
||||||
|
description = "The hook config, describing which paths to mount for which system features";
|
||||||
|
default = { inherit (defaults) opengl; };
|
||||||
|
defaultText = lib.literalExpression ''
|
||||||
|
{
|
||||||
|
opengl.paths = config.hardware.opengl.extraPackages ++ [
|
||||||
|
config.hardware.opengl.package
|
||||||
|
pkgs.addOpenGLRunpath.driverLink
|
||||||
|
"/dev/video*"
|
||||||
|
"/dev/dri"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
example.require-ipfs = [ "/ipfs" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable (lib.mkMerge [
|
||||||
|
{
|
||||||
|
nix.settings.pre-build-hook = lib.getExe hook;
|
||||||
|
}
|
||||||
|
(lib.mkIf cfg.presets.opengl.enable {
|
||||||
|
nix.settings.system-features = [ "opengl" ];
|
||||||
|
programs.nix-required-mounts.allowedPatterns = {
|
||||||
|
inherit (defaults) opengl;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.mkIf cfg.presets.cuda.enable {
|
||||||
|
nix.settings.system-features = [ "cuda" ];
|
||||||
|
programs.nix-required-mounts.allowedPatterns = {
|
||||||
|
inherit (defaults) cuda;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
||||||
118
pkgs/by-name/ni/nix-required-mounts/main.py
Normal file
118
pkgs/by-name/ni/nix-required-mounts/main.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import glob
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
import textwrap
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
from itertools import chain
|
||||||
|
from pathlib import Path
|
||||||
|
from sys import stderr
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
CONFIG = {
|
||||||
|
"nixExe": "nix",
|
||||||
|
"allowedPatterns": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
parser = ArgumentParser("pre-build-hook")
|
||||||
|
parser.add_argument("derivation_path")
|
||||||
|
parser.add_argument("sandbox_path", nargs="?")
|
||||||
|
parser.add_argument(
|
||||||
|
"--issue-command",
|
||||||
|
choices=("always", "conditional", "never"),
|
||||||
|
default="conditional",
|
||||||
|
help="Whether to print extra-sandbox-paths",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--issue-stop",
|
||||||
|
choices=("always", "conditional", "never"),
|
||||||
|
default="conditional",
|
||||||
|
help="Whether to print the final empty line",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def symlink_parents(p: Path) -> List[Path]:
|
||||||
|
out = []
|
||||||
|
while p.is_symlink() and p not in out:
|
||||||
|
p = p.readlink()
|
||||||
|
out.append(p)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def entrypoint():
|
||||||
|
if __name__ != "__main__":
|
||||||
|
return
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
drv_path = args.derivation_path
|
||||||
|
|
||||||
|
if not Path(drv_path).exists():
|
||||||
|
print(
|
||||||
|
f"[E] {drv_path} doesn't exist."
|
||||||
|
" This may happen with the remote builds."
|
||||||
|
" Exiting the hook",
|
||||||
|
file=stderr,
|
||||||
|
)
|
||||||
|
|
||||||
|
proc = subprocess.run(
|
||||||
|
[
|
||||||
|
CONFIG["nixExe"],
|
||||||
|
"show-derivation",
|
||||||
|
drv_path,
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
drv = json.loads(proc.stdout)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(
|
||||||
|
"[E] Couldn't parse the output of"
|
||||||
|
"`nix show-derivation`"
|
||||||
|
f". Expected JSON, observed: {proc.stdout}",
|
||||||
|
file=stderr,
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
textwrap.indent(proc.stdout.decode("utf8"), prefix=" " * 4),
|
||||||
|
file=stderr,
|
||||||
|
)
|
||||||
|
print("[I] Exiting the nix-required-binds hook", file=stderr)
|
||||||
|
return
|
||||||
|
[canon_drv_path] = drv.keys()
|
||||||
|
|
||||||
|
allowed_patterns = CONFIG["allowedPatterns"]
|
||||||
|
known_features = set(
|
||||||
|
chain.from_iterable(
|
||||||
|
pattern["onFeatures"] for pattern in allowed_patterns.values()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
drv_env = drv[canon_drv_path].get("env", {})
|
||||||
|
features = drv_env.get("requiredSystemFeatures", [])
|
||||||
|
if isinstance(features, str):
|
||||||
|
features = features.split()
|
||||||
|
|
||||||
|
features = list(filter(known_features.__contains__, features))
|
||||||
|
|
||||||
|
patterns = list(chain.from_iterable(allowed_patterns[f]["paths"] for f in features)) # noqa: E501
|
||||||
|
|
||||||
|
roots = sorted(
|
||||||
|
set(Path(path) for pattern in patterns for path in glob.glob(pattern))
|
||||||
|
)
|
||||||
|
|
||||||
|
# the pre-build-hook command
|
||||||
|
if args.issue_command == "always" or (
|
||||||
|
args.issue_command == "conditional" and roots
|
||||||
|
):
|
||||||
|
print("extra-sandbox-paths")
|
||||||
|
|
||||||
|
# arguments, one per line
|
||||||
|
for p in roots:
|
||||||
|
guest_path, host_path = p, p
|
||||||
|
print(f"{guest_path}={host_path}")
|
||||||
|
|
||||||
|
# terminated by an empty line
|
||||||
|
something_to_terminate = args.issue_stop == "conditional" and roots
|
||||||
|
if args.issue_stop == "always" or something_to_terminate:
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
entrypoint()
|
||||||
57
pkgs/by-name/ni/nix-required-mounts/package.nix
Normal file
57
pkgs/by-name/ni/nix-required-mounts/package.nix
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{ addOpenGLRunpath
|
||||||
|
, cmake
|
||||||
|
, allowedPatterns ? rec {
|
||||||
|
opengl.onFeatures = [ "opengl" ];
|
||||||
|
opengl.paths = [
|
||||||
|
addOpenGLRunpath.driverLink
|
||||||
|
"/dev/video*"
|
||||||
|
"/dev/dri"
|
||||||
|
];
|
||||||
|
cuda.onFeatures = [ "cuda" ];
|
||||||
|
cuda.paths = opengl.paths ++ [
|
||||||
|
"/dev/nvidia*"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
, buildPackages
|
||||||
|
, formats
|
||||||
|
, lib
|
||||||
|
, nix
|
||||||
|
, python3
|
||||||
|
, runCommand
|
||||||
|
}:
|
||||||
|
|
||||||
|
|
||||||
|
let
|
||||||
|
confPath = (formats.pythonVars { }).generate "config.py" {
|
||||||
|
CONFIG = {
|
||||||
|
inherit allowedPatterns;
|
||||||
|
nixExe = lib.getExe nix;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pname = "nix-required-mounts";
|
||||||
|
in
|
||||||
|
|
||||||
|
runCommand pname
|
||||||
|
{
|
||||||
|
inherit confPath;
|
||||||
|
meta.mainProgram = pname;
|
||||||
|
} ''
|
||||||
|
${lib.getExe buildPackages.python3.pkgs.flake8} ${./main.py}
|
||||||
|
|
||||||
|
cat > main.py << EOF
|
||||||
|
#!${lib.getExe python3}
|
||||||
|
|
||||||
|
$(cat ${./main.py})
|
||||||
|
EOF
|
||||||
|
|
||||||
|
sed -ie '
|
||||||
|
/^entrypoint()$/ {
|
||||||
|
x ;
|
||||||
|
r ${confPath}
|
||||||
|
}' main.py
|
||||||
|
|
||||||
|
echo "entrypoint()" >> main.py
|
||||||
|
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install main.py $out/bin/${pname}
|
||||||
|
''
|
||||||
2
pkgs/by-name/ni/nix-required-mounts/pyproject.toml
Normal file
2
pkgs/by-name/ni/nix-required-mounts/pyproject.toml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[tool.black]
|
||||||
|
line-length = 79
|
||||||
Reference in New Issue
Block a user