Set working directory for ddrescue TUI
* If cloning use backup server share * If imaging use destination directory * If a preferred directory and fstype can't be used then warn the user
This commit is contained in:
parent
428d255538
commit
0f2007f5dc
2 changed files with 81 additions and 8 deletions
|
|
@ -7,11 +7,6 @@ import re
|
|||
from collections import OrderedDict
|
||||
|
||||
|
||||
# General
|
||||
MAP_DIR = '/Backups/ddrescue-tui'
|
||||
RECOMMENDED_FSTYPES = ['ext3', 'ext4', 'xfs']
|
||||
RECOMMENDED_MAP_FSTYPES = ['cifs', 'ext2', 'ext3', 'ext4', 'vfat', 'xfs']
|
||||
|
||||
# Layout
|
||||
TMUX_SIDE_WIDTH = 21
|
||||
TMUX_LAYOUT = OrderedDict({
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ PANE_RATIOS = (
|
|||
4, # Journal (kernel messages)
|
||||
)
|
||||
PLATFORM = std.PLATFORM
|
||||
RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$')
|
||||
RECOMMENDED_MAP_FSTYPES = re.compile(r'^(cifs|ext[234]|ntfs|vfat|xfs)$')
|
||||
SETTING_PRESETS = (
|
||||
'Default',
|
||||
'Fast',
|
||||
|
|
@ -76,7 +78,7 @@ class State():
|
|||
self.init_tmux()
|
||||
exe.start_thread(self.fix_tmux_layout_loop)
|
||||
|
||||
def confirm_selections(self, mode, prompt):
|
||||
def confirm_selections(self, mode, prompt, map_dir=None):
|
||||
"""Show selection details and prompt for confirmation."""
|
||||
report = []
|
||||
|
||||
|
|
@ -111,6 +113,26 @@ class State():
|
|||
)
|
||||
report.append(' ')
|
||||
|
||||
# Map dir
|
||||
if map_dir:
|
||||
report.append(std.color_string('Map Save Directory', 'GREEN'))
|
||||
report.append(str(map_dir))
|
||||
report.append(' ')
|
||||
if map_dir and not fstype_is_ok(map_dir, map_dir=True):
|
||||
report.append(
|
||||
std.color_string(
|
||||
'Map file(s) are being saved to a non-recommended filesystem.',
|
||||
'YELLOW',
|
||||
),
|
||||
)
|
||||
report.append(
|
||||
std.color_string(
|
||||
['This is strongly discouraged and may lead to', 'DATA LOSS'],
|
||||
[None, 'RED'],
|
||||
),
|
||||
)
|
||||
report.append(' ')
|
||||
|
||||
# Prompt user
|
||||
std.clear_screen()
|
||||
std.print_report(report)
|
||||
|
|
@ -201,7 +223,13 @@ class State():
|
|||
self.confirm_selections(mode, 'Are these selections correct?')
|
||||
|
||||
# Set working dir
|
||||
# TODO
|
||||
working_dir = get_working_dir(mode, self.destination)
|
||||
if working_dir:
|
||||
LOG.info('Set working directory to: %s', working_dir)
|
||||
os.chdir(working_dir)
|
||||
else:
|
||||
LOG.error('Failed to set preferred working directory')
|
||||
working_dir = pathlib.Path(os.getcwd())
|
||||
|
||||
# Add block pairs
|
||||
# NOTE: Destination is not updated
|
||||
|
|
@ -211,7 +239,7 @@ class State():
|
|||
# TODO
|
||||
|
||||
# Confirmation #2
|
||||
self.confirm_selections(mode, 'Start recovery?')
|
||||
self.confirm_selections(mode, 'Start recovery?', map_dir=working_dir)
|
||||
|
||||
# Prep destination
|
||||
# if cloning and not resuming format destination
|
||||
|
|
@ -512,6 +540,36 @@ def build_settings_menu(silent=True):
|
|||
return menu
|
||||
|
||||
|
||||
def fstype_is_ok(path, map_dir=False):
|
||||
"""Check if filesystem type is acceptable, returns bool."""
|
||||
is_ok = False
|
||||
fstype = None
|
||||
|
||||
# Get fstype
|
||||
if PLATFORM == 'Darwin':
|
||||
# TODO: leave as None for now
|
||||
pass
|
||||
elif PLATFORM == 'Linux':
|
||||
cmd = [
|
||||
'findmnt',
|
||||
'--noheadings',
|
||||
'--output', 'FSTYPE',
|
||||
'--target', path,
|
||||
]
|
||||
proc = exe.run_program(cmd, check=False)
|
||||
fstype = proc.stdout
|
||||
fstype = fstype.strip().lower()
|
||||
|
||||
# Check fstype
|
||||
if map_dir:
|
||||
is_ok = RECOMMENDED_MAP_FSTYPES.match(fstype)
|
||||
else:
|
||||
is_ok = RECOMMENDED_FSTYPES.match(fstype)
|
||||
|
||||
# Done
|
||||
return is_ok
|
||||
|
||||
|
||||
def get_object(path):
|
||||
"""Get object based on path, returns obj."""
|
||||
obj = None
|
||||
|
|
@ -547,6 +605,26 @@ def get_object(path):
|
|||
return obj
|
||||
|
||||
|
||||
def get_working_dir(mode, destination):
|
||||
"""Get working directory using mode and destination, returns path."""
|
||||
working_dir = None
|
||||
if mode == 'Clone':
|
||||
net.mount_backup_shares(read_write=True)
|
||||
for server in cfg.net.BACKUP_SERVERS:
|
||||
path = pathlib.Path(f'/Backups/{server}')
|
||||
if path.exists() and fstype_is_ok(path, map_dir=True):
|
||||
# Acceptable path found
|
||||
working_dir = path
|
||||
break
|
||||
else:
|
||||
path = pathlib.Path(destination).resolve()
|
||||
if path.exists() and fstype_is_ok(path, map_dir=False):
|
||||
working_dir = path
|
||||
|
||||
# Done
|
||||
return working_dir
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function for ddrescue TUI."""
|
||||
args = docopt(DOCSTRING)
|
||||
|
|
|
|||
Loading…
Reference in a new issue