d085e9fecc
Python mtime timestamp logic does not work well with ostree force 0 mtime. Use a small script to post-process all compiled '.pyc' and force the timestamp to 0. See: https://github.com/ostreedev/ostree/issues/1469 Co-Authored-By: Miro Hrončok <miro@hroncok.cz>
153 lines
4.6 KiB
Bash
Executable file
153 lines
4.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -xeuo pipefail
|
|
|
|
# Setup unit & script for readonly sysroot migration:
|
|
# - https://fedoraproject.org/wiki/Changes/Silverblue_Kinoite_readonly_sysroot
|
|
# - https://bugzilla.redhat.com/show_bug.cgi?id=2060976
|
|
|
|
cat > /usr/lib/systemd/system/fedora-silverblue-readonly-sysroot.service <<'EOF'
|
|
[Unit]
|
|
Description=Fedora Silverblue Read-Only Sysroot Migration
|
|
Documentation=https://fedoraproject.org/wiki/Changes/Silverblue_Kinoite_readonly_sysroot
|
|
ConditionPathExists=!/var/lib/.fedora_silverblue_readonly_sysroot
|
|
RequiresMountsFor=/sysroot /boot
|
|
ConditionPathIsReadWrite=/sysroot
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/libexec/fedora-silverblue-readonly-sysroot
|
|
RemainAfterExit=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
chmod 644 /usr/lib/systemd/system/fedora-silverblue-readonly-sysroot.service
|
|
|
|
cat > /usr/libexec/fedora-silverblue-readonly-sysroot <<'EOF'
|
|
#!/bin/bash
|
|
|
|
# Update an existing system to use a read only sysroot
|
|
# See https://fedoraproject.org/wiki/Changes/Silverblue_Kinoite_readonly_sysroot
|
|
# and https://bugzilla.redhat.com/show_bug.cgi?id=2060976
|
|
|
|
set -euo pipefail
|
|
|
|
main() {
|
|
# Used to condition execution of this unit at the systemd level
|
|
local -r stamp_file="/var/lib/.fedora_silverblue_readonly_sysroot"
|
|
|
|
if [[ -f "${stamp_file}" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
local -r ostree_sysroot_readonly="$(ostree config --repo=/sysroot/ostree/repo get "sysroot.readonly" &> /dev/null || echo "false")"
|
|
if [[ "${ostree_sysroot_readonly}" == "true" ]]; then
|
|
# Nothing to do
|
|
touch "${stamp_file}"
|
|
exit 0
|
|
fi
|
|
|
|
local -r boot_entries="$(ls -A /boot/loader/entries/ | wc -l)"
|
|
|
|
# Ensure that we can read BLS entries to avoid touching systems where /boot
|
|
# is not mounted
|
|
if [[ "${boot_entries}" -eq 0 ]]; then
|
|
echo "No BLS entry found: Maybe /boot is not mounted?" 1>&2
|
|
echo "This is unexpected thus no migration will be performed" 1>&2
|
|
touch "${stamp_file}"
|
|
exit 0
|
|
fi
|
|
|
|
# Check if any existing deployment is still missing the rw karg
|
|
local rw_kargs_found=0
|
|
local count=0
|
|
for f in "/boot/loader/entries/"*; do
|
|
count="$(grep -c "^options .* rw" "${f}" || true)"
|
|
if [[ "${count}" -ge 1 ]]; then
|
|
rw_kargs_found=$((rw_kargs_found + 1))
|
|
fi
|
|
done
|
|
|
|
# Some deployments are still missing the rw karg. Let's try to update them
|
|
if [[ "${boot_entries}" -ne "${rw_kargs_found}" ]]; then
|
|
ostree admin kargs edit-in-place --append-if-missing=rw || \
|
|
echo "Failed to edit kargs in place with ostree" 1>&2
|
|
fi
|
|
|
|
# Re-check if any existing deployment is still missing the rw karg
|
|
rw_kargs_found=0
|
|
count=0
|
|
for f in "/boot/loader/entries/"*; do
|
|
count="$(grep -c "^options .* rw" "${f}" || true)"
|
|
if [[ "${count}" -ge 1 ]]; then
|
|
rw_kargs_found=$((rw_kargs_found + 1))
|
|
fi
|
|
done
|
|
unset count
|
|
|
|
# If all deployments are good, then we can set the sysroot.readonly option
|
|
# in the ostree repo config
|
|
if [[ "${boot_entries}" -eq "${rw_kargs_found}" ]]; then
|
|
echo "Setting up the sysroot.readonly option in the ostree repo config"
|
|
ostree config --repo=/sysroot/ostree/repo set "sysroot.readonly" "true"
|
|
touch "${stamp_file}"
|
|
exit 0
|
|
fi
|
|
|
|
# If anything else before failed, we will retry on next boot
|
|
echo "Will retry next boot" 1>&2
|
|
exit 0
|
|
}
|
|
|
|
main "${@}"
|
|
EOF
|
|
|
|
chmod 755 /usr/libexec/fedora-silverblue-readonly-sysroot
|
|
|
|
# Enable the corresponding unit
|
|
systemctl enable fedora-silverblue-readonly-sysroot.service
|
|
|
|
###
|
|
|
|
# Workaround for Python timestamp mismatch
|
|
# See: https://github.com/ostreedev/ostree/issues/1469
|
|
|
|
echo '
|
|
import os
|
|
import re
|
|
|
|
MIN_MAGIC = 3390 # The first magic number supporting PEP 552
|
|
ZERO = bytes((0, 0, 0, 0))
|
|
|
|
def pyc_set_zero_mtime(pyc_path):
|
|
with open(pyc_path, "r+b") as f:
|
|
w = f.read(4)
|
|
if len(w) < 4:
|
|
return 0
|
|
|
|
magic = (w[0] + (w[1] << 8) + (w[2] << 16) + (w[3] << 24)) & 0xFFFF
|
|
if magic < MIN_MAGIC:
|
|
invalidation = ZERO
|
|
else:
|
|
invalidation = f.read(4)
|
|
if len(invalidation) < 4:
|
|
return 0
|
|
|
|
if invalidation == ZERO:
|
|
f.write(ZERO)
|
|
return 1
|
|
return 0
|
|
|
|
if __name__ == "__main__":
|
|
REGEX = re.compile(r".*/__pycache__/[^/]+\.cpython-.*(\.opt-1|\.opt-2)?\.pyc$")
|
|
count = 0
|
|
|
|
for root, dirs, files in os.walk("/usr"):
|
|
for file in files:
|
|
path = os.path.join(root, file)
|
|
if REGEX.match(path):
|
|
count += pyc_set_zero_mtime(path)
|
|
|
|
print(f"Processed {count} pyc files")
|
|
' | python
|