Reworked the guided partitioning logic to better match new expectations of flexability. Still some work to be done and features to be implemented, but the structure is taking place

This commit is contained in:
Anton Hvornum 2021-03-08 16:52:06 +01:00
parent 0b3879ac58
commit 6306de4bfe
4 changed files with 51 additions and 13 deletions

View File

@ -196,28 +196,34 @@ class Partition():
if b'UUID' not in o: if b'UUID' not in o:
raise DiskError(f'Could not format {path} with {filesystem} because: {o}') raise DiskError(f'Could not format {path} with {filesystem} because: {o}')
self.filesystem = 'btrfs' self.filesystem = 'btrfs'
elif filesystem == 'vfat': elif filesystem == 'vfat':
o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {path}')) o = b''.join(sys_command(f'/usr/bin/mkfs.vfat -F32 {path}'))
if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o: if (b'mkfs.fat' not in o and b'mkfs.vfat' not in o) or b'command not found' in o:
raise DiskError(f'Could not format {path} with {filesystem} because: {o}') raise DiskError(f'Could not format {path} with {filesystem} because: {o}')
self.filesystem = 'vfat' self.filesystem = 'vfat'
elif filesystem == 'ext4': elif filesystem == 'ext4':
if (handle := sys_command(f'/usr/bin/mkfs.ext4 -F {path}')).exit_code != 0: if (handle := sys_command(f'/usr/bin/mkfs.ext4 -F {path}')).exit_code != 0:
raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}')
self.filesystem = 'ext4' self.filesystem = 'ext4'
elif filesystem == 'xfs': elif filesystem == 'xfs':
if (handle := sys_command(f'/usr/bin/mkfs.xfs -f {path}')).exit_code != 0: if (handle := sys_command(f'/usr/bin/mkfs.xfs -f {path}')).exit_code != 0:
raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}')
self.filesystem = 'xfs' self.filesystem = 'xfs'
elif filesystem == 'f2fs': elif filesystem == 'f2fs':
if (handle := sys_command(f'/usr/bin/mkfs.f2fs -f {path}')).exit_code != 0: if (handle := sys_command(f'/usr/bin/mkfs.f2fs -f {path}')).exit_code != 0:
raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}') raise DiskError(f'Could not format {path} with {filesystem} because: {b"".join(handle)}')
self.filesystem = 'f2fs' self.filesystem = 'f2fs'
elif filesystem == 'crypto_LUKS': elif filesystem == 'crypto_LUKS':
from .luks import luks2 from .luks import luks2
encrypted_partition = luks2(self, None, None) encrypted_partition = luks2(self, None, None)
encrypted_partition.format(path) encrypted_partition.format(path)
self.filesystem = 'crypto_LUKS' self.filesystem = 'crypto_LUKS'
else: else:
raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.")
return True return True
@ -327,7 +333,7 @@ class Filesystem():
if prep_mode == 'luks2': if prep_mode == 'luks2':
self.add_partition('primary', start='513MiB', end='100%') self.add_partition('primary', start='513MiB', end='100%')
else: else:
self.add_partition('primary', start='513MiB', end='100%', format='ext4') self.add_partition('primary', start='513MiB', end='100%', format=prep_mode)
def add_partition(self, type, start, end, format=None): def add_partition(self, type, start, end, format=None):
log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info) log(f'Adding partition to {self.blockdevice}', level=LOG_LEVELS.Info)

View File

@ -6,17 +6,28 @@ from .output import log, LOG_LEVELS
from .storage import storage from .storage import storage
class luks2(): class luks2():
def __init__(self, partition, mountpoint, password, *args, **kwargs): def __init__(self, partition, mountpoint, password, key_file=None, *args, **kwargs):
self.password = password self.password = password
self.partition = partition self.partition = partition
self.mountpoint = mountpoint self.mountpoint = mountpoint
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self.key_file = key_file
self.filesystem = 'crypto_LUKS' self.filesystem = 'crypto_LUKS'
def __enter__(self): def __enter__(self):
key_file = self.encrypt(self.partition, self.password, *self.args, **self.kwargs) if self.partition.allow_formatting:
return self.unlock(self.partition, self.mountpoint, key_file) self.key_file = self.encrypt(self.partition, *self.args, **self.kwargs)
else:
if not self.key_file:
self.key_file = f"/tmp/{os.path.basename(self.partition.path)}.disk_pw" # TODO: Make disk-pw-file randomly unique?
if type(self.password) != bytes: self.password = bytes(self.password, 'UTF-8')
with open(self.key_file, 'wb') as fh:
fh.write(self.password)
return self.unlock(self.partition, self.mountpoint, self.key_file)
def __exit__(self, *args, **kwargs): def __exit__(self, *args, **kwargs):
# TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager # TODO: https://stackoverflow.com/questions/28157929/how-to-safely-handle-an-exception-inside-a-context-manager
@ -24,13 +35,20 @@ class luks2():
raise args[1] raise args[1]
return True return True
def encrypt(self, partition, password, key_size=512, hash_type='sha512', iter_time=10000, key_file=None): def encrypt(self, partition, password=None, key_size=512, hash_type='sha512', iter_time=10000, key_file=None):
# TODO: We should be able to integrate this into the main log some how. # TODO: We should be able to integrate this into the main log some how.
# Perhaps post-mortem? # Perhaps post-mortem?
log(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info) log(f'Encrypting {partition} (This might take a while)', level=LOG_LEVELS.Info)
if not key_file: if not key_file:
key_file = f"/tmp/{os.path.basename(self.partition.path)}.disk_pw" # TODO: Make disk-pw-file randomly unique? if self.key_file:
key_file = self.key_file
else:
key_file = f"/tmp/{os.path.basename(self.partition.path)}.disk_pw" # TODO: Make disk-pw-file randomly unique?
if not password:
password = self.password
if type(password) != bytes: password = bytes(password, 'UTF-8') if type(password) != bytes: password = bytes(password, 'UTF-8')
with open(key_file, 'wb') as fh: with open(key_file, 'wb') as fh:

View File

@ -97,6 +97,18 @@ def ask_for_disk_layout():
value = generic_select(options.values(), "Found partitions on the selected drive, (select by number) what you want to do: ") value = generic_select(options.values(), "Found partitions on the selected drive, (select by number) what you want to do: ")
return next((key for key, val in options.items() if val == value), None) return next((key for key, val in options.items() if val == value), None)
def ask_for_main_filesystem_format():
options = {
'btrfs' : 'btrfs',
'ext4' : 'ext4',
'xfs' : 'xfs',
'f2fs' : 'f2fs',
'vfat' : 'vfat'
}
value = generic_select(options.values(), "Select your main partitions filesystem by number or free-text: ")
return next((key for key, val in options.items() if val == value), None)
def generic_select(options, input_text="Select one of the above by index or absolute value: ", sort=True): def generic_select(options, input_text="Select one of the above by index or absolute value: ", sort=True):
""" """
A generic select function that does not output anything A generic select function that does not output anything

View File

@ -165,6 +165,7 @@ if archinstall.arguments['harddrive'].has_partitions():
archinstall.log('Using existing partition table reported above.') archinstall.log('Using existing partition table reported above.')
elif option == 'format-all': elif option == 'format-all':
archinstall.arguments['filesystem'] = archinstall.ask_for_main_filesystem_format()
archinstall.arguments['harddrive'].keep_partitions = False archinstall.arguments['harddrive'].keep_partitions = False
# Get disk encryption password (or skip if blank) # Get disk encryption password (or skip if blank)
@ -272,22 +273,23 @@ signal.signal(signal.SIGINT, original_sigint_handler)
""" """
with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs: with archinstall.Filesystem(archinstall.arguments['harddrive'], archinstall.GPT) as fs:
if archinstall.arguments['harddrive'].keep_partitions is False: if archinstall.arguments['harddrive'].keep_partitions is False:
if disk_password: if archinstall.arguments.get('!encryption-password', None):
# Set a temporary partition format to indicate that the partitions is encrypted.
# Later on, we'll mount it and put an actual filesystem inside this encrypted container.
fs.use_entire_disk('luks2') fs.use_entire_disk('luks2')
else: else:
fs.use_entire_disk('ext4') fs.use_entire_disk(archinstall.arguments.get('filesystem', 'ext4'))
else: else:
for partition in archinstall.arguments['harddrive']: for partition in archinstall.arguments['harddrive']:
if partition.allow_formatting: if partition.allow_formatting:
partition.format() partition.format()
exit(0) if archinstall.arguments.get('!encryption-password', None):
if disk_password:
# First encrypt and unlock, then format the desired partition inside the encrypted part. # 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 # 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. # unlocks the drive so that it can be used as a normal block-device within archinstall.
with archinstall.luks2(harddrive.partition[1], 'luksloop', disk_password) as unlocked_device: with archinstall.luks2(harddrive.partition[1], 'luksloop', archinstall.arguments.get('!encryption-password', None)) as unlocked_device:
unlocked_device.format('btrfs') unlocked_device.format(archinstall.arguments.get('filesystem', 'btrfs'))
perform_installation(unlocked_device, perform_installation(unlocked_device,
harddrive.partition[0], harddrive.partition[0],