Skip to content

fix(nvidia): validate gpumem-percentage range to prevent silent unschedulability - #1997

Merged
hami-robot[bot] merged 3 commits into
Project-HAMi:masterfrom
saiyam1814:fix/gpumem-percentage-validation-1781
Jul 2, 2026
Merged

fix(nvidia): validate gpumem-percentage range to prevent silent unschedulability#1997
hami-robot[bot] merged 3 commits into
Project-HAMi:masterfrom
saiyam1814:fix/gpumem-percentage-validation-1781

Conversation

@saiyam1814

@saiyam1814 saiyam1814 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind bug

What this PR does / why we need it:

nvidia.com/gpumem-percentage is never range-validated. A pod requesting a value > 100 passes admission, but the scheduler then computes memreq = Totalmem * pct / 100 — larger than any card — so the pod stays Pending forever with a misleading CardInsufficientMemory reason. A value of exactly 101 silently collides with the internal "percentage not set" sentinel in GenerateResourceRequests.

This PR:

  • Rejects percentages outside [0, 100] at admission time in MutateAdmission with a clear error message (same pattern as Ascend's validation).
  • Clamps out-of-range percentages to 100 in GenerateResourceRequests (validated on the raw int64 before the int32 cast to avoid wraparound), mirroring the existing Coresreq > 100 clamp in Fit. This also covers init containers and pods that bypass the webhook — admission-time validation for init containers was dropped per review, as it needs more careful design.
  • Adds regression tests for both paths, including an int32-overflow case.

Valid 0–100 requests are unchanged; only invalid specs (negative, 101, >100) change behavior — from silent forever-Pending to an immediate, actionable rejection.

Which issue(s) this PR fixes:
Fixes #1781

Special notes for your reviewer:

The scenario as originally reported (missing gpumem on v2.6.14) is largely resolved on current releases: whole-card default exists since v2.3.2 and human-readable filter reasons landed in v2.7.0 (#1097). This PR closes the remaining gap that still reproduces the silent-unschedulability on master: out-of-range percentage values.

Known pre-existing limitation (not introduced here): pods bypassing the webhook don't get the admission-time exclusive-core mutation from defaultExclusiveCoreIfNeeded; the clamp keeps scheduling sane for them regardless.

Does this PR introduce a user-facing change?:

Pods requesting an out-of-range nvidia.com/gpumem-percentage (outside 0-100) are now rejected at admission with a clear error message instead of remaining permanently unschedulable.

…edulability

When a pod requests an out-of-range memory percentage (e.g.
nvidia.com/gpumem-percentage > 100), the scheduler computed a memory
request larger than any card's total memory, leaving the pod Pending
forever with a misleading CardInsufficientMemory reason. A value of
exactly 101 collided with the internal 'percentage not set' sentinel.

- Reject percentages outside [0, 100] at admission time in
  MutateAdmission with a human-readable error message. Init
  containers are validated as well: they are scheduled via
  Resourcereqs but never passed to MutateAdmission by the webhook.
- Clamp out-of-range percentages to 100 in GenerateResourceRequests
  as defense-in-depth for pods that bypass the admission webhook,
  mirroring the existing Coresreq > 100 clamp in Fit.

Fixes Project-HAMi#1781

Signed-off-by: Saiyam Pathak <saiyam911@gmail.com>
@hami-robot hami-robot Bot added kind/bug Something isn't working dco-signoff: yes labels Jul 2, 2026
@hami-robot
hami-robot Bot requested review from FouoF and archlitchi July 2, 2026 07:02
@hami-robot hami-robot Bot added the size/L label Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Validates NVIDIA memory-percentage values during admission and clamps out-of-range percentages to 100 during resource request generation. Tests cover accepted, rejected, and clamped inputs.

Changes

Memory Percentage Validation and Clamping

Layer / File(s) Summary
Admission-time memory percentage validation
pkg/device/nvidia/device.go, pkg/device/nvidia/device_test.go
MutateAdmission now rejects ResourceMemoryPercentageName values outside [0,100] through a new helper, with unit tests covering accepted and rejected values.
Resource request clamping
pkg/device/nvidia/device.go, pkg/device/nvidia/device_test.go
GenerateResourceRequests clamps out-of-range memory-percentage values to 100, and tests verify the clamped output for multiple invalid inputs.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit hopped by GPU land,
With percentages checked by hand.
One hundred stays, one-oh-one falls,
No sneaky overflow through the walls.
Hop, hop — the numbers now behave! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The change validates and clamps explicit gpumem-percentage values, but it does not address the linked issue's missing-gpumem path that produces MemPercentagereq:101. Handle the missing nvidia.com/gpumem case directly, either by treating it as whole-card memory or rejecting it with a clear admission error.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the main change: validating NVIDIA gpumem-percentage values to avoid silent scheduling failures.
Out of Scope Changes check ✅ Passed The diff stays focused on gpumem-percentage validation/clamping and related tests, with no unrelated functional changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces memory percentage validation for GPU devices in MutateAdmission (for both standard and init containers) and clamps out-of-range memory percentage requests to 100 in GenerateResourceRequests. Unit tests have been added to verify these validation and clamping behaviors. The reviewer suggested adding nil checks for the container and pod parameters in MutateAdmission to prevent potential nil pointer dereferences.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pkg/device/nvidia/device.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/device/nvidia/device.go (1)

566-580: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Bounds check happens after truncating int64→int32, defeating the clamp on overflow.

mempnum = int32(mempnums) truncates the raw int64 value before the range check on Line 575. If mempnums is a value that overflows int32 (e.g., 2^32 + 50), the truncated result can land inside [0, 100] and silently bypass the clamp — exactly the kind of malformed/bypassing input this defense-in-depth code is meant to catch. Since this resource has no upper bound enforced by the API server, a pod bypassing the webhook could supply such a value.

Validate against the original int64 before casting to int32.

🛡️ Proposed fix to validate before truncating
 			if ok {
 				mempnums, ok := mem.AsInt64()
 				if ok {
-					mempnum = int32(mempnums)
-					if mempnum < 0 || mempnum > 100 {
-						klog.ErrorS(nil, "memory percentage request out of range, clamping to 100", "container", ctr.Name, "requested", mempnum)
-						mempnum = 100
+					if mempnums < 0 || mempnums > 100 {
+						klog.ErrorS(nil, "memory percentage request out of range, clamping to 100", "container", ctr.Name, "requested", mempnums)
+						mempnum = 100
+					} else {
+						mempnum = int32(mempnums)
 					}
 				}
 			}
🤖 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 `@pkg/device/nvidia/device.go` around lines 566 - 580, The memory percentage
clamp in the NVIDIA device resource parsing is checking after the int64-to-int32
cast, so overflowed values can bypass validation. In the
`pkg/device/nvidia/device.go` logic around `mempnum`, validate `mempnums` as an
int64 first against the 0–100 range, log and clamp if it is out of range, and
only then assign it to `mempnum` as int32. Keep the fix inside the existing
`resourceMemPercentage` parsing block so the `klog.ErrorS` path still reports
the container name and requested value.
🧹 Nitpick comments (1)
pkg/device/nvidia/device_test.go (1)

1818-1853: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider adding an int32-overflow test case.

Given the truncation issue flagged in pkg/device/nvidia/device.go (Lines 566-580), consider adding a case here with a value like 4294967397 (2^32 + 101) to lock in the fix and prevent regression once the bounds check is moved before the cast.

🤖 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 `@pkg/device/nvidia/device_test.go` around lines 1818 - 1853, Add an
int32-overflow regression case in the GPU memory percentage table in
device_test.go, alongside the existing gpumem-percentage clamping tests. Use a
value beyond int32 range (for example 2^32+101) so the test exercises the
truncation path in the device parsing logic and verifies the request still
clamps to 100. Keep it aligned with the parsing behavior in the Nvidia device
request code so the fix in device.go is protected from future regressions.
🤖 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.

Outside diff comments:
In `@pkg/device/nvidia/device.go`:
- Around line 566-580: The memory percentage clamp in the NVIDIA device resource
parsing is checking after the int64-to-int32 cast, so overflowed values can
bypass validation. In the `pkg/device/nvidia/device.go` logic around `mempnum`,
validate `mempnums` as an int64 first against the 0–100 range, log and clamp if
it is out of range, and only then assign it to `mempnum` as int32. Keep the fix
inside the existing `resourceMemPercentage` parsing block so the `klog.ErrorS`
path still reports the container name and requested value.

---

Nitpick comments:
In `@pkg/device/nvidia/device_test.go`:
- Around line 1818-1853: Add an int32-overflow regression case in the GPU memory
percentage table in device_test.go, alongside the existing gpumem-percentage
clamping tests. Use a value beyond int32 range (for example 2^32+101) so the
test exercises the truncation path in the device parsing logic and verifies the
request still clamps to 100. Keep it aligned with the parsing behavior in the
Nvidia device request code so the fix in device.go is protected from future
regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e9519d16-25c6-4066-8961-21a2b7240690

📥 Commits

Reviewing files that changed from the base of the PR and between 0517f24 and 8d3922e.

📒 Files selected for processing (2)
  • pkg/device/nvidia/device.go
  • pkg/device/nvidia/device_test.go

@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 59.09% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/device/nvidia/device.go 98.18% <100.00%> (+0.03%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pkg/device/nvidia/device.go Outdated
…low wraparound

Values beyond int32 range (e.g. 2^32+50) wrapped to an in-range
number after the cast and bypassed the clamp. Validate the raw
int64 value first, then cast.

Addresses review feedback on Project-HAMi#1997.

Signed-off-by: Saiyam Pathak <saiyam911@gmail.com>
…review

Init containers need more careful design at the admission layer;
they remain protected by the out-of-range clamp in
GenerateResourceRequests, which covers the scheduling path.

Addresses review feedback from archlitchi on Project-HAMi#1997.

Signed-off-by: Saiyam Pathak <saiyam911@gmail.com>
@saiyam1814

Copy link
Copy Markdown
Contributor Author

@archlitchi Thanks for the review — removed the init-container loop in d5a1fe3. Regular containers are still validated at admission, and init containers remain covered by the out-of-range clamp in GenerateResourceRequests on the scheduling path, so they can't produce permanently-Pending pods. Happy to explore a more holistic init-container admission design in a follow-up if there's interest.

Comment thread pkg/device/nvidia/device.go
@mesutoezdil

Copy link
Copy Markdown
Contributor

/lgtm

@archlitchi archlitchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@hami-robot

hami-robot Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: archlitchi, saiyam1814

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scheduler extender returns MemPercentagereq:101 overflow sentinel when nvidia.com/gpu is requested without nvidia.com/gpumem — pod stays unschedulable

3 participants