Files
computer-playbook/plugins/lookup/gpu.py
T
kevinveenbirkenbachandClaude Opus 5 47467f6cce style: settle the formatter and ruff rewrites of this change set
make autoformat reflowed a resource_filter call, a generator expression and five test files it touched along the way. The new architecture test also carried the two findings the first gate run stopped on: three RUF012, where a TestCase class attribute needs ClassVar, and two PERF401, where an append loop becomes list.extend over a generator.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-06 00:23:15 +02:00

80 lines
2.8 KiB
Python

"""Whether a service gets a GPU: it asked for one AND the host carries one.
Two facts have to agree and used to be restated at every call site. The
declaration lives in ``applications`` under ``services.<service>.gpu``; the
hardware is ``sys-svc-container``'s stat of ``/dev/nvidia0`` on the target
host, registered as ``sys_svc_container_nvidia_device``. Asking only the
declaration selects a ``-cuda`` image on a host that has no device, and that
tag has no arm64 manifest at all, so the build fails with ``no match for
platform in manifest``.
The stat is a target-host fact, so this reads the register out of the play's
variables rather than inspecting the controller it runs on.
"""
from __future__ import annotations
from typing import Any
from ansible.errors import AnsibleError
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.plugins.loader import lookup_loader
from ansible.plugins.lookup import LookupBase
from plugins.filter.resource_filter import resource_filter
DEVICE_FACT = "sys_svc_container_nvidia_device"
def _device_present(variables: dict) -> bool:
"""Whether the target host registered an NVIDIA device node.
Args:
variables: the play's variables, carrying the register.
Returns:
False while the register is absent, which is also the answer before
``sys-svc-container`` has run.
"""
register = variables.get(DEVICE_FACT) or {}
if not isinstance(register, dict):
return False
return bool((register.get("stat") or {}).get("exists"))
class LookupModule(LookupBase):
def run(
self,
terms: list[Any],
variables: dict | None = None,
**kwargs: Any,
) -> list[bool]:
"""Return ``[bool]``: the service is GPU-accelerated on this host.
Args:
terms: ``application_id`` and optionally the service name; the
service defaults to the application's own entity.
variables: the play's variables.
Raises:
AnsibleError: wrong number of terms.
"""
if not 1 <= len(terms) <= 2:
raise AnsibleError(
"gpu: expected 1 or 2 terms: lookup('gpu', application_id[, service])"
)
application_id = str(terms[0])
service_name = str(terms[1]) if len(terms) == 2 else ""
templar = getattr(self, "_templar", None)
variables = variables or getattr(templar, "available_variables", {}) or {}
applications = lookup_loader.get(
"applications", loader=self._loader, templar=templar
).run([], variables=variables)[0]
wanted = resource_filter(
applications, application_id, "gpu", service_name, False
)
return [boolean(wanted, strict=False) and _device_present(variables)]