2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-01-07 08:32:29 +00:00
Files
confluent/confluent_osdeploy/common/profile/scripts/autoconsole
Jarrod Johnson 90f4a2a062 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.
2025-04-11 12:55:01 -04:00

118 lines
3.9 KiB
Python

#!/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 <node> 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('<Q', spcr[44:52])[0]
tty = None
try:
tty = addrtoname[address]
except KeyError:
return None
retval = { 'tty': tty }
try:
retval['speed'] = speedmap[spcr[58]]
except KeyError:
return None
if retval['speed']:
ttyf = os.open(tty, os.O_RDWR | os.O_NOCTTY)
currattr = termios.tcgetattr(ttyf)
currattr[4:6] = [0, termiobaud[retval['speed']]]
termios.tcsetattr(ttyf, termios.TCSANOW, currattr)
retval['connected'] = bool(struct.unpack('<I', fcntl.ioctl(
ttyf, termios.TIOCMGET, '\x00\x00\x00\x00'))[0] & termios.TIOCM_CAR)
os.close(ttyf)
return retval
def main():
autoconscfg = get_serial_config()
if not autoconscfg or not autoconscfg['connected']:
return
if os.path.exists('/etc/redhat-release'): # redhat family
deserialize_grub_rh()
elif os.path.exists('/etc/os-release'):
with open('/etc/os-release') as osr:
if 'Ubuntu' in osr.read():
fixup_ubuntu_grub_serial()
if __name__ == '__main__':
main()