Added Partition() properties: sector_size, start, end, boot, partition_type and a __dump__() function. As well as kept working on the partition logic of guided to have a more traditional workflow of adding/deleting partitions in a guided manner, as well as the ability to mark partitions as encrypted/boot and set target mountpoints.

This commit is contained in:
Anton Hvornum 2021-05-10 14:32:39 +02:00
parent 3e601ff9ab
commit 6d5d9a1798
3 changed files with 124 additions and 14 deletions

View File

@ -27,6 +27,7 @@ class BlockDevice():
self.info = info
self.keep_partitions = True
self.part_cache = OrderedDict()
# TODO: Currently disk encryption is a BIT misleading.
# It's actually partition-encryption, but for future-proofing this
# I'm placing the encryption password on a BlockDevice level.
@ -43,6 +44,9 @@ class BlockDevice():
raise KeyError(f'{self} does not contain information: "{key}"')
return self.info[key]
def __len__(self):
return len(self.partitions)
def json(self):
"""
json() has precedence over __dump__, so this is a way
@ -56,11 +60,21 @@ class BlockDevice():
def __dump__(self):
return {
'path': self.path,
'info': self.info,
'partition_cache': self.part_cache
self.path : {
'partuuid' : self.uuid,
'wipe' : self.info.get('wipe', None),
'partitions' : [part.__dump__() for part in self.partitions.values()]
}
}
@property
def partition_type(self):
output = b"".join(sys_command(f"lsblk --json -o+PTTYPE {self.path}"))
output = json.loads(output.decode('UTF-8'))
for device in output['blockdevices']:
return device['pttype']
@property
def device(self):
"""
@ -203,6 +217,82 @@ class Partition():
else:
return f'Partition(path={self.path}, size={self.size}, fs={self.filesystem}{mount_repr})'
def __dump__(self):
return {
'type' : 'primary',
'PARTUUID' : self.uuid,
'wipe' : self.allow_formatting,
'boot' : self.boot,
'ESP' : self.boot,
'mountpoint' : self.target_mountpoint,
'encrypted' : self._encrypted,
'start' : self.start,
'size' : self.end,
'filesystem' : {
'format' : get_filesystem_type(self.path)
}
}
@property
def sector_size(self):
output = b"".join(sys_command(f"lsblk --json -o+LOG-SEC {self.path}"))
output = json.loads(output.decode('UTF-8'))
for device in output['blockdevices']:
return device.get('log-sec', None)
@property
def start(self):
output = b"".join(sys_command(f"sfdisk --json {self.block_device.path}"))
output = json.loads(output.decode('UTF-8'))
for partition in output.get('partitionstable', {}).get('partitions', []):
if partition['node'] == self.path:
return partition['start']# * self.sector_size
@property
def end(self):
# TODO: Verify that the logic holds up, that 'size' is the size without 'start' added to it.
output = b"".join(sys_command(f"sfdisk --json {self.block_device.path}"))
output = json.loads(output.decode('UTF-8'))
for partition in output.get('partitionstable', {}).get('partitions', []):
if partition['node'] == self.path:
return partition['size']# * self.sector_size
@property
def boot(self):
output = b"".join(sys_command(f"sfdisk --json {self.block_device.path}"))
output = json.loads(output.decode('UTF-8'))
# Get the bootable flag from the sfdisk output:
# {
# "partitiontable": {
# "label":"dos",
# "id":"0xd202c10a",
# "device":"/dev/loop0",
# "unit":"sectors",
# "sectorsize":512,
# "partitions": [
# {"node":"/dev/loop0p1", "start":2048, "size":10483712, "type":"83", "bootable":true}
# ]
# }
# }
for partition in output.get('partitionstable', {}).get('partitions', []):
if partition['node'] == self.path:
return partition.get('bootable', False)
return False
@property
def partition_type(self):
output = b"".join(sys_command(f"lsblk --json -o+PTTYPE {self.path}"))
output = json.loads(output.decode('UTF-8'))
for device in output['blockdevices']:
return device['pttype']
@property
def uuid(self) -> str:
"""

View File

@ -542,7 +542,7 @@ def wipe_and_create_partitions(block_device):
else:
partition_type = 'msdos'
partitions_result = []
partitions_result = [block_device.__dump__()]
while True:
modes = [
@ -581,11 +581,33 @@ def wipe_and_create_partitions(block_device):
else:
log(f"Invalid start, end or fstype for this partition. Ignoring this partition creation.", fg="red")
continue
else:
for index, partition in enumerate(partitions_result):
print(partition)
print(f"{index}: {partition['start']} -> {partition['size']} ({partition['filesystem']['format']}{', mounting at: '+partition['mountpoint'] if partition['mountpoint'] else ''})")
elif task == "Delete partition":
elif task == "Assign mount-point for partition":
elif task == "Mark a partition as encrypted":
elif task == "Mark a partition as bootable (automatic for /boot)":
if task == "Delete partition":
partition = generic_select(partitions_result, 'Select which partition to delete: ', options_output=False)
del(partitions_result[partition])
elif task == "Assign mount-point for partition":
partition = generic_select(partitions_result, 'Select which partition to mount where: ', options_output=False)
mountpoint = input('Select where to mount partition (leave blank to remove mountpoint): ').strip()
if len(mountpoint):
partitions_result[partition]['mountpoint'] = mountpoint
if mountpoint == '/boot':
log(f"Marked partition as bootable because mountpoint was set to /boot.", fg="yellow")
partitions_result[partition]['boot'] = True
else:
del(partitions_result[partition]['mountpoint'])
elif task == "Mark a partition as encrypted":
partition = generic_select(partitions_result, 'Select which partition to mark as encrypted: ', options_output=False)
partitions_result[partition]['encrypted'] = True
elif task == "Mark a partition as bootable (automatic for /boot)":
partition = generic_select(partitions_result, 'Select which partition to mark as bootable: ', options_output=False)
partitions_result[partition]['boot'] = True
def select_individual_blockdevice_usage(block_devices :list):
result = {}

View File

@ -44,12 +44,6 @@ def ask_user_questions():
archinstall.arguments['mirror-region'] = {selected_region : archinstall.list_mirrors()[selected_region]}
# Ask which boot-loader to use (will only ask if we're in BIOS (non-efi) mode)
# We do this before the disk selection process because there are some soft dependencies
# in retards to which boot loader/mode we're in.
archinstall.arguments["bootloader"] = archinstall.ask_for_bootloader()
# Ask which harddrives/block-devices we will install to
# and convert them into archinstall.BlockDevice() objects.
if archinstall.arguments.get('harddrives', None):
@ -71,6 +65,10 @@ def ask_user_questions():
archinstall.arguments['!encryption-password'] = passwd
# Ask which boot-loader to use (will only ask if we're in BIOS (non-efi) mode)
archinstall.arguments["bootloader"] = archinstall.ask_for_bootloader()
# Get the hostname for the machine
if not archinstall.arguments.get('hostname', None):
archinstall.arguments['hostname'] = input('Desired hostname for the installation: ').strip(' ')