Release new version 0.108
[grml-debootstrap.git] / tests / serial-console-connection
1 #!/usr/bin/env python
2 import argparse
3 import pexpect
4 import serial
5 import sys
6 import time
7 from pexpect import fdpexpect, TIMEOUT
8
9 parser = argparse.ArgumentParser(description='Connect to serial console ' +
10                                  'to execute stuff')
11 parser.add_argument('--port', required=True,
12                     help='serial console device to connect ' +
13                     'to (e.g. /dev/pts/X)')
14 parser.add_argument('--hostname', default="buster",
15                     help='hostname of the system for login process ' +
16                     '(default: buster)')
17 parser.add_argument('--user', default="root",
18                     help='user name to use for login (default: root)')
19 parser.add_argument('--password', default="grml",
20                     help='password for login (default: grml)')
21 parser.add_argument('--tries', default="12", type=int,
22                     help='Number of retries for finding the login prompt')
23 parser.add_argument('--poweroff', action="store_true", default=False,
24                     help='send "poweroff" command after all other commands')
25 parser.add_argument('command', nargs='+',
26                     help='command to execute after logging in')
27
28
29
30 def print_ser_lines(ser):
31     for line in ser.readlines():
32         print("<<", line)  # line will be a binary string
33
34
35 def write_ser_line(ser, text):
36     print(">>", text)
37     ser.write(("%s\n" % text).encode())
38     ser.flush()
39
40
41 def login(ser, hostname, user, password, timeout=5):
42
43     child = fdpexpect.fdspawn(ser.fileno())
44     child.sendline("\n")
45
46     try:
47         child.expect("%s@%s" % (user, hostname), timeout=timeout)
48         return
49     except:
50         pass
51
52     print("Waiting for login prompt...")
53     child.expect("%s login:" % hostname, timeout=timeout)
54     print("Logging in...")
55     write_ser_line(ser, user)
56     time.sleep(1)
57     write_ser_line(ser, password)
58     time.sleep(1)
59
60     print("Waiting for shell prompt...")
61     child.expect("%s@%s" % (user, hostname), timeout=timeout)
62
63
64 def main():
65     args = parser.parse_args()
66     hostname = args.hostname
67     password = args.password
68     port = args.port
69     user = args.user
70     commands = args.command
71
72     ser = serial.Serial(port, 115200)
73     ser.flushInput()
74     ser.flushOutput()
75
76     success = False
77     for i in range(args.tries):
78         try:
79             print("Logging into %s via serial console [try %s]" % (port, i))
80             login(ser, hostname, user, password)
81             success = True
82             break
83         except Exception as except_inst:
84             print("Login failure (try %s):" % (i, ), except_inst, file=sys.stderr)
85             time.sleep(5)
86
87     if success:
88         write_ser_line(ser, "")
89         ser.timeout = 5
90         print_ser_lines(ser)
91         print("Running commands...")
92         for command in commands:
93             write_ser_line(ser, command)
94             print_ser_lines(ser)
95         if args.poweroff:
96             print("Sending final poweroff command...")
97             write_ser_line(ser, "poweroff")
98             ser.flush()
99             # after poweroff, the serial device will probably vanish. do not attempt reading from it anymore.
100
101     if not success:
102         sys.exit(1)
103
104 if __name__ == "__main__":
105     main()