55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""How many concurrent INTERACTIVE (`docker exec -i`) sessions does this host take?
|
||
|
|
|
||
|
|
Trivial non-interactive execs succeed 8-way, but the Phew SLA checker's 5-way
|
||
|
|
interactive test failed with
|
||
|
|
|
||
|
|
failed to open stdin fifo: error creating fifo ... -stdin: no such file
|
||
|
|
No such exec instance: <id>
|
||
|
|
|
||
|
|
which is a containerd exec-session limit, not a checker bug. Interactive execs
|
||
|
|
allocate a fifo + a tracked exec instance, so they hit a ceiling that plain
|
||
|
|
`docker exec <c> true` never approaches.
|
||
|
|
|
||
|
|
python3 panel/exec_probe_i.py [container] [N]
|
||
|
|
"""
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import time
|
||
|
|
from concurrent.futures import ThreadPoolExecutor
|
||
|
|
|
||
|
|
CONT = sys.argv[1] if len(sys.argv) > 1 else "phew_container_team1"
|
||
|
|
N = int(sys.argv[2]) if len(sys.argv) > 2 else 8
|
||
|
|
|
||
|
|
|
||
|
|
def interactive(i: int) -> tuple[int, str]:
|
||
|
|
"""Mimic the checker: `exec -i`, write a line, read the reply, exit."""
|
||
|
|
p = subprocess.Popen(
|
||
|
|
["docker", "exec", "-i", CONT, "sh", "-c",
|
||
|
|
"echo $$; read line; echo \"got:$line\""],
|
||
|
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||
|
|
stderr=subprocess.STDOUT, text=True, bufsize=0)
|
||
|
|
try:
|
||
|
|
out, _ = p.communicate("hello\n", timeout=45)
|
||
|
|
except subprocess.TimeoutExpired:
|
||
|
|
p.kill()
|
||
|
|
out = "TIMEOUT"
|
||
|
|
return p.returncode, (out or "").strip().replace("\n", " | ")[:150]
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> None:
|
||
|
|
print(f"container={CONT} N={N} interactive execs")
|
||
|
|
ok = 0
|
||
|
|
with ThreadPoolExecutor(max_workers=N) as ex:
|
||
|
|
for rc, out in ex.map(interactive, range(N)):
|
||
|
|
if rc == 0 and "got:hello" in out:
|
||
|
|
ok += 1
|
||
|
|
else:
|
||
|
|
print(f" FAIL rc={rc}: {out}")
|
||
|
|
print(f" {ok}/{N} interactive execs OK")
|
||
|
|
print("RESULT:", "PASS" if ok == N else f"limit reached at {ok}/{N}")
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|