mirror of
https://github.com/xcat2/confluent.git
synced 2026-01-11 10:32:31 +00:00
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.
This commit is contained in:
117
confluent_osdeploy/common/profile/scripts/autoconsole
Normal file
117
confluent_osdeploy/common/profile/scripts/autoconsole
Normal file
@@ -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 <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()
|
||||
@@ -34,6 +34,11 @@ run_remote_python add_local_repositories
|
||||
# run_remote_python will use the appropriate python interpreter path to run the specified script
|
||||
# A post.custom is provided to more conveniently hold customizations, see the post.custom file.
|
||||
|
||||
# This will do some serial console fixup for bad grub configuration when serial is firmware
|
||||
# managed. See script for details
|
||||
run_remote_python autoconsole
|
||||
|
||||
|
||||
# This will induce server side processing of the syncfile contents if
|
||||
# present
|
||||
run_remote_python syncfileclient
|
||||
|
||||
@@ -84,6 +84,10 @@ cat /target/etc/confluent/tls/*.pem > /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"
|
||||
|
||||
Reference in New Issue
Block a user