2021-12-22 13:50:08 +03:00
#!/usr/bin/python3
# SPDX-License-Identifier: LGPL-2.1-or-later
2022-11-30 18:18:50 +03:00
# pylint: disable=line-too-long,invalid-name,missing-module-docstring,missing-function-docstring,too-many-statements,broad-except
2021-12-22 13:50:08 +03:00
import argparse
import logging
import sys
2022-11-30 18:13:19 +03:00
import time
2021-12-22 13:50:08 +03:00
2022-05-27 12:45:15 +03:00
import pexpect
2021-12-22 13:50:08 +03:00
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 = 30 )
if args . verbose :
console . logfile = sys . stdout
2022-05-27 12:45:15 +03:00
logger . debug ( " child pid %d " , console . pid )
2021-12-22 13:50:08 +03:00
try :
logger . info ( " waiting for login prompt " )
console . expect ( ' H login: ' , 10 )
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 line %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 " )
2022-11-30 18:18:50 +03:00
console . expect ( f ' Broadcast message from root@H on { pty } ' , 2 )
console . expect ( f ' The system will reboot at { date } ' , 2 )
2021-12-22 13:50:08 +03:00
logger . info ( " check show output " )
console . sendline ( ' shutdown --show ' )
2022-11-30 18:18:50 +03:00
console . expect ( f " Reboot scheduled for { date } , use ' shutdown -c ' to cancel " , 2 )
2021-12-22 13:50:08 +03:00
logger . info ( " cancel shutdown " )
console . sendline ( ' shutdown -c ' )
console . sendcontrol ( ' a ' )
console . send ( ' 1 ' )
2022-05-30 13:08:41 +03:00
console . expect ( ' System shutdown has been cancelled ' , 2 )
2021-12-22 13:50:08 +03:00
logger . info ( " call for reboot " )
console . sendline ( ' sleep 10; shutdown -r now ' )
console . sendcontrol ( ' a ' )
console . send ( ' 0 ' )
2022-05-30 13:08:41 +03:00
console . expect ( " The system will reboot now! " , 12 )
2021-12-22 13:50:08 +03:00
logger . info ( " waiting for reboot " )
2022-08-26 16:53:46 +03:00
console . expect ( ' H login: ' , 60 )
2021-12-22 13:50:08 +03:00
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 )
2022-05-27 12:45:15 +03:00
logger . info ( " killing child pid %d " , console . pid )
2022-11-30 18:13:19 +03:00
# We can't use console.terminate(force=True) right away, since
# the internal delay between sending a signal and checking the process
# is just 0.1s [0], which means we'd get SIGKILLed pretty quickly.
# Let's send SIGHUP/SIGINT first, wait a bit, and then follow-up with
# SIGHUP/SIGINT/SIGKILL if the process is still alive.
# [0] https://github.com/pexpect/pexpect/blob/acb017a97332c19a9295660fe87316926a8adc55/pexpect/spawnbase.py#L71
console . terminate ( )
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 )
2021-12-22 13:50:08 +03:00
return ret
2022-05-27 12:45:15 +03:00
def main ( ) :
2021-12-22 13:50:08 +03:00
parser = argparse . ArgumentParser ( description = ' test logind shutdown feature ' )
parser . add_argument ( " -v " , " --verbose " , action = " store_true " , help = " verbose " )
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 )
2022-05-27 12:45:15 +03:00
return run ( args )
if __name__ == ' __main__ ' :
sys . exit ( main ( ) )
2021-12-22 13:50:08 +03:00
# vim: sw=4 et