aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/vm/Virsh.qml
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/vm/Virsh.qml')
-rw-r--r--desktop/modules/vm/Virsh.qml28
1 files changed, 28 insertions, 0 deletions
diff --git a/desktop/modules/vm/Virsh.qml b/desktop/modules/vm/Virsh.qml
index 14bd368..6a15f97 100644
--- a/desktop/modules/vm/Virsh.qml
+++ b/desktop/modules/vm/Virsh.qml
@@ -306,6 +306,32 @@ Singleton {
actProc.running = true;
}
+ // After a start, notify once sshd accepts connections. "Running" in
+ // libvirt means QEMU is up, not the guest, so the port is the real
+ // signal. Host and port come from `ssh -G <vm>`, because a Host alias
+ // named after the VM may put sshd on a non-default port (buildsystem
+ // listens on 2290, and probing 22 waited forever); without an alias
+ // `ssh -G` echoes the name back, and the guest agent's address with
+ // port 22 is used instead. Detached so several VMs can wait at once;
+ // a VM that never answers gets a notice after five minutes.
+ readonly property string _waitSsh: `
+ vm=$1; end=$(( $(date +%s) + 300 ))
+ set -- $(ssh -G "$vm" 2>/dev/null | awk '/^hostname /{h=$2} /^port /{p=$2} END{print h, p}')
+ host=$1; port=\${2:-22}
+ while [ "$(date +%s)" -lt "$end" ]; do
+ if [ "$host" = "$vm" ]; then
+ ip=$(virsh domifaddr "$vm" --source agent 2>/dev/null |
+ awk '$3 == "ipv4" && $4 !~ /^127\\./ { sub("/.*", "", $4); print $4; exit }')
+ else
+ ip=$host
+ fi
+ [ -n "$ip" ] && nc -z -w 2 "$ip" "$port" 2>/dev/null &&
+ exec notify-send --app-name=vm-manager --icon=computer "$vm is ready" "ssh $ip:$port"
+ sleep 2
+ done
+ notify-send --app-name=vm-manager --icon=dialog-warning "$vm not reachable" "no ssh after 5 minutes"
+ `
+
Process {
id: actProc
property string vm: ""
@@ -315,6 +341,8 @@ Singleton {
if (code !== 0)
root.actionFailed(actProc.vm, actProc.action,
actErr.text.trim() || `exited ${code}`);
+ else if (actProc.action === "start")
+ Quickshell.execDetached(["sh", "-c", root._waitSsh, "sh", actProc.vm]);
root.refreshList();
if (root.snapshots[actProc.vm]) root.loadSnapshots(actProc.vm);
}