mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-02 02:42:08 +00:00
fix: require running LXC for package checks
This commit is contained in:
@@ -6048,7 +6048,7 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
<h3 className="text-sm font-semibold text-foreground">{t("vmLxc.updates.osPackagesTitle")}</h3>
|
||||
<Button
|
||||
size="sm" variant="outline" className="ml-auto"
|
||||
disabled={osCheckingVmid !== null || updatesRefreshing || controlLoading || applyOpen}
|
||||
disabled={selectedVM.status !== "running" || osCheckingVmid !== null || updatesRefreshing || controlLoading || applyOpen}
|
||||
title={t("vmLxc.updates.refreshCheckHelp")}
|
||||
onClick={() => checkOsUpdates(selectedVM.vmid)}
|
||||
>
|
||||
@@ -6056,6 +6056,11 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
|
||||
{t("vmLxc.updates.checkSystemPackages")}
|
||||
</Button>
|
||||
</div>
|
||||
{selectedVM.status !== "running" && (
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
{t("vmLxc.updates.startBeforeCheck")}
|
||||
</p>
|
||||
)}
|
||||
<div className="text-xs text-muted-foreground mb-3 leading-relaxed">
|
||||
{t("vmLxc.updates.lastCheckedPrefix")}{" "}
|
||||
{uc?.last_check ? new Date(uc.last_check).toLocaleString() : "—"}
|
||||
|
||||
@@ -31,8 +31,8 @@ export function checkLxcUpdates<T>(vmid: number): Promise<T> {
|
||||
return fetchApi<T>(`/api/vms/${vmid}/updates/check`, { method: "POST" })
|
||||
}
|
||||
|
||||
// Separate explicit action: refresh indexes, check only, restore stopped CT.
|
||||
// The backend owns the job even if the browser closes or navigates away.
|
||||
// Explicit action: refresh indexes and check an already-running CT. The
|
||||
// backend owns the job even if the browser closes or navigates away.
|
||||
export async function refreshCheckLxcUpdates<T>(vmid: number): Promise<T> {
|
||||
const job = await fetchApi<{ job_id: string }>(`/api/vms/${vmid}/updates/refresh-check`, { method: "POST" })
|
||||
const deadline = Date.now() + 8 * 60_000
|
||||
|
||||
@@ -1335,9 +1335,9 @@
|
||||
"checkNow": "Check updates",
|
||||
"checkSystemPackages": "Check system packages",
|
||||
"checkInProgress": "Check in progress",
|
||||
"refreshCheckHelp": "Refreshes package indexes and checks pending updates. Nothing is installed. A stopped container is temporarily started and stopped again after the check.",
|
||||
"refreshCheckHelp": "Refreshes package indexes and checks pending updates while the container is running. Nothing is installed.",
|
||||
"notCheckedYet": "Updates have not been checked yet.",
|
||||
"checkStillRunning": "The check is still running. The monitor will restore the container's original state when it finishes.",
|
||||
"checkStillRunning": "The check is still running. Its result will be saved when it finishes.",
|
||||
"checkBeforeUpdate": "Check updates first",
|
||||
"startBeforeCheck": "Start the container, then check for updates. No badge does not mean there are no updates.",
|
||||
"checkReadOnlyHelp": "Read current OS and pending packages from existing indexes. No installation or package index refresh.",
|
||||
|
||||
@@ -1337,9 +1337,9 @@
|
||||
"checkNow": "Skontrolovať aktualizácie",
|
||||
"checkSystemPackages": "Skontrolovať balíky systému",
|
||||
"checkInProgress": "Prebieha kontrola",
|
||||
"refreshCheckHelp": "Obnoví zoznamy balíkov a skontroluje čakajúce aktualizácie. Nič nenainštaluje. Vypnutý kontajner sa dočasne zapne a po kontrole sa opäť vypne.",
|
||||
"refreshCheckHelp": "Obnoví zoznamy balíkov a skontroluje čakajúce aktualizácie, kým je kontajner spustený. Nič nenainštaluje.",
|
||||
"notCheckedYet": "Aktualizácie zatiaľ nie sú skontrolované.",
|
||||
"checkStillRunning": "Kontrola ešte prebieha. Monitor po jej dokončení obnoví pôvodný stav kontajnera.",
|
||||
"checkStillRunning": "Kontrola ešte prebieha. Po dokončení sa uloží jej výsledok.",
|
||||
"checkBeforeUpdate": "Najprv skontrolovať aktualizácie",
|
||||
"startBeforeCheck": "Spustite kontajner a potom skontrolujte aktualizácie. Chýbajúci odznak neznamená, že nie sú žiadne aktualizácie.",
|
||||
"checkReadOnlyHelp": "Zistí aktuálny systém a čakajúce balíky podľa existujúcich zoznamov. Nič nenainštaluje ani neobnoví zoznamy balíkov.",
|
||||
|
||||
@@ -13697,7 +13697,7 @@ def api_lxc_updates_check(vmid):
|
||||
@app.route('/api/vms/<int:vmid>/updates/refresh-check', methods=['POST'])
|
||||
@require_auth
|
||||
def api_lxc_updates_refresh_check(vmid):
|
||||
"""Explicit index refresh/check; never installs. Worker owns restoration."""
|
||||
"""Explicit index refresh/check for a running CT; never installs."""
|
||||
import lxc_check_job
|
||||
try:
|
||||
result, code = lxc_check_job.start(vmid)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Explicit check-only jobs; the shared updater lock protects each CT.
|
||||
|
||||
Importing or reading a job never probes a guest. Only start() may launch work.
|
||||
Package observations are saved before restoring a temporarily started guest.
|
||||
Importing or reading a job never probes a guest. Only start() may launch work
|
||||
for an already-running CT; package indexes are never refreshed by starting one.
|
||||
"""
|
||||
import datetime
|
||||
import fcntl
|
||||
@@ -99,51 +99,30 @@ def checked_os(vmid):
|
||||
|
||||
|
||||
def run(vmid, job_id, reservation):
|
||||
restore = False
|
||||
error = None
|
||||
check_started = False
|
||||
invalid = LOCK_DIR / f'proxmenux-lxc-check-invalid-{int(vmid)}'
|
||||
try:
|
||||
invalid.touch(mode=0o600)
|
||||
guard(vmid)
|
||||
original = status(vmid)
|
||||
if original == 'stopped':
|
||||
# Set before start: a timed-out command can still have started CT.
|
||||
restore = True
|
||||
command(vmid, 'start', timeout=60)
|
||||
deadline = time.monotonic() + 60
|
||||
while True:
|
||||
try:
|
||||
command(vmid, 'exec', '--', 'true', timeout=5)
|
||||
break
|
||||
except (RuntimeError, subprocess.TimeoutExpired):
|
||||
if time.monotonic() >= deadline:
|
||||
raise RuntimeError('Container did not become ready')
|
||||
time.sleep(1)
|
||||
if status(vmid) != 'running':
|
||||
raise RuntimeError('Container is stopped; start it first')
|
||||
check_started = True
|
||||
observation = lxc_update_observation.capture(vmid, job_id, refresh_indexes=True)
|
||||
if not managed_installs.store_lxc_update_observation(vmid, observation):
|
||||
raise RuntimeError(observation['result'].get('error') or 'Package check failed')
|
||||
lxc_update_observation.discard(vmid, job_id)
|
||||
except Exception as exc:
|
||||
error = str(exc)
|
||||
# Preflight/start failures must revoke a previous positive observation.
|
||||
try:
|
||||
managed_installs.store_lxc_update_observation(vmid, None)
|
||||
except Exception:
|
||||
error += '; package result could not be persisted'
|
||||
finally:
|
||||
if restore:
|
||||
# A failed package operation must block installation. A state change
|
||||
# before the worker runs did not check or alter packages, so keep the
|
||||
# last verified observation but leave the invalid marker in place.
|
||||
if check_started:
|
||||
try:
|
||||
if status(vmid) != 'stopped':
|
||||
command(vmid, 'shutdown', '--timeout', '30', timeout=40)
|
||||
if status(vmid) != 'stopped':
|
||||
raise RuntimeError('Container is still running')
|
||||
managed_installs.store_lxc_update_observation(vmid, None)
|
||||
except Exception:
|
||||
try:
|
||||
command(vmid, 'stop', timeout=30)
|
||||
if status(vmid) != 'stopped':
|
||||
raise RuntimeError('Container is still running')
|
||||
except Exception:
|
||||
error = (error + '; ' if error else '') + 'Original stopped state could not be restored'
|
||||
error += '; package result could not be persisted'
|
||||
finally:
|
||||
if not error:
|
||||
try:
|
||||
invalid.unlink()
|
||||
@@ -167,6 +146,8 @@ def start(vmid):
|
||||
reservation = acquire(vmid)
|
||||
try:
|
||||
guard(vmid)
|
||||
if status(vmid) != 'running':
|
||||
raise RuntimeError('Container is stopped; start it first')
|
||||
job_id = uuid.uuid4().hex
|
||||
_jobs[job_id] = dict(vmid=vmid, state='running', error=None, created=now)
|
||||
_attempts[vmid] = now
|
||||
|
||||
Reference in New Issue
Block a user