Skip to content

Commit aff86e8

Browse files
committed
SSH重构: 1.优化ui_page_task模块
2.新增remote_plan_service Signed-off-by: wuqiongjin <suchinfinity@qq.com>
1 parent 7065239 commit aff86e8

3 files changed

Lines changed: 110 additions & 62 deletions

File tree

src/extend/remote_plan_service.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from __future__ import annotations
2+
3+
from typing import Callable
4+
5+
from src.extend.remote_linux_runner import RemoteLinuxRunner
6+
from src.extend.ssh_client import SshClient, SshConfig
7+
from src.utils.const import WebPath, Key
8+
from src.utils.utils import Utils
9+
10+
11+
class RemotePlanService:
12+
def __init__(self, ssh_cfg_getter: Callable[[], SshConfig | None]):
13+
self._ssh_cfg_getter = ssh_cfg_getter
14+
15+
def _ensure_runner_ready(self, remote: RemoteLinuxRunner) -> tuple[bool, str | None]:
16+
version = Utils.get_app_version_from_config_json(default="")
17+
if not version:
18+
return False, "无法获取版本号"
19+
20+
url = WebPath.LinuxRunnerDownloadUrlTemplate.format(version=version)
21+
ok2, err = remote.ensure_installed_from_url(version=version, url=url)
22+
if not ok2:
23+
return False, err or "远端安装 linux-runner 失败"
24+
25+
code, out, err2 = remote.set_current(version)
26+
if code != 0:
27+
return False, (err2 or out or "").strip() or "远端 set_current 失败"
28+
29+
return True, None
30+
31+
def cron_create(self, task: dict) -> tuple[bool, str | None]:
32+
cfg = self._ssh_cfg_getter()
33+
if not cfg:
34+
return False, "SSH配置缺失"
35+
36+
with SshClient(cfg) as ssh:
37+
remote = RemoteLinuxRunner(ssh)
38+
ok2, err = self._ensure_runner_ready(remote)
39+
if not ok2:
40+
return False, err
41+
42+
code, out, err2 = remote.cron_create(task)
43+
if code != 0:
44+
return False, (err2 or out or "").strip() or "远端创建 crontab 失败"
45+
46+
return True, None
47+
48+
def cron_delete(self, task_names) -> tuple[bool, str | None]:
49+
cfg = self._ssh_cfg_getter()
50+
if not cfg:
51+
return False, "SSH配置缺失"
52+
53+
if task_names is None:
54+
return False, "task_names为空"
55+
56+
if isinstance(task_names, str):
57+
task_names = [task_names]
58+
59+
with SshClient(cfg) as ssh:
60+
remote = RemoteLinuxRunner(ssh)
61+
ok2, err = self._ensure_runner_ready(remote)
62+
if not ok2:
63+
return False, err
64+
65+
for name in task_names:
66+
if not name:
67+
continue
68+
code, out, err2 = remote.cron_delete(name)
69+
if code != 0:
70+
return False, (err2 or out or "").strip() or "远端删除 crontab 失败"
71+
72+
return True, None
73+
74+
@staticmethod
75+
def task_names_from_plan(task: dict):
76+
plan_name = task.get(Key.SystemPlanName)
77+
if task.get(Key.TriggerType) == Key.Multiple and isinstance(plan_name, dict):
78+
return [plan_name.get(k) for k in plan_name]
79+
return plan_name

ui/main_window/auto_clock_window.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from src.extend.ssh_client import SshClient, SshConfig
1313
from src.store.settings_store import SettingsStore
1414
from src.store.data_store import LocalDataStore, RemoteDataStore, IDataStore
15+
from src.extend.remote_plan_service import RemotePlanService
1516

1617

1718
class AutoClockWindow(MainWindow):
@@ -41,6 +42,8 @@ def __init__(self):
4142
self._remote_data_root_abs = None
4243
self._remote_ssh_cfg: SshConfig | None = None
4344

45+
self._remote_plan_service: RemotePlanService | None = None
46+
4447
self._data_store: IDataStore = LocalDataStore()
4548

4649
self.load_data_json()
@@ -129,6 +132,8 @@ def connect_remote_and_reload(self) -> tuple[bool, str | None]:
129132
self._remote_data_root_abs = store.remote_data_root_abs
130133
self._remote_ssh_cfg = cfg
131134
self._data_store = store
135+
136+
self._remote_plan_service = RemotePlanService(lambda: self._remote_ssh_cfg)
132137
self.load_data_json()
133138
self._reload_pages()
134139
self.refresh_ssh_status()
@@ -139,6 +144,7 @@ def connect_remote_and_reload(self) -> tuple[bool, str | None]:
139144
self._remote_home_dir = None
140145
self._remote_data_root_abs = None
141146
self._remote_ssh_cfg = None
147+
self._remote_plan_service = None
142148
self.refresh_ssh_status()
143149
return False, str(e)
144150

@@ -149,6 +155,8 @@ def disconnect_remote_and_reload(self):
149155
self._remote_data_root_abs = None
150156
self._remote_ssh_cfg = None
151157

158+
self._remote_plan_service = None
159+
152160
self._data_store = LocalDataStore()
153161

154162
AppPath.clear_remote()
@@ -312,6 +320,10 @@ def sync_remote_tasks_json(self) -> bool:
312320
def data_store(self) -> IDataStore:
313321
return self._data_store
314322

323+
@property
324+
def remote_plan_service(self) -> RemotePlanService | None:
325+
return self._remote_plan_service
326+
315327
def write_tasks_list(self, tasks) -> bool:
316328
return self._data_store.write_tasks(tasks)
317329

ui/pages/ui_page_task.py

Lines changed: 19 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
from ui.custom.custom_widget import TaskListWidget
1515
from ui.template.ui_page import PageContent, Container
1616
from src.ui.ui_system_plan import SystemPlanDialog
17-
from src.extend.ssh_client import SshClient, SshConfig
18-
from src.extend.remote_linux_runner import RemoteLinuxRunner
1917
from src.utils.const import WebPath
2018

2119
# 根据操作系统导入相应的模块
@@ -100,6 +98,15 @@ def _write_tasks(self, tasks) -> bool:
10098
except Exception:
10199
return False
102100

101+
def _get_remote_plan_service(self):
102+
try:
103+
w = self.window()
104+
if hasattr(w, "remote_plan_service"):
105+
return w.remote_plan_service
106+
except Exception:
107+
pass
108+
return None
109+
103110
def _read_config(self) -> dict:
104111
try:
105112
w = self.window()
@@ -250,33 +257,10 @@ def do_create_plan(self):
250257
MessageBox("请先在 Settings -> SSH Settings 点击“连接”,连接成功后再创建远端计划任务")
251258
return
252259

253-
host = str(self._get_cfg(Key.SshHost, "") or "").strip()
254-
username = str(self._get_cfg(Key.SshUsername, "") or "").strip()
255-
password = str(self._get_cfg(Key.SshPassword, "") or "")
256-
use_pkey = bool(self._get_cfg(Key.SshUsePrivateKey, False))
257-
pkey_path = str(self._get_cfg(Key.SshPrivateKeyPath, "") or "").strip()
258-
version = Utils.get_app_version_from_config_json(default="")
259-
if not host or not username or not version:
260-
raise Exception("SSH配置不完整或无法获取版本号")
261-
url = WebPath.LinuxRunnerDownloadUrlTemplate.format(version=version)
262-
ssh_cfg = SshConfig(
263-
host=host,
264-
username=username,
265-
password=None if use_pkey else password,
266-
pkey_path=pkey_path if use_pkey else None,
267-
)
268-
with SshClient(ssh_cfg) as ssh:
269-
remote = RemoteLinuxRunner(ssh)
270-
ok2, err = remote.ensure_installed_from_url(version=version, url=url)
271-
if not ok2:
272-
raise Exception(err or "远端安装 linux-runner 失败")
273-
code, out, err2 = remote.set_current(version)
274-
if code != 0:
275-
raise Exception((err2 or out or "").strip() or "远端 set_current 失败")
276-
code, out, err2 = remote.cron_create(task)
277-
if code != 0:
278-
raise Exception((err2 or out or "").strip() or "远端创建 crontab 失败")
279-
ok, error = True, None
260+
svc = self._get_remote_plan_service()
261+
if svc is None:
262+
raise Exception("远端服务未初始化,请重新连接SSH")
263+
ok, error = svc.cron_create(task)
280264
else:
281265
ok, error = create_task(task)
282266
elif platform.system() == "Linux":
@@ -331,39 +315,12 @@ def delete_system_plan(self):
331315
MessageBox("请先在 Settings -> SSH Settings 点击“连接”,连接成功后再删除远端计划任务")
332316
return
333317

334-
host = str(self._get_cfg(Key.SshHost, "") or "").strip()
335-
username = str(self._get_cfg(Key.SshUsername, "") or "").strip()
336-
password = str(self._get_cfg(Key.SshPassword, "") or "")
337-
use_pkey = bool(self._get_cfg(Key.SshUsePrivateKey, False))
338-
pkey_path = str(self._get_cfg(Key.SshPrivateKeyPath, "") or "").strip()
339-
version = Utils.get_app_version_from_config_json(default="")
340-
if not host or not username or not version:
341-
raise Exception("SSH配置不完整或无法获取版本号")
342-
url = WebPath.LinuxRunnerDownloadUrlTemplate.format(version=version)
343-
ssh_cfg = SshConfig(
344-
host=host,
345-
username=username,
346-
password=None if use_pkey else password,
347-
pkey_path=pkey_path if use_pkey else None,
348-
)
349-
with SshClient(ssh_cfg) as ssh:
350-
remote = RemoteLinuxRunner(ssh)
351-
ok2, err = remote.ensure_installed_from_url(version=version, url=url)
352-
if not ok2:
353-
raise Exception(err or "远端安装 linux-runner 失败")
354-
code, out, err2 = remote.set_current(version)
355-
if code != 0:
356-
raise Exception((err2 or out or "").strip() or "远端 set_current 失败")
357-
358-
if delete_task[Key.TriggerType] == Key.Multiple and isinstance(plan_name, dict):
359-
for task_name in plan_name:
360-
code, out, err2 = remote.cron_delete(plan_name.get(task_name))
361-
if code != 0:
362-
raise Exception((err2 or out or "").strip() or "远端删除 crontab 失败")
363-
else:
364-
code, out, err2 = remote.cron_delete(plan_name)
365-
if code != 0:
366-
raise Exception((err2 or out or "").strip() or "远端删除 crontab 失败")
318+
svc = self._get_remote_plan_service()
319+
if svc is None:
320+
raise Exception("远端服务未初始化,请重新连接SSH")
321+
322+
names = svc.task_names_from_plan(delete_task)
323+
ok, error = svc.cron_delete(names)
367324
else:
368325
if delete_task[Key.TriggerType] == Key.Multiple and isinstance(plan_name, dict):
369326
for task_name in plan_name:

0 commit comments

Comments
 (0)