Include more details in ddrescue-tui OST posts

This commit is contained in:
2Shirt 2023-07-09 13:19:47 -07:00
parent 593cb405c5
commit 33fe7b3b9e
Signed by: 2Shirt
GPG key ID: 152FAC923B0E132C

View file

@ -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__':