bugfix: comprehensive stability audit and fixes

- discover/docker.py: handle comma-separated compose_file in labels
- discover/network.py: replace os.getlogin() with robust user detection
- target.py: add lsb_release fallback via hostnamectl, guard None compose_file,
  use container name (not cached CID) for docker logs
- main.py: call reset_state(mode='target') before target mode,
  improve EOF handling info message
- source.py: remove redundant set_stage('DONE') inside transfer_offer
- transfer.py: fix stage naming for resume after transfer
- add dry_run.py for local logic validation
This commit is contained in:
2026-05-22 20:58:37 +04:00
parent 6f3637795b
commit 97b3623915
5 changed files with 205 additions and 27 deletions
+44 -25
View File
@@ -28,9 +28,17 @@ def do_preflight():
state.set_stage("TARGET_PREFLIGHT")
# Ubuntu version
out = run("lsb_release -ds", check=False).stdout.strip()
info(f"OS: {out}")
version_match = re.search(r'(\d+\.\d+)', out)
try:
out = run("lsb_release -ds", check=False).stdout.strip()
except RuntimeError:
out = ""
if not out and exists("hostnamectl"):
try:
out = run("hostnamectl | grep 'Operating System'", check=False).stdout.strip()
except RuntimeError:
out = ""
info(f"OS: {out or 'не определено'}")
version_match = re.search(r'(\d+\.\d+)', out) or re.search(r'Ubuntu\s+(\d+\.\d+)', out, re.I)
ubuntu_version = version_match.group(1) if version_match else None
if not ubuntu_version:
warn("Не удалось определить версию Ubuntu. Продолжаем на свой риск.")
@@ -346,23 +354,27 @@ def do_verify():
# Docker compose up
cf = manifest["docker"].get("compose_file")
if cf and os.path.isfile(cf):
info("Запускаем docker compose up ...")
compose_dir = os.path.dirname(cf)
r = run(f"cd {compose_dir} \u0026\u0026 {sudo} docker compose up -d", check=False)
if r.returncode != 0:
print(f"\n{r.stdout}")
print(f"\n{r.stderr}")
state.set_error(
step="docker_compose_up",
stdout=r.stdout,
stderr=r.stderr,
suggestion="Проверьте compose-файл, доступность image, volumes. После исправления запустите: ./migrate --resume"
)
raise RuntimeError("docker compose up failed")
success("Docker compose up выполнен")
if cf:
cf_path = cf
if os.path.isfile(cf_path):
info("Запускаем docker compose up ...")
compose_dir = os.path.dirname(cf_path)
r = run(f"cd {compose_dir} && {sudo} docker compose up -d", check=False)
if r.returncode != 0:
print(f"\n{r.stdout}")
print(f"\n{r.stderr}")
state.set_error(
step="docker_compose_up",
stdout=r.stdout,
stderr=r.stderr,
suggestion="Проверьте compose-файл, доступность image, volumes. После исправления запустите: docker-migrate --resume"
)
raise RuntimeError("docker compose up failed")
success("Docker compose up выполнен")
else:
warn(f"Compose-файл из манифеста не найден на target: {cf_path}")
elif manifest["docker"].get("container_name"):
info("Compose не найден, пробуем docker run по параметрам контейнера ...")
info("Compose не найден, запуск по docker run не реализован. Используйте docker run вручную.")
# Sidecar units start
for u in manifest.get("systemd_units", []):
@@ -371,12 +383,19 @@ def do_verify():
run(f"{sudo} systemctl start {uname}", check=False)
info(f"Запущен unit: {uname}")
# Логи
cid = manifest["docker"].get("container_id")
if cid:
info("Последние логи контейнера:")
log_out = run(f"docker logs --tail 30 {cid[:12]}", check=False)
print(log_out.stdout)
# Логи — ищем контейнер по имени, а не по ID (ID с другого сервера)
cname = manifest["docker"].get("container_name")
if cname:
try:
out = run(f"docker ps -q -f name={cname}", check=False)
if out.stdout.strip():
info("Последние логи контейнера:")
log_out = run(f"docker logs --tail 30 {cname}", check=False)
print(log_out.stdout)
else:
warn(f"Контейнер '{cname}' пока не запущен, логи недоступны")
except Exception as e:
warn(f"Не удалось получить логи: {e}")
success("Верификация завершена. Сервис должен работать.")
state.set_stage("DONE")