Include more details in ddrescue-tui OST posts
This commit is contained in:
parent
593cb405c5
commit
33fe7b3b9e
1 changed files with 61 additions and 2 deletions
|
|
@ -119,6 +119,7 @@ class BlockPair():
|
|||
self.map_data: dict[str, bool | int] = {}
|
||||
self.map_path: pathlib.Path = pathlib.Path()
|
||||
self.size: int = source_dev.size
|
||||
self.stats = {}
|
||||
self.status: dict[str, float | int | str] = {
|
||||
'read-skip': 'Pending',
|
||||
'read-full': 'Pending',
|
||||
|
|
@ -345,6 +346,7 @@ class State():
|
|||
self.ost = osticket.osTicket()
|
||||
self.progress_out: pathlib.Path = self.log_dir.joinpath('progress.out')
|
||||
self.mode: str = '?'
|
||||
self.notes = []
|
||||
self.source: hw_disk.Disk | None = None
|
||||
self.working_dir: pathlib.Path | None = None
|
||||
self.ui: tui.TUI = tui.TUI('Source')
|
||||
|
|
@ -584,6 +586,13 @@ class State():
|
|||
def generate_report(self) -> list[str]:
|
||||
"""Generate report of overall and per block_pair results, returns list."""
|
||||
report = []
|
||||
stats_str = (
|
||||
'\tnon-trimmed: {non-trimmed}, '
|
||||
'non-scraped: {non-scraped}, '
|
||||
'bad-sectors: {bad-sector}, '
|
||||
'slow reads: {slow reads}, '
|
||||
'run time: {run time}'
|
||||
)
|
||||
|
||||
# Header
|
||||
report.append(f'{self.mode.title()} Results:')
|
||||
|
|
@ -604,8 +613,16 @@ class State():
|
|||
report.append(f'Overall rescued: {percent}, error size: {error_size_str}')
|
||||
|
||||
# Block-Pairs
|
||||
if len(self.block_pairs) > 1:
|
||||
report.append(' ')
|
||||
if len(self.block_pairs) == 1:
|
||||
stats = self.block_pairs[0].stats
|
||||
if stats:
|
||||
try:
|
||||
report.append(stats_str.format(**stats))
|
||||
except KeyError:
|
||||
# Ignore and omit stats
|
||||
pass
|
||||
else:
|
||||
# Two or more block_pairs
|
||||
for pair in self.block_pairs:
|
||||
error_size = pair.get_error_size()
|
||||
error_size_str = std.bytes_to_string(error_size, decimals=2)
|
||||
|
|
@ -614,11 +631,25 @@ class State():
|
|||
pair_size = std.bytes_to_string(pair.size, decimals=2)
|
||||
percent = pair.get_percent_recovered()
|
||||
percent = format_status_string(percent, width=0)
|
||||
report.append(' ')
|
||||
report.append(
|
||||
f'{pair.source.name} ({pair_size}) '
|
||||
f'rescued: {percent}, '
|
||||
f'error size: {error_size_str}'
|
||||
)
|
||||
stats = pair.stats
|
||||
if not stats:
|
||||
continue
|
||||
try:
|
||||
report.append(stats_str.format(**stats))
|
||||
except KeyError:
|
||||
# Ignore and omit stats
|
||||
pass
|
||||
|
||||
# Notes
|
||||
if self.notes:
|
||||
report.append(' ')
|
||||
report.extend(self.notes)
|
||||
|
||||
# Done
|
||||
return report
|
||||
|
|
@ -1654,6 +1685,24 @@ def get_etoc() -> str:
|
|||
return etoc
|
||||
|
||||
|
||||
def get_stats() -> dict[str, Any]:
|
||||
"""Get stats from ddrescue output, returns dict."""
|
||||
output = tmux.capture_pane()
|
||||
stats = {}
|
||||
temp = []
|
||||
for line in output[output.find('ipos:'):].splitlines():
|
||||
temp.extend(line.split(','))
|
||||
for line in temp:
|
||||
line = line.strip()
|
||||
try:
|
||||
key, value = line.split(':')
|
||||
stats[key] = value.strip()
|
||||
except ValueError:
|
||||
# ignore
|
||||
pass
|
||||
return stats
|
||||
|
||||
|
||||
def finalize_recovery(state: State, dry_run: bool = True) -> None:
|
||||
"""Show recovery finalization options."""
|
||||
zero_fill_destination(state, dry_run=dry_run)
|
||||
|
|
@ -2096,6 +2145,9 @@ def relocate_backup_gpt(state: State, dry_run: bool = True) -> None:
|
|||
if proc.returncode:
|
||||
cli.print_error('ERROR: Failed to relocate backup GPT.')
|
||||
LOG.error('sfdisk result: %s, %s', proc.stdout, proc.stderr)
|
||||
state.notes.append('NOTE: Failed to relocated backup GPT')
|
||||
else:
|
||||
state.notes.append('NOTE: Relocated backup GPT to the end of the disk.')
|
||||
|
||||
|
||||
def run_ddrescue(state, block_pair, pass_name, settings, dry_run=True) -> None:
|
||||
|
|
@ -2183,6 +2235,9 @@ def run_ddrescue(state, block_pair, pass_name, settings, dry_run=True) -> None:
|
|||
# Update SMART pane
|
||||
_update_smart_panes()
|
||||
|
||||
# Stats
|
||||
block_pair.stats.update(get_stats())
|
||||
|
||||
# Check destination
|
||||
warning_message = check_destination_health(state.destination)
|
||||
if warning_message:
|
||||
|
|
@ -2430,9 +2485,13 @@ def zero_fill_destination(state: State, dry_run: bool = True) -> None:
|
|||
|
||||
# Re-run ddrescue to zero-fill gaps
|
||||
proc = exe.run_program(cmd, check=False, pipe=False)
|
||||
LOG.info('Zero-fill result: %s', proc)
|
||||
if proc.returncode:
|
||||
cli.print_error('ERROR: Failed to zero-fill: {block_pair.destination}')
|
||||
LOG.error('zero-fill error: %s, %s', proc.stdout, proc.stderr)
|
||||
state.notes.append('NOTE: Failed to zero-fill destination')
|
||||
else:
|
||||
state.notes.append('NOTE: Zero-filled gaps and extra space on destination.')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Reference in a new issue