diff --git a/src/components/vm/confirmDialog.jsx b/src/components/vm/confirmDialog.jsx
index a0bc44b2b..b7008235b 100644
--- a/src/components/vm/confirmDialog.jsx
+++ b/src/components/vm/confirmDialog.jsx
@@ -27,6 +27,7 @@ import { useDialogs } from 'dialogs.jsx';
import { distanceToNow } from 'timeformat.js';
import { domainGetStartTime } from '../../libvirtApi/domain.js';
+import { Enum } from '../../libvirtApi/helpers.js';
const _ = cockpit.gettext;
@@ -60,18 +61,65 @@ export const ConfirmDialog = ({ idPrefix, actionsList, title, titleIcon, vm }) =
);
- let body = (
-
-
-
- );
+ let body;
+ if (dialogLoading) {
+ body = (
+
+
+
+ );
+ } else if (uptime) {
+ let uptimeStr = distanceToNow(new Date(uptime));
+
+ // https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainRunningReason
+ switch (vm.stateReason) {
+ case Enum.VIR_DOMAIN_RUNNING_MIGRATED: {
+ uptimeStr = cockpit.format(_("$0 since migration"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_RESTORED: {
+ uptimeStr = cockpit.format(_("$0 since restoration from a state file"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_FROM_SNAPSHOT: {
+ uptimeStr = cockpit.format(_("$0 since reverting to snapshot"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_UNPAUSED: {
+ uptimeStr = cockpit.format(_("$0 since VM was resumed"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_MIGRATION_CANCELED: {
+ uptimeStr = cockpit.format(_("$0 since migration was cancelled"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_SAVE_CANCELED: {
+ uptimeStr = cockpit.format(_("$0 since failed save process"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_WAKEUP: {
+ uptimeStr = cockpit.format(_("$0 since wakeup event"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_CRASHED: {
+ uptimeStr = cockpit.format(_("$0 since resumed from crash"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_POSTCOPY: {
+ uptimeStr = cockpit.format(_("$0 since post-copy migration"), uptimeStr);
+ break;
+ }
+ case Enum.VIR_DOMAIN_RUNNING_POSTCOPY_FAILED: {
+ uptimeStr = cockpit.format(_("$0 since failed post-copy migration"), uptimeStr);
+ break;
+ }
+ }
- if (!dialogLoading) {
- body = (uptime &&
+ body = (
{_("Uptime")}
- {distanceToNow(new Date(uptime))}
+ {uptimeStr}
);
diff --git a/test/check-machines-lifecycle b/test/check-machines-lifecycle
index 6b4b3f147..03f271c45 100755
--- a/test/check-machines-lifecycle
+++ b/test/check-machines-lifecycle
@@ -244,6 +244,17 @@ class TestMachinesLifecycle(VirtualMachinesCase):
b.click(".pf-c-modal-box__footer button:contains(Cancel)")
b.wait_not_present("#vm-subVmTest2-system-confirm-action-modal")
+ # Check uptime with VM boot message
+ # Non-privileged user doesn't have access to system-connection VM's logs
+ if superuser:
+ m.execute("virsh managedsave --domain subVmTest2")
+ m.execute("virsh start --domain subVmTest2")
+ b.click("#vm-subVmTest2-system-shutdown-button")
+ b.wait_visible("#vm-subVmTest2-system-confirm-action-modal")
+ b.wait_in_text("#vm-subVmTest2-system-confirm-action-modal #uptime", "since restoration from a state file")
+ b.click(".pf-c-modal-box__footer button:contains(Cancel)")
+ b.wait_not_present("#vm-subVmTest2-system-confirm-action-modal")
+
b.set_input_text("#text-search", "subVmTest2")
self.waitVmRow("subVmTest2")
self.waitVmRow("subVmTest1", "system", False)