Skip to content

refactor(vGPUmonitor): inject nvml.Interface instead of CGo package-l… - #2628

Closed
Kanika0306 wants to merge 1 commit into
Project-HAMi:masterfrom
Kanika0306:fix/vgpumonitor-nvml-interface-injection
Closed

refactor(vGPUmonitor): inject nvml.Interface instead of CGo package-l…#2628
Kanika0306 wants to merge 1 commit into
Project-HAMi:masterfrom
Kanika0306:fix/vgpumonitor-nvml-interface-injection

Conversation

@Kanika0306

@Kanika0306 Kanika0306 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Refactors cmd/vGPUmonitor to use the nvml.Interface abstraction instead of package-level NVML CGo calls.

This aligns vGPUmonitor with the existing NVML interface-injection pattern used elsewhere in HAMi and removes unnecessary coupling to CGo-specific package-level symbols.

Changes

  • Inject nvml.Interface into ClusterManager.
  • Pass the NVML interface through the GPU metrics collection flow.
  • Update watchAndFeedback to receive an nvml.Interface.
  • Use nvml.New() from main.go when initializing the components.
  • Replace direct package-level nvml.Init() / nvml.Shutdown() calls with interface methods.
  • Replace direct NVML return-value comparisons with errors.Is().
  • Remove redundant nvml.ErrorString() usage where the returned value already implements error.
  • Add a nil guard to preserve the existing test behaviour when no NVML interface is provided.
  • Update NewClusterManager to accept the NVML interface.

Motivation

The current implementation relies on package-level NVML CGo calls and constants, which makes the code more tightly coupled to the CGo implementation of go-nvml.

Using nvml.Interface provides a cleaner abstraction boundary and makes the GPU monitoring code easier to test with mocked NVML implementations in the future.

This also follows the interface-based pattern already present in other HAMi NVIDIA device-plugin components.

Testing

Verified with:

go build ./cmd/vGPUmonitor/...
go test ./cmd/vGPUmonitor/... -short -v

No functional behaviour is intended to change.

Related Issue

Closes #2627

Summary by CodeRabbit

  • Bug Fixes
    • Improved NVIDIA GPU monitoring reliability by handling initialization, device lookup, and metric collection errors more consistently.
    • Ensured NVIDIA monitoring resources are properly released after monitoring and feedback operations.
    • Added graceful degraded-mode operation with a warning when NVIDIA monitoring is unavailable.
    • Skipped physical GPU metric collection when the required NVIDIA monitoring service is unavailable.

Copilot AI lite review requested due to automatic review settings August 12, 2026 18:29
@hami-robot
hami-robot Bot requested review from lengrongfu and wawa0210 August 12, 2026 18:29
@hami-robot

hami-robot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Kanika0306
Once this PR has been reviewed and has the lgtm label, please assign dsfans2014 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 added the size/M label Aug 12, 2026
@Kanika0306

Copy link
Copy Markdown
Contributor Author

/assign

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6fc1d1e1-d3ad-4c3e-8784-a3c1752ecedf

📥 Commits

Reviewing files that changed from the base of the PR and between c0ca20e and bc05abe.

📒 Files selected for processing (2)
  • cmd/vGPUmonitor/feedback.go
  • cmd/vGPUmonitor/metrics.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • cmd/vGPUmonitor/feedback.go
  • cmd/vGPUmonitor/metrics.go

📝 Walkthrough

Walkthrough

The vGPU monitor now injects nvml.Interface into feedback handling and ClusterManager. GPU discovery and metric collection use the interface, support nil configuration, manage NVML lifecycle, and handle statuses with errors.Is.

Changes

NVML interface injection

Layer / File(s) Summary
NVML interface wiring
cmd/vGPUmonitor/main.go, cmd/vGPUmonitor/feedback.go, cmd/vGPUmonitor/metrics.go
The monitor creates an NVML instance and passes it to watchAndFeedback and NewClusterManager. ClusterManager stores the injected interface.
Injected GPU collection
cmd/vGPUmonitor/metrics.go
GPU discovery and metric queries use the injected interface, skip collection when it is nil, manage NVML initialization and shutdown, and check returned statuses with errors.Is.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • Project-HAMi/HAMi#2451: Both changes modify cmd/vGPUmonitor/feedback.go and watchAndFeedback; this PR changes NVML injection, while that PR addresses MIG lock-state handling.

Suggested reviewers: lengrongfu, wawa0210

Poem

A rabbit passes NVML through,
To metrics and feedback too.
Status checks now speak clear,
Nil interfaces cause no fear.
Shutdown follows when work is through.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The refactor meets the injection requirements in [#2627], but no mock-based unit tests for GPU collection are shown. Add unit tests that mock nvml.Interface and verify GPU collection without physical GPU hardware.
✅ 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 describes the main change: injecting nvml.Interface instead of using package-level CGo NVML APIs.
Out of Scope Changes check ✅ Passed The changes are limited to NVML injection, error handling, initialization, shutdown, and nil-guard behavior required by [#2627].
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 `@cmd/vGPUmonitor/feedback.go`:
- Around line 136-141: Add a nil check for nvmllib at the start of
watchAndFeedback before calling Init, returning an appropriate error when the
NVML interface is absent; preserve the existing initialization and deferred
Shutdown behavior for non-nil interfaces.
🪄 Autofix

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: 4c842669-385a-40a6-8194-6812cacd8446

📥 Commits

Reviewing files that changed from the base of the PR and between e34913f and c9c1e33.

📒 Files selected for processing (3)
  • cmd/vGPUmonitor/feedback.go
  • cmd/vGPUmonitor/main.go
  • cmd/vGPUmonitor/metrics.go

Comment thread cmd/vGPUmonitor/feedback.go Outdated
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 6.97674% with 40 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/vGPUmonitor/metrics.go 8.82% 31 Missing ⚠️
cmd/vGPUmonitor/feedback.go 0.00% 7 Missing ⚠️
cmd/vGPUmonitor/main.go 0.00% 2 Missing ⚠️
Flag Coverage Δ
unittests 62.36% <6.97%> (+0.06%) ⬆️

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

Files with missing lines Coverage Δ
cmd/vGPUmonitor/main.go 9.72% <0.00%> (ø)
cmd/vGPUmonitor/feedback.go 20.68% <0.00%> (-0.74%) ⬇️
cmd/vGPUmonitor/metrics.go 42.62% <8.82%> (-2.42%) ⬇️

... and 6 files with indirect coverage changes

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

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

Refactors cmd/vGPUmonitor to use nvml.Interface injection instead of package-level NVML CGo calls, aligning the monitor with the interface-based NVML usage pattern in the rest of HAMi and reducing direct coupling to CGo symbols.

Changes:

  • Adds an injected nvml.Interface to ClusterManager and threads it through the physical GPU metrics collection flow (with a nil guard to preserve current test behavior).
  • Updates watchAndFeedback to accept and use an injected nvml.Interface.
  • Initializes NVML interfaces via nvml.New() in main.go and replaces direct NVML return-value comparisons with errors.Is().

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
cmd/vGPUmonitor/metrics.go Injects nvml.Interface into the metrics collector path and replaces package-level NVML calls with interface methods.
cmd/vGPUmonitor/main.go Constructs nvml.Interface instances via nvml.New() and passes them into metrics/feedback initialization.
cmd/vGPUmonitor/feedback.go Refactors NVML init/shutdown in the feedback loop to use the injected nvml.Interface.
Suppressed comments (6)

cmd/vGPUmonitor/metrics.go:282

  • nvret is an nvml.Return (error). Using %s here will likely format incorrectly; use %w/%v instead so the error string is meaningful and can be unwrapped.
func (cc ClusterManagerCollector) getDeviceCount(nvmllib nvml.Interface) (int, error) {
	devnum, nvret := nvmllib.DeviceGetCount()
	if !errors.Is(nvret, nvml.SUCCESS) {
		return 0, fmt.Errorf("nvml GetDeviceCount err: %s", nvret)
	}

cmd/vGPUmonitor/metrics.go:290

  • nvret is an nvml.Return (error). %s formatting is likely incorrect; prefer %w/%v for proper error reporting/unwrapping.
func (cc ClusterManagerCollector) collectGPUDeviceMetrics(ch chan<- prometheus.Metric, nvmllib nvml.Interface, index int) error {
	hdev, nvret := nvmllib.DeviceGetHandleByIndex(index)
	if !errors.Is(nvret, nvml.SUCCESS) {
		return fmt.Errorf("nvml DeviceGetHandleByIndex err: %s", nvret)
	}

cmd/vGPUmonitor/metrics.go:316

  • These NVML return values are nvml.Return (error). Using %s will likely format incorrectly; use %w/%v so the error message is meaningful and can be unwrapped.
	uuid, nvret := hdev.GetUUID()
	if !errors.Is(nvret, nvml.SUCCESS) {
		return fmt.Errorf("nvml GetUUID err: %s", nvret)
	}

cmd/vGPUmonitor/metrics.go:343

  • nvret is an nvml.Return (error). Formatting with %s will likely produce %!s(...); use %w/%v for correct error output and unwrapping.
	util, nvret := hdev.GetUtilizationRates()
	if !errors.Is(nvret, nvml.SUCCESS) {
		return fmt.Errorf("nvml GetUtilizationRates err: %s", nvret)
	}

cmd/vGPUmonitor/metrics.go:348

  • nvret is an nvml.Return (error). %s formatting is likely incorrect; use %w/%v so the error message is meaningful and can be unwrapped.
	uuid, nvret := hdev.GetUUID()
	if !errors.Is(nvret, nvml.SUCCESS) {
		return fmt.Errorf("nvml GetUUID err: %s", nvret)
	}

cmd/vGPUmonitor/metrics.go:353

  • nvret is an nvml.Return (error). Using %s here will likely format incorrectly; use %w/%v for correct error reporting and unwrapping.
	deviceName, nvret := hdev.GetName()
	if !errors.Is(nvret, nvml.SUCCESS) {
		return fmt.Errorf("nvml GetName err: %s", nvret)
	}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +270 to 276
func (cc ClusterManagerCollector) initNVML(nvmllib nvml.Interface) error {
nvret := nvmllib.Init()
if !errors.Is(nvret, nvml.SUCCESS) {
return fmt.Errorf("nvml Init err: %s", nvret)
}
return nil
}
Comment on lines +136 to 140
func watchAndFeedback(ctx context.Context, lister *nvidia.ContainerLister, nvmllib nvml.Interface, migLockSignal <-chan bool) error {
klog.Info("Starting watchAndFeedback")
if nvret := nvml.Init(); nvret != nvml.SUCCESS {
return fmt.Errorf("failed to initialize NVML: %s", nvml.ErrorString(nvret))
if nvret := nvmllib.Init(); !errors.Is(nvret, nvml.SUCCESS) {
return fmt.Errorf("failed to initialize NVML: %s", nvret)
}
…evel calls

Replace direct package-level nvml.Init/Shutdown/DeviceGetCount/DeviceGetHandleByIndex
calls with an injected nvml.Interface in ClusterManager. Switch constant
comparisons (nvret != nvml.SUCCESS) to errors.Is() — the same pattern
already used in pkg/device/nvidia/links.go.

Motivation
- The package-level nvml functions and constants (nvml.SUCCESS,
  nvml.ERROR_NOT_SUPPORTED) are defined via CGo (#include nvml.h).
  The Windows/non-CGo Go language server cannot resolve them, producing
  10 x "undefined: nvml.SUCCESS" IDE errors in metrics.go and feedback.go.
- Calling CGo package-level globals makes the collector hard to unit-test
  without real GPU hardware.

Changes
- cmd/vGPUmonitor/metrics.go
  - Add nvmllib nvml.Interface field to ClusterManager (unexported).
  - Guard collectGPUInfo with a nil check so existing tests that omit
    nvmllib continue to work without a mock.
  - Thread nvmllib through initNVML/getDeviceCount/collectGPUDeviceMetrics.
  - Replace nvret != nvml.SUCCESS with !errors.Is(nvret, nvml.SUCCESS).
  - Replace nvml.ERROR_NOT_SUPPORTED == with errors.Is().
  - Remove nvml.ErrorString() calls; nvml.Return implements error/Stringer
    so direct %s formatting works.
  - Update NewClusterManager signature to accept nvml.Interface.

- cmd/vGPUmonitor/feedback.go
  - watchAndFeedback now accepts nvml.Interface instead of calling
    package-level nvml.Init/Shutdown directly.

- cmd/vGPUmonitor/main.go
  - Pass nvml.New() to both NewClusterManager and watchAndFeedback.

All existing unit tests pass (go test ./cmd/vGPUmonitor/... -short).

Signed-off-by: Kanika0306 <kanikakatare0306@gmail.com>
@Kanika0306
Kanika0306 force-pushed the fix/vgpumonitor-nvml-interface-injection branch from c0ca20e to bc05abe Compare August 12, 2026 18:57
@mesutoezdil

Copy link
Copy Markdown
Contributor

This is being closed because it does not comply with the contribution guidelines.

@Kanika0306

Copy link
Copy Markdown
Contributor Author

ok I will adhere to the guideline and contribute

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.

cmd/vGPUmonitor: Replace package-level NVML CGo calls with nvml.Interface

3 participants