Renamed vfat -> fat32 for the purpose of consistency. Most actions are referring to fat32, it's only mkfs that has the notion vfat and then -F32 for format 32. And I think vfat confuses more people than it does good, so sticking with fat32 which works better with parted as well. Also added the partitioning logic, started on the mounting logic

This commit is contained in:
Anton Hvornum 2021-06-10 20:38:35 +02:00
parent 4691bad46b
commit 4e9b1c1635
3 changed files with 63 additions and 36 deletions

View File

@ -13,10 +13,19 @@ GPT = 0b00000001
MBR = 0b00000010
# import ctypes
# import ctypes.util
# libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
# libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p)
def valid_fs_type(fstype :str) -> bool:
# https://www.gnu.org/software/parted/manual/html_node/mkpart.html
return fstype in [
"ext2",
"fat16", "fat32",
"hfs", "hfs+", "hfsx",
"linux-swap",
"NTFS",
"reiserfs",
"ufs",
"btrfs",
]
class BlockDevice:
@ -177,6 +186,11 @@ class BlockDevice:
def flush_cache(self):
self.part_cache = {}
def get_partition(self, uuid):
for partition in self:
if partition.uuid == uuid:
return partition
class Partition:
def __init__(self, path: str, block_device: BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True):
@ -425,34 +439,34 @@ class Partition:
if filesystem == 'btrfs':
if b'UUID' not in (mkfs := SysCommand(f'/usr/bin/mkfs.btrfs -f {path}')):
raise DiskError(f'Could not format {path} with {filesystem} because: {mkfs}')
self.filesystem = 'btrfs'
self.filesystem = filesystem
elif filesystem == 'vfat':
elif filesystem == 'fat32':
mkfs = SysCommand(f'/usr/bin/mkfs.vfat -F32 {path}')
if (b'mkfs.fat' not in mkfs and b'mkfs.vfat' not in mkfs) or b'command not found' in mkfs:
raise DiskError(f"Could not format {path} with {filesystem} because: {mkfs}")
self.filesystem = 'vfat'
self.filesystem = filesystem
elif filesystem == 'ext4':
if (handle := SysCommand(f'/usr/bin/mkfs.ext4 -F {path}')).exit_code != 0:
raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}")
self.filesystem = 'ext4'
self.filesystem = filesystem
elif filesystem == 'xfs':
if (handle := SysCommand(f'/usr/bin/mkfs.xfs -f {path}')).exit_code != 0:
raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}")
self.filesystem = 'xfs'
self.filesystem = filesystem
elif filesystem == 'f2fs':
if (handle := SysCommand(f'/usr/bin/mkfs.f2fs -f {path}')).exit_code != 0:
raise DiskError(f"Could not format {path} with {filesystem} because: {handle.decode('UTF-8')}")
self.filesystem = 'f2fs'
self.filesystem = filesystem
elif filesystem == 'crypto_LUKS':
# from .luks import luks2
# encrypted_partition = luks2(self, None, None)
# encrypted_partition.format(path)
self.filesystem = 'crypto_LUKS'
self.filesystem = filesystem
else:
raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.")
@ -583,12 +597,32 @@ class Filesystem:
# We then iterate the partitions in order
for partition in layout.get('partitions', []):
# We don't want to re-add an existing partition (those containing a UUID already)
if 'UUID' not in partition:
self.add_partition(partition.get('type', 'primary'),
start=partition.get('start', '1MiB'), # TODO: Revisit sane block starts (4MB for memorycards for instance)
end=partition.get('size', '100%'),
partition_format=partition.get('filesystem', {}).get('format', 'btrfs'))
if partition.get('format', False) and not partition.get('uuid', None):
partition['device_instance'] = self.add_partition(partition.get('type', 'primary'),
start=partition.get('start', '1MiB'), # TODO: Revisit sane block starts (4MB for memorycards for instance)
end=partition.get('size', '100%'),
partition_format=partition.get('filesystem', {}).get('format', 'btrfs'))
elif partition_uuid := partition.get('uuid'):
if partition_instance := self.blockdevice.get_partition(uuid=partition_uuid):
partition['device_instance'] = partition_instance
else:
raise ValueError("BlockDevice().load_layout() doesn't know how to continue without either a UUID or creation of partition.")
if partition.get('filesystem', {}).get('format', None):
if partition.get('encrypt', False):
assert partition.get('password')
partition['device_instance'].encrypt(password=partition['password'])
with archinstall.luks2(partition['device_instance'], 'luksloop', partition['password']) as unlocked_device:
unlocked_device.format(partition['filesystem']['format'], allow_formatting=partition.get('format', False))
else:
partition['device_instance'].format(partition['filesystem']['format'], allow_formatting=partition.get('format', False))
def mount_ordered_layout(self, layout :dict):
mountpoints = {}
for partition in layout['partitions']:
print(partition)
exit(0)
def find_partition(self, mountpoint):
@ -610,17 +644,19 @@ class Filesystem:
"""
return self.raw_parted(string).exit_code
def use_entire_disk(self, root_filesystem_type='ext4'):
def use_entire_disk(self, root_filesystem_type='ext4') -> Partition:
# TODO: Implement this with declarative profiles instead.
raise ValueError("Installation().use_entire_disk() has to be re-worked.")
def add_partition(self, partition_type, start, end, partition_format=None):
log(f'Adding partition to {self.blockdevice}, {start}->{end}', level=logging.INFO)
previous_partitions = self.blockdevice.partitions
previous_partition_uuids = {partition.uuid for partition in self.blockdevice.partitions.values()}
if self.mode == MBR:
if len(self.blockdevice.partitions) > 3:
DiskError("Too many partitions on disk, MBR disks can only have 3 parimary partitions")
if partition_format:
partitioning = self.parted(f'{self.blockdevice.device} mkpart {partition_type} {partition_format} {start} {end}') == 0
else:
@ -628,12 +664,13 @@ class Filesystem:
if partitioning:
start_wait = time.time()
while previous_partitions == self.blockdevice.partitions:
time.sleep(0.025) # Let the new partition come up in the kernel
while previous_partition_uuids == {partition.uuid for partition in self.blockdevice.partitions.values()}:
if time.time() - start_wait > 10:
raise DiskError(f"New partition never showed up after adding new partition on {self} (timeout 10 seconds).")
time.sleep(0.025)
return True
time.sleep(0.5) # Let the kernel catch up with quick block devices (nvme for instance)
return self.blockdevice.get_partition(uuid=(previous_partition_uuids ^ {partition.uuid for partition in self.blockdevice.partitions.values()}).pop())
def set_name(self, partition: int, name: str):
return self.parted(f'{self.blockdevice.device} name {partition + 1} "{name}"') == 0

View File

@ -9,7 +9,7 @@ import signal
import sys
import time
from .disk import BlockDevice
from .disk import BlockDevice, valid_fs_type
from .exceptions import *
from .general import SysCommand
from .hardware import AVAILABLE_GFX_DRIVERS, has_uefi
@ -580,20 +580,6 @@ def select_partition_layout(block_device):
}
}
def valid_fs_type(fstype :str) -> bool:
# https://www.gnu.org/software/parted/manual/html_node/mkpart.html
return fstype in [
"ext2",
"fat16", "fat32",
"hfs", "hfs+", "hfsx",
"linux-swap",
"NTFS",
"reiserfs",
"ufs",
"btrfs",
]
def valid_parted_position(pos :str):
if not len(pos):
return False
@ -630,6 +616,7 @@ def get_default_partition_layout(block_devices):
"start" : "1MiB",
"size" : "513MiB",
"boot" : True,
"format" : True,
"mountpoint" : "/boot",
"filesystem" : {
"format" : "fat32"
@ -640,6 +627,7 @@ def get_default_partition_layout(block_devices):
"type" : "primary",
"start" : "513MiB",
"encrypted" : True,
"format" : True,
"size" : "100%" if block_devices[0].size < MIN_SIZE_TO_ALLOW_HOME_PART else f"{min(block_devices[0].size, 20)*1024}MiB",
"mountpoint" : "/",
"filesystem" : {
@ -652,6 +640,7 @@ def get_default_partition_layout(block_devices):
# Home
"type" : "primary",
"encrypted" : True,
"format" : True,
"start" : f"{min(block_devices[0].size*0.2, 20)*1024}MiB",
"size" : "100%",
"mountpoint" : "/home",

View File

@ -223,6 +223,7 @@ def perform_filesystem_operations():
for drive in archinstall.arguments['harddrives']:
with archinstall.Filesystem(drive, mode) as fs:
fs.load_layout(archinstall.storage['disk_layouts'][drive])
fs.mount_ordered_layout(archinstall.storage['disk_layouts'][drive])
perform_installation(archinstall.storage.get('MOUNT_POINT', '/mnt'))