Repository navigation
feat(platform): auto-wire KubeVirt permittedHostDevices and HostDevices feature gate when gpu-operator is enabled - #2768
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (11)
✅ Files skipped from review due to trivial changes (3)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughPlatform auto-wires KubeVirt feature gates and permittedHostDevices for NVIDIA passthrough and vGPU modes when ChangesGPU operator and KubeVirt integration
Sequence DiagramsequenceDiagram
participant Platform
participant IaaSBundle
participant KubeVirtChart
participant GPUOperator
participant KubeVirt
Platform->>IaaSBundle: bundles.iaas.gpuOperatorVariant + gpu.* values
IaaSBundle->>IaaSBundle: validate variant and select defaults
IaaSBundle->>IaaSBundle: merge or replace user device lists
alt Passthrough
IaaSBundle->>KubeVirtChart: kubevirtValues with extraFeatureGates and pciHostDevices
else vGPU
IaaSBundle->>KubeVirtChart: kubevirtValues with extraFeatureGates and mediatedDevicesConfiguration
IaaSBundle->>GPUOperator: forward vgpuManager and vgpuDeviceManager settings
end
KubeVirtChart->>KubeVirt: Rendered CR with featureGates and permittedHostDevices
GPUOperator->>KubeVirt: publishes device resources via sandbox-device-plugin
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
4d1bd0c to
796f362
Compare
5286e0b to
ae699f9
Compare
|
Actionable comments posted: 0 |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request automates the KubeVirt configuration required for GPU support in Cozystack. By dynamically injecting the necessary feature gates and device definitions into the KubeVirt CR based on the enabled GPU operator variant, it eliminates the need for manual post-deployment patching. The changes also introduce configurable defaults for common NVIDIA hardware and provide escape hatches for cluster-specific overrides. Highlights
New Features🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request implements GPU host-device wiring for VirtualMachine workloads in Cozystack, enabling automatic injection of PCI passthrough and mediated vGPU configurations into the KubeVirt CR when the gpu-operator package is enabled. It introduces default configuration files for both GPU variants, updates the iaas bundle template, and adds comprehensive unit tests. The review feedback highlights potential nil pointer dereference risks in the iaas.yaml template when accessing nested keys under .Values.gpu if they are omitted or null. It is recommended to define safe helper variables at the top of the template to handle these values safely.
| {{- $kubevirtValues := dict -}} | ||
| {{- if .Values.resources.cpuAllocationRatio -}} | ||
| {{- $_ := set $kubevirtComponents "kubevirt" (dict "values" (dict "cpuAllocationRatio" (.Values.resources.cpuAllocationRatio | int))) -}} | ||
| {{- $_ := set $kubevirtValues "cpuAllocationRatio" (.Values.resources.cpuAllocationRatio | int) -}} | ||
| {{- end -}} |
There was a problem hiding this comment.
To prevent potential nil pointer dereference errors when .Values.gpu or its nested keys are omitted or set to null in user-supplied values, we should define safe helper variables at the top of the template.
In Go templates, expressions like (.Values.gpu).permittedHostDevices are evaluated before the default function is called. If .Values.gpu is nil, evaluating any field on it will immediately cause a template rendering error.
Defining these helper variables at the top of the file makes them safely available throughout the entire template.
{{- $kubevirtValues := dict -}}
{{- if .Values.resources.cpuAllocationRatio -}}
{{- $_ := set $kubevirtValues "cpuAllocationRatio" (.Values.resources.cpuAllocationRatio | int) -}}
{{- end -}}
{{- $gpuValues := .Values.gpu | default dict -}}
{{- $permittedHostDevices := $gpuValues.permittedHostDevices | default dict -}}
{{- $vgpuDeviceManager := $gpuValues.vgpuDeviceManager | default dict -}}
{{- $deviceManagerOn := $vgpuDeviceManager.enabled | default false -}}There was a problem hiding this comment.
The .Values.gpu accesses here are intentionally fully parenthesized, which is nil-safe. (((.Values.gpu).permittedHostDevices).pciHostDevices) yields an invalid value that default then absorbs when any hop is nil, whereas the bare .Values.gpu.permittedHostDevices.pciHostDevices panics with nil pointer evaluating interface {}.permittedHostDevices on the first nil hop. I added regression cases (gpu: null in both variants and blank sub-keys) plus a comment so the parentheses aren't flattened away; a mutation check confirms they fail the moment the parentheses are removed. The same applies to the other threads on this file (lines 41/71/121).
| {{- $userPci := default (list) (((.Values.gpu).permittedHostDevices).pciHostDevices) -}} | ||
| {{- $userMdev := default (list) (((.Values.gpu).permittedHostDevices).mediatedDevices) -}} | ||
| {{- $userMdevConfig := default (dict) (.Values.gpu).mediatedDevicesConfiguration -}} | ||
| {{- $replace := default false (.Values.gpu).replaceDefaults -}} |
There was a problem hiding this comment.
Use the safe helper variables defined at the top of the template to avoid nil pointer dereferences when accessing nested keys under .Values.gpu.
{{- $userPci := $permittedHostDevices.pciHostDevices | default list -}}
{{- $userMdev := $permittedHostDevices.mediatedDevices | default list -}}
{{- $userMdevConfig := $gpuValues.mediatedDevicesConfiguration | default dict -}}
{{- $replace := $gpuValues.replaceDefaults | default false -}}| {{- $deviceManagerOn := default false (((.Values.gpu).vgpuDeviceManager).enabled) -}} | ||
| {{- if and (not $replace) $deviceManagerOn -}} |
| {{- $vgpuMgr := default (dict) (.Values.gpu).vgpuManager -}} | ||
| {{- $imageCustomized := and (hasKey $vgpuMgr "image") (ne (default "" $vgpuMgr.image) "vgpu-manager") -}} | ||
| {{- if or $vgpuMgr.repository $vgpuMgr.version $imageCustomized $vgpuMgr.imagePullSecrets -}} | ||
| {{- $_ := set $gpuOperatorOverrides "vgpuManager" $vgpuMgr -}} | ||
| {{- end -}} | ||
| {{- if (((.Values.gpu).vgpuDeviceManager).enabled) -}} | ||
| {{- $_ := set $gpuOperatorOverrides "vgpuDeviceManager" (dict "enabled" true) -}} | ||
| {{- end -}} |
There was a problem hiding this comment.
Use the safe helper variables $gpuValues and $deviceManagerOn to prevent nil pointer dereferences when configuring the GPU Operator overrides.
{{- $vgpuMgr := $gpuValues.vgpuManager | default dict -}}
{{- $imageCustomized := and (hasKey $vgpuMgr "image") (ne (default "" $vgpuMgr.image) "vgpu-manager") -}}
{{- if or $vgpuMgr.repository $vgpuMgr.version $imageCustomized $vgpuMgr.imagePullSecrets -}}
{{- $_ := set $gpuOperatorOverrides "vgpuManager" $vgpuMgr -}}
{{- end -}}
{{- if $deviceManagerOn -}}
{{- $_ := set $gpuOperatorOverrides "vgpuDeviceManager" (dict "enabled" true) -}}
{{- end -}}
Migration note: auto-wiring silently overwrites hand-edited
|
| Card | PCI | resourceName in use | Default table | Result on upgrade |
|---|---|---|---|---|
| L40S | 10DE:26B9 |
nvidia.com/AD102GL_L40S |
same | ✅ seamless |
| A100 PCIe 80GB | 10DE:20B5 |
nvidia.com/GA100_A100_PCIE_80GB |
same | ✅ seamless |
| A100 SXM4 80GB | 10DE:20B2 |
nvidia.com/GA100_A100_SXM4_80GB |
same | ✅ seamless |
| Tesla T4 | 10DE:1EB8 |
nvidia.com/TU104GL_TESLA_T4 |
nvidia.com/TU104GL_T4 |
❌ breaks |
PCI matches for the T4, but the table renames it TU104GL_T4. After upgrade the CR permits TU104GL_T4 while the node still advertises TU104GL_TESLA_T4 — so existing T4 VMs are rejected by the admission webhook on the next restart/migration, and nothing is allocatable under the permitted name. The change is invisible until a VM reschedules.
Suggested mitigations (docs-only, no code change required):
- Add an upgrade note to the
release-noteblock and to website#556: "The platform now managesspec.configuration.permittedHostDevices. If you previously hand-edited it, move your entries into.gpu.permittedHostDevicesand verify eachresourceNameagainst what your node advertises (kubectl describe node <node> | grep nvidia.com/) before upgrading — custom names (e.g. the legacyTESLA_*slugs) are otherwise overwritten by the default table and those VMs stop scheduling." - Recommend
replaceDefaults: truewith a curated list for such fleets, rather than appending — appending a second entry for the samepciVendorSelector(defaultTU104GL_T4+ overrideTU104GL_TESLA_T4on10DE:1EB8) yields two resourceNames for one selector, which KubeVirt resolves non-deterministically.
The wiring logic itself looks correct; this is purely about making the takeover of a previously hand-managed field non-silent at upgrade.
Andrei Kvapil (kvaps)
left a comment
There was a problem hiding this comment.
Requesting changes to gate the merge on one migration-safety item — the wiring logic itself is correct and I'm happy with it.
This PR makes templates/kubevirt-cr.yaml take ownership of spec.configuration.permittedHostDevices, which until now was hand-managed by operators (kubectl edit kubevirt). On the first reconcile after upgrade, Helm overwrites those manual entries with the rendered default table. Fleets whose resourceNames diverge from the static table — the common case being the legacy NVIDIA TESLA_* naming — will have running VMs silently rejected by the admission webhook on their next restart/migration.
Concrete example and the full breakdown are in #2768 (comment) (Tesla T4: table renames 10DE:1EB8 to TU104GL_T4 while real nodes advertise TU104GL_TESLA_T4).
This needs to be resolved before merge — it doesn't have to be code. Any of:
- an explicit upgrade note in the
release-noteblock + website#556 telling operators to move hand-edited entries into.gpu.permittedHostDevicesand verify eachresourceNameagainstkubectl describe node | grep nvidia.com/before upgrading, and/or - whatever you think is the right way to make the takeover of a previously hand-managed field non-silent.
Once there's a clear migration story for operators who already hand-edited permittedHostDevices, I'm good to approve.
ae699f9 to
883513b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/system/kubevirt/Makefile (3)
30-30: 💤 Low valueClarify the error message for missing template file.
The error message says "drop a hand-merged upstream CR there first" but could be more explicit about what "hand-merged" means and where to source the upstream CR from.
📝 Suggested improvement
- `@test` -f templates/kubevirt-cr.yaml || { echo "ERROR: templates/kubevirt-cr.yaml not found — drop a hand-merged upstream CR there first" >&2; exit 1; } + `@test` -f templates/kubevirt-cr.yaml || { echo "ERROR: templates/kubevirt-cr.yaml not found — manually merge upstream KubeVirt CR changes into that file first (see comments above for workflow)" >&2; exit 1; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/system/kubevirt/Makefile` at line 30, Update the error message in the Makefile check for templates/kubevirt-cr.yaml so it explicitly tells the user what "hand-merged upstream CR" means and where to get it; change the echo in the test that checks templates/kubevirt-cr.yaml to say something like "ERROR: templates/kubevirt-cr.yaml not found — please place the upstream kubevirt CR here (manually merged from the upstream release CR, e.g. fetch from the kubevirt repository or the vendor's release tarball)". Refer to the test command that checks for templates/kubevirt-cr.yaml in the Makefile and ensure the message gives clear sourcing guidance and action to perform.
28-28: 💤 Low valueProvide concrete macOS sed guidance.
The comment mentions running under a Linux container or using
gsedon macOS, but doesn't provide the specific command. Since GNU sed is a hard requirement (BSD sed's-isyntax and behavior differs), adding a concrete example would help macOS developers.📝 Suggested improvement
-# GNU sed is required — on macOS run under a Linux container or via gsed. +# GNU sed is required — on macOS install via `brew install gnu-sed` and use `gmake SED=gsed update` or run in a Linux container.Note: This assumes the Makefile could be extended to support a
SEDvariable, or alternatively just document thegsedcommand directly if the pattern is simple enough for users to adapt manually.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/system/kubevirt/Makefile` at line 28, Update the Makefile comment to give concrete macOS guidance: mention installing GNU sed (e.g., via Homebrew as "brew install gnu-sed") and show how to use it by either exporting/setting a SED variable (SED=gsed) or invoking gsed explicitly in the Makefile targets that rely on GNU sed; reference adding a SED variable and replacing plain "sed" calls with "$(SED)" (or documenting to call "gsed -i" instead) so macOS users have an exact command to run.
33-36: ⚡ Quick winConsider documenting sed pattern assumptions.
The sed patterns rely on specific anchors (
developerConfiguration:,- VMExport,evictionStrategy:) that could change in future upstream KubeVirt releases. While the sanity checks at lines 41-44 will catch missing anchors, documenting the exact anchor requirements in the comments would help future maintainers understand what to verify during manual upstream merges.📋 Suggested documentation addition
Add after line 26:
+# 4. When hand-merging, preserve these exact anchor lines (required by sed): +# - 'namespace: kubevirt' → patched to 'namespace: cozy-kubevirt' +# - ' developerConfiguration:' → cpuAllocationRatio inserted after +# - ' - VMExport' → extraFeatureGates appended after +# - ' evictionStrategy:' → permittedHostDevices/mediatedDevices inserted before # # GNU sed is required — on macOS run under a Linux container or via gsed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/system/kubevirt/Makefile` around lines 33 - 36, Add a short comment above the sed/grep block that documents the expected anchors and context in templates/kubevirt-cr.yaml (specifically the presence of "developerConfiguration:", the list item "- VMExport", and the "evictionStrategy:" field) and explain that the sed commands rely on those exact anchors and indentation; mention that these anchors must be verified when merging upstream and reference the sanity checks that follow the block so maintainers know where to look if anchors change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/system/kubevirt/Makefile`:
- Around line 41-44: The grep sanity checks in the Makefile are emitting
misleading messages (they search for template directives like '{{- if
.Values.cpuAllocationRatio }}' but error text mentions anchors such as
'developerConfiguration:'), so update each failing-branch message to reference
the actual template directive being checked (e.g., '{{- if
.Values.cpuAllocationRatio }}', '{{- range .Values.extraFeatureGates }}', '{{-
with .Values.permittedHostDevices }}', '{{- with
.Values.mediatedDevicesConfiguration }}') and/or state "template directive not
found" so the error accurately reflects a missing template insertion rather than
a missing anchor; modify the error strings in the lines containing the grep
calls to include the exact pattern being searched and a brief context like
"template directive '...pattern...' not found in templates/kubevirt-cr.yaml".
---
Nitpick comments:
In `@packages/system/kubevirt/Makefile`:
- Line 30: Update the error message in the Makefile check for
templates/kubevirt-cr.yaml so it explicitly tells the user what "hand-merged
upstream CR" means and where to get it; change the echo in the test that checks
templates/kubevirt-cr.yaml to say something like "ERROR:
templates/kubevirt-cr.yaml not found — please place the upstream kubevirt CR
here (manually merged from the upstream release CR, e.g. fetch from the kubevirt
repository or the vendor's release tarball)". Refer to the test command that
checks for templates/kubevirt-cr.yaml in the Makefile and ensure the message
gives clear sourcing guidance and action to perform.
- Line 28: Update the Makefile comment to give concrete macOS guidance: mention
installing GNU sed (e.g., via Homebrew as "brew install gnu-sed") and show how
to use it by either exporting/setting a SED variable (SED=gsed) or invoking gsed
explicitly in the Makefile targets that rely on GNU sed; reference adding a SED
variable and replacing plain "sed" calls with "$(SED)" (or documenting to call
"gsed -i" instead) so macOS users have an exact command to run.
- Around line 33-36: Add a short comment above the sed/grep block that documents
the expected anchors and context in templates/kubevirt-cr.yaml (specifically the
presence of "developerConfiguration:", the list item "- VMExport", and the
"evictionStrategy:" field) and explain that the sed commands rely on those exact
anchors and indentation; mention that these anchors must be verified when
merging upstream and reference the sanity checks that follow the block so
maintainers know where to look if anchors change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e7d9e363-d687-4997-b604-65f7b57e7428
📒 Files selected for processing (10)
docs/gpu-vgpu.mdpackages/core/platform/files/gpu-passthrough-defaults.yamlpackages/core/platform/files/gpu-vgpu-defaults.yamlpackages/core/platform/templates/bundles/iaas.yamlpackages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yamlpackages/core/platform/values.yamlpackages/system/kubevirt/Makefilepackages/system/kubevirt/templates/kubevirt-cr.yamlpackages/system/kubevirt/tests/kubevirt_cr_test.yamlpackages/system/kubevirt/values.yaml
✅ Files skipped from review due to trivial changes (1)
- docs/gpu-vgpu.md
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/core/platform/files/gpu-passthrough-defaults.yaml
- packages/system/kubevirt/values.yaml
- packages/system/kubevirt/templates/kubevirt-cr.yaml
- packages/core/platform/values.yaml
- packages/system/kubevirt/tests/kubevirt_cr_test.yaml
- packages/core/platform/files/gpu-vgpu-defaults.yaml
- packages/core/platform/templates/bundles/iaas.yaml
883513b to
bf8cda4
Compare
…-wires permittedHostDevices Step 2 of the GPU Passthrough guide instructed operators to `kubectl edit kubevirt -n cozy-kubevirt` and hand-paste a permittedHostDevices.pciHostDevices block. cozystack/cozystack#2768 removes the need for that step: when cozystack.gpu-operator is in bundles.enabledPackages, the platform now mirrors the chosen GPU variant into the KubeVirt CR automatically — appending HostDevices to the feature-gate list and rendering a starter NVIDIA pciHostDevices table covering Hopper, Ada Lovelace, Ampere, Turing and Volta. The new step 2 documents the contract (what the platform auto-injects and why), the verification recipe, the escape hatch via .gpu.permittedHostDevices / .gpu.replaceDefaults, and the manual Package-CR override path used by operators who need overrides the bundle does not expose (driver settings, custom node selectors, validator / dcgmExporter tweaks) — in that flow they also hand-craft the matching cozystack.kubevirt Package CR. Only next/virtualization/gpu.md is updated; v1.4 and earlier describe releases that still require the manual patch and stay as-is. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
|
Andrei Kvapil (@kvaps) addressed the migration-safety ask. The |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/system/kubevirt/Makefile`:
- Line 36: The current Makefile sed insertion uses a single guard checking for
{{- with .Values.permittedHostDevices }} before inserting both the
permittedHostDevices and mediatedDevicesConfiguration blocks, so if
mediatedDevicesConfiguration is absent it won't be reinserted; change this to
two independent idempotent checks: one that greps for '{{- with
.Values.permittedHostDevices }}' and only inserts the permittedHostDevices block
into templates/kubevirt-cr.yaml, and a second that greps for '{{- with
.Values.mediatedDevicesConfiguration }}' and only inserts the
mediatedDevicesConfiguration block, keeping the same insertion point (before the
evictionStrategy line) and preserving indentation and toYaml | nindent 6
formatting so both checks are independent and safe to reapply.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f804232a-32d9-422c-adde-28c26c1e36d2
📒 Files selected for processing (10)
docs/gpu-vgpu.mdpackages/core/platform/files/gpu-passthrough-defaults.yamlpackages/core/platform/files/gpu-vgpu-defaults.yamlpackages/core/platform/templates/bundles/iaas.yamlpackages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yamlpackages/core/platform/values.yamlpackages/system/kubevirt/Makefilepackages/system/kubevirt/templates/kubevirt-cr.yamlpackages/system/kubevirt/tests/kubevirt_cr_test.yamlpackages/system/kubevirt/values.yaml
🚧 Files skipped from review as they are similar to previous changes (7)
- packages/core/platform/files/gpu-passthrough-defaults.yaml
- packages/core/platform/files/gpu-vgpu-defaults.yaml
- docs/gpu-vgpu.md
- packages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml
- packages/system/kubevirt/templates/kubevirt-cr.yaml
- packages/system/kubevirt/values.yaml
- packages/core/platform/templates/bundles/iaas.yaml
|
removing from a roadmap as not roadmap related content |
The KubeVirt CR's developerConfiguration.featureGates list, the
permittedHostDevices block, and mediatedDevicesConfiguration are now
driven by chart values:
- extraFeatureGates is appended after the static default set so
HostDevices (or any other future gate) can be enabled without
forking the template.
- permittedHostDevices is rendered verbatim when set, allowing the
pciHostDevices (passthrough) and mediatedDevices (vGPU) shapes the
KubeVirt admission webhook requires for VMs that reference a GPU
by resourceName.
- mediatedDevicesConfiguration is rendered verbatim when set,
carrying mediatedDeviceTypes / nodeMediatedDeviceTypes for the
vGPU profile auto-creation loop.
Defaults stay empty so the rendered CR is byte-identical to the
previous template when no overrides are supplied.
The Makefile's update target re-applies the four sed transforms
in-place on templates/kubevirt-cr.yaml — it does not download anything
from upstream KubeVirt because the published CR is a near-empty stub
and would clobber the hand-curated cozystack defaults. To refresh from
a newer upstream release the operator hand-merges the new fields into
the in-tree template, then runs `make update` to re-assert the four
cozystack parameterization patches; grep sanity-checks at the end of
the target fail loudly if any anchor (developerConfiguration,
- VMExport, evictionStrategy) gets dropped during the hand-merge.
Companion helm-unittest coverage pins the default render and the
three populated shapes.
Signed-off-by: Aleksei Sviridkin <[email protected]>
…tor is enabled
When cozystack.gpu-operator is in bundles.enabledPackages, the platform
now mirrors the chosen GPU variant into the KubeVirt CR — the HostDevices
feature gate is appended to developerConfiguration.featureGates, and a
starter permittedHostDevices block is filled from a per-variant defaults
table. Without this, a passthrough-variant GPU shows up under
.status.allocatable on the node but the KubeVirt admission webhook
rejects every VM that references it as a hostDevices.deviceName.
Two defaults tables ship under packages/core/platform/files/:
- gpu-passthrough-defaults.yaml covers Hopper (H100/H200), Ada
Lovelace (L4/L40/L40S), Ampere (A100 PCIe/SXM, A40, A30, A10),
Turing (T4), Volta (V100/V100S). PCI vendor:device pairs are
stable; resourceName slugs mirror nvidia-sandbox-device-plugin's
<arch>_<model>_<form>_<mem> convention. externalResourceProvider
is set on every entry because the resources are advertised by
the sandbox-device-plugin DaemonSet, not by KubeVirt itself.
- gpu-vgpu-defaults.yaml covers the Pascal-Ampere mdev profile
range the upstream vgpu-device-manager walks /sys/class/mdev_bus/
for. Ada Lovelace and Blackwell SR-IOV vGPU is out of scope for
the chart's default list (NVIDIA driver path differs) and is
expected to be advertised via the user-override hook below.
bundles.iaas.gpuOperatorVariant picks which table applies (default =
passthrough, vgpu = mediated). The same variant flows through to the
gpu-operator Package CR, replacing the previous always-default call.
Operators extend or replace the defaults via .gpu in platform values:
gpu:
replaceDefaults: false
permittedHostDevices:
pciHostDevices: [...]
mediatedDevices: [...]
mediatedDevicesConfiguration: {...}
replaceDefaults: false (the default) appends the user list to the
NVIDIA table; true drops the table entirely for clusters with only
non-NVIDIA accelerators or a strict allowlist requirement.
Companion helm-unittest suite covers the eight branches: no gpu
package emits no extras; gpu-operator at default variant emits the
HostDevices gate plus pciHostDevices; vgpu variant emits the
HostDevices gate plus mediatedDevices and mediatedDevicesConfiguration;
user overrides append by default; replaceDefaults wipes; unknown
variant fails fast.
Signed-off-by: Aleksei Sviridkin <[email protected]>
The platform now wires permittedHostDevices and the HostDevices feature gate into the KubeVirt CR automatically whenever cozystack.gpu-operator is in bundles.enabledPackages. The KubeVirt configuration section now describes the auto-wiring contract, the per-variant defaults, the .gpu.permittedHostDevices / .gpu.replaceDefaults escape hatches, and calls out the sandbox-device-plugin resourceName slug convention so operators know where to look when a node's allocatable name does not match the platform default. Signed-off-by: Aleksei Sviridkin <[email protected]>
The .Values.gpu accesses in the iaas bundle are fully parenthesized
((( .Values.gpu ).x).y) so the field walk stays nil-safe when an operator
nulls the whole gpu block or leaves a sub-key blank (an empty YAML key
parses to null, which Helm then drops from .Values). A bare dotted walk
would panic with "nil pointer evaluating interface {}.<field>" on the
first nil hop.
Add regression cases covering gpu: null in both passthrough and vgpu
variants plus blank sub-keys, and a comment warning against flattening
the parenthesized form. A mutation check confirms the cases fail with the
nil-pointer panic the moment the parentheses are removed.
Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
The update target gated the insertion of both the permittedHostDevices and mediatedDevicesConfiguration directives behind a single `grep permittedHostDevices` guard. A hand-merge from a newer upstream KubeVirt CR that dropped only mediatedDevicesConfiguration left permittedHostDevices in place, so the guard skipped the combined sed and mediatedDevicesConfiguration was never reinserted — then the sanity-check tail aborted the target with a non-zero exit instead of self-healing. Split the two directives into independent guarded inserts so each self-heals on its own. Reword the sanity-check failures to name the directive that failed to land and the anchor its insert keys off, instead of implying the anchor itself is missing. Add a shell regression test that strips one directive at a time and asserts `make update` restores it without duplicating the other; the update target gains a CR_FILE override so the test can drive it against a throwaway copy. Wired into the package test target and guarded to skip on BSD sed. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
…the plugin advertises The auto-injected permittedHostDevices only works if each resourceName equals what nvidia-sandbox-device-plugin advertises on the node; otherwise the admission webhook rejects the VM — the very manual step this bundle removes. Several defaults did not match the slug the plugin (nvcr.io/nvidia/kubevirt-gpu-device-plugin) derives from the PCI-IDs database name, which uppercases the name and keeps the die suffix, the Tesla brand and the form-factor/memory tokens: 10DE:1EB8 TU104GL_T4 -> TU104GL_TESLA_T4 10DE:20B7 GA100_A30 -> GA100GL_A30_PCIE 10DE:2331 GH100_H100_PCIE_80GB-> GH100_H100_PCIE 10DE:2321 GH100_H100_NVL_94GB -> GH100_H100L_94GB 10DE:1DB1/1DB4/1DF6 + new 1DB5 -> GV100GL_TESLA_V100_* family Device 10DE:1DB1 was also mislabelled: it is the SXM2 16GB part, not the 32GB one — the 32GB SXM2 V100 is a distinct device (10DE:1DB5) that was missing entirely. Relabel 1DB1 as 16GB and add 1DB5. Restate the header comment as the actual generation rule and pin the corrected slugs (T4, A30, both V100 SXM2 parts) with a regression test that also asserts the tidy/short forms never reappear. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
The vgpu defaults shipped a mediatedDevicesConfiguration block whose mediatedDeviceTypes were hardcoded nvidia-NNN ids. Those ids are not stable identifiers — they are the per-(SKU, driver) indices under which a host enumerates mdev types in /sys/.../mdev_supported_types/, so the same profile gets a different number on a different card or driver branch. Auto-injecting them made KubeVirt try to create mdev types that usually do not exist on the operator's nodes, and duplicated work the GPU Operator's vGPU Device Manager already does. Delegate mdev creation to the vGPU Device Manager, which is name-based and stable, and keep only the name-based permittedHostDevices.mediatedDevices exposure list (mdevNameSelector) in the defaults. KubeVirt-driven creation stays available through the .gpu.mediatedDevicesConfiguration override for operators who supply host-verified type ids; document the lookup recipe. Update the bundle wiring, the gpu/vgpu values comments, the vGPU guide and the tests accordingly (the default vgpu path now emits no mediatedDevicesConfiguration; the override path is covered explicitly). Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
bf8cda4 to
117d317
Compare
|
Andrei Kvapil (@kvaps) the migration-safety ask is covered — the release-note upgrade block plus the website migration section route operators through I verified the Also addressed while here:
Re-requesting review. |
Andrei Kvapil (kvaps)
left a comment
There was a problem hiding this comment.
Re-review — my prior blocker is resolved. The passthrough default now uses the correct resourceName slug (TU104GL_TESLA_T4, not the _T4 I flagged), the release-note carries an explicit upgrade note that the iaas bundle now owns permittedHostDevices (move custom entries into .gpu.permittedHostDevices or set .gpu.replaceDefaults: true, and verify each resourceName against kubectl describe node | grep nvidia.com/ before upgrading), and the replaceDefaults/permittedHostDevices escape hatch is implemented and test-pinned. Nil-safety is real and covered (null/empty-gpu cases). No values.schema.json drift (platform chart has none). CI green.
LGTM.
…-wires permittedHostDevices Step 2 of the GPU Passthrough guide instructed operators to `kubectl edit kubevirt -n cozy-kubevirt` and hand-paste a permittedHostDevices.pciHostDevices block. cozystack/cozystack#2768 removes the need for that step: when cozystack.gpu-operator is in bundles.enabledPackages, the platform now mirrors the chosen GPU variant into the KubeVirt CR automatically — appending HostDevices to the feature-gate list and rendering a starter NVIDIA pciHostDevices table covering Hopper, Ada Lovelace, Ampere, Turing and Volta. The new step 2 documents the contract (what the platform auto-injects and why), the verification recipe, the escape hatch via .gpu.permittedHostDevices / .gpu.replaceDefaults, and the manual Package-CR override path used by operators who need overrides the bundle does not expose (driver settings, custom node selectors, validator / dcgmExporter tweaks) — in that flow they also hand-craft the matching cozystack.kubevirt Package CR. Only next/virtualization/gpu.md is updated; v1.4 and earlier describe releases that still require the manual patch and stay as-is. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
…-wires permittedHostDevices Step 2 of the GPU Passthrough guide instructed operators to `kubectl edit kubevirt -n cozy-kubevirt` and hand-paste a permittedHostDevices.pciHostDevices block. cozystack/cozystack#2768 removes the need for that step: when cozystack.gpu-operator is in bundles.enabledPackages, the platform now mirrors the chosen GPU variant into the KubeVirt CR automatically — appending HostDevices to the feature-gate list and rendering a starter NVIDIA pciHostDevices table covering Hopper, Ada Lovelace, Ampere, Turing and Volta. The new step 2 documents the contract (what the platform auto-injects and why), the verification recipe, the escape hatch via .gpu.permittedHostDevices / .gpu.replaceDefaults, and the manual Package-CR override path used by operators who need overrides the bundle does not expose (driver settings, custom node selectors, validator / dcgmExporter tweaks) — in that flow they also hand-craft the matching cozystack.kubevirt Package CR. Only next/virtualization/gpu.md is updated; v1.4 and earlier describe releases that still require the manual patch and stay as-is. Assisted-By: Claude <[email protected]> Signed-off-by: Aleksei Sviridkin <[email protected]>
…-wires permittedHostDevices (#556) Companion to [cozystack/cozystack#2768](cozystack/cozystack#2768). Rewrites step 2 of the GPU Passthrough guide. Until now the page instructed operators to run `kubectl edit kubevirt -n cozy-kubevirt` and hand-paste a `permittedHostDevices.pciHostDevices` block — that is the friction that ticket #2765 asked the platform to remove. With cozystack/cozystack#2768 landed, the bundle mirrors the chosen GPU variant into the KubeVirt CR automatically: `HostDevices` is appended to the feature-gate list and a starter NVIDIA `pciHostDevices` table (Hopper, Ada Lovelace, Ampere, Turing, Volta) is rendered alongside the operator's `.gpu.permittedHostDevices` extensions. The new step 2 documents: - The contract — what the platform auto-injects and why (`HostDevices` gate, NVIDIA default table, `externalResourceProvider: true` semantics). - How to verify (`kubectl -n cozy-kubevirt get kubevirt kubevirt -o yaml | yq ...`). - The escape hatch — `gpu.replaceDefaults`, `gpu.permittedHostDevices.pciHostDevices`, plus the consequence of `replaceDefaults: true` with an empty list (no admittable GPU VMs). - The manual Package-CR override path — when an operator hand-crafts `cozystack.gpu-operator` outside the bundle for advanced overrides, they also hand-craft `cozystack.kubevirt` with the matching `extraFeatureGates` / `permittedHostDevices`. The manual override takes precedence over the bundle render. Only `next/virtualization/gpu.md` is touched. The released doc versions (`v1.4` and earlier) describe earlier Cozystack releases that still require the manual `kubectl edit`, and stay as-is. ### Release note ```release-note docs(gpu): the GPU Passthrough guide no longer instructs operators to manually patch the KubeVirt CR — Cozystack now auto-wires the HostDevices feature gate and a starter NVIDIA permittedHostDevices table whenever cozystack.gpu-operator is enabled in bundles.enabledPackages. Operators extend or replace the defaults via .gpu.permittedHostDevices and .gpu.replaceDefaults. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated GPU virtualization guide to remove a manual edit step and explain automated configuration when the GPU package is enabled. * Added verification commands to inspect rendered GPU settings and detailed how to extend or fully replace NVIDIA defaults via package values. * Included upgrade guidance for prior manual setups and documented a manual override path for non-bundled deployments. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes #2765.
What this PR does
Makes the passthrough and vGPU variants of
cozystack.gpu-operatorproduce a KubeVirt CR that is immediately usable, without an out-of-bandkubectl patch. Today the gpu-operator stack reports green,nvidia.com/<model>shows up under node.status.allocatable, but everyVirtualMachinereferencing the resource viadomain.devices.hostDevicesis rejected by the admission webhook becauseHostDevicesis not indeveloperConfiguration.featureGatesand the resource is not listed underpermittedHostDevices. That manual reconciliation is now driven by the platform.The change has three parts.
packages/system/kubevirtnow parameterizes the KubeVirt CR template.developerConfiguration.featureGateskeeps its existing static defaults and appends.Values.extraFeatureGates;spec.configuration.permittedHostDevicesrenders verbatim from.Values.permittedHostDeviceswhen set;spec.configuration.mediatedDevicesConfigurationdoes the same. Defaults stay empty so the rendered CR is byte-identical to the previous template when no overrides are supplied. The chart'smake updatetarget re-applies the four sed transforms after fetching the upstream CR, so refreshing the KubeVirt release version stays a single command.packages/core/platformadds two defaults tables underfiles/.gpu-passthrough-defaults.yamlcovers Hopper (H100/H200), Ada Lovelace (L4/L40/L40S), Ampere (A100 PCIe/SXM, A40, A30, A10), Turing (T4) and Volta (V100/V100S); PCI vendor:device pairs are stable,resourceNameslugs follow the<arch>_<model>_<form>_<mem>conventionnvidia-sandbox-device-plugingenerates as of v25.x, andexternalResourceProvider: trueis set everywhere because those resources are advertised by the sandbox plugin rather than KubeVirt's in-tree device plugin.gpu-vgpu-defaults.yamlcovers the Pascal–Ampere mdev profile range (A100-40C/80C, A40-24Q/48Q, A30-24C, A10-24Q, V100D-32C, T4-16Q) — the same family span the upstreamvgpu-device-managerwalks/sys/class/mdev_bus/for. Ada Lovelace and Blackwell SR-IOV vGPU is intentionally out of scope for the default table and is expected to be advertised via the user-override hook described below.templates/bundles/iaas.yamlnow selects between the two tables via a newbundles.iaas.gpuOperatorVariantknob (defaultfor passthrough,vgpufor mediated; default is passthrough). The same variant flows through to the gpu-operator Package CR, replacing the previous always-default call. When the package is enabled, the platform injectsHostDevicesintoextraFeatureGatesplus the chosen defaults intopermittedHostDevicesfor the kubevirt component's values. Operators extend or replace via top-level platform values:docs/gpu-vgpu.mdis updated to drop the manualkubectl patchstep and describe the auto-wiring contract, the per-variant defaults, the escape hatches, and the sandbox-device-pluginresourceNameslug convention so an operator whose node publishes a different name knows where to override.Test coverage
helm-unittestcovers eight branches inpackages/core/platform/tests/bundles_gpu_kubevirt_wiring_test.yaml: gpu-operator disabled emits no extras; gpu-operator enabled at default variant emits the HostDevices gate pluspciHostDevices; vgpu variant switches tomediatedDevicesplusmediatedDevicesConfiguration; user overrides append by default;replaceDefaults: truewipes the platform table; an unknown variant fails fast with a descriptive error.packages/system/kubevirt/tests/kubevirt_cr_test.yamlpins the empty-values render and the three populated shapes at the CR template level.make helm-unit-testspasses locally on the full repo.Release note
Summary by CodeRabbit
New Features
Documentation
Tests
Chores