Prevent recovering to wrong devices or paths
Before starting a recovery run verify the source and destination have not changed. This will prevent issues on some extreme edge cases but the main goal is for disappearing source drives with heavy damage. e.g. A very damaged source drive disappears mid-recovery, drops off and before would need a restart, or unplug/replug, to continue. Now we can attempt to re-detect the drive and resume recovery without leaving the script. If for some reason the drive order were to change then we'll avoid using the wrong source or destination device.
This commit is contained in:
parent
43fd30322e
commit
5a2d35d3cc
1 changed files with 36 additions and 2 deletions
|
|
@ -1719,6 +1719,8 @@ def is_missing_source_or_destination(state):
|
||||||
'Source': state.source,
|
'Source': state.source,
|
||||||
'Destination': state.destination,
|
'Destination': state.destination,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check items
|
||||||
for name, item in items.items():
|
for name, item in items.items():
|
||||||
if not item:
|
if not item:
|
||||||
continue
|
continue
|
||||||
|
|
@ -1733,9 +1735,38 @@ def is_missing_source_or_destination(state):
|
||||||
else:
|
else:
|
||||||
LOG.error('Unknown %s type: %s', name, item)
|
LOG.error('Unknown %s type: %s', name, item)
|
||||||
|
|
||||||
|
# Update top panes
|
||||||
|
state.update_top_panes()
|
||||||
|
|
||||||
|
# Done
|
||||||
return missing
|
return missing
|
||||||
|
|
||||||
|
|
||||||
|
def source_or_destination_changed(state):
|
||||||
|
"""Verify the source and destination objects are still valid."""
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
# Compare objects
|
||||||
|
for obj in (state.source, state.destination):
|
||||||
|
if not obj:
|
||||||
|
changed = True
|
||||||
|
elif hasattr(obj, 'exists'):
|
||||||
|
# Assuming dest path
|
||||||
|
changed = changed or not obj.exists()
|
||||||
|
elif isinstance(obj, hw_obj.Disk):
|
||||||
|
compare_dev = hw_obj.Disk(obj.path)
|
||||||
|
for key in ('model', 'serial'):
|
||||||
|
changed = changed or obj.details[key] != compare_dev.details[key]
|
||||||
|
|
||||||
|
# Update top panes
|
||||||
|
state.update_top_panes()
|
||||||
|
|
||||||
|
# Done
|
||||||
|
if changed:
|
||||||
|
std.print_error('Source and/or Destination changed')
|
||||||
|
return changed
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
"""Main function for ddrescue TUI."""
|
"""Main function for ddrescue TUI."""
|
||||||
|
|
@ -1760,7 +1791,6 @@ def main():
|
||||||
|
|
||||||
# Show menu
|
# Show menu
|
||||||
while True:
|
while True:
|
||||||
state.update_top_panes()
|
|
||||||
selection = main_menu.advanced_select()
|
selection = main_menu.advanced_select()
|
||||||
|
|
||||||
# Change settings
|
# Change settings
|
||||||
|
|
@ -1781,6 +1811,8 @@ def main():
|
||||||
std.print_standard('Forcing controllers to rescan for devices...')
|
std.print_standard('Forcing controllers to rescan for devices...')
|
||||||
cmd = 'echo "- - -" | sudo tee /sys/class/scsi_host/host*/scan'
|
cmd = 'echo "- - -" | sudo tee /sys/class/scsi_host/host*/scan'
|
||||||
exe.run_program(cmd, check=False, shell=True)
|
exe.run_program(cmd, check=False, shell=True)
|
||||||
|
if source_or_destination_changed(state):
|
||||||
|
std.abort()
|
||||||
|
|
||||||
# Start recovery
|
# Start recovery
|
||||||
if 'Start' in selection:
|
if 'Start' in selection:
|
||||||
|
|
@ -2022,10 +2054,12 @@ def run_recovery(state, main_menu, settings_menu, dry_run=True):
|
||||||
|
|
||||||
# Bail early
|
# Bail early
|
||||||
if is_missing_source_or_destination(state):
|
if is_missing_source_or_destination(state):
|
||||||
state.update_top_panes()
|
|
||||||
std.print_standard('')
|
std.print_standard('')
|
||||||
std.pause('Press Enter to return to main menu...')
|
std.pause('Press Enter to return to main menu...')
|
||||||
return
|
return
|
||||||
|
if source_or_destination_changed(state):
|
||||||
|
std.print_standard('')
|
||||||
|
std.abort()
|
||||||
|
|
||||||
# Get settings
|
# Get settings
|
||||||
for name, details in main_menu.toggles.items():
|
for name, details in main_menu.toggles.items():
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue