From 1bf6e20bdea743a4f6fedc077d69ae58b59901e1 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 28 Mar 2022 16:41:03 +0200 Subject: moved GlobalMenu into lib/menu/global_menu.py instead --- archinstall/lib/menu/__init__.py | 2 +- archinstall/lib/menu/global_menu.py | 293 ++++++++++++++++++++++++ archinstall/lib/user_interaction/global_menu.py | 293 ------------------------ 3 files changed, 294 insertions(+), 294 deletions(-) create mode 100644 archinstall/lib/menu/global_menu.py delete mode 100644 archinstall/lib/user_interaction/global_menu.py diff --git a/archinstall/lib/menu/__init__.py b/archinstall/lib/menu/__init__.py index fd83ee01..9b0adb8b 100644 --- a/archinstall/lib/menu/__init__.py +++ b/archinstall/lib/menu/__init__.py @@ -1,2 +1,2 @@ from .menu import Menu as Menu -from .selection_menu import GlobalMenu as GlobalMenu \ No newline at end of file +from .global_menu import GlobalMenu as GlobalMenu \ No newline at end of file diff --git a/archinstall/lib/menu/global_menu.py b/archinstall/lib/menu/global_menu.py new file mode 100644 index 00000000..3f57941a --- /dev/null +++ b/archinstall/lib/menu/global_menu.py @@ -0,0 +1,293 @@ +from __future__ import annotations + +from typing import Any, List, Optional + +from ..menu import Menu +from ..menu.selection_menu import Selector, GeneralMenu +from ..general import SysCommand, secret +from ..hardware import has_uefi +from ..storage import storage +from ..output import log +from ..profiles import is_desktop_profile +from ..disk import encrypted_partitions + +from ..user_interaction import get_password, ask_for_a_timezone, save_config +from ..user_interaction import ask_ntp +from ..user_interaction import ask_for_swap +from ..user_interaction import ask_for_bootloader +from ..user_interaction import ask_hostname +from ..user_interaction import ask_for_audio_selection +from ..user_interaction import ask_additional_packages_to_install +from ..user_interaction import ask_to_configure_network +from ..user_interaction import ask_for_superuser_account +from ..user_interaction import ask_for_additional_users +from ..user_interaction import select_language +from ..user_interaction import select_mirror_regions +from ..user_interaction import select_locale_lang +from ..user_interaction import select_locale_enc +from ..user_interaction import select_disk_layout +from ..user_interaction import select_kernel +from ..user_interaction import select_encrypted_partitions +from ..user_interaction import select_harddrives +from ..user_interaction import select_profile +from ..user_interaction import select_additional_repositories + +class GlobalMenu(GeneralMenu): + def __init__(self,data_store): + super().__init__(data_store=data_store, auto_cursor=True) + + def _setup_selection_menu_options(self): + # archinstall.Language will not use preset values + self._menu_options['archinstall-language'] = \ + Selector( + _('Select Archinstall language'), + lambda x: self._select_archinstall_language('English'), + default='English', + enabled=True) + self._menu_options['keyboard-layout'] = \ + Selector(_('Select keyboard layout'), lambda preset: select_language('us',preset), default='us') + self._menu_options['mirror-region'] = \ + Selector( + _('Select mirror region'), + select_mirror_regions, + display_func=lambda x: list(x.keys()) if x else '[]', + default={}) + self._menu_options['sys-language'] = \ + Selector(_('Select locale language'), lambda preset: select_locale_lang('en_US',preset), default='en_US') + self._menu_options['sys-encoding'] = \ + Selector(_('Select locale encoding'), lambda preset: select_locale_enc('utf-8',preset), default='utf-8') + self._menu_options['harddrives'] = \ + Selector( + _('Select harddrives'), + self._select_harddrives) + self._menu_options['disk_layouts'] = \ + Selector( + _('Select disk layout'), + lambda x: select_disk_layout( + storage['arguments'].get('harddrives', []), + storage['arguments'].get('advanced', False) + ), + dependencies=['harddrives']) + self._menu_options['!encryption-password'] = \ + Selector( + _('Set encryption password'), + lambda x: self._select_encrypted_password(), + display_func=lambda x: secret(x) if x else 'None', + dependencies=['harddrives']) + self._menu_options['swap'] = \ + Selector( + _('Use swap'), + lambda preset: ask_for_swap(preset), + default=True) + self._menu_options['bootloader'] = \ + Selector( + _('Select bootloader'), + lambda preset: ask_for_bootloader(storage['arguments'].get('advanced', False),preset), + default="systemd-bootctl" if has_uefi() else "grub-install") + self._menu_options['hostname'] = \ + Selector( + _('Specify hostname'), + ask_hostname, + default='archlinux') + # root password won't have preset value + self._menu_options['!root-password'] = \ + Selector( + _('Set root password'), + lambda preset:self._set_root_password(), + display_func=lambda x: secret(x) if x else 'None') + self._menu_options['!superusers'] = \ + Selector( + _('Specify superuser account'), + lambda preset: self._create_superuser_account(), + exec_func=lambda n,v:self._users_resynch(), + dependencies_not=['!root-password'], + display_func=lambda x: self._display_superusers()) + self._menu_options['!users'] = \ + Selector( + _('Specify user account'), + lambda x: self._create_user_account(), + default={}, + exec_func=lambda n,v:self._users_resynch(), + display_func=lambda x: list(x.keys()) if x else '[]') + self._menu_options['profile'] = \ + Selector( + _('Specify profile'), + lambda x: self._select_profile(), + display_func=lambda x: x if x else 'None') + self._menu_options['audio'] = \ + Selector( + _('Select audio'), + lambda preset: ask_for_audio_selection(is_desktop_profile(storage['arguments'].get('profile', None)),preset)) + self._menu_options['kernels'] = \ + Selector( + _('Select kernels'), + lambda preset: select_kernel(preset), + default=['linux']) + self._menu_options['packages'] = \ + Selector( + _('Additional packages to install'), + # lambda x: ask_additional_packages_to_install(storage['arguments'].get('packages', None)), + ask_additional_packages_to_install, + default=[]) + self._menu_options['additional-repositories'] = \ + Selector( + _('Additional repositories to enable'), + select_additional_repositories, + default=[]) + self._menu_options['nic'] = \ + Selector( + _('Configure network'), + ask_to_configure_network, + display_func=lambda x: x if x else _('Not configured, unavailable unless setup manually'), + default={}) + self._menu_options['timezone'] = \ + Selector( + _('Select timezone'), + lambda preset: ask_for_a_timezone(preset), + default='UTC') + self._menu_options['ntp'] = \ + Selector( + _('Set automatic time sync (NTP)'), + lambda preset: self._select_ntp(preset), + default=True) + self._menu_options['save_config'] = \ + Selector( + _('Save configuration'), + lambda preset: save_config(self._data_store), + enabled=True, + no_store=True) + self._menu_options['install'] = \ + Selector( + self._install_text(), + exec_func=lambda n,v: True if len(self._missing_configs()) == 0 else False, + preview_func=self._prev_install_missing_config, + enabled=True, + no_store=True) + + self._menu_options['abort'] = Selector(_('Abort'), exec_func=lambda n,v:exit(1), enabled=True) + + def _update_install_text(self, name :str = None, result :Any = None): + text = self._install_text() + self._menu_options.get('install').update_description(text) + + def post_callback(self,name :str = None ,result :Any = None): + self._update_install_text(name, result) + + def exit_callback(self): + if self._data_store.get('harddrives', None) and self._data_store.get('!encryption-password', None): + # If no partitions was marked as encrypted, but a password was supplied and we have some disks to format.. + # Then we need to identify which partitions to encrypt. This will default to / (root). + if len(list(encrypted_partitions(storage['arguments'].get('disk_layouts', [])))) == 0: + storage['arguments']['disk_layouts'] = select_encrypted_partitions( + storage['arguments']['disk_layouts'], storage['arguments']['!encryption-password']) + + def _install_text(self): + missing = len(self._missing_configs()) + if missing > 0: + return _('Install ({} config(s) missing)').format(missing) + return 'Install' + + def _prev_install_missing_config(self) -> Optional[str]: + if missing := self._missing_configs(): + text = str(_('Missing configurations:\n')) + for m in missing: + text += f'- {m}\n' + return text[:-1] # remove last new line + return None + + def _missing_configs(self) -> List[str]: + def check(s): + return self._menu_options.get(s).has_selection() + + missing = [] + if not check('bootloader'): + missing += ['Bootloader'] + if not check('hostname'): + missing += ['Hostname'] + if not check('audio'): + missing += ['Audio'] + if not check('!root-password') and not check('!superusers'): + missing += [str(_('Either root-password or at least 1 superuser must be specified'))] + if not check('harddrives'): + missing += ['Hard drives'] + if check('harddrives'): + if not self._menu_options.get('harddrives').is_empty() and not check('disk_layouts'): + missing += ['Disk layout'] + + return missing + + def _set_root_password(self): + prompt = str(_('Enter root password (leave blank to disable root): ')) + password = get_password(prompt=prompt) + return password + + def _select_encrypted_password(self): + if passwd := get_password(prompt=str(_('Enter disk encryption password (leave blank for no encryption): '))): + return passwd + else: + return None + + def _select_ntp(self, preset :bool = True) -> bool: + ntp = ask_ntp(preset) + + value = str(ntp).lower() + SysCommand(f'timedatectl set-ntp {value}') + + return ntp + + def _select_harddrives(self, old_harddrives : list) -> list: + # old_haddrives = storage['arguments'].get('harddrives', []) + harddrives = select_harddrives(old_harddrives) + + # in case the harddrives got changed we have to reset the disk layout as well + if old_harddrives != harddrives: + self._menu_options.get('disk_layouts').set_current_selection(None) + storage['arguments']['disk_layouts'] = {} + + if not harddrives: + prompt = _( + "You decided to skip harddrive selection\nand will use whatever drive-setup is mounted at {} (experimental)\n" + "WARNING: Archinstall won't check the suitability of this setup\n" + "Do you wish to continue?" + ).format(storage['MOUNT_POINT']) + + choice = Menu(prompt, ['yes', 'no'], default_option='yes').run() + + if choice == 'no': + return self._select_harddrives(old_harddrives) + + return harddrives + + def _select_profile(self): + profile = select_profile() + + # Check the potentially selected profiles preparations to get early checks if some additional questions are needed. + if profile and profile.has_prep_function(): + namespace = f'{profile.namespace}.py' + with profile.load_instructions(namespace=namespace) as imported: + if not imported._prep_function(): + log(' * Profile\'s preparation requirements was not fulfilled.', fg='red') + exit(1) + + return profile + + def _create_superuser_account(self): + superusers = ask_for_superuser_account(str(_('Manage superuser accounts: '))) + return superusers if superusers else None + + def _create_user_account(self): + users = ask_for_additional_users(str(_('Manage ordinary user accounts: '))) + return users + + def _display_superusers(self): + superusers = self._data_store.get('!superusers', {}) + + if self._menu_options.get('!root-password').has_selection(): + return list(superusers.keys()) if superusers else '[]' + else: + return list(superusers.keys()) if superusers else '' + + def _users_resynch(self): + self.synch('!superusers') + self.synch('!users') + return False diff --git a/archinstall/lib/user_interaction/global_menu.py b/archinstall/lib/user_interaction/global_menu.py deleted file mode 100644 index 2001103a..00000000 --- a/archinstall/lib/user_interaction/global_menu.py +++ /dev/null @@ -1,293 +0,0 @@ -from __future__ import annotations - -from typing import Any, List, Optional - -from ..menu import Menu -from ..menu.selection_menu import Selector, GeneralMenu -from ..general import SysCommand, secret -from ..hardware import has_uefi -from ..storage import storage -from ..output import log -from ..profiles import is_desktop_profile -from ..disk import encrypted_partitions - -from ..user_interaction import get_password, ask_for_a_timezone, save_config -from ..user_interaction import ask_ntp -from ..user_interaction import ask_for_swap -from ..user_interaction import ask_for_bootloader -from ..user_interaction import ask_hostname -from ..user_interaction import ask_for_audio_selection -from ..user_interaction import ask_additional_packages_to_install -from ..user_interaction import ask_to_configure_network -from ..user_interaction import ask_for_superuser_account -from ..user_interaction import ask_for_additional_users -from ..user_interaction import select_language -from ..user_interaction import select_mirror_regions -from ..user_interaction import select_locale_lang -from ..user_interaction import select_locale_enc -from ..user_interaction import select_disk_layout -from ..user_interaction import select_kernel -from ..user_interaction import select_encrypted_partitions -from ..user_interaction import select_harddrives -from ..user_interaction import select_profile -from ..user_interaction import select_additional_repositories - -class GlobalMenu(GeneralMenu): - def __init__(self,data_store): - super().__init__(data_store=data_store, auto_cursor=True) - - def _setup_selection_menu_options(self): - # archinstall.Language will not use preset values - self._menu_options['archinstall-language'] = \ - Selector( - _('Select Archinstall language'), - lambda x: self._select_archinstall_language('English'), - default='English', - enabled=True) - self._menu_options['keyboard-layout'] = \ - Selector(_('Select keyboard layout'), lambda preset: select_language('us',preset), default='us') - self._menu_options['mirror-region'] = \ - Selector( - _('Select mirror region'), - select_mirror_regions, - display_func=lambda x: list(x.keys()) if x else '[]', - default={}) - self._menu_options['sys-language'] = \ - Selector(_('Select locale language'), lambda preset: select_locale_lang('en_US',preset), default='en_US') - self._menu_options['sys-encoding'] = \ - Selector(_('Select locale encoding'), lambda preset: select_locale_enc('utf-8',preset), default='utf-8') - self._menu_options['harddrives'] = \ - Selector( - _('Select harddrives'), - self._select_harddrives) - self._menu_options['disk_layouts'] = \ - Selector( - _('Select disk layout'), - lambda x: select_disk_layout( - storage['arguments'].get('harddrives', []), - storage['arguments'].get('advanced', False) - ), - dependencies=['harddrives']) - self._menu_options['!encryption-password'] = \ - Selector( - _('Set encryption password'), - lambda x: self._select_encrypted_password(), - display_func=lambda x: secret(x) if x else 'None', - dependencies=['harddrives']) - self._menu_options['swap'] = \ - Selector( - _('Use swap'), - lambda preset: ask_for_swap(preset), - default=True) - self._menu_options['bootloader'] = \ - Selector( - _('Select bootloader'), - lambda preset: ask_for_bootloader(storage['arguments'].get('advanced', False),preset), - default="systemd-bootctl" if has_uefi() else "grub-install") - self._menu_options['hostname'] = \ - Selector( - _('Specify hostname'), - ask_hostname, - default='archlinux') - # root password won't have preset value - self._menu_options['!root-password'] = \ - Selector( - _('Set root password'), - lambda preset:self._set_root_password(), - display_func=lambda x: secret(x) if x else 'None') - self._menu_options['!superusers'] = \ - Selector( - _('Specify superuser account'), - lambda preset: self._create_superuser_account(), - exec_func=lambda n,v:self._users_resynch(), - dependencies_not=['!root-password'], - display_func=lambda x: self._display_superusers()) - self._menu_options['!users'] = \ - Selector( - _('Specify user account'), - lambda x: self._create_user_account(), - default={}, - exec_func=lambda n,v:self._users_resynch(), - display_func=lambda x: list(x.keys()) if x else '[]') - self._menu_options['profile'] = \ - Selector( - _('Specify profile'), - lambda x: self._select_profile(), - display_func=lambda x: x if x else 'None') - self._menu_options['audio'] = \ - Selector( - _('Select audio'), - lambda preset: ask_for_audio_selection(is_desktop_profile(storage['arguments'].get('profile', None)),preset)) - self._menu_options['kernels'] = \ - Selector( - _('Select kernels'), - lambda preset: select_kernel(preset), - default=['linux']) - self._menu_options['packages'] = \ - Selector( - _('Additional packages to install'), - # lambda x: ask_additional_packages_to_install(storage['arguments'].get('packages', None)), - ask_additional_packages_to_install, - default=[]) - self._menu_options['additional-repositories'] = \ - Selector( - _('Additional repositories to enable'), - select_additional_repositories, - default=[]) - self._menu_options['nic'] = \ - Selector( - _('Configure network'), - ask_to_configure_network, - display_func=lambda x: x if x else _('Not configured, unavailable unless setup manually'), - default={}) - self._menu_options['timezone'] = \ - Selector( - _('Select timezone'), - lambda preset: ask_for_a_timezone(preset), - default='UTC') - self._menu_options['ntp'] = \ - Selector( - _('Set automatic time sync (NTP)'), - lambda preset: self._select_ntp(preset), - default=True) - self._menu_options['save_config'] = \ - Selector( - _('Save configuration'), - lambda preset: save_config(self._data_store), - enabled=True, - no_store=True) - self._menu_options['install'] = \ - Selector( - self._install_text(), - exec_func=lambda n,v: True if len(self._missing_configs()) == 0 else False, - preview_func=self._prev_install_missing_config, - enabled=True, - no_store=True) - - self._menu_options['abort'] = Selector(_('Abort'), exec_func=lambda n,v:exit(1), enabled=True) - - def _update_install_text(self, name :str = None, result :Any = None): - text = self._install_text() - self._menu_options.get('install').update_description(text) - - def post_callback(self,name :str = None ,result :Any = None): - self._update_install_text(name, result) - - def exit_callback(self): - if self._data_store.get('harddrives', None) and self._data_store.get('!encryption-password', None): - # If no partitions was marked as encrypted, but a password was supplied and we have some disks to format.. - # Then we need to identify which partitions to encrypt. This will default to / (root). - if len(list(encrypted_partitions(storage['arguments'].get('disk_layouts', [])))) == 0: - storage['arguments']['disk_layouts'] = select_encrypted_partitions( - storage['arguments']['disk_layouts'], storage['arguments']['!encryption-password']) - - def _install_text(self): - missing = len(self._missing_configs()) - if missing > 0: - return _('Install ({} config(s) missing)').format(missing) - return 'Install' - - def _prev_install_missing_config(self) -> Optional[str]: - if missing := self._missing_configs(): - text = str(_('Missing configurations:\n')) - for m in missing: - text += f'- {m}\n' - return text[:-1] # remove last new line - return None - - def _missing_configs(self) -> List[str]: - def check(s): - return self._menu_options.get(s).has_selection() - - missing = [] - if not check('bootloader'): - missing += ['Bootloader'] - if not check('hostname'): - missing += ['Hostname'] - if not check('audio'): - missing += ['Audio'] - if not check('!root-password') and not check('!superusers'): - missing += [str(_('Either root-password or at least 1 superuser must be specified'))] - if not check('harddrives'): - missing += ['Hard drives'] - if check('harddrives'): - if not self._menu_options.get('harddrives').is_empty() and not check('disk_layouts'): - missing += ['Disk layout'] - - return missing - - def _set_root_password(self): - prompt = str(_('Enter root password (leave blank to disable root): ')) - password = get_password(prompt=prompt) - return password - - def _select_encrypted_password(self): - if passwd := get_password(prompt=str(_('Enter disk encryption password (leave blank for no encryption): '))): - return passwd - else: - return None - - def _select_ntp(self, preset :bool = True) -> bool: - ntp = ask_ntp(preset) - - value = str(ntp).lower() - SysCommand(f'timedatectl set-ntp {value}') - - return ntp - - def _select_harddrives(self, old_harddrives : list) -> list: - # old_haddrives = storage['arguments'].get('harddrives', []) - harddrives = select_harddrives(old_harddrives) - - # in case the harddrives got changed we have to reset the disk layout as well - if old_harddrives != harddrives: - self._menu_options.get('disk_layouts').set_current_selection(None) - storage['arguments']['disk_layouts'] = {} - - if not harddrives: - prompt = _( - "You decided to skip harddrive selection\nand will use whatever drive-setup is mounted at {} (experimental)\n" - "WARNING: Archinstall won't check the suitability of this setup\n" - "Do you wish to continue?" - ).format(storage['MOUNT_POINT']) - - choice = Menu(prompt, ['yes', 'no'], default_option='yes').run() - - if choice == 'no': - return self._select_harddrives() - - return harddrives - - def _select_profile(self): - profile = select_profile() - - # Check the potentially selected profiles preparations to get early checks if some additional questions are needed. - if profile and profile.has_prep_function(): - namespace = f'{profile.namespace}.py' - with profile.load_instructions(namespace=namespace) as imported: - if not imported._prep_function(): - log(' * Profile\'s preparation requirements was not fulfilled.', fg='red') - exit(1) - - return profile - - def _create_superuser_account(self): - superusers = ask_for_superuser_account(str(_('Manage superuser accounts: '))) - return superusers if superusers else None - - def _create_user_account(self): - users = ask_for_additional_users(str(_('Manage ordinary user accounts: '))) - return users - - def _display_superusers(self): - superusers = self._data_store.get('!superusers', {}) - - if self._menu_options.get('!root-password').has_selection(): - return list(superusers.keys()) if superusers else '[]' - else: - return list(superusers.keys()) if superusers else '' - - def _users_resynch(self): - self.synch('!superusers') - self.synch('!users') - return False -- cgit v1.2.3-54-g00ecf