#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1-or-later
-#
+# pylint: disable=broad-except
import argparse
import logging
-import pexpect
+import signal
import sys
+import time
+
+import pexpect
def run(args):
-
ret = 1
logger = logging.getLogger("test-shutdown")
+ logfile = None
- logger.info("spawning test")
- console = pexpect.spawn(args.command, args.arg, env={
- "TERM": "linux",
- }, encoding='utf-8', timeout=30)
+ if args.logfile:
+ logger.debug("Logging pexpect IOs to %s", args.logfile)
+ logfile = open(args.logfile, 'w')
+ elif args.verbose:
+ logfile = sys.stdout
- if args.verbose:
- console.logfile = sys.stdout
+ logger.info("spawning test")
+ console = pexpect.spawn(args.command, args.arg, logfile=logfile, env={
+ "TERM": "dumb",
+ }, encoding='utf-8', timeout=60)
- logger.debug("child pid %d" % console.pid)
+ logger.debug("child pid %d", console.pid)
try:
logger.info("waiting for login prompt")
console.send('c')
console.expect('screen1 ', 10)
+ logger.info('wait for the machine to fully boot')
+ console.sendline('systemctl is-system-running --wait')
+ console.expect(r'\b(running|degraded)\b', 60)
+
# console.interact()
console.sendline('tty')
console.expect(r'/dev/(pts/\d+)')
pty = console.match.group(1)
- logger.info("window 1 at line %s", pty)
+ logger.info("window 1 at tty %s", pty)
logger.info("schedule reboot")
console.sendline('shutdown -r')
console.sendcontrol('a')
console.send('0')
logger.info("verify broadcast message")
- console.expect('Broadcast message from root@H on %s' % pty, 2)
- console.expect('The system is going down for reboot at %s' % date, 2)
+ console.expect(f'Broadcast message from root@H on {pty}', 2)
+ console.expect(f'The system will reboot at {date}', 2)
logger.info("check show output")
console.sendline('shutdown --show')
- console.expect("Reboot scheduled for %s, use 'shutdown -c' to cancel" % date, 2)
+ console.expect(f"Reboot scheduled for {date}, use 'shutdown -c' to cancel", 2)
logger.info("cancel shutdown")
console.sendline('shutdown -c')
console.sendcontrol('a')
console.send('1')
- console.expect('The system shutdown has been cancelled', 2)
+ console.expect('System shutdown has been cancelled', 2)
logger.info("call for reboot")
console.sendline('sleep 10; shutdown -r now')
console.sendcontrol('a')
console.send('0')
- console.expect("The system is going down for reboot NOW!", 12)
+ console.expect("The system will reboot now!", 12)
logger.info("waiting for reboot")
- console.expect('H login: ', 30)
+ console.expect('H login: ', 60)
console.sendline('root')
console.expect('bash.*# ', 10)
ret = 0
except Exception as e:
logger.error(e)
- logger.info("killing child pid %d" % console.pid)
- console.terminate()
+ logger.info("killing child pid %d", console.pid)
- return ret
+ # Ask systemd-nspawn to stop and release the container's resources properly.
+ console.kill(signal.SIGTERM)
+ for _ in range(10):
+ if not console.isalive():
+ break
-if __name__ == '__main__':
+ time.sleep(1)
+ else:
+ # We haven't exited the loop early, so check if the process is
+ # still alive - if so, force-kill it.
+ if console.isalive():
+ console.terminate(force=True)
+
+ return ret
+
+def main():
parser = argparse.ArgumentParser(description='test logind shutdown feature')
parser.add_argument("-v", "--verbose", action="store_true", help="verbose")
+ parser.add_argument("--logfile", metavar='FILE', help="Save all test input/output to the given path")
parser.add_argument("command", help="command to run")
parser.add_argument("arg", nargs='*', help="args for command")
logging.basicConfig(level=level)
- sys.exit(run(args))
+ return run(args)
+
+if __name__ == '__main__':
+ sys.exit(main())
# vim: sw=4 et