@@ -125,15 +125,18 @@ incus_storage_pool_free_gb() {
125125 local info free_bytes total_bytes used_bytes free_raw total_raw used_raw
126126
127127 # Prefer machine-readable bytes when available (Incus --bytes).
128- info=$( incus storage info --bytes " $pool " 2> /dev/null || true)
128+ # LC_ALL=C: incus translates this output. A German host reports "Gesamter
129+ # Speicherplatz" and "Speicherplatz in Benutzung", so the awk below matched
130+ # nothing and a 357GB pool looked unmeasurable.
131+ info=$( LC_ALL=C incus storage info --bytes " $pool " 2> /dev/null || true)
129132 free_raw=$( echo " $info " | awk -F' : *' ' /space free:/ {print $2; exit}' )
130133 if [[ -n " $free_raw " ]]; then
131134 free_bytes=" $( _incus_parse_size_to_bytes " $free_raw " 2> /dev/null || true) "
132135 fi
133136
134137 # Older/human output often has only "space used" + "total space" (no free line).
135138 if [[ -z " ${free_bytes:- } " ]]; then
136- info=$( incus storage info " $pool " 2> /dev/null || true)
139+ info=$( LC_ALL=C incus storage info " $pool " 2> /dev/null || true)
137140 free_raw=$( echo " $info " | awk -F' : *' ' /space free:/ {print $2; exit}' )
138141 total_raw=$( echo " $info " | awk -F' : *' ' /total space:/ {print $2; exit}' )
139142 used_raw=$( echo " $info " | awk -F' : *' ' /space used:/ {print $2; exit}' )
@@ -148,6 +151,16 @@ incus_storage_pool_free_gb() {
148151 fi
149152 fi
150153
154+ # A dir pool is just a path, so ask the filesystem when incus says nothing.
155+ # Does not help lvm or zfs, where source is not a path.
156+ if [[ -z " ${free_bytes:- } " ]]; then
157+ local src
158+ src=" $( LC_ALL=C incus storage get " $pool " source 2> /dev/null || true) "
159+ if [[ -n " $src " && -d " $src " ]]; then
160+ free_bytes=" $( df -PB1 " $src " 2> /dev/null | awk ' NR==2 {print $4}' ) "
161+ fi
162+ fi
163+
151164 [[ -z " ${free_bytes:- } " || " $free_bytes " -le 0 ]] && return 1
152165 echo $(( free_bytes / 1024 / 1024 / 1024 ))
153166}
@@ -178,8 +191,13 @@ resolve_storage_preselect() {
178191 incus storage info " $preselect " & > /dev/null || return 1
179192 STORAGE_RESULT=" $preselect "
180193 local free_gb
181- free_gb=$( incus_storage_pool_free_gb " $preselect " 2> /dev/null || echo " ?" )
182- STORAGE_INFO=" Free: ~${free_gb} GB"
194+ free_gb=$( incus_storage_pool_free_gb " $preselect " 2> /dev/null || true)
195+ # "Free: ~?GB" reads like a broken template. Say what is actually known.
196+ if [[ -n " $free_gb " ]]; then
197+ STORAGE_INFO=" Free: ~${free_gb} GB"
198+ else
199+ STORAGE_INFO=" Free: unknown"
200+ fi
183201 return 0
184202}
185203
@@ -474,7 +492,12 @@ incus_create_lxc_container() {
474492 msg_ok " Container configuration verified"
475493 fi
476494 else
477- msg_warn " Container restart failed after configuration changes"
495+ # Everything past this point needs incus exec. Warning and carrying on
496+ # over a stopped container is what turned one failed restart into three
497+ # unrelated-looking errors further down.
498+ msg_error " Container ${CT_NAME} is not running after configuration changes"
499+ msg_custom " ℹ️" " ${YW} " " See: incus info --show-log ${CT_NAME} "
500+ return 1
478501 fi
479502 fi
480503}
0 commit comments