diff options
-rw-r--r-- | data/templates/grub/grub_compat.j2 | 4 | ||||
-rw-r--r-- | data/templates/grub/grub_options.j2 | 6 | ||||
-rw-r--r-- | op-mode-definitions/system-image.xml.in | 9 | ||||
-rw-r--r-- | python/vyos/system/compat.py | 10 | ||||
-rwxr-xr-x | src/op_mode/image_installer.py | 22 | ||||
-rwxr-xr-x | src/op_mode/image_manager.py | 28 |
6 files changed, 57 insertions, 22 deletions
diff --git a/data/templates/grub/grub_compat.j2 b/data/templates/grub/grub_compat.j2 index d1085eec8..8fb4f71dc 100644 --- a/data/templates/grub/grub_compat.j2 +++ b/data/templates/grub/grub_compat.j2 @@ -14,8 +14,6 @@ KVM {%- elif type == 'ttyS' -%} Serial -{%- elif type == 'ttyUSB' -%} - USB {%- else -%} Unknown {%- endif %} @@ -25,8 +23,6 @@ console=ttyS0,{{ console_speed }} console=tty0 {%- elif type == 'ttyS' -%} console=tty0 console=ttyS0,{{ console_speed }} -{%- elif type == 'ttyUSB' -%} - console=tty0 console=ttyUSB0,115200 {%- else -%} console=tty0 console=ttyS0,{{ console_speed }} {%- endif %} diff --git a/data/templates/grub/grub_options.j2 b/data/templates/grub/grub_options.j2 index c8a1472e1..a00bf4e37 100644 --- a/data/templates/grub/grub_options.j2 +++ b/data/templates/grub/grub_options.j2 @@ -33,12 +33,6 @@ submenu "Boot options" { setup_serial configfile ${prefix}/grub.cfg.d/*vyos-menu*.cfg } - menuentry "ttyUSB (USB serial)" { - set console_type="ttyUSB" - export console_type - setup_serial - configfile ${prefix}/grub.cfg.d/*vyos-menu*.cfg - } } menuentry "Enter console number" { read console_num diff --git a/op-mode-definitions/system-image.xml.in b/op-mode-definitions/system-image.xml.in index c131087be..13bc408de 100644 --- a/op-mode-definitions/system-image.xml.in +++ b/op-mode-definitions/system-image.xml.in @@ -72,6 +72,15 @@ <help>Set system operational parameters</help> </properties> <children> + <tagNode name="boot-console"> + <properties> + <help>Set system console type at boot</help> + <completionHelp> + <script>sudo ${vyos_op_scripts_dir}/image_manager.py --action list_console_types</script> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action set_console_type --console-type "${4}"</command> + </tagNode> <node name="image"> <properties> <help>Set system image parameters</help> diff --git a/python/vyos/system/compat.py b/python/vyos/system/compat.py index 1b487c1d2..94e40d268 100644 --- a/python/vyos/system/compat.py +++ b/python/vyos/system/compat.py @@ -220,14 +220,8 @@ def get_default(data: dict, root_dir: str = '') -> Union[int, None]: sublist = list(filter(lambda x: (x.get('version') == image_name and x.get('console_type') == console_type and - x.get('console_num') == console_num and x.get('bootmode') == 'normal'), menu_entries)) - # legacy images added with legacy tools omitted 'ttyUSB'; if entry not - # available, default to initial entry of version - if not sublist: - sublist = list(filter(lambda x: x.get('version') == image_name, - menu_entries)) if sublist: return menu_entries.index(sublist[0]) @@ -268,7 +262,9 @@ def update_version_list(root_dir: str = '') -> list[dict]: add = list(set(current_versions) - set(menu_versions)) for ver in add: last = menu_entries[0].get('version') - new = deepcopy(list(filter(lambda x: x.get('version') == last, + # copy legacy format of menu entries; ignore deprecated ttyUSB + new = deepcopy(list(filter(lambda x: (x.get('version') == last and + x.get('console_type') != 'ttyUSB'), menu_entries))) for e in new: boot_opts = grub.get_boot_opts(ver) diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index 185d12c49..d65cd6b1d 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -23,6 +23,8 @@ from shutil import copy, chown, rmtree, copytree from glob import glob from sys import exit from os import environ +from os import readlink +from os import getpid, getppid from typing import Union from urllib.parse import urlparse from passlib.hosts import linux_context @@ -63,7 +65,7 @@ MSG_INPUT_PASSWORD: str = 'Please enter a password for the "vyos" user:' MSG_INPUT_PASSWORD_CONFIRM: str = 'Please confirm password for the "vyos" user:' MSG_INPUT_ROOT_SIZE_ALL: str = 'Would you like to use all the free space on the drive?' MSG_INPUT_ROOT_SIZE_SET: str = 'Please specify the size (in GB) of the root partition (min is 1.5 GB)?' -MSG_INPUT_CONSOLE_TYPE: str = 'What console should be used by default? (K: KVM, S: Serial, U: USB-Serial)?' +MSG_INPUT_CONSOLE_TYPE: str = 'What console should be used by default? (K: KVM, S: Serial)?' MSG_INPUT_COPY_DATA: str = 'Would you like to copy data to the new image?' MSG_INPUT_CHOOSE_COPY_DATA: str = 'From which image would you like to save config information?' MSG_WARN_ISO_SIGN_INVALID: str = 'Signature is not valid. Do you want to continue with installation?' @@ -564,6 +566,20 @@ def copy_ssh_host_keys() -> bool: return False +def console_hint() -> str: + pid = getppid() if 'SUDO_USER' in environ else getpid() + try: + path = readlink(f'/proc/{pid}/fd/1') + except OSError: + path = '/dev/tty' + + name = Path(path).name + if name == 'ttyS0': + return 'S' + else: + return 'K' + + def cleanup(mounts: list[str] = [], remove_items: list[str] = []) -> None: """Clean up after installation @@ -660,8 +676,8 @@ def install_image() -> None: # ask for default console console_type: str = ask_input(MSG_INPUT_CONSOLE_TYPE, default='K', - valid_responses=['K', 'S', 'U']) - console_dict: dict[str, str] = {'K': 'tty', 'S': 'ttyS', 'U': 'ttyUSB'} + valid_responses=['K', 'S']) + console_dict: dict[str, str] = {'K': 'tty', 'S': 'ttyS'} config_boot_list = ['/opt/vyatta/etc/config/config.boot', '/opt/vyatta/etc/config.boot.default'] diff --git a/src/op_mode/image_manager.py b/src/op_mode/image_manager.py index 51b95e4d5..05d3b0048 100755 --- a/src/op_mode/image_manager.py +++ b/src/op_mode/image_manager.py @@ -21,7 +21,7 @@ from argparse import ArgumentParser, Namespace from pathlib import Path from shutil import rmtree from sys import exit -from typing import Optional +from typing import Optional, Literal, TypeAlias, get_args from vyos.system import disk, grub, image, compat from vyos.utils.io import ask_yes_no, select_entry @@ -33,6 +33,8 @@ DELETE_IMAGE_PROMPT_MSG: str = 'Select an image to delete:' MSG_DELETE_IMAGE_RUNNING: str = 'Currently running image cannot be deleted; reboot into another image first' MSG_DELETE_IMAGE_DEFAULT: str = 'Default image cannot be deleted; set another image as default first' +ConsoleType: TypeAlias = Literal['tty', 'ttyS'] + def annotate_list(images_list: list[str]) -> list[str]: """Annotate list of images with additional info @@ -183,6 +185,15 @@ def rename_image(name_old: str, name_new: str) -> None: exit(f'Unable to rename image "{name_old}" to "{name_new}": {err}') +@compat.grub_cfg_update +def set_console_type(console_type: ConsoleType) -> None: + console_choice = get_args(ConsoleType) + if console_type not in console_choice: + exit(f'console type \'{console_type}\' not available') + + grub.set_console_type(console_type) + + def list_images() -> None: """Print list of available images for CLI hints""" images_list: list[str] = grub.version_list() @@ -190,6 +201,13 @@ def list_images() -> None: print(image_name) +def list_console_types() -> None: + """Print list of console types for CLI hints""" + console_types: list[str] = list(get_args(ConsoleType)) + for console_type in console_types: + print(console_type) + + def parse_arguments() -> Namespace: """Parse arguments @@ -198,7 +216,8 @@ def parse_arguments() -> Namespace: """ parser: ArgumentParser = ArgumentParser(description='Manage system images') parser.add_argument('--action', - choices=['delete', 'set', 'rename', 'list'], + choices=['delete', 'set', 'set_console_type', + 'rename', 'list', 'list_console_types'], required=True, help='action to perform with an image') parser.add_argument('--no-prompt', action='store_true', @@ -208,6 +227,7 @@ def parse_arguments() -> Namespace: help= 'a name of an image to add, delete, install, rename, or set as default') parser.add_argument('--image-new-name', help='a new name for image') + parser.add_argument('--console-type', help='console type for boot') args: Namespace = parser.parse_args() # Validate arguments if args.action == 'rename' and (not args.image_name or @@ -224,10 +244,14 @@ if __name__ == '__main__': delete_image(args.image_name, args.no_prompt) if args.action == 'set': set_image(args.image_name) + if args.action == 'set_console_type': + set_console_type(args.console_type) if args.action == 'rename': rename_image(args.image_name, args.image_new_name) if args.action == 'list': list_images() + if args.action == 'list_console_types': + list_console_types() exit() |