Fix 1669 | Refactor display of sizes in tables (#2100)
* Use sector as default display * Display tables in sector size * Refactor size * Update * Update * fix flake8 --------- Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
parent
9e3e4a5df5
commit
b141609990
|
|
@ -14,6 +14,7 @@ from .device_model import (
|
|||
PartitionTable,
|
||||
Unit,
|
||||
Size,
|
||||
SectorSize,
|
||||
SubvolumeModification,
|
||||
DeviceGeometry,
|
||||
PartitionType,
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class DiskLayoutConfiguration:
|
|||
status=ModificationStatus(partition['status']),
|
||||
fs_type=FilesystemType(partition['fs_type']),
|
||||
start=Size.parse_args(partition['start']),
|
||||
length=Size.parse_args(partition['length']),
|
||||
length=Size.parse_args(partition['size']),
|
||||
mount_options=partition['mount_options'],
|
||||
mountpoint=Path(partition['mountpoint']) if partition['mountpoint'] else None,
|
||||
dev_path=Path(partition['dev_path']) if partition['dev_path'] else None,
|
||||
|
|
@ -138,80 +138,89 @@ class Unit(Enum):
|
|||
|
||||
sectors = 'sectors' # size in sector
|
||||
|
||||
Percent = '%' # size in percentile
|
||||
|
||||
@staticmethod
|
||||
def get_all_units() -> List[str]:
|
||||
return [u.name for u in Unit]
|
||||
|
||||
@staticmethod
|
||||
def get_si_units() -> List[Unit]:
|
||||
return [u for u in Unit if 'i' not in u.name and u.name != 'sectors']
|
||||
|
||||
|
||||
@dataclass
|
||||
class SectorSize:
|
||||
value: int
|
||||
unit: Unit
|
||||
|
||||
def __post_init__(self):
|
||||
match self.unit:
|
||||
case Unit.sectors:
|
||||
raise ValueError('Unit type sector not allowed for SectorSize')
|
||||
|
||||
@staticmethod
|
||||
def default() -> SectorSize:
|
||||
return SectorSize(512, Unit.B)
|
||||
|
||||
def json(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'value': self.value,
|
||||
'unit': self.unit.name,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def parse_args(cls, arg: Dict[str, Any]) -> SectorSize:
|
||||
return SectorSize(
|
||||
arg['value'],
|
||||
Unit[arg['unit']]
|
||||
)
|
||||
|
||||
def normalize(self) -> int:
|
||||
"""
|
||||
will normalize the value of the unit to Byte
|
||||
"""
|
||||
return int(self.value * self.unit.value) # type: ignore
|
||||
|
||||
|
||||
@dataclass
|
||||
class Size:
|
||||
value: int
|
||||
unit: Unit
|
||||
sector_size: Optional[Size] = None # only required when unit is sector
|
||||
total_size: Optional[Size] = None # required when operating on percentages
|
||||
sector_size: SectorSize
|
||||
|
||||
def __post_init__(self):
|
||||
if self.unit == Unit.sectors and self.sector_size is None:
|
||||
raise ValueError('Sector size is required when unit is sectors')
|
||||
elif self.unit == Unit.Percent:
|
||||
if self.value < 0 or self.value > 100:
|
||||
raise ValueError('Percentage must be between 0 and 100')
|
||||
elif self.total_size is None:
|
||||
raise ValueError('Total size is required when unit is percentage')
|
||||
|
||||
@property
|
||||
def _total_size(self) -> Size:
|
||||
"""
|
||||
Save method to get the total size, mainly to satisfy mypy
|
||||
This shouldn't happen as the Size object fails instantiation on missing total size
|
||||
"""
|
||||
if self.unit == Unit.Percent and self.total_size is None:
|
||||
raise ValueError('Percent unit size must specify a total size')
|
||||
return self.total_size # type: ignore
|
||||
if not isinstance(self.sector_size, SectorSize):
|
||||
raise ValueError('sector size must be of type SectorSize')
|
||||
|
||||
def json(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'value': self.value,
|
||||
'unit': self.unit.name,
|
||||
'sector_size': self.sector_size.json() if self.sector_size else None,
|
||||
'total_size': self._total_size.json() if self._total_size else None
|
||||
'sector_size': self.sector_size.json() if self.sector_size else None
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def parse_args(cls, size_arg: Dict[str, Any]) -> Size:
|
||||
sector_size = size_arg['sector_size']
|
||||
total_size = size_arg['total_size']
|
||||
|
||||
return Size(
|
||||
size_arg['value'],
|
||||
Unit[size_arg['unit']],
|
||||
Size.parse_args(sector_size) if sector_size else None,
|
||||
Size.parse_args(total_size) if total_size else None
|
||||
SectorSize.parse_args(sector_size),
|
||||
)
|
||||
|
||||
def convert(
|
||||
self,
|
||||
target_unit: Unit,
|
||||
sector_size: Optional[Size] = None,
|
||||
total_size: Optional[Size] = None
|
||||
sector_size: Optional[SectorSize] = None
|
||||
) -> Size:
|
||||
if target_unit == Unit.sectors and sector_size is None:
|
||||
raise ValueError('If target has unit sector, a sector size must be provided')
|
||||
|
||||
# not sure why we would ever wanna convert to percentages
|
||||
if target_unit == Unit.Percent and total_size is None:
|
||||
raise ValueError('Missing parameter total size to be able to convert to percentage')
|
||||
|
||||
if self.unit == target_unit:
|
||||
return self
|
||||
elif self.unit == Unit.Percent:
|
||||
amount = int(self._total_size._normalize() * (self.value / 100))
|
||||
return Size(amount, Unit.B)
|
||||
elif self.unit == Unit.sectors:
|
||||
norm = self._normalize()
|
||||
return Size(norm, Unit.B).convert(target_unit, sector_size)
|
||||
return Size(norm, Unit.B, self.sector_size).convert(target_unit, sector_size)
|
||||
else:
|
||||
if target_unit == Unit.sectors and sector_size is not None:
|
||||
norm = self._normalize()
|
||||
|
|
@ -219,7 +228,7 @@ class Size:
|
|||
return Size(sectors, Unit.sectors, sector_size)
|
||||
else:
|
||||
value = int(self._normalize() / target_unit.value) # type: ignore
|
||||
return Size(value, target_unit)
|
||||
return Size(value, target_unit, self.sector_size)
|
||||
|
||||
def as_text(self) -> str:
|
||||
return self.format_size(
|
||||
|
|
@ -230,31 +239,45 @@ class Size:
|
|||
def format_size(
|
||||
self,
|
||||
target_unit: Unit,
|
||||
sector_size: Optional[Size] = None,
|
||||
sector_size: Optional[SectorSize] = None,
|
||||
include_unit: bool = True
|
||||
) -> str:
|
||||
if self.unit == Unit.Percent:
|
||||
return f'{self.value}%'
|
||||
else:
|
||||
target_size = self.convert(target_unit, sector_size)
|
||||
if include_unit:
|
||||
return f'{target_size.value} {target_unit.name}'
|
||||
return f'{target_size.value}'
|
||||
target_size = self.convert(target_unit, sector_size)
|
||||
|
||||
if include_unit:
|
||||
return f'{target_size.value} {target_unit.name}'
|
||||
return f'{target_size.value}'
|
||||
|
||||
def format_highest(self, include_unit: bool = True) -> str:
|
||||
si_units = Unit.get_si_units()
|
||||
all_si_values = [self.convert(si) for si in si_units]
|
||||
filtered = filter(lambda x: x.value >= 1, all_si_values)
|
||||
|
||||
# we have to get the max by the unit value as we're interested
|
||||
# in getting the value in the highest possible unit without floats
|
||||
si_value = max(filtered, key=lambda x: x.unit.value)
|
||||
|
||||
if include_unit:
|
||||
return f'{si_value.value} {si_value.unit.name}'
|
||||
return f'{si_value.value}'
|
||||
|
||||
def _normalize(self) -> int:
|
||||
"""
|
||||
will normalize the value of the unit to Byte
|
||||
"""
|
||||
if self.unit == Unit.Percent:
|
||||
return self.convert(Unit.B).value
|
||||
elif self.unit == Unit.sectors and self.sector_size is not None:
|
||||
return self.value * self.sector_size._normalize()
|
||||
if self.unit == Unit.sectors and self.sector_size is not None:
|
||||
return self.value * self.sector_size.normalize()
|
||||
return int(self.value * self.unit.value) # type: ignore
|
||||
|
||||
def __sub__(self, other: Size) -> Size:
|
||||
src_norm = self._normalize()
|
||||
dest_norm = other._normalize()
|
||||
return Size(abs(src_norm - dest_norm), Unit.B)
|
||||
return Size(abs(src_norm - dest_norm), Unit.B, self.sector_size)
|
||||
|
||||
def __add__(self, other: Size) -> Size:
|
||||
src_norm = self._normalize()
|
||||
dest_norm = other._normalize()
|
||||
return Size(abs(src_norm + dest_norm), Unit.B, self.sector_size)
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._normalize() < other._normalize()
|
||||
|
|
@ -296,14 +319,22 @@ class _PartitionInfo:
|
|||
mountpoints: List[Path]
|
||||
btrfs_subvol_infos: List[_BtrfsSubvolumeInfo] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
def sector_size(self) -> SectorSize:
|
||||
sector_size = self.partition.geometry.device.sectorSize
|
||||
return SectorSize(sector_size, Unit.B)
|
||||
|
||||
def table_data(self) -> Dict[str, Any]:
|
||||
end = self.start + self.length
|
||||
|
||||
part_info = {
|
||||
'Name': self.name,
|
||||
'Type': self.type.value,
|
||||
'Filesystem': self.fs_type.value if self.fs_type else str(_('Unknown')),
|
||||
'Path': str(self.path),
|
||||
'Start': self.start.format_size(Unit.MiB),
|
||||
'Length': self.length.format_size(Unit.MiB),
|
||||
'Start': self.start.format_size(Unit.sectors, self.sector_size, include_unit=False),
|
||||
'End': end.format_size(Unit.sectors, self.sector_size, include_unit=False),
|
||||
'Size': self.length.format_highest(),
|
||||
'Flags': ', '.join([f.name for f in self.flags])
|
||||
}
|
||||
|
||||
|
|
@ -327,10 +358,14 @@ class _PartitionInfo:
|
|||
start = Size(
|
||||
partition.geometry.start,
|
||||
Unit.sectors,
|
||||
Size(partition.disk.device.sectorSize, Unit.B)
|
||||
SectorSize(partition.disk.device.sectorSize, Unit.B)
|
||||
)
|
||||
|
||||
length = Size(int(partition.getLength(unit='B')), Unit.B)
|
||||
length = Size(
|
||||
int(partition.getLength(unit='B')),
|
||||
Unit.B,
|
||||
SectorSize(partition.disk.device.sectorSize, Unit.B)
|
||||
)
|
||||
|
||||
return _PartitionInfo(
|
||||
partition=partition,
|
||||
|
|
@ -355,7 +390,7 @@ class _DeviceInfo:
|
|||
type: str
|
||||
total_size: Size
|
||||
free_space_regions: List[DeviceGeometry]
|
||||
sector_size: Size
|
||||
sector_size: SectorSize
|
||||
read_only: bool
|
||||
dirty: bool
|
||||
|
||||
|
|
@ -365,7 +400,7 @@ class _DeviceInfo:
|
|||
'Model': self.model,
|
||||
'Path': str(self.path),
|
||||
'Type': self.type,
|
||||
'Size': self.total_size.format_size(Unit.MiB),
|
||||
'Size': self.total_size.format_highest(),
|
||||
'Free space': int(total_free_space),
|
||||
'Sector size': self.sector_size.value,
|
||||
'Read only': self.read_only
|
||||
|
|
@ -379,15 +414,17 @@ class _DeviceInfo:
|
|||
else:
|
||||
device_type = parted.devices[device.type]
|
||||
|
||||
sector_size = Size(device.sectorSize, Unit.B)
|
||||
sector_size = SectorSize(device.sectorSize, Unit.B)
|
||||
free_space = [DeviceGeometry(g, sector_size) for g in disk.getFreeSpaceRegions()]
|
||||
|
||||
sector_size = SectorSize(device.sectorSize, Unit.B)
|
||||
|
||||
return _DeviceInfo(
|
||||
model=device.model.strip(),
|
||||
path=Path(device.path),
|
||||
type=device_type,
|
||||
sector_size=sector_size,
|
||||
total_size=Size(int(device.getLength(unit='B')), Unit.B),
|
||||
total_size=Size(int(device.getLength(unit='B')), Unit.B, sector_size),
|
||||
free_space_regions=free_space,
|
||||
read_only=device.readOnly,
|
||||
dirty=device.dirty
|
||||
|
|
@ -470,7 +507,7 @@ class SubvolumeModification:
|
|||
|
||||
|
||||
class DeviceGeometry:
|
||||
def __init__(self, geometry: Geometry, sector_size: Size):
|
||||
def __init__(self, geometry: Geometry, sector_size: SectorSize):
|
||||
self._geometry = geometry
|
||||
self._sector_size = sector_size
|
||||
|
||||
|
|
@ -498,7 +535,7 @@ class DeviceGeometry:
|
|||
'Sector size': self._sector_size.value,
|
||||
'Start (sector/B)': start_str,
|
||||
'End (sector/B)': end_str,
|
||||
'Length (sectors/B)': length_str
|
||||
'Size (sectors/B)': length_str
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -751,7 +788,7 @@ class PartitionModification:
|
|||
'status': self.status.value,
|
||||
'type': self.type.value,
|
||||
'start': self.start.json(),
|
||||
'length': self.length.json(),
|
||||
'size': self.length.json(),
|
||||
'fs_type': self.fs_type.value if self.fs_type else '',
|
||||
'mountpoint': str(self.mountpoint) if self.mountpoint else None,
|
||||
'mount_options': self.mount_options,
|
||||
|
|
@ -764,12 +801,15 @@ class PartitionModification:
|
|||
"""
|
||||
Called for displaying data in table format
|
||||
"""
|
||||
end = self.start + self.length
|
||||
|
||||
part_mod = {
|
||||
'Status': self.status.value,
|
||||
'Device': str(self.dev_path) if self.dev_path else '',
|
||||
'Type': self.type.value,
|
||||
'Start': self.start.format_size(Unit.MiB),
|
||||
'Length': self.length.format_size(Unit.MiB),
|
||||
'Start': self.start.format_size(Unit.sectors, self.start.sector_size, include_unit=False),
|
||||
'End': end.format_size(Unit.sectors, self.start.sector_size, include_unit=False),
|
||||
'Size': self.length.format_highest(),
|
||||
'FS type': self.fs_type.value if self.fs_type else 'Unknown',
|
||||
'Mountpoint': self.mountpoint if self.mountpoint else '',
|
||||
'Mount options': ', '.join(self.mount_options),
|
||||
|
|
@ -938,7 +978,7 @@ class LsblkInfo:
|
|||
name: str = ''
|
||||
path: Path = Path()
|
||||
pkname: str = ''
|
||||
size: Size = field(default_factory=lambda: Size(0, Unit.B))
|
||||
size: Size = field(default_factory=lambda: Size(0, Unit.B, SectorSize.default()))
|
||||
log_sec: int = 0
|
||||
pttype: str = ''
|
||||
ptuuid: str = ''
|
||||
|
|
@ -1017,7 +1057,8 @@ class LsblkInfo:
|
|||
if isinstance(getattr(lsblk_info, data_field), Path):
|
||||
val = Path(blockdevice[lsblk_field])
|
||||
elif isinstance(getattr(lsblk_info, data_field), Size):
|
||||
val = Size(blockdevice[lsblk_field], Unit.B)
|
||||
sector_size = SectorSize(blockdevice['log-sec'], Unit.B)
|
||||
val = Size(blockdevice[lsblk_field], Unit.B, sector_size)
|
||||
else:
|
||||
val = blockdevice[lsblk_field]
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from pathlib import Path
|
|||
from typing import Any, Dict, TYPE_CHECKING, List, Optional, Tuple
|
||||
|
||||
from .device_model import PartitionModification, FilesystemType, BDevice, Size, Unit, PartitionType, PartitionFlag, \
|
||||
ModificationStatus, DeviceGeometry
|
||||
ModificationStatus, DeviceGeometry, SectorSize
|
||||
from ..menu import Menu, ListManager, MenuSelection, TextInput
|
||||
from ..output import FormattedOutput, warn
|
||||
from .subvolume_menu import SubvolumeMenu
|
||||
|
|
@ -194,42 +194,47 @@ class PartitioningList(ListManager):
|
|||
|
||||
def _validate_value(
|
||||
self,
|
||||
sector_size: Size,
|
||||
sector_size: SectorSize,
|
||||
total_size: Size,
|
||||
value: str
|
||||
text: str,
|
||||
start: Optional[Size]
|
||||
) -> Optional[Size]:
|
||||
match = re.match(r'([0-9]+)([a-zA-Z|%]*)', value, re.I)
|
||||
match = re.match(r'([0-9]+)([a-zA-Z|%]*)', text, re.I)
|
||||
|
||||
if match:
|
||||
value, unit = match.groups()
|
||||
str_value, unit = match.groups()
|
||||
|
||||
if unit == '%':
|
||||
unit = Unit.Percent.name
|
||||
if unit == '%' and start:
|
||||
available = total_size - start
|
||||
value = int(available.value * (int(str_value) / 100))
|
||||
unit = available.unit.name
|
||||
else:
|
||||
value = int(str_value)
|
||||
|
||||
if unit and unit not in Unit.get_all_units():
|
||||
return None
|
||||
|
||||
unit = Unit[unit] if unit else Unit.sectors
|
||||
return Size(int(value), unit, sector_size, total_size)
|
||||
return Size(value, unit, sector_size)
|
||||
|
||||
return None
|
||||
|
||||
def _enter_size(
|
||||
self,
|
||||
sector_size: Size,
|
||||
sector_size: SectorSize,
|
||||
total_size: Size,
|
||||
prompt: str,
|
||||
default: Size
|
||||
default: Size,
|
||||
start: Optional[Size],
|
||||
) -> Size:
|
||||
while True:
|
||||
value = TextInput(prompt).run().strip()
|
||||
|
||||
size: Optional[Size] = None
|
||||
|
||||
if not value:
|
||||
size = default
|
||||
else:
|
||||
size = self._validate_value(sector_size, total_size, value)
|
||||
size = self._validate_value(sector_size, total_size, value, start)
|
||||
|
||||
if size:
|
||||
return size
|
||||
|
|
@ -247,7 +252,7 @@ class PartitioningList(ListManager):
|
|||
total_bytes = device_info.total_size.format_size(Unit.B)
|
||||
|
||||
prompt += str(_('Total: {} / {}')).format(total_sectors, total_bytes) + '\n\n'
|
||||
prompt += str(_('All entered values can be suffixed with a unit: B, KB, KiB, MB, MiB...')) + '\n'
|
||||
prompt += str(_('All entered values can be suffixed with a unit: %, B, KB, KiB, MB, MiB...')) + '\n'
|
||||
prompt += str(_('If no unit is provided, the value is interpreted as sectors')) + '\n'
|
||||
print(prompt)
|
||||
|
||||
|
|
@ -260,13 +265,14 @@ class PartitioningList(ListManager):
|
|||
device_info.sector_size,
|
||||
device_info.total_size,
|
||||
start_prompt,
|
||||
default_start
|
||||
default_start,
|
||||
None
|
||||
)
|
||||
|
||||
if start_size.value == largest_free_area.start:
|
||||
end_size = Size(largest_free_area.end, Unit.sectors, device_info.sector_size)
|
||||
else:
|
||||
end_size = Size(100, Unit.Percent, total_size=device_info.total_size)
|
||||
end_size = device_info.total_size
|
||||
|
||||
# prompt until valid end sector was entered
|
||||
end_prompt = str(_('Enter end (default: {}): ')).format(end_size.as_text())
|
||||
|
|
@ -274,7 +280,8 @@ class PartitioningList(ListManager):
|
|||
device_info.sector_size,
|
||||
device_info.total_size,
|
||||
end_prompt,
|
||||
end_size
|
||||
end_size,
|
||||
start_size
|
||||
)
|
||||
|
||||
return start_size, end_size
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ class Installer:
|
|||
lsblk_info = disk.get_lsblk_by_mountpoint(boot_mount)
|
||||
|
||||
if len(lsblk_info) > 0:
|
||||
if lsblk_info[0].size < disk.Size(200, disk.Unit.MiB):
|
||||
if lsblk_info[0].size < disk.Size(200, disk.Unit.MiB, disk.SectorSize.default()):
|
||||
raise DiskError(
|
||||
f'The boot partition mounted at {boot_mount} is not large enough to install a boot loader. '
|
||||
f'Please resize it to at least 200MiB and re-run the installation.'
|
||||
|
|
|
|||
|
|
@ -170,13 +170,13 @@ def select_disk_config(
|
|||
return None
|
||||
|
||||
|
||||
def _boot_partition() -> disk.PartitionModification:
|
||||
def _boot_partition(sector_size: disk.SectorSize) -> disk.PartitionModification:
|
||||
if SysInfo.has_uefi():
|
||||
start = disk.Size(1, disk.Unit.MiB)
|
||||
size = disk.Size(512, disk.Unit.MiB)
|
||||
start = disk.Size(1, disk.Unit.MiB, sector_size)
|
||||
size = disk.Size(512, disk.Unit.MiB, sector_size)
|
||||
else:
|
||||
start = disk.Size(3, disk.Unit.MiB)
|
||||
size = disk.Size(203, disk.Unit.MiB)
|
||||
start = disk.Size(3, disk.Unit.MiB, sector_size)
|
||||
size = disk.Size(203, disk.Unit.MiB, sector_size)
|
||||
|
||||
# boot partition
|
||||
return disk.PartitionModification(
|
||||
|
|
@ -215,8 +215,9 @@ def suggest_single_disk_layout(
|
|||
if not filesystem_type:
|
||||
filesystem_type = select_main_filesystem_format(advanced_options)
|
||||
|
||||
min_size_to_allow_home_part = disk.Size(40, disk.Unit.GiB)
|
||||
root_partition_size = disk.Size(20, disk.Unit.GiB)
|
||||
sector_size = device.device_info.sector_size
|
||||
min_size_to_allow_home_part = disk.Size(40, disk.Unit.GiB, sector_size)
|
||||
root_partition_size = disk.Size(20, disk.Unit.GiB, sector_size)
|
||||
using_subvolumes = False
|
||||
using_home_partition = False
|
||||
compression = False
|
||||
|
|
@ -244,7 +245,7 @@ def suggest_single_disk_layout(
|
|||
# Also re-align the start to 1MiB since we don't need the first sectors
|
||||
# like we do in MBR layouts where the boot loader is installed traditionally.
|
||||
|
||||
boot_partition = _boot_partition()
|
||||
boot_partition = _boot_partition(sector_size)
|
||||
device_modification.add_partition(boot_partition)
|
||||
|
||||
if not using_subvolumes:
|
||||
|
|
@ -259,11 +260,11 @@ def suggest_single_disk_layout(
|
|||
using_home_partition = False
|
||||
|
||||
# root partition
|
||||
start = disk.Size(513, disk.Unit.MiB) if SysInfo.has_uefi() else disk.Size(206, disk.Unit.MiB)
|
||||
start = disk.Size(513, disk.Unit.MiB, sector_size) if SysInfo.has_uefi() else disk.Size(206, disk.Unit.MiB, sector_size)
|
||||
|
||||
# Set a size for / (/root)
|
||||
if using_subvolumes or device_size_gib < min_size_to_allow_home_part or not using_home_partition:
|
||||
length = disk.Size(100, disk.Unit.Percent, total_size=device.device_info.total_size)
|
||||
length = device.device_info.total_size - start
|
||||
else:
|
||||
length = min(device.device_info.total_size, root_partition_size)
|
||||
|
||||
|
|
@ -294,11 +295,14 @@ def suggest_single_disk_layout(
|
|||
# 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
|
||||
start = root_partition.length
|
||||
length = device.device_info.total_size - root_partition.length
|
||||
|
||||
home_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=root_partition.length,
|
||||
length=disk.Size(100, disk.Unit.Percent, total_size=device.device_info.total_size),
|
||||
start=start,
|
||||
length=length,
|
||||
mountpoint=Path('/home'),
|
||||
fs_type=filesystem_type,
|
||||
mount_options=['compress=zstd'] if compression else []
|
||||
|
|
@ -319,9 +323,9 @@ def suggest_multi_disk_layout(
|
|||
# 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_home_partition_size = disk.Size(40, disk.Unit.GiB)
|
||||
min_home_partition_size = disk.Size(40, disk.Unit.GiB, disk.SectorSize.default())
|
||||
# rough estimate taking in to account user desktops etc. TODO: Catch user packages to detect size?
|
||||
desired_root_partition_size = disk.Size(20, disk.Unit.GiB)
|
||||
desired_root_partition_size = disk.Size(20, disk.Unit.GiB, disk.SectorSize.default())
|
||||
compression = False
|
||||
|
||||
if not filesystem_type:
|
||||
|
|
@ -362,28 +366,41 @@ def suggest_multi_disk_layout(
|
|||
root_device_modification = disk.DeviceModification(root_device, wipe=True)
|
||||
home_device_modification = disk.DeviceModification(home_device, wipe=True)
|
||||
|
||||
root_device_sector_size = root_device_modification.device.device_info.sector_size
|
||||
home_device_sector_size = home_device_modification.device.device_info.sector_size
|
||||
|
||||
# add boot partition to the root device
|
||||
boot_partition = _boot_partition()
|
||||
boot_partition = _boot_partition(root_device_sector_size)
|
||||
root_device_modification.add_partition(boot_partition)
|
||||
|
||||
if SysInfo.has_uefi():
|
||||
root_start = disk.Size(513, disk.Unit.MiB, root_device_sector_size)
|
||||
else:
|
||||
root_start = disk.Size(206, disk.Unit.MiB, root_device_sector_size)
|
||||
|
||||
root_length = root_device.device_info.total_size - root_start
|
||||
|
||||
# add root partition to the root device
|
||||
root_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=disk.Size(513, disk.Unit.MiB) if SysInfo.has_uefi() else disk.Size(206, disk.Unit.MiB),
|
||||
length=disk.Size(100, disk.Unit.Percent, total_size=root_device.device_info.total_size),
|
||||
start=root_start,
|
||||
length=root_length,
|
||||
mountpoint=Path('/'),
|
||||
mount_options=['compress=zstd'] if compression else [],
|
||||
fs_type=filesystem_type
|
||||
)
|
||||
root_device_modification.add_partition(root_partition)
|
||||
|
||||
start = disk.Size(1, disk.Unit.MiB, home_device_sector_size)
|
||||
length = home_device.device_info.total_size - start
|
||||
|
||||
# add home partition to home device
|
||||
home_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=disk.Size(1, disk.Unit.MiB),
|
||||
length=disk.Size(100, disk.Unit.Percent, total_size=home_device.device_info.total_size),
|
||||
start=start,
|
||||
length=length,
|
||||
mountpoint=Path('/home'),
|
||||
mount_options=['compress=zstd'] if compression else [],
|
||||
fs_type=filesystem_type,
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@
|
|||
"Boot"
|
||||
],
|
||||
"fs_type": "fat32",
|
||||
"length": {
|
||||
"size": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "MiB",
|
||||
"value": 512
|
||||
},
|
||||
|
|
@ -28,7 +27,6 @@
|
|||
"obj_id": "2c3fa2d5-2c79-4fab-86ec-22d0ea1543c0",
|
||||
"start": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "MiB",
|
||||
"value": 1
|
||||
},
|
||||
|
|
@ -39,9 +37,8 @@
|
|||
"btrfs": [],
|
||||
"flags": [],
|
||||
"fs_type": "ext4",
|
||||
"length": {
|
||||
"size": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "GiB",
|
||||
"value": 20
|
||||
},
|
||||
|
|
@ -50,7 +47,6 @@
|
|||
"obj_id": "3e7018a0-363b-4d05-ab83-8e82d13db208",
|
||||
"start": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "MiB",
|
||||
"value": 513
|
||||
},
|
||||
|
|
@ -61,14 +57,8 @@
|
|||
"btrfs": [],
|
||||
"flags": [],
|
||||
"fs_type": "ext4",
|
||||
"length": {
|
||||
"size": {
|
||||
"sector_size": null,
|
||||
"total_size": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "B",
|
||||
"value": 250148290560
|
||||
},
|
||||
"unit": "Percent",
|
||||
"value": 100
|
||||
},
|
||||
|
|
@ -77,7 +67,6 @@
|
|||
"obj_id": "ce58b139-f041-4a06-94da-1f8bad775d3f",
|
||||
"start": {
|
||||
"sector_size": null,
|
||||
"total_size": null,
|
||||
"unit": "GiB",
|
||||
"value": 20
|
||||
},
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ device_modification = disk.DeviceModification(device, wipe=True)
|
|||
boot_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=disk.Size(1, disk.Unit.MiB),
|
||||
length=disk.Size(512, disk.Unit.MiB),
|
||||
start=disk.Size(1, disk.Unit.MiB, device.device_info.sector_size),
|
||||
length=disk.Size(512, disk.Unit.MiB, device.device_info.sector_size),
|
||||
mountpoint=Path('/boot'),
|
||||
fs_type=disk.FilesystemType.Fat32,
|
||||
flags=[disk.PartitionFlag.Boot]
|
||||
|
|
@ -35,20 +35,23 @@ device_modification.add_partition(boot_partition)
|
|||
root_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=disk.Size(513, disk.Unit.MiB),
|
||||
length=disk.Size(20, disk.Unit.GiB),
|
||||
start=disk.Size(513, disk.Unit.MiB, device.device_info.sector_size),
|
||||
length=disk.Size(20, disk.Unit.GiB, device.device_info.sector_size),
|
||||
mountpoint=None,
|
||||
fs_type=fs_type,
|
||||
mount_options=[],
|
||||
)
|
||||
device_modification.add_partition(root_partition)
|
||||
|
||||
start_home = root_partition.length
|
||||
length_home = device.device_info.total_size - start_home
|
||||
|
||||
# create a new home partition
|
||||
home_partition = disk.PartitionModification(
|
||||
status=disk.ModificationStatus.Create,
|
||||
type=disk.PartitionType.Primary,
|
||||
start=root_partition.length,
|
||||
length=disk.Size(100, disk.Unit.Percent, total_size=device.device_info.total_size),
|
||||
start=start_home,
|
||||
length=length_home,
|
||||
mountpoint=Path('/home'),
|
||||
fs_type=fs_type,
|
||||
mount_options=[]
|
||||
|
|
|
|||
Loading…
Reference in New Issue