From d812916896f38890c90bd165f2fc4e1d2a36c7a4 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Tue, 3 Nov 2026 05:24:30 +0300 Subject: [PATCH] feat(platform): add gpu.vgpu, the root tenant's vGPU entitlement Every tenant's vGPU entitlement needs its parent's, so the chain needs a start the hoster controls. gpu.vgpu is it: the platform passes it to cozystack-basics as _cluster.gpu-vgpu, which renders the root tenant. The key is written only when on, since _cluster reaches every tenant's values and an always-present key would upgrade every release. The flag feeds only the entitlement, never the KubeVirt or GPU Operator packages. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin --- packages/core/platform/templates/apps.yaml | 6 +++ .../tests/apps_gpu_vgpu_wiring_test.yaml | 42 +++++++++++++++ .../bundles_gpu_kubevirt_wiring_test.yaml | 53 +++++++++++++++++++ packages/core/platform/values.yaml | 4 ++ 4 files changed, 105 insertions(+) create mode 100644 packages/core/platform/tests/apps_gpu_vgpu_wiring_test.yaml diff --git a/packages/core/platform/templates/apps.yaml b/packages/core/platform/templates/apps.yaml index 030cfe8b2..a3ae0e802 100644 --- a/packages/core/platform/templates/apps.yaml +++ b/packages/core/platform/templates/apps.yaml @@ -253,6 +253,12 @@ stringData: null/omitted in custom values. Missing key -> the true default, matching the chart values.yaml. */}} monitoring-enabled: {{ dig "rootEnabled" true (.Values.monitoring | default dict) | quote }} + {{- /* The root tenant's vGPU entitlement, read by cozystack-basics. + Only written when on: every release in every tenant reads this + Secret, and a key appearing would upgrade all of them. */}} + {{- if eq (printf "%v" ((.Values.gpu).vgpu | default false)) "true" }} + gpu-vgpu: "true" + {{- end }} {{- /* The rate each shared-central tracing tenant's collector holds it to. Only written when set: every release in every tenant reads this Secret, and a key appearing would upgrade all of them. */}} diff --git a/packages/core/platform/tests/apps_gpu_vgpu_wiring_test.yaml b/packages/core/platform/tests/apps_gpu_vgpu_wiring_test.yaml new file mode 100644 index 000000000..f7b7712af --- /dev/null +++ b/packages/core/platform/tests/apps_gpu_vgpu_wiring_test.yaml @@ -0,0 +1,42 @@ +suite: apps.yaml gpu.vgpu → _cluster wiring +templates: + - templates/apps.yaml +release: + name: cozy-platform + namespace: cozy-system + +# gpu.vgpu entitles the root tenant to vGPU, and every child's entitlement +# needs its parent's. cozystack-basics renders the root tenant from +# _cluster.gpu-vgpu. The key is written only when on: _cluster is copied into +# every tenant's cozystack-values, so a key that is always present would +# upgrade every release in every tenant. +tests: + - it: writes gpu-vgpu when gpu.vgpu is on + set: + gpu.vgpu: true + asserts: + - matchRegex: + path: stringData["values.yaml"] + pattern: '(?m)^_cluster:\n( .*\n)* gpu-vgpu: "true"$' + + - it: leaves gpu-vgpu out by default + asserts: + - notMatchRegex: + path: stringData["values.yaml"] + pattern: gpu-vgpu + + - it: leaves gpu-vgpu out for a quoted "false" + set: + gpu.vgpu: "false" + asserts: + - notMatchRegex: + path: stringData["values.yaml"] + pattern: gpu-vgpu + + - it: does not fail on a null gpu block + set: + gpu: null + asserts: + - notMatchRegex: + path: stringData["values.yaml"] + pattern: gpu-vgpu diff --git a/packages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml b/packages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml index 997f8c50d..066677a7b 100644 --- a/packages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml +++ b/packages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml @@ -949,3 +949,56 @@ tests: - contains: path: spec.components.kubevirt.values.mediatedDevicesConfiguration.mediatedDeviceTypes content: nvidia-473 + + # gpu.vgpu feeds the tenant entitlement, not KubeVirt or the GPU Operator. + - it: keeps gpu.vgpu out of the kubevirt component + set: + bundles: + system: + enabled: true + variant: isp-full + iaas: + enabled: true + enabledPackages: + - cozystack.gpu-operator + gpu: + vgpu: true + documentSelector: + path: metadata.name + value: cozystack.kubevirt + asserts: + - equal: + path: spec.components.kubevirt.values.extraFeatureGates + value: + - HostDevices + - contains: + path: spec.components.kubevirt.values.permittedHostDevices.pciHostDevices + content: + pciVendorSelector: "10DE:2335" + resourceName: nvidia.com/GH100_H200_SXM_141GB + externalResourceProvider: true + - notExists: + path: spec.components.kubevirt.values.vgpu + + - it: keeps gpu.vgpu out of the gpu-operator Package under vgpu + set: + bundles: + system: + enabled: true + variant: isp-full + iaas: + enabled: true + gpuOperatorVariant: vgpu + enabledPackages: + - cozystack.gpu-operator + gpu: + vgpu: true + documentSelector: + path: metadata.name + value: cozystack.gpu-operator + asserts: + - equal: + path: spec.variant + value: vgpu + - notExists: + path: spec.components diff --git a/packages/core/platform/values.yaml b/packages/core/platform/values.yaml index d60effbc8..41b3e54a1 100644 --- a/packages/core/platform/values.yaml +++ b/packages/core/platform/values.yaml @@ -917,6 +917,10 @@ gpu: # missing entries). vgpuDeviceManager: enabled: false + # Entitle the root tenant to vGPU classes. Every other tenant is entitled + # only when its own Tenant sets gpu.vgpu and its parent is entitled, so + # vGPU reaches no tenant until this is on. + vgpu: false # VM import from external virtualization platforms (opt-in; see the iaas bundle). vmImport: