/
serial-console-connection
executable file
·112 lines (98 loc) · 3.81 KB
/
serial-console-connection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python
from __future__ import print_function
import argparse
import pexpect
import serial
import sys
import time
from pexpect import fdpexpect
parser = argparse.ArgumentParser(description='Connect to serial console ' +
'to execute stuff')
parser.add_argument('--port', required=True,
help='serial console device to connect ' +
'to (e.g. /dev/pts/X)')
parser.add_argument('--hostname', default="buster",
help='hostname of the system for login process ' +
'(default: buster)')
parser.add_argument('--pipefile', default="./serial0",
help='file name for named pipe file (for ' +
'interacting between host + VM via QEMU ' +
'(default: ./serial0)')
parser.add_argument('--vmoutput', default="vm-output.log",
help='filename for VM output (default: vm-output.log)')
parser.add_argument('--user', default="root",
help='user name to use for login (default: root)')
parser.add_argument('--password', default="grml",
help='password for login (default: grml)')
args = parser.parse_args()
def execute(port, hostname, user, baudrate=115200, timeout=5):
ser = serial.Serial(port, baudrate)
ser.flushInput()
ser.flushOutput()
ser.write("\n")
ser.flush()
child = fdpexpect.fdspawn(ser.fileno())
child.sendline("")
try:
print("Begin of execution inside VM")
child.expect("%s@%s" % (user, hostname), timeout=timeout)
child.sendline("/usr/local/bin/goss --gossfile /root/goss.yaml " +
"validate --format tap > /root/goss.tap ; " +
"echo $? > /root/goss.exitcode\n")
# NOTE - the serial0 is hardcoded here
child.sendline("cat /root/goss.tap > /dev/virtio-ports/serial0\n")
child.sendline("grep -q '^0' /root/goss.exitcode && " +
"echo clean_exit > /dev/virtio-ports/serial0\n")
child.sendline("grep -q '^0' /root/goss.exitcode || " +
"echo failure_exit > /dev/virtio-ports/serial0\n")
child.sendline("poweroff\n")
print("End of execution inside VM")
except Exception as except_inst:
print("Execution inside VM failed: ", except_inst)
def login(port, hostname, user, password,
baudrate=115200, timeout=5):
ser = serial.Serial(port, baudrate)
ser.flushInput()
ser.flushOutput()
child = fdpexpect.fdspawn(ser.fileno())
child.sendline("\n")
try:
child.expect("root@%s" % hostname, timeout=timeout)
return
except:
pass
print("Checking for login prompt...")
child.expect("%s login:" % hostname, timeout=timeout)
ser.write("%s\n" % user)
ser.flush()
time.sleep(1)
ser.write("%s\n" % password)
ser.flush()
time.sleep(1)
print("login ok...")
if __name__ == "__main__":
hostname = args.hostname
password = args.password
pipefile = args.pipefile
port = args.port
user = args.user
vmoutput = args.vmoutput
with open(pipefile, 'r') as output_pipe:
success = False
for i in range(12):
try:
print("Logging into {0} via serial "
"console [try {1}]".format(port, i))
login(port, hostname, user, password)
success = True
break
except Exception as except_inst:
print("Login failure (try {0}):".format(i),
except_inst, file=sys.stderr)
time.sleep(5)
if success:
execute(port, hostname, user)
with open(vmoutput, 'w') as fp:
output = output_pipe.read()
print(output)
fp.write(output)