The buttons of the VM page's section bar and of the Settings bar under it
sat at the start of the row and left its end empty. Both bars now share
the whole row out among their buttons (Bootstrap's nav-fill), also when
they wrap on a narrow screen.
A template's page was a VM's: it opened on Power, with only a note there
that a template is not started, while its clone form waited in a section
of Settings, next to a console, access, snapshots and stats that a VM
that never runs has no use for. A template's page now carries a Template
badge and a Clone button, opens on the clone form, and leaves out Power,
Access, Snapshot, Stats, the console settings, host devices and the
guest agent and address lines; Resize, Settings and Destroy stay for
whoever may change it. A page that no section opens shows its first.
A VM made from a template came out at the template's size and shut off,
and was then resized and started by hand. The Clone tab now asks for the
clone's vCPUs and memory, filled in with the VM's, and whether to start
it. After the copy, before the clone is recorded, it is resized with the
Resize tab's own functions and started; a step that fails is a warning
of the job, and the clone stays. The quota counts the larger of the size
asked and the VM's, so a resize that fails leaves the clone at a size it
allowed.
When the job ends the page opens the clone's, not the cloned VM's again:
a template's page, shut off, read as a clone that had not started. An
outcome kept for a warning links to it.
A libvirtError made in a test takes the message of the thread's last real
libvirt error: in a live run, after another test's closed connection,
"no marker" read "client socket is closed" and the test failed. It now
checks that the move raised that very error, as the test after it does.
A VM list showed what it read when it was loaded: a VM stopped from
inside its guest or with virsh, or made or removed elsewhere, showed only
after a reload, unlike the VM page, which reloads when its VM's state
changes. The lists of all VMs and of one host's VMs now poll the states
of their VMs, at once and then every 5 s as the VM page does, and reload
when an answer differs from the one before. The states come from one
libvirt call per host; a user who does not see hosts gets only their own
VMs. The page in use (a dialog, a field, an unsaved XML edit, a job
outcome shown) holds the reload until it is free; that check is shared
with the job panel.
Since VM creation, clones, migrations and uploads run as jobs, the page
came back before they ended and the job panel then showed the outcome
with a Refresh button: a new VM, for one, showed only after a click. A
job of the page that succeeds without a warning now reloads the page,
which shows what it changed. The outcome box stays, with Refresh, for a
job that failed or warned, and when a reload would lose something: a
dialog open, a field in use, an XML edit not saved, or another job still
running, shown or awaited. A remembered job is taken when the page
renders, so the reload does not see it again.
Without a migration address libvirt sends a migrating VM to the
destination's own host name, which the source host often cannot resolve:
a live migration to a host added without one failed ("Unable to resolve
address ..."), also when the other host had one. The destination's
address on the Computes page, which the panel reaches it at, is now the
default; the migration address stays for another network. A host the
panel reaches on its loopback keeps libvirt's default.
A live migration whose source host could not resolve the destination's
name for the migration stream failed with "The host of this virtual
machine cannot be reached right now": libvirt reports that failure as a
connection error, and a job's error hides those behind that sentence so
as not to name hosts. Only superusers migrate, so the migration job now
fails with libvirt's own words, here "Unable to resolve address ...",
which points at the destination's Migration address.
The Migrate tab shows a running VM's live migration switch, on by
default. A VM shut down after the tab opened, as one is to move it shut
off, was then refused: "A shut-off VM cannot be migrated live". A
shut-off VM now moves offline whatever the request says about live, as
the tab tells for a shut-off VM; the tuning options are for a running VM
only, as before. An offline request for a running or paused VM is still
refused.
A shut-off VM with TPM state, as every Windows 11 VM, was refused for
migration: the state is a file of the source host, and an offline move
would start it there with a new TPM. Such a VM now migrates as a shut-off
VM with disks to copy does: its UEFI variables are copied, it is started
paused, its CPUs never run, migrates live, which carries the TPM state,
and is shut off on the destination. A shut-off VM with a saved state is
refused before any of that, for every way it moves: started paused, it
would resume and then lose the saved memory.
The clone tab says that a clone gets a new, empty TPM, and the destroy
page that the TPM state goes with the VM.
A VM made without a TPM, a Windows 10 to be upgraded to Windows 11, had
no way to get one but the XML editor. The Options tab has a TPM 2.0
switch, as the RNG one: it adds an emulated TPM of the host's model to
the definition for the next start, or removes it. Its state stays on the
host until the VM is undefined, so a TPM added again has it back. A TPM
the switch did not make (passthrough, 1.2, encrypted, with its own state
path) is left to the XML editor, and a host without swtpm says so.
A running VM got its new CD-ROM on SCSI, the one bus the panel could plug
in then, and Windows does not see a virtio-scsi drive before the driver
on that ISO is installed. Add CD-ROM is now a dialog that chooses the bus
and the ISO: a running VM takes USB, first, which every guest sees and
which hot-plugs, or SCSI; a shut-off one SATA (IDE on pc), SCSI or USB.
libvirt has no empty USB drive, so a USB CD-ROM takes its ISO when it is
added and is detached instead of ejected, also while the VM runs.
A USB CD-ROM is a CD drive on QEMU's usb-bot only. Where QEMU has none
(RHEL 9), libvirt took usb-storage, which shows the guest a hard disk
that Windows does not read; the drive now asks for usb-bot, and such a
host refuses it with libvirt's message.
nginx ends a proxied websocket that sends nothing for 60 seconds, and the
VNC console sends nothing while the VM's screen stays the same: an idle
console, an installer's progress screen, closed after a minute and had to
be connected again. novncd now pings the browser every 30 seconds. The SSH
tunnel of an SSH compute sends a keepalive as often, for a firewall on the
way that ends idle connections.
Windows 11 does not install without Secure Boot and a TPM 2.0, and the new
VM form offered neither: its firmware list was BIOS and one UEFI loader
guessed from file names, which on RHEL never matched the Secure Boot one.
The firmware choices are now BIOS, UEFI and UEFI Secure Boot, as the
host's libvirt reports them (its firmware features from libvirt 12.1,
before that its loaders), and libvirt picks the firmware itself: UEFI
without Secure Boot, or with Microsoft's keys enrolled. A TPM 2.0 switch,
shown when the host has swtpm, adds an emulated TPM. The create job
refuses a firmware or a TPM the host does not offer, and the API takes
both. The path-guessing helpers are gone.
A panel on another machine or in a container (the Docker setup, also on
the compute) reaches gstfsd at the compute's address, so most
installations need GSTFSD_BIND_HOST and GSTFSD_ALLOW_REMOTE; the step
named them only in its text. They now come with their own commands,
which replace any earlier lines, so a re-run or a half-set file ends with
the two.
When a VM stopped, its console's stream could end before the worker's
next check saw the VM shut off. The check then found no stream to drop and
said nothing, or, seeing the VM still running, opened the console again,
which libvirt refused, and the session ended. The worker now remembers
whether the VM ran at its last check, and a console that cannot be opened
again because the VM stopped meanwhile is a stop: the terminal says the VM
is not running and the console opens again when it starts. A new stream is
the console's before its callback is registered, which may end it at once.
The live serial test's VM now repeats its BIOS banner (it reboots right
after finding no boot disk), so a console attached late still gets one,
and the test waits for the superuser's console to show it before the VM
stops. A run of the whole live suite over the socket missed the banner of
the paused-then-resumed VM before.
The New pool form asks for the erase confirmation on a logical pool since
the storage pages were redone; the live test's pool request lacked it, so
the pool was never created and both LVM tests failed in setUp.
The Turkish catalog had not been extracted since 2024: of the panel's
1727 messages, 817 were missing and 489 carried old fuzzy guesses, so
most pages, dialogs and messages showed in English, and some fuzzy
guesses said something else.
The catalog is extracted again (obsolete entries dropped) and every
message is translated, the earlier terms kept (Sanal Makine, Sunucu,
Depolama havuzu, Birim, Anlık görüntü), placeholders and markup checked
against the English. The Settings page's names and descriptions come
from the database through migrations that did not mark them for
translation; they are marked now (gettext_noop, the stored values
unchanged), so they are in the catalog too.
Deleting or detaching a disk, deleting a network card, forcing a VM off,
reverting or deleting a snapshot, stopping or deleting a pool, a
network, an interface, a filter or a secret, and the other actions that
ask first opened the browser's yes/no box (confirm()), and the ISO
upload told its mistakes in the browser's alert().
One dialog in the base page now asks for all of them: its title and
confirming button carry the button's own words, its body the button's
question, the confirming button red for a destructive action. Confirmed,
the button is clicked again, so its form sends what it did before. A
button inside another dialog (the flavors) hides that one while asking
and shows it again after; Cancel gives the focus back, and the
confirming button acts once. The ISO upload's mistakes show in its
dialog's error box, announced.
An existing q35 VM whose PCIe root ports are all used takes no new
virtio disk or network device while it runs, and the only way to give
it more was editing its XML.
The Disks tab of a PCIe machine now counts its slots, "PCIe slots: 0
free of 7", in red when none is free, with what its next start will
have when that differs, and Add PCIe slots adds four root ports to its
persistent definition: libvirt numbers and places them, and a running
VM gets them at its next start. The no-slot advice of Add disk and Add
network device points at it.
The Add disk dialog kept Bootstrap's default 500px width when it got
its source cards, so their help and the name's hint broke over two
lines and left gaps between the fields. It now opens large, scrollable
and full screen on a phone, as the New storage pool and New network
dialogs that use the same cards.
On a q35 machine each PCIe device (a virtio disk, a network card) takes
a root port of its own, libvirt makes only as many ports as the VM is
defined with, and a running VM gets no new one: adding a virtio disk to
such a VM failed with libvirt's "No more available PCI slots".
A new q35 VM is now defined with the PCIe root and 14 root ports, as
virt-install makes them: libvirt puts the VM's devices into them and
leaves the rest free for devices added while it runs.
When a running VM has no free slot, Add disk and Add network device say
what to do instead of libvirt's words: for a disk, the scsi bus when
the VM has a SCSI controller (its disks need no slot of their own), or
adding it with the VM shut down, where libvirt makes the port; for a
network device, shutting the VM down. A new volume whose attach was
refused stays in its pool, as before, to attach as an existing volume.
The host pages' dialogs (new network, fixed address, DHCP range,
bandwidth limit, new interface, new filter, filter rule, filter clone,
new storage pool, new secret, a secret's value) and the VM page's XML
review closed with a grey filled Cancel beside their action; the
redone dialogs use an outlined Cancel, so the action is the one filled
button.
A New volume form the pool page refused, for a name with a space or a
character not allowed, redirected back with the reasons at the top of
the page and lost what was typed.
The form now posts to the pool page itself: a valid one makes the
volume and redirects as before, a refused one renders the page with
the dialog open on what was entered, the refused field marked with its
reason and focused. A pool stopped meanwhile has no dialog: its page
shows the reasons. The separate create_volume view and URL go.
The New volume, Clone image and Upload ISO dialogs of a pool set their
labels in a narrow column beside the fields and closed with a grey
Close; Clone image showed the volume's name in red and offered bare
Convert and Metadata boxes, New volume an unlabelled meta_prealloc box.
Now their labels sit above the fields, tied to them: New volume asks
for the name, with what it may hold, then the size and the format side
by side and "Preallocate metadata (qcow2)"; Clone image names the
volume in monospace, asks for the name of the copy and offers "Convert
it to another format", its format and the same preallocation; Upload
ISO asks for the ISO file and says to keep the page open while the
browser sends it. Each closes with Cancel and its action; the posted
fields are unchanged.
The Add disk, Add network device and bandwidth dialogs of the VM page
set their labels in a narrow column beside the fields and closed with
a grey Close: Add disk split "GB" over two lines and offered an
unexplained Metadata box, its existing-volume pool was a dropdown of
links that wrote a hidden field; the network list prefixed every
choice with "Network" or "Interface"; the bandwidth fields asked for
"kilobytes" where libvirt counts KiB/s and KiB.
Now their labels sit above the fields, tied to them, in two columns.
Add disk is one form whose source, New disk or Existing volume, is a
radio card as in the new VM form, the chosen source's fields shown and
sent and its action taken; the size has a GiB suffix and
"Preallocate metadata (qcow2)", the existing volume's pool is a select
that loads its volumes, the bus and the cache are shared. Add network
device picks its
source from Networks and Interfaces groups and says how its MAC is
filled; the bandwidth limit names its units and when a running VM gets
it. Move says when the host has no other pool and is disabled then.
Every dialog closes with Cancel and its action; the posted fields are
unchanged.
An outlined secondary button (Cancel, a row's ⋯ menu, the console and
VM action buttons) takes the theme's secondary colour, which sits near
the page background in many Bootswatch themes: its text was at 1.3:1
in Darkly and Materia, under 3:1 in a dozen others. It now takes the
page's own text colour and a muted border, set on the button itself
because some themes set it there and not through Bootstrap's variable;
its hover and disabled looks stay the theme's.
The disk Edit dialog showed a disk without a serial as "None" in its
Serial box, so saving it untouched gave the disk the serial "None".
The box and the format box are now empty for a missing value.
The dialog also hid most of its nine fields behind three tabs, said
nothing about a running VM, greyed the bus without a reason and its
switch labels did not toggle them. Now one body shows the disk's bus,
format and size under the title; a running VM's note that the changes
apply at its next start; the path and the Read-only and Shareable
switches in a Source card; the four performance modes in a grid; and
the bus, serial and image format folded under Device, with why the bus
is locked and that changing the format does not convert the image.
Cancel is outlined and Save the primary action.
The Edit dialog of a VM's network device selected the listed network
or interface whose name matched the device's source, and the first one
when none did: saving only a new model moved a macvtap device or a
bridge the host's lists did not show onto the first network, a bridge
named like a network became that network, and a macvtap device chosen
again lost its mode.
The dialog now offers the device's own source first, "<name>, as it
is", and posts nothing for it; the view passes no source and the
device's source element is left as it is. Choosing another source
changes it as before.
The Edit dialog of a VM's network device listed its fields in an
order of its own, named the source list "Net Source" with every option
prefixed "Network" or "Interface", said nothing about a running VM and
closed with Close and Apply.
Now it reads like the disk Edit dialog: the device's model and MAC
under the title, a running VM's note that the changes apply at its
next start, the source chosen from Networks and Interfaces groups, the
model and the NWFilter side by side, the MAC in monospace, and Cancel
and Save. The posted fields are unchanged.
The Network tab gave each network device a card with its buttons in a
footer, two cards to a row, as the disks had.
Each device is now a row of the same kind of list as the disks: eth N
with its target, the source, the IPv4 addresses and the link switch,
and Edit, Add QoS and Delete at the row's end; the device details, the
QoS limits and the macvtap note still fold out below it. A row holds
its Edit and Add QoS dialogs, so only rows sit in the list.
The Disks tab gave each disk a card: its capacity in large type, its
pool, its path and its buttons stacked, two cards to a row, so a VM
with a few disks filled the screen.
Each disk is now a row of one list: the device with its bus and format,
the capacity and the space used with a thin bar, the pool and the path,
and Edit, Move, Detach and Delete at the row's end; the device details
still fold out below it. A qcow2 file whose metadata takes it past its
capacity shows a full bar.
The pages many views share were a horizontal form whose Cancel went
back in a primary colour beside a green Save, and a delete question in
a yellow alert squeezed into half the width, which wrapped word by word
on a phone.
Both now sit in a centred column with their heading: the form's fields
with their labels above in a card, Cancel outlined and Save the primary
action; the delete page asks "Delete <name>?" in a card with a red
edge, says what deleting does, and offers Cancel and Delete.
The form for a user's rights on a VM names them as the VM's Users tab
does: Change settings, Delete the VM, and Change console settings,
which only counts together with Change settings.
The host form said "Add Compute" or "Edit Compute" whatever the
connection, set its labels in a narrow column, and on an edit showed an
empty password box as if the password were gone; the migration address
and the gstfsd key sat among the basics with their long help, Cancel
went back in the browser history and Save was green.
Now the heading names the host and the connection type, with the line
the add menu uses for it; a Connection card holds the name, the address,
the login and the password in two columns (SASL login and password for
TCP and TLS, SSH user for SSH) and the description the hosts list
shows; the migration address and the gstfsd key fold under Advanced,
whose summary says what is set, open when one has a value or an error.
A stored password or key says so in its box. Cancel returns to the
hosts list and Save is the primary action.
A superuser's page of a user was a heading, two unlabelled icon buttons
and three tabs: the VMs a table of check columns, the SSH keys a table
that pushed the page sideways on a phone.
Now a card at the top shows the user's name, role, Blocked when they
are, username, email, groups, last login and joining date, with Edit
user and Email OTP QR code as labelled buttons and links to the sections
below with their counts. The VMs card shows each VM with its host and
what the user may do beyond power and console as badges in the VM Users
tab's words (Change settings, Delete the VM, Change console settings),
with Change access and Remove from user in a menu, and Add VM in its
header. The SSH keys and the API tokens are cards; the key rows are now
one include with the user's own Profile, and both lists say when they
are empty. The full key shows over its fingerprint.
The tab script had no page left and goes.
The Profile page was three tabs, each a box inside a box with horizontal
labels: the SSH keys a centred bare row with a grey trash icon, a tall
empty textarea under them, and the user known only by the heading.
Now the user's name, username, role, email and last login head a card
that holds the profile form and the password link; beside it the SSH
keys and the API tokens are cards with their count, a line on what
they are for, one row each with Delete in a menu, and the form to add
one behind a button. Adding or deleting a key returns to #sshkeys.
The token rows are a list-group include that the administrator's view
of a user shares.
The Settings page was one tall column of cards, a label column beside
every field and True/False chosen from a select. Now an index of the
groups stays beside the cards on a wide screen and wraps above them on
a phone; each group lays its fields out in two columns with the label
above; a True/False setting is a switch; each Save names its group.
A switch posts nothing when off, so a hidden False of the same name
comes first and a checked switch's True, posted last, wins: the view
and its was-KEY check stay as they are.
The Jobs list sits in a card: the count and the filters in its header,
the job with its phase, its progress and its date in one cell, the state
at the row's end.
The job page is one card: resource, user and state on top, then the
phase, Cancel and the progress, the error and the results, and a
timeline that says how long the job waited and ran. Resolving an
uncertain job folds into its own card.
The Users, Groups and Removed VMs pages were bare tables: rows of
coloured icon buttons without words, five columns of small checks for
a user's role and permissions, dates broken over three lines and a
lone "+" for a new entry. The owner chose a directory layout from three
rendered options; it follows the host pages' cards:
- Each list is a card with its count and search in the header and one
list-group item per entry, which stacks on a phone without scrolling.
- A user shows their role as a badge (Superuser, Template editor) or
"User", Blocked as a red badge, their groups, a granted clone
permission and live API tokens, and the last login on one line;
role and status are searchable. Edit is the visible action, the menu
holds View profile, Block or Unblock and Delete; Block and Delete
are disabled on one's own account, which the server refuses anyway.
- A group shows its member and permission counts; its name opens it.
The page's title said "Users".
- A removed VM shows its UUID, the host it left, its owners and when
the record was made and expires.
- Logs keep their table in a card, the server search in its header,
the count of matching rows, Done and Failed as badges, and a message
column wide enough to read on a phone.
The user form was one long column of horizontal fields. The owner
rejected three boxed layouts and chose one led by what the user may
do: the Active switch, Template editor and Superuser as two cards,
groups as chips, the user's own permissions as switches each saying
what it allows, then the name and password and the quota folded into
details whose summaries tell their values (-1 as "any"); they open on
a new user and on an error inside them. A refused group or permission
is said beside its field. The group form follows it: the name, what
its members may do, its members as chips. Cancel goes back to the
list instead of the browser history.
The features list still described the panel before jobs, external
snapshots, migration with disk copies, host devices, the serial
console, the address search, the audit log and API tokens; it now
names them. The Updating section gains the behavior changes of the
latest fixes an operator notices: the quota counts next-start values
and queued clones, a non-superuser's clone takes a name the form
offers, deleting a VM's files checks the other computes first, and an
internal snapshot is reverted only on a shut-off VM.
A count or label badge (badge text-bg-light border) kept Bootstrap's
light background but took the theme's light-text colour: white on pale
grey in Darkly and Superhero, white on cyan in Vapor. Such a badge now
takes the page's own text and background colours, which every bundled
theme sets to a readable pair.
gstfsd, the root service on each compute that rewrites a shut-off VM's
/etc/shadow and authorized_keys, did what any client on its port asked.
Now it needs GSTFSD_KEY (64 hexadecimal characters, in the unit's
/etc/default/webvirt-gstfsd) and does not start without it. Each
connection gets a new challenge; the panel signs its request for it
with HMAC-SHA256 and gstfsd checks the signature before any change, so
a request recorded on one connection is refused on another. gstfsd
signs its reply for the same challenge and the panel's nonce, and the
panel accepts only that reply.
Each compute has a gstfsd key, the host's GSTFSD_KEY: the compute forms
and the API take it and never show it, and an empty value on an edit
keeps it. The bootstrap script makes the key file once, readable by
root only; the README shows how to make it and where the panel takes
it. The traffic is still not encrypted: a remote panel's port stays
open to the panel's address only.
The Migrate tab offered every other host alike, and its plan showed
neither a file of the same name in a destination pool nor the disks of
the VM's next start, which the job then refused. Now:
- When the tab opens, the hosts are checked first: one that cannot be
reached, or the VM's own host under another record (the same libvirt
host UUID), is shown with why and cannot be chosen, and the disks of
the first one left are checked. The job refuses the VM's own host
under another name too.
- A pool of the destination that has a file of a disk's name is shown
but cannot be chosen for it; a disk no pool can take refuses the form.
- The next start's file disks the migration does not carry are listed;
one not on storage both hosts share refuses the form, as the job does.
Destroying a VM with its disk files forced it off first and then
worked out which files to delete, so a check that failed left the VM
stopped, and only this host's VMs and volumes were checked: a file on
shared storage that a VM on another host uses was deleted.
The files are now worked out before the VM is stopped: the disks it
runs with and those of its next start, as before with their snapshot
files and seed. A file a VM or volume of another of the panel's hosts
uses at the same path (shared storage is mounted at one path on every
host, as migration needs) is kept like one used here; another record
of the VM's own host is skipped, as there the VM itself uses them. A
host that cannot be read stops the destruction with its name, before
anything is stopped or deleted.
A user's quota counted each VM's running vCPUs, memory and disks, so a
larger value set for the VM's next start was not counted, and a clone
counted only once its VM was recorded, so a user could queue clones
past the quota. Now:
- Each VM counts the larger of its running and its next-start values.
- A clone job counts as one VM with the source's persistent vCPUs,
memory and disk size, which its plan stores, from its admission until
its VM is recorded; a failed, cancelled or resolved job no longer
counts. The clone's VM and its owner are recorded in one transaction,
so the quota counts either the job or the VM, never neither.
- The quota reads each VM's definition once (cached_reads).
A user who is not a superuser chooses the clone's name from the free
names the clone form lists, or gets the first one with automatic names,
but the server took any posted name. It now refuses a name outside the
list, and with automatic names it takes the first free one whatever is
posted. A superuser still names a clone freely.
The panel checks VM names on every compute, but a job held a name only
on its compute, so two clones from VMs on two hosts could take the same
free name at once; a name claim now holds the name everywhere. A clone
job whose name a VM found on a host took while it was queued stops
before it copies anything.
With one owner per VM, the VM page and a user's page counted the VM's
owners and then added one in separate steps, so two owners added at the
same moment both found the VM without one, and it got two. The check
and the insert now run in one transaction that holds the ownership lock
(PostgreSQL's advisory lock; SQLite's IMMEDIATE transactions already
serialize them): the second waits for the first and is refused. The
audit row is written after the transaction, so a failure keeps its row.
The Stats tab stacked one large card per chart, so a VM with a few
devices made a long page, and its "Real Time" and "Logs" sub-tabs were
shown to every user although only a superuser may read the logs. The
owner chose the layout from rendered options: a state line, CPU and
memory side by side, one chart per NIC and disk below, each with its
latest reading next to its title, and a small Graphs/Logs switch for
superusers.
Codex reviewed the tab; this is fixed:
- Memory is shown in MiB (it was labelled MB), and its axis grows to
the RSS when the RSS passes the balloon size instead of clipping it.
- The CPU reading says it is of the host's CPUs.
- A NIC is titled by its MAC, not an invented "eth0", and its readings
are matched to its chart by the MAC: they were matched by position, so
removing a NIC while the page was open moved the next one's readings
into its chart.
- A VM that is not running says nothing is measured.
- The logs load whenever the Logs view is shown, by keyboard too; an
empty answer says "None" and a failed one says so, instead of an
empty table. The tab shows the latest 50 rows, with a link to all of
the VM's rows on the Logs page.
- The VM's header shows memory in MiB; it said MB.
The Destroy tab was a sub-tab with one sentence and a link; its
confirmation page said only "This action is irreversible!" over a
"Remove Instance's data" switch. The tab now shows the state and
"Review destruction". The owner chose the confirmation layout from
three rendered options: the VM and its host, that its definition,
saved state and snapshot records go and that a running VM is forced
off, two plans for the files (delete the disk files, or keep them), the
VM's disks, what is always kept, the NVRAM choice, and Cancel.
Codex reviewed destroying; this is fixed:
- A disk file that cannot be deleted keeps the files below it, which
it needs: they were deleted after it, leaving it broken. The files
are deleted overlays first (split_disk_paths_by_use orders them by
how many files each grows from), and if the files a kept one needs
cannot be read, none of the rest goes. A message names each file
kept so, and a failed deletion says the VM is removed.
The Snapshots tab had three sub-tabs: internal, external and the
lists, with the two kinds side by side as equals. The owner set the
direction: external snapshots are the way; internal ones pause the VM
while its memory is saved and can take long, so they stay only as a
fallback for a VM that cannot take an external one.
The tab now has the external snapshot form on top, its name and
description on one line, with its memory and freeze options; the
internal snapshot under a folded "fallback" line with its warning; and
one list of all snapshots, newest first, each on one line with its
name, description, kind and date, and Revert and Delete.
Codex reviewed snapshots end to end; these are fixed:
- The pause and memory lines follow the VM's state and the kind.
- An internal snapshot is reverted to on a shut-off VM only, on the
server too; the tab alone held that rule.
- A paused VM's revert says it comes back paused, not that it starts.
- An external snapshot waits, with the reason, while snapshots newer
than the one reverted to exist; the server refused it unexplained.
- Deleting an external snapshot says its files are merged with the
disks; "into the next one" was wrong for the last one.
- The description has no 45-character limit only the browser kept.
- Freezing is not shown ticked where it cannot be offered, and
unticking memory gives back the earlier freeze choice.
- Internal create, revert and delete refuse a saved state or a running
disk job, as external ones do.