diff --git a/labsim/console-apply.py b/labsim/console-apply.py index 82b1f42..a15bb90 100755 --- a/labsim/console-apply.py +++ b/labsim/console-apply.py @@ -38,23 +38,39 @@ def main() -> int: # 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 # 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): i = c.expect([r"login:", r"\$ ", r"# ", pexpect.TIMEOUT], timeout=15) if i == 0: c.sendline(args.user) c.expect("Password:", timeout=30) c.sendline(args.password) - c.expect(r"\$ ", timeout=60) + c.expect([r"\$ ", r"# "], timeout=60) break - if i in (1, 2): + if i == 1: + break + if i == 2: + in_config = True break c.sendline("") else: print("never reached a prompt", file=sys.stderr) return 1 - c.sendline("configure") - c.expect(r"# ", timeout=60) + 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.expect(r"# ", timeout=60) for cmd in cmds: c.sendline(cmd) @@ -69,10 +85,14 @@ def main() -> int: commit_out = c.before or "" c.sendline("save") 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.expect(r"\$ ", timeout=60) + c.expect([r"\$ ", r"# ", pexpect.TIMEOUT], timeout=60) c.sendline("exit") - c.close() + c.close(force=True) bad = [l for l in commit_out.splitlines() if "failed" in l.lower() or "error" in l.lower()]