Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Hvornum <anton.feeds@gmail.com>2021-05-10 14:32:39 +0200
committerAnton Hvornum <anton.feeds@gmail.com>2021-05-10 14:32:39 +0200
commit6d5d9a1798e97b5e2d1db3339197ca2a767a6715 (patch)
tree4129678218c0ff59da067da9ef6c3db8e96235e7
parent3e601ff9ab32947cc5a12b6059cde360b9191477 (diff)
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.
-rw-r--r--archinstall/lib/disk.py96
-rw-r--r--archinstall/lib/user_interaction.py34
-rw-r--r--examples/guided.py10
3 files changed, 125 insertions, 15 deletions
diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py
index 1865c4fb..dd704261 100644
--- a/archinstall/lib/disk.py
+++ b/archinstall/lib/disk.py
@@ -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,12 +60,22 @@ 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):
"""
Returns the actual device-endpoint of the BlockDevice.
@@ -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:
"""
diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py
index 57ea5349..050825cb 100644
--- a/archinstall/lib/user_interaction.py
+++ b/archinstall/lib/user_interaction.py
@@ -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
-
- 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)":
+ 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 ''})")
+
+ 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 = {}
diff --git a/examples/guided.py b/examples/guided.py
index d65df218..8e267df9 100644
--- a/examples/guided.py
+++ b/examples/guided.py
@@ -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(' ')