blob: 8032ea54f8b6f9f9a0dc5708f697165768e43c8c [file] [log] [blame]
#!/usr/bin/env python3
import argparse
import sys
import time
import toml
from os import path
from telnetlib import Telnet
from types import MethodType
from xdg import BaseDirectory
def expect_or_raise(conn, patterns, timeout=None):
i, m, d = conn.expect([bytes(p, 'ascii') for p in patterns], timeout)
if i == -1:
msg = "Match failed, expected '%s', got '%s'" % (str(patterns), d)
print(msg, file=sys.stderr)
raise ValueError
return i, m, d
def encode_and_write(conn, comm="", sep="\n"):
# Slow down the writes to help poor ol' serial-over-telnet
for c in comm + sep:
conn.write(bytes(c, 'ascii'))
time.sleep(0.01)
def init_telnet(host, port=0, timeout=None):
conn = Telnet(host, port, timeout)
conn.encode_and_write = MethodType(encode_and_write, conn)
conn.expect_or_raise = MethodType(expect_or_raise, conn)
return conn
def main():
parser = argparse.ArgumentParser()
parser.add_argument("machine", nargs="?")
parser.add_argument("-l", "--list-machines", action="store_true")
parser.add_argument("-i", "--initramfs", action="store_true")
args = parser.parse_args()
confbase = BaseDirectory.save_config_path("obmc-scripts")
conffile = path.join(confbase, "netboot")
if not path.exists(conffile):
print("Missing configuration file: %s" % (conffile))
sys.exit(1)
conf = toml.load(conffile)
if args.list_machines:
print("Machines:", *list(sorted(conf.keys())), sep="\n\t")
sys.exit(0)
if not args.machine:
print("Machine name required")
sys.exit(1)
mach = conf[args.machine]
console = mach["console"]
conn = init_telnet(console["host"], console["port"])
try:
conn.encode_and_write()
i, m, d = conn.expect_or_raise([
"%s login:" % (mach["platform"]),
"root@%s:.*#" % (mach["platform"]),
"root@%s:.*#" % (args.machine),
"ast#",
"# ",
], 5)
if i != 3:
if i == 0:
conn.encode_and_write(mach["user"])
conn.read_until(b"Password:")
conn.encode_and_write(mach["password"])
conn.expect_or_raise(["root@%s:.*#" % (mach["platform"])])
conn.encode_and_write("reboot")
conn.expect_or_raise(["Hit any key to stop autoboot"])
conn.encode_and_write()
for comm in mach["u-boot"]["commands"]:
conn.encode_and_write(comm)
if "tftp" in comm:
i, m, d = conn.expect_or_raise([
r"Bytes transferred = \d+ \([0-9a-f]+ hex\)",
"Not retrying...",
r"## Warning:",
r"[*]{3} ERROR:",
"Abort",
"Retry count exceeded; starting again",
])
if i > 0:
print("Error detected, exiting", file=sys.stderr)
return
if args.initramfs:
conn.encode_and_write("setenv bootargs console=ttyS4,115200n root=/dev/ram rw earlyprintk debug")
conn.read_until(b"ast#")
else:
conn.encode_and_write("printenv set_bootargs")
i, m, d = conn.expect_or_raise([
"set_bootargs=.*$",
"## Error: \"set_bootargs\" not defined",
], 1)
if i == 0:
conn.encode_and_write("run set_bootargs")
conn.read_until(b"ast#")
conn.encode_and_write("bootm")
conn.read_until(b"Starting kernel")
finally:
conn.close()
if __name__ == "__main__":
main()