Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
0af8be2c47
5 changed files with 52 additions and 52 deletions
|
|
@ -87,11 +87,6 @@ REGEX_REMAINING_TIME = re.compile(
|
||||||
r'\s*(?P<na>n/a)?',
|
r'\s*(?P<na>n/a)?',
|
||||||
re.IGNORECASE
|
re.IGNORECASE
|
||||||
)
|
)
|
||||||
PANE_RATIOS = (
|
|
||||||
12, # SMART
|
|
||||||
22, # ddrescue progress
|
|
||||||
4, # Journal (kernel messages)
|
|
||||||
)
|
|
||||||
PLATFORM = std.PLATFORM
|
PLATFORM = std.PLATFORM
|
||||||
RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$')
|
RECOMMENDED_FSTYPES = re.compile(r'^(ext[234]|ntfs|xfs)$')
|
||||||
if PLATFORM == 'Darwin':
|
if PLATFORM == 'Darwin':
|
||||||
|
|
@ -2094,19 +2089,22 @@ def run_ddrescue(state, block_pair, pass_name, settings, dry_run=True) -> None:
|
||||||
'Press Enter to return to main menu...', end='', flush=True,
|
'Press Enter to return to main menu...', end='', flush=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _update_smart_pane() -> None:
|
def _update_smart_panes() -> None:
|
||||||
"""Update SMART pane every 30 seconds."""
|
"""Update SMART panes every 30 seconds."""
|
||||||
update_smart_details(state.source)
|
|
||||||
now = datetime.datetime.now(tz=TIMEZONE).strftime('%Y-%m-%d %H:%M %Z')
|
now = datetime.datetime.now(tz=TIMEZONE).strftime('%Y-%m-%d %H:%M %Z')
|
||||||
with open(f'{state.log_dir}/smart.out', 'w', encoding='utf-8') as _f:
|
for dev_str in ('source', 'destination'):
|
||||||
_f.write(
|
dev = getattr(state, dev_str)
|
||||||
ansi.color_string(
|
out_path = f'{state.log_dir}/smart_{dev_str}.out'
|
||||||
['SMART Attributes', f'Updated: {now}\n'],
|
update_smart_details(dev)
|
||||||
['BLUE', 'YELLOW'],
|
with open(out_path, 'w', encoding='utf-8') as _f:
|
||||||
sep='\t\t',
|
_f.write(
|
||||||
),
|
ansi.color_string(
|
||||||
)
|
['SMART Attributes', f'Updated: {now}\n'],
|
||||||
_f.write('\n'.join(state.source.generate_report(header=False)))
|
['BLUE', 'YELLOW'],
|
||||||
|
sep='\t\t',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
_f.write('\n'.join(dev.generate_report(header=False)))
|
||||||
|
|
||||||
# Dry run
|
# Dry run
|
||||||
if dry_run:
|
if dry_run:
|
||||||
|
|
@ -2129,7 +2127,7 @@ def run_ddrescue(state, block_pair, pass_name, settings, dry_run=True) -> None:
|
||||||
while True:
|
while True:
|
||||||
if _i % 30 == 0:
|
if _i % 30 == 0:
|
||||||
# Update SMART pane
|
# Update SMART pane
|
||||||
_update_smart_pane()
|
_update_smart_panes()
|
||||||
|
|
||||||
# Check destination
|
# Check destination
|
||||||
warning_message = check_destination_health(state.destination)
|
warning_message = check_destination_health(state.destination)
|
||||||
|
|
@ -2226,7 +2224,12 @@ def run_recovery(state: State, main_menu, settings_menu, dry_run=True) -> None:
|
||||||
state.ui.add_info_pane(
|
state.ui.add_info_pane(
|
||||||
percent=50,
|
percent=50,
|
||||||
update_layout=False,
|
update_layout=False,
|
||||||
watch_file=f'{state.log_dir}/smart.out',
|
watch_file=f'{state.log_dir}/smart_source.out',
|
||||||
|
)
|
||||||
|
state.ui.add_info_pane(
|
||||||
|
percent=50,
|
||||||
|
update_layout=False,
|
||||||
|
watch_file=f'{state.log_dir}/smart_destination.out',
|
||||||
)
|
)
|
||||||
if PLATFORM == 'Linux':
|
if PLATFORM == 'Linux':
|
||||||
state.ui.add_worker_pane(lines=4, cmd='journal-datarec-monitor')
|
state.ui.add_worker_pane(lines=4, cmd='journal-datarec-monitor')
|
||||||
|
|
|
||||||
|
|
@ -56,18 +56,12 @@ class Disk:
|
||||||
ssd: bool = field(init=False)
|
ssd: bool = field(init=False)
|
||||||
tests: list[Test] = field(init=False, default_factory=list)
|
tests: list[Test] = field(init=False, default_factory=list)
|
||||||
trim: bool = field(init=False)
|
trim: bool = field(init=False)
|
||||||
use_sat: bool = field(init=False, default=False)
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.path = pathlib.Path(self.path_str).resolve()
|
self.path = pathlib.Path(self.path_str).resolve()
|
||||||
self.update_details()
|
self.update_details()
|
||||||
self.set_description()
|
self.set_description()
|
||||||
self.known_attributes = get_known_disk_attributes(self.model)
|
self.known_attributes = get_known_disk_attributes(self.model)
|
||||||
if not self.attributes and self.bus == 'USB':
|
|
||||||
# Try using SAT
|
|
||||||
LOG.warning('Using SAT for smartctl for %s', self.path)
|
|
||||||
self.notes = []
|
|
||||||
self.use_sat = True
|
|
||||||
self.initial_attributes = copy.deepcopy(self.attributes)
|
self.initial_attributes = copy.deepcopy(self.attributes)
|
||||||
if not self.is_4k_aligned():
|
if not self.is_4k_aligned():
|
||||||
self.add_note('One or more partitions are not 4K aligned', 'YELLOW')
|
self.add_note('One or more partitions are not 4K aligned', 'YELLOW')
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ def enable_smart(dev) -> None:
|
||||||
cmd = [
|
cmd = [
|
||||||
'sudo',
|
'sudo',
|
||||||
'smartctl',
|
'smartctl',
|
||||||
f'--device={"sat,auto" if dev.use_sat else "auto"}',
|
'--device=auto',
|
||||||
'--tolerance=permissive',
|
'--tolerance=permissive',
|
||||||
'--smart=on',
|
'--smart=on',
|
||||||
dev.path,
|
dev.path,
|
||||||
|
|
@ -461,7 +461,7 @@ def update_smart_details(dev) -> None:
|
||||||
cmd = [
|
cmd = [
|
||||||
'sudo',
|
'sudo',
|
||||||
'smartctl',
|
'smartctl',
|
||||||
f'--device={"sat,auto" if dev.use_sat else "auto"}',
|
'--device=auto',
|
||||||
'--tolerance=verypermissive',
|
'--tolerance=verypermissive',
|
||||||
'--all',
|
'--all',
|
||||||
'--json',
|
'--json',
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ def fix_layout(
|
||||||
avail_vertical -= layout[group].get('height', 0) + 1
|
avail_vertical -= layout[group].get('height', 0) + 1
|
||||||
num_workers = len(layout['Workers']['Panes'])
|
num_workers = len(layout['Workers']['Panes'])
|
||||||
avail_vertical -= num_workers * (layout['Workers'].get('height', 0) + 1)
|
avail_vertical -= num_workers * (layout['Workers'].get('height', 0) + 1)
|
||||||
avail_horizontal -= layout['Started']['width'] + 1
|
avail_horizontal -= layout['Progress']['width'] + 1
|
||||||
|
|
||||||
# Fix heights
|
# Fix heights
|
||||||
for group, data in layout.items():
|
for group, data in layout.items():
|
||||||
|
|
@ -89,16 +89,17 @@ def fix_layout(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fix widths
|
# Fix widths
|
||||||
for group in ('Started', 'Progress'):
|
resize_kwargs.append(
|
||||||
resize_kwargs.append(
|
{'pane_id': layout['Progress']['Panes'][0], 'width': layout['Progress']['width']}
|
||||||
{'pane_id': layout[group]['Panes'][0], 'width': layout[group]['width']}
|
)
|
||||||
)
|
resize_kwargs.append(
|
||||||
|
{'pane_id': layout['Started']['Panes'][0], 'height': layout['Started']['height']}
|
||||||
|
)
|
||||||
for group, data in layout.items():
|
for group, data in layout.items():
|
||||||
num_panes = len(data['Panes'])
|
num_panes = len(data['Panes'])
|
||||||
if num_panes < 2 or group not in ('Title', 'Subtitle', 'Info'):
|
if num_panes < 2 or group not in ('Title', 'Subtitle', 'Info'):
|
||||||
continue
|
continue
|
||||||
avail_horizontal -= (num_panes - 1)
|
pane_width, remainder = divmod(avail_horizontal - (num_panes-1), num_panes)
|
||||||
pane_width, remainder = divmod(avail_horizontal, num_panes)
|
|
||||||
for pane_id in data['Panes']:
|
for pane_id in data['Panes']:
|
||||||
new_width = pane_width
|
new_width = pane_width
|
||||||
if remainder > 0:
|
if remainder > 0:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ TMUX_LAYOUT = { # NOTE: This needs to be in order from top to bottom
|
||||||
'Info': {'Panes': []},
|
'Info': {'Panes': []},
|
||||||
'Current': {'Panes': [environ.get('TMUX_PANE', None)]},
|
'Current': {'Panes': [environ.get('TMUX_PANE', None)]},
|
||||||
'Workers': {'Panes': []},
|
'Workers': {'Panes': []},
|
||||||
'Started': {'Panes': [], 'width': TMUX_SIDE_WIDTH},
|
'Started': {'Panes': [], 'height': TMUX_TITLE_HEIGHT},
|
||||||
'Progress': {'Panes': [], 'width': TMUX_SIDE_WIDTH},
|
'Progress': {'Panes': [], 'width': TMUX_SIDE_WIDTH},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,6 +204,25 @@ class TUI():
|
||||||
self.layout.clear()
|
self.layout.clear()
|
||||||
self.layout.update(deepcopy(TMUX_LAYOUT))
|
self.layout.update(deepcopy(TMUX_LAYOUT))
|
||||||
|
|
||||||
|
# Progress
|
||||||
|
self.layout['Progress']['Panes'].append(tmux.split_window(
|
||||||
|
lines=TMUX_SIDE_WIDTH,
|
||||||
|
text=' ',
|
||||||
|
))
|
||||||
|
|
||||||
|
# Started
|
||||||
|
self.layout['Started']['Panes'].append(tmux.split_window(
|
||||||
|
behind=True,
|
||||||
|
lines=2,
|
||||||
|
target_id=self.layout['Progress']['Panes'][0],
|
||||||
|
text=ansi.color_string(
|
||||||
|
['Started', time.strftime("%Y-%m-%d %H:%M %Z")],
|
||||||
|
['BLUE', None],
|
||||||
|
sep='\n',
|
||||||
|
),
|
||||||
|
vertical=True,
|
||||||
|
))
|
||||||
|
|
||||||
# Title
|
# Title
|
||||||
self.layout['Title']['Panes'].append(tmux.split_window(
|
self.layout['Title']['Panes'].append(tmux.split_window(
|
||||||
behind=True,
|
behind=True,
|
||||||
|
|
@ -216,23 +235,6 @@ class TUI():
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
|
||||||
# Started
|
|
||||||
self.layout['Started']['Panes'].append(tmux.split_window(
|
|
||||||
lines=TMUX_SIDE_WIDTH,
|
|
||||||
target_id=self.layout['Title']['Panes'][0],
|
|
||||||
text=ansi.color_string(
|
|
||||||
['Started', time.strftime("%Y-%m-%d %H:%M %Z")],
|
|
||||||
['BLUE', None],
|
|
||||||
sep='\n',
|
|
||||||
),
|
|
||||||
))
|
|
||||||
|
|
||||||
# Progress
|
|
||||||
self.layout['Progress']['Panes'].append(tmux.split_window(
|
|
||||||
lines=TMUX_SIDE_WIDTH,
|
|
||||||
text=' ',
|
|
||||||
))
|
|
||||||
|
|
||||||
def remove_all_info_panes(self) -> None:
|
def remove_all_info_panes(self) -> None:
|
||||||
"""Remove all info panes and update layout."""
|
"""Remove all info panes and update layout."""
|
||||||
self.layout['Info'].pop('height', None)
|
self.layout['Info'].pop('height', None)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue