From 90f4a2a062c0b06b82a27cc9b94f73431bb9a257 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 11 Apr 2025 12:55:01 -0400 Subject: [PATCH] Improve text console behaviors of Ubuntu and RedHat RedHat makes grub redundantly handle serial output that firmware already handles. If we detect EFI firmware and SPCR ACPI table and connected serial port, that suggests that firmware will handle. Ubuntu hates serial console by default, amend it so it can actually work for serial users. --- .../common/profile/scripts/autoconsole | 117 ++++++++++++++++++ .../el8/profiles/default/scripts/post.sh | 5 + .../profiles/default/scripts/post.sh | 4 + 3 files changed, 126 insertions(+) create mode 100644 confluent_osdeploy/common/profile/scripts/autoconsole diff --git a/confluent_osdeploy/common/profile/scripts/autoconsole b/confluent_osdeploy/common/profile/scripts/autoconsole new file mode 100644 index 00000000..b37e1df6 --- /dev/null +++ b/confluent_osdeploy/common/profile/scripts/autoconsole @@ -0,0 +1,117 @@ +#!/usr/bin/python3 + +# This script evaluates whether firmware redirection is likely. It uses three cues: +# - Does the system offer up SPCR? This would indicate that the firmware is doing serial output. +# Otherwise, there's no indication that the firmware cares about serial console. +# - Is the system EFI? BIOS implementations may not intercept text draw calls after POST exit, +# thus even when BIOS tells us serial port is in use, it may not be doing anything when +# grub would be running +# - Is the serial port connected? In the event that firmware indicates serial port, but +# serial port is not reporting DCD, then it doesn't look like a comfortable enough scenario + +import fcntl +import os +import os.path +import struct +import subprocess +import termios + + +addrtoname = { + 0x3f8: '/dev/ttyS0', + 0x2f8: '/dev/ttyS1', + 0x3e8: '/dev/ttyS2', + 0x2e8: '/dev/ttyS3', +} +speedmap = { + 0: None, + 3: 9600, + 4: 19200, + 6: 57600, + 7: 115200, +} + +termiobaud = { + 9600: termios.B9600, + 19200: termios.B19200, + 57600: termios.B57600, + 115200: termios.B115200, +} + + +def deserialize_grub_rh(): + if 'console=ttyS' in open('/proc/cmdline').read(): + return None # User manually indicated serial config + # they own the grub behavior too for now + grublines = [] + with open('/etc/default/grub') as grubin: + grublines = grubin.read().split('\n') + with open('/etc/default/grub', 'w') as grubout: + for grubline in grublines: + if grubline.startswith('GRUB_TERMINAL'): + grubline = grubline.replace('serial ', '') + grubout.write(grubline + '\n') + subprocess.check_call(['grub2-mkconfig', '-o', '/boot/grub2/grub.cfg']) + +def fixup_ubuntu_grub_serial(): + # Ubuntu aggressively tries to graphics up + # grub. We will counter that for serial + # They also aggressively hide UI and + # block ability to interject. We will + # compromise and lean on nodeboot setup + # as a means to give someone reasonable shot at + # the short timeout + with open('/etc/default/grub') as grubin: + grublines = grubin.read().split('\n') + with open('/etc/default/grub', 'w') as grubout: + for grubline in grublines: + if grubline.startswith('GRUB_TIMEOUT_STYLE=hidden'): + grubline = 'GRUB_TIMEOUT_STYLE=menu' + elif grubline.startswith('GRUB_TIMEOUT=0'): + grubline = 'GRUB_TIMEOUT=2' + elif grubline.startswith('#GRUB_TERMINAL=console'): + grubline = grubline.replace('#', '') + grubout.write(grubline + '\n') + subprocess.check_call(['update-grub']) + +def get_serial_config(): + if not os.path.exists('/sys/firmware/efi'): + return None + spcr = open("/sys/firmware/acpi/tables/SPCR", "rb") + spcr = bytearray(spcr.read()) + if spcr[8] != 2 or spcr[36] != 0 or spcr[40] != 1: + return None + address = struct.unpack(' /target/etc/confluent/ca.pem cat /target/etc/confluent/tls/*.pem > /target/usr/local/share/ca-certificates/confluent.crt cat /target/etc/confluent/tls/*.pem > /etc/confluent/ca.pem chroot /target update-ca-certificates + +# Ubuntu mangles grub function for serial users, undo that mangling +chroot /target bash -c "source /etc/confluent/functions; run_remote_python autoconsole" + chroot /target bash -c "source /etc/confluent/functions; run_remote_python syncfileclient" chroot /target bash -c "source /etc/confluent/functions; run_remote_python confignet" chroot /target bash -c "source /etc/confluent/functions; run_remote_parts post.d"