Merged PR #711 - Fixing disk "ghosting" issues using partprobe
* Adding partprobe at strategic places. * Swapped `for partition in blockdevice` to `for uuid, partition in blockdevice.partitions.items()` instead as `__iter__` for debugging purposes. * `get_mount_info()` now causes a exception rather than returning nothing if there is nothing to be shown. This to avoid issues where in places this is crucial information and it went by unnoticeable. Using exception handlers where it doesn't matter if there's any information or not.
This commit is contained in:
commit
ca52c796a5
|
|
@ -112,8 +112,8 @@ class BlockDevice:
|
|||
@property
|
||||
def partitions(self):
|
||||
from .filesystem import Partition
|
||||
SysCommand(['partprobe', self.path])
|
||||
|
||||
self.partprobe()
|
||||
result = SysCommand(['/usr/bin/lsblk', '-J', self.path])
|
||||
|
||||
if b'not a block device' in result:
|
||||
|
|
@ -202,6 +202,9 @@ class BlockDevice:
|
|||
info = space_info
|
||||
return info
|
||||
|
||||
def partprobe(self):
|
||||
SysCommand(['partprobe', self.path])
|
||||
|
||||
def has_partitions(self):
|
||||
return len(self.partitions)
|
||||
|
||||
|
|
@ -217,7 +220,7 @@ class BlockDevice:
|
|||
def get_partition(self, uuid):
|
||||
count = 0
|
||||
while count < 5:
|
||||
for partition in self:
|
||||
for partition_uuid, partition in self.partitions.items():
|
||||
if partition.uuid == uuid:
|
||||
return partition
|
||||
else:
|
||||
|
|
@ -226,4 +229,7 @@ class BlockDevice:
|
|||
count += 1
|
||||
else:
|
||||
log(f"Could not find {uuid} in disk after 5 retries",level=logging.INFO)
|
||||
print(f"Cache: {self.part_cache}")
|
||||
print(f"Partitions: {self.partitions.items()}")
|
||||
print(f"UUID: {[uuid]}")
|
||||
raise DiskError(f"New partition {uuid} never showed up after adding new partition on {self}")
|
||||
|
|
|
|||
|
|
@ -20,24 +20,8 @@ class Filesystem:
|
|||
self.mode = mode
|
||||
|
||||
def __enter__(self, *args, **kwargs):
|
||||
if self.blockdevice.keep_partitions is False:
|
||||
log(f'Wiping {self.blockdevice} by using partition format {self.mode}', level=logging.DEBUG)
|
||||
if self.mode == GPT:
|
||||
if self.parted_mklabel(self.blockdevice.device, "gpt"):
|
||||
self.blockdevice.flush_cache()
|
||||
return self
|
||||
else:
|
||||
raise DiskError('Problem setting the disk label type to GPT:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel gpt')
|
||||
elif self.mode == MBR:
|
||||
if self.parted_mklabel(self.blockdevice.device, "msdos"):
|
||||
return self
|
||||
else:
|
||||
raise DiskError('Problem setting the disk label type to msdos:', f'/usr/bin/parted -s {self.blockdevice.device} mklabel msdos')
|
||||
else:
|
||||
raise DiskError(f'Unknown mode selected to format in: {self.mode}')
|
||||
|
||||
# TODO: partition_table_type is hardcoded to GPT at the moment. This has to be changed.
|
||||
elif self.mode == self.blockdevice.partition_table_type:
|
||||
if self.mode == self.blockdevice.partition_table_type:
|
||||
log(f'Kept partition format {self.mode} for {self.blockdevice}', level=logging.DEBUG)
|
||||
else:
|
||||
raise DiskError(f'The selected partition table format {self.mode} does not match that of {self.blockdevice}.')
|
||||
|
|
@ -74,6 +58,8 @@ class Filesystem:
|
|||
if not self.parted_mklabel(self.blockdevice.device, "msdos"):
|
||||
raise KeyError(f"Could not create a MSDOS label on {self}")
|
||||
|
||||
self.blockdevice.flush_cache()
|
||||
|
||||
# We then iterate the partitions in order
|
||||
for partition in layout.get('partitions', []):
|
||||
# We don't want to re-add an existing partition (those containing a UUID already)
|
||||
|
|
@ -132,6 +118,9 @@ class Filesystem:
|
|||
if partition.target_mountpoint == mountpoint or partition.mountpoint == mountpoint:
|
||||
return partition
|
||||
|
||||
def partprobe(self):
|
||||
SysCommand(f'bash -c "partprobe"')
|
||||
|
||||
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")
|
||||
|
|
@ -146,6 +135,7 @@ class Filesystem:
|
|||
:type string: str
|
||||
"""
|
||||
if (parted_handle := self.raw_parted(string)).exit_code == 0:
|
||||
self.partprobe()
|
||||
return True
|
||||
else:
|
||||
raise DiskError(f"Parted failed to add a partition: {parted_handle}")
|
||||
|
|
@ -176,7 +166,15 @@ class Filesystem:
|
|||
if len(new_uuid_set) > 0:
|
||||
new_uuid = new_uuid_set.pop()
|
||||
if new_uuid:
|
||||
return self.blockdevice.get_partition(new_uuid)
|
||||
try:
|
||||
return self.blockdevice.get_partition(new_uuid)
|
||||
except Exception as err:
|
||||
print('Blockdevice:', self.blockdevice)
|
||||
print('Partitions:', self.blockdevice.partitions)
|
||||
print('Partition set:', new_uuid_set)
|
||||
print('New UUID:', [new_uuid])
|
||||
print('get_partition():', self.blockdevice.get_partition)
|
||||
raise err
|
||||
else:
|
||||
count += 1
|
||||
log(f"Could not get uuid for partition. Waiting for the {count} time",level=logging.DEBUG)
|
||||
|
|
@ -199,4 +197,5 @@ class Filesystem:
|
|||
SysCommand(f'bash -c "umount {device}?"')
|
||||
except:
|
||||
pass
|
||||
self.partprobe()
|
||||
return self.raw_parted(f'{device} mklabel {disk_label}').exit_code == 0
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ def harddrive(size=None, model=None, fuzzy=False):
|
|||
def get_mount_info(path :Union[pathlib.Path, str], traverse=False, return_real_path=False) -> dict:
|
||||
for traversal in list(map(str, [str(path)] + list(pathlib.Path(str(path)).parents))):
|
||||
try:
|
||||
log(f"Getting mount information at location {traversal}", level=logging.INFO)
|
||||
log(f"Getting mount information for device path {traversal}", level=logging.INFO)
|
||||
output = SysCommand(f'/usr/bin/findmnt --json {traversal}').decode('UTF-8')
|
||||
if output:
|
||||
break
|
||||
|
|
@ -132,10 +132,7 @@ def get_mount_info(path :Union[pathlib.Path, str], traverse=False, return_real_p
|
|||
break
|
||||
|
||||
if not output:
|
||||
if return_real_path:
|
||||
return {}, None
|
||||
else:
|
||||
return {}
|
||||
raise DiskError(f"Could not get mount information for device path {path}")
|
||||
|
||||
output = json.loads(output)
|
||||
if 'filesystems' in output:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@ class Partition:
|
|||
if mountpoint:
|
||||
self.mount(mountpoint)
|
||||
|
||||
mount_information = get_mount_info(self.path)
|
||||
try:
|
||||
mount_information = get_mount_info(self.path)
|
||||
except DiskError:
|
||||
mount_information = {}
|
||||
|
||||
if self.mountpoint != mount_information.get('target', None) and mountpoint:
|
||||
raise DiskError(f"{self} was given a mountpoint but the actual mountpoint differs: {mount_information.get('target', None)}")
|
||||
|
|
@ -145,8 +148,11 @@ class Partition:
|
|||
it doesn't seam to be able to detect md raid partitions.
|
||||
"""
|
||||
|
||||
lsblk = json.loads(SysCommand(f'lsblk -J -o+PARTUUID {self.path}').decode('UTF-8'))
|
||||
for partition in lsblk['blockdevices']:
|
||||
partuuid_struct = SysCommand(f'lsblk -J -o+PARTUUID {self.path}')
|
||||
if not partuuid_struct.exit_code == 0:
|
||||
raise DiskError(f"Could not get PARTUUID for {self.path}: {partuuid_struct}")
|
||||
|
||||
for partition in json.loads(partuuid_struct.decode('UTF-8'))['blockdevices']:
|
||||
return partition.get('partuuid', None)
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ class luks2:
|
|||
with open(key_file, 'wb') as fh:
|
||||
fh.write(password)
|
||||
|
||||
SysCommand(f'bash -c "partprobe"') # Might be redundant
|
||||
|
||||
cryptsetup_args = shlex.join([
|
||||
'/usr/bin/cryptsetup',
|
||||
'--batch-mode',
|
||||
|
|
@ -86,6 +88,7 @@ class luks2:
|
|||
|
||||
# Get crypt-information about the device by doing a reverse lookup starting with the partition path
|
||||
# For instance: /dev/sda
|
||||
SysCommand(f'bash -c "partprobe"')
|
||||
devinfo = json.loads(b''.join(SysCommand(f"lsblk --fs -J {partition.path}")).decode('UTF-8'))['blockdevices'][0]
|
||||
|
||||
# For each child (sub-partition/sub-device)
|
||||
|
|
|
|||
Loading…
Reference in New Issue