diff --git a/readme-vars.yml b/readme-vars.yml index 27a1076..3cb4930 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -132,6 +132,9 @@ init_diagram: | "kasm:latest" <- Base Images # changelog changelogs: + - {date: "23.09.26:", desc: "Also bring Workspace sessions back after an unclean shutdown."} + - {date: "23.09.26:", desc: "Bring running and paused Workspace sessions back after a container restart."} + - {date: "23.09.26:", desc: "Give Workspace sessions their address back after a container restart."} - {date: "07.08.26:", desc: "Fix NVIDIA passthrough to Workspace containers by generating a CDI specification inside the DinD layer."} - {date: "04.08.26:", desc: "Give kasm_manager a healthcheck start period so a cold start does not leave kasm_proxy created but never started."} - {date: "16.04.26:", desc: "Update for 1.18.1 release. Use rolling service images. Bump docker to v29."} diff --git a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run index c12e153..9bbbce3 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run +++ b/root/etc/s6-overlay/s6-rc.d/init-config-kasm/run @@ -51,3 +51,9 @@ if [[ ! -L "/var/lib/docker-plugins" ]]; then mkdir -p /var/lib/docker-plugins/rclone/config mkdir -p /var/lib/docker-plugins/rclone/cache fi + +# After an unclean shutdown svc-kasm/finish has not recorded the sessions, but +# dockerd's records, read before it starts, still hold them as they were +if [[ ! -f /opt/kasm_sessions.state && -d /opt/docker/containers ]]; then + find /opt/docker/containers -name config.v2.json -exec jq -r 'select(.Config.Labels["kasm.kasmid"] and .State.Running) | "\(.ID) \(if .State.Paused then "paused" else "running" end)\(.NetworkSettings.Networks | to_entries? // [] | map(" \(.key)=\(.value.IPAddress)") | join(""))"' {} \; > /opt/kasm_sessions.state +fi diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm/finish b/root/etc/s6-overlay/s6-rc.d/svc-kasm/finish index e99a399..1e852a8 100755 --- a/root/etc/s6-overlay/s6-rc.d/svc-kasm/finish +++ b/root/etc/s6-overlay/s6-rc.d/svc-kasm/finish @@ -1,4 +1,8 @@ #!/usr/bin/with-contenv bash # shellcheck shell=bash +# Kasm routes to a session by the address its container was created with +# shellcheck disable=SC2016 +docker ps -q --filter "label=kasm.kasmid" | xargs -r docker inspect --format '{{.Id}} {{.State.Status}}{{range $network, $settings := .NetworkSettings.Networks}} {{$network}}={{$settings.IPAddress}}{{end}}' > /opt/kasm_sessions.state + /opt/kasm/bin/stop diff --git a/root/etc/s6-overlay/s6-rc.d/svc-kasm/run b/root/etc/s6-overlay/s6-rc.d/svc-kasm/run index eb51c00..da2d693 100755 --- a/root/etc/s6-overlay/s6-rc.d/svc-kasm/run +++ b/root/etc/s6-overlay/s6-rc.d/svc-kasm/run @@ -8,6 +8,21 @@ done # Stop any running containers that shouldn't be docker ps -q | xargs docker stop &> /dev/null +# Restore sessions before the services start, as Docker gives a starting +# container the lowest free address, not its previous one +if [[ -f /opt/kasm_sessions.state ]]; then + while read -r id status networks; do + for network in ${networks}; do + [[ -n "${network#*=}" ]] || continue + docker network disconnect --force "${network%%=*}" "${id}" + docker network connect --ip "${network#*=}" "${network%%=*}" "${id}" || docker network connect "${network%%=*}" "${id}" + done + docker start "${id}" > /dev/null + [[ "${status}" == "paused" ]] && docker pause "${id}" > /dev/null + done < /opt/kasm_sessions.state + rm -f /opt/kasm_sessions.state +fi + if [[ -f /opt/kasm/bin/start ]]; then /opt/kasm/bin/start fi