From 6bc0e2502f81f6af1d12cd4488aa66f4dd99c032 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Sun, 19 Nov 2023 22:09:10 +1100 Subject: [PATCH] Update LVM --- archinstall/lib/disk/device_handler.py | 16 +- archinstall/lib/disk/device_model.py | 31 +++ archinstall/lib/disk/disk_menu.py | 4 +- archinstall/lib/disk/filesystem.py | 10 +- archinstall/lib/installer.py | 297 ++++++++++++++-------- archinstall/lib/interactions/disk_conf.py | 1 + 6 files changed, 234 insertions(+), 125 deletions(-) diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py index f500e8a9a0..08b6cbf2cb 100644 --- a/archinstall/lib/disk/device_handler.py +++ b/archinstall/lib/disk/device_handler.py @@ -286,12 +286,7 @@ def lvm_pv_create(self, pvs: List[PartitionModification]): cmd = 'pvcreate ' + ' '.join([str(pv.safe_dev_path) for pv in pvs]) debug(f'Creating LVM PVS: {cmd}') - # SysCommand(cmd, peek_output=True) - - worker = SysCommandWorker(cmd) - worker.poll() - info(worker) - worker.write(b'y\n', line_ending=False) + SysCommand(cmd) def lvm_group_create(self, vg: LvmVolumeGroup): pvs_str = ' '.join([str(pv.safe_dev_path) for pv in vg.pvs]) @@ -302,11 +297,14 @@ def lvm_group_create(self, vg: LvmVolumeGroup): def lvm_vol_create(self, vg_name: str, volume: LvmVolume, offset: Size): length = volume.length - offset - length = length.format_size(Unit.B, include_unit=False) - cmd = f'lvcreate -L {length}B {vg_name} -n {volume.name} --wipesignatures y --zero y --yes' + length_str = length.format_size(Unit.B, include_unit=False) + cmd = f'lvcreate -L {length_str}B {vg_name} -n {volume.name} --wipesignatures y --zero y' debug(f'Creating volume: {cmd}') - SysCommand(cmd) + + worker = SysCommandWorker(cmd) + worker.poll() + worker.write(b'y\n', line_ending=False) volume.dev_path = f'/dev/{vg_name}/{volume.name}' diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py index 2814689ede..4fddbc3a39 100644 --- a/archinstall/lib/disk/device_model.py +++ b/archinstall/lib/disk/device_model.py @@ -918,6 +918,7 @@ class LvmVolume: mount_options: List[str] = field(default_factory=list) btrfs_subvols: List[SubvolumeModification] = field(default_factory=list) + # mapper device path /dev// dev_path: Optional[Path] = None @property @@ -926,6 +927,12 @@ def safe_dev_path(self) -> Path: return self.dev_path raise ValueError('No device path for volume defined') + @property + def safe_fs_type(self) -> FilesystemType: + if self.fs_type is None: + raise ValueError('File system type is not set') + return self.fs_type + @property def relative_mountpoint(self) -> Path: """ @@ -981,6 +988,16 @@ def exists(self) -> bool: def is_exists_or_modify(self) -> bool: return self.status in [LvmVolumeStatus.Exist, LvmVolumeStatus.Modify] + def is_root(self) -> bool: + if self.mountpoint is not None: + return Path('/') == self.mountpoint + else: + for subvol in self.btrfs_subvols: + if subvol.is_root(): + return True + + return False + @dataclass class LvmGroupInfo: @@ -1022,6 +1039,20 @@ def parse_arg(arg: Dict[str, Any], disk_config: DiskLayoutConfiguration) -> LvmC vol_groups=[LvmVolumeGroup.parse_arg(vol_group, disk_config) for vol_group in arg['vol_groups']], ) + def get_all_pvs(self) -> List[PartitionModification]: + pvs = [] + for vg in self.vol_groups: + pvs += vg.pvs + + return pvs + + def get_root_volume(self) -> Optional[LvmVolume]: + for vg in self.vol_groups: + filtered = next(filter(lambda x: x.is_root(), vg.volumes), None) + if filtered: + return filtered + + return None @dataclass class DeviceModification: diff --git a/archinstall/lib/disk/disk_menu.py b/archinstall/lib/disk/disk_menu.py index a44998412d..d3a801ab4c 100644 --- a/archinstall/lib/disk/disk_menu.py +++ b/archinstall/lib/disk/disk_menu.py @@ -130,8 +130,10 @@ def _prev_lvm_config(self) -> Optional[str]: pv_table = FormattedOutput.as_table(vol_gp.pvs) output += '{}:\n{}'.format(str(_('Physical volumes')), pv_table) + output += f'\nVolume Group: {vol_gp.name}' + lvm_volumes = FormattedOutput.as_table(vol_gp.volumes) - output += '\n{}:\n{}'.format(str(_('Volumes')), lvm_volumes) + output += '\n\n{}:\n{}'.format(str(_('Volumes')), lvm_volumes) return output diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index 5443035fa1..bec6e3c5c8 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -62,7 +62,7 @@ def perform_filesystem_operations(self, show_countdown: bool = True): for mod in device_mods: if boot_part := mod.get_boot_partition(): info(f'Formatting boot partition: {boot_part.dev_path}') - device_handler.format_partitions( + self.format_partitions( [boot_part], mod.device_path ) @@ -70,7 +70,7 @@ def perform_filesystem_operations(self, show_countdown: bool = True): self.setup_lvm(self._disk_config.lvm_config) else: for mod in device_mods: - device_handler.format_partitions( + self.format_partitions( mod.partitions, mod.device_path, enc_conf=self._enc_config @@ -162,10 +162,14 @@ def setup_lvm( for volume in vol_gp.volumes: device_handler.lvm_vol_create(vol_gp.name, volume, offset) - device_handler.format(volume.fs_type, volume.safe_dev_path) self._lvm_vol_handle_e2scrub(vol_gp) + for volume in vol_gp.volumes: + # wait a bit otherwise the mkfs will fail as it can't + # find the mapper device yet + device_handler.format(volume.fs_type, volume.safe_dev_path) + def _lvm_vol_handle_e2scrub(self, vol_gp: LvmVolumeGroup): # from arch wiki: # If a logical volume will be formatted with ext4, leave at least 256 MiB diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index c17714a9af..447529eb20 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -52,7 +52,7 @@ def __init__( `Installer()` is the wrapper for most basic installation steps. It also wraps :py:func:`~archinstall.Installer.pacstrap` among other things. """ - self.base_packages = base_packages or __packages__[:3] + self._base_packages = base_packages or __packages__[:3] self.kernels = kernels or ['linux'] self._disk_config = disk_config @@ -64,11 +64,11 @@ def __init__( self.helper_flags: Dict[str, Any] = {'base': False, 'bootloader': None} for kernel in self.kernels: - self.base_packages.append(kernel) + self._base_packages.append(kernel) # If using accessibility tools in the live environment, append those to the packages list if accessibility_tools_in_use(): - self.base_packages.extend(__accessibility_packages__) + self._base_packages.extend(__accessibility_packages__) self.post_base_install: List[Callable] = [] @@ -90,6 +90,8 @@ def __init__( self._fstab_entries: List[str] = [] self._zram_enabled = False + self._disable_fstrim = False + self.pacman = Pacman(self.target, storage['arguments'].get('silent', False)) def __enter__(self) -> 'Installer': @@ -179,18 +181,24 @@ def sanity_check(self): def mount_ordered_layout(self): info('Mounting partitions in order') + self._mount_partition_layout() - if self._disk_config.lvm_config: - self._mount_lvm_layout() - else: - self._mount_partition_layout() + info('Mounting LVM in order') + self._mount_lvm_layout() def _mount_partition_layout(self): + # do not mount any PVs from the LVM configuration + pvs = [] + if self._disk_config.lvm_config: + pvs = self._disk_config.lvm_config.get_all_pvs() + for mod in self._disk_config.device_modifications: + part_mods = list(filter(lambda x: x not in pvs, mod.partitions)) + # partitions have to mounted in the right order on btrfs the mountpoint will # be empty as the actual subvolumes are getting mounted instead so we'll use # '/' just for sorting - sorted_part_mods = sorted(mod.partitions, key=lambda x: x.mountpoint or Path('/')) + sorted_part_mods = sorted(part_mods, key=lambda x: x.mountpoint or Path('/')) enc_partitions = [] if self._disk_encryption.encryption_type is not disk.EncryptionType.NoEncryption: @@ -245,8 +253,8 @@ def _mount_lvm_vol(self, volume: disk.LvmVolume): if volume.fs_type == disk.FilesystemType.Btrfs: self._mount_btrfs_subvol(volume.dev_path, volume.btrfs_subvols) elif volume.mountpoint: - target = self.target / volume.relative_mountpoint - disk.device_handler.mount(volume.dev_path, target, options=volume.mount_options) + target = self.target / volume.relative_mountpoint + disk.device_handler.mount(volume.dev_path, target, options=volume.mount_options) def _mount_luks_partition(self, part_mod: disk.PartitionModification, luks_handler: Luks2): # it would be none if it's btrfs as the subvolumes will have the mountpoints defined @@ -361,36 +369,44 @@ def genfstab(self, flags: str = '-pU'): for entry in self._fstab_entries: fp.write(f'{entry}\n') - for mod in self._disk_config.device_modifications: - for part_mod in mod.partitions: - if part_mod.fs_type != disk.FilesystemType.Btrfs: - continue - - with fstab_path.open('r') as fp: - fstab = fp.readlines() + btrfs_sub_vols: List[disk.SubvolumeModification] = [] - # Replace the {installation}/etc/fstab with entries - # using the compress=zstd where the mountpoint has compression set. - for index, line in enumerate(fstab): - # So first we grab the mount options by using subvol=.*? as a locator. - # And we also grab the mountpoint for the entry, for instance /var/log - subvoldef = re.findall(',.*?subvol=.*?[\t ]', line) - mountpoint = re.findall('[\t ]/.*?[\t ]', line) - - if not subvoldef or not mountpoint: - continue - - for sub_vol in part_mod.btrfs_subvols: - # We then locate the correct subvolume and check if it's compressed, - # and skip entries where compression is already defined - # We then sneak in the compress=zstd option if it doesn't already exist: - if sub_vol.compress and str(sub_vol.mountpoint) == Path( - mountpoint[0].strip()) and ',compress=zstd,' not in line: - fstab[index] = line.replace(subvoldef[0], f',compress=zstd{subvoldef[0]}') - break + if self._disk_config.lvm_config: + for vg in self._disk_config.lvm_config.vol_groups: + for vol in vg.volumes: + if vol.fs_type == disk.FilesystemType.Btrfs: + btrfs_sub_vols += vol.btrfs_subvols + else: + for mod in self._disk_config.device_modifications: + for part_mod in mod.partitions: + if part_mod.fs_type == disk.FilesystemType.Btrfs: + btrfs_sub_vols += part_mod.btrfs_subvols + + with fstab_path.open('r') as fp: + fstab = fp.readlines() + + # Replace the {installation}/etc/fstab with entries + # using the compress=zstd where the mountpoint has compression set. + for index, line in enumerate(fstab): + # So first we grab the mount options by using subvol=.*? as a locator. + # And we also grab the mountpoint for the entry, for instance /var/log + subvoldef = re.findall(',.*?subvol=.*?[\t ]', line) + mountpoint = re.findall('[\t ]/.*?[\t ]', line) + + if not subvoldef or not mountpoint: + continue + + for sub_vol in btrfs_sub_vols: + # We then locate the correct subvolume and check if it's compressed, + # and skip entries where compression is already defined + # We then sneak in the compress=zstd option if it doesn't already exist: + if sub_vol.compress and str(sub_vol.mountpoint) == Path( + mountpoint[0].strip()) and ',compress=zstd,' not in line: + fstab[index] = line.replace(subvoldef[0], f',compress=zstd{subvoldef[0]}') + break - with fstab_path.open('w') as fp: - fp.writelines(fstab) + with fstab_path.open('w') as fp: + fp.writelines(fstab) def set_hostname(self, hostname: str, *args: str, **kwargs: str) -> None: with open(f'{self.target}/etc/hostname', 'w') as fh: @@ -531,7 +547,7 @@ def copy_iso_network_config(self, enable_services: bool = False) -> bool: if enable_services: # If we haven't installed the base yet (function called pre-maturely) if self.helper_flags.get('base', False) is False: - self.base_packages.append('iwd') + self._base_packages.append('iwd') # This function will be called after minimal_installation() # as a hook for post-installs. This hook is only needed if @@ -607,55 +623,99 @@ def _get_microcode(self) -> Optional[Path]: return vendor.get_ucode() return None - def minimal_installation( - self, - testing: bool = False, - multilib: bool = False, - mkinitcpio: bool = True, - hostname: str = 'archinstall', - locale_config: LocaleConfiguration = LocaleConfiguration.default() - ): - _disable_fstrim = False + def _handle_partition_installation(self): + pvs = [] + if self._disk_config.lvm_config: + pvs = self._disk_config.lvm_config.get_all_pvs() + for mod in self._disk_config.device_modifications: for part in mod.partitions: - if part.fs_type is not None: - if (pkg := part.fs_type.installation_pkg) is not None: - self.base_packages.append(pkg) - if (module := part.fs_type.installation_module) is not None: + if part in pvs or part.fs_type is None: + continue + + if (pkg := part.fs_type.installation_pkg) is not None: + self._base_packages.append(pkg) + if (module := part.fs_type.installation_module) is not None: + self.modules.append(module) + if (binary := part.fs_type.installation_binary) is not None: + self._binaries.append(binary) + + # https://github.com/archlinux/archinstall/issues/1837 + if part.fs_type.fs_type_mount == 'btrfs': + self._disable_fstrim = True + + # There is not yet an fsck tool for NTFS. If it's being used for the root filesystem, the hook should be removed. + if part.fs_type.fs_type_mount == 'ntfs3' and part.mountpoint == self.target: + if 'fsck' in self._hooks: + self._hooks.remove('fsck') + + if part in self._disk_encryption.partitions: + if self._disk_encryption.hsm_device: + # Required by mkinitcpio to add support for fido2-device options + self.pacman.strap('libfido2') + + if 'sd-encrypt' not in self._hooks: + self._hooks.insert(self._hooks.index('filesystems'), 'sd-encrypt') + else: + if 'encrypt' not in self._hooks: + self._hooks.insert(self._hooks.index('filesystems'), 'encrypt') + + def _handle_lvm_installation(self): + if not self._disk_config.lvm_config: + return + + for vg in self._disk_config.lvm_config.vol_groups: + for vol in vg.volumes: + if vol.fs_type is not None: + if (pkg := vol.fs_type.installation_pkg) is not None: + self._base_packages.append(pkg) + if (module := vol.fs_type.installation_module) is not None: self.modules.append(module) - if (binary := part.fs_type.installation_binary) is not None: + if (binary := vol.fs_type.installation_binary) is not None: self._binaries.append(binary) - # https://github.com/archlinux/archinstall/issues/1837 - if part.fs_type.fs_type_mount == 'btrfs': - _disable_fstrim = True + if vol.fs_type.fs_type_mount == 'btrfs': + self._disable_fstrim = True # There is not yet an fsck tool for NTFS. If it's being used for the root filesystem, the hook should be removed. - if part.fs_type.fs_type_mount == 'ntfs3' and part.mountpoint == self.target: + if vol.fs_type.fs_type_mount == 'ntfs3' and vol.mountpoint == self.target: if 'fsck' in self._hooks: self._hooks.remove('fsck') - if part in self._disk_encryption.partitions: - if self._disk_encryption.hsm_device: - # Required by mkinitcpio to add support for fido2-device options - self.pacman.strap('libfido2') + # if part in self._disk_encryption.partitions: + # if self._disk_encryption.hsm_device: + # # Required by mkinitcpio to add support for fido2-device options + # self.pacman.strap('libfido2') + # + # if 'sd-encrypt' not in self._hooks: + # self._hooks.insert(self._hooks.index('filesystems'), 'sd-encrypt') + # else: + # if 'encrypt' not in self._hooks: + # self._hooks.insert(self._hooks.index('filesystems'), 'encrypt') - if 'sd-encrypt' not in self._hooks: - self._hooks.insert(self._hooks.index('filesystems'), 'sd-encrypt') - else: - if 'encrypt' not in self._hooks: - self._hooks.insert(self._hooks.index('filesystems'), 'encrypt') + def minimal_installation( + self, + testing: bool = False, + multilib: bool = False, + mkinitcpio: bool = True, + hostname: str = 'archinstall', + locale_config: LocaleConfiguration = LocaleConfiguration.default() + ): if self._disk_config.lvm_config: + self._handle_lvm_installation() + self.add_additional_packages('lvm2') - self._hooks.insert(self._hooks.index('filesystems')-1, 'lvm2') + self._hooks.insert(self._hooks.index('filesystems') - 1, 'lvm2') + else: + self._handle_partition_installation() if not SysInfo.has_uefi(): - self.base_packages.append('grub') + self._base_packages.append('grub') if ucode := self._get_microcode(): (self.target / 'boot' / ucode).unlink(missing_ok=True) - self.base_packages.append(ucode.stem) + self._base_packages.append(ucode.stem) else: debug('Archinstall will not install any ucode.') @@ -678,7 +738,7 @@ def minimal_installation( pacman_conf.apply() - self.pacman.strap(self.base_packages) + self.pacman.strap(self._base_packages) self.helper_flags['base-strapped'] = True pacman_conf.persist() @@ -690,7 +750,7 @@ def minimal_installation( # https://github.com/archlinux/archinstall/issues/880 # https://github.com/archlinux/archinstall/issues/1837 # https://github.com/archlinux/archinstall/issues/1841 - if not _disable_fstrim: + if not self._disable_fstrim: self.enable_periodic_trim() # TODO: Support locale and timezone @@ -746,47 +806,56 @@ def _get_boot_partition(self) -> Optional[disk.PartitionModification]: return boot return None - def _get_root_partition(self) -> Optional[disk.PartitionModification]: - for mod in self._disk_config.device_modifications: - if root := mod.get_root_partition(): - return root + def _get_root(self) -> Optional[disk.PartitionModification | disk.LvmVolume]: + if self._disk_config.lvm_config: + return self._disk_config.lvm_config.get_root_volume() + else: + for mod in self._disk_config.device_modifications: + if root := mod.get_root_partition(): + return root return None def _get_kernel_params( self, - root_partition: disk.PartitionModification, + root: disk.PartitionModification | disk.LvmVolume, id_root: bool = True, partuuid: bool = True ) -> List[str]: kernel_parameters = [] - if root_partition in self._disk_encryption.partitions: + if root in self._disk_encryption.partitions: # TODO: We need to detect if the encrypted device is a whole disk encryption, # or simply a partition encryption. Right now we assume it's a partition (and we always have) if self._disk_encryption and self._disk_encryption.hsm_device: - debug(f'Root partition is an encrypted device, identifying by UUID: {root_partition.uuid}') + debug(f'Root partition is an encrypted device, identifying by UUID: {root.uuid}') # Note: UUID must be used, not PARTUUID for sd-encrypt to work - kernel_parameters.append(f'rd.luks.name={root_partition.uuid}=root') + kernel_parameters.append(f'rd.luks.name={root.uuid}=root') # Note: tpm2-device and fido2-device don't play along very well: # https://github.com/archlinux/archinstall/pull/1196#issuecomment-1129715645 kernel_parameters.append('rd.luks.options=fido2-device=auto,password-echo=no') elif partuuid: - debug(f'Root partition is an encrypted device, identifying by PARTUUID: {root_partition.partuuid}') - kernel_parameters.append(f'cryptdevice=PARTUUID={root_partition.partuuid}:root') + debug(f'Root partition is an encrypted device, identifying by PARTUUID: {root.partuuid}') + kernel_parameters.append(f'cryptdevice=PARTUUID={root.partuuid}:root') else: - debug(f'Root partition is an encrypted device, identifying by UUID: {root_partition.uuid}') - kernel_parameters.append(f'cryptdevice=UUID={root_partition.uuid}:root') + debug(f'Root partition is an encrypted device, identifying by UUID: {root.uuid}') + kernel_parameters.append(f'cryptdevice=UUID={root.uuid}:root') if id_root: kernel_parameters.append('root=/dev/mapper/root') elif id_root: - if partuuid: - debug(f'Identifying root partition by PARTUUID: {root_partition.partuuid}') - kernel_parameters.append(f'root=PARTUUID={root_partition.partuuid}') + if isinstance(root, disk.PartitionModification): + if partuuid: + debug(f'Identifying root partition by PARTUUID: {root.partuuid}') + kernel_parameters.append(f'root=PARTUUID={root.partuuid}') + else: + debug(f'Identifying root partition by UUID: {root.uuid}') + kernel_parameters.append(f'root=UUID={root.uuid}') + elif isinstance(root, disk.LvmVolume): + debug(f'Identifying root lvm by mapper device: {root.dev_path}') + kernel_parameters.append(f'root={root.safe_dev_path}') else: - debug(f'Identifying root partition by UUID: {root_partition.uuid}') - kernel_parameters.append(f'root=UUID={root_partition.uuid}') + raise ValueError('root is of unknown type') # Zswap should be disabled when using zram. # https://github.com/archlinux/archinstall/issues/881 @@ -794,14 +863,14 @@ def _get_kernel_params( kernel_parameters.append('zswap.enabled=0') if id_root: - for sub_vol in root_partition.btrfs_subvols: + for sub_vol in root.btrfs_subvols: if sub_vol.is_root(): kernel_parameters.append(f'rootflags=subvol={sub_vol.name}') break kernel_parameters.append('rw') - kernel_parameters.append(f'rootfstype={root_partition.safe_fs_type.fs_type_mount}') + kernel_parameters.append(f'rootfstype={root.safe_fs_type.fs_type_mount}') kernel_parameters.extend(self._kernel_params) debug(f'kernel parameters: {" ".join(kernel_parameters)}') @@ -811,7 +880,7 @@ def _get_kernel_params( def _add_systemd_bootloader( self, boot_partition: disk.PartitionModification, - root_partition: disk.PartitionModification, + root: disk.PartitionModification | disk.LvmVolume, efi_partition: Optional[disk.PartitionModification], uki_enabled: bool = False ): @@ -832,7 +901,11 @@ def _add_systemd_bootloader( # Install the boot loader try: SysCommand(f"/usr/bin/arch-chroot {self.target} bootctl {' '.join(bootctl_options)} install") - except SysCallError: + except SysCallError as e: + debug(e.message) + debug(e.exit_code) + deubut(e.worker.decode()) + # Fallback, try creating the boot loader without touching the EFI variables SysCommand(f"/usr/bin/arch-chroot {self.target} bootctl --no-variables {' '.join(bootctl_options)} install") @@ -893,7 +966,7 @@ def _add_systemd_bootloader( else: debug('Archinstall will not add any ucode to systemd-boot config.') - options = 'options ' + ' '.join(self._get_kernel_params(root_partition)) + options = 'options ' + ' '.join(self._get_kernel_params(root)) for kernel in self.kernels: for variant in ("", "-fallback"): @@ -916,7 +989,7 @@ def _add_systemd_bootloader( def _add_grub_bootloader( self, boot_partition: disk.PartitionModification, - root_partition: disk.PartitionModification, + root: disk.PartitionModification | disk.LvmVolume, efi_partition: Optional[disk.PartitionModification], uki_enabled: bool = False ): @@ -926,15 +999,15 @@ def _add_grub_bootloader( grub_default = self.target / 'etc/default/grub' config = grub_default.read_text() - kernel_parameters = ' '.join(self._get_kernel_params(root_partition, False, False)) + kernel_parameters = ' '.join(self._get_kernel_params(root, False, False)) config = re.sub(r'(GRUB_CMDLINE_LINUX=")("\n)', rf'\1{kernel_parameters}\2', config, 1) grub_default.write_text(config) info(f"GRUB boot partition: {boot_partition.dev_path}") - if boot_partition == root_partition and root_partition.mountpoint: - boot_dir = root_partition.mountpoint / 'boot' + if boot_partition == root and root.mountpoint: + boot_dir = root.mountpoint / 'boot' elif boot_partition.mountpoint: boot_dir = boot_partition.mountpoint else: @@ -1005,12 +1078,12 @@ def _add_grub_bootloader( def _add_limine_bootloader( self, boot_partition: disk.PartitionModification, - root_partition: disk.PartitionModification + root: disk.PartitionModification | disk.LvmVolume ): self.pacman.strap('limine') info(f"Limine boot partition: {boot_partition.dev_path}") - root_uuid = root_partition.uuid + root_uuid = root.uuid def create_pacman_hook(contents: str): HOOK_DIR = "/etc/pacman.d/hooks" @@ -1091,13 +1164,13 @@ def create_pacman_hook(contents: str): :Arch Linux PROTOCOL=linux KERNEL_PATH=boot:///vmlinuz-linux - CMDLINE=root=UUID={root_uuid} rw rootfstype={root_partition.safe_fs_type.value} loglevel=3 + CMDLINE=root=UUID={root_uuid} rw rootfstype={root.safe_fs_type.value} loglevel=3 MODULE_PATH=boot:///initramfs-linux.img :Arch Linux (fallback) PROTOCOL=linux KERNEL_PATH=boot:///vmlinuz-linux - CMDLINE=root=UUID={root_uuid} rw rootfstype={root_partition.safe_fs_type.value} loglevel=3 + CMDLINE=root=UUID={root_uuid} rw rootfstype={root.safe_fs_type.value} loglevel=3 MODULE_PATH=boot:///initramfs-linux-fallback.img """ @@ -1110,7 +1183,7 @@ def create_pacman_hook(contents: str): def _add_efistub_bootloader( self, boot_partition: disk.PartitionModification, - root_partition: disk.PartitionModification, + root: disk.PartitionModification | disk.LvmVolume, uki_enabled: bool = False ): self.pacman.strap('efibootmgr') @@ -1135,7 +1208,7 @@ def _add_efistub_bootloader( entries = ( *microcode, 'initrd=/initramfs-{kernel}.img', - *self._get_kernel_params(root_partition) + *self._get_kernel_params(root) ) cmdline = [' '.join(entries)] @@ -1165,7 +1238,7 @@ def _add_efistub_bootloader( def _config_uki( self, - root_partition: disk.PartitionModification, + root: disk.PartitionModification | disk.LvmVolume, efi_partition: Optional[disk.PartitionModification] ): if not efi_partition or not efi_partition.mountpoint: @@ -1173,7 +1246,7 @@ def _config_uki( # Set up kernel command line with open(self.target / 'etc/kernel/cmdline', 'w') as cmdline: - kernel_parameters = self._get_kernel_params(root_partition) + kernel_parameters = self._get_kernel_params(root) cmdline.write(' '.join(kernel_parameters) + '\n') ucode = self._get_microcode() @@ -1239,28 +1312,28 @@ def add_bootloader(self, bootloader: Bootloader, uki_enabled: bool = False): efi_partition = self._get_efi_partition() boot_partition = self._get_boot_partition() - root_partition = self._get_root_partition() + root = self._get_root() if boot_partition is None: raise ValueError(f'Could not detect boot at mountpoint {self.target}') - if root_partition is None: + if root is None: raise ValueError(f'Could not detect root at mountpoint {self.target}') info(f'Adding bootloader {bootloader.value} to {boot_partition.dev_path}') if uki_enabled: - self._config_uki(root_partition, efi_partition) + self._config_uki(root, efi_partition) match bootloader: case Bootloader.Systemd: - self._add_systemd_bootloader(boot_partition, root_partition, efi_partition, uki_enabled) + self._add_systemd_bootloader(boot_partition, root, efi_partition, uki_enabled) case Bootloader.Grub: - self._add_grub_bootloader(boot_partition, root_partition, efi_partition, uki_enabled) + self._add_grub_bootloader(boot_partition, root, efi_partition, uki_enabled) case Bootloader.Efistub: - self._add_efistub_bootloader(boot_partition, root_partition, uki_enabled) + self._add_efistub_bootloader(boot_partition, root, uki_enabled) case Bootloader.Limine: - self._add_limine_bootloader(boot_partition, root_partition) + self._add_limine_bootloader(boot_partition, root) def add_additional_packages(self, packages: Union[str, List[str]]) -> bool: return self.pacman.strap(packages) diff --git a/archinstall/lib/interactions/disk_conf.py b/archinstall/lib/interactions/disk_conf.py index 6df2268479..4f0737af22 100644 --- a/archinstall/lib/interactions/disk_conf.py +++ b/archinstall/lib/interactions/disk_conf.py @@ -475,6 +475,7 @@ def suggest_lvm_layout(disk_config: disk.DiskLayoutConfiguration) -> disk.LvmCon for mod in disk_config.device_modifications: for part in mod.partitions: + # or is EFI??? if part.is_boot(): boot_part = part else: