Files
ProxMenux/oci/remote/oci_nvidia_dynamic.py
T
MacRimiandClaude Opus 5 bcabcb618c feat(oci): run official container images as native LXC containers
Adds the OCI manager: an engine that turns a Docker Compose file into an
LXC definition, a catalog of 365 applications drawn from LinuxServer.io
and other container image sources, and a per-instance registry recording
what each container was built from. Reachable from the main menu.

Catalog text is translated like every other string in the project: the
taglines go through translate() and land in lang/*.json, so the entries
read in all eight languages instead of only English.

Translation cache builder:
- a failed translation leaves the key absent rather than writing English,
  which previously made the string count as translated forever
- a result identical to a 3+ word source is rejected, catching a provider
  that silently returns the text it was given
- strings that are nothing but glossary terms keep their source spelling
  instead of being discarded as failures
- no backoff between attempts when the provider is deterministic
- application names are protected so "HAOS One" survives translation
- argos joins the provider list, and the workflow reads the OCI sources

Audit & Report:
- findings that moved in the wrong direction between runs are reported
  alongside the ones that improved
- an accepted risk can carry a review date and is flagged when it falls due
- backup checks explain in plain language what they looked at and what to
  do next

Monitor:
- disks can be excluded from periodic reads, and an idle disk says so
  instead of showing a stale temperature
- per-disk identity survives a controller or enclosure change
- scheduled Borg backups resolve their SSH key from the repository entry
- PVE upgrades log the package list and the resulting dpkg changes

The web build no longer copies scripts/ into public/: the documentation
links to GitHub, so nothing read that folder.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 18:24:59 +02:00

58 lines
2.6 KiB
Python

"""Validation for the experimental native-device/dynamic-library NVIDIA profile.
Driver files are runtime evidence, not persistent desired-state dependencies.
This module does not enable transactions before the common installer supports
the same profile.
"""
from pathlib import Path
import hashlib
import oci_nvidia_runtime as nv
from oci_ui import translate
def gpu_identity(inventory):
identities = []
for row in inventory['gpus']:
fields = [part.strip() for part in row.split(',')]
if len(fields) != 3 or not all(fields):
raise ValueError(translate('Incomplete NVIDIA identity'))
identities.append(tuple(fields[:2]))
if not identities or len(set(identities)) != len(identities):
raise ValueError(translate('Empty or duplicated NVIDIA identity'))
return sorted(identities)
def validate(config, previous, current, hook, expected_hook_sha256,
capabilities='compute,utility,video'):
if gpu_identity(previous) != gpu_identity(current):
raise ValueError(translate('The selected GPU changed'))
if nv.mount_lines(config):
raise ValueError(translate('The dynamic profile does not support static driver mounts'))
hook = Path(hook)
info = hook.stat()
if (hook.is_symlink() or not hook.is_file() or info.st_uid != 0
or info.st_mode & 0o022 or not info.st_mode & 0o111
or hashlib.sha256(hook.read_bytes()).hexdigest() != expected_hook_sha256):
raise ValueError(translate('Untrusted or modified NVIDIA hook'))
allowed = {'lxc.hook.mount': str(hook),
'lxc.environment': {'NVIDIA_VISIBLE_DEVICES=all',
f'NVIDIA_DRIVER_CAPABILITIES={capabilities}'}}
found_hook, environments = [], []
for line in config.decode().splitlines():
if not line.startswith('lxc.') or ': ' not in line:
continue
key, value = line.split(': ', 1)
if key == 'lxc.hook.mount':
found_hook.append(value)
elif key == 'lxc.environment':
environments.append(value)
elif key.startswith(('lxc.hook.', 'lxc.cgroup', 'lxc.apparmor')):
raise ValueError(translate('Security directive outside the dynamic profile'))
if found_hook != [allowed['lxc.hook.mount']] or (
len(environments) != 2 or set(environments) != allowed['lxc.environment']):
raise ValueError(translate('The NVIDIA hook or environment differs from the declared one'))
nv.check_devices(config, current)
return {'gpu_identity': gpu_identity(current), 'hook_sha256': expected_hook_sha256,
'driver_capabilities': capabilities, 'inventory': current}