diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/interfaces_bonding.py | 11 | ||||
| -rwxr-xr-x | src/op_mode/image_installer.py | 24 | ||||
| -rwxr-xr-x | src/op_mode/image_manager.py | 28 | 
3 files changed, 57 insertions, 6 deletions
| diff --git a/src/conf_mode/interfaces_bonding.py b/src/conf_mode/interfaces_bonding.py index 371b219c0..5e5d5fba1 100755 --- a/src/conf_mode/interfaces_bonding.py +++ b/src/conf_mode/interfaces_bonding.py @@ -33,6 +33,7 @@ from vyos.ifconfig import BondIf  from vyos.ifconfig.ethernet import EthernetIf  from vyos.ifconfig import Section  from vyos.template import render_to_string +from vyos.utils.assertion import assert_mac  from vyos.utils.dict import dict_search  from vyos.utils.dict import dict_to_paths_values  from vyos.utils.network import interface_exists @@ -244,6 +245,16 @@ def verify(bond):              raise ConfigError('primary interface only works for mode active-backup, ' \                                'transmit-load-balance or adaptive-load-balance') +    if 'system_mac' in bond: +        if bond['mode'] != '802.3ad': +            raise ConfigError('Actor MAC address only available in 802.3ad mode!') + +        system_mac = bond['system_mac'] +        try: +            assert_mac(system_mac, test_all_zero=False) +        except: +            raise ConfigError(f'Cannot use a multicast MAC address "{system_mac}" as system-mac!') +      return None  def generate(bond): diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index ba0e3b6db..0d2d7076c 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 @@ -65,7 +67,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_INPUT_COPY_ENC_DATA: str = 'Would you like to copy the encrypted config to the new image?' @@ -614,6 +616,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 @@ -709,9 +725,9 @@ 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'} +                                  default=console_hint(), +                                  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 1cfb5f5a1..fb4286dbc 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 @@ -202,6 +204,15 @@ def rename_image(name_old: str, name_new: str) -> None:              exit(f'Unable to rename the encrypted config for "{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() @@ -209,6 +220,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 @@ -217,7 +235,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', @@ -227,6 +246,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 @@ -243,10 +263,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() | 
