deploy-remote: privileged rename + deep merge in migrate_data_root
rename() of a directory requires write on the directory itself; mariadb/ redis data roots are owned by the containers' mapped subuids (100998), so the deploy user cannot move them. Use run_privileged mv (numeric ownership preserved = rootless mapping contract) and skip the chown pass for romm via the new keep mode — chowning mapped subuid data to the deploy uid breaks the in-container mysql/redis users. Collisions with rescued anonymous-volume stubs now merge one level deep instead of stranding real data under /opt. Reverse the podman rm order so the dependent romm container is removed before its backends.
This commit is contained in:
1 parent
a18bb62d30
commit
26b0d4c357
1 file changed
+37
-19
+37
-19
@@ -537,25 +537,43 @@ wait_container_healthy() {
|
|||||||
# the unit; re-running the handler on an already-active unit restarts only the
|
# the unit; re-running the handler on an already-active unit restarts only the
|
||||||
# selected unit.
|
# selected unit.
|
||||||
|
|
||||||
migrate_data_root() { # $1 = old /opt path, $2 = new data-root path (same fs: rename/merge)
|
migrate_data_root() { # $1=old /opt path, $2=new data root, $3=chown|keep (default chown)
|
||||||
local from="$1" to="$2" entry
|
local from="$1" to="$2" mode="${3:-chown}" entry sub base
|
||||||
[[ -d "$from" ]] || return 0
|
[[ -d "$from" ]] || return 0
|
||||||
if [[ -d "$to" && -n "$(ls -A "$to" 2>/dev/null)" ]]; then
|
# Renaming a directory needs WRITE permission on the directory being
|
||||||
# The destination already holds seeded state (env file, rescued
|
# renamed itself. Compose-era data roots contain directories owned by
|
||||||
# anonymous-volume data). Merge the old root into it without ever
|
# the containers' mapped host uids (mariadb/redis land in the subuid
|
||||||
# overwriting an existing entry, then drop the emptied source.
|
# range as 100998), which the deploy user cannot rename. Privileged mv
|
||||||
shopt -s dotglob
|
# preserves numeric ownership — the rootless mapping contract.
|
||||||
for entry in "$from"/*; do
|
mkdir -p "$to"
|
||||||
[[ -e "$entry" ]] || continue
|
shopt -s dotglob
|
||||||
mv -n -- "$entry" "$to/"
|
for entry in "$from"/*; do
|
||||||
done
|
[[ -e "$entry" || -L "$entry" ]] || continue
|
||||||
shopt -u dotglob
|
base="${entry##*/}"
|
||||||
rmdir -- "$from" 2>/dev/null || \
|
if [[ -e "$to/$base" ]]; then
|
||||||
echo "WARN: $from not empty after merge (collisions kept old side); left in place" >&2
|
# Collides with pre-seeded state (env file) or a rescued
|
||||||
else
|
# anonymous-volume stub: merge one level deep, never overwriting
|
||||||
mv -- "$from" "$to"
|
# an existing entry.
|
||||||
|
if [[ -d "$entry" && -d "$to/$base" ]]; then
|
||||||
|
for sub in "$entry"/*; do
|
||||||
|
[[ -e "$sub" || -L "$sub" ]] || continue
|
||||||
|
run_privileged mv -n -- "$sub" "$to/$base/"
|
||||||
|
done
|
||||||
|
run_privileged rmdir -- "$entry" 2>/dev/null || \
|
||||||
|
echo "WARN: $entry not empty after merge; left in place" >&2
|
||||||
|
else
|
||||||
|
echo "WARN: collision on $to/$base kept existing; $entry left in place" >&2
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
run_privileged mv -- "$entry" "$to/"
|
||||||
|
done
|
||||||
|
shopt -u dotglob
|
||||||
|
run_privileged rmdir -- "$from" 2>/dev/null || \
|
||||||
|
echo "WARN: $from not empty after migration; left in place" >&2
|
||||||
|
if [[ "$mode" == chown ]]; then
|
||||||
|
chown -R "$(id -u):$(id -g)" "$to"
|
||||||
fi
|
fi
|
||||||
chown -R "$(id -u):$(id -g)" "$to"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deploy_romm_stack() {
|
deploy_romm_stack() {
|
||||||
@@ -580,7 +598,7 @@ deploy_romm_stack() {
|
|||||||
local vols
|
local vols
|
||||||
vols="$(podman inspect -f '{{range .Mounts}}{{if eq .Type "volume"}}{{.Name}} {{end}}{{end}}' romm 2>/dev/null || true)"
|
vols="$(podman inspect -f '{{range .Mounts}}{{if eq .Type "volume"}}{{.Name}} {{end}}{{end}}' romm 2>/dev/null || true)"
|
||||||
podman stop -t 60 romm-mariadb romm-redis romm || true
|
podman stop -t 60 romm-mariadb romm-redis romm || true
|
||||||
podman rm romm-mariadb romm-redis romm || true
|
podman rm romm romm-redis romm-mariadb || true
|
||||||
for vol in $vols; do
|
for vol in $vols; do
|
||||||
tmp="$(mktemp -d)"
|
tmp="$(mktemp -d)"
|
||||||
podman volume export --output "$tmp/v.tar" "$vol"
|
podman volume export --output "$tmp/v.tar" "$vol"
|
||||||
@@ -589,7 +607,7 @@ deploy_romm_stack() {
|
|||||||
tar --skip-old-files -C /home/dank/Containers/romm -xf "$tmp/v.tar"
|
tar --skip-old-files -C /home/dank/Containers/romm -xf "$tmp/v.tar"
|
||||||
rm -rf -- "$tmp"
|
rm -rf -- "$tmp"
|
||||||
done
|
done
|
||||||
migrate_data_root /opt/romm /home/dank/Containers/romm
|
migrate_data_root /opt/romm /home/dank/Containers/romm keep
|
||||||
systemctl --user start romm-mariadb.service
|
systemctl --user start romm-mariadb.service
|
||||||
wait_container_healthy romm-mariadb 120 || return 1
|
wait_container_healthy romm-mariadb 120 || return 1
|
||||||
systemctl --user start romm-redis.service
|
systemctl --user start romm-redis.service
|
||||||
|
|||||||
Reference in new issue
Block a user