diff --git a/src/components/vm/confirmDialog.jsx b/src/components/vm/confirmDialog.jsx index a0bc44b2b..3c44fa109 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,56 @@ 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: + case Enum.VIR_DOMAIN_RUNNING_POSTCOPY: { + uptimeStr = cockpit.format(_("$0 since migration"), uptimeStr); + break; + } + case Enum.VIR_DOMAIN_RUNNING_FROM_SNAPSHOT: { + uptimeStr = cockpit.format(_("$0 since reverting to snapshot"), uptimeStr); + break; + } + case Enum.VIR_DOMAIN_RUNNING_RESTORED: + case Enum.VIR_DOMAIN_RUNNING_UNPAUSED: { + uptimeStr = cockpit.format(_("$0 since VM was resumed"), uptimeStr); + break; + } + case Enum.VIR_DOMAIN_RUNNING_MIGRATION_CANCELED: + case Enum.VIR_DOMAIN_RUNNING_POSTCOPY_FAILED: { + 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; + } + } - if (!dialogLoading) { - body = (uptime && + body = ( {_("Uptime")} - {distanceToNow(new Date(uptime))} + {uptimeStr} ); diff --git a/test/check-machines-lifecycle b/test/check-machines-lifecycle index e9c546b2f..912ffbfb7 100755 --- a/test/check-machines-lifecycle +++ b/test/check-machines-lifecycle @@ -232,6 +232,8 @@ class TestMachinesLifecycle(VirtualMachinesCase): self.performAction("subVmTest2", "forceOff") b.click("#vm-subVmTest2-system-run") + # wait for libvirt to update the internal state (reason) of VM + wait(lambda: "running (booted)" in m.execute("virsh domstate --reason subVmTest2"), delay=3) # Check uptime b.click("#vm-subVmTest2-system-shutdown-button") @@ -244,6 +246,19 @@ 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") + # wait for libvirt to update the internal state (reason) of VM + wait(lambda: "running (restored)" in m.execute("virsh domstate --reason subVmTest2"), delay=3) + 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 VM was resumed") + 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)