refactor(ui): reuse _launch_and_mark for Run tab
This commit is contained in:
@@ -1147,7 +1147,7 @@ RU: Применяет policy-rules и проверяет health. При оши
|
|||||||
if code == 0 and (out or "").strip().lower() == "active":
|
if code == 0 and (out or "").strip().lower() == "active":
|
||||||
cg = self._effective_cgroup_for_unit_retry(unit, timeout_sec=3.0)
|
cg = self._effective_cgroup_for_unit_retry(unit, timeout_sec=3.0)
|
||||||
self._append_app_log(
|
self._append_app_log(
|
||||||
f"[profile] already running: app={key} target={tgt} unit={unit} (refreshing mark)"
|
f"[app] already running: app={key} target={tgt} unit={unit} (refreshing mark)"
|
||||||
)
|
)
|
||||||
res = self.ctrl.traffic_appmarks_apply(
|
res = self.ctrl.traffic_appmarks_apply(
|
||||||
op="add",
|
op="add",
|
||||||
@@ -1174,14 +1174,15 @@ RU: Применяет policy-rules и проверяет health. При оши
|
|||||||
self.refresh_appmarks_items(quiet=True)
|
self.refresh_appmarks_items(quiet=True)
|
||||||
self.refresh_appmarks_counts()
|
self.refresh_appmarks_counts()
|
||||||
self.refresh_running_scopes(quiet=True)
|
self.refresh_running_scopes(quiet=True)
|
||||||
|
self.refresh_app_profiles(quiet=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
unit = f"svpn-{tgt}-{int(time.time())}.service"
|
unit = f"svpn-{tgt}-{int(time.time())}.service"
|
||||||
self._append_app_log(f"[profile] launching: app={key or '-'} target={tgt} ttl={ttl}s unit={unit}")
|
self._append_app_log(f"[app] launching: app={key or '-'} target={tgt} ttl={ttl}s unit={unit}")
|
||||||
cg, out = self._run_systemd_unit(cmdline, unit=unit)
|
cg, out = self._run_systemd_unit(cmdline, unit=unit)
|
||||||
if out:
|
if out:
|
||||||
self._append_app_log(f"[profile] systemd-run:\n{out}")
|
self._append_app_log(f"[app] systemd-run:\n{out}")
|
||||||
self._append_app_log(f"[profile] ControlGroup: {cg}")
|
self._append_app_log(f"[app] ControlGroup: {cg}")
|
||||||
self._set_last_scope(unit=unit, target=tgt, app_key=key, cmdline=cmdline, cgroup_id=0)
|
self._set_last_scope(unit=unit, target=tgt, app_key=key, cmdline=cmdline, cgroup_id=0)
|
||||||
|
|
||||||
res = self.ctrl.traffic_appmarks_apply(
|
res = self.ctrl.traffic_appmarks_apply(
|
||||||
@@ -1194,6 +1195,16 @@ RU: Применяет policy-rules и проверяет health. При оши
|
|||||||
timeout_sec=ttl,
|
timeout_sec=ttl,
|
||||||
)
|
)
|
||||||
if not res.ok:
|
if not res.ok:
|
||||||
|
low = (res.message or "").lower()
|
||||||
|
if "cgroupv2 path fails" in low or "no such file or directory" in low:
|
||||||
|
raise RuntimeError(
|
||||||
|
(res.message or "appmark apply failed")
|
||||||
|
+ "\n\n"
|
||||||
|
+ "EN: This usually means the app didn't stay inside the new systemd unit "
|
||||||
|
+ "(often because it was already running). Close the app completely and run again.\n"
|
||||||
|
+ "RU: Обычно это значит, что приложение не осталось в новом systemd unit "
|
||||||
|
+ "(часто потому что оно уже было запущено). Полностью закрой приложение и запусти снова."
|
||||||
|
)
|
||||||
raise RuntimeError(res.message or "appmark apply failed")
|
raise RuntimeError(res.message or "appmark apply failed")
|
||||||
|
|
||||||
self._append_app_log(f"[appmarks] OK: {res.message} cgroup_id={res.cgroup_id} timeout={res.timeout_sec}s")
|
self._append_app_log(f"[appmarks] OK: {res.message} cgroup_id={res.cgroup_id} timeout={res.timeout_sec}s")
|
||||||
@@ -1208,6 +1219,7 @@ RU: Применяет policy-rules и проверяет health. При оши
|
|||||||
self.refresh_appmarks_items(quiet=True)
|
self.refresh_appmarks_items(quiet=True)
|
||||||
self.refresh_appmarks_counts()
|
self.refresh_appmarks_counts()
|
||||||
self.refresh_running_scopes(quiet=True)
|
self.refresh_running_scopes(quiet=True)
|
||||||
|
self.refresh_app_profiles(quiet=True)
|
||||||
|
|
||||||
def _selected_app_profile(self):
|
def _selected_app_profile(self):
|
||||||
it = self.lst_app_profiles.currentItem()
|
it = self.lst_app_profiles.currentItem()
|
||||||
@@ -1972,132 +1984,10 @@ RU: Применяет policy-rules и проверяет health. При оши
|
|||||||
QMessageBox.warning(self, "Missing command", "Please enter a command to run.")
|
QMessageBox.warning(self, "Missing command", "Please enter a command to run.")
|
||||||
return
|
return
|
||||||
|
|
||||||
app_key = ""
|
|
||||||
try:
|
|
||||||
args = shlex.split(cmdline or "")
|
|
||||||
if args:
|
|
||||||
app_key = str(args[0] or "").strip()
|
|
||||||
except Exception:
|
|
||||||
app_key = ""
|
|
||||||
if not app_key:
|
|
||||||
# Fallback: best-effort first token.
|
|
||||||
app_key = (cmdline.split() or [""])[0].strip()
|
|
||||||
|
|
||||||
target = "vpn" if self.rad_app_vpn.isChecked() else "direct"
|
target = "vpn" if self.rad_app_vpn.isChecked() else "direct"
|
||||||
ttl_sec = int(self.spn_app_ttl.value()) * 3600
|
ttl_sec = int(self.spn_app_ttl.value()) * 3600
|
||||||
|
app_key = self._infer_app_key_from_cmdline(cmdline)
|
||||||
# EN: If the app is already running inside the last svpn unit, don't spawn a new instance.
|
self._launch_and_mark(cmdline=cmdline, target=target, ttl_sec=ttl_sec, app_key=app_key)
|
||||||
# RU: Если приложение уже запущено в последнем svpn unit, не запускаем второй экземпляр.
|
|
||||||
last_unit = (self._last_app_unit or "").strip()
|
|
||||||
last_target = (self._last_app_target or "").strip().lower()
|
|
||||||
last_key = (self._last_app_key or "").strip()
|
|
||||||
if last_unit and last_target == target and last_key and last_key == app_key:
|
|
||||||
code, out = self._systemctl_user(["is-active", last_unit])
|
|
||||||
if code == 0 and (out or "").strip().lower() == "active":
|
|
||||||
cg = self._effective_cgroup_for_unit_retry(last_unit, timeout_sec=3.0)
|
|
||||||
self._append_app_log(
|
|
||||||
f"[app] already running: app={app_key} target={target} unit={last_unit} (refreshing mark)"
|
|
||||||
)
|
|
||||||
res = self.ctrl.traffic_appmarks_apply(
|
|
||||||
op="add",
|
|
||||||
target=target,
|
|
||||||
cgroup=cg,
|
|
||||||
unit=last_unit,
|
|
||||||
command=cmdline,
|
|
||||||
app_key=app_key,
|
|
||||||
timeout_sec=ttl_sec,
|
|
||||||
)
|
|
||||||
if res.ok:
|
|
||||||
self._append_app_log(
|
|
||||||
f"[appmarks] OK: {res.message} cgroup_id={res.cgroup_id} timeout={res.timeout_sec}s"
|
|
||||||
)
|
|
||||||
self._set_action_status(
|
|
||||||
f"App mark refreshed: target={target} cgroup_id={res.cgroup_id}",
|
|
||||||
ok=True,
|
|
||||||
)
|
|
||||||
self._set_last_scope(
|
|
||||||
unit=last_unit,
|
|
||||||
target=target,
|
|
||||||
app_key=app_key,
|
|
||||||
cmdline=cmdline,
|
|
||||||
cgroup_id=int(res.cgroup_id or 0),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._append_app_log(f"[appmarks] ERROR: {res.message}")
|
|
||||||
self._set_action_status(
|
|
||||||
f"App mark refresh failed: target={target} ({res.message})",
|
|
||||||
ok=False,
|
|
||||||
)
|
|
||||||
QMessageBox.critical(self, "App mark error", res.message or "unknown error")
|
|
||||||
self.refresh_appmarks_counts()
|
|
||||||
self.refresh_running_scopes()
|
|
||||||
self.refresh_app_profiles(quiet=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
unit = f"svpn-{target}-{int(time.time())}.service"
|
|
||||||
|
|
||||||
self._append_app_log(
|
|
||||||
f"[app] launching: app={app_key or '-'} target={target} ttl={ttl_sec}s unit={unit}"
|
|
||||||
)
|
|
||||||
|
|
||||||
cg, out = self._run_systemd_unit(cmdline, unit=unit)
|
|
||||||
if out:
|
|
||||||
self._append_app_log(f"[app] systemd-run:\n{out}")
|
|
||||||
self._append_app_log(f"[app] ControlGroup: {cg}")
|
|
||||||
self._set_last_scope(unit=unit, target=target, app_key=app_key, cmdline=cmdline, cgroup_id=0)
|
|
||||||
|
|
||||||
res = self.ctrl.traffic_appmarks_apply(
|
|
||||||
op="add",
|
|
||||||
target=target,
|
|
||||||
cgroup=cg,
|
|
||||||
unit=unit,
|
|
||||||
command=cmdline,
|
|
||||||
app_key=app_key,
|
|
||||||
timeout_sec=ttl_sec,
|
|
||||||
)
|
|
||||||
if res.ok:
|
|
||||||
self._append_app_log(
|
|
||||||
f"[appmarks] OK: {res.message} cgroup_id={res.cgroup_id} timeout={res.timeout_sec}s"
|
|
||||||
)
|
|
||||||
self._set_action_status(
|
|
||||||
f"App mark added: target={target} cgroup_id={res.cgroup_id}",
|
|
||||||
ok=True,
|
|
||||||
)
|
|
||||||
self._set_last_scope(
|
|
||||||
unit=unit,
|
|
||||||
target=target,
|
|
||||||
app_key=app_key,
|
|
||||||
cmdline=cmdline,
|
|
||||||
cgroup_id=int(res.cgroup_id or 0),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._append_app_log(f"[appmarks] ERROR: {res.message}")
|
|
||||||
self._set_action_status(
|
|
||||||
f"App mark failed: target={target} ({res.message})",
|
|
||||||
ok=False,
|
|
||||||
)
|
|
||||||
low = (res.message or "").lower()
|
|
||||||
if "cgroupv2 path fails" in low or "no such file or directory" in low:
|
|
||||||
QMessageBox.critical(
|
|
||||||
self,
|
|
||||||
"App mark error",
|
|
||||||
(res.message or "unknown error")
|
|
||||||
+ "\n\n"
|
|
||||||
+ "EN: This usually means the app didn't stay inside the new systemd unit "
|
|
||||||
+ "(often because it was already running). Close the app completely and run again from here.\n"
|
|
||||||
+ "RU: Обычно это значит, что приложение не осталось в новом systemd unit "
|
|
||||||
+ "(часто потому что оно уже было запущено). Полностью закрой приложение и запусти снова отсюда.",
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
QMessageBox.critical(
|
|
||||||
self,
|
|
||||||
"App mark error",
|
|
||||||
res.message or "unknown error",
|
|
||||||
)
|
|
||||||
|
|
||||||
self.refresh_appmarks_counts()
|
|
||||||
self.refresh_running_scopes()
|
|
||||||
self.refresh_app_profiles(quiet=True)
|
|
||||||
|
|
||||||
self._safe(work, title="Run app error")
|
self._safe(work, title="Run app error")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user