+#!/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="stretch",
+ help='hostname of the system for login process ' +
+ '(default: stretch)')
+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)