Updated select_device() to use DevObj()
* Also fixed child/parent check(s) * Removed menu_select_device() since code was moved into select_device()
This commit is contained in:
parent
03bdb4b4b7
commit
ccf7f0686e
1 changed files with 51 additions and 116 deletions
|
|
@ -164,8 +164,8 @@ class DevObj(BaseObj):
|
||||||
self.path))
|
self.path))
|
||||||
if self.parent:
|
if self.parent:
|
||||||
print_warning('"{}" is a child device.'.format(self.path))
|
print_warning('"{}" is a child device.'.format(self.path))
|
||||||
if ask('Use parent device "{}" instead?'.format(self.parent):
|
if ask('Use parent device "{}" instead?'.format(self.parent)):
|
||||||
self.path = os.path.realpath(path)
|
self.path = os.path.realpath(self.parent)
|
||||||
self.set_details()
|
self.set_details()
|
||||||
|
|
||||||
def set_details(self):
|
def set_details(self):
|
||||||
|
|
@ -576,17 +576,17 @@ def menu_ddrescue(source_path, dest_path, run_mode):
|
||||||
dest = None
|
dest = None
|
||||||
if source_path:
|
if source_path:
|
||||||
source = create_path_obj(source_path)
|
source = create_path_obj(source_path)
|
||||||
|
else:
|
||||||
|
source = select_device('source')
|
||||||
|
source.self_check()
|
||||||
if dest_path:
|
if dest_path:
|
||||||
dest = create_path_obj(dest_path)
|
dest = create_path_obj(dest_path)
|
||||||
|
else:
|
||||||
# Show selection menus (if necessary)
|
|
||||||
if not source:
|
|
||||||
source = select_device('source')
|
|
||||||
if not dest:
|
|
||||||
if run_mode == 'clone':
|
if run_mode == 'clone':
|
||||||
dest = select_device('destination', skip_device=source)
|
dest = select_device('destination', skip_device=source)
|
||||||
else:
|
else:
|
||||||
dest = select_directory()
|
dest = select_directory()
|
||||||
|
dest.self_check()
|
||||||
|
|
||||||
# Build BlockPairs
|
# Build BlockPairs
|
||||||
state = RecoveryState(run_mode)
|
state = RecoveryState(run_mode)
|
||||||
|
|
@ -796,58 +796,6 @@ def menu_select_children(source):
|
||||||
return selected_children
|
return selected_children
|
||||||
|
|
||||||
|
|
||||||
def menu_select_device(title='Which device?', skip_device={}):
|
|
||||||
"""Select block device via a menu, returns dev_path as str."""
|
|
||||||
skip_names = [
|
|
||||||
skip_device.get('name', None), skip_device.get('pkname', None)]
|
|
||||||
skip_names = [n for n in skip_names if n]
|
|
||||||
try:
|
|
||||||
cmd = (
|
|
||||||
'lsblk',
|
|
||||||
'--json',
|
|
||||||
'--nodeps',
|
|
||||||
'--output-all',
|
|
||||||
'--paths')
|
|
||||||
result = run_program(cmd)
|
|
||||||
json_data = json.loads(result.stdout.decode())
|
|
||||||
except CalledProcessError:
|
|
||||||
raise GenericError(
|
|
||||||
'Failed to get device details for {}'.format(dev_path))
|
|
||||||
|
|
||||||
# Build menu
|
|
||||||
dev_options = []
|
|
||||||
for dev in json_data['blockdevices']:
|
|
||||||
# Disable dev if in skip_names
|
|
||||||
disable_dev = dev['name'] in skip_names or dev['pkname'] in skip_names
|
|
||||||
|
|
||||||
# Append non-matching devices
|
|
||||||
dev_options.append({
|
|
||||||
'Name': '{name:12} {tran:5} {size:6} {model} {serial}'.format(
|
|
||||||
name=dev['name'],
|
|
||||||
tran=dev['tran'] if dev['tran'] else '',
|
|
||||||
size=dev['size'] if dev['size'] else '',
|
|
||||||
model=dev['model'] if dev['model'] else '',
|
|
||||||
serial=dev['serial'] if dev['serial'] else ''),
|
|
||||||
'Path': dev['name'],
|
|
||||||
'Disabled': disable_dev})
|
|
||||||
dev_options = sorted(dev_options, key=itemgetter('Name'))
|
|
||||||
if not dev_options:
|
|
||||||
raise GenericError('No devices available.')
|
|
||||||
|
|
||||||
# Show Menu
|
|
||||||
actions = [{'Name': 'Quit', 'Letter': 'Q'}]
|
|
||||||
selection = menu_select(
|
|
||||||
title=title,
|
|
||||||
main_entries=dev_options,
|
|
||||||
action_entries=actions,
|
|
||||||
disabled_label='SOURCE DEVICE')
|
|
||||||
|
|
||||||
if selection.isnumeric():
|
|
||||||
return dev_options[int(selection)-1]['Path']
|
|
||||||
elif selection == 'Q':
|
|
||||||
raise GenericAbort()
|
|
||||||
|
|
||||||
|
|
||||||
def menu_select_path(skip_device={}):
|
def menu_select_path(skip_device={}):
|
||||||
"""Select path via menu, returns path as str."""
|
"""Select path via menu, returns path as str."""
|
||||||
pwd = os.path.realpath(global_vars['Env']['PWD'])
|
pwd = os.path.realpath(global_vars['Env']['PWD'])
|
||||||
|
|
@ -1134,67 +1082,54 @@ def select_dest_path(provided_path=None, skip_device={}):
|
||||||
return dest
|
return dest
|
||||||
|
|
||||||
|
|
||||||
def select_device(description='device', provided_path=None,
|
def select_device(description='device', skip_device=None):
|
||||||
skip_device={}, allow_image_file=True):
|
"""Select device via a menu, returns DevObj."""
|
||||||
"""Select device via provided path or menu, return dev as dict."""
|
cmd = (
|
||||||
dev = {'Is Dir': False, 'Is Image': False}
|
'lsblk',
|
||||||
|
'--json',
|
||||||
|
'--nodeps',
|
||||||
|
'--output-all',
|
||||||
|
'--paths')
|
||||||
|
result = run_program(cmd)
|
||||||
|
json_data = json.loads(result.stdout.decode())
|
||||||
|
skip_names = []
|
||||||
|
if skip_device:
|
||||||
|
skip_names.append(skip_device.path)
|
||||||
|
if skip_device.parent:
|
||||||
|
skip_names.append(skip_device.parent)
|
||||||
|
|
||||||
# Set path
|
# Build menu
|
||||||
if provided_path:
|
dev_options = []
|
||||||
dev['Path'] = provided_path
|
for dev in json_data['blockdevices']:
|
||||||
else:
|
# Disable dev if in skip_names
|
||||||
dev['Path'] = menu_select_device(
|
disabled = dev['name'] in skip_names or dev['pkname'] in skip_names
|
||||||
title='Please select a {}'.format(description),
|
|
||||||
skip_device=skip_device)
|
|
||||||
dev['Path'] = os.path.realpath(dev['Path'])
|
|
||||||
|
|
||||||
# Check path
|
# Add to options
|
||||||
if pathlib.Path(dev['Path']).is_block_device():
|
dev_options.append({
|
||||||
dev['Dev Path'] = dev['Path']
|
'Name': '{name:12} {tran:5} {size:6} {model} {serial}'.format(
|
||||||
elif allow_image_file and pathlib.Path(dev['Path']).is_file():
|
name=dev['name'],
|
||||||
dev['Dev Path'] = setup_loopback_device(dev['Path'])
|
tran=dev['tran'] if dev['tran'] else '',
|
||||||
dev['Is Image'] = True
|
size=dev['size'] if dev['size'] else '',
|
||||||
else:
|
model=dev['model'] if dev['model'] else '',
|
||||||
raise GenericError('Invalid {} "{}"'.format(description, dev['Path']))
|
serial=dev['serial'] if dev['serial'] else ''),
|
||||||
|
'Dev': DevObj(dev['name']),
|
||||||
|
'Disabled': disabled})
|
||||||
|
dev_options = sorted(dev_options, key=itemgetter('Name'))
|
||||||
|
if not dev_options:
|
||||||
|
raise GenericError('No devices available.')
|
||||||
|
|
||||||
# Get device details
|
# Show Menu
|
||||||
dev['Details'] = get_device_details(dev['Dev Path'])
|
actions = [{'Name': 'Quit', 'Letter': 'Q'}]
|
||||||
if 'Children' not in dev:
|
selection = menu_select(
|
||||||
dev['Children'] = []
|
title='Please select the {} device'.format(description),
|
||||||
|
main_entries=dev_options,
|
||||||
|
action_entries=actions,
|
||||||
|
disabled_label='ALREADY SELECTED')
|
||||||
|
|
||||||
# Check for parent device(s)
|
if selection.isnumeric():
|
||||||
while dev['Details']['pkname']:
|
return dev_options[int(selection)-1]['Dev']
|
||||||
print_warning('{} "{}" is a child device.'.format(
|
elif selection == 'Q':
|
||||||
description.title(), dev['Dev Path']))
|
raise GenericAbort()
|
||||||
if ask('Use parent device "{}" instead?'.format(
|
|
||||||
dev['Details']['pkname'])):
|
|
||||||
# Update dev with parent info
|
|
||||||
dev['Dev Path'] = dev['Details']['pkname']
|
|
||||||
dev['Details'] = get_device_details(dev['Dev Path'])
|
|
||||||
else:
|
|
||||||
# Leave alone
|
|
||||||
break
|
|
||||||
|
|
||||||
# Set display name
|
|
||||||
if dev['Is Image']:
|
|
||||||
dev['Display Name'] = dev['Path']
|
|
||||||
else:
|
|
||||||
dev['Display Name'] = '{name} {size} {model}'.format(
|
|
||||||
**dev['Details'])
|
|
||||||
result = run_program(['tput', 'cols'])
|
|
||||||
width = int(
|
|
||||||
(int(result.stdout.decode().strip()) - SIDE_PANE_WIDTH) / 2) - 2
|
|
||||||
if len(dev['Display Name']) > width:
|
|
||||||
if dev['Is Image']:
|
|
||||||
dev['Display Name'] = '...{}'.format(
|
|
||||||
dev['Display Name'][-(width-3):])
|
|
||||||
else:
|
|
||||||
dev['Display Name'] = '{}...'.format(
|
|
||||||
dev['Display Name'][:(width-3)])
|
|
||||||
else:
|
|
||||||
dev['Display Name'] = dev['Display Name']
|
|
||||||
|
|
||||||
return dev
|
|
||||||
|
|
||||||
|
|
||||||
def setup_loopback_device(source_path):
|
def setup_loopback_device(source_path):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue