Files
archy/tests/regression/d09-systemd-reboot.py

91 lines
4.3 KiB
Python

#!/usr/bin/python3
"""Second stage after restart of the SAME disposable rootless PID1 container.
This is container/PID1 restart qualification, not a physical-node reboot or
native artifact/terminal acceptance. Prior authority evidence stays intact.
"""
import importlib.util
import json
import os
from pathlib import Path
import secrets
import socket
import subprocess
import sys
import time
assert os.geteuid() == 0 and socket.gethostname() == 'd09-qualification'
assert Path('/run/.containerenv').exists() and os.environ.get('D09_DISPOSABLE_SYSTEMD') == '1'
PACKAGE = Path('/opt/d09-fixture')
sys.path.insert(0, str(PACKAGE / 'scripts'))
import d09_store as store
import d09_wire as wire
spec = importlib.util.spec_from_file_location('provision', PACKAGE / 'scripts/provision-d09-lifecycle.py')
provision = importlib.util.module_from_spec(spec)
spec.loader.exec_module(provision)
owner = provision.owner
def run(*args):
return subprocess.run(args, check=True, capture_output=True, text=True, timeout=45)
def wait(predicate):
for _ in range(450):
try:
value = predicate()
if value:
return value
except (OSError, ValueError, subprocess.SubprocessError):
pass
time.sleep(.1)
raise AssertionError('reboot fixture timed out')
before = store.read(owner.ROOT / 'ledger.json')
value = json.loads(before)
binding = value['active_binding']
assert value['receipt']['phase'] == 'COMPLETE' and value['receipt']['config_action'] == 'RESTORE'
assert not (owner.RUN / 'bootstrap.json').exists()
# /run is genuinely fresh. Restore only the inert requester's disposable IPC
# directory; no authority, journal or permit is copied into the new boot.
import pwd
account = pwd.getpwnam('archipelago')
control = Path('/run/d09-fixture-client')
control.mkdir(mode=0o700, exist_ok=True)
os.chown(control, account.pw_uid, account.pw_gid)
run('systemctl', 'start', 'archipelago-d09-lifecycle.service')
wait(lambda: json.loads(run('/usr/libexec/archipelago-d09ctl', 'inspect').stdout)['state'] == 'UNKNOWN')
assert store.read(owner.ROOT / 'ledger.json') == before
probe = owner.Owner.__new__(owner.Owner)
disposition = wait(lambda: probe.drained_disposition(value))
index = {k: binding[k] for k in ('target_binding_digest', 'composition_digest', 'transaction_id')}
fields = dict(index, predecessor_epoch_id=value['epoch'], head_sequence=value['sequence'],
preserved_head_digest=wire.digest(wire.canonical(value['receipt'])),
preserved_journal_digest=wire.digest(wire.canonical({'receipts': value['journal'], 'intents': value['intents']})),
preserved_consumed_history_digest=wire.digest(wire.canonical(owner.consumption_history(value))),
preserved_target_index_digest=wire.digest(wire.canonical(index)), disposition_digest=disposition,
new_epoch_id=secrets.token_hex(16), new_grant_digest=secrets.token_hex(32),
execution_grant_digest=secrets.token_hex(32), allowed_action='REACTIVATE_RETAINED')
directory = PACKAGE / 'external-history'
history_path = directory / 'pid1-restart-history.json'
record_path = directory / 'pid1-restart-record.json'
store.atomic(history_path, wire.canonical(dict(fields, sequence=1)))
record = dict(fields, schema_version=1, external_history_sequence=1,
external_history_digest=wire.digest(store.read(history_path)), observed_boot_id=owner.boot_id())
store.atomic(record_path, wire.canonical(record))
provision.readmit(record_path, history_path, activation=True)
def awaiting():
latest = json.loads(store.read(owner.ROOT / 'ledger.json'))
return latest if latest['receipt']['phase'] == 'AWAITING_OBSERVATION' else None
latest = wait(awaiting)
assert latest['journal'][:len(value['journal'])] == value['journal']
assert latest['receipt']['observed_invocation_id'] != value['receipt']['observed_invocation_id']
assert latest['receipt']['namespace_observation_digest'] is None
for name, destination in owner.DESTINATIONS.items():
assert owner.object_digest(destination) == binding['objects'][name]['restore']
before_retry = store.read(owner.ROOT / 'ledger.json')
provision.readmit(record_path, history_path, activation=True)
assert store.read(owner.ROOT / 'ledger.json') == before_retry
print('PASS fresh container PID1/run state: UNKNOWN before external authority; exact retained B activated once; journal preserved; fresh observation still required', flush=True)