mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-02 19:02:31 +00:00
fix: keep LXC updates running when the browser session ends
This commit is contained in:
@@ -22,6 +22,8 @@ import useSWR from "swr"
|
||||
import { MetricsView } from "./metrics-dialog"
|
||||
import { LxcTerminalModal } from "./lxc-terminal-modal"
|
||||
import { ScriptTerminalModal } from "./script-terminal-modal"
|
||||
import { LxcUpdateJobs } from "./lxc-update-jobs"
|
||||
import { markUpdateJobViewed, type LxcUpdateJob } from "../lib/lxc-update-jobs"
|
||||
import { OCI_CANCELLED_EXIT_CODE, shouldRefreshOciAfterCompletion } from "@/lib/script-completion"
|
||||
import { LxcAppPanel, ThemeAwareLogo, ociImageLabel } from "./lxc-app-panel"
|
||||
import { GuestBackupList } from "./guest-backup-list"
|
||||
@@ -1998,6 +2000,7 @@ export function VirtualMachines() {
|
||||
const [applyRestart, setApplyRestart] = useState(false)
|
||||
const [applyStartedAt, setApplyStartedAt] = useState<number>(0)
|
||||
const [applyRunId, setApplyRunId] = useState<string>("")
|
||||
const [applyResume, setApplyResume] = useState(false)
|
||||
const [applyCheckedOs, setApplyCheckedOs] = useState(false)
|
||||
const [applyTargetIds, setApplyTargetIds] = useState<string[]>([])
|
||||
const [applyTargetLabels, setApplyTargetLabels] = useState<string[]>([])
|
||||
@@ -2639,6 +2642,7 @@ export function VirtualMachines() {
|
||||
setApplyVmid(vmid)
|
||||
setApplyTarget(target)
|
||||
setApplyRunId(runId)
|
||||
setApplyResume(false)
|
||||
setApplyCheckedOs(opts?.checkedOs === true)
|
||||
setApplyTargetIds(opts?.targetIds?.length ? opts.targetIds : fallbackTargets)
|
||||
setApplyTargetLabels(opts?.targetLabels?.length ? opts.targetLabels : fallbackLabels)
|
||||
@@ -2659,27 +2663,37 @@ export function VirtualMachines() {
|
||||
setApplyStartedAt(Date.now())
|
||||
setApplyOpen(true)
|
||||
}
|
||||
const handleApplyComplete = async (exitCode = 0) => {
|
||||
const resumeApplyJob = (job: LxcUpdateJob) => {
|
||||
setApplyVmid(job.vmid)
|
||||
setApplyTarget(job.target)
|
||||
setApplyRunId(job.id)
|
||||
setApplyCheckedOs(job.script_path.endsWith("/install_checked_os_updates.sh"))
|
||||
setApplyResume(true)
|
||||
setApplyStartedAt(job.created_at * 1000)
|
||||
setApplyOpen(true)
|
||||
}
|
||||
const handleApplyComplete = async (exitCode = 0, notifyBackend = true) => {
|
||||
if (applyVmid == null) return
|
||||
const duration = Math.max(0, Math.round((Date.now() - applyStartedAt) / 1000))
|
||||
// The modal fires onComplete on any WS close (success or user cancel).
|
||||
// Report the same run ID so the backend can collapse this compatibility
|
||||
// callback with its authoritative process-completion hook.
|
||||
// Legacy callers may report the same run ID to the compatibility route.
|
||||
// Background Updates only refresh the view after the server's real exit.
|
||||
try {
|
||||
await fetchApi(`/api/lxc-updates/${applyVmid}/applied`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
success: exitCode === 0,
|
||||
run_id: applyRunId,
|
||||
target: applyTarget,
|
||||
requested_targets: applyTargetIds,
|
||||
target_labels: applyTargetLabels,
|
||||
duration_seconds: duration,
|
||||
ct_name: selectedVM?.name || `CT-${applyVmid}`,
|
||||
refresh_docker_inventory: applyDockerRefresh,
|
||||
}),
|
||||
})
|
||||
if (notifyBackend) {
|
||||
await fetchApi(`/api/lxc-updates/${applyVmid}/applied`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
success: exitCode === 0,
|
||||
run_id: applyRunId,
|
||||
target: applyTarget,
|
||||
requested_targets: applyTargetIds,
|
||||
target_labels: applyTargetLabels,
|
||||
duration_seconds: duration,
|
||||
ct_name: selectedVM?.name || `CT-${applyVmid}`,
|
||||
refresh_docker_inventory: applyDockerRefresh,
|
||||
}),
|
||||
})
|
||||
}
|
||||
} catch {
|
||||
// Non-fatal — the backend process hook owns finalization.
|
||||
}
|
||||
@@ -7960,6 +7974,8 @@ export function VirtualMachines() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<LxcUpdateJobs activeRunId={applyOpen ? applyRunId : undefined} onResume={resumeApplyJob} />
|
||||
|
||||
{/* LXC Update Apply Terminal — streams the apply_updates.sh
|
||||
script over WS/PTY (same wiring as the hardware installers).
|
||||
The backend finalizes on process exit; the close callback only
|
||||
@@ -7971,7 +7987,13 @@ export function VirtualMachines() {
|
||||
setApplyOpen(false)
|
||||
setApplyVmid(null)
|
||||
}}
|
||||
onComplete={handleApplyComplete}
|
||||
onComplete={(exitCode) => {
|
||||
markUpdateJobViewed(applyRunId)
|
||||
// The server-owned job is the sole completion authority.
|
||||
void handleApplyComplete(exitCode ?? 1, false)
|
||||
}}
|
||||
backgroundUpdate={{ runId: applyRunId, vmid: applyVmid, resume: applyResume }}
|
||||
cancelledExitCode={130}
|
||||
scriptPath={applyCheckedOs
|
||||
? "/usr/local/share/proxmenux/scripts/lxc/install_checked_os_updates.sh"
|
||||
: "/usr/local/share/proxmenux/scripts/lxc/apply_updates.sh"}
|
||||
@@ -7981,13 +8003,7 @@ export function VirtualMachines() {
|
||||
completedWithErrorMessage={(exitCode) =>
|
||||
t("vmLxc.updates.terminalCompletedWithError", { code: exitCode })
|
||||
}
|
||||
description={
|
||||
applyTarget === "os"
|
||||
? t("vmLxc.updates.terminalDescriptionOs")
|
||||
: applyTarget === "app"
|
||||
? t("vmLxc.updates.terminalDescriptionApp")
|
||||
: t("vmLxc.updates.terminalDescriptionBoth")
|
||||
}
|
||||
description={t("vmLxc.updates.backgroundDescription")}
|
||||
params={{
|
||||
VMID: String(applyVmid),
|
||||
RUN_ID: applyRunId,
|
||||
|
||||
Reference in New Issue
Block a user