Add udev sync before lsblk that follows formatting (#2412)

This commit is contained in:
codefiles 2024-03-12 05:25:15 -04:00 committed by GitHub
parent 613bec6562
commit df2884085d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 36 deletions

View File

@ -2,7 +2,6 @@ from __future__ import annotations
import json import json
import os import os
import time
import logging import logging
from pathlib import Path from pathlib import Path
from typing import List, Dict, Any, Optional, TYPE_CHECKING from typing import List, Dict, Any, Optional, TYPE_CHECKING
@ -316,6 +315,9 @@ class DeviceHandler(object):
else: else:
self._perform_formatting(part_mod.safe_fs_type, part_mod.safe_dev_path) self._perform_formatting(part_mod.safe_fs_type, part_mod.safe_dev_path)
# synchronize with udev before using lsblk
SysCommand('udevadm settle')
lsblk_info = self._fetch_part_info(part_mod.safe_dev_path) lsblk_info = self._fetch_part_info(part_mod.safe_dev_path)
part_mod.partn = lsblk_info.partn part_mod.partn = lsblk_info.partn
@ -384,19 +386,7 @@ class DeviceHandler(object):
part_mod.dev_path = Path(partition.path) part_mod.dev_path = Path(partition.path)
def _fetch_part_info(self, path: Path) -> LsblkInfo: def _fetch_part_info(self, path: Path) -> LsblkInfo:
attempts = 3 lsblk_info = get_lsblk_info(path)
lsblk_info: Optional[LsblkInfo] = None
for attempt_nr in range(attempts):
time.sleep(attempt_nr + 1)
lsblk_info = get_lsblk_info(path)
if lsblk_info.partn and lsblk_info.partuuid and lsblk_info.uuid:
break
if not lsblk_info:
debug(f'Unable to get partition information: {path}')
raise DiskError(f'Unable to get partition information: {path}')
if not lsblk_info.partn: if not lsblk_info.partn:
debug(f'Unable to determine new partition number: {path}\n{lsblk_info}') debug(f'Unable to determine new partition number: {path}\n{lsblk_info}')

View File

@ -3,7 +3,6 @@ from __future__ import annotations
import dataclasses import dataclasses
import json import json
import math import math
import time
import uuid import uuid
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
@ -1103,39 +1102,34 @@ def _clean_field(name: str, clean_type: CleanType) -> str:
return name.replace('_percentage', '%').replace('_', '-') return name.replace('_percentage', '%').replace('_', '-')
def _fetch_lsblk_info(dev_path: Optional[Union[Path, str]] = None, retry: int = 3) -> List[LsblkInfo]: def _fetch_lsblk_info(dev_path: Optional[Union[Path, str]] = None) -> List[LsblkInfo]:
fields = [_clean_field(f, CleanType.Lsblk) for f in LsblkInfo.fields()] fields = [_clean_field(f, CleanType.Lsblk) for f in LsblkInfo.fields()]
lsblk_fields = ','.join(fields) cmd = ['lsblk', '--json', '--bytes', '--output', '+' + ','.join(fields)]
if not dev_path: if dev_path:
dev_path = '' cmd.append(str(dev_path))
for retry_attempt in range(retry + 1): try:
try: result = SysCommand(cmd).decode()
result = SysCommand(f'lsblk --json -b -o+{lsblk_fields} {dev_path}').decode() except SysCallError as err:
break # Get the output minus the message/info from lsblk if it returns a non-zero exit code.
except SysCallError as err: if err.worker:
# Get the output minus the message/info from lsblk if it returns a non-zero exit code. err_str = err.worker.decode()
if err.worker: debug(f'Error calling lsblk: {err_str}')
err_str = err.worker.decode()
debug(f'Error calling lsblk: {err_str}')
else:
raise err
if retry_attempt == retry: if dev_path:
raise err raise DiskError(f'Failed to read disk "{dev_path}" with lsblk')
time.sleep(1) raise err
try: try:
block_devices = json.loads(result) block_devices = json.loads(result)
blockdevices = block_devices['blockdevices']
return [LsblkInfo.from_json(device) for device in blockdevices]
except json.decoder.JSONDecodeError as err: except json.decoder.JSONDecodeError as err:
error(f"Could not decode lsblk JSON: {result}") error(f"Could not decode lsblk JSON: {result}")
raise err raise err
raise DiskError(f'Failed to read disk "{dev_path}" with lsblk') blockdevices = block_devices['blockdevices']
return [LsblkInfo.from_json(device) for device in blockdevices]
def get_lsblk_info(dev_path: Union[Path, str]) -> LsblkInfo: def get_lsblk_info(dev_path: Union[Path, str]) -> LsblkInfo: