Skip to content

enforce resource quota for all device backends - #2172

Closed
Jay2006sawant wants to merge 2 commits into
Project-HAMi:masterfrom
Jay2006sawant:fix/resourcequota-multi-vendor
Closed

enforce resource quota for all device backends#2172
Jay2006sawant wants to merge 2 commits into
Project-HAMi:masterfrom
Jay2006sawant:fix/resourcequota-multi-vendor

Conversation

@Jay2006sawant

@Jay2006sawant Jay2006sawant commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind bug

What this PR does / why we need it:

HAMi's QuotaManager tracks namespace memory and core usage in a device agnostic way, but quota enforcement was wired only for NVIDIA. The admission webhook skipped all non-NVIDIA devices, and only NVIDIA's Fit() path called FitQuota() during scheduling.

This PR adds shared quota helpers in pkg/device/quota.go and enforces namespace ResourceQuota for all registered device backends at admission time. It also adds pre-allocation quota checks in the scheduler Fit() path for Cambricon, Ascend, and Hygon, matching the existing NVIDIA behavior.

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

Special notes for your reviewer:

  • Shared helpers: PodQuotaRequests, FitPodQuota, FitAllocationQuota
  • Webhook fitResourceQuota() now iterates all devices in DevicesMap
  • NVIDIA fitQuota() refactored to use FitAllocationQuota
  • Added quota checks in Fit() for Cambricon, Ascend, and Hygon
  • New tests cover non-NVIDIA webhook denial and quota request calculation
  • make test and make verify pass locally
  • No GPU hardware required

Does this PR introduce a user-facing change?:

Yes. In multi-vendor clusters, pods requesting Cambricon, Ascend, Hygon, or other registered backends can now be denied at admission or scheduler Filter time when namespace ResourceQuota limits for vendor memory or core resources would be exceeded. Previously, only NVIDIA quota enforcement was active.

AI assistance disclosure:
I used AI assistance to understand the codebase and explore the quota enforcement flow. All code changes, tests, and verification were written and run by me. I reviewed and understand the full diff.

Summary by CodeRabbit

  • New Features
    • Enhanced namespace quota validation to account for pod memory and compute requests across supported device types.
    • Applied device-specific memory scaling when calculating quota consumption.
  • Bug Fixes
    • Prevented allocations that exceed namespace quotas, including pending and already allocated resources.
    • Extended quota enforcement to non-NVIDIA device types.
  • Tests
    • Added coverage for quota calculations, memory scaling, allocation rejection, and scheduler admission enforcement.

@hami-robot hami-robot Bot added kind/bug Something isn't working dco-signoff: yes labels Jul 28, 2026
@hami-robot
hami-robot Bot requested a review from archlitchi July 28, 2026 11:34
@hami-robot

hami-robot Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Jay2006sawant
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

@hami-robot
hami-robot Bot requested a review from lengrongfu July 28, 2026 11:34
@hami-robot hami-robot Bot added the size/L label Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Resource quota calculations are centralized in shared helpers. Scheduler admission and accelerator allocation now apply quota checks across NVIDIA and non-NVIDIA device backends. Tests cover request extraction, memory factors, allocation accounting, and quota rejection.

Changes

Resource quota enforcement

Layer / File(s) Summary
Shared quota helpers and device contract
pkg/device/devices.go, pkg/device/quota.go, pkg/device/*/device.go, pkg/device/*/vdevice.go, pkg/device/*/gcu.go, pkg/device/*/sdevice.go, pkg/device/*_test.go, pkg/scheduler/*_test.go
Adds the MemoryFactor() interface method and default implementations. Adds pod request extraction, memory scaling, allocation quota helpers, backend accessors, and related tests.
All-device admission checks
pkg/scheduler/webhook.go, pkg/scheduler/webhook_test.go
Replaces NVIDIA-only quota handling with FitPodQuota calls for registered device types. Adds non-NVIDIA admission rejection coverage.
Backend allocation quota gates
pkg/device/ascend/*, pkg/device/cambricon/*, pkg/device/hygon/*, pkg/device/nvidia/*
Adds pre-allocation quota checks for Ascend, Cambricon, and Hygon. Routes NVIDIA allocation accounting through FitAllocationQuota. Adds backend rejection tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Scheduler
  participant fitResourceQuota
  participant FitPodQuota
  participant QuotaManager
  Scheduler->>fitResourceQuota: check pod quota
  fitResourceQuota->>FitPodQuota: compute device-specific requests
  FitPodQuota->>QuotaManager: validate memory and cores
  QuotaManager-->>fitResourceQuota: return quota result
  fitResourceQuota-->>Scheduler: allow or deny admission
Loading

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: lengrongfu, archlitchi

Poem

I’m a rabbit with a quota chart,
Memory and cores each play their part.
Every device checks the gate,
Shared rules decide its fate.
Over the limit, no pods hop through.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes enforcement of resource quotas across all device backends.
Linked Issues check ✅ Passed The changes address issue #2157 by adding shared quota checks, extending webhook enforcement, updating backend Fit paths, and preserving NVIDIA memory-factor behavior.
Out of Scope Changes check ✅ Passed The changes are related to quota enforcement, backend integration, interface updates, and tests required by issue #2157.
✨ 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.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.18310% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/device/quota.go 95.83% 1 Missing and 1 partial ⚠️
Flag Coverage Δ
unittests 64.38% <97.18%> (+0.16%) ⬆️

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

Files with missing lines Coverage Δ
pkg/device/amd/device.go 76.64% <ø> (ø)
pkg/device/ascend/device.go 83.83% <100.00%> (+0.22%) ⬆️
pkg/device/awsneuron/device.go 76.05% <ø> (ø)
pkg/device/biren/device.go 94.89% <ø> (ø)
pkg/device/cambricon/device.go 85.76% <100.00%> (+2.17%) ⬆️
pkg/device/devices.go 91.39% <100.00%> (+0.04%) ⬆️
pkg/device/enflame/device.go 61.73% <ø> (ø)
pkg/device/enflame/gcu.go 90.35% <ø> (ø)
pkg/device/hygon/device.go 92.82% <100.00%> (+0.21%) ⬆️
pkg/device/iluvatar/device.go 57.99% <ø> (ø)
... and 9 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@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: 3

🧹 Nitpick comments (1)
pkg/device/quota_test.go (1)

231-296: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tests mutate the package-level QuotaManager singleton without restoring it. All five sites call device.NewQuotaManager() (or the in-package NewQuotaManager()) and write qm.Quotas["default"] = ... directly on the shared singleton, but only device.DevicesMap is restored via t.Cleanup; the quota entry is never reset, leaving stale quota state for any later test in the same binary that reuses namespace "default".

  • pkg/device/quota_test.go#L231-L296: add t.Cleanup to delete/reset qm.Quotas["default"] after TestFitAllocationQuota (and the adjacent TestFitPodQuotaMemoryFactor/TestFitPodQuotaNonNvidia).
  • pkg/device/ascend/device_test.go#L2110-L2159: add the same cleanup for qm.Quotas["default"] in TestDevices_Fit_ResourceQuotaExceeded.
  • pkg/device/cambricon/device_test.go#L1074-L1108: add the same cleanup in TestDevices_Fit_ResourceQuotaExceeded.
  • pkg/device/hygon/device_test.go#L1167-L1201: add the same cleanup in TestDevices_Fit_ResourceQuotaExceeded.
  • pkg/scheduler/webhook_test.go#L461-L499: add the same cleanup in TestFitResourceQuotaNonNvidiaExceeded.
🤖 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/quota_test.go` around lines 231 - 296, Add t.Cleanup to restore or
delete qm.Quotas["default"] after each test mutates the shared quota singleton.
Apply this in pkg/device/quota_test.go:231-296 for TestFitAllocationQuota and
the adjacent quota tests, pkg/device/ascend/device_test.go:2110-2159,
pkg/device/cambricon/device_test.go:1074-1108,
pkg/device/hygon/device_test.go:1167-1201, and
pkg/scheduler/webhook_test.go:461-499, preserving the existing DevicesMap
cleanup.
🤖 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/device/ascend/device.go`:
- Around line 520-524: The quota check in the device allocation flow should use
Ascend’s configured MemoryFactor instead of the hardcoded factor 1. Update the
FitAllocationQuota call to pass the same factor applied by
GenerateResourceRequests for both percentage-based memory requests (dev.Totalmem
* k.MemPercentagereq / 100) and normal Memreq, while preserving the existing
quota failure handling.

In `@pkg/device/hygon/device.go`:
- Around line 304-308: The quota checks do not consistently apply Hygon's memory
factor. In pkg/device/hygon/device.go lines 304-308, update the
FitAllocationQuota call in the Hygon allocation path to use the package
MemoryFactor instead of 1; in pkg/scheduler/webhook.go lines 132-137, extend
memoryFactor resolution beyond NVIDIA to include Hygon's MemoryFactor and
preserve the analogous behavior for future supported devices.

In `@pkg/device/quota.go`:
- Around line 132-138: Update FitPodQuota to immediately allow pods with no
request for the specified device, using the values returned by PodQuotaRequests
to detect zero resource usage before calling GetLocalCache().FitQuota; retain
the existing memoryFactor adjustment and quota evaluation for pods that request
the device.

---

Nitpick comments:
In `@pkg/device/quota_test.go`:
- Around line 231-296: Add t.Cleanup to restore or delete qm.Quotas["default"]
after each test mutates the shared quota singleton. Apply this in
pkg/device/quota_test.go:231-296 for TestFitAllocationQuota and the adjacent
quota tests, pkg/device/ascend/device_test.go:2110-2159,
pkg/device/cambricon/device_test.go:1074-1108,
pkg/device/hygon/device_test.go:1167-1201, and
pkg/scheduler/webhook_test.go:461-499, preserving the existing DevicesMap
cleanup.
🪄 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: 3d1472d5-4099-4327-a32c-66751bb4e290

📥 Commits

Reviewing files that changed from the base of the PR and between 37730dd and bcd0850.

📒 Files selected for processing (11)
  • pkg/device/ascend/device.go
  • pkg/device/ascend/device_test.go
  • pkg/device/cambricon/device.go
  • pkg/device/cambricon/device_test.go
  • pkg/device/hygon/device.go
  • pkg/device/hygon/device_test.go
  • pkg/device/nvidia/device.go
  • pkg/device/quota.go
  • pkg/device/quota_test.go
  • pkg/scheduler/webhook.go
  • pkg/scheduler/webhook_test.go

Comment thread pkg/device/ascend/device.go Outdated
Comment thread pkg/device/hygon/device.go Outdated
Comment thread pkg/device/quota.go

@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

🧹 Nitpick comments (1)
pkg/scheduler/webhook.go (1)

132-141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Denial log doesn't identify which vendor/device caused the quota rejection.

Now that the loop checks every registered device type instead of only NVIDIA, the unchanged log line ("... - Denying admission", no deviceName) loses the ability to tell operators which backend's quota was exceeded. Also, the inline if deviceName == nvidia.NvidiaGPUDevice special-case will need to be extended for every future vendor that needs a non-default factor; consider moving factor resolution behind the Devices interface/registry so fitResourceQuota stays vendor-agnostic.

♻️ Include deviceName in the denial log
 		if !device.FitPodQuota(pod, deviceName, memoryFactor) {
-			klog.Infof(template+" - Denying admission", pod.Namespace, pod.Name, pod.UID)
+			klog.Infof(template+" - Denying admission, device %s exceeds quota", pod.Namespace, pod.Name, pod.UID, deviceName)
 			return false
 		}
🤖 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.go` around lines 132 - 141, Update the quota rejection
log in the device-checking loop to include the failing deviceName, while
preserving the existing admission-denial behavior. Keep factor selection
vendor-agnostic by moving device-specific memory-factor resolution behind the
Devices interface or registry rather than extending the inline NVIDIA special
case.
🤖 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.go`:
- Around line 133-136: Update the memoryFactor selection in fitResourceQuota to
use the configured factor for each device vendor, including Hygon and Ascend,
rather than defaulting to 1 for all non-NVIDIA devices. Reuse the existing
vendor configuration or shared interface used during resource request generation
so admission-time quota validation matches the scheduler’s authoritative check.

---

Nitpick comments:
In `@pkg/scheduler/webhook.go`:
- Around line 132-141: Update the quota rejection log in the device-checking
loop to include the failing deviceName, while preserving the existing
admission-denial behavior. Keep factor selection vendor-agnostic by moving
device-specific memory-factor resolution behind the Devices interface or
registry rather than extending the inline NVIDIA special case.
🪄 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: f8af6780-7b5e-4081-9937-d7850095a2d2

📥 Commits

Reviewing files that changed from the base of the PR and between bcd0850 and e138494.

📒 Files selected for processing (11)
  • pkg/device/ascend/device.go
  • pkg/device/ascend/device_test.go
  • pkg/device/cambricon/device.go
  • pkg/device/cambricon/device_test.go
  • pkg/device/hygon/device.go
  • pkg/device/hygon/device_test.go
  • pkg/device/nvidia/device.go
  • pkg/device/quota.go
  • pkg/device/quota_test.go
  • pkg/scheduler/webhook.go
  • pkg/scheduler/webhook_test.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • pkg/device/hygon/device_test.go
  • pkg/device/hygon/device.go
  • pkg/device/cambricon/device.go
  • pkg/device/nvidia/device.go
  • pkg/device/quota.go
  • pkg/device/ascend/device_test.go
  • pkg/scheduler/webhook_test.go
  • pkg/device/cambricon/device_test.go
  • pkg/device/quota_test.go
  • pkg/device/ascend/device.go

Comment thread pkg/scheduler/webhook.go Outdated
@github-actions github-actions Bot removed the kind/bug Something isn't working label Jul 28, 2026

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

Comment thread pkg/device/hygon/device.go Outdated
//This incurs an issue
memreq = dev.Totalmem * k.MemPercentagereq / 100
}
if !device.FitAllocationQuota(pod.Namespace, k.Type, 1, int64(memreq), int64(k.Coresreq), tmpDevs, allocated) {

@mesutoezdil mesutoezdil Jul 29, 2026

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.

hygon already scales memnums by its own MemoryFactor in GenerateResourceRequests, so the hardcoded 1 here leaves the quota limit unscaled. what happens on a cluster w/ memoryFactor 10? ascend has the same issue.

Comment thread pkg/scheduler/webhook.go Outdated
continue
for deviceName := range device.GetDevices() {
memoryFactor := int32(1)
if deviceName == nvidia.NvidiaGPUDevice {

@mesutoezdil mesutoezdil Jul 29, 2026

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.

this swaps one hardcoded nvidia branch for another, a MemoryFactor() on the Devices interface would cover every backend.

},
},
}
qm := device.NewQuotaManager()

@mesutoezdil mesutoezdil Jul 29, 2026

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.

NewQuotaManager is a sync.Once singleton, so this writes to the global w/ no cleanup, unlike DevicesMap above.

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

This PR adds shared quota helpers in pkg/device/quota.go and enforces namespace ResourceQuota for all registered device backends at admission time. It also adds pre-allocation quota checks in the scheduler Fit() path for Cambricon, Ascend, and Hygon, matching the existing NVIDIA behavior.

Why check all devices at admission but only Cambricon, Ascend, Hygon and NVIDIA in fit?

Signed-off-by: Jay2006sawant <jay242902@gmail.com>
@Jay2006sawant
Jay2006sawant force-pushed the fix/resourcequota-multi-vendor branch from 5c7e5f0 to 81a5f49 Compare July 31, 2026 17:59

@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 (5)
pkg/device/mthreads/device.go (3)

97-99: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Complete the request fallback before mutating resources.

When the GPU count comes from ctr.Resources.Requests and ctr.Resources.Limits is nil, the assignments below panic with assignment to entry in nil map. The same path reads memory only from Limits, so a request-only memory value is ignored.

Initialize Limits and fall back to Requests for the memory resource.

Proposed fix
 if ok {
 	if count.Value() <= 0 {
 		return false, fmt.Errorf("%s must be greater than 0", MthreadsResourceCount)
 	}
+	if ctr.Resources.Limits == nil {
+		ctr.Resources.Limits = corev1.ResourceList{}
+	}
 	if count.Value() > 1 {
 		...
 	}
 	mem, memok := ctr.Resources.Limits[corev1.ResourceName(MthreadsResourceMemory)]
+	if !memok {
+		mem, memok = ctr.Resources.Requests[corev1.ResourceName(MthreadsResourceMemory)]
+	}

Also applies to: 110-113

🤖 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/mthreads/device.go` around lines 97 - 99, Update the resource
fallback logic around the GPU count lookup to initialize ctr.Resources.Limits
before any assignments when it is nil, and use ctr.Resources.Requests as the
fallback source for the memory resource when no limit is present. Preserve the
existing limit values when available and ensure both GPU and memory request-only
paths can be written safely.

211-213: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Bound memory and core quantities before narrowing them.

The current check only rejects out-of-range device counts. A large memnums makes int(memnums) * 512 overflow before it is returned as int32(memnum), and negative corenums turns into a large positive Coresreq. Reject invalid memnums * 512 and corenums before conversion.

Proposed fix
 			if ok {
 				memnums, ok := mem.AsInt64()
 				if ok {
+					if memnums < 0 || memnums > math.MaxInt32/512 {
+						return device.ContainerDeviceRequest{}
+					}
 					memnum = int(memnums) * 512
 				}
 			}
...
 			if ok {
 				corenums, ok := core.AsInt64()
 				if ok {
+					if corenums < 0 || corenums > math.MaxInt32 {
+						return device.ContainerDeviceRequest{}
+					}
 					corenum = int32(corenums)
 				}
 			}
🤖 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/mthreads/device.go` around lines 211 - 213, Update the validation
near the device quantity checks to reject negative or overflow-prone memnums
before calculating memnums*512, and reject invalid corenums before narrowing it
to the request’s core field. Preserve the existing invalid-device response and
only perform the int32 conversions after all bounds checks pass.

100-103: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require an exact integer GPU count.

count.Value() rounds decimal quantities up, so 0.5 becomes one GPU and 1.5 becomes two GPUs. Use count.AsInt64() and reject non-integral or oversized values before allocating cores, memory, or setting mthreads.com/request-gpu-num.

Proposed fix
 if ok {
-	if count.Value() <= 0 {
+	countValue, exact := count.AsInt64()
+	if !exact || countValue <= 0 || countValue > math.MaxInt32 {
 		return false, fmt.Errorf("%s must be greater than 0", MthreadsResourceCount)
 	}
-	if count.Value() > 1 {
+	if countValue > 1 {

Use countValue for the later calculations and annotation.

🤖 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/mthreads/device.go` around lines 100 - 103, Update the GPU count
validation in the device setup flow to use count.AsInt64(), rejecting
non-integral or oversized quantities before allocating cores, memory, or setting
mthreads.com/request-gpu-num. Store the validated integer as countValue and
reuse it for subsequent calculations and annotation instead of count.Value().
pkg/device/enflame/device.go (2)

406-408: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject negative profile.CorePercent values.

The new check validates only the upper bound. A negative value converts to a negative profileCorePercent, passes the available-core check, and is stored as negative Usedcores. Later usage accounting can decrease the recorded core usage.

Proposed fix
-if profile.CorePercent > math.MaxInt32 {
+if profile.CorePercent < 0 || profile.CorePercent > math.MaxInt32 {
🤖 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/enflame/device.go` around lines 406 - 408, Update the validation
around profile.CorePercent to reject values below zero as well as values above
math.MaxInt32, returning the same common.ModeNotFit result for either invalid
bound before converting or storing the value as profileCorePercent or Usedcores.

645-649: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject fractional values before integer conversion.

Both float64 branches accept values such as 1.5 and truncate them to 1. This silently changes DRS capacity and custom-info values. Require an integral value before conversion in parseDRSCapacity and readCustomInfoInt.

🤖 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/enflame/device.go` around lines 645 - 649, Update the float64
handling in parseDRSCapacity and readCustomInfoInt to reject fractional values
before converting to int32. Extend the existing NaN and int32-range validation
with an integrality check, returning the current invalid-value error for
non-integral inputs while preserving valid integral conversions.
🤖 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/enflame/device.go`:
- Around line 406-408: Update the validation around profile.CorePercent to
reject values below zero as well as values above math.MaxInt32, returning the
same common.ModeNotFit result for either invalid bound before converting or
storing the value as profileCorePercent or Usedcores.
- Around line 645-649: Update the float64 handling in parseDRSCapacity and
readCustomInfoInt to reject fractional values before converting to int32. Extend
the existing NaN and int32-range validation with an integrality check, returning
the current invalid-value error for non-integral inputs while preserving valid
integral conversions.

In `@pkg/device/mthreads/device.go`:
- Around line 97-99: Update the resource fallback logic around the GPU count
lookup to initialize ctr.Resources.Limits before any assignments when it is nil,
and use ctr.Resources.Requests as the fallback source for the memory resource
when no limit is present. Preserve the existing limit values when available and
ensure both GPU and memory request-only paths can be written safely.
- Around line 211-213: Update the validation near the device quantity checks to
reject negative or overflow-prone memnums before calculating memnums*512, and
reject invalid corenums before narrowing it to the request’s core field.
Preserve the existing invalid-device response and only perform the int32
conversions after all bounds checks pass.
- Around line 100-103: Update the GPU count validation in the device setup flow
to use count.AsInt64(), rejecting non-integral or oversized quantities before
allocating cores, memory, or setting mthreads.com/request-gpu-num. Store the
validated integer as countValue and reuse it for subsequent calculations and
annotation instead of count.Value().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6cfd702a-f6fd-4351-9409-cfd0fcf15cda

📥 Commits

Reviewing files that changed from the base of the PR and between e138494 and e30ab78.

📒 Files selected for processing (27)
  • pkg/device/amd/device.go
  • pkg/device/ascend/device.go
  • pkg/device/ascend/device_test.go
  • pkg/device/awsneuron/device.go
  • pkg/device/biren/device.go
  • pkg/device/cambricon/device.go
  • pkg/device/cambricon/device_test.go
  • pkg/device/devices.go
  • pkg/device/devices_test.go
  • pkg/device/enflame/device.go
  • pkg/device/enflame/gcu.go
  • pkg/device/hygon/device.go
  • pkg/device/hygon/device_test.go
  • pkg/device/iluvatar/device.go
  • pkg/device/kunlun/device.go
  • pkg/device/kunlun/vdevice.go
  • pkg/device/metax/device.go
  • pkg/device/metax/sdevice.go
  • pkg/device/mthreads/device.go
  • pkg/device/nvidia/device.go
  • pkg/device/quota.go
  • pkg/device/quota_test.go
  • pkg/device/vastai/device.go
  • pkg/scheduler/scheduler_test.go
  • pkg/scheduler/score_test.go
  • pkg/scheduler/webhook.go
  • pkg/scheduler/webhook_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • pkg/device/hygon/device_test.go
  • pkg/device/cambricon/device_test.go
  • pkg/device/ascend/device_test.go
  • pkg/device/quota.go

Signed-off-by: Jay2006sawant <jay242902@gmail.com>
@Jay2006sawant

Copy link
Copy Markdown
Contributor Author

@DSFans2014 Good catch. Admission now enforces quota for all registered devices (the #2157 bug). Fit() quota was NVIDIA-only before; I added it for Cambricon/Ascend/Hygon since they share the same vGPU allocation path. Other backends are covered at admission but not yet in Fit().happy to extend that in a follow-up if you'd like.

@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/device/nvidia/device_test.go`:
- Around line 1910-1915: Update TestMemoryFactor to capture the package-level
MemoryFactor before calling InitNvidiaDevice, then register t.Cleanup to restore
that value after the test. Keep the existing assertion unchanged.
🪄 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: 9b8e2481-335a-4ed4-9b71-4ddcc12bdf9e

📥 Commits

Reviewing files that changed from the base of the PR and between 81a5f49 and b42f228.

📒 Files selected for processing (18)
  • pkg/device/amd/device.go
  • pkg/device/ascend/device_test.go
  • pkg/device/awsneuron/device.go
  • pkg/device/biren/device.go
  • pkg/device/cambricon/device.go
  • pkg/device/devices.go
  • pkg/device/enflame/device.go
  • pkg/device/enflame/gcu.go
  • pkg/device/hygon/device_test.go
  • pkg/device/iluvatar/device.go
  • pkg/device/kunlun/device.go
  • pkg/device/kunlun/vdevice.go
  • pkg/device/metax/device.go
  • pkg/device/metax/sdevice.go
  • pkg/device/mthreads/device.go
  • pkg/device/nvidia/device_test.go
  • pkg/device/quota_test.go
  • pkg/device/vastai/device.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/device/hygon/device_test.go

Comment on lines +1910 to +1915
func TestMemoryFactor(t *testing.T) {
dev := InitNvidiaDevice(NvidiaConfig{
ResourceCountName: "nvidia.com/gpu",
MemoryFactor: 3,
})
assert.Equal(t, dev.MemoryFactor(), int32(3))

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 package-level MemoryFactor after this test.

InitNvidiaDevice changes the package-level MemoryFactor to 3. Restore the previous value with t.Cleanup; otherwise, later or parallel tests can observe state created by this test.

Restore the test state
 func TestMemoryFactor(t *testing.T) {
+	oldMemoryFactor := MemoryFactor
+	t.Cleanup(func() {
+		MemoryFactor = oldMemoryFactor
+	})
 	dev := InitNvidiaDevice(NvidiaConfig{
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func TestMemoryFactor(t *testing.T) {
dev := InitNvidiaDevice(NvidiaConfig{
ResourceCountName: "nvidia.com/gpu",
MemoryFactor: 3,
})
assert.Equal(t, dev.MemoryFactor(), int32(3))
func TestMemoryFactor(t *testing.T) {
oldMemoryFactor := MemoryFactor
t.Cleanup(func() {
MemoryFactor = oldMemoryFactor
})
dev := InitNvidiaDevice(NvidiaConfig{
ResourceCountName: "nvidia.com/gpu",
MemoryFactor: 3,
})
assert.Equal(t, dev.MemoryFactor(), int32(3))
🤖 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 1910 - 1915, Update
TestMemoryFactor to capture the package-level MemoryFactor before calling
InitNvidiaDevice, then register t.Cleanup to restore that value after the test.
Keep the existing assertion unchanged.

@mesutoezdil

Copy link
Copy Markdown
Contributor

@DSFans2014 Good catch. Admission now enforces quota for all registered devices (the #2157 bug). Fit() quota was NVIDIA-only before; I added it for Cambricon/Ascend/Hygon since they share the same vGPU allocation path. Other backends are covered at admission but not yet in Fit().happy to extend that in a follow-up if you'd like.

Reminder: Answers must be written by human being. You can view the relevant rule here.
https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
"4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed."

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

3 participants