diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/activation-scripts/05-serial_console.py | 57 | ||||
| -rwxr-xr-x | src/conf_mode/system_console.py | 26 | ||||
| -rwxr-xr-x | src/op_mode/image_installer.py | 23 |
3 files changed, 87 insertions, 19 deletions
diff --git a/src/activation-scripts/05-serial_console.py b/src/activation-scripts/05-serial_console.py new file mode 100755 index 000000000..93e381d17 --- /dev/null +++ b/src/activation-scripts/05-serial_console.py @@ -0,0 +1,57 @@ +# Copyright (C) VyOS Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +import re + +from typing import Optional +from typing import Tuple + +from vyos.configtree import ConfigTree +from vyos.utils.file import read_file +from vyos.system.image import is_live_boot + +base = ['system', 'console', 'device'] + +def get_kernel_serial_console() -> Tuple[Optional[str], Optional[str]]: + """ + Extract the serial console device and speed setting from the kernel + command line. + """ + device = speed = None + CMDLINE_CONSOLE_RE = re.compile( + r'(?:^|\s)console=(?P<device>tty(?:S|AMA)\d+),(?P<speed>\d+)(?=\s|$)' + ) + kernel_cmdline = read_file('/proc/cmdline') + if m := CMDLINE_CONSOLE_RE.search(kernel_cmdline): + device = m.group("device") # "ttyS0" + speed = m.group("speed") # Baud rate/speed, e.g. "115200" + + return (device, speed) + +def activate(config: ConfigTree): + # Configure the kernel serial console only once during live boot. + # During installation, the user can define the console. If this is not + # limited to live boot, the serial interface will always be re-added during + # system boot, even if it was removed from config.boot. + if not is_live_boot(): + return + + (device, speed) = get_kernel_serial_console() + if device and speed: + # The kernel was booted with a configured serial console, but no + # console is configured in the CLI; align/fix the CLI configuration. + if not config.exists(base + [device]): + config.set(base + [device, 'speed'], value=speed) + config.set_tag(base) diff --git a/src/conf_mode/system_console.py b/src/conf_mode/system_console.py index 4411257e3..5d89eeba7 100755 --- a/src/conf_mode/system_console.py +++ b/src/conf_mode/system_console.py @@ -68,7 +68,7 @@ def verify(console): # and it can not be used as a serial interface if not os.path.isdir(by_bus_dir) or not os.path.exists(by_bus_device): raise ConfigError(f'Device {device} does not support being used as tty') - if not is_tty(device): + if not is_tty(device, warning=True): Warning(f'Device "{device}" used for console is not a TTY!') return None @@ -82,6 +82,7 @@ def generate(console): os.unlink(os.path.join(root, basename)) if not console or 'device' not in console: + grub_util.update_serial_console('', '', '') return None # replace keys in the config for ttyUSB items to use them in `apply()` later @@ -112,14 +113,17 @@ def generate(console): render(config_file, 'getty/serial-getty.service.j2', device_config) os.symlink(config_file, getty_wants_symlink) - # GRUB - # For existing serial line change speed (if necessary) - # Only applies to ttyS0 - if 'ttyS0' not in console['device']: - return None + # GRUB - use first defined serial console to populate Kernel console= parameter + device = None + if 'device' in console and len(console['device']) > 0: + # We use the first device for the Kernel console + console_device = next(iter(console['device'])) + console_speed = console['device'][console_device]['speed'] - speed = console['device']['ttyS0']['speed'] - grub_util.update_console_speed(speed) + # get console type ("ttyS" or "ttyAMA") from console_device (e.g. "ttyS0") + console_type = console_device.translate(str.maketrans('', '', '0123456789')) + console_num = ''.join(ch for ch in console_device if ch.isdigit()) + grub_util.update_serial_console(console_type, console_num, console_speed) return None @@ -127,9 +131,9 @@ def apply(console): # Reset screen blanking call('/usr/bin/setterm -blank 0 -powersave off -powerdown 0 -term linux </dev/tty1 >/dev/tty1 2>&1') - # Service control moved to vyos.utils.serial to unify checks and prompts. - # If users are connected, we want to show an informational message on completing - # the process, but not halt configuration processing with an interactive prompt. + # Service control moved to vyos.utils.serial to unify checks and prompts. + # If users are connected, we want to show an informational message on completing + # the process, but not halt configuration processing with an interactive prompt. restart_login_consoles(prompt_user=False, quiet=False) if not console: diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index db9647782..fb3cdda9e 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -42,8 +42,10 @@ from psutil import disk_partitions from vyos.base import Warning from vyos.configtree import ConfigTree +from vyos.config_mgmt import unsaved_commits from vyos.defaults import base_dir from vyos.defaults import directories +from vyos.flavor import get_image_serial_console from vyos.remote import download from vyos.system import disk from vyos.system import grub @@ -69,7 +71,6 @@ from vyos.utils.process import cmd from vyos.utils.process import run from vyos.utils.process import rc_cmd from vyos.version import get_version_data -from vyos.config_mgmt import unsaved_commits # define text messages MSG_ERR_NOT_LIVE: str = 'The system is already installed. Please use "add system image" instead.' @@ -143,16 +144,17 @@ ISO_DOWNLOAD_PATH: str = '' external_download_script: str = f'{base_dir}/simple-download.py' external_latest_image_url_script: str = f'{base_dir}/latest-image-url.py' +(flavor_sercon_type, flavor_sercon_num, flavor_sercon_speed) = get_image_serial_console() + # default boot variables DEFAULT_BOOT_VARS: dict[str, str] = { 'timeout': '5', 'console_type': 'tty', - 'console_num': '0', - 'console_speed': '115200', + 'console_num': flavor_sercon_num, + 'console_speed': flavor_sercon_speed, 'bootmode': 'normal' } - def bytes_to_gb(size: int) -> float: """Convert Bytes to GBytes, rounded to 1 decimal number @@ -767,12 +769,13 @@ def console_hint() -> str: path = '/dev/tty' name = Path(path).name - if name in ['ttyS0', 'ttyAMA0']: + if name in ['ttyS0']: return 'S' + elif name in ['ttyAMA0']: + return 'A' else: return 'K' - def cleanup(mounts: list[str] = [], remove_items: list[str] = []) -> None: """Clean up after installation @@ -921,10 +924,14 @@ def install_image() -> None: print(MSG_WARN_PASSWORD_CONFIRM) # ask for default console + console_dict: dict[str, str] = {'K': 'tty'} + if flavor_sercon_type: + tmp: str = flavor_sercon_type[-1] # get "S" from "ttyS" and "A" from "ttyAMA" + console_dict.update({tmp: flavor_sercon_type}) + console_type: str = ask_input(MSG_INPUT_CONSOLE_TYPE, default=console_hint(), - valid_responses=['K', 'S']) - console_dict: dict[str, str] = {'K': 'tty', 'S': 'ttyS'} + valid_responses=console_dict.keys()) config_boot_list = [f'{DIR_CONFIG}/config.boot', '/opt/vyatta/etc/config.boot.default'] |
