109 lines
3.5 KiB
Python
109 lines
3.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
fsm.py — Конечный автомат (Finite State Machine) для миграции.
|
|
Каждый mode (source/target) имеет свой pipeline steps.
|
|
"""
|
|
|
|
from core import state
|
|
from core.color import header, subheader, success, error as cerror, warn, info, step
|
|
|
|
|
|
class FSM:
|
|
SOURCE_STEPS = [
|
|
"INIT",
|
|
"SOURCE_DISCOVER",
|
|
"SOURCE_MANIFEST_REVIEW",
|
|
"SOURCE_PACK",
|
|
"SOURCE_STOP_SERVICE",
|
|
"TRANSFER",
|
|
"DONE",
|
|
]
|
|
|
|
TARGET_STEPS = [
|
|
"INIT",
|
|
"TARGET_PREFLIGHT",
|
|
"TARGET_INSTALL",
|
|
"TARGET_BACKUP",
|
|
"TARGET_RESTORE",
|
|
"TARGET_VERIFY",
|
|
"DONE",
|
|
]
|
|
|
|
def __init__(self, mode="source"):
|
|
self.mode = mode
|
|
self.steps = self.SOURCE_STEPS if mode == "source" else self.TARGET_STEPS
|
|
|
|
def _index(self, stage):
|
|
try:
|
|
return self.steps.index(stage)
|
|
except ValueError:
|
|
return -1
|
|
|
|
def resume_from(self, stage):
|
|
idx = self._index(stage)
|
|
if idx < 0:
|
|
warn(f"Неизвестный stage '{stage}', начинаем с начала")
|
|
idx = 0
|
|
for s in self.steps[idx:]:
|
|
if state.is_completed(s):
|
|
info(f"Шаг {s} уже выполнен, пропускаем")
|
|
continue
|
|
self._run_step(s)
|
|
|
|
def _run_step(self, step_name):
|
|
header(f"ШАГ: {step_name}")
|
|
try:
|
|
if self.mode == "source":
|
|
self._source_step(step_name)
|
|
else:
|
|
self._target_step(step_name)
|
|
state.mark_completed(step_name)
|
|
state.set_stage(step_name)
|
|
except Exception as e:
|
|
msg = str(e)
|
|
cerror(f"Ошибка на шаге {step_name}: {msg}")
|
|
state.set_error(step_name, "", msg, suggestion="Исправьте проблему и запустите: ./migrate --resume")
|
|
raise
|
|
|
|
def _source_step(self, name):
|
|
if name == "INIT":
|
|
info("Инициализация source-режима")
|
|
elif name == "SOURCE_DISCOVER":
|
|
from source.source import do_discovery
|
|
do_discovery()
|
|
elif name == "SOURCE_MANIFEST_REVIEW":
|
|
from source.source import do_manifest_review
|
|
do_manifest_review()
|
|
elif name == "SOURCE_PACK":
|
|
from source.source import do_pack
|
|
do_pack()
|
|
elif name == "SOURCE_STOP_SERVICE":
|
|
from source.source import do_stop_service
|
|
do_stop_service()
|
|
elif name == "TRANSFER":
|
|
from transfer.transfer import do_transfer
|
|
do_transfer()
|
|
elif name == "DONE":
|
|
success("Source-режим завершён")
|
|
|
|
def _target_step(self, name):
|
|
if name == "INIT":
|
|
info("Инициализация target-режима")
|
|
elif name == "TARGET_PREFLIGHT":
|
|
from target.target import do_preflight
|
|
do_preflight()
|
|
elif name == "TARGET_INSTALL":
|
|
from target.target import do_install
|
|
do_install()
|
|
elif name == "TARGET_BACKUP":
|
|
from target.target import do_backup_existing
|
|
do_backup_existing()
|
|
elif name == "TARGET_RESTORE":
|
|
from target.target import do_restore
|
|
do_restore()
|
|
elif name == "TARGET_VERIFY":
|
|
from target.target import do_verify
|
|
do_verify()
|
|
elif name == "DONE":
|
|
success("Target-режим завершён")
|