1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-10 20:26:48 +00:00

feat(instances): the VM lists follow changes by themselves

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.
This commit is contained in:
catborise 2026-11-01 19:37:33 +03:00
parent f88deb22c1
commit eb6e6ca626
15 changed files with 276 additions and 11 deletions

View file

@ -49,3 +49,12 @@ function pollWhileVisible(interval, request, onData, firstDelay) {
},
};
}
// The user is in the page: a dialog open, a field in use or an XML edit not
// saved. A poll that would reload the page waits for its next answer.
function pageInUse() {
var active = document.activeElement;
return !!document.querySelector(".modal.show")
|| !!(active && active.matches && active.matches("input, select, textarea"))
|| !!(window.xmlEditUnsaved && window.xmlEditUnsaved());
}

28
static/js/vm_states.js Normal file
View file

@ -0,0 +1,28 @@
// A VM list follows libvirt: it polls the states of its VMs (instances:states)
// at once, then every 5 s, as the VM page, and reloads when an answer differs
// from the one before: a VM started or stopped, made, removed or renamed
// outside the page included. The page in use or the job panel showing
// something: it waits for the next answer. poll.js gives the polling.
function vmStatesKey(states) {
return Object.keys(states).sort().map(function (id) {
var host = states[id];
return id + ":" + (host.ok ? Object.keys(host.vms).sort().map(function (uuid) {
return uuid + "=" + host.vms[uuid].join("/");
}).join(",") : "unreadable");
}).join(";");
}
function followVmStates(url) {
var last = null;
// the first answer, at once, is what the page was rendered with
return pollWhileVisible(5000, function () { return $.getJSON(url); }, function (data) {
var key = vmStatesKey(data.computes);
if (last !== null && key !== last) {
if (!pageInUse() && !window.backgroundJobRunning) {
window.location.reload();
}
return; // in use: the change stays against the answer before
}
last = key;
}, 0);
}