blob: 47c0373f134e5c07d7a1235cbb33c166adab3147 [file] [log] [blame]
Andrew Jeffery75d9c242017-09-27 23:08:56 +09301#!/usr/bin/env python3
2
3import argparse
4import sys
5import time
Andrew Jeffery75d9c242017-09-27 23:08:56 +09306from os import path
7from telnetlib import Telnet
8from types import MethodType
Patrick Williamsa3db66b2022-12-04 16:27:08 -06009
10import toml
Andrew Jeffery75d9c242017-09-27 23:08:56 +093011from xdg import BaseDirectory
12
Patrick Williamsa3db66b2022-12-04 16:27:08 -060013
Andrew Jeffery75d9c242017-09-27 23:08:56 +093014def expect_or_raise(conn, patterns, timeout=None):
Patrick Williamsa3db66b2022-12-04 16:27:08 -060015 i, m, d = conn.expect([bytes(p, "ascii") for p in patterns], timeout)
Andrew Jeffery75d9c242017-09-27 23:08:56 +093016 if i == -1:
17 msg = "Match failed, expected '%s', got '%s'" % (str(patterns), d)
18 print(msg, file=sys.stderr)
19 raise ValueError
20 return i, m, d
21
Patrick Williamsa3db66b2022-12-04 16:27:08 -060022
Andrew Jeffery75d9c242017-09-27 23:08:56 +093023def encode_and_write(conn, comm="", sep="\n"):
24 # Slow down the writes to help poor ol' serial-over-telnet
25 for c in comm + sep:
Patrick Williamsa3db66b2022-12-04 16:27:08 -060026 conn.write(bytes(c, "ascii"))
Andrew Jeffery75d9c242017-09-27 23:08:56 +093027 time.sleep(0.01)
28
Patrick Williamsa3db66b2022-12-04 16:27:08 -060029
Andrew Jeffery75d9c242017-09-27 23:08:56 +093030def init_telnet(host, port=0, timeout=None):
31 conn = Telnet(host, port, timeout)
32 conn.encode_and_write = MethodType(encode_and_write, conn)
33 conn.expect_or_raise = MethodType(expect_or_raise, conn)
34 return conn
35
36
37def main():
38 parser = argparse.ArgumentParser()
Andrew Jeffery49b35be2017-09-28 10:32:20 +093039 parser.add_argument("machine", nargs="?")
40 parser.add_argument("-l", "--list-machines", action="store_true")
Andrew Jeffery291f0812017-10-07 00:52:56 +103041 parser.add_argument("-i", "--initramfs", action="store_true")
Andrew Jeffery75d9c242017-09-27 23:08:56 +093042 args = parser.parse_args()
43
44 confbase = BaseDirectory.save_config_path("obmc-scripts")
45 conffile = path.join(confbase, "netboot")
46 if not path.exists(conffile):
47 print("Missing configuration file: %s" % (conffile))
48 sys.exit(1)
49
50 conf = toml.load(conffile)
Andrew Jeffery49b35be2017-09-28 10:32:20 +093051 if args.list_machines:
52 print("Machines:", *list(sorted(conf.keys())), sep="\n\t")
53 sys.exit(0)
54
55 if not args.machine:
56 print("Machine name required")
57 sys.exit(1)
58
Andrew Jeffery75d9c242017-09-27 23:08:56 +093059 mach = conf[args.machine]
60 console = mach["console"]
61 conn = init_telnet(console["host"], console["port"])
62
63 try:
64 conn.encode_and_write()
Patrick Williamsa3db66b2022-12-04 16:27:08 -060065 i, m, d = conn.expect_or_raise(
66 [
67 "%s login:" % (mach["platform"]),
68 "root@%s:.*#" % (mach["platform"]),
69 "root@%s:.*#" % (args.machine),
70 "ast#",
71 "# ",
72 ],
73 5,
74 )
Andrew Jeffery75d9c242017-09-27 23:08:56 +093075
Andrew Jefferyac475772018-02-02 17:47:24 +103076 if i != 3:
Andrew Jeffery75d9c242017-09-27 23:08:56 +093077 if i == 0:
78 conn.encode_and_write(mach["user"])
79 conn.read_until(b"Password:")
80 conn.encode_and_write(mach["password"])
81 conn.expect_or_raise(["root@%s:.*#" % (mach["platform"])])
82
83 conn.encode_and_write("reboot")
84
85 conn.expect_or_raise(["Hit any key to stop autoboot"])
86 conn.encode_and_write()
87
88 for comm in mach["u-boot"]["commands"]:
89 conn.encode_and_write(comm)
90 if "tftp" in comm:
Patrick Williamsa3db66b2022-12-04 16:27:08 -060091 i, m, d = conn.expect_or_raise(
92 [
93 r"Bytes transferred = \d+ \([0-9a-f]+ hex\)",
94 "Not retrying...",
95 r"## Warning:",
96 r"[*]{3} ERROR:",
97 "Abort",
98 "Retry count exceeded; starting again",
99 ]
100 )
Andrew Jefferye4bf3362017-09-28 10:32:05 +0930101 if i > 0:
Andrew Jeffery75d9c242017-09-27 23:08:56 +0930102 print("Error detected, exiting", file=sys.stderr)
103 return
104
Andrew Jeffery291f0812017-10-07 00:52:56 +1030105 if args.initramfs:
Patrick Williamsa3db66b2022-12-04 16:27:08 -0600106 conn.encode_and_write(
107 "setenv bootargs "
108 + "console=ttyS4,115200n root=/dev/ram rw earlyprintk debug"
109 )
Andrew Jeffery75d9c242017-09-27 23:08:56 +0930110 conn.read_until(b"ast#")
Andrew Jeffery291f0812017-10-07 00:52:56 +1030111 else:
112 conn.encode_and_write("printenv set_bootargs")
Patrick Williamsa3db66b2022-12-04 16:27:08 -0600113 i, m, d = conn.expect_or_raise(
114 [
115 "set_bootargs=.*$",
116 '## Error: "set_bootargs" not defined',
117 ],
118 1,
119 )
Andrew Jeffery291f0812017-10-07 00:52:56 +1030120 if i == 0:
121 conn.encode_and_write("run set_bootargs")
122 conn.read_until(b"ast#")
Andrew Jeffery75d9c242017-09-27 23:08:56 +0930123
124 conn.encode_and_write("bootm")
125 conn.read_until(b"Starting kernel")
126 finally:
127 conn.close()
128
Patrick Williamsa3db66b2022-12-04 16:27:08 -0600129
Andrew Jeffery75d9c242017-09-27 23:08:56 +0930130if __name__ == "__main__":
131 main()