diff --git a/pleskdistup/convert.py b/pleskdistup/convert.py index 7792af2..e9807c3 100644 --- a/pleskdistup/convert.py +++ b/pleskdistup/convert.py @@ -47,12 +47,15 @@ def start_flow( # Unfortunately, dataclasses available since Python 3.7 aren't supported # on Ubuntu 18 (Python 3.6) class ConvertResult: + success: bool reboot_requested: bool def __init__( self, + success: bool = True, reboot_requested: bool = False, ): + self.success = success self.reboot_requested = reboot_requested def __repr__(self) -> str: @@ -74,4 +77,4 @@ def convert( start_flow(flow, status_file_path, time_exceeded_msg) if flow.is_failed(): raise RuntimeError(flow.get_error()) - return ConvertResult(reboot_requested=(flow.reboot_requested is not None)) + return ConvertResult(success=True, reboot_requested=(flow.reboot_requested is not None)) diff --git a/pleskdistup/main.py b/pleskdistup/main.py index 18d5cc6..bc3a4f3 100644 --- a/pleskdistup/main.py +++ b/pleskdistup/main.py @@ -202,6 +202,21 @@ def find_duplicate_actions( return None +def print_plan( + actions_map: typing.Dict[str, typing.List[action.ActiveAction]], + options: typing.Any, +) -> pleskdistup.convert.ConvertResult: + for stage_id, actions in actions_map.items(): + if not options.show_hidden_stages and stage_id.startswith("_"): + continue + print(f"Stage {stage_id!r}:") + for act in actions: + if not options.show_hidden_stages and act.name.startswith("_"): + continue + print(f"- {act.name}") + return pleskdistup.convert.ConvertResult(success=True, reboot_requested=False) + + def do_convert( upgrader: DistUpgrader, options: typing.Any, @@ -209,77 +224,56 @@ def do_convert( logfile_path: PathType, util_name: str, show_plan: bool, -) -> int: +) -> pleskdistup.convert.ConvertResult: if not options.resume and not options.phase == Phase.REVERT and not required_conditions_satisfied(upgrader, options, options.phase): printerr("Conversion can't be performed due to the problems noted above") if not show_plan: - return 1 + return pleskdistup.convert.ConvertResult(success=False, reboot_requested=False) actions_map = upgrader.construct_actions(sys.argv[0], options, options.phase) dup = find_duplicate_actions(actions_map) if dup: printerr(f"Stage {dup[0]!r} contains duplicate actions: {dup[1]}") - return 1 + return pleskdistup.convert.ConvertResult(success=False, reboot_requested=False) - if not show_plan: - resume_tracker = ResumeTracker(options.resume_data, options.resume_path) - if options.resume: - # Restore status flag in resume mode (it could be removed by - # plesk.send_conversion_status() called by handle_error() in - # case of error) - if not os.path.exists(options.status_flag_path): - log.debug(f"Restoring lost status flag at {options.status_flag_path!r} due to resume mode") - plesk.prepare_conversion_flag(options.status_flag_path) - else: - # Write initial resume file - resume_tracker() + if show_plan: + return print_plan(actions_map, options) - try: - convert_result = pleskdistup.convert.convert( - options.phase, - options.resume_stage, - actions_map, - options.state_dir, - status_file_path, - messages.TIME_EXCEEDED_MESSAGE.format(logfile_path=logfile_path), - resume_tracker, - ) - if not options.no_reboot and convert_result.reboot_requested: - log.info("Going to reboot the system") - if options.phase is Phase.CONVERT: - print( - messages.CONVERT_RESTART_MESSAGE.format( - time=datetime.now().strftime("%H:%M:%S"), - util_path=os.path.abspath(sys.argv[0]) - ), - end='', - ) - elif options.phase is Phase.FINISH: - print(messages.FINISH_RESTART_MESSAGE, end='') - systemd.do_reboot() - except (UnicodeEncodeError, UnicodeDecodeError) as e: - if locale.getpreferredencoding(False).lower() != "utf-8": - printerr(messages.ENCODING_INCONSISTENCY_ERROR_MESSAGE) - - handle_error(str(e), logfile_path, util_name, options.status_flag_path, options.phase, upgrader) - return 1 - except Exception as e: - handle_error(str(e), logfile_path, util_name, options.status_flag_path, options.phase, upgrader) - return 1 + resume_tracker = ResumeTracker(options.resume_data, options.resume_path) + if options.resume: + # Restore status flag in resume mode (it could be removed by + # plesk.send_conversion_status() called by handle_error() in + # case of error) + if not os.path.exists(options.status_flag_path): + log.debug(f"Restoring lost status flag at {options.status_flag_path!r} due to resume mode") + plesk.prepare_conversion_flag(options.status_flag_path) else: - for stage_id, actions in actions_map.items(): - if not options.show_hidden_stages and stage_id.startswith("_"): - continue - print(f"Stage {stage_id!r}:") - for act in actions: - if not options.show_hidden_stages and act.name.startswith("_"): - continue - print(f"- {act.name}") + # Write initial resume file + resume_tracker() - if options.phase == Phase.REVERT: - print(messages.REVERT_FINISHED_MESSAGE, end='') + try: + convert_result = pleskdistup.convert.convert( + options.phase, + options.resume_stage, + actions_map, + options.state_dir, + status_file_path, + messages.TIME_EXCEEDED_MESSAGE.format(logfile_path=logfile_path), + resume_tracker, + ) + if options.phase == Phase.REVERT: + print(messages.REVERT_FINISHED_MESSAGE, end='') + return convert_result + + except (UnicodeEncodeError, UnicodeDecodeError) as e: + if locale.getpreferredencoding(False).lower() != "utf-8": + printerr(messages.ENCODING_INCONSISTENCY_ERROR_MESSAGE) - return 0 + handle_error(str(e), logfile_path, util_name, options.status_flag_path, options.phase, upgrader) + return pleskdistup.convert.ConvertResult(success=False, reboot_requested=False) + except Exception as e: + handle_error(str(e), logfile_path, util_name, options.status_flag_path, options.phase, upgrader) + return pleskdistup.convert.ConvertResult(success=False, reboot_requested=False) def read_resume_data(resume_path: PathType) -> ResumeData: @@ -590,15 +584,29 @@ def main(): options.status_flag_path = os.path.join(options.state_dir, "dist-upgrade-conversion.flag") options.completion_flag_path = os.path.join(options.state_dir, "dist-upgrade-done.flag") - convert_res = do_convert(upgrader, options, status_file_path, logfile_path, util_name, options.show_plan) - if convert_res == 0 and os.path.exists(options.completion_flag_path): + convert_result = do_convert(upgrader, options, status_file_path, logfile_path, util_name, options.show_plan) + if convert_result is not None and convert_result.success and os.path.exists(options.completion_flag_path): log.info("Dist-upgrade process completed, cleaning up...") if os.path.exists(options.resume_path): os.unlink(options.resume_path) log.debug(f"Removed the resume file {options.resume_path!r}") os.unlink(options.completion_flag_path) - return convert_res + if not options.no_reboot and convert_result.reboot_requested: + log.info("Going to reboot the system") + if options.phase is Phase.CONVERT: + print( + messages.CONVERT_RESTART_MESSAGE.format( + time=datetime.now().strftime("%H:%M:%S"), + util_path=os.path.abspath(sys.argv[0]) + ), + end='', + ) + elif options.phase is Phase.FINISH: + print(messages.FINISH_RESTART_MESSAGE, end='') + systemd.do_reboot() + + return 0 if convert_result.success else 1 if __name__ == "__main__":