Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move reboot out of lock #50

Merged
merged 3 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pleskdistup/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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))
130 changes: 69 additions & 61 deletions pleskdistup/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,84 +202,78 @@ 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,
status_file_path: PathType,
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:
Expand Down Expand Up @@ -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__":
Expand Down
Loading