93 lines
3.2 KiB
Python
93 lines
3.2 KiB
Python
"""
|
||
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
|