Added run_ddrescue() and update_smart_report()
* Working "wait" loop while ddrescue is running.
This commit is contained in:
parent
d1d3e1592e
commit
358191539c
1 changed files with 123 additions and 39 deletions
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import psutil
|
||||||
import re
|
import re
|
||||||
|
import signal
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from functions.common import *
|
from functions.common import *
|
||||||
|
|
@ -108,10 +110,11 @@ def menu_clone(source_path, dest_path):
|
||||||
|
|
||||||
# Set devices
|
# Set devices
|
||||||
source = select_device('source', source_path)
|
source = select_device('source', source_path)
|
||||||
source['Type'] = 'Clone'
|
source['Current Pass'] = 'Pass 1'
|
||||||
source['Pass 1'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 1'] = {'Status': 'Pending', 'Done': False}
|
||||||
source['Pass 2'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 2'] = {'Status': 'Pending', 'Done': False}
|
||||||
source['Pass 3'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 3'] = {'Status': 'Pending', 'Done': False}
|
||||||
|
source['Type'] = 'Clone'
|
||||||
dest = select_device('destination', dest_path,
|
dest = select_device('destination', dest_path,
|
||||||
skip_device = source['Details'], allow_image_file = False)
|
skip_device = source['Details'], allow_image_file = False)
|
||||||
|
|
||||||
|
|
@ -165,10 +168,11 @@ def menu_image(source_path, dest_path):
|
||||||
|
|
||||||
# Set devices
|
# Set devices
|
||||||
source = select_device('source', source_path, allow_image_file = False)
|
source = select_device('source', source_path, allow_image_file = False)
|
||||||
source['Type'] = 'Image'
|
source['Current Pass'] = 'Pass 1'
|
||||||
source['Pass 1'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 1'] = {'Status': 'Pending', 'Done': False}
|
||||||
source['Pass 2'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 2'] = {'Status': 'Pending', 'Done': False}
|
||||||
source['Pass 3'] = {'Status': 'Pending', 'Done': False}
|
source['Pass 3'] = {'Status': 'Pending', 'Done': False}
|
||||||
|
source['Type'] = 'Image'
|
||||||
dest = select_dest_path(dest_path, skip_device=source['Details'])
|
dest = select_dest_path(dest_path, skip_device=source['Details'])
|
||||||
|
|
||||||
# Show selection details
|
# Show selection details
|
||||||
|
|
@ -213,7 +217,7 @@ def menu_main(source):
|
||||||
# Update entries
|
# Update entries
|
||||||
for opt in main_options:
|
for opt in main_options:
|
||||||
opt['Name'] = '{} {}'.format(
|
opt['Name'] = '{} {}'.format(
|
||||||
'✓' if opt['Enabled'] else 'X',
|
'[✓]' if opt['Enabled'] else '[ ]',
|
||||||
opt['Base Name'])
|
opt['Base Name'])
|
||||||
|
|
||||||
selection = menu_select(
|
selection = menu_select(
|
||||||
|
|
@ -228,7 +232,6 @@ def menu_main(source):
|
||||||
elif selection == 'S':
|
elif selection == 'S':
|
||||||
# Set settings for pass
|
# Set settings for pass
|
||||||
settings = []
|
settings = []
|
||||||
# TODO move to new function and replace with real code
|
|
||||||
for k, v in source['Settings'].items():
|
for k, v in source['Settings'].items():
|
||||||
if not v['Enabled']:
|
if not v['Enabled']:
|
||||||
continue
|
continue
|
||||||
|
|
@ -245,38 +248,9 @@ def menu_main(source):
|
||||||
settings.append('--reverse')
|
settings.append('--reverse')
|
||||||
# Disable for next pass
|
# Disable for next pass
|
||||||
opt['Enabled'] = False
|
opt['Enabled'] = False
|
||||||
print_success('GO!')
|
|
||||||
if source['Pass 3']['Done']:
|
# Run pass
|
||||||
# Go to results
|
run_ddrescue(source, settings)
|
||||||
print_success('Done?')
|
|
||||||
elif source['Pass 2']['Done']:
|
|
||||||
# In pass 3
|
|
||||||
print_error('Pass 3')
|
|
||||||
print_standard(str(settings))
|
|
||||||
source['Pass 3']['Done'] = True
|
|
||||||
source['Pass 3']['Status'] = '99.99'
|
|
||||||
elif source['Pass 1']['Done']:
|
|
||||||
# In pass 2
|
|
||||||
print_warning('Pass 2')
|
|
||||||
settings.append('--no-scrape')
|
|
||||||
print_standard(str(settings))
|
|
||||||
source['Pass 2']['Done'] = True
|
|
||||||
source['Pass 2']['Status'] = '98.1415'
|
|
||||||
else:
|
|
||||||
# In pass 1
|
|
||||||
print_info('Pass 1')
|
|
||||||
settings.extend(['--no-trim', '--no-scrape'])
|
|
||||||
print_standard(str(settings))
|
|
||||||
status = source['Pass 1']['Status']
|
|
||||||
if status == 'Pending':
|
|
||||||
source['Pass 1']['Status'] = '78.6623'
|
|
||||||
elif float(status) < 80:
|
|
||||||
source['Pass 1']['Status'] = '86.1102'
|
|
||||||
elif float(status) < 95:
|
|
||||||
source['Pass 1']['Status'] = '97.77'
|
|
||||||
source['Pass 1']['Done'] = True
|
|
||||||
update_progress(source)
|
|
||||||
pause()
|
|
||||||
elif selection == 'C':
|
elif selection == 'C':
|
||||||
menu_settings(source)
|
menu_settings(source)
|
||||||
elif selection == 'Q':
|
elif selection == 'Q':
|
||||||
|
|
@ -502,9 +476,9 @@ def menu_settings(source):
|
||||||
enabled = source['Settings'][flag]['Enabled']
|
enabled = source['Settings'][flag]['Enabled']
|
||||||
if 'Value' in source['Settings'][flag]:
|
if 'Value' in source['Settings'][flag]:
|
||||||
answer = choice(
|
answer = choice(
|
||||||
choices = ['Toggle flag', 'Change value'],
|
choices = ['T', 'C'],
|
||||||
prompt = 'Please make a selection for "{}"'.format(flag))
|
prompt = 'Toggle or change value for "{}"'.format(flag))
|
||||||
if answer == 'Toggle flag':
|
if answer == 'T':
|
||||||
# Toggle
|
# Toggle
|
||||||
source['Settings'][flag]['Enabled'] = not enabled
|
source['Settings'][flag]['Enabled'] = not enabled
|
||||||
else:
|
else:
|
||||||
|
|
@ -516,6 +490,99 @@ def menu_settings(source):
|
||||||
elif selection == 'M':
|
elif selection == 'M':
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def run_ddrescue(source, settings):
|
||||||
|
"""Run ddrescue pass."""
|
||||||
|
if source['Current Pass'] == 'Pass 1':
|
||||||
|
settings.extend(['--no-trim', '--no-scrape'])
|
||||||
|
elif source['Current Pass'] == 'Pass 2':
|
||||||
|
settings.append('--no-scrape')
|
||||||
|
elif source['Current Pass'] == 'Pass 3':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Assuming Done
|
||||||
|
return
|
||||||
|
|
||||||
|
# Set heights
|
||||||
|
## NOTE: 10/32 is based on min heights for SMART/ddrescue panes (10 + 22)
|
||||||
|
result = run_program(['tput', 'lines'])
|
||||||
|
height = int(result.stdout.decode().strip())
|
||||||
|
height_smart = int(height * (12 / 34))
|
||||||
|
height_ddrescue = height - height_smart
|
||||||
|
|
||||||
|
# Show SMART status
|
||||||
|
update_smart_report(source)
|
||||||
|
smart_pane = tmux_splitw(
|
||||||
|
'-bdvl', str(height_smart),
|
||||||
|
'-PF', '#D',
|
||||||
|
'watch', '--color', '--no-title', '--interval', '5',
|
||||||
|
'cat', source['SMART Report'])
|
||||||
|
|
||||||
|
# Start ddrescue
|
||||||
|
return_code = None
|
||||||
|
try:
|
||||||
|
clear_screen()
|
||||||
|
#ddrescue_proc = popen_program('ddrescue who.dd wat.dd why.map'.split())
|
||||||
|
ddrescue_proc = popen_program(['./__choose_exit'])
|
||||||
|
while True:
|
||||||
|
sleep(3)
|
||||||
|
with open(source['SMART Report'], 'a') as f:
|
||||||
|
f.write('heh.\n')
|
||||||
|
return_code = ddrescue_proc.poll()
|
||||||
|
if return_code:
|
||||||
|
# i.e. not None and not 0
|
||||||
|
print_error('Error(s) encountered, see message above.')
|
||||||
|
break
|
||||||
|
elif return_code is not None:
|
||||||
|
# Assuming normal exit
|
||||||
|
break
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
# Catch user abort
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Was ddrescue aborted?
|
||||||
|
if return_code is None:
|
||||||
|
print_warning('Aborted')
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
update_progress(source)
|
||||||
|
print_info('Return: {}'.format(return_code))
|
||||||
|
pause()
|
||||||
|
run_program(['tmux', 'kill-pane', '-t', smart_pane])
|
||||||
|
return
|
||||||
|
|
||||||
|
##TODO
|
||||||
|
#print_success('GO!')
|
||||||
|
#if source['Pass 3']['Done']:
|
||||||
|
# # Go to results
|
||||||
|
# print_success('Done?')
|
||||||
|
#elif source['Pass 2']['Done']:
|
||||||
|
# # In pass 3
|
||||||
|
# print_error('Pass 3')
|
||||||
|
# print_standard(str(settings))
|
||||||
|
# source['Pass 3']['Done'] = True
|
||||||
|
# source['Pass 3']['Status'] = '99.99'
|
||||||
|
#elif source['Pass 1']['Done']:
|
||||||
|
# # In pass 2
|
||||||
|
# print_warning('Pass 2')
|
||||||
|
# settings.append('--no-scrape')
|
||||||
|
# print_standard(str(settings))
|
||||||
|
# source['Pass 2']['Done'] = True
|
||||||
|
# source['Pass 2']['Status'] = '98.1415'
|
||||||
|
#else:
|
||||||
|
# # In pass 1
|
||||||
|
# print_info('Pass 1')
|
||||||
|
# settings.extend(['--no-trim', '--no-scrape'])
|
||||||
|
# print_standard(str(settings))
|
||||||
|
# status = source['Pass 1']['Status']
|
||||||
|
# if status == 'Pending':
|
||||||
|
# source['Pass 1']['Status'] = '78.6623'
|
||||||
|
# elif float(status) < 80:
|
||||||
|
# source['Pass 1']['Status'] = '86.1102'
|
||||||
|
# elif float(status) < 95:
|
||||||
|
# source['Pass 1']['Status'] = '97.77'
|
||||||
|
# source['Pass 1']['Done'] = True
|
||||||
|
#update_progress(source)
|
||||||
|
|
||||||
def select_dest_path(provided_path=None, skip_device={}):
|
def select_dest_path(provided_path=None, skip_device={}):
|
||||||
dest = {}
|
dest = {}
|
||||||
|
|
||||||
|
|
@ -773,6 +840,23 @@ def update_progress(source):
|
||||||
with open(source['Progress Out'], 'w') as f:
|
with open(source['Progress Out'], 'w') as f:
|
||||||
f.writelines(output)
|
f.writelines(output)
|
||||||
|
|
||||||
|
def update_smart_report(source):
|
||||||
|
"""Update smart report file."""
|
||||||
|
if 'SMART Report' not in source:
|
||||||
|
source['SMART Report'] = '{}/smart_report.out'.format(
|
||||||
|
global_vars['LogDir'])
|
||||||
|
output = []
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
output.append('SMART Report')
|
||||||
|
output.append('TODO')
|
||||||
|
|
||||||
|
# Add line-endings
|
||||||
|
output = ['{}\n'.format(line) for line in output]
|
||||||
|
|
||||||
|
with open(source['SMART Report'], 'w') as f:
|
||||||
|
f.writelines(output)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print("This file is not meant to be called directly.")
|
print("This file is not meant to be called directly.")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue