Support vnpus.configs wrapper format for HAMi vNPU device config#5399
Support vnpus.configs wrapper format for HAMi vNPU device config#5399shivansh-gohem wants to merge 2 commits into
Conversation
|
Welcome @shivansh-gohem! It looks like this is your first PR to volcano-sh/volcano 🎉 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR updates VNPU configuration parsing to support a new “HAMi wrapper” YAML format while preserving support for the legacy direct-array format, and updates call sites accordingly.
Changes:
- Introduced
VNPUsConfigwrapper type with custom YAML unmarshaling to accept both wrapper and legacy array formats. - Updated scheduler/device code paths to read VNPU configs via
config.VNPUs.Configs. - Added unit tests covering unmarshaling for both YAML formats.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/scheduler/plugins/deviceshare/deviceshare.go | Switch VNPU iteration to the new VNPUs.Configs field. |
| pkg/scheduler/api/devices/config/vnpu.go | Add VNPUsConfig and custom UnmarshalYAML supporting wrapper + legacy formats. |
| pkg/scheduler/api/devices/config/config_test.go | Add tests for parsing the new wrapper and legacy array vnpus YAML. |
| pkg/scheduler/api/devices/config/config.go | Change Config.VNPUs type to VNPUsConfig and update default config + docs comment. |
| pkg/scheduler/api/devices/ascend/hami/device_info_test.go | Update tests to reference VNPUs.Configs. |
| pkg/scheduler/api/devices/ascend/hami/device_info.go | Update runtime VNPU usage to reference VNPUs.Configs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func (v *VNPUsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||
| // Try the new wrapper format: { hamiVnpuCore: ..., configs: [...] } | ||
| type vnpusConfigAlias VNPUsConfig // alias prevents infinite recursion | ||
| var wrapper vnpusConfigAlias | ||
| if err := unmarshal(&wrapper); err == nil && len(wrapper.Configs) > 0 { | ||
| *v = VNPUsConfig(wrapper) | ||
| return nil | ||
| } | ||
|
|
||
| // Fallback: try legacy direct array format: [{ chipName: ... }] | ||
| var configs []VNPUConfig | ||
| if err := unmarshal(&configs); err != nil { | ||
| return fmt.Errorf("vnpus: failed to parse as either wrapper struct or direct array: %w", err) | ||
| } | ||
| v.Configs = configs | ||
| v.HamiVnpuCore = false | ||
| return nil | ||
| } |
| func TestParseVNPUsNewWrapperFormat(t *testing.T) { | ||
| yamlStr := ` | ||
| vnpus: | ||
| hamiVnpuCore: false | ||
| configs: | ||
| - chipName: 910A | ||
| commonWord: Ascend910A | ||
| resourceName: huawei.com/Ascend910A | ||
| resourceMemoryName: huawei.com/Ascend910A-memory | ||
| memoryAllocatable: 32768 | ||
| memoryCapacity: 32768 | ||
| aiCore: 30 | ||
| templates: | ||
| - name: vir02 | ||
| memory: 2184 | ||
| aiCore: 2 | ||
| ` | ||
| var config Config | ||
| err := yaml.Unmarshal([]byte(yamlStr), &config) | ||
| assert.Nil(t, err) | ||
| assert.Equal(t, false, config.VNPUs.HamiVnpuCore) | ||
| assert.Equal(t, 1, len(config.VNPUs.Configs)) | ||
| assert.Equal(t, "910A", config.VNPUs.Configs[0].ChipName) | ||
| assert.Equal(t, "Ascend910A", config.VNPUs.Configs[0].CommonWord) | ||
| assert.Equal(t, int64(32768), config.VNPUs.Configs[0].MemoryAllocatable) | ||
| assert.Equal(t, 1, len(config.VNPUs.Configs[0].Templates)) | ||
| assert.Equal(t, "vir02", config.VNPUs.Configs[0].Templates[0].Name) | ||
| } |
| type Config struct { | ||
| //NvidiaConfig is used for vGPU feature for nvidia, gpushare is not using this config | ||
| NvidiaConfig NvidiaConfig `yaml:"nvidia"` | ||
| VNPUs []VNPUConfig `yaml:"vnpus"` | ||
| VNPUs VNPUsConfig `yaml:"vnpus"` | ||
| } |
There was a problem hiding this comment.
Code Review
This pull request introduces a new wrapper format for VNPU configurations (VNPUsConfig) that supports both a new HAMi wrapper format and the legacy direct array format, updating references and adding corresponding unit tests. A review comment identifies a bug in the custom UnmarshalYAML implementation where a valid wrapper format with an empty configs list would incorrectly fall back to the legacy format and fail to parse, and provides a robust solution to handle this case.
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.
| func (v *VNPUsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { | ||
| // Try the new wrapper format: { hamiVnpuCore: ..., configs: [...] } | ||
| type vnpusConfigAlias VNPUsConfig // alias prevents infinite recursion | ||
| var wrapper vnpusConfigAlias | ||
| if err := unmarshal(&wrapper); err == nil && len(wrapper.Configs) > 0 { | ||
| *v = VNPUsConfig(wrapper) | ||
| return nil | ||
| } | ||
|
|
||
| // Fallback: try legacy direct array format: [{ chipName: ... }] | ||
| var configs []VNPUConfig | ||
| if err := unmarshal(&configs); err != nil { | ||
| return fmt.Errorf("vnpus: failed to parse as either wrapper struct or direct array: %w", err) | ||
| } | ||
| v.Configs = configs | ||
| v.HamiVnpuCore = false | ||
| return nil | ||
| } |
There was a problem hiding this comment.
The current custom UnmarshalYAML implementation relies on len(wrapper.Configs) > 0 to detect the new wrapper format. However, if a user provides a valid new wrapper format with an empty configs list (e.g., vnpus: { hamiVnpuCore: false, configs: [] }), len(wrapper.Configs) > 0 will be false. This causes the parser to fall back to the legacy direct array format, which then fails because a YAML map cannot be unmarshaled into a slice.
To fix this and make the parsing robust, we should explicitly check if the YAML node is a map (representing the new wrapper format) by attempting to unmarshal it into a temporary map first. If that succeeds, we parse it as the wrapper format; otherwise, we fall back to the legacy direct array format.
func (v *VNPUsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
// Check if the input is a map (new wrapper format)
var raw map[string]interface{}
if err := unmarshal(&raw); err == nil {
type vnpusConfigAlias VNPUsConfig // alias prevents infinite recursion
var wrapper vnpusConfigAlias
if err := unmarshal(&wrapper); err != nil {
return fmt.Errorf("vnpus: failed to parse wrapper struct: %w", err)
}
*v = VNPUsConfig(wrapper)
return nil
}
// Fallback: try legacy direct array format: [{ chipName: ... }]
var configs []VNPUConfig
if err := unmarshal(&configs); err != nil {
return fmt.Errorf("vnpus: failed to parse as either wrapper struct or direct array: %w", err)
}
v.Configs = configs
v.HamiVnpuCore = false
return nil
}596f7ad to
1341adf
Compare
| } | ||
|
|
||
| // UnmarshalYAML implements custom YAML unmarshaling for VNPUsConfig. | ||
| // It probes the YAML node type to disambiguate between the two formats: |
There was a problem hiding this comment.
Please remove these API-comments
|
/ok-to-test |
|
/assign |
|
@archlitchi resolved the feedback!! ptal |
| return nil | ||
| } | ||
|
|
||
| // Fallback: YAML node is an array — parse as legacy direct array format. |
There was a problem hiding this comment.
remove all comments in this method except this one
|
@archlitchi ptal whenever you have time |
|
please resolve the conflicts for it to be merged |
0a352a2 to
0258f50
Compare
|
@archlitchi i have resolved all the conflicts , please have a look!! |
Signed-off-by: Shivansh Sahu <sahushivansh142@gmail.com>
0258f50 to
dd6deab
Compare
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
What type of PR is this?
/kind bug
What this PR does / why we need it
The HAMi / ascend-device-plugin shared ConfigMap (
hami-scheduler-device) has moved to a newvnpusstructure:But Volcano currently parses
vnpusas a direct array:This means users following the HAMi vNPU guide will deploy the new format, but Volcano silently fails to parse the vNPU configs — resulting in zero configs being loaded.
This PR adds a
VNPUsConfigwrapper struct with a customUnmarshalYAMLthat auto-detects the YAML shape:vnpus: { hamiVnpuCore: ..., configs: [...] }vnpus: [{ chipName: ... }]This ensures full backward compatibility — existing deployments using the old array format continue to work, while new deployments following HAMi docs also parse correctly.
Which issue(s) this PR fixes
Fixes #5372
Changes
Core: Config Package
config/vnpu.go: AddedVNPUsConfigwrapper struct withHamiVnpuCorebool +Configs []VNPUConfig, and a customUnmarshalYAMLmethod for dual-format parsingconfig/config.go: ChangedConfig.VNPUsfield type from[]VNPUConfigtoVNPUsConfig; updatedGetDefaultDevicesConfig()and inline YAML documentationconfig/config_test.go: AddedTestParseVNPUsNewWrapperFormatandTestParseVNPUsLegacyArrayFormatConsumers
deviceshare/deviceshare.go: Updated.VNPUs→.VNPUs.Configs(1 site)ascend/hami/device_info.go: Updated.VNPUs→.VNPUs.Configs(3 sites)ascend/hami/device_info_test.go: Updated.VNPUs→.VNPUs.Configs(3 sites)Special notes for your reviewer
UnmarshalYAMLuses a type alias (vnpusConfigAlias) to prevent infinite recursion when unmarshaling the wrapper formatHamiVnpuCorefield is parsed and stored but not yet consumed by Volcano — included for forward compatibility with HAMiDoes this PR introduce a user-facing change?