mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-20 14:42:29 +02:00
198 lines
7.5 KiB
Python
198 lines
7.5 KiB
Python
import os
|
|
import time
|
|
import threading
|
|
from datetime import datetime
|
|
|
|
from .socket_server import StatusServer, StatusClient, register_cleanup
|
|
from mod.project.node.dbutil import FileTransferDB, FileTransfer, FileTransferTask
|
|
from mod.project.node.nodeutil import ServerNode, LocalNode, LPanelNode
|
|
from typing import Optional, Callable, Union
|
|
|
|
|
|
class Filetransfer:
|
|
SOCKET_FILE_DIR = "/tmp/filetransfer"
|
|
if not os.path.exists(SOCKET_FILE_DIR):
|
|
os.mkdir(SOCKET_FILE_DIR)
|
|
|
|
def __init__(self, task_id: int):
|
|
self.ft_db = FileTransferDB()
|
|
task_data, err = self.ft_db.get_task(task_id)
|
|
if err is None:
|
|
raise ValueError(err)
|
|
|
|
self.task = FileTransferTask.from_dict(task_data)
|
|
|
|
file_list = self.ft_db.get_task_file_transfers(task_id)
|
|
if not file_list:
|
|
raise ValueError("task_id:{} file_list is empty".format(task_id))
|
|
|
|
self.file_map = {file_data["transfer_id"]: FileTransfer.from_dict(file_data) for file_data in file_list}
|
|
self.file_count = len(self.file_map)
|
|
self.file_complete = sum([1 for file in self.file_map.values() if file.status == "complete"])
|
|
self.file_error = sum([1 for file in self.file_map.values() if file.status == "error"])
|
|
self.count_size = sum([file.file_size for file in self.file_map.values()])
|
|
self.complete_size = sum([file.file_size for file in self.file_map.values() if file.status == "complete"])
|
|
self.current_file_size = 0 # 记录当前文件完成的大小
|
|
self._srv = StatusServer(self.get_task_status, self.SOCKET_FILE_DIR + "/task_" + str(task_id))
|
|
|
|
if self.task.task_action == "upload":
|
|
self.sn = LocalNode()
|
|
if self.task.target_node["lpver"]:
|
|
self.dn = LPanelNode(self.task.target_node["address"], self.task.target_node["api_key"],
|
|
self.task.target_node["lpver"])
|
|
else:
|
|
self.dn = ServerNode(self.task.target_node["address"], self.task.target_node["api_key"],
|
|
self.task.target_node["app_key"])
|
|
else:
|
|
if self.task.source_node["lpver"]:
|
|
self.sn = LPanelNode(self.task.source_node["address"], self.task.source_node["api_key"],
|
|
self.task.source_node["lpver"])
|
|
else:
|
|
self.sn = ServerNode(self.task.source_node["address"], self.task.source_node["api_key"],
|
|
self.task.source_node["app_key"])
|
|
self.dn = LocalNode()
|
|
|
|
self._close_func: Optional[Callable]= None
|
|
|
|
def get_task_status(self, init: bool = False) -> dict:
|
|
task_dict = self.task.to_dict()
|
|
task_dict.update({
|
|
"file_count": self.file_count,
|
|
"file_complete": self.file_complete,
|
|
"file_error": self.file_error,
|
|
"count_size": self.count_size,
|
|
"complete_size": self.complete_size,
|
|
"progress": (self.complete_size + self.current_file_size) * 100 / self.count_size if self.count_size > 0 else 0,
|
|
})
|
|
return {
|
|
"task": task_dict,
|
|
"file_status_list": [{
|
|
"source_path": file.src_file,
|
|
"target_path": file.dst_file,
|
|
"status": file.status,
|
|
"progress": file.progress,
|
|
"log": file.message,
|
|
} for file in self.file_map.values()],
|
|
}
|
|
|
|
def start_server(self):
|
|
t = threading.Thread(target=self._srv.start_server, args=(), daemon=True)
|
|
t.start()
|
|
register_cleanup(self._srv)
|
|
def close():
|
|
self._srv.stop()
|
|
|
|
self._close_func = close
|
|
|
|
def close(self):
|
|
if self._close_func is None:
|
|
return
|
|
self._close_func()
|
|
|
|
def update_status(self):
|
|
self._srv.update_status()
|
|
|
|
def run(self):
|
|
self.task.status = "running"
|
|
self.ft_db.update_task(self.task)
|
|
self.start_server()
|
|
|
|
pending_list = [file for file in self.file_map.values() if file.status == "pending"]
|
|
for file in pending_list:
|
|
if file.is_dir > 0:
|
|
# 空文件夹处理部分
|
|
exits, _ = self.dn.target_file_exits(file.dst_file)
|
|
if exits:
|
|
file.progress = 100
|
|
file.status = "complete"
|
|
self.ft_db.update_file_transfer(file)
|
|
continue
|
|
res, err = self.dn.create_dir(path=file.dst_file)
|
|
if err:
|
|
file.progress = 0
|
|
file.status = "failed"
|
|
file.message = err
|
|
else:
|
|
if res.get("status",False) or res.get("status",-1) == 0:
|
|
file.progress = 100
|
|
file.status = "complete"
|
|
else:
|
|
file.progress = 0
|
|
file.status = "failed"
|
|
file.message = res["msg"]
|
|
self.ft_db.update_file_transfer(file)
|
|
continue
|
|
|
|
|
|
file.status = "running"
|
|
file.started_at = datetime.now()
|
|
self.ft_db.update_file_transfer(file)
|
|
|
|
def call_log(progress, log):
|
|
file.progress = progress
|
|
self.current_file_size = file.file_size * progress // 100
|
|
self.ft_db.update_file_transfer(file)
|
|
self.update_status()
|
|
|
|
if self.task.task_action == "upload":
|
|
self.ft_db.update_file_transfer(file)
|
|
res = self.dn.upload_file(
|
|
filename=file.src_file,
|
|
target_path=os.path.dirname(file.dst_file),
|
|
mode=self.task.default_mode,
|
|
call_log=call_log,
|
|
)
|
|
else:
|
|
self.ft_db.update_file_transfer(file)
|
|
res = self.sn.download_file(
|
|
filename=file.src_file,
|
|
target_path=os.path.dirname(file.dst_file),
|
|
mode=self.task.default_mode,
|
|
call_log=call_log,
|
|
)
|
|
|
|
self.current_file_size = 0
|
|
|
|
if res:
|
|
file.status = "failed"
|
|
file.message = res
|
|
self.file_error += 1
|
|
else:
|
|
file.status = "complete"
|
|
file.progress = 100
|
|
self.file_complete += 1
|
|
self.complete_size += file.file_size
|
|
|
|
self.ft_db.update_file_transfer(file)
|
|
self.update_status()
|
|
|
|
if self.file_error == 0:
|
|
self.task.status = "complete"
|
|
else:
|
|
self.task.status = "failed"
|
|
self.ft_db.update_task(self.task)
|
|
self.update_status()
|
|
time.sleep(10)
|
|
self.close()
|
|
|
|
|
|
def run_file_transfer_task(task_id: int):
|
|
ft = Filetransfer(task_id)
|
|
ft.run()
|
|
|
|
def task_running_log(task_id: int, call_log: Callable[[Union[str,dict]], None]):
|
|
socket_file = Filetransfer.SOCKET_FILE_DIR + "/task_" + str(task_id)
|
|
if not os.path.exists(socket_file):
|
|
call_log("The task status link does not exist")
|
|
return
|
|
s_client = StatusClient(socket_file, callback=call_log)
|
|
s_client.connect()
|
|
|
|
def wait_running(task_id: int, timeout:float = 3.0) -> str:
|
|
socket_file = Filetransfer.SOCKET_FILE_DIR + "/task_" + str(task_id)
|
|
while not os.path.exists(socket_file):
|
|
if timeout <= 0:
|
|
return "Task startup timeout"
|
|
timeout -= 0.05
|
|
time.sleep(0.05)
|
|
return "" |