Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/installer.py
diff options
context:
space:
mode:
Diffstat (limited to 'archinstall/lib/installer.py')
-rw-r--r--archinstall/lib/installer.py124
1 files changed, 60 insertions, 64 deletions
diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py
index b2cd6306..1270959e 100644
--- a/archinstall/lib/installer.py
+++ b/archinstall/lib/installer.py
@@ -24,6 +24,7 @@ from .disk.partition import get_mount_fs_type
from .exceptions import DiskError, ServiceException, RequirementError, HardwareIncompatibilityError, SysCallError
from .hsm import fido2_enroll
from .models.users import User
+from .models.subvolume import Subvolume
if TYPE_CHECKING:
_: Any
@@ -158,8 +159,6 @@ class Installer:
print(_(" Please submit this issue (and file) to https://github.com/archlinux/archinstall/issues"))
raise args[1]
- self.genfstab()
-
if not (missing_steps := self.post_install_check()):
self.log('Installation completed without any errors. You may now reboot.', fg='green', level=logging.INFO)
self.sync_log_to_install_medium()
@@ -195,7 +194,7 @@ class Installer:
return True
def _create_keyfile(self,luks_handle , partition :dict, password :str):
- """ roiutine to create keyfiles, so it can be moved elsewere
+ """ roiutine to create keyfiles, so it can be moved elsewhere
"""
if partition.get('generate-encryption-key-file'):
if not (cryptkey_dir := pathlib.Path(f"{self.target}/etc/cryptsetup-keys.d")).exists():
@@ -220,7 +219,7 @@ class Installer:
"""
if partition.get("mountpoint") is None:
if (sub_list := partition.get("btrfs",{}).get('subvolumes',{})):
- for mountpoint in [sub_list[subvolume] if isinstance(sub_list[subvolume],str) else sub_list[subvolume].get("mountpoint") for subvolume in sub_list if sub_list[subvolume]]:
+ for mountpoint in [sub_list[subvolume].get("mountpoint") if isinstance(subvolume, dict) else subvolume.mountpoint for subvolume in sub_list]:
if mountpoint == '/':
return True
return False
@@ -247,16 +246,17 @@ class Installer:
# we manage the encrypted partititons
for partition in [entry for entry in list_part if entry.get('encrypted', False)]:
# open the luks device and all associate stuff
- if not (password := partition.get('!password', None)):
- raise RequirementError(f"Missing partition {partition['device_instance'].path} encryption password in layout: {partition}")
- loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['mountpoint']).name}loop"
- else:
- loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['device_instance'].path).name}"
+ if not (password := partition.get('!password', None)) and storage['arguments'].get('!encryption-password'):
+ password = storage['arguments'].get('!encryption-password')
+ elif not password:
+ raise RequirementError(f"Missing partition encryption password in layout: {partition}")
+
+ loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['device_instance'].path).name}"
# note that we DON'T auto_unmount (i.e. close the encrypted device so it can be used
with (luks_handle := luks2(partition['device_instance'], loopdev, password, auto_unmount=False)) as unlocked_device:
- if partition.get('generate-encryption-key-file',False) and not self._has_root(partition):
- list_luks_handles.append([luks_handle,partition,password])
+ if partition.get('generate-encryption-key-file', False) and not self._has_root(partition):
+ list_luks_handles.append([luks_handle, partition, password])
# this way all the requesrs will be to the dm_crypt device and not to the physical partition
partition['device_instance'] = unlocked_device
@@ -265,47 +265,25 @@ class Installer:
hsm_device_path = storage['arguments']['HSM']
fido2_enroll(hsm_device_path, partition['device_instance'], password)
- # we manage the btrfs partitions
- if any(btrfs_subvolumes := [entry for entry in list_part if entry.get('btrfs', {}).get('subvolumes', {})]):
- for partition in btrfs_subvolumes:
- if mount_options := ','.join(partition.get('filesystem',{}).get('mount_options',[])):
- self.mount(partition['device_instance'], "/", options=mount_options)
- else:
- self.mount(partition['device_instance'], "/")
-
- setup_subvolumes(
- installation=self,
- partition_dict=partition
- )
+ btrfs_subvolumes = [entry for entry in list_part if entry.get('btrfs', {}).get('subvolumes', [])]
- partition['device_instance'].unmount()
+ for partition in btrfs_subvolumes:
+ device_instance = partition['device_instance']
+ mount_options = partition.get('filesystem', {}).get('mount_options', [])
+ self.mount(device_instance, "/", options=','.join(mount_options))
+ setup_subvolumes(installation=self, partition_dict=partition)
+ device_instance.unmount()
# We then handle any special cases, such as btrfs
- if any(btrfs_subvolumes := [entry for entry in list_part if entry.get('btrfs', {}).get('subvolumes', {})]):
- for partition_information in btrfs_subvolumes:
- for name, mountpoint in sorted(partition_information['btrfs']['subvolumes'].items(), key=lambda item: item[1]):
- btrfs_subvolume_information = {}
-
- match mountpoint:
- case str(): # backwards-compatability
- btrfs_subvolume_information['mountpoint'] = mountpoint
- btrfs_subvolume_information['options'] = []
- case dict():
- btrfs_subvolume_information['mountpoint'] = mountpoint.get('mountpoint', None)
- btrfs_subvolume_information['options'] = mountpoint.get('options', [])
- case _:
- continue
-
- if mountpoint_parsed := btrfs_subvolume_information.get('mountpoint'):
- # We cache the mount call for later
- mount_queue[mountpoint_parsed] = lambda device=partition_information['device_instance'], \
- name=name, \
- subvolume_information=btrfs_subvolume_information: mount_subvolume(
- installation=self,
- device=device,
- name=name,
- subvolume_information=subvolume_information
- )
+ for partition in btrfs_subvolumes:
+ subvolumes: List[Subvolume] = partition['btrfs']['subvolumes']
+ for subvolume in sorted(subvolumes, key=lambda item: item.mountpoint):
+ # We cache the mount call for later
+ mount_queue[subvolume.mountpoint] = lambda sub_vol=subvolume, device=partition['device_instance']: mount_subvolume(
+ installation=self,
+ device=device,
+ subvolume=sub_vol
+ )
# We mount ordinary partitions, and we sort them by the mountpoint
for partition in sorted([entry for entry in list_part if entry.get('mountpoint', False)], key=lambda part: part['mountpoint']):
@@ -348,7 +326,7 @@ class Installer:
def enable_multilib_repository(self):
# Set up a regular expression pattern of a commented line containing 'multilib' within []
- pattern = re.compile("^#\\[.*multilib.*\\]$")
+ pattern = re.compile(r"^#\s*\[multilib\]$")
# This is used to track if the previous line is a match, so we end up uncommenting the line after the block.
matched = False
@@ -413,7 +391,7 @@ class Installer:
try:
run_pacman('-Syy', default_cmd='/usr/bin/pacman')
except SysCallError as error:
- self.log(f'Could not sync a new package databse: {error}', level=logging.ERROR, fg="red")
+ self.log(f'Could not sync a new package database: {error}', level=logging.ERROR, fg="red")
if storage['arguments'].get('silent', False) is False:
if input('Would you like to re-try this download? (Y/n): ').lower().strip() in ('', 'y'):
@@ -454,7 +432,8 @@ class Installer:
for plugin in plugins.values():
if hasattr(plugin, 'on_genfstab'):
- plugin.on_genfstab(self)
+ if plugin.on_genfstab(self) is True:
+ break
return True
@@ -466,10 +445,27 @@ class Installer:
if not len(locale):
return True
+ modifier = ''
+
+ # This is a temporary patch to fix #1200
+ if '.' in locale:
+ locale, potential_encoding = locale.split('.', 1)
+
+ # Override encoding if encoding is set to the default parameter
+ # and the "found" encoding differs.
+ if encoding == 'UTF-8' and encoding != potential_encoding:
+ encoding = potential_encoding
+
+ # Make sure we extract the modifier, that way we can put it in if needed.
+ if '@' in locale:
+ locale, modifier = locale.split('@', 1)
+ modifier = f"@{modifier}"
+ # - End patch
+
with open(f'{self.target}/etc/locale.gen', 'a') as fh:
- fh.write(f'{locale}.{encoding} {encoding}\n')
+ fh.write(f'{locale}.{encoding}{modifier} {encoding}\n')
with open(f'{self.target}/etc/locale.conf', 'w') as fh:
- fh.write(f'LANG={locale}.{encoding}\n')
+ fh.write(f'LANG={locale}.{encoding}{modifier}\n')
return True if SysCommand(f'/usr/bin/arch-chroot {self.target} locale-gen').exit_code == 0 else False
@@ -654,7 +650,7 @@ class Installer:
mkinit.write(f"BINARIES=({' '.join(self.BINARIES)})\n")
mkinit.write(f"FILES=({' '.join(self.FILES)})\n")
- if not storage['arguments']['HSM']:
+ if not storage['arguments'].get('HSM'):
# For now, if we don't use HSM we revert to the old
# way of setting up encryption hooks for mkinitcpio.
# This is purely for stability reasons, we're going away from this.
@@ -696,7 +692,7 @@ class Installer:
self.HOOKS.remove('fsck')
if self.detect_encryption(partition):
- if storage['arguments']['HSM']:
+ if storage['arguments'].get('HSM'):
# Required bby mkinitcpio to add support for fido2-device options
self.pacstrap('libfido2')
@@ -728,7 +724,7 @@ class Installer:
self.log("The multilib flag is set. This system will be installed with the multilib repository enabled.")
self.enable_multilib_repository()
else:
- self.log("The testing flag is not set. This system will be installed without testing repositories enabled.")
+ self.log("The multilib flag is not set. This system will be installed without multilib repositories enabled.")
if testing:
self.log("The testing flag is set. This system will be installed with testing repositories enabled.")
@@ -760,7 +756,7 @@ class Installer:
# TODO: Use python functions for this
SysCommand(f'/usr/bin/arch-chroot {self.target} chmod 700 /root')
- if storage['arguments']['HSM']:
+ if storage['arguments'].get('HSM'):
# TODO:
# A bit of a hack, but we need to get vconsole.conf in there
# before running `mkinitcpio` because it expects it in HSM mode.
@@ -872,7 +868,7 @@ class Installer:
options_entry = f'rw intel_pstate=no_hwp {" ".join(self.KERNEL_PARAMS)}\n'
for subvolume in root_partition.subvolumes:
- if subvolume.root is True:
+ if subvolume.root is True and subvolume.name != '<FS_TREE>':
options_entry = f"rootflags=subvol={subvolume.name} " + options_entry
# Zswap should be disabled when using zram.
@@ -888,7 +884,7 @@ class Installer:
kernel_options = f"options"
- if storage['arguments']['HSM']:
+ if storage['arguments'].get('HSM'):
# Note: lsblk UUID must be used, not PARTUUID for sd-encrypt to work
kernel_options += f" rd.luks.name={real_device.uuid}=luksdev"
# Note: tpm2-device and fido2-device don't play along very well:
@@ -1022,10 +1018,9 @@ class Installer:
boot_partition = None
root_partition = None
for partition in self.partitions:
- print(partition, [partition.mountpoint], [self.target])
- if partition.mountpoint == self.target / 'boot':
+ if self.target / 'boot' in partition.mountpoints:
boot_partition = partition
- elif partition.mountpoint == self.target:
+ elif self.target in partition.mountpoints:
root_partition = partition
if boot_partition is None or root_partition is None:
@@ -1154,7 +1149,8 @@ class Installer:
return SysCommand(f"/usr/bin/arch-chroot {self.target} sh -c \"chsh -s {shell} {user}\"").exit_code == 0
def chown(self, owner :str, path :str, options :List[str] = []) -> bool:
- return SysCommand(f"/usr/bin/arch-chroot {self.target} sh -c 'chown {' '.join(options)} {owner} {path}").exit_code == 0
+ cleaned_path = path.replace('\'', '\\\'')
+ return SysCommand(f"/usr/bin/arch-chroot {self.target} sh -c 'chown {' '.join(options)} {owner} {cleaned_path}'").exit_code == 0
def create_file(self, filename :str, owner :Optional[str] = None) -> InstallationFile:
return InstallationFile(self, filename, owner)