Skip to content

vcsim: Reconfigure does not populate ConfigInfo.NumaInfo from ConfigSpec.VirtualNuma #4072

Description

@hpannem

Is your feature request related to a problem? Please describe.

vcsim's ReconfigVM_Task handler never reads or reflects VirtualMachineConfigSpec.VirtualNuma into VirtualMachineConfigInfo.NumaInfo. Confirmed via grep -n "VirtualNuma\|NumaInfo" simulator/virtual_machine.go on v0.55.0-alpha.0.0.20260622155957-a8a7db14910d — zero matches. A ReconfigVM_Task that sets an explicit VirtualNuma.CoresPerNumaNode is accepted with no fault, but a subsequent read of config.numaInfo never shows the value — it stays permanently nil, regardless of power state or how many times the identical Reconfigure is repeated.

This diverges from real vSphere. I verified against vSphere 8.0 U1+ (hw version vmx-23, 2-vCPU VM) with a small pyVmomi script: an explicit CoresPerNumaNode is reflected in config.numaInfo.coresPerNumaNode immediately after the Reconfigure task completes — even while the VM is powered off — and it persists correctly across power-on/power-off cycles:

Step NumaInfo.CoresPerNumaNode AutoCoresPerNumaNode
Before any change None True
After Reconfigure, still powered off 2 False
After identical Reconfigure repeated, still off 2 False
After power-on 2 False
After power-off again 2 False
After Reconfigure with coresPerNumaNode=0 (rollback to auto) None True

Because vcsim never reflects this, any controller that reconciles VirtualNuma/NumaInfo against vcsim by diffing desired vs. live config.numaInfo can never observe convergence — it keeps re-issuing an identical, silently no-op-from-vcsim's-perspective ReconfigVM_Task forever. There's no fault or error, so it only surfaces as a runaway reconcile loop in the consuming project's own tests or safety limits.

Describe the solution you'd like

In the ReconfigVM_Task handler in simulator/virtual_machine.go, when spec.VirtualNuma != nil:

  • If CoresPerNumaNode is set and non-zero, set vm.Config.NumaInfo = &types.VirtualMachineVirtualNumaInfo{CoresPerNumaNode: spec.VirtualNuma.CoresPerNumaNode, AutoCoresPerNumaNode: types.NewBool(false)}.
  • If CoresPerNumaNode == 0, clear the override (NumaInfo = nil or AutoCoresPerNumaNode: true), matching the documented semantics on VirtualMachineVirtualNuma.CoresPerNumaNode ("If set to be zero, it clears any manual override and autosize vNUMA node").

This would make config.numaInfo observable immediately after Reconfigure, matching real vSphere's behavior, and let vcsim-based tests exercise reconcile loops that depend on this field converging.

Describe alternatives you've considered

  • Working around this entirely in the consuming project's tests (e.g. dropping vNUMA-topology assertions from vcsim-based tests, or reaching into the simulator's model directly via Map.Handler/Map.Get to patch config.numaInfo after Reconfigure). This avoids touching vcsim but has to be re-applied by every test that touches this field, and doesn't help anyone else hitting the same gap.
  • Leaving differs()-style convergence checks in consuming controllers to stop trusting live NumaInfo and instead track "last applied" state themselves (e.g. via an annotation). Rejected for our use case specifically because a controller that stops relying on live vSphere state to detect convergence can't tell a real silent rejection by vSphere apart from a successful apply — it would mask genuine reconfigure failures, not just work around a test-environment gap.

Additional context

The VirtualMachineVirtualNuma and VirtualMachineVirtualNumaInfo types are gated to API version 8.0.0.1 (vim:"8.0.0.1" in vim25/types/types.go), consistent with vSphere 8.0 Update 1+. Hardware version requirement observed/enforced on the consuming side is vmx-20+.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions