mirror of
https://github.com/systemd/systemd.git
synced 2024-12-01 14:23:36 +08:00
cf14d11447
Given that the test involves screen(1), sending various control sequences to resize/clear the screen, most of the logs sent from the python script were nearly impossible to read or mixed with other messages sent to the console hence making the debug harder when the test is run manually. This patch introduces an option to redirect the pexpect IOs into a file (to be used in $STATEDIR/TEST-69-SHUTDOWN/run-nspawn). The pexpect logs are also enabled later so the boot logs are skipped since those are already included in the journal.
137 lines
3.9 KiB
Python
Executable File
137 lines
3.9 KiB
Python
Executable File
#!/usr/bin/python3
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
# pylint: disable=broad-except
|
|
|
|
import argparse
|
|
import logging
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
import pexpect
|
|
|
|
|
|
def run(args):
|
|
|
|
ret = 1
|
|
logger = logging.getLogger("test-shutdown")
|
|
|
|
logger.info("spawning test")
|
|
console = pexpect.spawn(args.command, args.arg, env={
|
|
"TERM": "linux",
|
|
}, encoding='utf-8', timeout=60)
|
|
|
|
logger.debug("child pid %d", console.pid)
|
|
|
|
try:
|
|
logger.info("waiting for login prompt")
|
|
console.expect('H login: ', 10)
|
|
|
|
if args.logfile:
|
|
logger.debug("Logging pexpect IOs to %s", args.logfile)
|
|
console.logfile = open(args.logfile, 'w')
|
|
elif args.verbose:
|
|
console.logfile = sys.stdout
|
|
|
|
logger.info("log in and start screen")
|
|
console.sendline('root')
|
|
console.expect('bash.*# ', 10)
|
|
console.sendline('screen')
|
|
console.expect('screen0 ', 10)
|
|
console.sendcontrol('a')
|
|
console.send('c')
|
|
console.expect('screen1 ', 10)
|
|
|
|
# console.interact()
|
|
|
|
console.sendline('tty')
|
|
console.expect(r'/dev/(pts/\d+)')
|
|
pty = console.match.group(1)
|
|
logger.info("window 1 at tty %s", pty)
|
|
|
|
logger.info("schedule reboot")
|
|
console.sendline('shutdown -r')
|
|
console.expect("Reboot scheduled for (?P<date>.*), use 'shutdown -c' to cancel", 2)
|
|
date = console.match.group('date')
|
|
logger.info("reboot scheduled for %s", date)
|
|
|
|
console.sendcontrol('a')
|
|
console.send('0')
|
|
logger.info("verify broadcast message")
|
|
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(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('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 will reboot now!", 12)
|
|
|
|
logger.info("waiting for reboot")
|
|
|
|
console.expect('H login: ', 60)
|
|
console.sendline('root')
|
|
console.expect('bash.*# ', 10)
|
|
|
|
console.sendline('> /testok')
|
|
|
|
logger.info("power off")
|
|
console.sendline('poweroff')
|
|
|
|
logger.info("expect termination now")
|
|
console.expect(pexpect.EOF)
|
|
|
|
ret = 0
|
|
except Exception as e:
|
|
logger.error(e)
|
|
logger.info("killing child pid %d", console.pid)
|
|
|
|
# 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
|
|
|
|
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")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.verbose:
|
|
level = logging.DEBUG
|
|
else:
|
|
level = logging.INFO
|
|
|
|
logging.basicConfig(level=level)
|
|
|
|
return run(args)
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|
|
|
|
# vim: sw=4 et
|