fix(delivery): derive installation reserve from verified inventory

This commit is contained in:
2026-10-12 20:50:11 +08:00
parent 3cde198358
commit 7145fb3fa4
4 changed files with 26 additions and 7 deletions
+2 -2
View File
@@ -61,8 +61,8 @@ def main() -> None:
elif args.command == "build":
result = build.build(args.repo, args.inputs, args.output, args.work)
elif args.command == "preflight":
manifest.verify(args.bundle, args.manifest_sha256)
result = preflight.observe(args.bundle / "payload")
data = manifest.verify(args.bundle, args.manifest_sha256)
result = preflight.observe(args.bundle / "payload", bundle_data=data)
print(json.dumps(result, sort_keys=True))
if not result["eligible"]:
parser.exit(1)
+1 -1
View File
@@ -182,7 +182,7 @@ def files(bundle: Path, expected: str) -> dict:
raise DeliveryError("installer requires root")
preflight.protected(bundle, directory=True)
data = manifest.verify(bundle, expected)
observation = preflight.observe(bundle / "payload")
observation = preflight.observe(bundle / "payload", bundle_data=data)
if not observation["eligible"]:
raise DeliveryError("installation preflight refused: " + "; ".join(observation["errors"]))
# Per-entry ownership matters even when the inventory is identical.
+19 -4
View File
@@ -120,7 +120,7 @@ def identity_conflicts() -> list[str]:
return errors
def observe(payload: Path, *, require_root: bool = True) -> dict:
def observe(payload: Path, *, bundle_data: dict, require_root: bool = True) -> dict:
errors = []
observations = {}
if platform.system() != "Linux" or platform.machine() != "x86_64":
@@ -183,9 +183,24 @@ def observe(payload: Path, *, require_root: bool = True) -> dict:
# A 4-GiB physical guest exposes slightly less MemTotal after kernel reserve.
if memory["MemTotal"] < 15 * GIB // 4 or memory["MemAvailable"] < 5 * GIB // 2:
errors.append("physical/available memory below installation capacity")
observations["disk_free_bytes"] = shutil.disk_usage("/var/lib").free
if observations["disk_free_bytes"] < 12 * GIB:
errors.append("installation/data disk reserve below 12 GiB")
disk = shutil.disk_usage("/var/lib")
protected_images = sum(
entry["bytes"] for entry in bundle_data["files"] if entry["path"].startswith("images/")
)
legacy_image = sum(
entry["bytes"] for entry in bundle_data["files"] if entry["path"].startswith("images/gnu/")
)
# Count a full new application + protected image copies + legacy image and
# four GiB of mutable data/operation reserve. Filesystem metadata makes a
# 12-GiB device expose less than 12 GiB free even when it is empty.
required = bundle_data["payload_bytes"] + protected_images + legacy_image + 4 * GIB
observations["disk"] = {
"total_bytes": disk.total,
"free_bytes": disk.free,
"required_free_bytes": required,
}
if disk.total < 12 * GIB or disk.free < required:
errors.append("installation/data capacity or inventory-derived free reserve insufficient")
for name in ("libc.so.6", "ld-linux-x86-64.so.2"):
system = Path("/usr/lib") / name
try: