harvester-ui-extension PR 1175 (abonillabeeche), skip the restart prompt when only a NIC's network changes, at 9499c335, reviewed 2026-11-06. Alejandro asked for this round after running it end to end on v1.10.0-rc1.
Preview:harvesterpr1175m1206r.13.48.147.135.sslip.io, built from 9499c335 merged with PR 1206 (7554cedf), backend Harvester .105 (v1.8.0-rc5, PCI add-on on). Also: the PR alone, and the shared main preview rebuilt today from 73eaccc2.
Verdict: approve once PR 1206 merges, two small points to raise now
The feature works. With 1206 merged in, a network-only change on a running, migratable VM saved with no dialog, 3 of 3, and on every affinity shape I tried.
It still needs 1206. With the PCI add-on on, the PR alone showed the dialog 3 of 3. You re-approved 1206 on 11-03, and it's open and mergeable.
To raise: the banner text now promises no restart even when the save will ask for one (card 1), and a new prop was added to two tabs that don't use it (card 2). Neither blocks.
Your call: a save with no changes on a VLAN VM still asks for a restart. It's the same on main, but the cause is the one this PR just handled for network changes (card 3). Separately, your silent-save thread has an answer waiting (card 4).
Copilot's two comments on the new affinity code don't need a change (card 5).
Not checked by me: the real migration. We have no v1.10 cluster, so that part rests on Alejandro's run on v1.10.0-rc1.
Nothing is posted. Suggested text is at the bottom.
Test it yourself
These previews won't show the feature on their own. Our Harvesters run v1.8 and v1.9, so the flag is off, and they're single-node, so no VM has the Migrate action. All the results below come from a Playwright run that changes the responses in the browser: the server version, the extra NICs, the Migrate action, two extra networks and the affinity. Every save stays in the browser.
Don't save on these previews. They talk to the real .105 with real writes, and a save on main stores hostDevices: [] on the VM. What you can check by hand without saving: open the bar's PR + 1206 link and look at the Filesystem tab in DevTools for the stray attribute in card 2. To run a scenario from the tables, ask me: the harness takes a scenario name and a preview, and leaves the VM alone.
Round 2, then and now
Round 2
Alejandro
Checked now
Nit: the banner also shows on stopped VMs and VMs that can't migrate, where the save still asks for a restart
Fixed: banner and save share a new canLiveUpdateNADRef getter. He also dropped "otherwise it takes effect after a restart" from the text.
Works. No Migrate action: no banner, dialog. Stopped VM with its real actions: no banner, no dialog. The dropped sentence is what causes card 1.
After a silent save nothing tells the user, and the guest usually keeps its old IP
"The operator's responsibility": a deliberate change, and the banner covers it
Open thread, your call (card 4)
Blocker moved to PR 1206: the tabs write hostDevices: []
1206 is a listed dependency
Still needed, see below. You approved 1206 at 7554cedf; not merged yet.
The rest of the code is unchanged since round 2. New commits: the shared getter, tests for the restart prompt, and 9499c335 for the affinity.
What's new: the affinity fix
Alejandro's v1.10 run found a second cause of the dialog. When the Node Scheduling form opens, it adds empty placeholders straight onto a VM's existing nodeAffinity: preferredDuringScheduling…: [], or an empty required if the VM only has preferred rules. Every VM on a VLAN network has a nodeAffinity, so a network change looked like a second change. 9499c335 ignores those empty terms when deciding whether only the network changed.
Read in the shell code and confirmed in the saved request: the fix is right. It's in the PR's own code path only, which is what card 3 is about.
Bridge to bridge on a running VLAN VM: the banner shows, and the save goes through with no dialog.
Dialog on a bridge to bridge change, PCI add-on on, tabs loaded
Build
Restart dialog
hostDevices in the save
main
Yes
[]
PR alone
Yes, 3 of 3
[]
PR alone, device lists held back
No
Not sent
PR + 1206
No, 0 of 3
Not sent
The third row shows the dialog on the second row comes from the device tabs, not the network logic. A word on timing: my first runs waited a fixed 8 s, and on a slow load they saved before the lists arrived, so the PR alone looked fine. The harness now waits for the PCI and USB responses, and these numbers come from that version.
Every case, on PR + 1206
Edit, on a running VM unless noted
Banner
Dialog
Right?
Bridge to bridge, VLAN VM (required rule)
Yes
No
Yes, 3 of 3
Same, with no affinity, affinity: {}, preferred only, required + preferred, pod anti-affinity only, required + anti-affinity
Yes
No
Yes, all six
Same, network name without a namespace, in the forklift namespace
Yes
No
Yes
Bridge to overlay
No
Yes
Yes
VM without the Migrate action
No
Yes
Yes
Stopped VM, real actions
No
No
Yes
Server v1.9.1, flag off
No
Yes
Yes, unchanged
Remove the first NIC, next NIC untouched
No
Not saved
Yes, the round 1 row-key bug stays fixed
Network + CPU Network + a new NIC Two NICs, one to a bridge and one to an overlay
Yes
Yes
Dialog right, banner wrong: card 1
VLAN VM, no changes VLAN VM, network changed and changed back
No
Yes
Same on main: card 3
VM with no node affinity, no changes
No
No
Yes
Jest: 122 passed on the PR's touched suites. 185 passed on a wider set against the merged code. The 1 skipped test is older than this PR. CI is green.
Findings
1
The banner promises no restart, then the save asks for one
pkg/harvester/l10n/en-us.yaml:872
Suggestion
The text used to be conditional. After our round 2 nit it became "The virtual machine is live-migrated to apply the network change without a restart." The banner only looks at this NIC, so it stays up when something else in the same edit forces a restart: another field, a new NIC, or another NIC moving to an overlay.
So the screen says "without a restart" with a restart dialog on top of it. The dialog is correct. His own Cypress case 2 goes through this path.
Network + CPU changed: the banner says "without a restart" behind the restart dialog.
Suggested fix
One short clause in the text, along the lines of "if this is the only change". The banner logic doesn't need to change, and I wouldn't ask for it to track the whole form.
2
The new prop was also added to the Filesystem and Sysprep tabs
Only the Networks tab uses canLiveUpdateNADRef. Neither of the other two components declares it, so Vue puts it on their root element. I saw can-live-update-n-a-d-ref on div.vm-filesystem in the page. Sysprep needs a Windows VM, so that one is from the code only. It has no effect on behaviour, and the fix is deleting the two lines. It looks like a slip from the line above, since all three follow :namespace.
3
A save with no changes on a VLAN VM still asks for a restart
Same placeholder, same symptom as 1206, on the path that 9499c335 doesn't cover: specChanged is computed before the cleanup, and the cleanup only runs inside isNADOnlyChange. Changing the network and then changing it back hits this too.
Same on main (dialog with the device lists held back, so it isn't hostDevices), so it isn't this PR's bug. I'm raising it because it undercuts what 1206 set out to do: every VM on a VLAN network keeps the empty-save prompt after both PRs merge.
VLAN VM, nothing changed: Save still opens the restart dialog. Main does the same.
Simplest fix, if you want it
Apply the cleanup before specChanged is computed, so both paths compare the same thing. That's one call site moved, not new logic. I haven't built this. It's in the suggested text as optional, so drop it if you'd rather keep the PR focused or raise it separately.
4
Your silent-save thread: I would accept his answer and resolve it
His argument holds: moving a VM to another VLAN is deliberate, and forcing a restart would take away the common case where the subnet is the same. The banner mentions the DHCP renew before the save.
One small gap, not worth a comment on its own: his reply says the banner tells people the guest isn't notified and may need a restart. The text only says it "may need to renew its DHCP lease".
5
Copilot's two comments don't need a change
pkg/harvester/utils/vm.js:98, 103
FYI
High: "an empty required selector is a real scheduling change". That empty value is exactly the placeholder the form adds to a VM with only preferred rules; I saw it in the saved request. In a server dry run on .105, the API accepted it and left it out of the result, so nothing stored changes. This was v1.8.0-rc5, not v1.10.
Medium: "affinity: {} left behind causes an extra prompt". It's reachable but rare: a VM with no affinity key at all, where someone also picks "scheduling rules" without adding a rule. All 9 VMs on .105 have the key. And it fails safe: one extra dialog.
These threads are Alejandro's to close, so I left them out of the suggested text.
6
Other things worth knowing
not in the suggested text
FYI
Backend PR 11770 is still open. It adds the duplicate-MAC check for network-only updates. The gap exists without the UI change, but this PR makes that edit one click. Not a UI blocker. Alejandro has asked rrajendran17 to look.
Moving across cluster networks: you dropped this question in round 1, so I didn't raise it again. The issue now documents that it needs a target node with the new cluster network.
Screenshots: the description says they're in a comment below, and his comment says "Screenshots follow", but none are on the PR yet.
Unrelated bug on main: Edit Config is a blank form for a VM with domain.resources: {}, like default/forklift-vm-1 on .105. It throws reading memory at mixins/harvester-vm/index.js:369. I didn't look further.
What I didn't check, and what I did on the backends
Not run by me: the live migration, the MAC staying the same, the new network showing up on the VM, and RestartRequired staying off. These need v1.10 and more than one node. Alejandro reports them on a 3-node v1.10.0-rc1, and his Cypress PR 76 and robot PR 3038 cover them.
Faked in the browser: server version, extra NICs, Migrate action, affinity, and the networks harvester-public/2012, 2013, ovn-1 and the two in forklift. The PCI add-on, the device lists and andy itself were real.
Writes: none reached Harvester from the tests. VM and secret saves were answered in the browser, and everything else was aborted. Separately I sent one server-side dry run through the Kubernetes API on the stopped forklift-vm-small. Its resourceVersion read back unchanged.
Left running on mf: previews pr1175, pr1175m1206 and upstream-main, with their package servers, in harvester-preview.
Suggested review
Comment now, Approve after 1206 merges. Short intro, with each point inline. Screenshots get uploaded when you ask for the pending review. No preview link and no code, as usual.
Body
Thanks for the end to end run. The affinity fix and the banner fix both work. With PR 1206 merged in I get no dialog on a network-only save, so I'll approve once that one is in. A few small points inline, none blocking.
en-us.yaml:872
Since this no longer has a condition, it now promises no restart even when the save asks for one: another field changed in the same edit, a new NIC, or a second NIC moved to an overlay network. Your Cypress case 2 goes through this. Could the text say it applies when the network is the only change?
[screenshot: banner and restart dialog together]
index.vue:1010 (same on 1206)
Filesystem and WindowsSysprep don't have this prop, so it ends up as an attribute on their root element. Only the Networks tab needs it.
Optional: index.vue:533
Not from this PR, since main does the same: a save with no changes on a VM on a VLAN network still asks for a restart, from the same empty affinity terms. Changing the network and changing it back hits it too. Would it make sense to do the cleanup before this comparison instead of only in isNADOnlyChange? Then both cases are covered. Fine as a follow-up if you'd rather keep this PR focused.
[screenshot: restart dialog on a VM with no changes]
Your silent-save thread
Resolve without a reply, if you agree with card 4.