File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -159,6 +159,28 @@ wait_for_ssh() { # host [tries]
159159 die " ssh never became ready on ${host} "
160160}
161161
162+ # Wait until a freshly-booted droplet is done with its boot-time apt activity.
163+ # cloud-init (and unattended-upgrades it triggers) holds the dpkg/apt lock for a
164+ # while after SSH is reachable, so any apt use before this races and fails with
165+ # "Could not get lock /var/lib/apt/lists/lock". Block on cloud-init completion
166+ # and then on the dpkg frontend lock being free.
167+ wait_for_apt () { # host
168+ local host=" $1 "
169+ log " waiting for cloud-init + apt lock on ${host} "
170+ _ssh " $host " " bash -seuo pipefail" << 'EOF '
171+ cloud-init status --wait >/dev/null 2>&1 || true
172+ for i in $(seq 1 60); do
173+ # -n: try once without blocking; succeeds (and immediately releases) only when
174+ # no other process holds the apt/dpkg frontend lock.
175+ if flock -n /var/lib/dpkg/lock-frontend true 2>/dev/null; then
176+ echo "apt is free"; exit 0
177+ fi
178+ echo " apt busy, waiting... ($i/60)"; sleep 5
179+ done
180+ echo "apt lock still held after timeout" >&2; exit 1
181+ EOF
182+ }
183+
162184# ----------------------------------------------------------------------------
163185# DigitalOcean Spaces URL parsing
164186#
Original file line number Diff line number Diff line change @@ -84,6 +84,11 @@ export SERVER_PUBLIC_IP CLIENT_PUBLIC_IP
8484wait_for_ssh " $SERVER_PUBLIC_IP "
8585wait_for_ssh " $CLIENT_PUBLIC_IP "
8686
87+ # Let cloud-init / unattended-upgrades finish so later apt use does not race the
88+ # boot-time apt lock.
89+ wait_for_apt " $SERVER_PUBLIC_IP "
90+ wait_for_apt " $CLIENT_PUBLIC_IP "
91+
8792log " provisioning complete"
8893log " server: public=${SERVER_PUBLIC_IP} private=${SERVER_PRIVATE_IP} "
8994log " client: public=${CLIENT_PUBLIC_IP} "
You can’t perform that action at this time.
0 commit comments