aboutsummaryrefslogtreecommitdiffstats
path: root/vm-manager/Virsh.qml
diff options
context:
space:
mode:
Diffstat (limited to 'vm-manager/Virsh.qml')
-rw-r--r--vm-manager/Virsh.qml45
1 files changed, 43 insertions, 2 deletions
diff --git a/vm-manager/Virsh.qml b/vm-manager/Virsh.qml
index 309781c..14bd368 100644
--- a/vm-manager/Virsh.qml
+++ b/vm-manager/Virsh.qml
@@ -21,7 +21,7 @@ import QtQuick
Singleton {
id: root
- // name -> { state, cpu, memUsed, memTotal, fsUsed, fsTotal, ip, vcpus, agent }
+ // name -> { state, cpu, memUsed, memTotal, fsUsed, fsTotal, ip, vcpus, agent, saved }
property var vms: ({})
property var names: []
property var snapshots: ({}) // name -> [{ name, created, state, current }]
@@ -33,7 +33,8 @@ Singleton {
function _vm(name) {
return vms[name] ?? { state: "unknown", cpu: -1, memUsed: -1, memTotal: -1,
- fsUsed: -1, fsTotal: -1, ip: "", vcpus: 0, agent: false };
+ fsUsed: -1, fsTotal: -1, ip: "", vcpus: 0, agent: false,
+ saved: false };
}
function _set(name, fields) {
@@ -52,6 +53,7 @@ Singleton {
const found = text.trim().split("\n").map(s => s.trim()).filter(s => s.length);
root.names = found;
for (const n of found) if (!(n in root.vms)) root._set(n, {});
+ root._pollSaved();
root.refresh();
}
}
@@ -191,6 +193,44 @@ Singleton {
onExited: code => { if (code !== 0) { root._set(vm, { ip: "" }); root._nextAgent(); } }
}
+ // --- managed save ----------------------------------------------------
+ //
+ // A shut-off VM can still carry a saved memory image, and `virsh start`
+ // then restores it rather than booting. When that image cannot be
+ // restored the start fails every time with a QEMU migrate-incoming
+ // error, and nothing in the panel said why. `domstats` does not report
+ // it: the shut-off reason reads "failed", from the failed start, not
+ // from the save. `dominfo` is the only cheap source, so it is polled per
+ // VM the way the agent rows are.
+
+ property var _savedQueue: []
+
+ function _pollSaved() {
+ _savedQueue = names.slice();
+ _nextSaved();
+ }
+
+ function _nextSaved() {
+ if (_savedQueue.length === 0) return;
+ const vm = _savedQueue[0];
+ _savedQueue = _savedQueue.slice(1);
+ savedProc.vm = vm;
+ savedProc.command = ["virsh", "dominfo", vm];
+ savedProc.running = true;
+ }
+
+ Process {
+ id: savedProc
+ property string vm: ""
+ stdout: StdioCollector {
+ onStreamFinished: {
+ root._set(savedProc.vm, { saved: /^Managed save:\s+yes$/m.test(text) });
+ root._nextSaved();
+ }
+ }
+ onExited: code => { if (code !== 0) { root._set(vm, { saved: false }); root._nextSaved(); } }
+ }
+
// --- snapshots -------------------------------------------------------
Process {
@@ -227,6 +267,7 @@ Singleton {
destroy: v => ["virsh", "destroy", v],
suspend: v => ["virsh", "suspend", v],
resume: v => ["virsh", "resume", v],
+ discardsave: v => ["virsh", "managedsave-remove", v],
})
function act(vm, action) {