Skip to content

Fix/multi device quota enforcement - #2218

Closed
manmathbh wants to merge 1 commit into
Project-HAMi:masterfrom
manmathbh:fix/multi-device-quota-enforcement
Closed

Fix/multi device quota enforcement#2218
manmathbh wants to merge 1 commit into
Project-HAMi:masterfrom
manmathbh:fix/multi-device-quota-enforcement

Conversation

@manmathbh

@manmathbh manmathbh commented Jul 30, 2026

Copy link
Copy Markdown

What type of PR is this?

/kind bug

What this PR does / why we need it:

fitResourceQuota had a hard skip for every device except NVIDIA. Pods
requesting Ascend, Cambricon, Hygon or any other backend could blow right
past namespace ResourceQuota at admission time.

Removed the guard. Non-NVIDIA devices use memoryFactor=1, NVIDIA keeps
nvidia.MemoryFactor as before.

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

Special notes for your reviewer:

FitQuota in pkg/device/quota.go was already device-agnostic — call it with
an Ascend device name and it returns the right answer. The gap was purely
in fitResourceQuota skipping the call for non-NVIDIA.

Test setup registers a stub Ascend device with a 1000mb quota (0 used) and
verifies deny/allow for over/under-quota requests plus a no-count-resource
edge case.

Does this PR introduce a user-facing change?:

Pods requesting non-NVIDIA accelerator memory or core resources are now
checked against namespace ResourceQuota at admission time, same as NVIDIA.
Previously they were silently excluded.

Summary by CodeRabbit

  • Bug Fixes
    • Quota checks now account for all supported device types, not only NVIDIA GPUs.
    • Improved handling of device-specific memory quotas, including Ascend devices.
  • Tests
    • Expanded quota validation coverage for mixed device types and memory-only requests.
    • Added scenarios for exceeded and successfully fitted Ascend quotas.

…not only NVIDIA

Remove the NVIDIA-only guard in fitResourceQuota() that skipped quota enforcement for every non-NVIDIA device backend (Ascend, Cambricon, Hygon, etc.). MemoryFactor defaults to 1 for non-NVIDIA devices. Add mock device test helper and three new Ascend quota enforcement test cases including exceeded-quota, within-quota, and memory-only-no-count scenarios. Fixes Project-HAMi#2157

Signed-off-by: Manmath Hatte <manmathcode@gmail.com>
Copilot AI review requested due to automatic review settings July 30, 2026 18:49
@hami-robot hami-robot Bot added kind/bug Something isn't working dco-signoff: yes labels Jul 30, 2026
@hami-robot

hami-robot Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: manmathbh
Once this PR has been reviewed and has the lgtm label, please assign fouof for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found 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

Copilot AI 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.

Pull request overview

This PR fixes a gap in the scheduler admission webhook’s namespace ResourceQuota enforcement so that quota checks apply to non-NVIDIA accelerator backends (e.g., Ascend/Cambricon/Hygon) instead of being hard-skipped for all devices except NVIDIA. This aligns fitResourceQuota() behavior with the already device-agnostic QuotaManager.FitQuota() logic.

Changes:

  • Removed the NVIDIA-only guard in fitResourceQuota() and applied FitQuota() checks across all registered device backends.
  • Preserved NVIDIA’s existing nvidia.MemoryFactor behavior while defaulting other backends to memoryFactor=1.
  • Added webhook unit tests with a stub (mock) Ascend device to verify over-quota/within-quota and a “memory-only without count” edge case.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
pkg/scheduler/webhook.go Removes NVIDIA-only quota enforcement and applies quota checks to all registered device backends, keeping NVIDIA memoryFactor behavior.
pkg/scheduler/webhook_test.go Adds a mock Ascend device and test cases to validate quota enforcement for a non-NVIDIA backend.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +300 to +307
ascendCountName := "huawei.com/Ascend910B"
ascendMemName := "huawei.com/Ascend910B-memory"
device.DevicesMap["Ascend910B"] = &mockDevices{
resourceNames: device.ResourceNames{
ResourceCountName: ascendCountName,
ResourceMemoryName: ascendMemName,
},
}
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The webhook quota-fitting loop now checks all registered device types, using NVIDIA’s memory factor only for NVIDIA devices. Tests add Ascend device registration, quota data, and coverage for exceeded, within-quota, and memory-only requests.

Changes

Cross-device quota enforcement

Layer / File(s) Summary
Apply quota checks to every device
pkg/scheduler/webhook.go
fitResourceQuota invokes quota fitting for every device and retains the NVIDIA-specific memory factor.
Register and validate Ascend quota scenarios
pkg/scheduler/webhook_test.go
Mock devices expose resource names, Ascend quotas are registered, and Ascend exceeded, within-quota, and memory-only requests are tested.

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

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: copilot, dsfans2014, jay2006sawant

Poem

I’m a rabbit guarding quotas tonight,
Ascend hops into the ledger light.
NVIDIA keeps its factor true,
Every device gets checked anew.
Over the limit? No pass-through flight! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: quota enforcement for multiple device backends.
Linked Issues check ✅ Passed The webhook now enforces quota for all registered devices, matching the issue's non-NVIDIA quota gap.
Out of Scope Changes check ✅ Passed The code changes stay focused on quota enforcement and related tests, with no obvious unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@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.

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 `@pkg/scheduler/webhook_test.go`:
- Around line 302-320: Update the test setup around the Ascend910B device and
default quota entry to save their existing global values before overwriting
them, then restore those values in defer cleanup; only delete each key when no
prior value existed. Ensure both device.DevicesMap and qm.Quotas retain their
original state for subsequent tests.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c1e58a6-bd7b-42b9-b828-ab578ebf539b

📥 Commits

Reviewing files that changed from the base of the PR and between 05e6c80 and 523aaa8.

📒 Files selected for processing (2)
  • pkg/scheduler/webhook.go
  • pkg/scheduler/webhook_test.go

Comment on lines +302 to +320
device.DevicesMap["Ascend910B"] = &mockDevices{
resourceNames: device.ResourceNames{
ResourceCountName: ascendCountName,
ResourceMemoryName: ascendMemName,
},
}
defer func() {
delete(device.DevicesMap, "Ascend910B")
}()

qm := device.NewQuotaManager()
ns := "default"
memName := "nvidia.com/gpumem"
coreName := "nvidia.com/gpucores"
nvidiaMemName := "nvidia.com/gpumem"
nvidiaCoreName := "nvidia.com/gpucores"

qm.Quotas[ns] = &device.DeviceQuota{
memName: &device.Quota{Used: 1000, Limit: 2000},
coreName: &device.Quota{Used: 200, Limit: 400},
nvidiaMemName: &device.Quota{Used: 1000, Limit: 2000},
nvidiaCoreName: &device.Quota{Used: 200, Limit: 400},
ascendMemName: &device.Quota{Used: 0, Limit: 1000},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Restore the global test state instead of deleting it.

Line 302 can overwrite an existing Ascend910B device, but the defer always deletes it; Line 317 also leaves the singleton quota entry for default behind. Save and restore both prior values so later tests cannot become order-dependent.

Proposed fix
+	oldAscend, hadAscend := device.DevicesMap["Ascend910B"]
+	oldQuota, hadQuota := qm.Quotas[ns]
 	device.DevicesMap["Ascend910B"] = &mockDevices{
 		resourceNames: device.ResourceNames{
 			ResourceCountName:  ascendCountName,
 			ResourceMemoryName: ascendMemName,
 		},
 	}
 	defer func() {
-		delete(device.DevicesMap, "Ascend910B")
+		if hadAscend {
+			device.DevicesMap["Ascend910B"] = oldAscend
+		} else {
+			delete(device.DevicesMap, "Ascend910B")
+		}
+		if hadQuota {
+			qm.Quotas[ns] = oldQuota
+		} else {
+			delete(qm.Quotas, ns)
+		}
 	}()
🤖 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/scheduler/webhook_test.go` around lines 302 - 320, Update the test setup
around the Ascend910B device and default quota entry to save their existing
global values before overwriting them, then restore those values in defer
cleanup; only delete each key when no prior value existed. Ensure both
device.DevicesMap and qm.Quotas retain their original state for subsequent
tests.

@mesutoezdil

mesutoezdil commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

the gap is real, but hardcoding memoryfactor=1 for non-nvidia devices is wrong..

quota usage is accumulated from factor-scaled values (ascend/hygon multiply by their configured memoryfactor in generateresourcerequests),
so with factor > 1 the check compares mixed units and denies pods that are within quota.

the factor must come from each backend's config.
also note the issue author had already volunteered to work on #2157.

@DSFans2014 DSFans2014 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.

@manmathbh thank you for your contribution. it seems duplicated with #2172

@manmathbh

Copy link
Copy Markdown
Author

Didn't see #2172 was open for this. Closing, thanks for the review.

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.

[Bug] ResourceQuota enforcement only applies to NVIDIA devices, not other accelerator backends

4 participants