#!/usr/bin/env python3
"""Runtime review regressions using temporary artifacts and stubbed commands only."""
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest
import test_maintenance_logging as maintenance_fixtures
BIN = Path(__file__).resolve().parents[1] / "Server/Unix/p4/common/bin"
BASH = os.environ.get("SDP_TEST_BASH", shutil.which("bash"))
class BackupRuntimeReview(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix="sdp-runtime-")
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.checkpoints = self.root / "checkpoints with spaces"
self.offline = self.root / "offline"
self.checkpoints.mkdir()
self.offline.mkdir()
self.env = dict(os.environ, P4CBIN=str(self.root), CHECKPOINTS=str(self.checkpoints),
P4CKP_PREFIX="p4.test", AWK="awk", TEST_OFFLINE=str(self.offline),
LOGFILE=str(self.root / "run.log"), TEST_ROOT=str(self.root),
BACKUP_FUNCTIONS=str(BIN / "backup_functions.sh"))
def run_backup(self, commands, extra=None):
env = dict(self.env, **(extra or {}))
return subprocess.run([BASH, "-c", '''source "$BACKUP_FUNCTIONS"
function die () { printf '%s\\n' "$*" >&2; exit 97; }
OFFLINE_DB=$TEST_OFFLINE
''' + commands], env=env, cwd=self.root, text=True, capture_output=True, timeout=10)
def artifact(self, kind, number, directory=False):
path = self.checkpoints / f"p4.test.{kind}.{number}"
if directory:
path.mkdir()
(path / "db.counters.gz").write_text("checkpoint")
else:
path = Path(str(path) + ".gz")
path.write_text("artifact")
Path(str(path) + ".md5").write_text("digest")
return path
def cleanup(self):
return self.run_backup('KEEPCKPS=1; KEEPJNLS=2; OFFLINEJNLNUM=1000; remove_old_checkpoints_and_journals')
def test_serial_cleanup_preserves_newer_numbers_with_same_prefix(self):
old = self.artifact("ckp", 1)
new = self.artifact("ckp", 100)
result = self.cleanup()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertFalse(old.exists())
self.assertTrue(new.exists())
self.assertTrue(Path(str(new) + ".md5").exists())
def test_parallel_cleanup_preserves_newer_numbers_with_same_prefix(self):
old = self.artifact("ckp", 1, directory=True)
new = self.artifact("ckp", 100, directory=True)
result = self.cleanup()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertFalse(old.exists())
self.assertTrue(new.exists())
self.assertTrue(Path(str(new) + ".md5").exists())
def test_journal_cleanup_preserves_newer_numbers_with_same_prefix(self):
self.artifact("ckp", 100)
old = self.artifact("jnl", 1)
new = [self.artifact("jnl", n) for n in [10, 100]]
result = self.cleanup()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertFalse(old.exists())
self.assertTrue(all(p.exists() for p in new))
def test_cleanup_failure_is_reported(self):
self.artifact("ckp", 3)
self.artifact("jnl", 1)
self.artifact("jnl", 2)
self.artifact("jnl", 3)
result = self.run_backup('''rm () { echo 'mock delete denied' >&2; return 13; }
KEEPCKPS=1; KEEPJNLS=2; OFFLINEJNLNUM=1000
remove_old_checkpoints_and_journals''')
self.assertEqual(result.returncode, 97)
self.assertIn("Failed to remove journal", result.stderr)
self.assertIn("mock delete denied", (self.root / "run.log").read_text())
def test_restore_ignores_foreign_or_journal_checksums(self):
good = self.artifact("ckp", 5, directory=True)
os.utime(Path(str(good) + ".md5"), (1, 1))
self.artifact("jnl", 9)
(self.checkpoints / "other.ckp.9").mkdir()
(self.checkpoints / "other.ckp.9.md5").write_text("other")
result = self.run_backup('''DoParallelCheckpoints=1; NumCheckPointThreads=2
P4DBIN=fake_p4d
fake_p4d () { if [[ ${1:-} == -h ]]; then echo -jvp; else printf '%s\\n' "$@" > "$TEST_ROOT/restore.args"; fi; }
recreate_offline_db_files''')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((self.root / "restore.args").read_text().splitlines()[-1], str(good))
def test_missing_parallel_checkpoint_preserves_offline_database(self):
db = self.offline / "db.counters"
db.write_text("preserve")
(self.checkpoints / "p4.test.ckp.1.md5").write_text("orphan")
result = self.run_backup('DoParallelCheckpoints=1; recreate_offline_db_files')
self.assertEqual(result.returncode, 97)
self.assertEqual(db.read_text(), "preserve")
def test_missing_serial_checkpoint_preserves_offline_database(self):
db = self.offline / "db.counters"
db.write_text("preserve")
(self.checkpoints / "p4.test.ckp.1.gz.md5").write_text("orphan")
result = self.run_backup('DoParallelCheckpoints=0; recreate_offline_db_files')
self.assertEqual(result.returncode, 97)
self.assertEqual(db.read_text(), "preserve")
def test_rsync_dry_run_failure_stops_copy_and_keeps_diagnostics(self):
result = self.run_backup('''rsync () { echo 'mock dry run denied' >&2; return 23; }
rsync_with_preflight "$TEST_ROOT/source" "$TEST_ROOT/target" 0''')
self.assertNotEqual(result.returncode, 0)
self.assertIn("mock dry run denied", (self.root / "run.log").read_text())
def test_rsync_missing_statistics_stops_copy(self):
result = self.run_backup('''rsync () { echo 'unexpected rsync statistics'; }
rsync_with_preflight "$TEST_ROOT/source" "$TEST_ROOT/target" 0''')
self.assertEqual(result.returncode, 1)
self.assertIn("Cannot determine", (self.root / "run.log").read_text())
def test_rsync_invalid_free_space_stops_copy(self):
result = self.run_backup('''rsync () { echo 'Total transferred file size: 1,024 bytes'; }
df () { echo 'invalid output'; }
rsync_with_preflight "$TEST_ROOT/source" "$TEST_ROOT/target" 0''')
self.assertEqual(result.returncode, 1)
self.assertIn("Invalid available space", (self.root / "run.log").read_text())
def test_rsync_keeps_paths_literal_and_converts_bytes(self):
source = str(self.root / 'source $(touch injected)')
result = self.run_backup('''rsync () {
case " $* " in
*' --dry-run '*) echo 'Total transferred file size: 1,024 bytes' ;;
*) printf '%s\\n' "$@" > "$TEST_ROOT/rsync.args" ;;
esac
}
df () { printf 'Filesystem 1024-blocks Used Available Capacity Mounted on\\nmock 100 98 2 98%% /\\n'; }
rsync_with_preflight "$SOURCE" "$TEST_ROOT/target with spaces" 1''', {"SOURCE": source})
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((self.root / "rsync.args").read_text().splitlines()[-2:], [source + "/", str(self.root / "target with spaces")])
self.assertFalse((self.root / "injected").exists())
def test_readonly_config_failure_prevents_swap_copy(self):
(self.root / "db.config").touch()
(self.root / "server.id").write_text("test\n")
p4d = self.root / "fake_p4d"
p4d.write_text("#!/bin/bash\necho 'mock configuration read denied' >&2\nexit 8\n")
p4d.chmod(0o755)
result = self.run_backup('''P4DBIN=$TEST_ROOT/fake_p4d; P4ROOT=$TEST_ROOT; SERVERID=test
copy_readonly_clients_dir''')
self.assertEqual(result.returncode, 1)
self.assertIn("mock configuration read denied", (self.root / "run.log").read_text())
def test_missing_journals_directory_is_not_scanned_from_current_directory(self):
result = self.run_backup('JOURNALS=$TEST_ROOT/missing; gzip_mv_journals')
self.assertEqual(result.returncode, 97)
self.assertIn("Cannot enter journals", result.stderr)
def test_counter_dump_failure_is_not_an_empty_database(self):
(self.root / "db.counters").write_text("not empty")
result = self.run_backup('''P4ROOT=$TEST_ROOT; P4DBIN=fake_p4d
fake_p4d () { echo 'mock corrupt counters' >&2; return 8; }
get_journalnum''')
self.assertEqual(result.returncode, 97)
self.assertIn("Cannot read the journal counter", result.stderr)
self.assertIn("mock corrupt counters", (self.root / "run.log").read_text())
def test_valid_empty_counter_dump_stays_zero(self):
(self.root / "db.counters").touch()
result = self.run_backup('''P4ROOT=$TEST_ROOT; P4DBIN=fake_p4d
fake_p4d () { return 0; }
EDGESERVER=0; REPLICASERVER=0; STANDBYSERVER=0
get_journalnum
printf '%s %s' "$JOURNALNUM" "$CHECKPOINTNUM"''')
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout, "0 1")
def test_disk_threshold_supports_bytes_units_and_percent(self):
for value, total, expected in [("0", "", "0"), ("250M", "", "262144000"),
("20%", "1000", "200"), ("08K", "", "8192")]:
with self.subTest(value=value):
result = self.run_backup('convert_to_bytes "$VALUE" "$TOTAL"',
{"VALUE": value, "TOTAL": total})
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout.strip(), expected)
def test_invalid_disk_threshold_is_rejected(self):
for value, total in [("Undefined", ""), ("1.5G", ""), ("101%", "1000"), ("20%", "bad")]:
with self.subTest(value=value):
result = self.run_backup('convert_to_bytes "$VALUE" "$TOTAL"',
{"VALUE": value, "TOTAL": total})
self.assertEqual(result.returncode, 1)
self.assertIn("Invalid", result.stderr)
def test_failed_disk_query_is_logged_and_rejected(self):
result = self.run_backup('''P4BIN=fake_p4; AWK=awk; CUT=cut
fake_p4 () { echo 'mock disk query failed' >&2; return 8; }
get_journal_stats''')
self.assertEqual(result.returncode, 97)
self.assertIn("mock disk query failed", (self.root / "run.log").read_text())
class CacheCleanupReview(unittest.TestCase):
def setUp(self):
self.fixture = maintenance_fixtures.MaintenanceLogging(methodName="runTest")
self.fixture.setUp()
self.addCleanup(self.fixture.doCleanups)
f = self.fixture
(f.home / "depots/depot").mkdir(parents=True)
f.write_executable(f.home / "bin/p4_1", "#!" + BASH + '''
case "$*" in
*lbr.replication*) echo readonly ;;
*dm.shelve.promote*)
if [[ ${MOCK_PROMOTE_FAIL:-0} == 1 ]]; then echo 'mock config failure' >&2; exit 9; fi
echo "${MOCK_PROMOTE:-1}" ;;
esac
''')
f.write_executable(f.mockbin / "findmnt", "#!" + BASH + '\necho rw,relatime\n')
f.write_executable(f.mockbin / "df", "#!" + BASH + "\nprintf 'Filesystem 1024-blocks Used Available Capacity Mounted on\\nmock 100 95 5 95%% /\\n'\n")
f.write_executable(f.mockbin / "find", "#!" + BASH + '''
[[ $1 == "$SDP_TEST_ROOT/metrics" ]] && exit 0
echo invoked >> "$SDP_TEST_ROOT/deletions"
if [[ ${MOCK_FIND_FAIL:-0} == 1 ]]; then echo 'mock delete failure' >&2; exit 13; fi
printf '..'
''')
def test_disabled_promotion_never_deletes_files(self):
f = self.fixture
result = f.run_script("cacheclean.sh", "1", extra={"MOCK_PROMOTE": "0"})
self.assertEqual(result.returncode, 1)
self.assertFalse((f.root / "deletions").exists())
self.assertIn("dm.shelve.promote=1", f.log("cacheclean"))
self.assertEqual(f.event("cacheclean")["status"], "failure")
def test_promotion_query_failure_keeps_diagnostics(self):
f = self.fixture
result = f.run_script("cacheclean.sh", "1", extra={"MOCK_PROMOTE_FAIL": "1"})
self.assertEqual(result.returncode, 1)
self.assertFalse((f.root / "deletions").exists())
self.assertIn("mock config failure", f.log("cacheclean"))
def test_failed_deletion_worker_fails_run(self):
f = self.fixture
result = f.run_script("cacheclean.sh", "1", extra={"MOCK_FIND_FAIL": "1"})
self.assertEqual(result.returncode, 1)
self.assertIn("mock delete failure", f.log("cacheclean"))
self.assertEqual(f.event("cacheclean")["status"], "failure")
def test_successful_deletion_counts_are_logged(self):
f = self.fixture
result = f.run_script("cacheclean.sh", "1")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(f.event("cacheclean")["files_removed"], 2)
self.assertEqual(f.event("cacheclean")["status"], "success")
class RecoveryReview(unittest.TestCase):
def setUp(self):
self.fixture = maintenance_fixtures.MaintenanceLogging(methodName="runTest")
self.fixture.setUp()
self.addCleanup(self.fixture.doCleanups)
f = self.fixture
for name in ["offline_db", "checkpoints"]:
(f.home / name).mkdir()
with (f.common / "p4_vars").open("a") as out:
out.write('''export P4DBIN="$P4HOME/bin/p4d_stub" P4JOURNAL="$LOGS/journal"
export CHECKPOINTS="$P4HOME/checkpoints" P4CKP_PREFIX=p4_1
''')
f.write_executable(f.common / "backup_functions.sh", '''
OFFLINE_DB="$P4HOME/offline_db"
log () { echo "$*" >> "$LOGFILE"; }
die () { log "$*"; exit 97; }
check_vars () { :; }; set_vars () { :; }; check_uid () { :; }; check_dirs () { :; }
log_init () { :; }; rotate_log_file () { :; }; sdp_log_init () { :; }
ckp_running () { :; }; ckp_complete () { :; }; mail_log_file () { :; }
verify_checkpoint () { :; }
restore_checkpoint () { "$P4DBIN" -r "$2" -jr "$1" >> "$LOGFILE" 2>&1; }
switch_db_files () { local rebuilt=${2:-$OFFLINE_DB}; mv "$rebuilt"/db.* "$P4ROOT"/; }
complete_db_switch () { :; }
dump_checkpoint_from_root () { DoParallelCheckpoints=1; mkdir "$CHECKPOINTS/$P4CKP_PREFIX.ckp.$CHECKPOINTNUM"; }
DoParallelCheckpoints=1
stop_p4d () { echo stopped >> "$SDP_TEST_ROOT/actions"; }
start_p4d () { echo started >> "$SDP_TEST_ROOT/actions"; }
get_offline_journal_num () {
[[ -f "$OFFLINE_DB/offline_db_usable.txt" ]] || die 'offline database marker missing'
OFFLINECHECKPOINTNUM=1
}
''')
f.write_executable(f.home / "bin/p4d_stub", "#!" + BASH + '''
count=0
[[ -f "$SDP_TEST_ROOT/p4d_count" ]] && count=$(cat "$SDP_TEST_ROOT/p4d_count")
count=$((count + 1)); echo "$count" > "$SDP_TEST_ROOT/p4d_count"
if [[ "$count" == "${MOCK_FAIL_STAGE:-0}" ]]; then echo 'mock p4d failure' >&2; exit 7; fi
# A checkpoint dump reads the source; it must not overwrite the live DB.
[[ " $* " != *" -jd "* ]] || exit 0
# Simulate restore into the target passed by the staging caller.
while [[ $# -gt 0 ]]; do
if [[ $1 == -r ]]; then target=$2; shift 2; else shift; fi
done
printf restored > "${target:-$P4HOME/offline_db}/db.counters"
''')
(f.home / "root/db.counters").write_text("live database")
(f.home / "root/server.id").write_text("replica")
(f.home / "root/sdp_server_type.txt").write_text("p4d_standby")
(f.home / "root/statejcopy").write_text("3/1024")
(f.logs / "journal.3").write_text("recovery journal")
(f.root / "master.ckp").mkdir()
for name in ["root", "offline_db"]:
real = f.home / (name + "_physical")
(f.home / name).rename(real)
(f.home / name).symlink_to(real)
f.write_executable(f.mockbin / "mv", "#!" + __import__("sys").executable + '\nimport os, subprocess, sys\nargs = sys.argv[1:]\nif "-Tf" in args: os.replace(args[-2], args[-1])\nelse: sys.exit(subprocess.call(["/bin/mv"] + args))\n')
def test_failover_does_not_start_after_failed_journal_replay(self):
f = self.fixture
result = f.run_script("convert_standby_to_master.sh", "1", extra={"MOCK_FAIL_STAGE": "1"})
self.assertEqual(result.returncode, 97, result.stderr)
self.assertEqual((f.root / "actions").read_text(), "stopped\n")
self.assertIn("mock p4d failure", f.log("convert_standby_to_master"))
def test_failover_accepts_source_identity_after_position_record(self):
f = self.fixture
(f.home / "root/statejcopy").write_text("3/1024\nmaster-id\n")
result = f.run_script("convert_standby_to_master.sh", "1")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((f.root / "actions").read_text(), "stopped\nstarted\n")
self.assertEqual((f.home / "root/server.id").read_text(), "master-id\n")
self.assertEqual((f.logs / "journal").read_text(), "recovery journal")
def test_failover_accepts_legacy_position_without_final_newline(self):
f = self.fixture
result = f.run_script("convert_standby_to_master.sh", "1")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual((f.root / "actions").read_text(), "stopped\nstarted\n")
self.assertEqual((f.logs / "journal").read_text(), "recovery journal")
def test_failover_rejects_malformed_position_before_identity_change(self):
f = self.fixture
for state in ("", "bad", "3\nmaster-id\n", "3/invalid\nmaster-id\n", "3/1024/extra\nmaster-id\n"):
with self.subTest(state=state):
(f.root / "actions").unlink(missing_ok=True)
(f.home / "root/statejcopy").write_text(state)
result = f.run_script("convert_standby_to_master.sh", "1")
self.assertEqual(result.returncode, 97, result.stderr)
self.assertEqual((f.root / "actions").read_text(), "stopped\n")
self.assertEqual((f.home / "root/server.id").read_text(), "replica")
self.assertTrue((f.logs / "journal.3").exists())
self.assertFalse((f.root / "p4d_count").exists())
def test_failover_validates_journal_before_changing_identity(self):
f = self.fixture
(f.logs / "journal.3").unlink()
result = f.run_script("convert_standby_to_master.sh", "1")
self.assertEqual(result.returncode, 97)
self.assertEqual((f.root / "actions").read_text(), "stopped\n")
self.assertEqual((f.home / "root/server.id").read_text(), "replica")
def test_failover_reads_the_final_journal_after_stopping(self):
f = self.fixture
helper = f.common / "backup_functions.sh"
helper.write_text(helper.read_text().replace(
'stop_p4d () { echo stopped >> "$SDP_TEST_ROOT/actions"; }',
'''stop_p4d () {
echo stopped >> "$SDP_TEST_ROOT/actions"
echo '4/2048' > "$P4ROOT/statejcopy"
echo 'new final journal' > "$LOGS/journal.4"
}'''))
result = f.run_script("convert_standby_to_master.sh", "1", extra={"MOCK_FAIL_STAGE": "1"})
self.assertEqual(result.returncode, 97)
self.assertEqual((f.logs / "journal").read_text(), "new final journal\n")
self.assertTrue((f.logs / "journal.3").exists())
def test_edge_recovery_failure_preserves_live_database(self):
f = self.fixture
for stage in [1, 2, 3]:
with self.subTest(stage=stage):
(f.root / "p4d_count").write_text("0")
result = f.run_script("recover_edge.sh", "1", str(f.root / "master.ckp"),
extra={"MOCK_FAIL_STAGE": str(stage)})
self.assertEqual(result.returncode, 97, result.stderr)
self.assertEqual((f.home / "root/db.counters").read_text(), "live database")
if (f.root / "actions").exists():
self.assertNotIn("started", (f.root / "actions").read_text())
self.assertIn("mock p4d failure", f.log("recover_edge"))
def test_edge_success_marks_offline_db_and_preserves_number_prefix(self):
f = self.fixture
old = f.home / "checkpoints/p4_1.ckp.1"
newer = f.home / "checkpoints/p4_1.ckp.10"
old.mkdir(); newer.mkdir()
result = f.run_script("recover_edge.sh", "1", str(f.root / "master.ckp"))
self.assertEqual(result.returncode, 0, result.stderr + f.log("recover_edge"))
self.assertTrue((f.home / "offline_db/offline_db_usable.txt").exists())
self.assertTrue(newer.exists())
self.assertTrue(old.exists())
self.assertTrue(list((f.home / "checkpoints").glob(".sdp-edge-dump.*/previous-checkpoint/p4_1.ckp.1")))
def test_latest_restore_ignores_journal_and_other_instance(self):
f = self.fixture
candidates = f.home / "checkpoints"
good = candidates / "p4_1.ckp.2.gz.md5"
good.touch(); os.utime(good, (1, 1))
(candidates / "p4_1.jnl.3.gz.md5").touch()
(candidates / "p4_10.ckp.4.gz.md5").touch()
source = (BIN / "load_checkpoint.sh").read_text()
start = source.index("function find_latest_checkpoint_md5 () {")
end = source.index("\n#------------------------------------------------------------------------------", start)
result = subprocess.run([BASH, "-c", source[start:end] + '\nfind_latest_checkpoint_md5 "$1"',
"test", str(candidates / "p4_1")], capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout.strip(), str(good))
class PasswordFileReview(unittest.TestCase):
def test_failed_service_password_setup_leaves_no_plaintext_file(self):
for name in ["mkedge", "mkedge-standby", "mkstandby", "mkstandby_shared"]:
with self.subTest(name=name):
f = maintenance_fixtures.MaintenanceLogging(methodName="runTest")
f.setUp()
try:
f.write_executable(f.home / "bin/p4_1", "#!" + BASH + '''
case "$1 $2" in
'server -o') printf 'Services:\tstandard\n' ;;
'server -i'|'user -f') cat >/dev/null ;;
'user -o') echo 'Type: standard' ;;
'-ztag configure') printf '... Value 0\\n' ;;
'passwd '*) cat > "$SDP_TEST_ROOT/password_received"; echo 'mock passwd failure' >&2; exit 7 ;;
esac
''')
# A preexisting unrelated file must not be overwritten.
sentinel = f.root / "passwd.txt"
sentinel.write_text("preserve unrelated file")
secret = "test password with * spaces"
result = f.run_script(name + ".sh", "1", "replica", secret, "master:1666", "upstream")
self.assertNotEqual(result.returncode, 0)
self.assertEqual(sentinel.read_text(), "preserve unrelated file")
self.assertEqual((f.root / "password_received").read_text(), secret + "\n" + secret + "\n")
self.assertNotIn(secret, f.log(name))
finally:
f.doCleanups()
if __name__ == "__main__":
unittest.main()
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #3 | 34011 | Russell C. Jackson (Rusty) |
Reduce checkpoint thread defaults to 16, tolerate missing journal numbers, and clean dedicated send queues during stopped database recreation. Resolve client.sendq.dir and client.readonly.dir from the local database with the effective server identity. Preserve all shared readonly storage with a warning, protect database and journal paths, and clean both database roots while stopped. Correct readonly configuration lookup and nested copy destinations. Preserve journal archival thresholds, intentional server.locks removal, and existing shell modes. Update operational documentation and regression coverage. Validation passed on the exact source manifest: 44 platform stages, 30 topology scenarios, 112 historical scenarios across p4d 2023.1-2026.1 on UBI 8/9, 70 focused tests on each of Bash 3.2/5.3, and the combined release gate. RHEL tests use UBI containers; historical 2023 releases use x86 emulation. |
||
| #2 | 34004 | Russell C. Jackson (Rusty) |
Improve SDP backup/recovery, Maintenance, logging and cloud operation. Add owned checkpoint locks, recovery-aware retention, preserved database switches, bounded cleanup and coordinated AWS/Azure snapshots. Fix service-user password initialization, edge staging, standby promotion state parsing, proxy cache setup, typed depot verification and historical-server configuration/error handling. Remove unused OTP programs; keep Windows removed, server.locks cleanup and the journal-count condition unchanged. Add no global shell strict modes. Update operational documentation and add reproducible mkdirs.sh/mkdirs.cfg container assurance. Validate Ubuntu 26.04 and UBI 8.10/9.8/10.2 across both Python runtimes: 44 stages; 428 offline tests per runtime/OS, zero offline skips; 19 deployed-archive comparisons per combination. Three six-node topology runs pass all 30 recovery/failure scenarios. P4D 2023.1 through 2026.1 on UBI 8/9 pass all 14 cells and 98 scenarios. Static, documentation and provenance checks pass. Containers do not certify every fleet kernel, patch build or integration. Tested source manifest SHA-256: e1a23e17b8ced8c1148d9a250589977c6f6e98606bf2a81dc3ff5d7c909e3695 Deployed comparison archive SHA-256: 1bd23217356ee3808e040d39aea5be9519bda7c8f2b4924656a70aff8ad7293a |
||
| #1 | 34003 | Russell C. Jackson (Rusty) |
Improve SDP diagnostics and correct maintenance/recovery failures. Add durable logs and explicit failure handling across operational, Maintenance, setup, trigger, snapshot and download scripts. Correct retention selection, restore preflights, environment setup and command/API handling. Include offline regression coverage and the review report with deferred improvement proposals. Include requested journal archiving and automatic acceptance of new SSH host keys for remote rsync. Preserve the NumJnls > 2 threshold and existing shell options. Remove Windows scripts as requested. Validation: full review suite 138 passed, 8 skipped; subsequent rsync/logging suite 29 passed. Shell/Python/JSON static checks passed; no live operations run. |