From 43eda458dd6cedfa8d0471b9077a3958717b2f2f Mon Sep 17 00:00:00 2001 From: "riad.elhajjaji" Date: Thu, 29 Oct 2026 09:24:49 +0100 Subject: [PATCH] fix: ask cloud-init whether a machine booted as root Updating a platform waits again on every machine, the ones left alone included. On a Rocky machine where anything installed a package since it booted, `cloud-init status` failed as the SSH user with a PermissionError on /run/cloud-init/cloud.cfg, so the update failed with "booted badly, cloud-init exited 1". The cloud-init package keeps /run/cloud-init to root through a tmpfiles rule, and the systemd package runs every tmpfiles rule again whenever a package ships one. cloud-init then cannot read its own runtime config for anybody else (canonical/cloud-init#6680). Freshly booted machines did not show it, which is why spawns, and updates of platforms nothing was installed on, went through. The status is now asked through `sudo -n`, which the SSH users of the images have, and which fails rather than waits on a password. --- __main__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/__main__.py b/__main__.py index 381efa3..873a735 100644 --- a/__main__.py +++ b/__main__.py @@ -39,11 +39,14 @@ sleep 5 done - # NOTE: Bounded like the wait above. `cloud-init status --wait` holds for - # as long as it takes, and a boot that never ends would otherwise hold the - # update with it. 124 is what the timeout itself exits with. + # NOTE: `cloud-init status --wait` can wait forever if a boot gets stuck, + # so we cap it with a timeout, just like the SSH wait above. When time + # runs out, `timeout` exits with 124. + # NOTE: We need sudo here. On Rocky, installing a package locks + # /run/cloud-init down to root, and `cloud-init status` then fails for + # the SSH user. booted=0 - timeout {timeout} ssh -F {config} "$host" cloud-init status --wait || booted=$? + timeout {timeout} ssh -F {config} "$host" sudo -n cloud-init status --wait || booted=$? if [ "$booted" -eq 124 ]; then echo "$host was still booting after {timeout}s" >&2 exit 1