fix(labsim): console-apply must handle both VyOS prompts, not just $
Two failures from one strict expect, both hit while building the sim ISPs. A run that dies mid-config leaves the console parked in configuration mode. The next run then waits for the operational `$ ` prompt against a perfectly healthy VM and hangs until timeout, with nothing in the output to say why -- the box was sitting at `vyos@isp-dhcp#` the whole time. Login now accepts `# ` as well and discards the stale candidate rather than committing something nobody has seen. The same mistake at the exit step: insisting on `$ ` after `save` hung, AND left the console in config mode, which is what created the first failure for the following run. Now accepts either prompt. Known-bad, not fixed: the tool reports "committed and saved" when the set commands have not applied. Verified against the clone -- prompt showed the host-name change had landed while `grep -c dhcp-server` returned 0. The failure detection only inspects c.before for a few strings and evidently misses the real failure mode, so success is being reported without evidence. That needs fixing before this tool is trusted for anything; it is currently only safe to use with an independent check afterwards, which is how the gap was found. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DMVzWZgiKW2wquf5z8S1yH
This commit is contained in:
@@ -38,21 +38,37 @@ def main() -> int:
|
|||||||
# Log in. A freshly booted box may still be starting services, so allow a
|
# Log in. A freshly booted box may still be starting services, so allow a
|
||||||
# generous window and re-prod the console rather than failing on the first
|
# generous window and re-prod the console rather than failing on the first
|
||||||
# miss.
|
# miss.
|
||||||
|
#
|
||||||
|
# `# ` matters as much as `$ `: a previous run that died mid-config leaves
|
||||||
|
# the console sitting in configuration mode, and waiting only for the
|
||||||
|
# operational prompt then hangs forever against a perfectly healthy VM.
|
||||||
|
in_config = False
|
||||||
for _ in range(40):
|
for _ in range(40):
|
||||||
i = c.expect([r"login:", r"\$ ", r"# ", pexpect.TIMEOUT], timeout=15)
|
i = c.expect([r"login:", r"\$ ", r"# ", pexpect.TIMEOUT], timeout=15)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
c.sendline(args.user)
|
c.sendline(args.user)
|
||||||
c.expect("Password:", timeout=30)
|
c.expect("Password:", timeout=30)
|
||||||
c.sendline(args.password)
|
c.sendline(args.password)
|
||||||
c.expect(r"\$ ", timeout=60)
|
c.expect([r"\$ ", r"# "], timeout=60)
|
||||||
break
|
break
|
||||||
if i in (1, 2):
|
if i == 1:
|
||||||
|
break
|
||||||
|
if i == 2:
|
||||||
|
in_config = True
|
||||||
break
|
break
|
||||||
c.sendline("")
|
c.sendline("")
|
||||||
else:
|
else:
|
||||||
print("never reached a prompt", file=sys.stderr)
|
print("never reached a prompt", file=sys.stderr)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
if in_config:
|
||||||
|
# Drop whatever the previous run left half-built rather than committing
|
||||||
|
# a candidate nobody has seen.
|
||||||
|
print("console was left in config mode; discarding stale candidate",
|
||||||
|
file=sys.stderr)
|
||||||
|
c.sendline("discard")
|
||||||
|
c.expect(r"# ", timeout=60)
|
||||||
|
else:
|
||||||
c.sendline("configure")
|
c.sendline("configure")
|
||||||
c.expect(r"# ", timeout=60)
|
c.expect(r"# ", timeout=60)
|
||||||
|
|
||||||
@@ -69,10 +85,14 @@ def main() -> int:
|
|||||||
commit_out = c.before or ""
|
commit_out = c.before or ""
|
||||||
c.sendline("save")
|
c.sendline("save")
|
||||||
c.expect(r"# ", timeout=120)
|
c.expect(r"# ", timeout=120)
|
||||||
|
# Accept either prompt on the way out. Insisting on `$ ` here hangs against
|
||||||
|
# a healthy box -- and worse, leaves the console parked in config mode, so
|
||||||
|
# the NEXT run finds a `# ` it was not expecting either. One strict expect
|
||||||
|
# turned into two failures.
|
||||||
c.sendline("exit")
|
c.sendline("exit")
|
||||||
c.expect(r"\$ ", timeout=60)
|
c.expect([r"\$ ", r"# ", pexpect.TIMEOUT], timeout=60)
|
||||||
c.sendline("exit")
|
c.sendline("exit")
|
||||||
c.close()
|
c.close(force=True)
|
||||||
|
|
||||||
bad = [l for l in commit_out.splitlines()
|
bad = [l for l in commit_out.splitlines()
|
||||||
if "failed" in l.lower() or "error" in l.lower()]
|
if "failed" in l.lower() or "error" in l.lower()]
|
||||||
|
|||||||
Reference in New Issue
Block a user