gpustack-runtime 0.2.2.post7__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/PKG-INFO +2 -2
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/deploy/manifests/kubernetes.yaml +24 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/_version.py +2 -2
- gpustack_runtime-0.2.3/gpustack_runtime/_version_appendix.py +1 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/cmds/detector.py +50 -9
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/__types__.py +205 -1
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/ascend.py +11 -3
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/iluvatar.py +5 -1
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/thead.py +18 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/docker.py +20 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/kuberentes.py +345 -1
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/podman.py +20 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/__init__.py +8 -3
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/__types__.py +168 -12
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/__utils__.py +139 -14
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/amd.py +208 -48
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/ascend.py +298 -120
- gpustack_runtime-0.2.3/gpustack_runtime/detector/cambricon.py +348 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/hygon.py +107 -28
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/iluvatar.py +146 -43
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/metax.py +138 -49
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/mthreads.py +137 -50
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/nvidia.py +329 -136
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyamdgpu/__init__.py +13 -0
- gpustack_runtime-0.2.3/gpustack_runtime/detector/pycndev/__init__.py +840 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pydcmi/__init__.py +52 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/thead.py +291 -95
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/envs.py +22 -10
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/ruff.toml +1 -0
- gpustack_runtime-0.2.3/specs/2026-08-14-detector-alignment-and-workload-exit-status.md +1088 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/deployer/test_docker_status.py +181 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/deployer/test_kubernetes_status.py +446 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/deployer/test_podman_status.py +144 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/deployer/test_runtime_class.py +183 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/deployer/test_visible_devices_ordering.py +349 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/test_workload_status.py +76 -1
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/README.md +46 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_amd_mi300x.json +0 -2
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_amd_mi308x.json +0 -8
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/detect_output_amd_rx7800xt.json +54 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_ascend_310p3.json +0 -2
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_ascend_910b2.json +96 -96
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_hygon_k100ai.json +0 -8
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_metax_c500.json +0 -8
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_gb10.json +1 -1
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h100.json +8 -8
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h100_mig.json +151 -128
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_h200.json +8 -8
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4080super.json +2 -2
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4090_48g.json +54 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx4090d.json +1 -1
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/detect_output_nvidia_rtx5090d.json +9 -8
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/detect_output_thead_ppu.json +402 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_amd_rx7800xt.json +9 -1
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4090_48g.json +27 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/samples/topology_output_thead_ppu.json +413 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_amd.py +572 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_ascend.py +735 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_cambricon.py +568 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_detector_cli.py +162 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_detector_types.py +422 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_hygon.py +521 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_iluvatar.py +333 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_metax.py +390 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/test_mig_devices.py +5 -5
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_mthreads.py +445 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_nvidia.py +771 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_pycndev.py +926 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_samples.py +97 -0
- gpustack_runtime-0.2.3/tests/gpustack_runtime/detector/test_thead.py +830 -0
- gpustack_runtime-0.2.2.post7/gpustack_runtime/_version_appendix.py +0 -1
- gpustack_runtime-0.2.2.post7/gpustack_runtime/detector/cambricon.py +0 -133
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/samples/README.md +0 -3
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/samples/detect_output_amd_rx7800xt.json +0 -29
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/samples/detect_output_thead_ppu.json +0 -50
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/samples/topology_output_thead_ppu.json +0 -35
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_amd.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_ascend.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_cambricon.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_hygon.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_iluvatar.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_metax.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_mthreads.py +0 -23
- gpustack_runtime-0.2.2.post7/tests/gpustack_runtime/detector/test_nvidia.py +0 -23
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.codespelldict +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.codespellrc +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.dockerignore +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.gitattributes +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.gitignore +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.pre-commit-config.yaml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/.python-version +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/LICENSE +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/Makefile +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/README.md +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/deploy/manifests/docker-compose.yaml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/docs/index.md +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/docs/modules/gpustack_runtime.deployer.md +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/docs/modules/gpustack_runtime.detector.md +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/docs/modules/gpustack_runtime.md +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/__main__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/_version.pyi +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/cmds/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/cmds/__types__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/cmds/deployer.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/cmds/images.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/__patches__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/__utils__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/__types__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/__utils__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/amd.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/hygon.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/metax.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/k8s/devicemanager/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyamdsmi/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyhgml/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyhgml/libhgml.so +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyhgml/libuki.so +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyhsa/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyixml/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pymtml/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pymxsml/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pynvml/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/detector/pyrocmsmi/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/logging.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/hatch.toml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/mkdocs.yml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/pack/Dockerfile +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/pack/Dockerfile.dummy +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/pyproject.toml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/pytest.ini +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_compare_versions.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_correct_runner_image.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_multiple_jsons.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_multiple_yamls.yaml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_single_json.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_load_yaml_or_json_single_yaml.yaml +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/fixtures/test_nginx_entrypoint.sh +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/test_privileged.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/deployer/test_utils.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/fixtures/__init__.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_amd_mi300x.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_amd_mi308x.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_ascend_310p3.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_ascend_910b2.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_hygon_k100ai.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_metax_c500.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_mthreads_s5000.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h100.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h100_mig.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_h200.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4080super.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx4090d.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/samples/topology_output_nvidia_rtx5090d.json +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/tests/gpustack_runtime/detector/test_detector_utils.py +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/uv.lock +0 -0
- {gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/uv.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: gpustack-runtime
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: GPUStack Runtime is library for detecting GPU resources and launching GPU workloads.
|
|
5
5
|
Project-URL: Homepage, https://github.com/gpustack/runtime
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/gpustack/gpustack/issues
|
|
@@ -25,6 +25,25 @@ rules:
|
|
|
25
25
|
- "pods/exec"
|
|
26
26
|
verbs:
|
|
27
27
|
- "*"
|
|
28
|
+
# Allow reading the Events of a workload Pod, so an image-pull failure
|
|
29
|
+
# reports the registry error behind a bare "ImagePullBackOff" reason.
|
|
30
|
+
# Kept as its own rule with only "get"/"list": the rule above grants "*",
|
|
31
|
+
# which would also allow creating and deleting Events.
|
|
32
|
+
- apiGroups:
|
|
33
|
+
- ""
|
|
34
|
+
resources:
|
|
35
|
+
- "events"
|
|
36
|
+
verbs:
|
|
37
|
+
- "get"
|
|
38
|
+
- "list"
|
|
39
|
+
# Allow resolving the vendor RuntimeClass (e.g. "ascend", "nvidia") for
|
|
40
|
+
# accelerated workload Pods, see GPUSTACK_RUNTIME_DEPLOY_RESOURCE_KEY_MAP_RUNTIME_CLASS.
|
|
41
|
+
- apiGroups:
|
|
42
|
+
- "node.k8s.io"
|
|
43
|
+
resources:
|
|
44
|
+
- "runtimeclasses"
|
|
45
|
+
verbs:
|
|
46
|
+
- "get"
|
|
28
47
|
---
|
|
29
48
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
30
49
|
kind: RoleBinding
|
|
@@ -76,6 +95,11 @@ spec:
|
|
|
76
95
|
"app.kubernetes.io/name": "gpustack-runtime"
|
|
77
96
|
spec:
|
|
78
97
|
# Provide GPU resource request for gpustack-runtime if not using default runtime.
|
|
98
|
+
# The runtimeClassName set here is mirrored to every deployed workload Pod
|
|
99
|
+
# that does not resolve one itself. Usually this is unnecessary: workload
|
|
100
|
+
# Pods requesting device plugin resources automatically adopt the mapped
|
|
101
|
+
# vendor RuntimeClass when it exists in the cluster,
|
|
102
|
+
# see GPUSTACK_RUNTIME_DEPLOY_RESOURCE_KEY_MAP_RUNTIME_CLASS.
|
|
79
103
|
#
|
|
80
104
|
# runtimeClassName: nvidia
|
|
81
105
|
|
|
@@ -27,8 +27,8 @@ version_tuple: VERSION_TUPLE
|
|
|
27
27
|
__commit_id__: COMMIT_ID
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
|
|
30
|
-
__version__ = version = '0.2.
|
|
31
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
30
|
+
__version__ = version = '0.2.3'
|
|
31
|
+
__version_tuple__ = version_tuple = (0, 2, 3)
|
|
32
32
|
try:
|
|
33
33
|
from ._version_appendix import git_commit
|
|
34
34
|
__commit_id__ = commit_id = git_commit
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
git_commit = "518db70"
|
|
@@ -26,6 +26,7 @@ class DetectDevicesSubCommand(SubCommand):
|
|
|
26
26
|
|
|
27
27
|
format: str = "table"
|
|
28
28
|
watch: int = 0
|
|
29
|
+
no_usage: bool = False
|
|
29
30
|
|
|
30
31
|
@staticmethod
|
|
31
32
|
def register(parser: _SubParsersAction):
|
|
@@ -49,19 +50,26 @@ class DetectDevicesSubCommand(SubCommand):
|
|
|
49
50
|
help="Continuously watch for GPU in intervals of N seconds",
|
|
50
51
|
)
|
|
51
52
|
|
|
53
|
+
detect_parser.add_argument(
|
|
54
|
+
"--no-usage",
|
|
55
|
+
action="store_true",
|
|
56
|
+
help="Report inventory only, without querying utilization, temperature or power",
|
|
57
|
+
)
|
|
58
|
+
|
|
52
59
|
detect_parser.set_defaults(func=DetectDevicesSubCommand)
|
|
53
60
|
|
|
54
61
|
def __init__(self, args: Namespace):
|
|
55
62
|
self.format = args.format
|
|
56
63
|
self.watch = args.watch
|
|
64
|
+
self.no_usage = args.no_usage
|
|
57
65
|
|
|
58
66
|
def run(self):
|
|
59
67
|
while True:
|
|
60
|
-
devs: Devices = detect_devices(fast=False)
|
|
68
|
+
devs: Devices = detect_devices(fast=False, usage=not self.no_usage)
|
|
61
69
|
print("\033[2J\033[H", end="")
|
|
62
70
|
match self.format.lower():
|
|
63
71
|
case "json":
|
|
64
|
-
print(format_devices_json(devs))
|
|
72
|
+
print(format_devices_json(devs, usage=not self.no_usage))
|
|
65
73
|
case _:
|
|
66
74
|
# Group devices by manufacturer.
|
|
67
75
|
group_devs = group_devices_by_manufacturer(devs)
|
|
@@ -70,7 +78,9 @@ class DetectDevicesSubCommand(SubCommand):
|
|
|
70
78
|
else:
|
|
71
79
|
# Print each group separately.
|
|
72
80
|
for devs in group_devs.values():
|
|
73
|
-
print(
|
|
81
|
+
print(
|
|
82
|
+
format_devices_table(devs, usage=not self.no_usage),
|
|
83
|
+
)
|
|
74
84
|
if not self.watch:
|
|
75
85
|
break
|
|
76
86
|
time.sleep(self.watch)
|
|
@@ -134,11 +144,37 @@ class GetDevicesTopologySubCommand(SubCommand):
|
|
|
134
144
|
print(os.linesep.join(legend_lines))
|
|
135
145
|
|
|
136
146
|
|
|
137
|
-
|
|
138
|
-
|
|
147
|
+
_USAGE_ONLY_KEYS = (
|
|
148
|
+
"cores_utilization",
|
|
149
|
+
"memory_used",
|
|
150
|
+
"memory_utilization",
|
|
151
|
+
"temperature",
|
|
152
|
+
"power_used",
|
|
153
|
+
)
|
|
154
|
+
"""
|
|
155
|
+
The keys only the usage query fills. `memory_status` is deliberately absent:
|
|
156
|
+
the information query reports it too, which is why the table keeps Status.
|
|
157
|
+
"""
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def format_devices_json(devs: Devices, usage: bool = True) -> str:
|
|
161
|
+
devs_dict = [dev.to_dict() for dev in devs]
|
|
162
|
+
|
|
163
|
+
if not usage:
|
|
164
|
+
# Without the usage query these fields hold their defaults, and a
|
|
165
|
+
# serialized 0 reads as a real idle measurement. The table drops them
|
|
166
|
+
# for that reason, and a machine-readable consumer is the more likely of
|
|
167
|
+
# the two to act on it -- so absent, meaning unmeasured.
|
|
168
|
+
for dev_dict in devs_dict:
|
|
169
|
+
mig_devs_dict = (dev_dict.get("appendix") or {}).get("mig_devices") or []
|
|
170
|
+
for d in [dev_dict, *mig_devs_dict]:
|
|
171
|
+
for key in _USAGE_ONLY_KEYS:
|
|
172
|
+
d.pop(key, None)
|
|
173
|
+
|
|
174
|
+
return json.dumps(devs_dict, indent=2)
|
|
139
175
|
|
|
140
176
|
|
|
141
|
-
def format_devices_table(devs: Devices) -> str:
|
|
177
|
+
def format_devices_table(devs: Devices, usage: bool = True) -> str:
|
|
142
178
|
if not devs:
|
|
143
179
|
return "No GPUs detected."
|
|
144
180
|
|
|
@@ -150,9 +186,14 @@ def format_devices_table(devs: Devices) -> str:
|
|
|
150
186
|
row = [
|
|
151
187
|
str(dev.index),
|
|
152
188
|
dev.name if dev.name else "N/A",
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
189
|
+
# Without the usage query these fields hold their defaults, and a
|
|
190
|
+
# rendered 0 would read as a real idle measurement. Total memory
|
|
191
|
+
# and the status stay, being reported by the information query.
|
|
192
|
+
f"{dev.memory_used}MiB / {dev.memory}MiB"
|
|
193
|
+
if usage
|
|
194
|
+
else f"N/A / {dev.memory}MiB",
|
|
195
|
+
f"{dev.cores_utilization}%" if usage else "N/A",
|
|
196
|
+
f"{dev.temperature}C" if usage and dev.temperature is not None else "N/A",
|
|
156
197
|
dev.compute_capability if dev.compute_capability else "N/A",
|
|
157
198
|
"OK" if dev.memory_status == DeviceMemoryStatusEnum.HEALTHY else "ERR",
|
|
158
199
|
]
|
{gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/__types__.py
RENAMED
|
@@ -8,7 +8,7 @@ from abc import ABC, abstractmethod
|
|
|
8
8
|
from concurrent.futures import ThreadPoolExecutor
|
|
9
9
|
from dataclasses import dataclass, field
|
|
10
10
|
from enum import Enum
|
|
11
|
-
from typing import TYPE_CHECKING
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
12
|
|
|
13
13
|
from dataclasses_json import dataclass_json
|
|
14
14
|
|
|
@@ -1130,6 +1130,165 @@ class WorkloadStatusOperation:
|
|
|
1130
1130
|
return self._name_rfc1123_guard
|
|
1131
1131
|
|
|
1132
1132
|
|
|
1133
|
+
@dataclass_json
|
|
1134
|
+
@dataclass
|
|
1135
|
+
class WorkloadStatusExit:
|
|
1136
|
+
"""
|
|
1137
|
+
An exit information of a workload's container.
|
|
1138
|
+
|
|
1139
|
+
Attributes:
|
|
1140
|
+
name (str):
|
|
1141
|
+
Name representing the exited target, e.g., human-readable container name.
|
|
1142
|
+
token (WorkloadOperationToken):
|
|
1143
|
+
Token of the exited target, e.g., container ID.
|
|
1144
|
+
exit_code (int | None):
|
|
1145
|
+
Exit code of the container.
|
|
1146
|
+
reason (str):
|
|
1147
|
+
Short reason of the termination or the blocking.
|
|
1148
|
+
message (str):
|
|
1149
|
+
Detailed message of the termination or the blocking.
|
|
1150
|
+
started_at (str):
|
|
1151
|
+
Start time of the container's last execution.
|
|
1152
|
+
finished_at (str):
|
|
1153
|
+
Finish time of the container's last execution.
|
|
1154
|
+
restart_count (int):
|
|
1155
|
+
Restart times of the container.
|
|
1156
|
+
|
|
1157
|
+
"""
|
|
1158
|
+
|
|
1159
|
+
name: str
|
|
1160
|
+
"""
|
|
1161
|
+
Name representing the exited target, e.g., human-readable container name.
|
|
1162
|
+
"""
|
|
1163
|
+
token: WorkloadOperationToken
|
|
1164
|
+
"""
|
|
1165
|
+
Token of the exited target, e.g. container ID,
|
|
1166
|
+
which addresses the same container as the logs/exec operations.
|
|
1167
|
+
"""
|
|
1168
|
+
exit_code: int | None = None
|
|
1169
|
+
"""
|
|
1170
|
+
Exit code of the container,
|
|
1171
|
+
None if the container has not terminated, e.g. blocked from starting.
|
|
1172
|
+
"""
|
|
1173
|
+
reason: str = ""
|
|
1174
|
+
"""
|
|
1175
|
+
Short reason of the termination or the blocking,
|
|
1176
|
+
e.g. "OOMKilled", "Error", "ImagePullBackOff".
|
|
1177
|
+
"""
|
|
1178
|
+
message: str = ""
|
|
1179
|
+
"""
|
|
1180
|
+
Detailed message of the termination or the blocking.
|
|
1181
|
+
"""
|
|
1182
|
+
started_at: str = ""
|
|
1183
|
+
"""
|
|
1184
|
+
Start time of the container's last execution,
|
|
1185
|
+
empty if the container has never started.
|
|
1186
|
+
"""
|
|
1187
|
+
finished_at: str = ""
|
|
1188
|
+
"""
|
|
1189
|
+
Finish time of the container's last execution,
|
|
1190
|
+
empty if the container has not finished.
|
|
1191
|
+
"""
|
|
1192
|
+
restart_count: int = 0
|
|
1193
|
+
"""
|
|
1194
|
+
Restart times of the container.
|
|
1195
|
+
"""
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
_CONTAINER_EXITED_STATUSES = ("exited", "dead", "restarting")
|
|
1199
|
+
"""
|
|
1200
|
+
Container statuses carrying an exit code. "restarting" is one of them: a
|
|
1201
|
+
crash-looping container sits there between attempts with the last attempt's
|
|
1202
|
+
ExitCode already filled in, and that code is the diagnosis being asked for.
|
|
1203
|
+
"""
|
|
1204
|
+
|
|
1205
|
+
_CONTAINER_UNSET_TIMESTAMP_PREFIX = "0001-01-01"
|
|
1206
|
+
"""
|
|
1207
|
+
What Docker fills an unset timestamp with -- Go's zero time -- rather than
|
|
1208
|
+
omitting the key, which is why a plain `.get(..., "")` never defaults.
|
|
1209
|
+
"""
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
def parse_container_exit(
|
|
1213
|
+
c: Any,
|
|
1214
|
+
component_name_label: str,
|
|
1215
|
+
) -> WorkloadStatusExit | None:
|
|
1216
|
+
"""
|
|
1217
|
+
Build the exit entry of a container that has terminated.
|
|
1218
|
+
|
|
1219
|
+
Docker and Podman report the same State object -- podman-py is Docker-API
|
|
1220
|
+
compatible and both call sites inspect a fully reloaded container -- so both
|
|
1221
|
+
deployers share this. Keeping it in one place is the point: the reason
|
|
1222
|
+
derivation and the timestamp normalization below are exactly the kind of
|
|
1223
|
+
detail that silently drifts when it lives in two files.
|
|
1224
|
+
|
|
1225
|
+
Args:
|
|
1226
|
+
c:
|
|
1227
|
+
A Docker-API-compatible container to inspect.
|
|
1228
|
+
component_name_label:
|
|
1229
|
+
The label the deployer names its components with.
|
|
1230
|
+
|
|
1231
|
+
Returns:
|
|
1232
|
+
A WorkloadStatusExit if the container has terminated, None if it is
|
|
1233
|
+
still running or pending and so contributes nothing.
|
|
1234
|
+
|
|
1235
|
+
"""
|
|
1236
|
+
if c.status not in _CONTAINER_EXITED_STATUSES:
|
|
1237
|
+
return None
|
|
1238
|
+
|
|
1239
|
+
# Every read is .get()-able: a container whose State is missing keys (or
|
|
1240
|
+
# missing entirely) must degrade gracefully, never raise.
|
|
1241
|
+
state = c.attrs.get("State", {}) or {}
|
|
1242
|
+
|
|
1243
|
+
exit_code = state.get("ExitCode")
|
|
1244
|
+
if state.get("OOMKilled"):
|
|
1245
|
+
reason = "OOMKilled"
|
|
1246
|
+
elif state.get("Error"):
|
|
1247
|
+
reason = "Error"
|
|
1248
|
+
elif exit_code not in (0, None):
|
|
1249
|
+
# Docker fills State.Error for a container that failed to *start*, not
|
|
1250
|
+
# for one that ran and exited non-zero -- the commonest crash of all.
|
|
1251
|
+
# Without this the caller has an exit code and no reason, so it sets no
|
|
1252
|
+
# state_message, while the Kubernetes deployer reports "Error" for the
|
|
1253
|
+
# same event. Same field, same answer, either backend.
|
|
1254
|
+
reason = "Error"
|
|
1255
|
+
else:
|
|
1256
|
+
reason = ""
|
|
1257
|
+
|
|
1258
|
+
return WorkloadStatusExit(
|
|
1259
|
+
name=c.labels.get(component_name_label, "") or c.name,
|
|
1260
|
+
token=c.attrs.get("Id", "") or c.name,
|
|
1261
|
+
exit_code=exit_code,
|
|
1262
|
+
reason=reason,
|
|
1263
|
+
message=state.get("Error", ""),
|
|
1264
|
+
started_at=_parse_container_timestamp(state.get("StartedAt")),
|
|
1265
|
+
finished_at=_parse_container_timestamp(state.get("FinishedAt")),
|
|
1266
|
+
restart_count=c.attrs.get("RestartCount", 0),
|
|
1267
|
+
)
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
def _parse_container_timestamp(value: str | None) -> str:
|
|
1271
|
+
"""
|
|
1272
|
+
Normalize a container's State timestamp to what WorkloadStatusExit promises.
|
|
1273
|
+
|
|
1274
|
+
Args:
|
|
1275
|
+
value:
|
|
1276
|
+
The raw timestamp as the container's State reports it.
|
|
1277
|
+
|
|
1278
|
+
Returns:
|
|
1279
|
+
The timestamp, empty if it never happened.
|
|
1280
|
+
|
|
1281
|
+
"""
|
|
1282
|
+
if not value or value.startswith(_CONTAINER_UNSET_TIMESTAMP_PREFIX):
|
|
1283
|
+
# WorkloadStatusExit documents these as empty when they never happened,
|
|
1284
|
+
# and Go's zero time rendered by a UI reads as "January 1, year 1".
|
|
1285
|
+
return ""
|
|
1286
|
+
# Docker reports 9-digit nanoseconds where the Kubernetes deployer formats 6
|
|
1287
|
+
# (_TIMESTAMP_FORMAT), and strptime's %f accepts at most 6, so a consumer
|
|
1288
|
+
# parsing this field would succeed on one backend and raise on the other.
|
|
1289
|
+
return re.sub(r"(\.\d{6})\d+", r"\1", value)
|
|
1290
|
+
|
|
1291
|
+
|
|
1133
1292
|
@dataclass_json
|
|
1134
1293
|
@dataclass
|
|
1135
1294
|
class WorkloadStatus:
|
|
@@ -1153,6 +1312,9 @@ class WorkloadStatus:
|
|
|
1153
1312
|
The operation for the executable containers of the workload.
|
|
1154
1313
|
loggable (list[WorkloadStatusOperation]):
|
|
1155
1314
|
The operation for the loggable containers of the workload.
|
|
1315
|
+
exits (list[WorkloadStatusExit]):
|
|
1316
|
+
The exit information for the terminated or start-blocked containers
|
|
1317
|
+
of the workload.
|
|
1156
1318
|
state (WorkloadStatusStateEnum):
|
|
1157
1319
|
Current state of the workload.
|
|
1158
1320
|
|
|
@@ -1192,6 +1354,12 @@ class WorkloadStatus:
|
|
|
1192
1354
|
"""
|
|
1193
1355
|
The operation for the loggable containers of the workload.
|
|
1194
1356
|
"""
|
|
1357
|
+
exits: list[WorkloadStatusExit] | None = field(default_factory=list)
|
|
1358
|
+
"""
|
|
1359
|
+
The exit information for the terminated or start-blocked containers
|
|
1360
|
+
of the workload, one entry per container.
|
|
1361
|
+
Containers in neither state are not listed.
|
|
1362
|
+
"""
|
|
1195
1363
|
state: WorkloadStatusStateEnum = WorkloadStatusStateEnum.UNKNOWN
|
|
1196
1364
|
"""
|
|
1197
1365
|
The current state of the workload.
|
|
@@ -1619,6 +1787,42 @@ class Deployer(ABC):
|
|
|
1619
1787
|
)
|
|
1620
1788
|
return ret
|
|
1621
1789
|
|
|
1790
|
+
def map_visible_devices_ordering(
|
|
1791
|
+
self,
|
|
1792
|
+
runtime_envs: list[str],
|
|
1793
|
+
) -> dict[str, str]:
|
|
1794
|
+
"""
|
|
1795
|
+
Return the device ordering environment variables
|
|
1796
|
+
for the given runtime visible devices env names.
|
|
1797
|
+
|
|
1798
|
+
Only meaningful for a container seeing every device of the host:
|
|
1799
|
+
it must number the devices as the detector, the driver and the vendor
|
|
1800
|
+
tooling do, otherwise an index computed from detection addresses
|
|
1801
|
+
another device inside the container.
|
|
1802
|
+
For example, CUDA's default ordering, CUDA_DEVICE_ORDER=FASTEST_FIRST,
|
|
1803
|
+
sorts the visible devices by a performance heuristic, which reshuffles
|
|
1804
|
+
the ordinals on a heterogeneous host,
|
|
1805
|
+
while PCI_BUS_ID sorts by PCI bus id, as NVML and the detector enumerate,
|
|
1806
|
+
see https://github.com/gpustack/gpustack/issues/6041.
|
|
1807
|
+
No other manufacturer documents such an ordering switch,
|
|
1808
|
+
so none of them contributes a variable.
|
|
1809
|
+
|
|
1810
|
+
Args:
|
|
1811
|
+
runtime_envs:
|
|
1812
|
+
The runtime visible devices environment variable names.
|
|
1813
|
+
|
|
1814
|
+
Returns:
|
|
1815
|
+
A dictionary mapping device ordering environment variable names
|
|
1816
|
+
to corresponding values.
|
|
1817
|
+
|
|
1818
|
+
"""
|
|
1819
|
+
if any(
|
|
1820
|
+
self.get_manufacturer(runtime_env) == ManufacturerEnum.NVIDIA
|
|
1821
|
+
for runtime_env in runtime_envs
|
|
1822
|
+
):
|
|
1823
|
+
return {"CUDA_DEVICE_ORDER": "PCI_BUS_ID"}
|
|
1824
|
+
return {}
|
|
1825
|
+
|
|
1622
1826
|
def map_visible_devices_affinities(
|
|
1623
1827
|
self,
|
|
1624
1828
|
runtime_envs: list[str],
|
{gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/ascend.py
RENAMED
|
@@ -112,9 +112,17 @@ class AscendGenerator(Generator):
|
|
|
112
112
|
|
|
113
113
|
container_device_nodes = []
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
# The device node is numbered by the driver's physical id, which
|
|
116
|
+
# Device.index no longer carries: it is the detector's enumeration
|
|
117
|
+
# index, i.e. the DCMI logic id here. The two are different
|
|
118
|
+
# numbers, so a device without a physical id is skipped instead of
|
|
119
|
+
# addressed by the index, which would resolve to another NPU's
|
|
120
|
+
# node. The detector already drops such a device; this guards the
|
|
121
|
+
# devices a caller passes in.
|
|
122
|
+
cdn_number = dev.appendix.get("physical_id")
|
|
123
|
+
if cdn_number is None:
|
|
124
|
+
continue
|
|
125
|
+
cdn_path = f"/dev/davinci{cdn_number}"
|
|
118
126
|
cdn = device_to_cdi_device_node(
|
|
119
127
|
path=cdn_path,
|
|
120
128
|
)
|
{gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/iluvatar.py
RENAMED
|
@@ -81,8 +81,12 @@ class IluvatarGenerator(Generator):
|
|
|
81
81
|
|
|
82
82
|
container_device_nodes = []
|
|
83
83
|
|
|
84
|
+
# The device node is numbered by the driver's minor number, which
|
|
85
|
+
# Device.index no longer carries: it is the detector's enumeration
|
|
86
|
+
# index. Fall back to it for a device whose minor number could not
|
|
87
|
+
# be read.
|
|
84
88
|
cdn = device_to_cdi_device_node(
|
|
85
|
-
path=f"/dev/iluvatar{dev.index}",
|
|
89
|
+
path=f"/dev/iluvatar{dev.appendix.get('minor_number', dev.index)}",
|
|
86
90
|
)
|
|
87
91
|
if not cdn:
|
|
88
92
|
continue
|
{gpustack_runtime-0.2.2.post7 → gpustack_runtime-0.2.3}/gpustack_runtime/deployer/cdi/thead.py
RENAMED
|
@@ -82,11 +82,29 @@ class THeadGenerator(Generator):
|
|
|
82
82
|
|
|
83
83
|
container_device_nodes = []
|
|
84
84
|
|
|
85
|
+
# Named after the card ordinal, i.e. the enumeration index, not
|
|
86
|
+
# after the driver's minor number that the detector records in
|
|
87
|
+
# appendix["minor_number"]. Unlike /dev/nvidia{N} and
|
|
88
|
+
# /dev/iluvatar{N}, which the minor number does name, the operator
|
|
89
|
+
# records T-Head's purely to PROVE this node addresses the card it
|
|
90
|
+
# describes, by comparing it against the node's character-device
|
|
91
|
+
# minor.
|
|
85
92
|
cdn = device_to_cdi_device_node(
|
|
86
93
|
path=f"/dev/alixpu_ppu{dev.index}",
|
|
87
94
|
)
|
|
88
95
|
if not cdn:
|
|
89
96
|
continue
|
|
97
|
+
|
|
98
|
+
# So make that comparison rather than assume it: where the detector
|
|
99
|
+
# read a minor, the node this ordinal names must carry it. The two
|
|
100
|
+
# numbers are independent -- neither is computed from the other, at
|
|
101
|
+
# any offset or none -- so a mismatch means this ordinal addresses a
|
|
102
|
+
# neighbouring accelerator, which the operator's allocator refuses
|
|
103
|
+
# outright rather than hand over.
|
|
104
|
+
dev_minor_number = dev.appendix.get("minor_number")
|
|
105
|
+
if dev_minor_number is not None and cdn.minor != dev_minor_number:
|
|
106
|
+
continue
|
|
107
|
+
|
|
90
108
|
all_device_nodes.append(cdn)
|
|
91
109
|
container_device_nodes.append(cdn)
|
|
92
110
|
|
|
@@ -45,6 +45,7 @@ from .__types__ import (
|
|
|
45
45
|
WorkloadStatus,
|
|
46
46
|
WorkloadStatusOperation,
|
|
47
47
|
WorkloadStatusStateEnum,
|
|
48
|
+
parse_container_exit,
|
|
48
49
|
)
|
|
49
50
|
from .__utils__ import (
|
|
50
51
|
_MiB,
|
|
@@ -279,6 +280,12 @@ class DockerWorkloadStatus(WorkloadStatus):
|
|
|
279
280
|
self.executable.append(op)
|
|
280
281
|
self.loggable.append(op)
|
|
281
282
|
|
|
283
|
+
exit_ = parse_container_exit(c, _LABEL_COMPONENT_NAME)
|
|
284
|
+
if exit_ is not None:
|
|
285
|
+
self.exits.append(exit_)
|
|
286
|
+
if exit_.reason and not self.state_message:
|
|
287
|
+
self.state_message = exit_.message or exit_.reason
|
|
288
|
+
|
|
282
289
|
self.state = self.parse_state(d_containers)
|
|
283
290
|
|
|
284
291
|
|
|
@@ -1111,6 +1118,19 @@ class DockerDeployer(EndoscopicDeployer):
|
|
|
1111
1118
|
)
|
|
1112
1119
|
create_options["environment"].update(b_vs)
|
|
1113
1120
|
|
|
1121
|
+
# If requesting all devices or privileged,
|
|
1122
|
+
# the container sees every device of the host,
|
|
1123
|
+
# so pin the device ordering to keep its numbering
|
|
1124
|
+
# aligned with the detection.
|
|
1125
|
+
if r_v == "all" or privileged:
|
|
1126
|
+
o_vs = self.map_visible_devices_ordering(runtime_envs)
|
|
1127
|
+
# Take the ordering as default,
|
|
1128
|
+
# never overwrite the one declared by the container.
|
|
1129
|
+
create_options["environment"] = {
|
|
1130
|
+
**o_vs,
|
|
1131
|
+
**create_options["environment"],
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1114
1134
|
# Configure affinity if applicable.
|
|
1115
1135
|
create_options.update(
|
|
1116
1136
|
self.map_visible_devices_affinities(
|