"use client" import { cn } from "@/lib/utils" interface SriovInfo { role: "vf" | "pf-active" | "pf-idle" physfn?: string // VF only: parent PF BDF vfCount?: number // PF only: active VF count totalvfs?: number // PF only: maximum VFs } interface GpuSwitchModeIndicatorProps { mode: "lxc" | "vm" | "sriov" | "unknown" isEditing?: boolean pendingMode?: "lxc" | "vm" | null onToggle?: (e: React.MouseEvent) => void className?: string sriovInfo?: SriovInfo } export function GpuSwitchModeIndicator({ mode, isEditing = false, pendingMode = null, onToggle, className, sriovInfo, }: GpuSwitchModeIndicatorProps) { // SR-IOV is a non-editable hardware state. Pending toggles don't apply here. const displayMode = mode === "sriov" ? "sriov" : (pendingMode ?? mode) const isLxcActive = displayMode === "lxc" const isVmActive = displayMode === "vm" const isSriovActive = displayMode === "sriov" const hasChanged = mode !== "sriov" && pendingMode !== null && pendingMode !== mode // Colors const sriovColor = "#14b8a6" // teal-500 const activeColor = isSriovActive ? sriovColor : isLxcActive ? "#3b82f6" : isVmActive ? "#a855f7" : "#6b7280" const inactiveColor = "#374151" // gray-700 for dark theme const dimmedColor = "#4b5563" // gray-600 for dashed SR-IOV branches const lxcColor = isLxcActive ? "#3b82f6" : inactiveColor const vmColor = isVmActive ? "#a855f7" : inactiveColor const handleClick = (e: React.MouseEvent) => { // SR-IOV state can't be toggled — swallow the click so it doesn't reach // the card (which would open the detail modal unexpectedly from this // area). For lxc/vm, preserve the original behavior. if (isSriovActive) { e.stopPropagation() return } if (isEditing) { e.stopPropagation() if (onToggle) { onToggle(e) } } // When not editing, let the click propagate to the card to open the modal } // Build the VF count label shown in the SR-IOV badge. For PFs we know // exactly how many VFs are active; for a VF we show its parent PF. const sriovBadgeText = (() => { if (!isSriovActive) return "" if (sriovInfo?.role === "vf") return "SR-IOV VF" if (sriovInfo?.vfCount && sriovInfo.vfCount > 0) return `SR-IOV ×${sriovInfo.vfCount}` return "SR-IOV" })() return (
{/* Large SVG Diagram */} {/* GPU Chip - Large with "GPU" text */} {/* Main chip body */} {/* Chip pins - top */} {/* Chip pins - bottom */} {/* GPU text */} GPU {/* Connection line from GPU to switch */} {/* Central Switch Node - Large circle with inner dot */} {/* LXC Branch Line - going up-right. In SR-IOV mode the branch is dashed + dimmed to show that the target is theoretically reachable via a VF but not controlled by ProxMenux. */} {/* VM Branch Line - going down-right (dashed/dimmed in SR-IOV). */} {/* SR-IOV in-line connector + badge (only when mode === 'sriov'). A horizontal line from the switch node leads to a pill-shaped badge carrying the "SR-IOV ×N" label. Placed on the GPU's baseline to visually read as an in-line extension, not as a third branch. */} {isSriovActive && ( <> {sriovBadgeText} )} {/* LXC Container Icon - dimmed/smaller in SR-IOV mode. */} {!isSriovActive && ( )} {/* SR-IOV: compact dimmed LXC glyph so the geometry stays recognizable but it's clearly not the active target. */} {isSriovActive && ( )} {/* LXC Label */} {!isSriovActive && ( LXC )} {isSriovActive && ( LXC )} {/* VM Monitor Icon - active view */} {!isSriovActive && ( )} {/* SR-IOV: compact dimmed VM monitor glyph, mirror of the LXC glyph. */} {isSriovActive && ( )} {/* VM Label */} {!isSriovActive && ( VM )} {isSriovActive && ( VM )} {/* Status Text - Large like GPU name */}
{isSriovActive ? "SR-IOV active" : isLxcActive ? "Ready for LXC containers" : isVmActive ? "Ready for VM passthrough" : "Mode unknown"} {isSriovActive ? "Virtual Functions managed externally" : isLxcActive ? "Native driver active" : isVmActive ? "VFIO-PCI driver active" : "No driver detected"} {isSriovActive && sriovInfo && ( {sriovInfo.role === "vf" ? `Virtual Function${sriovInfo.physfn ? ` · parent PF ${sriovInfo.physfn}` : ""}` : sriovInfo.vfCount !== undefined ? `1 PF + ${sriovInfo.vfCount} VF${sriovInfo.vfCount === 1 ? "" : "s"}${sriovInfo.totalvfs ? ` / ${sriovInfo.totalvfs} max` : ""}` : null} )} {hasChanged && ( Change pending... )}
) }