Skip to content

Commit edbe2c2

Browse files
committed
Fix page crash on invalid domain startup times
When the log file contains a "starting up" timestamp which `new Date()` cannot parse, the page oopsed with a `RangeError` from `distanceToNow()`. Change `domainGetStartTime()` to return a Date object instead of a raw string, to keep the knowledge of the date format/parsing entirely within the function. Check for invalid dates and return `null` in the error cases, which the confirmation dialog already handles. Also, fix the `grep` to look for the same pattern that the `.split()` uses, to avoid mismatches. In the confirmation dialog, rename `uptime` to `startTime`, as that's what it is -- uptime is a duration, which is only computed inside of the render function, but that state is an absolute time stamp. https://issues.redhat.com/browse/RHEL-19878
1 parent 9e57ed9 commit edbe2c2

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

src/components/vm/confirmDialog.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ const _ = cockpit.gettext;
3030

3131
export const ConfirmDialog = ({ idPrefix, actionsList, title, titleIcon, vm }) => {
3232
const Dialogs = useDialogs();
33-
const [uptime, setUptime] = useState();
33+
const [startTime, setStartTime] = useState();
3434

3535
useEffect(() => {
3636
return domainGetStartTime({ connectionName: vm.connectionName, vmName: vm.name })
37-
.then(res => setUptime(res))
37+
.then(res => setStartTime(res))
3838
.catch(e => console.error(JSON.stringify(e)));
3939
}, [vm]);
4040

@@ -64,11 +64,11 @@ export const ConfirmDialog = ({ idPrefix, actionsList, title, titleIcon, vm }) =
6464
titleIconVariant={titleIcon}
6565
isOpen
6666
footer={actions}>
67-
{uptime
67+
{startTime
6868
? <DescriptionList isHorizontal isFluid>
6969
<DescriptionListGroup>
7070
<DescriptionListTerm>{_("Uptime")}</DescriptionListTerm>
71-
<DescriptionListDescription id="uptime">{distanceToNow(new Date(uptime))}</DescriptionListDescription>
71+
<DescriptionListDescription id="uptime">{distanceToNow(startTime)}</DescriptionListDescription>
7272
</DescriptionListGroup>
7373
</DescriptionList>
7474
/* for tests */

src/libvirtApi/domain.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -790,16 +790,20 @@ export function domainGetStartTime({
790790

791791
// Use libvirt APIs for getting VM start up time when it's implemented:
792792
// https://gitlab.com/libvirt/libvirt/-/issues/481
793-
return cockpit.script(`grep 'starting up' '${logFile}' | tail -1`, options);
793+
return cockpit.script(`grep ': starting up' '${logFile}' | tail -1`, options);
794794
})
795795
.then(line => {
796796
// Line from a log with a start up time is expected to look like this:
797797
// 2023-05-05 11:22:03.043+0000: starting up libvirt version: 8.6.0, package: 3.fc37 (Fedora Project, 2022-08-09-13:54:03, ), qemu version: 7.0.0qemu-7.0.0-9.fc37, kernel: 6.0.6-300.fc37.x86_64, hostname: fedora
798798

799799
// Alternatively regex line.match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/g) can be used
800-
const timeStr = line.split(': starting')[0];
801-
802-
return Promise.resolve(timeStr);
800+
const timeStr = line.split(': starting up')[0];
801+
const date = new Date(timeStr);
802+
return isNaN(date) ? null : date;
803+
})
804+
.catch(ex => {
805+
console.log("Unable to detect domain start time:", ex);
806+
return null;
803807
});
804808
}
805809

test/check-machines-lifecycle

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,22 @@ class TestMachinesLifecycle(VirtualMachinesCase):
246246
b.click(".pf-v5-c-modal-box__footer button:contains(Cancel)")
247247
b.wait_not_present("#vm-subVmTest2-system-confirm-action-modal")
248248

249+
# uptime parsing robustness: unparseable format
250+
self.machine.execute(f"sed -i '/: starting up/ s/^/invalidtime/' {args2['qemulog']}")
251+
b.click("#vm-subVmTest2-system-shutdown-button")
252+
b.wait_visible("#vm-subVmTest2-system-confirm-action-modal")
253+
b._wait_present(".uptime-not-available")
254+
b.click(".pf-v5-c-modal-box__footer button:contains(Cancel)")
255+
b.wait_not_present("#vm-subVmTest2-system-confirm-action-modal")
256+
257+
# uptime parsing robustness: no "starting up" line
258+
self.machine.execute(f"sed -i '/: starting up/d' {args2['qemulog']}")
259+
b.click("#vm-subVmTest2-system-shutdown-button")
260+
b.wait_visible("#vm-subVmTest2-system-confirm-action-modal")
261+
b._wait_present(".uptime-not-available")
262+
b.click(".pf-v5-c-modal-box__footer button:contains(Cancel)")
263+
b.wait_not_present("#vm-subVmTest2-system-confirm-action-modal")
264+
249265
b.set_input_text("#text-search", "subVmTest2")
250266
self.waitVmRow("subVmTest2")
251267
self.waitVmRow("subVmTest1", "system", False)

0 commit comments

Comments
 (0)