Skip to content

feat(server): report the node a running VM is scheduled on as Oem.KubeVirt.NodeName - #42

Open
itayherzberg wants to merge 9 commits into
kubevirt:mainfrom
team-redbull:system-node-name
Open

itayherzberg wants to merge 9 commits into
kubevirt:mainfrom
team-redbull:system-node-name

Conversation

@itayherzberg

Copy link
Copy Markdown
Contributor

Depends on #25 (it builds on getRunningVMI, processorFields and Oem.KubeVirt.Processors). Until #25 merges, this diff also shows #25's 8 commits: only the last commit, a90e725, is this PR. I will rebase it as soon as #25 is in.

It is independent of #41 (the ComputerSystem identity fields): either can merge first, and the second gets a small server.go rebase.

Problem

An inventory that holds both the VMs behind this API and the nodes they run on cannot link the two: nothing in the ComputerSystem says where the VM runs. A client that wants the physical CPU, rack or health of the host behind a VM has to query the Kubernetes API with credentials of its own, which a Redfish client usually does not have.

KubeVirt's own answer to "which CPU does this VM get" does not help. domain.cpu.model is often a mode (host-model), not a model, and the node's host-model-cpu.node.kubevirt.io/<family> label gives only a family. Under software emulation that family is wrong: an Intel Xeon node was labelled EPYC.

Fix

GET /redfish/v1/Systems/{id}, and the response to a boot-device PATCH, carry Oem.KubeVirt.NodeName: the running VMI's status.nodeName.

  • It is omitted when the VM is not running: no VMI, or a VMI in a final phase, the same rule getRunningVMI applies everywhere else.
  • It is also omitted when the VMI cannot be read, logged as an error; the System still answers 200.
  • Redfish has no standard property for the host of a virtual ComputerSystem (Links covers chassis, managers and composition), so it sits next to the existing Oem.KubeVirt.Processors.

Oem.KubeVirt.Processors becomes a pointer (OemProcessors), so an Oem that carries only the node name does not report a 0x0x0 vCPU layout. Its JSON is unchanged whenever the topology is read.

Example, running VM:

"Oem": {
  "KubeVirt": {
    "Processors": { "Sockets": 1, "CoresPerSocket": 2, "ThreadsPerCore": 1 },
    "NodeName": "worker-3"
  }
}

Things to know

  • Who can see it: every Redfish user who can see the VM's chassis. It is a Kubernetes node name, not an address or a credential.
  • It changes: a live migration changes it, and a client polling it sees the node at the time of the request.
  • Cost: none extra; it reuses the VMI read processorFields and the other sub-resources already make.

Tests

TestSystemNodeName in pkg/server/system_devices_test.go:

  • a running VMI reports its node next to the vCPU layout;
  • a stopped VM has no NodeName but keeps the layout;
  • a Succeeded VMI reports none;
  • an unreadable VMI leaves it out and still answers 200.

Branch system-node-name (a90e725) is one commit on #25's head 05be86f. go vet ./... and go test ./... pass. go test -race fails only in connection_pool.go, memory_monitor.go and job_scheduler.go, exactly as on main; TestSystemNodeName is clean under -race.

Verification on a cluster

OpenShift Virtualization 4.20.27, three cirros VMs (two running, one Halted), the controller built from a branch that carries this change on top of #25 and #29-#39. NodeName equalled oc get vmi -o jsonpath='{.status.nodeName}' for both running VMs (ip-10-0-28-121.us-east-2.compute.internal) and was absent for the halted one.

@kubevirt-prow kubevirt-prow Bot added the dco-signoff: yes Indicates the PR's author has DCO signed all their commits. label Nov 9, 2026
@kubevirt-prow

kubevirt-prow Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign marsik for approval. For more information see the 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

@kubevirt-prow
kubevirt-prow Bot requested review from MarSik and yanirq November 9, 2026 06:18
@kubevirt-prow

kubevirt-prow Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Hi @itayherzberg. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

TomerKarniol and others added 9 commits November 12, 2026 20:31
ComputerSystem advertised Storage and EthernetInterfaces links, but
requests to them fell through to the system handler and returned the
parent resource. Memory had the same problem.

Add collection and member resources for Memory, Processors, Storage
(with drives) and EthernetInterfaces, built from the VM spec. Compute
ProcessorSummary from sockets x cores x threads instead of cores only,
and stop reporting made-up defaults when the VM does not declare memory.

Note: ComputerSystem.Memory is now a link and the memory total moves to
MemorySummary, matching the Redfish schema.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
Processors had no architecture, so clients such as sushy/Ironic reported
the architecture as unknown. Map spec.architecture (unset means amd64,
the KubeVirt default) to ProcessorArchitecture and InstructionSet:
amd64 -> x86 / x86-64 and arm64 -> ARM / ARM-A64. Other architectures
are omitted rather than guessed.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
When a VM declares no spec.architecture, leave ProcessorArchitecture and
InstructionSet out instead of assuming amd64. KubeVirt's real default is
the cluster's configured architecture, so a hardcoded amd64 would be
wrong on an arm64 cluster. KubeVirt normally fills the field in on
creation, so the common case is unchanged.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
…hardware

Follow-up fixes found while testing the Memory, Processors, Storage and
EthernetInterfaces resources on OpenShift Virtualization and reviewing
the change.

Cost:
- Read the size of one drive per request instead of one PVC per disk.
  GetVMDisks now returns names and bus only; GetVMDisk resolves a single
  size. A 24-disk VM went from about 4.7s to about 0.5s per request.

Errors that were hidden:
- A PVC that cannot be read for a reason other than NotFound (forbidden,
  timeout) is now an error (HTTP 500) instead of a size taken from the
  DataVolume template.
- A VMI that cannot be read for a reason other than NotFound is now an
  error instead of reporting NoLink for a VM that may be running. The
  test mock returns a typed NotFound like the real API.
- If the CPU topology cannot be read, ProcessorSummary and Oem are left
  out instead of showing a guessed 1/1/1. GetVMCPUTopology returns the
  zero value on error, and the now unused GetVMCPU is removed.

Schema:
- Declare versions that define what is emitted, checked with the DMTF
  Redfish Service Validator: ComputerSystem v1_15_0, Memory v1_1_0,
  EthernetInterface v1_1_0 and VirtualMedia v1_2_0.
- ProcessorSummary has no Oem property in any schema version, so the
  vCPU layout moves to the system-level Oem.
- Add IPv6Addresses next to IPv4Addresses.
- A zero-sized emptyDisk reports no capacity. Remove the unused
  Drive.MediaType and EthernetInterface.Description fields.

Tests cover forbidden/timeout/not-found for PVC and VMI reads, the PVC
lookup count for a 24-disk VM, users without access to the chassis, a
running NIC with IPv4 and IPv6, empty VMs, and the schema versions.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
Update the single-system example to the current ComputerSystem shape
(MemorySummary and Memory link, Processors link, ProcessorSummary counts,
system-level Oem) and add a section with real responses for Processors,
Memory, a Drive and an EthernetInterface.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
The VM spec holds the staged values; the VMI is what the guest is running.
Reviewing the Processors and Memory resources raised the question whether
hotplug and not-yet-applied edits are accounted for. They were not: every
value came from the VM spec.

A running VM now reports its VMI, a stopped VM its VM spec:
- CPU: status.currentCPUTopology, then the VMI spec, then the VM spec.
- Memory: status.memory.guestCurrent, then the VMI spec, then the VM spec.
- Architecture: the VMI spec, then the VM spec.
- Disks and NICs: the VMI spec, then the VM spec. A volume hot-plugged
  without --persist is listed, one only staged in the VM is not.
- NICs report the operational linkState (up/down) the VMI gives.

Only "VMI not found" and a VMI in a final phase (Succeeded/Failed, which
KubeVirt can leave behind after a shutdown) count as stopped. Any other
failure to read the VMI is returned, so a running VM is never shown with
its staged values. GetVMNICs shares the same helper.

Tests cover VMI over VM for each value, hotplug status, nil status fields,
final-phase VMIs, hot-plugged disks, link state and VMI read errors.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
Routing:
- handleSystem sent every PATCH under /Systems/{id}/... to the boot update
  handler before looking at the path, so PATCH /Systems/vm-1/Memory/1 was
  treated as a boot update and answered 200 instead of 405. The hardware
  resources (Memory, Processors, Storage, EthernetInterfaces) are now
  routed first.
- The Reset action was matched with strings.Contains, so POST
  /Systems/vm-1/Memory/1/Actions/ComputerSystem.Reset reached the power
  handler. Only /Systems/{id}/Actions/ComputerSystem.Reset matches now.

NICs:
- A NIC the VMI reports as linkState "down" is NoLink. A running NIC with
  no reported state is still LinkUp.

Tests and review follow-ups:
- 405 with Allow: GET for POST/PATCH/PUT/DELETE (with a boot body) on every
  hardware path, and the Reset action under them.
- A VMI that cannot be read gives 500 on every hardware endpoint.
- Asymmetric topologies (3x2x1, 1x3x4), hotplug status over the VMI spec,
  VMI over VM for storage and NICs, final-phase VMIs, odd member paths.
- Test helper comments explain that the VMI is not derived from the VM and
  why a controller RBAC failure is a 500 and not a 403.
- Document the VMI-first rule and the link state.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
handleSystem now validates the method and resolves the VM with its access
check for Memory, Processors, Storage and EthernetInterfaces, then hands
the resolved namespace and VM name to handleSystemDevices. The handler no
longer repeats the check itself.

The method check still comes first, so non-GET requests keep answering 405
with Allow: GET. The power, boot and virtual media handlers are unchanged.

Signed-off-by: Tomer Karniol <tomer.karniol@gmail.com>
…eVirt.NodeName

An inventory that holds both the VMs behind this API and the nodes they
run on cannot link the two: nothing in the ComputerSystem says where
the VM runs. Tooling that wants the physical CPU, the rack or the
health of the host behind a VM has to go to the Kubernetes API with
its own credentials, which a Redfish client usually does not have.

GET /redfish/v1/Systems/{id}, and the response to a boot-device PATCH,
now carry Oem.KubeVirt.NodeName: the running VMI's status.nodeName. It
is omitted when the VM is not running (no VMI, or a VMI in a final
phase) and when the VMI cannot be read; the System still answers 200.
Redfish has no standard property for the host of a virtual
ComputerSystem, so it sits next to the existing Oem.KubeVirt.Processors.

Oem.KubeVirt.Processors becomes a pointer (OemProcessors), so an Oem
that carries only the node name does not report a 0x0x0 vCPU layout.
Its JSON is unchanged whenever the topology is read.

The node name is visible to every Redfish user who can see the VM's
chassis. It names a Kubernetes node, not an address or a credential.

Depends on kubevirt#25 (getRunningVMI, processorFields, Oem.KubeVirt.Processors).

Signed-off-by: itayherzberg <itayherzberg@gmail.com>
@kubevirt-prow kubevirt-prow Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has DCO signed all their commits. size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants