Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Hvornum <anton@hvornum.se>2021-05-10 19:21:05 +0200
committerAnton Hvornum <anton@hvornum.se>2021-05-10 19:21:05 +0200
commitdd52bfb3a7f6f7a150e46f7c99d538e26de60276 (patch)
treebab058d1ebd323fccf45bd5acf8d324b894ea529
parent4aaaa3208bedc110cef4b4545031e8e43103161a (diff)
Tested the workflow, and it works pretty decent. There's some kinks to work out. Added BlockDevice().size as well.
-rw-r--r--archinstall/lib/disk.py10
-rw-r--r--archinstall/lib/user_interaction.py138
2 files changed, 122 insertions, 26 deletions
diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py
index dd704261..ab3560a9 100644
--- a/archinstall/lib/disk.py
+++ b/archinstall/lib/disk.py
@@ -152,6 +152,16 @@ class BlockDevice():
for partition in json.loads(lsblk.decode('UTF-8'))['blockdevices']:
return partition.get('uuid', None)
+ @property
+ def size(self):
+ output = b"".join(sys_command(f"lsblk --json -o+SIZE {self.path}"))
+ output = json.loads(output.decode('UTF-8'))
+
+ for device in output['blockdevices']:
+ assert device['size'][-1] == 'G' # Make sure we're counting in Gigabytes, otherwise the next logic fails.
+
+ return float(device['size'][:-1])
+
def has_partitions(self):
return len(self.partitions)
diff --git a/archinstall/lib/user_interaction.py b/archinstall/lib/user_interaction.py
index 21295537..f51fb4a4 100644
--- a/archinstall/lib/user_interaction.py
+++ b/archinstall/lib/user_interaction.py
@@ -549,6 +549,43 @@ def partition_overlap(partitions :list, start :str, end :str) -> bool:
# TODO: Implement sanity check
return False
+def get_default_partition_layout(block_devices):
+ if len(block_devices) == 1:
+ return {
+ block_devices[0] : [
+ { # Boot
+ "type" : "primary",
+ "start" : "0MiB",
+ "size" : "513MiB",
+ "boot" : True,
+ "mountpoint" : "/boot",
+ "filesystem" : {
+ "format" : "fat32"
+ }
+ },
+ { # Root
+ "type" : "primary",
+ "start" : "513MiB",
+ "encrypted" : True,
+ "size" : f"{max(block_devices[0].size*0.2, 20)}GiB",
+ "mountpoint" : "",
+ "filesystem" : {
+ "format" : "btrfs"
+ }
+ },
+ { # Home
+ "type" : "primary",
+ "encrypted" : True,
+ "start" : f"{max(block_devices[0].size*0.2, 20)}GiB",
+ "size" : "100%",
+ "mountpoint" : "/home",
+ "filesystem" : {
+ "format" : "btrfs"
+ }
+ }
+ ]
+ }
+
def wipe_and_create_partitions(block_device):
if hasUEFI():
partition_type = 'gpt'
@@ -556,14 +593,48 @@ def wipe_and_create_partitions(block_device):
partition_type = 'msdos'
partitions_result = [part.__dump__() for part in block_device.partitions]
+ suggested_layout = [
+ { # Boot
+ "type" : "primary",
+ "start" : "0MiB",
+ "size" : "513MiB",
+ "boot" : True,
+ "mountpoint" : "/boot",
+ "filesystem" : {
+ "format" : "fat32"
+ }
+ },
+ { # Root
+ "type" : "primary",
+ "start" : "513MiB",
+ "encrypted" : True,
+ "size" : f"{max(block_device.size*0.2, 20)}GiB",
+ "mountpoint" : "",
+ "filesystem" : {
+ "format" : "btrfs"
+ }
+ },
+ { # Home
+ "type" : "primary",
+ "encrypted" : True,
+ "start" : f"{max(block_device.size*0.2, 20)}GiB",
+ "size" : "100%",
+ "mountpoint" : "/home",
+ "filesystem" : {
+ "format" : "btrfs"
+ }
+ }
+ ]
+ # TODO: Squeeze in BTRFS subvolumes here
while True:
modes = [
"Create new partition",
+ "Suggest partition layout",
"Delete partition" if len(partitions_result) else "",
"Assign mount-point for partition" if len(partitions_result) else "",
- "Mark a partition as encrypted" if len(partitions_result) else "",
- "Mark a partition as bootable (automatic for /boot)" if len(partitions_result) else ""
+ "Mark/Unmark a partition as encrypted" if len(partitions_result) else "",
+ "Mark/Unmark a partition as bootable (automatic for /boot)" if len(partitions_result) else ""
]
# Print current partition layout:
@@ -574,7 +645,7 @@ def wipe_and_create_partitions(block_device):
print()
task = generic_select(modes,
- input_text=f"Select what to do with {block_device}: ")
+ input_text=f"Select what to do with {block_device} (leave blank when done): ")
if task == 'Create new partition':
if partition_type == 'gpt':
@@ -602,39 +673,50 @@ 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 == "Suggest partition layout":
+ if len(partitions_result):
+ if input(f"{block_device} contains queued partitions, this will remove those, are you sure? y/N: ").strip().lower() in ('', 'n'):
+ continue
+
+ partitions_result = [*suggested_layout]
+ elif task is None:
+ return partitions_result
else:
for index, partition in enumerate(partitions_result):
- print(partition)
print(f"{index}: Start: {partition['start']}, End: {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[partitions_result.index(partition)])
+ if (partition := generic_select(partitions_result, 'Select which partition to delete: ', options_output=False)):
+ del(partitions_result[partitions_result.index(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 (partition := generic_select(partitions_result, 'Select which partition to mount where: ', options_output=False)):
+ print(' * Partition mount-points are relative to inside the installation, the boot would be /boot as an example.')
+ mountpoint = input('Select where to mount partition (leave blank to remove mountpoint): ').strip()
+
+ if len(mountpoint):
+ partitions_result[partitions_result.index(partition)]['mountpoint'] = mountpoint
+ if mountpoint == '/boot':
+ log(f"Marked partition as bootable because mountpoint was set to /boot.", fg="yellow")
+ partitions_result[partitions_result.index(partition)]['boot'] = True
+ else:
+ del(partitions_result[partitions_result.index(partition)]['mountpoint'])
- 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/Unmark a partition as encrypted":
+ if (partition := generic_select(partitions_result, 'Select which partition to mark as encrypted: ', options_output=False)):
+ # Negate the current encryption marking
+ partitions_result[partitions_result.index(partition)]['encrypted'] = not partitions_result[partitions_result.index(partition)].get('encrypted', False)
- 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/Unmark a partition as bootable (automatic for /boot)":
+ if (partition := generic_select(partitions_result, 'Select which partition to mark as bootable: ', options_output=False)):
+ partitions_result[partitions_result.index(partition)]['boot'] = not partitions_result[partitions_result.index(partition)].get('boot', False)
- 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
+ return partitions_result
def select_individual_blockdevice_usage(block_devices :list):
result = {}
for device in block_devices:
- print(f'Select what to do with {device}')
+ log(f'Select what to do with {device}', fg="yellow")
modes = [
"Wipe and create new partitions",
"Re-use partitions"
@@ -644,10 +726,14 @@ def select_individual_blockdevice_usage(block_devices :list):
if device_mode == "Re-use partitions":
layout = select_partition_layout(device)
- else:
+ elif device_mode == "Wipe and create new partitions":
layout = wipe_and_create_partitions(device)
+ else:
+ continue
- result[device.path] = layout
+ result[device] = layout
+
+ return result
def select_disk_layout(block_devices :list):
@@ -656,12 +742,12 @@ def select_disk_layout(block_devices :list):
"Select what to do with each individual drive (followed by partition usage)"
]
- mode = input("Do you wish to ")
+ mode = generic_select(modes, input_text=f"Select what you wish to do with the selected block devices: ")
if mode == 'Wipe all selected drives and use a best-effort default partition layout':
return get_default_partition_layout(block_devices)
else:
- partitions = select_individual_blockdevice_usage(block_devices)
+ return select_individual_blockdevice_usage(block_devices)
def select_disk(dict_o_disks):
"""