Compare commits
1
Commits
v0.8.0-rc2
...
v0.8.0-rc3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f8d42f2cf |
+8
-1
@@ -76,7 +76,14 @@ worse than no alert, because one day it carries a security fix.
|
|||||||
straight back into the same race. So the overlay is re-mounted for the benefit
|
straight back into the same race. So the overlay is re-mounted for the benefit
|
||||||
of the next restart, and the question of whether *this* middlewared actually
|
of the next restart, and the question of whether *this* middlewared actually
|
||||||
holds the patch is left to the one thing that can answer it exactly — the
|
holds the patch is left to the one thing that can answer it exactly — the
|
||||||
in-process alert below.
|
in-process alert below. That re-mount preserves `hook_status.json`'s
|
||||||
|
`patched_at`: `create_task.py verify` decides "loaded" by comparing
|
||||||
|
middlewared's start time against that stamp, so a re-apply running *after* the
|
||||||
|
restart would have made the stamp newer than the process which correctly
|
||||||
|
imported the patch, and `verify` would have reported FAIL forever on every
|
||||||
|
boot where the sysext merge detaches the overlay. Caught on hardware while
|
||||||
|
validating the candidate — a new lying status introduced by the fix for a
|
||||||
|
lying status.
|
||||||
|
|
||||||
Two supporting fixes fell out of the same failure. `_ensure_writable` treated
|
Two supporting fixes fell out of the same failure. `_ensure_writable` treated
|
||||||
"one of our overlays is listed on this directory" as "already done" — but it
|
"one of our overlays is listed on this directory" as "already done" — but it
|
||||||
|
|||||||
@@ -143,7 +143,26 @@ else
|
|||||||
_log "nvidia sysext merge follows it) -- re-mounting for the next restart."
|
_log "nvidia sysext merge follows it) -- re-mounting for the next restart."
|
||||||
_log "Whether THIS middlewared loaded the patch is answered in-process by"
|
_log "Whether THIS middlewared loaded the patch is answered in-process by"
|
||||||
_log "the 'installed but NOT loaded' alert, not by this check."
|
_log "the 'installed but NOT loaded' alert, not by this check."
|
||||||
|
|
||||||
|
# Preserve hook_status.json's patched_at across this re-mount.
|
||||||
|
#
|
||||||
|
# create_task.py verify decides "loaded" by comparing middlewared's start
|
||||||
|
# time against patched_at. This re-apply restores the SAME patch the boot
|
||||||
|
# pass already applied, but it runs *after* the restart -- so letting it
|
||||||
|
# re-stamp would make patched_at newer than the process that correctly
|
||||||
|
# imported the patch, and verify would report FAIL forever, on every boot
|
||||||
|
# where docker's sysext merge detaches the overlay. That is precisely the
|
||||||
|
# lying-status failure this release exists to remove, so do not introduce a
|
||||||
|
# new one. The snapshot lives in /run, never in the repo: a leftover file
|
||||||
|
# there would leave the tree dirty and update.sh refuses to run over that.
|
||||||
|
_saved_status=/run/truecloud-hook_status.pre
|
||||||
|
cp -p "$PATCH_DIR/hook_status.json" "$_saved_status" 2>/dev/null
|
||||||
|
|
||||||
TRUECLOUD_REAPPLY=1 /bin/bash "$PATCH_DIR/patch/apply.sh"
|
TRUECLOUD_REAPPLY=1 /bin/bash "$PATCH_DIR/patch/apply.sh"
|
||||||
|
|
||||||
|
if [ -f "$_saved_status" ]; then
|
||||||
|
mv -f "$_saved_status" "$PATCH_DIR/hook_status.json" 2>/dev/null
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_log "=== deferred restart complete ==="
|
_log "=== deferred restart complete ==="
|
||||||
|
|||||||
@@ -172,3 +172,28 @@ def test_mount_retries_on_a_private_workdir():
|
|||||||
body = src[start:end]
|
body = src[start:end]
|
||||||
assert body.count("mount -t overlay") == 2, "expected a retry mount"
|
assert body.count("mount -t overlay") == 2, "expected a retry mount"
|
||||||
assert 'work="/run/truecloud-${tag}-work.$$"' in body
|
assert 'work="/run/truecloud-${tag}-work.$$"' in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_post_restart_remount_preserves_the_patched_at_stamp():
|
||||||
|
"""create_task.py verify compares middlewared's start time to patched_at.
|
||||||
|
|
||||||
|
The post-restart re-mount restores the same patch the boot pass applied, so
|
||||||
|
letting apply.sh re-stamp would make patched_at newer than the process that
|
||||||
|
correctly imported it -- verify would then report FAIL forever on every boot
|
||||||
|
where docker's sysext merge detaches the overlay.
|
||||||
|
"""
|
||||||
|
src = wait_restart_source()
|
||||||
|
tail = src[src.index("systemctl try-restart middlewared"):]
|
||||||
|
assert "hook_status.json" in tail
|
||||||
|
save = tail.index("/run/truecloud-hook_status.pre")
|
||||||
|
reapply = tail.index("TRUECLOUD_REAPPLY=1")
|
||||||
|
restore = tail.rindex("hook_status.json")
|
||||||
|
assert save < reapply < restore, "snapshot must bracket the re-apply"
|
||||||
|
|
||||||
|
|
||||||
|
def test_status_snapshot_is_not_written_into_the_repo():
|
||||||
|
"""A leftover file in the repo dir leaves the tree dirty, and update.sh
|
||||||
|
refuses to run over a dirty tree -- that once made the patch un-updatable."""
|
||||||
|
src = wait_restart_source()
|
||||||
|
assert "/run/truecloud-hook_status.pre" in src
|
||||||
|
assert '"$PATCH_DIR/hook_status.json.pre' not in src
|
||||||
|
|||||||
Reference in New Issue
Block a user