import os,json,pathlib,subprocess,time,sys,urllib.parse,ipaddress
os.umask(0o077);R=pathlib.Path(__file__).parent
sys.path.insert(0,'/workspace/contextra-analytics-runtime-lifecycle-refactor')
import yaml
from tools.validate_deployment import load_env_file
def shell(cmd):return subprocess.check_output(cmd,text=True,timeout=10)
def gpu():return int(shell(['nvidia-smi','--id=0','--query-gpu=memory.used','--format=csv,noheader,nounits']).strip())
assert not (R/'result.json').exists()
assert not (R/'rtsp-resources.json').exists()
assert json.loads((R/'cpu-gate.json').read_text())['pass'] is True
env=load_env_file('/workspace/contextra-runtime-config/runtime.env')
specs=yaml.safe_load((pathlib.Path(env['CONTEXTRA_RUNTIME_STATE_ROOT'])/'streams_runtime.yaml').read_text())['added']
assert len(specs)==1;s=specs[0];u=urllib.parse.urlsplit(s['uri']);ip=ipaddress.ip_address(u.hostname)
assert u.scheme=='rtsp' and ip.version==4 and not ip.is_loopback
assert s.get('source_options',{}).get('transport','tcp')=='tcp'
data=json.loads(shell(['docker','inspect','contextra-analytics-1']))[0];assert data['State']['Status']=='exited'
baseline=gpu();assert baseline<16384
assert __import__('shutil').disk_usage(R).free > 2*1024**3
import hashlib
model=pathlib.Path('/data/contextra/models/triton/RFDETRMedium')
assert hashlib.sha256((model/'2/model.plan').read_bytes()).hexdigest()=='5fdf1e9c55ab947a3b7d5f7f6bdceaf1e36a9e52efdf86f5a15d3b99b8631d1e'
assert hashlib.sha256((model/'config.pbtxt').read_bytes()).hexdigest()=='5e5a4d22786f8b5218ac821379fbec091d9e3006f62c880ee3e3da5ced2f0e0b'
mem=dict((l.split(':')[0],int(l.split()[1])) for l in pathlib.Path('/proc/meminfo').read_text().splitlines())
assert mem['MemAvailable']>10*1024**2
assert data['Image']=='sha256:228fc2493dcb81454453d05a66528dd5927d74a40fb85f76d6950afbf0b56d1a'
private=R/'source-private.json';assert not private.exists()
private.write_text(json.dumps({'uri':s['uri'],'options':s.get('source_options',{}),'threshold':s.get('inference_profile',{}).get('score_threshold',0.5)}));private.chmod(0o600)
name='codex-stdin-eos-r01';peak=baseline;start=time.monotonic();reason=None;p=None
try:
    shell(['docker','run','-d','--rm','--pull','never','--name',name,'--network','bridge','--gpus','device=0',
      '--cpus','4','--memory','8g','--ulimit','core=0','-e','NVIDIA_VISIBLE_DEVICES=0',
      '-e','NVIDIA_DRIVER_CAPABILITIES=compute,video,utility','-e','PYTHONDONTWRITEBYTECODE=1',
      '-e','LD_LIBRARY_PATH=/opt/tritonserver/lib:/opt/nvidia/deepstream/deepstream/lib:/usr/local/cuda/lib64:/usr/local/nvidia/lib64',
      '--mount','type=bind,src=/data/contextra/models/triton/RFDETRMedium,dst=/models/RFDETRMedium,readonly',
      '--mount','type=bind,src=/tmp/codex/ltb1021/2026-09-10_preprocess-isolation_r01/generated,dst=/configs,readonly',
      '--tmpfs','/tmp:rw,size=128m','--mount',f'type=bind,src={private},dst=/source.json,readonly',
      '--mount',f'type=bind,src={R},dst=/evidence','--entrypoint','sleep',data['Image'],'280'])
    pid=int(shell(['docker','inspect','--format','{{.State.Pid}}',name]).strip())
    assert pid>1
    assert os.readlink(f'/proc/{pid}/ns/net')!=os.readlink('/proc/self/ns/net')
    prefix=['nsenter','-t',str(pid),'-n','iptables','-w','2']
    for args in [['-P','OUTPUT','DROP'],['-A','OUTPUT','-o','lo','-j','ACCEPT'],
                 ['-A','OUTPUT','-p','tcp','-d',str(ip),'--dport',str(u.port or 554),'-j','ACCEPT']]:
        subprocess.run(prefix+args,check=True,capture_output=True,timeout=5)
    with (R/'rtsp.log').open('w') as log:
        p=subprocess.Popen(['docker','exec',name,'timeout','240s','python3','/evidence/inside.py'],stdout=log,stderr=subprocess.STDOUT)
        while p.poll() is None:
            peak=max(peak,gpu())
            if peak-baseline>8192 or time.monotonic()-start>250:reason='TIME_OR_GPU_CAP';break
            time.sleep(1)
finally:
    subprocess.run(['docker','kill',name],capture_output=True,timeout=10)
    if p is not None:p.wait(timeout=15)
    private.unlink(missing_ok=True)
summary=dict(returncode=p.returncode if p else None,reason=reason,gpu_before=baseline,gpu_peak=peak,
             gpu_after=gpu(),elapsed_s=round(time.monotonic()-start,2),network='isolated namespace: loopback + approved TCP peer only')
(R/'rtsp-resources.json').write_text(json.dumps(summary,indent=2));print(json.dumps(summary))
if (R/'live.json').exists():print((R/'live.json').read_text())

