Skip to content

Commit d7af8ee

Browse files
authored
Merge pull request #1272 from c-po/testsuite-boot
Testsuite: T9214: make GRUB console-select navigation non-fatal on auto-boot race
2 parents ac5ad10 + 0a8a6e0 commit d7af8ee

1 file changed

Lines changed: 55 additions & 36 deletions

File tree

scripts/check-qemu-install

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ def toggleUEFISecureBoot(c):
547547
UEFIKeyPress(c, KEY_DOWN)
548548
UEFIKeyPress(c, KEY_RETURN)
549549

550-
def BOOTLOADERchooseSerialConsole(child, live: bool) -> None:
550+
def BOOTLOADERchooseSerialConsole(child, live: bool, log=None) -> None:
551551
""" Select GRUB boot entry that uses the serial console. This differs
552552
between a LIVE ISO image and an already installed system. """
553553
BOOTLOADER_TMO = 40
@@ -596,39 +596,58 @@ def BOOTLOADERchooseSerialConsole(child, live: bool) -> None:
596596
# Wait for GRUB
597597
child.expect(GRUB_STRING, timeout=BOOTLOADER_TMO)
598598

599-
# Unlike the live ISO menus (10s timeout), the installed system's
600-
# top-level menu auto-boots its default entry after ~BOOTLOADER_LOAD_TMO
601-
# seconds - the same delay this script would otherwise sleep before
602-
# sending any key. Under host load that leaves no margin: GRUB can
603-
# auto-boot before "Boot options" is ever selected. Send the first
604-
# navigation key immediately to cancel the countdown, then give the
605-
# screen time to settle.
606-
# Select GRUB serial console
607-
# Boot options
608-
child.send(KEY_DOWN)
609-
time.sleep(BOOTLOADER_LOAD_TMO)
610-
child.send(KEY_RETURN)
611-
time.sleep(BOOTLOADER_SLEEP)
612-
# GRUB submenus never time out on their own, so confirm we actually
613-
# landed on this submenu before navigating further - otherwise a
614-
# dropped keypress leaves the VM stuck here until the login wait
615-
# elsewhere expires
616-
child.expect('Select console type', timeout=BOOTLOADER_TMO)
617-
618-
# Select console type
619-
child.send(KEY_DOWN)
620-
time.sleep(BOOTLOADER_SLEEP)
621-
child.send(KEY_RETURN)
622-
time.sleep(BOOTLOADER_SLEEP)
623-
child.expect(r'ttyS \(serial\)', timeout=BOOTLOADER_TMO)
624-
625-
# *ttyS (serial)
626-
child.send(KEY_DOWN)
627-
time.sleep(BOOTLOADER_SLEEP)
628-
child.send(KEY_RETURN)
629-
time.sleep(BOOTLOADER_SLEEP)
630-
# Boot
631-
child.send(KEY_RETURN)
599+
# The installed system's top-level menu auto-boots its default
600+
# entry after ~BOOTLOADER_LOAD_TMO seconds, timed from when GRUB
601+
# itself draws the menu - not from when this script's regex match
602+
# on GRUB_STRING returns. Under host load the menu text can reach
603+
# us well after that internal countdown already started, so there
604+
# is no reliable amount of "send a key fast enough" that wins this
605+
# race every time.
606+
#
607+
# That's fine to lose: the installer always answers 'S' (serial)
608+
# to "What console should be used by default?", so the default
609+
# entry GRUB auto-boots already targets the right console.
610+
# waitForLogin()/loginVM(), called after this function returns,
611+
# already tolerate landing straight on the GRUB countdown or the
612+
# login prompt. So treat this submenu navigation as best-effort:
613+
# if we don't land in "Boot options" in time, stop navigating and
614+
# let the default entry (which is already auto-booting) carry on,
615+
# instead of raising and aborting the whole test.
616+
try:
617+
# Select GRUB serial console
618+
# Boot options
619+
child.send(KEY_DOWN)
620+
time.sleep(BOOTLOADER_LOAD_TMO)
621+
child.send(KEY_RETURN)
622+
time.sleep(BOOTLOADER_SLEEP)
623+
# GRUB submenus never time out on their own, so confirm we actually
624+
# landed on this submenu before navigating further - otherwise a
625+
# dropped keypress leaves the VM stuck here until the login wait
626+
# elsewhere expires
627+
child.expect('Select console type', timeout=BOOTLOADER_TMO)
628+
except pexpect.TIMEOUT:
629+
if log is not None:
630+
log.warning('GRUB auto-booted the default entry before "Boot '
631+
'options" navigation completed; continuing since '
632+
'the default entry already boots the serial '
633+
'console selected during install')
634+
else:
635+
# We're inside the submenu, so a timeout past this point is a
636+
# real navigation bug, not the auto-boot race - let it propagate.
637+
# Select console type
638+
child.send(KEY_DOWN)
639+
time.sleep(BOOTLOADER_SLEEP)
640+
child.send(KEY_RETURN)
641+
time.sleep(BOOTLOADER_SLEEP)
642+
child.expect(r'ttyS \(serial\)', timeout=BOOTLOADER_TMO)
643+
644+
# *ttyS (serial)
645+
child.send(KEY_DOWN)
646+
time.sleep(BOOTLOADER_SLEEP)
647+
child.send(KEY_RETURN)
648+
time.sleep(BOOTLOADER_SLEEP)
649+
# Boot
650+
child.send(KEY_RETURN)
632651

633652
return None
634653

@@ -904,7 +923,7 @@ try:
904923
log.info('Disable UEFI Secure Boot for initial installation')
905924
toggleUEFISecureBoot(c)
906925

907-
BOOTLOADERchooseSerialConsole(c, live=(not args.cloud_init))
926+
BOOTLOADERchooseSerialConsole(c, live=(not args.cloud_init), log=log)
908927
loginVM(c, log)
909928

910929
#################################################
@@ -1070,7 +1089,7 @@ try:
10701089
# Booting installed system
10711090
#################################################
10721091
log.info('Booting installed system')
1073-
BOOTLOADERchooseSerialConsole(c, live=False)
1092+
BOOTLOADERchooseSerialConsole(c, live=False, log=log)
10741093

10751094
#################################################
10761095
# Logging into VyOS system

0 commit comments

Comments
 (0)