Skip to content

feat(servers): retry a failed install - #171

Merged
ericwang401 merged 4 commits into
4.xfrom
feat/retry-failed-install
Oct 16, 2026
Merged

ericwang401 merged 4 commits into
4.xfrom
feat/retry-failed-install

Conversation

@ericwang401

@ericwang401 ericwang401 commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Until now a failed install was a dead end. Users saw "Install failed. Please contact your administrator.", and the API refused every settings route with 409.

Changes

  • Retry from the install-failed screen. The screen now shows the reinstall form: pick a template, set a new OS password, and choose whether to start after install. AuthenticateServerAccess lets install_failed servers reach only the template list and reinstall routes. Suspended servers and other states still get 409.
  • Fix: reinstalling a server that has no VM. Reinstall always stopped and deleted the old VM first. When the failed install never created a VM, Proxmox answered "does not exist" and the reinstall failed every time. It now skips straight to the build in that case.
  • Fix: failed retries stuck on "Installing". The chain's failure handler updated the server through the copy captured when the chain was dispatched. On a retry that copy already read install_failed, so Eloquent saw no change and skipped the write. It now updates by ID.
  • Installing and restoring screens update by themselves. "Installing", "Restoring Backup" and "Restoring Snapshot" used to stay put until the page was refreshed. The page now re-fetches the server every 5s while it's in one of those states, and moves on once the work is done. The icon turns slowly to show it's live (2s per turn; off for reduced motion).

Testing

  • Pest: covers the missing-VM chain, the stale-status failure handler (using serializeAndRestore(), which serializes jobs the way the real queue does), and that blocked states stay blocked. The two bug tests fail on the old code.
  • Playwright: a new spec against a seeded install_failed server. It fails on the old UI. It also fakes the install finishing and expects the page to leave "Installing" without a reload, which fails without the polling.
  • Real Proxmox node: retried a server whose VM was never created; it installed in about 20 seconds. Reinstalling a working server through the UI was also re-tested.

Notes

Two problems surfaced by reinstalling a server whose install had failed:

- rebuild() always stopped and deleted the old VM first. When the failed
  install died before or during the clone there is no VM, Proxmox answers
  the stop with "does not exist", and the chain fails every time. It now
  skips straight to the build when isVmDeleted() says the VM is gone. If
  that check is wrong because the VM does exist, the clone refuses the
  VMID and nothing is lost.

- The chain's catch wrote install_failed through the server captured at
  dispatch. That copy is serialized with the chain, and when it already
  read install_failed -- a retry starts from exactly that -- Eloquent saw
  nothing dirty and skipped the write, leaving the server on "installing"
  forever. It now updates by ID.
A failed install was a dead end: the client showed "contact your
administrator" and the API refused every settings route with 409.

The screen now carries the reinstall form (template, a new OS password,
start after install), and AuthenticateServerAccess lets install_failed
servers through to the two routes it needs -- the template list and
reinstall. Any other blocked state, like suspended, still gets 409.
ReinstallServerCard takes an optional title, description and button label
so the same form serves both places.

Tested with Pest (the missing-VM chain, the stale-status catch, and that
other states stay blocked), a Playwright spec against a seeded
install_failed server, and a real retry on a Proxmox node of a server
whose VM was never created.
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Contributor License Agreement

All identified human contributors have signed the current CLA.

The "Installing", "Restoring Backup" and "Restoring Snapshot" screens only
ever change when a queued job finishes, but nothing told the page: it
stayed on the screen until the user refreshed. ServerRouter now re-fetches
the server every 5s while it's in one of those states, so the screen moves
on as soon as the work is done -- including straight after retrying a
failed install. A failed poll is simply retried on the next tick.

ScreenBlock takes a `spin` flag, used by those three screens, that turns
the icon slowly (2s per turn, off for reduced motion) to show it's live.
The icon's border box moves to a wrapper so only the glyph turns.

The retry e2e spec now fakes the install finishing and expects the page to
leave "Installing" without a reload; it fails without the polling.
@ericwang401
ericwang401 merged commit d913d0a into 4.x Oct 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant