Fixed remaining installation steps and remove legacy references to archinstall.storage['_guided'] and archinstall.storage['_guided_hidden']. Which were great at the time, but they are not deprecated and moved into archinstall.arguments instead to support parameters on command-line. As well as being a bit more description, since they are arguments afterall to various setup instructions.

This commit is contained in:
Anton Hvornum 2021-03-09 16:10:57 +01:00
parent 1167cf589b
commit aafe3d19c6
1 changed files with 230 additions and 227 deletions

View File

@ -43,280 +43,283 @@ def perform_installation(device, boot_partition, language, mirrors):
# If user selected to copy the current ISO network configuration # If user selected to copy the current ISO network configuration
# Perform a copy of the config # Perform a copy of the config
if archinstall.storage['_guided']['network'] == 'Copy ISO network configuration to installation': if archinstall.arguments.get('nic', None) == 'Copy ISO network configuration to installation':
installation.copy_ISO_network_config(enable_services=True) # Sources the ISO network configuration to the install medium. installation.copy_ISO_network_config(enable_services=True) # Sources the ISO network configuration to the install medium.
# Otherwise, if a interface was selected, configure that interface # Otherwise, if a interface was selected, configure that interface
elif archinstall.storage['_guided']['network']: elif archinstall.arguments.get('nic', None):
installation.configure_nic(**archinstall.storage['_guided']['network']) installation.configure_nic(**archinstall.arguments.get('nic', {}))
installation.enable_service('systemd-networkd') installation.enable_service('systemd-networkd')
installation.enable_service('systemd-resolved') installation.enable_service('systemd-resolved')
if archinstall.storage['_guided']['packages'] and archinstall.storage['_guided']['packages'][0] != '': if archinstall.arguments.get('packages', None) and archinstall.arguments.get('packages', None)[0] != '':
installation.add_additional_packages(archinstall.storage['_guided']['packages']) installation.add_additional_packages(archinstall.arguments.get('packages', None))
if 'profile' in archinstall.storage['_guided'] and len(profile := archinstall.storage['_guided']['profile']['path'].strip()): if archinstall.arguments.get('profile', None) and len(profile := archinstall.arguments.get('profile').strip()):
installation.install_profile(profile) installation.install_profile(profile)
if archinstall.storage['_guided']['users']: if archinstall.arguments.get('users', None):
for user in archinstall.storage['_guided']['users']: for user, password in archinstall.arguments.get('users').items():
password = users[user] installation.user_create(user, password, sudo=False)
sudo = False if archinstall.arguments.get('superusers', None):
if 'root_pw' not in archinstall.storage['_guided_hidden'] or len(archinstall.storage['_guided_hidden']['root_pw'].strip()) == 0: for user, password in archinstall.arguments.get('superusers').items():
sudo = True installation.user_create(user, password, sudo=True)
installation.user_create(user, password, sudo=sudo) if (root_pw := archinstall.arguments.get('!root-password', None)) and len(root_pw):
installation.user_set_pw('root', root_pw)
if 'root_pw' in archinstall.storage['_guided_hidden'] and archinstall.storage['_guided_hidden']['root_pw']: def ask_user_questions():
installation.user_set_pw('root', archinstall.storage['_guided_hidden']['root_pw']) """
First, we'll ask the user for a bunch of user input.
Not until we're satisfied with what we want to install
will we continue with the actual installation steps.
"""
if not archinstall.arguments.get('keyboard-language', None):
archinstall.arguments['keyboard-language'] = archinstall.select_language(archinstall.list_keyboard_languages()).strip()
""" # Before continuing, set the preferred keyboard layout/language in the current terminal.
First, we'll ask the user for a bunch of user input. # This will just help the user with the next following questions.
Not until we're satisfied with what we want to install if len(archinstall.arguments['keyboard-language']):
will we continue with the actual installation steps. archinstall.set_keyboard_language(archinstall.arguments['keyboard-language'])
"""
if not archinstall.arguments.get('keyboard-language', None):
archinstall.arguments['keyboard-language'] = archinstall.select_language(archinstall.list_keyboard_languages()).strip()
# Before continuing, set the preferred keyboard layout/language in the current terminal. # Set which region to download packages from during the installation
# This will just help the user with the next following questions. if not archinstall.arguments.get('mirror-region', None):
if len(archinstall.arguments['keyboard-language']): archinstall.arguments['mirror-region'] = archinstall.select_mirror_regions(archinstall.list_mirrors())
archinstall.set_keyboard_language(archinstall.arguments['keyboard-language']) else:
selected_region = archinstall.arguments['mirror-region']
# Set which region to download packages from during the installation archinstall.arguments['mirror-region'] = {selected_region : archinstall.list_mirrors()[selected_region]}
if not archinstall.arguments.get('mirror-region', None):
archinstall.arguments['mirror-region'] = archinstall.select_mirror_regions(archinstall.list_mirrors())
else:
selected_region = archinstall.arguments['mirror-region']
archinstall.arguments['mirror-region'] = {selected_region : archinstall.list_mirrors()[selected_region]}
# Ask which harddrive/block-device we will install to # Ask which harddrive/block-device we will install to
if archinstall.arguments.get('harddrive', None): if archinstall.arguments.get('harddrive', None):
archinstall.arguments['harddrive'] = archinstall.BlockDevice(archinstall.arguments['harddrive']) archinstall.arguments['harddrive'] = archinstall.BlockDevice(archinstall.arguments['harddrive'])
else: else:
archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks()) archinstall.arguments['harddrive'] = archinstall.select_disk(archinstall.all_disks())
# Perform a quick sanity check on the selected harddrive. # Perform a quick sanity check on the selected harddrive.
# 1. Check if it has partitions # 1. Check if it has partitions
# 3. Check that we support the current partitions # 3. Check that we support the current partitions
# 2. If so, ask if we should keep them or wipe everything # 2. If so, ask if we should keep them or wipe everything
if archinstall.arguments['harddrive'].has_partitions(): if archinstall.arguments['harddrive'].has_partitions():
archinstall.log(f"{archinstall.arguments['harddrive']} contains the following partitions:", fg='red') archinstall.log(f"{archinstall.arguments['harddrive']} contains the following partitions:", fg='red')
# We curate a list pf supported paritions # We curate a list pf supported paritions
# and print those that we don't support. # and print those that we don't support.
partition_mountpoints = {} partition_mountpoints = {}
for partition in archinstall.arguments['harddrive']: for partition in archinstall.arguments['harddrive']:
try: try:
if partition.filesystem_supported(): if partition.filesystem_supported():
archinstall.log(f" {partition}") archinstall.log(f" {partition}")
partition_mountpoints[partition] = None partition_mountpoints[partition] = None
except archinstall.UnknownFilesystemFormat as err: except archinstall.UnknownFilesystemFormat as err:
archinstall.log(f" {partition} (Filesystem not supported)", fg='red') archinstall.log(f" {partition} (Filesystem not supported)", fg='red')
# We then ask what to do with the paritions. # We then ask what to do with the paritions.
if (option := archinstall.ask_for_disk_layout()) == 'abort': if (option := archinstall.ask_for_disk_layout()) == 'abort':
archinstall.log(f"Safely aborting the installation. No changes to the disk or system has been made.") archinstall.log(f"Safely aborting the installation. No changes to the disk or system has been made.")
exit(1) exit(1)
elif option == 'keep-existing': elif option == 'keep-existing':
archinstall.arguments['harddrive'].keep_partitions = True archinstall.arguments['harddrive'].keep_partitions = True
archinstall.log(f" ** You will now select which partitions to use by selecting mount points (inside the installation). **") archinstall.log(f" ** You will now select which partitions to use by selecting mount points (inside the installation). **")
archinstall.log(f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **") archinstall.log(f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **")
while True: while True:
# Select a partition # Select a partition
partition = archinstall.generic_select(partition_mountpoints.keys(), partition = archinstall.generic_select(partition_mountpoints.keys(),
"Select a partition by number that you want to set a mount-point for (leave blank when done): ") "Select a partition by number that you want to set a mount-point for (leave blank when done): ")
if not partition: if not partition:
break
# Select a mount-point
mountpoint = input(f"Enter a mount-point for {partition}: ").strip(' ')
if len(mountpoint):
# Get a valid & supported filesystem for the parition:
while 1:
new_filesystem = input(f"Enter a valid filesystem for {partition} (leave blank for {partition.filesystem}): ").strip(' ')
if len(new_filesystem) <= 0:
if partition.encrypted and partition.filesystem == 'crypto_LUKS':
if (autodetected_filesystem := partition.detect_inner_filesystem(archinstall.arguments.get('!encryption-password', None))):
new_filesystem = autodetected_filesystem
else:
archinstall.log(f"Could not auto-detect the filesystem inside the encrypted volume.", fg='red')
archinstall.log(f"A filesystem must be defined for the unlocked encrypted partition.")
continue
break
# Since the potentially new filesystem is new
# we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem.
# There's a nice wrapper for this on the partition object itself that supports a path-override during .format()
try:
partition.format(new_filesystem, path='/dev/null', log_formating=False, allow_formatting=True)
except archinstall.UnknownFilesystemFormat:
archinstall.log(f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/Torxed/archinstall/issues.")
archinstall.log(f"Until then, please enter another supported filesystem.")
continue
except archinstall.SysCallError:
pass # Expected exception since mkfs.<format> can not format /dev/null.
# But that means our .format() function supported it.
break break
# When we've selected all three criterias, # Select a mount-point
# We can safely mark the partition for formatting and where to mount it. mountpoint = input(f"Enter a mount-point for {partition}: ").strip(' ')
# TODO: allow_formatting might be redundant since target_mountpoint should only be if len(mountpoint):
# set if we actually want to format it anyway.
partition.allow_formatting = True
partition.target_mountpoint = mountpoint
# Only overwrite the filesystem definition if we selected one:
if len(new_filesystem):
partition.filesystem = new_filesystem
archinstall.log('Using existing partition table reported above.') # Get a valid & supported filesystem for the parition:
elif option == 'format-all': while 1:
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format() new_filesystem = input(f"Enter a valid filesystem for {partition} (leave blank for {partition.filesystem}): ").strip(' ')
archinstall.arguments['harddrive'].keep_partitions = False if len(new_filesystem) <= 0:
if partition.encrypted and partition.filesystem == 'crypto_LUKS':
if (autodetected_filesystem := partition.detect_inner_filesystem(archinstall.arguments.get('!encryption-password', None))):
new_filesystem = autodetected_filesystem
else:
archinstall.log(f"Could not auto-detect the filesystem inside the encrypted volume.", fg='red')
archinstall.log(f"A filesystem must be defined for the unlocked encrypted partition.")
continue
break
# Get disk encryption password (or skip if blank) # Since the potentially new filesystem is new
if not archinstall.arguments.get('!encryption-password', None): # we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem.
archinstall.arguments['!encryption-password'] = archinstall.get_password(prompt='Enter disk encryption password (leave blank for no encryption): ') # There's a nice wrapper for this on the partition object itself that supports a path-override during .format()
archinstall.arguments['harddrive'].encryption_password = archinstall.arguments['!encryption-password'] try:
partition.format(new_filesystem, path='/dev/null', log_formating=False, allow_formatting=True)
except archinstall.UnknownFilesystemFormat:
archinstall.log(f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/Torxed/archinstall/issues.")
archinstall.log(f"Until then, please enter another supported filesystem.")
continue
except archinstall.SysCallError:
pass # Expected exception since mkfs.<format> can not format /dev/null.
# But that means our .format() function supported it.
break
# Get the hostname for the machine # When we've selected all three criterias,
if not archinstall.arguments.get('hostname', None): # We can safely mark the partition for formatting and where to mount it.
archinstall.arguments['hostname'] = input('Desired hostname for the installation: ').strip(' ') # TODO: allow_formatting might be redundant since target_mountpoint should only be
# set if we actually want to format it anyway.
partition.allow_formatting = True
partition.target_mountpoint = mountpoint
# Only overwrite the filesystem definition if we selected one:
if len(new_filesystem):
partition.filesystem = new_filesystem
# Ask for a root password (optional, but triggers requirement for super-user if skipped) archinstall.log('Using existing partition table reported above.')
if not archinstall.arguments.get('!root-password', None): elif option == 'format-all':
archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (Recommended: leave blank to leave root disabled): ') archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
archinstall.arguments['harddrive'].keep_partitions = False
# # Storing things in _guided_hidden helps us avoid printing it # Get disk encryption password (or skip if blank)
# # when echoing user configuration: archinstall.storage['_guided'] if not archinstall.arguments.get('!encryption-password', None):
# archinstall.storage['_guided_hidden']['root_pw'] = root_pw archinstall.arguments['!encryption-password'] = archinstall.get_password(prompt='Enter disk encryption password (leave blank for no encryption): ')
# archinstall.storage['_guided']['root_unlocked'] = True archinstall.arguments['harddrive'].encryption_password = archinstall.arguments['!encryption-password']
# break
# Ask for additional users (super-user if root pw was not set) # Get the hostname for the machine
archinstall.arguments['users'] = {} if not archinstall.arguments.get('hostname', None):
archinstall.arguments['superusers'] = {} archinstall.arguments['hostname'] = input('Desired hostname for the installation: ').strip(' ')
if not archinstall.arguments.get('!root-password', None):
archinstall.arguments['superusers'] = archinstall.ask_for_superuser_account('Create a required super-user with sudo privileges: ', forced=True)
users, superusers = archinstall.ask_for_additional_users('Any additional users to install (leave blank for no users): ') # Ask for a root password (optional, but triggers requirement for super-user if skipped)
archinstall.arguments['users'] = users if not archinstall.arguments.get('!root-password', None):
archinstall.arguments['superusers'] = {**archinstall.arguments['superusers'], **superusers} archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (Recommended: leave blank to leave root disabled): ')
# Ask for archinstall-specific profiles (such as desktop environments etc) # # Storing things in _guided_hidden helps us avoid printing it
if not archinstall.arguments.get('profile', None): # # when echoing user configuration: archinstall.storage['_guided']
archinstall.arguments['profile'] = archinstall.select_profile(archinstall.list_profiles()) # archinstall.storage['_guided_hidden']['root_pw'] = root_pw
else: # archinstall.storage['_guided']['root_unlocked'] = True
archinstall.arguments['profile'] = archinstall.list_profiles()[archinstall.arguments['profile']] # break
# Check the potentially selected profiles preperations to get early checks if some additional questions are needed. # Ask for additional users (super-user if root pw was not set)
if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function(): archinstall.arguments['users'] = {}
with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported: archinstall.arguments['superusers'] = {}
if not imported._prep_function(): if not archinstall.arguments.get('!root-password', None):
archinstall.log( archinstall.arguments['superusers'] = archinstall.ask_for_superuser_account('Create a required super-user with sudo privileges: ', forced=True)
' * Profile\'s preparation requirements was not fulfilled.',
bg='black',
fg='red'
)
exit(1)
# Additional packages (with some light weight error handling for invalid package names) users, superusers = archinstall.ask_for_additional_users('Any additional users to install (leave blank for no users): ')
if not archinstall.arguments.get('packages', None): archinstall.arguments['users'] = users
archinstall.arguments['packages'] = [package for package in input('Additional packages aside from base (space separated): ').split(' ') if len(package)] archinstall.arguments['superusers'] = {**archinstall.arguments['superusers'], **superusers}
# Verify packages that were given # Ask for archinstall-specific profiles (such as desktop environments etc)
try: if not archinstall.arguments.get('profile', None):
archinstall.validate_package_list(archinstall.arguments['packages']) archinstall.arguments['profile'] = archinstall.select_profile(archinstall.list_profiles())
except archinstall.RequirementError as e: else:
archinstall.log(e, fg='red') archinstall.arguments['profile'] = archinstall.list_profiles()[archinstall.arguments['profile']]
exit(1)
# Ask or Call the helper function that asks the user to optionally configure a network. # Check the potentially selected profiles preperations to get early checks if some additional questions are needed.
if not archinstall.arguments.get('nic', None): if archinstall.arguments['profile'] and archinstall.arguments['profile'].has_prep_function():
archinstall.arguments['nic'] = archinstall.ask_to_configure_network() with archinstall.arguments['profile'].load_instructions(namespace=f"{archinstall.arguments['profile'].namespace}.py") as imported:
if not imported._prep_function():
archinstall.log(
' * Profile\'s preparation requirements was not fulfilled.',
bg='black',
fg='red'
)
exit(1)
print() # Additional packages (with some light weight error handling for invalid package names)
print('This is your chosen configuration:') if not archinstall.arguments.get('packages', None):
archinstall.log("-- Guided template chosen (with below config) --", level=archinstall.LOG_LEVELS.Debug) archinstall.arguments['packages'] = [package for package in input('Additional packages aside from base (space separated): ').split(' ') if len(package)]
archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=archinstall.LOG_LEVELS.Info)
print()
input('Press Enter to continue.') # Verify packages that were given
try:
archinstall.validate_package_list(archinstall.arguments['packages'])
except archinstall.RequirementError as e:
archinstall.log(e, fg='red')
exit(1)
""" # Ask or Call the helper function that asks the user to optionally configure a network.
Issue a final warning before we continue with something un-revertable. if not archinstall.arguments.get('nic', None):
We mention the drive one last time, and count from 5 to 0. archinstall.arguments['nic'] = archinstall.ask_to_configure_network()
"""
print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='') def perform_installation_steps():
print()
print('This is your chosen configuration:')
archinstall.log("-- Guided template chosen (with below config) --", level=archinstall.LOG_LEVELS.Debug)
archinstall.log(json.dumps(archinstall.arguments, indent=4, sort_keys=True, cls=archinstall.JSON), level=archinstall.LOG_LEVELS.Info)
print()
for i in range(5, 0, -1): input('Press Enter to continue.')
print(f"{i}", end='')
for x in range(4): """
sys.stdout.flush() Issue a final warning before we continue with something un-revertable.
time.sleep(0.25) We mention the drive one last time, and count from 5 to 0.
print(".", end='') """
if SIG_TRIGGER: print(f" ! Formatting {archinstall.arguments['harddrive']} in ", end='')
abort = input('\nDo you really want to abort (y/n)? ')
if abort.strip() != 'n':
exit(0)
if SIG_TRIGGER is False: for i in range(5, 0, -1):
sys.stdin.read() print(f"{i}", end='')
SIG_TRIGGER = False
signal.signal(signal.SIGINT, sig_handler)
# Put back the default/original signal handler now that we're done catching for x in range(4):
# and interrupting SIGINT with "Do you really want to abort". sys.stdout.flush()
print() time.sleep(0.25)
signal.signal(signal.SIGINT, original_sigint_handler) print(".", end='')
""" if SIG_TRIGGER:
Setup the blockdevice, filesystem (and optionally encryption). abort = input('\nDo you really want to abort (y/n)? ')
Once that's done, we'll hand over to perform_installation() if abort.strip() != 'n':
""" exit(0)
with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs:
# Wipe the entire drive if the disk flag `keep_partitions`is False. if SIG_TRIGGER is False:
if archinstall.arguments['harddrive'].keep_partitions is False: sys.stdin.read()
fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs'), SIG_TRIGGER = False
encrypt_root_partition=archinstall.arguments.get('!encryption-password', False)) signal.signal(signal.SIGINT, sig_handler)
# Otherwise, check if encryption is desired and mark the root partition as encrypted.
elif archinstall.arguments.get('!encryption-password', None): # Put back the default/original signal handler now that we're done catching
root_partition = fs.find_partition('/') # and interrupting SIGINT with "Do you really want to abort".
root_partition.encrypted = True print()
signal.signal(signal.SIGINT, original_sigint_handler)
# After the disk is ready, iterate the partitions and check
# which ones are safe to format, and format those. """
for partition in archinstall.arguments['harddrive']: Setup the blockdevice, filesystem (and optionally encryption).
if partition.safe_to_format(): Once that's done, we'll hand over to perform_installation()
if partition.encrypted: """
partition.encrypt(password=archinstall.arguments.get('!encryption-password', None)) with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs:
# Wipe the entire drive if the disk flag `keep_partitions`is False.
if archinstall.arguments['harddrive'].keep_partitions is False:
fs.use_entire_disk(root_filesystem_type=archinstall.arguments.get('filesystem', 'btrfs'),
encrypt_root_partition=archinstall.arguments.get('!encryption-password', False))
# Otherwise, check if encryption is desired and mark the root partition as encrypted.
elif archinstall.arguments.get('!encryption-password', None):
root_partition = fs.find_partition('/')
root_partition.encrypted = True
# After the disk is ready, iterate the partitions and check
# which ones are safe to format, and format those.
for partition in archinstall.arguments['harddrive']:
if partition.safe_to_format():
if partition.encrypted:
partition.encrypt(password=archinstall.arguments.get('!encryption-password', None))
else:
partition.format()
else: else:
partition.format() archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug)
if archinstall.arguments.get('!encryption-password', None):
# First encrypt and unlock, then format the desired partition inside the encrypted part.
# archinstall.luks2() encrypts the partition when entering the with context manager, and
# unlocks the drive so that it can be used as a normal block-device within archinstall.
with archinstall.luks2(fs.find_partition('/'), 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device:
unlocked_device.format(fs.find_partition('/').filesystem)
perform_installation(device=unlocked_device,
boot_partition=fs.find_partition('/boot'),
language=archinstall.arguments['keyboard-language'],
mirrors=archinstall.arguments['mirror-region'])
else: else:
archinstall.log(f"Did not format {partition} because .safe_to_format() returned False or .allow_formatting was False.", level=archinstall.LOG_LEVELS.Debug) archinstall.arguments['harddrive'].partition[1].format('ext4')
perform_installation(device=fs.find_partition('/'),
if archinstall.arguments.get('!encryption-password', None):
# First encrypt and unlock, then format the desired partition inside the encrypted part.
# archinstall.luks2() encrypts the partition when entering the with context manager, and
# unlocks the drive so that it can be used as a normal block-device within archinstall.
with archinstall.luks2(fs.find_partition('/'), 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device:
unlocked_device.format(fs.find_partition('/').filesystem)
perform_installation(device=unlocked_device,
boot_partition=fs.find_partition('/boot'), boot_partition=fs.find_partition('/boot'),
language=archinstall.arguments['keyboard-language'], language=archinstall.arguments['keyboard-language'],
mirrors=archinstall.arguments['mirror-region']) mirrors=archinstall.arguments['mirror-region'])
else:
archinstall.arguments['harddrive'].partition[1].format('ext4') ask_user_questions()
perform_installation(device=fs.find_partition('/'), perform_pre_installation_steps()
boot_partition=fs.find_partition('/boot'),
language=archinstall.arguments['keyboard-language'],
mirrors=archinstall.arguments['mirror-region'])