""" Luồng SSH cho chế độ "Update Firmware" (thiết bị đã cài sẵn OpenWrt). Đặc điểm: - Thiết bị đang chạy bình thường, SSH đã mở sẵn với pass đã biết. - Không có bước Telnet / đặt lại mật khẩu. - Kết nối trực tiếp → upload SCP → verify → sync + sysupgrade. Public API: flash_device_update_ssh(ip, firmware_path, user, password, backup_password, status_cb) """ import time import paramiko from core.ssh_utils import ( _create_ssh_client, _upload_firmware, _verify_firmware, _sync_and_sysupgrade, ) def flash_device_update_ssh(ip, firmware_path, user="root", password="admin123a", backup_password="", status_cb=None): """ Cập nhật firmware lên thiết bị OpenWrt đang chạy qua SSH / sysupgrade. Luồng: 1. Kết nối SSH (thử password, nếu lỗi auth thử backup_password) 2. Upload firmware qua SCP lên /tmp/ 3. Verify file tồn tại 4. sync + sysupgrade Args: ip : địa chỉ IP thiết bị firmware_path : đường dẫn file .bin trên máy tính user : SSH username (mặc định "root") password : SSH password chính backup_password : SSH password dự phòng nếu password chính sai status_cb : callback(str) để cập nhật trạng thái lên UI Returns: "DONE" — update thành công "FAIL: …" — thất bại, kèm lý do """ # ── STEP 1: Kết nối SSH ───────────────────────────────────────── if status_cb: status_cb("Connecting SSH...") client = None # Thử password chính trước try: client = _create_ssh_client(ip, user, password) except paramiko.AuthenticationException: # Thử backup_password nếu có if backup_password: try: client = _create_ssh_client(ip, user, backup_password) except paramiko.AuthenticationException: return "FAIL: SSH authentication failed (wrong password)" except paramiko.SSHException as e: return f"FAIL: SSH error — {e}" except Exception as e: return f"FAIL: Cannot connect — {e}" else: return "FAIL: SSH authentication failed" except paramiko.SSHException as e: return f"FAIL: SSH error — {e}" except Exception as e: return f"FAIL: Cannot connect — {e}" # ── STEP 2–4: Upload → Verify → sysupgrade ───────────────────── try: remote_path = _upload_firmware(client, firmware_path, status_cb) _verify_firmware(client, remote_path, status_cb) return _sync_and_sysupgrade(client, remote_path, status_cb) except RuntimeError as e: return f"FAIL: {e}" except Exception as e: return f"FAIL: {e}" finally: try: client.close() except Exception: pass