From 9639dd422a9c5dd3232ce5a2665c065587de822e Mon Sep 17 00:00:00 2001 From: MacRimi Date: Sun, 30 Nov 2025 19:15:07 +0100 Subject: [PATCH] Update AppImage --- AppImage/app/api/gpu/nvidia/install/route.ts | 40 ++++++++++ AppImage/components/hardware.tsx | 82 +++++++++++++++----- AppImage/lib/script-executor.ts | 39 ++++++++++ 3 files changed, 143 insertions(+), 18 deletions(-) create mode 100644 AppImage/app/api/gpu/nvidia/install/route.ts create mode 100644 AppImage/lib/script-executor.ts diff --git a/AppImage/app/api/gpu/nvidia/install/route.ts b/AppImage/app/api/gpu/nvidia/install/route.ts new file mode 100644 index 0000000..b38acfa --- /dev/null +++ b/AppImage/app/api/gpu/nvidia/install/route.ts @@ -0,0 +1,40 @@ +import { NextResponse } from "next/server" +import { executeScript } from "@/lib/script-executor" + +export async function POST() { + try { + // Execute the NVIDIA installer script + const result = await executeScript("/usr/local/share/proxmenux/scripts/gpu_tpu/nvidia_installer.sh", { + env: { + EXECUTION_MODE: "web", + WEB_LOG: "/tmp/nvidia_web_install.log", + }, + }) + + if (result.exitCode === 0) { + return NextResponse.json({ + success: true, + message: "NVIDIA drivers installed successfully", + output: result.stdout, + }) + } else { + return NextResponse.json( + { + success: false, + error: "Installation failed", + output: result.stderr || result.stdout, + }, + { status: 500 }, + ) + } + } catch (error) { + console.error("NVIDIA installation error:", error) + return NextResponse.json( + { + success: false, + error: error instanceof Error ? error.message : "Unknown error", + }, + { status: 500 }, + ) + } +} diff --git a/AppImage/components/hardware.tsx b/AppImage/components/hardware.tsx index de4abba..5480b24 100644 --- a/AppImage/components/hardware.tsx +++ b/AppImage/components/hardware.tsx @@ -5,19 +5,21 @@ import { Badge } from "@/components/ui/badge" import { Progress } from "@/components/ui/progress" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { - Thermometer, - CpuIcon, - Zap, - HardDrive, - Network, - FanIcon, - PowerIcon, - Battery, Cpu, - MemoryStick, - Cpu as Gpu, + HardDrive, + Thermometer, + Zap, Loader2, + CpuIcon, + Cpu as Gpu, + Network, + MemoryStick, + PowerIcon, + FanIcon, + Battery, } from "lucide-react" +import { Download } from "lucide-react" +import { Button } from "@/components/ui/button" import useSWR from "swr" import { useState, useEffect } from "react" import { @@ -236,6 +238,7 @@ export default function Hardware() { const [selectedDisk, setSelectedDisk] = useState(null) const [selectedNetwork, setSelectedNetwork] = useState(null) const [selectedUPS, setSelectedUPS] = useState(null) + const [installingNvidiaDriver, setInstallingNvidiaDriver] = useState(false) const fetcher = async (url: string) => { const data = await fetchApi(url) @@ -246,7 +249,7 @@ export default function Hardware() { data: hardwareDataSWR, error: swrError, isLoading: swrLoading, - mutate, + mutate: mutateHardware, } = useSWR("/api/hardware", fetcher, { refreshInterval: 30000, revalidateOnFocus: false, @@ -311,6 +314,34 @@ export default function Hardware() { return pciDevice || null } + const handleInstallNvidiaDriver = async () => { + setInstallingNvidiaDriver(true) + try { + const response = await fetch("/api/gpu/nvidia/install", { + method: "POST", + }) + + if (!response.ok) { + throw new Error("Failed to start NVIDIA driver installation") + } + + const data = await response.json() + + // Show success message (you might want to add a toast notification here) + alert("NVIDIA driver installation started. Please check the terminal for progress.") + + // Refresh GPU data after installation + setTimeout(() => { + mutateHardware() + }, 2000) + } catch (error) { + console.error("Error installing NVIDIA driver:", error) + alert("Failed to start NVIDIA driver installation. Please try manually.") + } finally { + setInstallingNvidiaDriver(false) + } + } + const hasRealtimeData = (): boolean => { if (!realtimeGPUData) return false @@ -1090,11 +1121,31 @@ export default function Hardware() { /> -
+

Extended Monitoring Not Available

-

+

{getMonitoringToolRecommendation(selectedGPU.vendor)}

+ {selectedGPU.vendor.toLowerCase().includes("nvidia") && ( + + )}
@@ -1105,7 +1156,6 @@ export default function Hardware() { - {/* Power Consumption */} {hardwareDataSWR?.power_meter && ( @@ -1476,8 +1526,6 @@ export default function Hardware() { - - {/* PCI Devices - Changed to modal */} {hardwareDataSWR?.pci_devices && hardwareDataSWR.pci_devices.length > 0 && ( @@ -1564,8 +1612,6 @@ export default function Hardware() { - - {/* Network Summary - Clickable */} {hardwareDataSWR?.pci_devices && hardwareDataSWR.pci_devices.filter((d) => d.type.toLowerCase().includes("network")).length > 0 && ( diff --git a/AppImage/lib/script-executor.ts b/AppImage/lib/script-executor.ts new file mode 100644 index 0000000..6ffdf4c --- /dev/null +++ b/AppImage/lib/script-executor.ts @@ -0,0 +1,39 @@ +import { exec } from "child_process" +import { promisify } from "util" + +const execAsync = promisify(exec) + +interface ScriptExecutorOptions { + env?: Record + timeout?: number +} + +interface ScriptResult { + stdout: string + stderr: string + exitCode: number +} + +export async function executeScript(scriptPath: string, options: ScriptExecutorOptions = {}): Promise { + const { env = {}, timeout = 300000 } = options // 5 minutes default timeout + + try { + const { stdout, stderr } = await execAsync(`bash ${scriptPath}`, { + env: { ...process.env, ...env }, + timeout, + maxBuffer: 1024 * 1024 * 10, // 10MB buffer + }) + + return { + stdout, + stderr, + exitCode: 0, + } + } catch (error: any) { + return { + stdout: error.stdout || "", + stderr: error.stderr || error.message || "Unknown error", + exitCode: error.code || 1, + } + } +}