fdm/deploy/upgrade.py

63 lines
2.8 KiB
Python

import getpass
import hashlib
from datetime import datetime, timezone
from pathlib import Path
import paramiko
root = Path(__file__).resolve().parent.parent
client = paramiko.SSHClient()
client.load_host_keys(str(Path.home() / ".ssh" / "known_hosts"))
client.connect("47.108.78.12", username="root", password=getpass.getpass("SSH password: "), timeout=20)
def run(command):
print(command, flush=True)
_, stdout, stderr = client.exec_command(command, timeout=120)
output = stdout.read().decode() + stderr.read().decode()
print(output, flush=True)
if stdout.channel.recv_exit_status():
raise RuntimeError("部署命令失败,保留已有版本和备份")
return output.strip()
switched = False
previous = ""
try:
run("nginx -t && systemctl is-active nginx && df -h /opt && ss -ltnp '( sport = :9999 or sport = :19999 )'")
previous = run("readlink -f /opt/fdm/current || true")
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
release = f"/opt/fdm/releases/{stamp}"
backup = f"/var/backups/fdm/{stamp}"
run(f'install -d -m 755 {release} {backup} && cp -a /etc/nginx/conf.d/fdm-cdis.conf {backup}/')
sftp = client.open_sftp()
binary = root / "artifacts/fdm-studio"
sftp.put(str(binary), release + "/fdm-studio")
sftp.chmod(release + "/fdm-studio", 0o755)
expected = hashlib.sha256(binary.read_bytes()).hexdigest()
run(f"echo '{expected} {release}/fdm-studio' | sha256sum -c -")
sftp.put(str(root / "deploy/fdm-studio.service"), "/etc/systemd/system/fdm-studio.service")
sftp.put(str(root / 'deploy/nginx-cdis-http.conf'), release + '/nginx-http.conf')
run("systemctl daemon-reload")
run(f"systemd-run --unit=fdm-candidate-{stamp.lower()} --property=DynamicUser=yes {release}/fdm-studio -listen 127.0.0.1:19999")
run("sleep 2 && curl -fsS http://127.0.0.1:19999/healthz")
run(f"systemctl stop fdm-candidate-{stamp.lower()}")
switched = True
run(f"ln -sfn {release} /opt/fdm/current")
run(f'cp {release}/nginx-http.conf /etc/nginx/conf.d/fdm-cdis.conf && nginx -t && systemctl reload nginx')
run("sleep 3 && systemctl enable fdm-studio && systemctl restart fdm-studio && sleep 3 && systemctl is-active fdm-studio")
run('curl -fsS http://127.0.0.1:9999/healthz && curl -fsS --resolve cdis.cn:443:127.0.0.1 https://cdis.cn/healthz')
run("systemctl is-enabled certbot.timer || true")
sftp.close()
print("部署完成:" + release, flush=True)
except Exception:
if switched:
print("切换验证失败,恢复先前配置", flush=True)
run("systemctl stop fdm-studio || true")
if previous:
run(f"ln -sfn {previous} /opt/fdm/current && systemctl start fdm-studio")
run(f'cp {backup}/fdm-cdis.conf /etc/nginx/conf.d/fdm-cdis.conf && nginx -t && systemctl reload nginx')
raise
finally:
client.close()