test_operational_edges.py #1

  • //
  • guest/
  • russell_jackson/
  • sdp/
  • test/
  • test_operational_edges.py
  • View
  • Commits
  • Open Download .zip Download (5 KB)
#!/usr/bin/env python3
"""Offline configuration-generation and cloud-entry contracts; no live APIs."""
from pathlib import Path
import os
import shutil
import subprocess
import tempfile
import unittest

SDP = Path(__file__).resolve().parents[1]
BIN = SDP / "Server/Unix/p4/common/bin"
BASH = os.environ.get("SDP_TEST_BASH", shutil.which("bash"))


class OperationalEdges(unittest.TestCase):
    def setUp(self):
        self.temp = tempfile.TemporaryDirectory(prefix="sdp-operational-edges-")
        self.addCleanup(self.temp.cleanup)
        self.root = Path(self.temp.name)
        self.env = dict(os.environ, TEST_ROOT=str(self.root))

    def executable(self, path, body):
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text("#!" + BASH + "\n" + body)
        path.chmod(0o755)

    def run_script(self, path, args=(), extra=None):
        return subprocess.run([BASH, path, *args], env=dict(self.env, **(extra or {})),
                              capture_output=True, text=True, timeout=10)

    def broker_fixture(self):
        common = self.root / "common/bin"
        common.mkdir(parents=True)
        (self.root / "database").mkdir()
        (common / "p4_vars").write_text('''P4ROOT="$TEST_ROOT/database"
P4DBIN="$TEST_ROOT/p4d"
P4BROKERBIN="$TEST_ROOT/broker"
P4TICKETS=/p4/tickets
P4HOME=/p4/blue
LOGS=/p4/blue/logs
P4BROKERPORT=1669
P4PORT=127.0.0.1:1668
[email protected]
GREP=grep
''')
        (common / "backup_functions.sh").write_text('''copy_jd_table () { JDTmpDir="$TEST_ROOT/database"; }
remove_jd_tables () { touch "$TEST_ROOT/cleaned"; }
''')
        self.executable(self.root / "broker", '''[[ ${FAIL_BROKER:-0} == 0 ]] || { echo broker-denied >&2; exit 7; }
printf '%s\n' 'target = localhost:1666;' 'listen = 1667;' 'directory = /p4/broker;' 'tickets=/p4/broker/.p4tickets;' 'logfile = broker.log;' 'admin-email = [email protected];' 'debug-level = server=1;'
''')
        self.executable(self.root / "p4d", '''[[ ${FAIL_QUERY:-0} == 0 ]] || { echo query-denied >&2; exit 8; }
echo 'any: net.autotune = 1'
''')
        path = self.root / "generate.sh"
        path.write_text((BIN / "gen_default_broker_cfg.sh").read_text().replace("/p4/common/bin/", str(common) + "/"))
        return path

    def test_broker_generation_substitutes_endpoint_paths_and_autotune(self):
        script = self.broker_fixture()
        for autotune in (False, True):
            with self.subTest(autotune=autotune):
                if autotune:
                    (self.root / "database/db.config").touch()
                result = self.run_script(script, ["blue"])
                self.assertEqual(result.returncode, 0, result.stderr)
                for expected in ["127.0.0.1:1668", "1669", "/p4/blue/bin", "/p4/tickets", '"/p4/blue/logs/p4broker.log"', '"[email protected]"']:
                    self.assertIn(expected, result.stdout)
                self.assertEqual("net.autotune=1" in result.stdout, autotune)

    def test_broker_failure_never_becomes_successful_empty_configuration(self):
        script = self.broker_fixture()
        result = self.run_script(script, ["blue"], {"FAIL_BROKER": "1"})
        self.assertEqual(result.returncode, 1)
        self.assertEqual(result.stdout, "")
        self.assertIn("broker-denied", result.stderr)

    def test_server_query_failure_cleans_temporary_database_and_stops_generation(self):
        script = self.broker_fixture()
        (self.root / "database/db.config").touch()
        result = self.run_script(script, ["blue"], {"FAIL_QUERY": "1"})
        self.assertEqual(result.returncode, 1)
        self.assertEqual(result.stdout, "")
        self.assertTrue((self.root / "cleaned").exists())

    def test_azure_wrapper_selects_provider_and_preserves_instance_argument(self):
        cloud = SDP / "Server/Unix/p4/common/cloud"
        target = self.root / "cloud/azure/bin/snapshot.sh"
        self.executable(target, (cloud / "azure/bin/snapshot.sh").read_text())
        self.executable(self.root / "cloud/aws/bin/snapshot.sh", 'printf "<%s>\\n" "$@"\nexit 9\n')
        for args, expected in [(["blue"], "blue"), ([], "green")]:
            result = self.run_script(target, args, {"SDP_INSTANCE": "green"})
            self.assertEqual(result.returncode, 9)
            self.assertEqual(result.stdout, "<" + expected + ">\n<azure>\n")

    def test_ec2id_reads_current_cloud_init_link_and_reports_missing_link(self):
        script = self.root / "ec2id"
        link = self.root / "cloud-instance"
        original = SDP / "Server/Unix/p4/common/cloud/aws/bin/ec2id"
        script.write_text(original.read_text().replace("/var/lib/cloud/instance", str(link)))
        link.symlink_to("instances/i-012345abcdef")
        result = self.run_script(script)
        self.assertEqual(result.returncode, 0)
        self.assertEqual(result.stdout, "i-012345abcdef\n")
        link.unlink()
        result = self.run_script(script)
        self.assertNotEqual(result.returncode, 0)
        self.assertEqual(result.stdout, "")


if __name__ == "__main__":
    unittest.main()
# Change User Description Committed
#1 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