From 7ac06d75d0785da07d270dc38a7581d74c285cc5 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 22 Oct 2021 20:43:01 +0200 Subject: Restructured disk.py into lib/disk/.py instead. Shouldn't be any broken links as we expose all the functions through __init__.py - but you never know so I'll keep an eye for issues with this. --- archinstall/lib/disk/user_guides.py | 145 ++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 archinstall/lib/disk/user_guides.py (limited to 'archinstall/lib/disk/user_guides.py') diff --git a/archinstall/lib/disk/user_guides.py b/archinstall/lib/disk/user_guides.py new file mode 100644 index 00000000..f6466268 --- /dev/null +++ b/archinstall/lib/disk/user_guides.py @@ -0,0 +1,145 @@ +from ..output import log + +def suggest_single_disk_layout(block_device, default_filesystem=None): + if not default_filesystem: + from .user_interaction import ask_for_main_filesystem_format + default_filesystem = ask_for_main_filesystem_format() + + MIN_SIZE_TO_ALLOW_HOME_PART = 40 # Gb + + layout = { + block_device.path : { + "wipe" : True, + "partitions" : [] + } + } + + layout[block_device.path]['partitions'].append({ + # Boot + "type" : "primary", + "start" : "1MiB", + "size" : "513MiB", + "boot" : True, + "encrypted" : False, + "format" : True, + "mountpoint" : "/boot", + "filesystem" : { + "format" : "fat32" + } + }) + layout[block_device.path]['partitions'].append({ + # Root + "type" : "primary", + "start" : "513MiB", + "encrypted" : False, + "format" : True, + "size" : "100%" if block_device.size < MIN_SIZE_TO_ALLOW_HOME_PART else f"{min(block_device.size, 20)*1024}MiB", + "mountpoint" : "/", + "filesystem" : { + "format" : default_filesystem + } + }) + + if default_filesystem == 'btrfs' and input('Would you like to use BTRFS subvolumes? (Y/n)').strip().lower() in ('', 'y', 'yes'): + # https://btrfs.wiki.kernel.org/index.php/FAQ + # https://unix.stackexchange.com/questions/246976/btrfs-subvolume-uuid-clash + # https://github.com/classy-giraffe/easy-arch/blob/main/easy-arch.sh + layout[block_device.path]['partitions'][1]['btrfs'] = { + "subvolumes" : { + '@home' : '/home', + '@log' : '/var/log', + '@pkgs' : '/var/cache/pacman/pkg', + '@.snapshots' : '/.snapshots' + } + } + + elif block_device.size >= MIN_SIZE_TO_ALLOW_HOME_PART: + # If we don't want to use subvolumes, + # But we want to be able to re-use data between re-installs.. + # A second partition for /home would be nice if we have the space for it + layout[block_device.path]['partitions'].append({ + # Home + "type" : "primary", + "encrypted" : False, + "format" : True, + "start" : f"{min(block_device.size*0.2, 20)*1024}MiB", + "size" : "100%", + "mountpoint" : "/home", + "filesystem" : { + "format" : default_filesystem + } + }) + + return layout + + +def suggest_multi_disk_layout(block_devices, default_filesystem=None): + if not default_filesystem: + from .user_interaction import ask_for_main_filesystem_format + default_filesystem = ask_for_main_filesystem_format() + + # Not really a rock solid foundation of information to stand on, but it's a start: + # https://www.reddit.com/r/btrfs/comments/m287gp/partition_strategy_for_two_physical_disks/ + # https://www.reddit.com/r/btrfs/comments/9us4hr/what_is_your_btrfs_partitionsubvolumes_scheme/ + + MIN_SIZE_TO_ALLOW_HOME_PART = 40 # Gb + ARCH_LINUX_INSTALLED_SIZE = 20 # Gb, rough estimate taking in to account user desktops etc. TODO: Catch user packages to detect size? + + block_devices = sort_block_devices_based_on_performance(block_devices).keys() + + home_device = select_largest_device(block_devices, gigabytes=MIN_SIZE_TO_ALLOW_HOME_PART) + root_device = select_disk_larger_than_or_close_to(block_devices, gigabytes=ARCH_LINUX_INSTALLED_SIZE, filter_out=[home_device]) + + log(f"Suggesting multi-disk-layout using {len(block_devices)} disks, where {root_device} will be /root and {home_device} will be /home", level=logging.DEBUG) + + layout = { + root_device.path : { + "wipe" : True, + "partitions" : [] + }, + home_device.path : { + "wipe" : True, + "partitions" : [] + }, + } + + layout[root_device.path]['partitions'].append({ + # Boot + "type" : "primary", + "start" : "1MiB", + "size" : "513MiB", + "boot" : True, + "encrypted" : False, + "format" : True, + "mountpoint" : "/boot", + "filesystem" : { + "format" : "fat32" + } + }) + layout[root_device.path]['partitions'].append({ + # Root + "type" : "primary", + "start" : "513MiB", + "encrypted" : False, + "format" : True, + "size" : "100%", + "mountpoint" : "/", + "filesystem" : { + "format" : default_filesystem + } + }) + + layout[home_device.path]['partitions'].append({ + # Home + "type" : "primary", + "encrypted" : False, + "format" : True, + "start" : "4MiB", + "size" : "100%", + "mountpoint" : "/home", + "filesystem" : { + "format" : default_filesystem + } + }) + + return layout \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 8b96080ec81939f3a69c28585c21c43e496d087b Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 22 Oct 2021 21:02:39 +0200 Subject: Forgot some imports that didn't show up on a static run without going through a few of the menu's --- archinstall/lib/disk/blockdevice.py | 1 + archinstall/lib/disk/partition.py | 1 + archinstall/lib/disk/user_guides.py | 1 + 3 files changed, 3 insertions(+) (limited to 'archinstall/lib/disk/user_guides.py') diff --git a/archinstall/lib/disk/blockdevice.py b/archinstall/lib/disk/blockdevice.py index 422f35aa..daa65323 100644 --- a/archinstall/lib/disk/blockdevice.py +++ b/archinstall/lib/disk/blockdevice.py @@ -1,4 +1,5 @@ import json +import logging from ..output import log from ..general import SysCommand diff --git a/archinstall/lib/disk/partition.py b/archinstall/lib/disk/partition.py index 6b60347f..30151583 100644 --- a/archinstall/lib/disk/partition.py +++ b/archinstall/lib/disk/partition.py @@ -1,6 +1,7 @@ import glob import pathlib import time +import logging from typing import Optional from .blockdevice import BlockDevice from ..output import log diff --git a/archinstall/lib/disk/user_guides.py b/archinstall/lib/disk/user_guides.py index f6466268..0a975149 100644 --- a/archinstall/lib/disk/user_guides.py +++ b/archinstall/lib/disk/user_guides.py @@ -1,3 +1,4 @@ +import logging from ..output import log def suggest_single_disk_layout(block_device, default_filesystem=None): -- cgit v1.2.3-54-g00ecf From 7149b76f3bd3163938fe7413546e5f678f98851f Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Fri, 22 Oct 2021 21:54:16 +0200 Subject: Forgot some imports that didn't show up on a static run without going through a few of the menu's --- archinstall/lib/disk/__init__.py | 2 +- archinstall/lib/disk/blockdevice.py | 3 +++ archinstall/lib/disk/filesystem.py | 6 +++++- archinstall/lib/disk/helpers.py | 2 ++ archinstall/lib/disk/partition.py | 4 ++++ archinstall/lib/disk/user_guides.py | 4 ++-- examples/guided.py | 6 +++--- 7 files changed, 20 insertions(+), 7 deletions(-) (limited to 'archinstall/lib/disk/user_guides.py') diff --git a/archinstall/lib/disk/__init__.py b/archinstall/lib/disk/__init__.py index 8237f774..352d04b9 100644 --- a/archinstall/lib/disk/__init__.py +++ b/archinstall/lib/disk/__init__.py @@ -1,7 +1,7 @@ from .btrfs import * from .helpers import * from .blockdevice import BlockDevice -from .filesystem import Filesystem +from .filesystem import Filesystem, MBR, GPT from .partition import * from .user_guides import * from .validators import * \ No newline at end of file diff --git a/archinstall/lib/disk/blockdevice.py b/archinstall/lib/disk/blockdevice.py index daa65323..57cbcfa6 100644 --- a/archinstall/lib/disk/blockdevice.py +++ b/archinstall/lib/disk/blockdevice.py @@ -1,3 +1,4 @@ +import os import json import logging from ..output import log @@ -94,6 +95,7 @@ class BlockDevice: @property def partitions(self): + from .filesystem import Partition SysCommand(['partprobe', self.path]) result = SysCommand(['/usr/bin/lsblk', '-J', self.path]) @@ -123,6 +125,7 @@ class BlockDevice: @property def partition_table_type(self): + from .filesystem import GPT return GPT @property diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index b53d8451..28846764 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -1,7 +1,11 @@ import time +import logging +import json from .partition import Partition from .blockdevice import BlockDevice +from ..general import SysCommand from ..output import log +from ..storage import storage GPT = 0b00000001 MBR = 0b00000010 @@ -58,7 +62,7 @@ class Filesystem: return index def load_layout(self, layout :dict): - from .luks import luks2 + from ..luks import luks2 # If the layout tells us to wipe the drive, we do so if layout.get('wipe', False): diff --git a/archinstall/lib/disk/helpers.py b/archinstall/lib/disk/helpers.py index 8b372f73..65abdea2 100644 --- a/archinstall/lib/disk/helpers.py +++ b/archinstall/lib/disk/helpers.py @@ -132,6 +132,8 @@ def get_mount_info(path) -> dict: def get_partitions_in_use(mountpoint) -> list: + from .partition import Partition + try: output = SysCommand(f"/usr/bin/findmnt --json -R {mountpoint}").decode('UTF-8') except SysCallError: diff --git a/archinstall/lib/disk/partition.py b/archinstall/lib/disk/partition.py index 30151583..3bb2982b 100644 --- a/archinstall/lib/disk/partition.py +++ b/archinstall/lib/disk/partition.py @@ -2,9 +2,13 @@ import glob import pathlib import time import logging +import json +import os from typing import Optional from .blockdevice import BlockDevice +from .helpers import get_mount_info, get_filesystem_type from ..output import log +from ..general import SysCommand class Partition: def __init__(self, path: str, block_device: BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): diff --git a/archinstall/lib/disk/user_guides.py b/archinstall/lib/disk/user_guides.py index 0a975149..79b9d48f 100644 --- a/archinstall/lib/disk/user_guides.py +++ b/archinstall/lib/disk/user_guides.py @@ -3,7 +3,7 @@ from ..output import log def suggest_single_disk_layout(block_device, default_filesystem=None): if not default_filesystem: - from .user_interaction import ask_for_main_filesystem_format + from ..user_interaction import ask_for_main_filesystem_format default_filesystem = ask_for_main_filesystem_format() MIN_SIZE_TO_ALLOW_HOME_PART = 40 # Gb @@ -76,7 +76,7 @@ def suggest_single_disk_layout(block_device, default_filesystem=None): def suggest_multi_disk_layout(block_devices, default_filesystem=None): if not default_filesystem: - from .user_interaction import ask_for_main_filesystem_format + from ..user_interaction import ask_for_main_filesystem_format default_filesystem = ask_for_main_filesystem_format() # Not really a rock solid foundation of information to stand on, but it's a start: diff --git a/examples/guided.py b/examples/guided.py index b7c75b30..2efb4972 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -140,7 +140,7 @@ def ask_user_questions(): # Ask for a root password (optional, but triggers requirement for super-user if skipped) if not archinstall.arguments.get('!root-password', None): - archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (Recommendation: leave blank to leave root disabled): ') + archinstall.arguments['!root-password'] = archinstall.get_password(prompt='Enter root password (leave blank to disable disabled & create superuser): ') # Ask for additional users (super-user if root pw was not set) @@ -245,9 +245,9 @@ def perform_filesystem_operations(): Setup the blockdevice, filesystem (and optionally encryption). Once that's done, we'll hand over to perform_installation() """ - mode = archinstall.GPT + mode = archinstall.disk.GPT if has_uefi() is False: - mode = archinstall.MBR + mode = archinstall.disk.MBR for drive in archinstall.arguments['harddrives']: with archinstall.Filesystem(drive, mode) as fs: -- cgit v1.2.3-54-g00ecf From 76dc426a0fb69fa2d8cbc5c76934dc736d2839a6 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sat, 30 Oct 2021 11:00:22 +0200 Subject: Added creating and mounting of subvolume structure for BTRFS. --- archinstall/lib/disk/btrfs.py | 4 +++- archinstall/lib/disk/filesystem.py | 1 + archinstall/lib/disk/user_guides.py | 25 ++++++++++++++----------- archinstall/lib/installer.py | 7 +++++++ 4 files changed, 25 insertions(+), 12 deletions(-) (limited to 'archinstall/lib/disk/user_guides.py') diff --git a/archinstall/lib/disk/btrfs.py b/archinstall/lib/disk/btrfs.py index 558a249e..e9ffec66 100644 --- a/archinstall/lib/disk/btrfs.py +++ b/archinstall/lib/disk/btrfs.py @@ -23,7 +23,9 @@ def mount_subvolume(installation, location :Union[pathlib.Path, str], force=Fals raise DiskError(f"Cannot mount subvolume to {installation.target/location} because it contains data (non-empty folder target)") # Mount the logical volume to the physical structure - return SysCommand(f"mount {get_mount_info(installation.target/location)['source']} {installation.target}/{str(location)} -o subvol=@/{str(location)}").exit_code == 0 + mount_location = get_mount_info(installation.target/location)['source'] + SysCommand(f"umount {mount_location}") + return SysCommand(f"mount {mount_location} {installation.target}/{str(location)} -o subvol=@/{str(location)}").exit_code == 0 def create_subvolume(installation, location :Union[pathlib.Path, str]) -> bool: """ diff --git a/archinstall/lib/disk/filesystem.py b/archinstall/lib/disk/filesystem.py index 28846764..0328cd83 100644 --- a/archinstall/lib/disk/filesystem.py +++ b/archinstall/lib/disk/filesystem.py @@ -132,6 +132,7 @@ class Filesystem: def raw_parted(self, string: str): if (cmd_handle := SysCommand(f'/usr/bin/parted -s {string}')).exit_code != 0: log(f"Parted ended with a bad exit code: {cmd_handle}", level=logging.ERROR, fg="red") + time.sleep(0.5) return cmd_handle def parted(self, string: str): diff --git a/archinstall/lib/disk/user_guides.py b/archinstall/lib/disk/user_guides.py index 79b9d48f..6f8a1edb 100644 --- a/archinstall/lib/disk/user_guides.py +++ b/archinstall/lib/disk/user_guides.py @@ -41,18 +41,21 @@ def suggest_single_disk_layout(block_device, default_filesystem=None): } }) - if default_filesystem == 'btrfs' and input('Would you like to use BTRFS subvolumes? (Y/n)').strip().lower() in ('', 'y', 'yes'): - # https://btrfs.wiki.kernel.org/index.php/FAQ - # https://unix.stackexchange.com/questions/246976/btrfs-subvolume-uuid-clash - # https://github.com/classy-giraffe/easy-arch/blob/main/easy-arch.sh - layout[block_device.path]['partitions'][1]['btrfs'] = { - "subvolumes" : { - '@home' : '/home', - '@log' : '/var/log', - '@pkgs' : '/var/cache/pacman/pkg', - '@.snapshots' : '/.snapshots' + if default_filesystem == 'btrfs' and input('Would you like to use BTRFS subvolumes? (Y/n): ').strip().lower() in ('', 'y', 'yes'): + if input('Do you want to use a recommended structure? (Y/n): ').strip().lower() in ('', 'y', 'yes'): + # https://btrfs.wiki.kernel.org/index.php/FAQ + # https://unix.stackexchange.com/questions/246976/btrfs-subvolume-uuid-clash + # https://github.com/classy-giraffe/easy-arch/blob/main/easy-arch.sh + layout[block_device.path]['partitions'][1]['btrfs'] = { + "subvolumes" : { + '@home' : '/home', + '@log' : '/var/log', + '@pkgs' : '/var/cache/pacman/pkg', + '@.snapshots' : '/.snapshots' + } } - } + else: + pass #... implement a guided setup elif block_device.size >= MIN_SIZE_TO_ALLOW_HOME_PART: # If we don't want to use subvolumes, diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 2aac8510..41d918a1 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -5,6 +5,7 @@ from .mirrors import * from .plugins import plugins from .storage import storage from .user_interaction import * +from .disk.btrfs import create_subvolume, mount_subvolume # Any package that the Installer() is responsible for (optional and the default ones) __packages__ = ["base", "base-devel", "linux-firmware", "linux", "linux-lts", "linux-zen", "linux-hardened"] @@ -139,9 +140,15 @@ class Installer: password = mountpoints[mountpoint]['password'] with luks2(mountpoints[mountpoint]['device_instance'], loopdev, password, auto_unmount=False) as unlocked_device: unlocked_device.mount(f"{self.target}{mountpoint}") + else: mountpoints[mountpoint]['device_instance'].mount(f"{self.target}{mountpoint}") + if (subvolumes := mountpoints[mountpoint].get('btrfs', {}).get('subvolumes', {})): + for name, location in subvolumes.items(): + create_subvolume(self, location) + mount_subvolume(self, location) + def mount(self, partition, mountpoint, create_mountpoint=True): if create_mountpoint and not os.path.isdir(f'{self.target}{mountpoint}'): os.makedirs(f'{self.target}{mountpoint}') -- cgit v1.2.3-54-g00ecf