Merge remote-tracking branch 'origin'
This commit is contained in:
commit
759ef95676
|
|
@ -29,3 +29,4 @@ venv
|
||||||
.idea/**
|
.idea/**
|
||||||
**/install.log
|
**/install.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
**/cmd_history.txt
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ class BlockDevice:
|
||||||
count = 0
|
count = 0
|
||||||
while count < 5:
|
while count < 5:
|
||||||
for partition_uuid, partition in self.partitions.items():
|
for partition_uuid, partition in self.partitions.items():
|
||||||
if partition.uuid == uuid:
|
if partition.uuid.lower() == uuid.lower():
|
||||||
return partition
|
return partition
|
||||||
else:
|
else:
|
||||||
log(f"uuid {uuid} not found. Waiting for {count +1} time",level=logging.DEBUG)
|
log(f"uuid {uuid} not found. Waiting for {count +1} time",level=logging.DEBUG)
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,14 @@ class Filesystem:
|
||||||
self.partprobe()
|
self.partprobe()
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
# TODO: Convert to blkid (or something similar, but blkid doesn't support traversing to list sub-PARTUUIDs based on blockdevice path?)
|
# We'll use unreliable lbslk to grab children under the /dev/<device>
|
||||||
output = json.loads(SysCommand(f"lsblk --json -o+PARTUUID {self.blockdevice.device}").decode('UTF-8'))
|
output = json.loads(SysCommand(f"lsblk --json {self.blockdevice.device}").decode('UTF-8'))
|
||||||
|
|
||||||
for device in output['blockdevices']:
|
for device in output['blockdevices']:
|
||||||
for index, partition in enumerate(device['children']):
|
for index, partition in enumerate(device['children']):
|
||||||
if (partuuid := partition.get('partuuid', None)) and partuuid.lower() == uuid:
|
# But we'll use blkid to reliably grab the PARTUUID for that child device (partition)
|
||||||
|
partition_uuid = SysCommand(f"blkid -s PARTUUID -o value /dev/{partition.get('name')}").decode().strip()
|
||||||
|
if partition_uuid.lower() == uuid.lower():
|
||||||
return index
|
return index
|
||||||
|
|
||||||
time.sleep(storage['DISK_TIMEOUTS'])
|
time.sleep(storage['DISK_TIMEOUTS'])
|
||||||
|
|
@ -87,12 +89,16 @@ class Filesystem:
|
||||||
print("Re-using partition_instance:", partition_instance)
|
print("Re-using partition_instance:", partition_instance)
|
||||||
partition['device_instance'] = partition_instance
|
partition['device_instance'] = partition_instance
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"{self}.load_layout() doesn't know how to continue without a new partition definition or a UUID ({partition.get('PARTUUID')}) on the device ({self.blockdevice.get_partition(uuid=partition_uuid)}).")
|
raise ValueError(f"{self}.load_layout() doesn't know how to continue without a new partition definition or a UUID ({partition.get('PARTUUID')}) on the device ({self.blockdevice.get_partition(uuid=partition.get('PARTUUID'))}).")
|
||||||
|
|
||||||
if partition.get('filesystem', {}).get('format', False):
|
if partition.get('filesystem', {}).get('format', False):
|
||||||
|
|
||||||
# needed for backward compatibility with the introduction of the new "format_options"
|
# needed for backward compatibility with the introduction of the new "format_options"
|
||||||
format_options = partition.get('options',[]) + partition.get('filesystem',{}).get('format_options',[])
|
format_options = partition.get('options',[]) + partition.get('filesystem',{}).get('format_options',[])
|
||||||
if partition.get('encrypted', False):
|
if partition.get('encrypted', False):
|
||||||
|
if not partition['device_instance']:
|
||||||
|
raise DiskError(f"Internal error caused us to loose the partition. Please report this issue upstream!")
|
||||||
|
|
||||||
if not partition.get('!password'):
|
if not partition.get('!password'):
|
||||||
if not storage['arguments'].get('!encryption-password'):
|
if not storage['arguments'].get('!encryption-password'):
|
||||||
if storage['arguments'] == 'silent':
|
if storage['arguments'] == 'silent':
|
||||||
|
|
@ -107,6 +113,7 @@ class Filesystem:
|
||||||
loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['mountpoint']).name}loop"
|
loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['mountpoint']).name}loop"
|
||||||
else:
|
else:
|
||||||
loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['device_instance'].path).name}"
|
loopdev = f"{storage.get('ENC_IDENTIFIER', 'ai')}{pathlib.Path(partition['device_instance'].path).name}"
|
||||||
|
|
||||||
partition['device_instance'].encrypt(password=partition['!password'])
|
partition['device_instance'].encrypt(password=partition['!password'])
|
||||||
# Immediately unlock the encrypted device to format the inner volume
|
# Immediately unlock the encrypted device to format the inner volume
|
||||||
with luks2(partition['device_instance'], loopdev, partition['!password'], auto_unmount=True) as unlocked_device:
|
with luks2(partition['device_instance'], loopdev, partition['!password'], auto_unmount=True) as unlocked_device:
|
||||||
|
|
@ -127,6 +134,9 @@ class Filesystem:
|
||||||
|
|
||||||
unlocked_device.format(partition['filesystem']['format'], options=format_options)
|
unlocked_device.format(partition['filesystem']['format'], options=format_options)
|
||||||
elif partition.get('format', False):
|
elif partition.get('format', False):
|
||||||
|
if not partition['device_instance']:
|
||||||
|
raise DiskError(f"Internal error caused us to loose the partition. Please report this issue upstream!")
|
||||||
|
|
||||||
partition['device_instance'].format(partition['filesystem']['format'], options=format_options)
|
partition['device_instance'].format(partition['filesystem']['format'], options=format_options)
|
||||||
|
|
||||||
if partition.get('boot', False):
|
if partition.get('boot', False):
|
||||||
|
|
@ -139,7 +149,13 @@ class Filesystem:
|
||||||
return partition
|
return partition
|
||||||
|
|
||||||
def partprobe(self) -> bool:
|
def partprobe(self) -> bool:
|
||||||
return SysCommand(f'bash -c "partprobe"').exit_code == 0
|
result = SysCommand(f'partprobe {self.blockdevice.device}')
|
||||||
|
|
||||||
|
if result.exit_code != 0:
|
||||||
|
log(f"Could not execute partprobe: {result!r}", level=logging.ERROR, fg="red")
|
||||||
|
raise DiskError(f"Could not run partprobe: {result!r}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def raw_parted(self, string: str) -> SysCommand:
|
def raw_parted(self, string: str) -> SysCommand:
|
||||||
if (cmd_handle := SysCommand(f'/usr/bin/parted -s {string}')).exit_code != 0:
|
if (cmd_handle := SysCommand(f'/usr/bin/parted -s {string}')).exit_code != 0:
|
||||||
|
|
@ -155,9 +171,7 @@ class Filesystem:
|
||||||
:type string: str
|
:type string: str
|
||||||
"""
|
"""
|
||||||
if (parted_handle := self.raw_parted(string)).exit_code == 0:
|
if (parted_handle := self.raw_parted(string)).exit_code == 0:
|
||||||
if self.partprobe():
|
return self.partprobe()
|
||||||
return True
|
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
raise DiskError(f"Parted failed to add a partition: {parted_handle}")
|
raise DiskError(f"Parted failed to add a partition: {parted_handle}")
|
||||||
|
|
||||||
|
|
@ -165,7 +179,7 @@ class Filesystem:
|
||||||
# TODO: Implement this with declarative profiles instead.
|
# TODO: Implement this with declarative profiles instead.
|
||||||
raise ValueError("Installation().use_entire_disk() has to be re-worked.")
|
raise ValueError("Installation().use_entire_disk() has to be re-worked.")
|
||||||
|
|
||||||
def add_partition(self, partition_type :str, start :str, end :str, partition_format :Optional[str] = None) -> None:
|
def add_partition(self, partition_type :str, start :str, end :str, partition_format :Optional[str] = None) -> Partition:
|
||||||
log(f'Adding partition to {self.blockdevice}, {start}->{end}', level=logging.INFO)
|
log(f'Adding partition to {self.blockdevice}, {start}->{end}', level=logging.INFO)
|
||||||
|
|
||||||
previous_partition_uuids = {partition.uuid for partition in self.blockdevice.partitions.values()}
|
previous_partition_uuids = {partition.uuid for partition in self.blockdevice.partitions.values()}
|
||||||
|
|
@ -179,31 +193,41 @@ class Filesystem:
|
||||||
else:
|
else:
|
||||||
parted_string = f'{self.blockdevice.device} mkpart {partition_type} {start} {end}'
|
parted_string = f'{self.blockdevice.device} mkpart {partition_type} {start} {end}'
|
||||||
|
|
||||||
|
log(f"Adding partition using the following parted command: {parted_string}", level=logging.DEBUG)
|
||||||
|
|
||||||
if self.parted(parted_string):
|
if self.parted(parted_string):
|
||||||
count = 0
|
count = 0
|
||||||
while count < 10:
|
while count < 10:
|
||||||
new_uuid = None
|
new_uuid = None
|
||||||
new_uuid_set = (previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()})
|
new_uuid_set = (previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()})
|
||||||
|
|
||||||
if len(new_uuid_set) > 0:
|
if len(new_uuid_set) > 0:
|
||||||
new_uuid = new_uuid_set.pop()
|
new_uuid = new_uuid_set.pop()
|
||||||
|
|
||||||
if new_uuid:
|
if new_uuid:
|
||||||
try:
|
try:
|
||||||
return self.blockdevice.get_partition(new_uuid)
|
return self.blockdevice.get_partition(new_uuid)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print('Blockdevice:', self.blockdevice)
|
log(f'Blockdevice: {self.blockdevice}', level=logging.ERROR, fg="red")
|
||||||
print('Partitions:', self.blockdevice.partitions)
|
log(f'Partitions: {self.blockdevice.partitions}', level=logging.ERROR, fg="red")
|
||||||
print('Partition set:', new_uuid_set)
|
log(f'Partition set: {new_uuid_set}', level=logging.ERROR, fg="red")
|
||||||
print('New UUID:', [new_uuid])
|
log(f'New UUID: {[new_uuid]}', level=logging.ERROR, fg="red")
|
||||||
print('get_partition():', self.blockdevice.get_partition)
|
log(f'get_partition(): {self.blockdevice.get_partition}', level=logging.ERROR, fg="red")
|
||||||
raise err
|
raise err
|
||||||
else:
|
else:
|
||||||
count += 1
|
count += 1
|
||||||
log(f"Could not get UUID for partition. Waiting for the {count} time",level=logging.DEBUG)
|
log(f"Could not get UUID for partition. Waiting before retry attempt {count} of 10 ...",level=logging.DEBUG)
|
||||||
time.sleep(float(storage['arguments'].get('disk-sleep', 0.2)))
|
time.sleep(float(storage['arguments'].get('disk-sleep', 0.2)))
|
||||||
else:
|
else:
|
||||||
log("Add partition is exiting due to excessive wait time",level=logging.INFO)
|
log("Add partition is exiting due to excessive wait time", level=logging.ERROR, fg="red")
|
||||||
raise DiskError(f"New partition never showed up after adding new partition on {self}.")
|
raise DiskError(f"New partition never showed up after adding new partition on {self}.")
|
||||||
|
|
||||||
|
# TODO: This should never be able to happen
|
||||||
|
log(f"Could not find the new PARTUUID after adding the partition.", level=logging.ERROR, fg="red")
|
||||||
|
log(f"Previous partitions: {previous_partition_uuids}", level=logging.ERROR, fg="red")
|
||||||
|
log(f"New partitions: {(previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()})}", level=logging.ERROR, fg="red")
|
||||||
|
raise DiskError(f"Could not add partition using: {parted_string}")
|
||||||
|
|
||||||
def set_name(self, partition: int, name: str) -> bool:
|
def set_name(self, partition: int, name: str) -> bool:
|
||||||
return self.parted(f'{self.blockdevice.device} name {partition + 1} "{name}"') == 0
|
return self.parted(f'{self.blockdevice.device} name {partition + 1} "{name}"') == 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,10 +190,26 @@ def get_partitions_in_use(mountpoint :str) -> List[Partition]:
|
||||||
|
|
||||||
output = json.loads(output)
|
output = json.loads(output)
|
||||||
for target in output.get('filesystems', []):
|
for target in output.get('filesystems', []):
|
||||||
mounts.append(Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target']))
|
# We need to create a BlockDevice() instead of 'None' here when creaiting Partition()
|
||||||
|
# Otherwise subsequent calls to .size etc will fail due to BlockDevice being None.
|
||||||
|
|
||||||
|
# So first, we create the partition without a BlockDevice and carefully only use it to get .real_device
|
||||||
|
# Note: doing print(partition) here will break because the above mentioned issue.
|
||||||
|
partition = Partition(target['source'], None, filesystem=target.get('fstype', None), mountpoint=target['target'])
|
||||||
|
partition = Partition(target['source'], partition.real_device, filesystem=target.get('fstype', None), mountpoint=target['target'])
|
||||||
|
|
||||||
|
# Once we have the real device (for instance /dev/nvme0n1p5) we can find the parent block device using
|
||||||
|
# (lsblk pkname lists both the partition and blockdevice, BD being the last entry)
|
||||||
|
result = SysCommand(f'lsblk -no pkname {partition.real_device}').decode().rstrip('\r\n').split('\r\n')[-1]
|
||||||
|
block_device = BlockDevice(f"/dev/{result}")
|
||||||
|
|
||||||
|
# Once we figured the block device out, we can properly create the partition object
|
||||||
|
partition = Partition(target['source'], block_device, filesystem=target.get('fstype', None), mountpoint=target['target'])
|
||||||
|
|
||||||
|
mounts.append(partition)
|
||||||
|
|
||||||
for child in target.get('children', []):
|
for child in target.get('children', []):
|
||||||
mounts.append(Partition(child['source'], None, filesystem=child.get('fstype', None), mountpoint=child['target']))
|
mounts.append(Partition(child['source'], block_device, filesystem=child.get('fstype', None), mountpoint=child['target']))
|
||||||
|
|
||||||
return mounts
|
return mounts
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,12 @@ class Partition:
|
||||||
except DiskError:
|
except DiskError:
|
||||||
mount_information = {}
|
mount_information = {}
|
||||||
|
|
||||||
if self.mountpoint != mount_information.get('target', None) and mountpoint:
|
if mount_information.get('target', None):
|
||||||
raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
|
if self.mountpoint != mount_information.get('target', None) and mountpoint:
|
||||||
|
raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
|
||||||
|
|
||||||
if target := mount_information.get('target', None):
|
if target := mount_information.get('target', None):
|
||||||
self.mountpoint = target
|
self.mountpoint = target
|
||||||
|
|
||||||
if not self.filesystem and autodetect_filesystem:
|
if not self.filesystem and autodetect_filesystem:
|
||||||
if fstype := mount_information.get('fstype', get_filesystem_type(path)):
|
if fstype := mount_information.get('fstype', get_filesystem_type(path)):
|
||||||
|
|
@ -130,6 +131,9 @@ class Partition:
|
||||||
|
|
||||||
for device in lsblk['blockdevices']:
|
for device in lsblk['blockdevices']:
|
||||||
return convert_size_to_gb(device['size'])
|
return convert_size_to_gb(device['size'])
|
||||||
|
elif handle.exit_code == 8192:
|
||||||
|
# Device is not a block device
|
||||||
|
return None
|
||||||
|
|
||||||
time.sleep(storage['DISK_TIMEOUTS'])
|
time.sleep(storage['DISK_TIMEOUTS'])
|
||||||
|
|
||||||
|
|
@ -225,7 +229,7 @@ class Partition:
|
||||||
return bind_name
|
return bind_name
|
||||||
|
|
||||||
def partprobe(self) -> bool:
|
def partprobe(self) -> bool:
|
||||||
if SysCommand(f'bash -c "partprobe"').exit_code == 0:
|
if self.block_device and SysCommand(f'partprobe {self.block_device.device}').exit_code == 0:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
|
|
@ -767,7 +767,7 @@ class Installer:
|
||||||
log(f"GRUB uses {boot_partition.path} as the boot partition.", level=logging.INFO)
|
log(f"GRUB uses {boot_partition.path} as the boot partition.", level=logging.INFO)
|
||||||
if has_uefi():
|
if has_uefi():
|
||||||
self.pacstrap('efibootmgr') # TODO: Do we need? Yes, but remove from minimal_installation() instead?
|
self.pacstrap('efibootmgr') # TODO: Do we need? Yes, but remove from minimal_installation() instead?
|
||||||
if not (handle := SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB')).exit_code == 0:
|
if not (handle := SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB --removable')).exit_code == 0:
|
||||||
raise DiskError(f"Could not install GRUB to {self.target}/boot: {handle}")
|
raise DiskError(f"Could not install GRUB to {self.target}/boot: {handle}")
|
||||||
else:
|
else:
|
||||||
if not (handle := SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc --recheck {boot_partition.parent}')).exit_code == 0:
|
if not (handle := SysCommand(f'/usr/bin/arch-chroot {self.target} grub-install --target=i386-pc --recheck {boot_partition.parent}')).exit_code == 0:
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ class GlobalMenu:
|
||||||
if key not in archinstall.arguments:
|
if key not in archinstall.arguments:
|
||||||
archinstall.arguments[key] = sel._current_selection
|
archinstall.arguments[key] = sel._current_selection
|
||||||
self._post_processing()
|
self._post_processing()
|
||||||
exit()
|
|
||||||
def _process_selection(self, selection):
|
def _process_selection(self, selection):
|
||||||
# find the selected option in our option list
|
# find the selected option in our option list
|
||||||
option = [[k, v] for k, v in self._menu_options.items() if v.text.strip() == selection]
|
option = [[k, v] for k, v in self._menu_options.items() if v.text.strip() == selection]
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ def perform_installation(mountpoint):
|
||||||
archinstall.log(f"Disk states after installing: {archinstall.disk_layouts()}", level=logging.DEBUG)
|
archinstall.log(f"Disk states after installing: {archinstall.disk_layouts()}", level=logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
if not archinstall.check_mirror_reachable():
|
if not (archinstall.check_mirror_reachable() or archinstall.arguments.get('skip-mirror-check', False)):
|
||||||
log_file = os.path.join(archinstall.storage.get('LOG_PATH', None), archinstall.storage.get('LOG_FILE', None))
|
log_file = os.path.join(archinstall.storage.get('LOG_PATH', None), archinstall.storage.get('LOG_FILE', None))
|
||||||
archinstall.log(f"Arch Linux mirrors are not reachable. Please check your internet connection and the log file '{log_file}'.", level=logging.INFO, fg="red")
|
archinstall.log(f"Arch Linux mirrors are not reachable. Please check your internet connection and the log file '{log_file}'.", level=logging.INFO, fg="red")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
|
|
||||||
# Define the package list in order for lib to source
|
# Define the package list in order for lib to source
|
||||||
# which packages will be installed by this profile
|
# which packages will be installed by this profile
|
||||||
__packages__ = ["pipewire", "pipewire-alsa", "pipewire-jack", "pipewire-media-session", "pipewire-pulse", "gst-plugin-pipewire", "libpulse"]
|
__packages__ = ["pipewire", "pipewire-alsa", "pipewire-jack", "pipewire-pulse", "gst-plugin-pipewire", "libpulse", "wireplumber"]
|
||||||
|
|
||||||
archinstall.log('Installing pipewire', level=logging.INFO)
|
archinstall.log('Installing pipewire', level=logging.INFO)
|
||||||
archinstall.storage['installation_session'].add_additional_packages(__packages__)
|
archinstall.storage['installation_session'].add_additional_packages(__packages__)
|
||||||
|
|
@ -11,4 +11,4 @@ archinstall.storage['installation_session'].add_additional_packages(__packages__
|
||||||
@archinstall.plugin
|
@archinstall.plugin
|
||||||
def on_user_created(installation :archinstall.Installer, user :str):
|
def on_user_created(installation :archinstall.Installer, user :str):
|
||||||
archinstall.log(f"Enabling pipewire-pulse for {user}", level=logging.INFO)
|
archinstall.log(f"Enabling pipewire-pulse for {user}", level=logging.INFO)
|
||||||
installation.chroot('systemctl enable --user pipewire-pulse.service', run_as=user)
|
installation.chroot('systemctl enable --user pipewire-pulse.service', run_as=user)
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@
|
||||||
"required": [
|
"required": [
|
||||||
"bootloader",
|
"bootloader",
|
||||||
"kernels",
|
"kernels",
|
||||||
"mirror-region",
|
"mirror-region"
|
||||||
],
|
],
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue