Skip to content

feat(server): report SerialNumber, UUID, Manufacturer and Model on the ComputerSystem - #41

Open
itayherzberg wants to merge 9 commits into
kubevirt:mainfrom
team-redbull:system-identity-fields
Open

itayherzberg wants to merge 9 commits into
kubevirt:mainfrom
team-redbull:system-identity-fields

Conversation

@itayherzberg

@itayherzberg itayherzberg commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

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

Related: #42 reports the node a running VM is scheduled on (Oem.KubeVirt.NodeName), also on top of #25 and independent of this one.

Problem

A Redfish client that inventories machines tells one machine from another by SerialNumber and UUID, and shows Manufacturer and Model. A KubeVirt ComputerSystem has none of the four, so the only stable handle a client gets is the System Id. That handle changes when the VM is renamed or system_id_convention changes, and under legacy two chassis can serve VMs with the same Id.

Fix

GET /redfish/v1/Systems/{id}, and the response to a boot-device PATCH, now carry:

Property Source, first non-empty wins
Manufacturer always "KubeVirt" (not read from the cluster)
SerialNumber running VMI spec.domain.firmware.serial, then the VM template's
UUID running VMI spec.domain.firmware.uuid, then the VM template's, then the VM's metadata.uid
Model running VMI spec.domain.machine.type (the QEMU machine type), then the VM template's

The read is GetVMIdentity in pkg/kubevirt/devices.go, built like GetVMCPUTopology: GetVM, then getRunningVMI and effectiveSpec.

If the VM or the VMI cannot be read, the three read properties are left out (omitempty) and the System still answers 200. A VMI read error does not fall back to the template, for the same reason as in #25: the staged spec may not be what is running.

The two ComputerSystem literals in server.go (GET and the boot PATCH response) are replaced by one buildComputerSystem, so the two cannot drift.

What a cluster reports

On OpenShift Virtualization 4.22.12 and 4.20.27, KubeVirt writes a random firmware.serial, a random firmware.uuid and the default machine type (pc-q35-rhel9.x) into the VM template within seconds of creation. That includes a Halted VM that declared none, so every VM has all four, and they survive restarts. A VM deleted and recreated from the same manifest gets a new serial and UUID. The metadata.uid fallback is for a template without firmware.uuid.

Tests

TestSystemIdentity in pkg/server/system_devices_test.go:

  • declared values are reported;
  • a running VMI wins over the template;
  • a field the VMI leaves unset falls back to the template;
  • with no firmware block, UUID is metadata.uid and there is no SerialNumber key;
  • an unreadable VMI leaves the keys out and still answers 200;
  • the boot PATCH response carries them too.

go vet ./... and go test ./... pass.

Base

Branch system-identity-fields (3cd0695) is one commit on #25's head 05be86f, which is rebased onto main (2e38e46, after #34). gofmt, go mod tidy, go vet and go test ./... pass. go test -race fails in connection_pool.go, memory_monitor.go and job_scheduler.go exactly as it does on main; TestSystemIdentity and TestSystemDevices are clean under -race.

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

[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 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>
…e ComputerSystem

A Redfish client that inventories machines recognises the same machine
across reads by its serial number and UUID, and shows its maker and
model. The ComputerSystem had none of them, so a VM could only be
recognised by its System Id, which changes when the VM is renamed or
when system_id_convention changes.

GET /redfish/v1/Systems/{id}, and the response to a boot-device PATCH,
now carry:

- Manufacturer: always "KubeVirt".
- SerialNumber: spec.domain.firmware.serial.
- UUID: spec.domain.firmware.uuid, else the VM's metadata.uid, so a
  stopped VM still has a stable UUID.
- Model: spec.domain.machine.type (the QEMU machine type).

Each is read from the running VMI first and the VM template second
(GetVMIdentity, built like GetVMCPUTopology on getRunningVMI and
effectiveSpec). If the VM or the VMI cannot be read, the three read
properties are left out and the System still answers 200; a VMI read
error does not fall back to the template, whose staged values may not
be what is running.

KubeVirt writes a random firmware serial and uuid and the default
machine type into the VM template within seconds of creation, Halted
VMs included, so on a current cluster every VM has all four.

Both ComputerSystem literals in server.go (GET and the boot PATCH
response) are replaced by one buildComputerSystem.

Depends on kubevirt#25 (getRunningVMI, effectiveSpec, processorFields).

Signed-off-by: itayherzberg <itayherzberg@gmail.com>
@itayherzberg
itayherzberg force-pushed the system-identity-fields branch from 3cd0695 to c89ba9d Compare November 12, 2026 18:33
@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