mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-05-03 04:46:24 +00:00
update flask_proxmenux_routes.py
This commit is contained in:
@@ -191,6 +191,7 @@ interface ProxMenuxTool {
|
|||||||
enabled: boolean
|
enabled: boolean
|
||||||
version?: string
|
version?: string
|
||||||
has_source?: boolean
|
has_source?: boolean
|
||||||
|
deprecated?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RemoteStorage {
|
interface RemoteStorage {
|
||||||
@@ -234,7 +235,8 @@ export function Settings() {
|
|||||||
source: string
|
source: string
|
||||||
script: string
|
script: string
|
||||||
error: string
|
error: string
|
||||||
}>({ open: false, loading: false, toolName: '', version: '', functionName: '', source: '', script: '', error: '' })
|
deprecated: boolean
|
||||||
|
}>({ open: false, loading: false, toolName: '', version: '', functionName: '', source: '', script: '', error: '', deprecated: false })
|
||||||
const [codeCopied, setCodeCopied] = useState(false)
|
const [codeCopied, setCodeCopied] = useState(false)
|
||||||
|
|
||||||
// Health Monitor suppression settings
|
// Health Monitor suppression settings
|
||||||
@@ -278,11 +280,11 @@ export function Settings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const viewToolSource = async (tool: ProxMenuxTool) => {
|
const viewToolSource = async (tool: ProxMenuxTool) => {
|
||||||
setCodeModal({ open: true, loading: true, toolName: tool.name, version: tool.version || '1.0', functionName: '', source: '', script: '', error: '' })
|
setCodeModal({ open: true, loading: true, toolName: tool.name, version: tool.version || '1.0', functionName: '', source: '', script: '', error: '', deprecated: !!tool.deprecated })
|
||||||
try {
|
try {
|
||||||
const data = await fetchApi(`/api/proxmenux/tool-source/${tool.key}`)
|
const data = await fetchApi(`/api/proxmenux/tool-source/${tool.key}`)
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
setCodeModal(prev => ({ ...prev, loading: false, functionName: data.function, source: data.source, script: data.script }))
|
setCodeModal(prev => ({ ...prev, loading: false, functionName: data.function, source: data.source, script: data.script, deprecated: !!data.deprecated }))
|
||||||
} else {
|
} else {
|
||||||
setCodeModal(prev => ({ ...prev, loading: false, error: data.error || 'Source code not available' }))
|
setCodeModal(prev => ({ ...prev, loading: false, error: data.error || 'Source code not available' }))
|
||||||
}
|
}
|
||||||
@@ -1019,16 +1021,22 @@ export function Settings() {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
||||||
{proxmenuxTools.map((tool) => {
|
{proxmenuxTools.map((tool) => {
|
||||||
const clickable = !!tool.has_source
|
const clickable = !!tool.has_source
|
||||||
|
const isDeprecated = !!tool.deprecated
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={tool.key}
|
key={tool.key}
|
||||||
onClick={clickable ? () => viewToolSource(tool) : undefined}
|
onClick={clickable ? () => viewToolSource(tool) : undefined}
|
||||||
className={`flex items-center justify-between gap-2 p-3 bg-muted/50 rounded-lg border border-border transition-colors ${clickable ? 'hover:bg-muted hover:border-orange-500/40 cursor-pointer' : ''}`}
|
className={`flex items-center justify-between gap-2 p-3 bg-muted/50 rounded-lg border border-border transition-colors ${clickable ? 'hover:bg-muted hover:border-orange-500/40 cursor-pointer' : ''}`}
|
||||||
title={clickable ? 'Click to view source code' : undefined}
|
title={clickable ? (isDeprecated ? 'Legacy optimization — click to view source' : 'Click to view source code') : undefined}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2 min-w-0">
|
<div className="flex items-center gap-2 min-w-0">
|
||||||
<div className="w-2 h-2 rounded-full bg-green-500 flex-shrink-0" />
|
<div className={`w-2 h-2 rounded-full flex-shrink-0 ${isDeprecated ? 'bg-amber-500' : 'bg-green-500'}`} />
|
||||||
<span className="text-sm font-medium truncate">{tool.name}</span>
|
<span className="text-sm font-medium truncate">{tool.name}</span>
|
||||||
|
{isDeprecated && (
|
||||||
|
<span className="text-[9px] uppercase tracking-wider text-amber-500 bg-amber-500/10 border border-amber-500/30 px-1.5 py-0.5 rounded flex-shrink-0">
|
||||||
|
legacy
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded font-mono flex-shrink-0">v{tool.version || '1.0'}</span>
|
<span className="text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded font-mono flex-shrink-0">v{tool.version || '1.0'}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -1051,9 +1059,16 @@ export function Settings() {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between p-4 border-b border-border">
|
<div className="flex items-center justify-between p-4 border-b border-border">
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
<Code className="h-5 w-5 text-orange-500 flex-shrink-0" />
|
<Code className={`h-5 w-5 flex-shrink-0 ${codeModal.deprecated ? 'text-amber-500' : 'text-orange-500'}`} />
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<h3 className="text-sm font-semibold truncate">{codeModal.toolName}</h3>
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
|
<h3 className="text-sm font-semibold truncate">{codeModal.toolName}</h3>
|
||||||
|
{codeModal.deprecated && (
|
||||||
|
<span className="text-[9px] uppercase tracking-wider text-amber-500 bg-amber-500/10 border border-amber-500/30 px-1.5 py-0.5 rounded flex-shrink-0">
|
||||||
|
legacy
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
{codeModal.functionName && <span className="font-mono">{codeModal.functionName}()</span>}
|
{codeModal.functionName && <span className="font-mono">{codeModal.functionName}()</span>}
|
||||||
{codeModal.script && <span> — {codeModal.script}</span>}
|
{codeModal.script && <span> — {codeModal.script}</span>}
|
||||||
|
|||||||
@@ -3368,15 +3368,6 @@ function SmartTestTab({ disk, observations = [], lastTestDate }: SmartTestTabPro
|
|||||||
)}
|
)}
|
||||||
Extended Test (background)
|
Extended Test (background)
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={fetchSmartStatus}
|
|
||||||
className="gap-2 bg-blue-500/10 border-blue-500/30 text-blue-500 hover:bg-blue-500/20 hover:text-blue-400"
|
|
||||||
>
|
|
||||||
<Activity className="h-4 w-4" />
|
|
||||||
Refresh Status
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Short test takes ~2 minutes. Extended test runs in the background and can take several hours for large disks.
|
Short test takes ~2 minutes. Extended test runs in the background and can take several hours for large disks.
|
||||||
|
|||||||
@@ -30,11 +30,61 @@ TOOL_METADATA = {
|
|||||||
'vfio_iommu': {'name': 'VFIO/IOMMU Passthrough', 'function': 'enable_vfio_iommu', 'version': '1.0'},
|
'vfio_iommu': {'name': 'VFIO/IOMMU Passthrough', 'function': 'enable_vfio_iommu', 'version': '1.0'},
|
||||||
'lvm_repair': {'name': 'LVM PV Headers Repair', 'function': 'repair_lvm_headers', 'version': '1.0'},
|
'lvm_repair': {'name': 'LVM PV Headers Repair', 'function': 'repair_lvm_headers', 'version': '1.0'},
|
||||||
'repo_cleanup': {'name': 'Repository Cleanup', 'function': 'cleanup_repos', 'version': '1.0'},
|
'repo_cleanup': {'name': 'Repository Cleanup', 'function': 'cleanup_repos', 'version': '1.0'},
|
||||||
|
# ── Legacy / Deprecated entries ──
|
||||||
|
# These optimizations were applied by previous ProxMenux versions but are
|
||||||
|
# no longer needed or have been removed from the current scripts. We still
|
||||||
|
# expose their source code for transparency with existing users.
|
||||||
|
'entropy': {'name': 'Entropy Generation (haveged)', 'function': 'configure_entropy', 'version': '1.0', 'deprecated': True},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Backward-compatible description mapping (used by get_installed_tools)
|
# Backward-compatible description mapping (used by get_installed_tools)
|
||||||
TOOL_DESCRIPTIONS = {k: v['name'] for k, v in TOOL_METADATA.items()}
|
TOOL_DESCRIPTIONS = {k: v['name'] for k, v in TOOL_METADATA.items()}
|
||||||
|
|
||||||
|
# Source code preserved for deprecated/removed optimization functions.
|
||||||
|
# When a function is removed from the active bash scripts (because it's
|
||||||
|
# no longer needed, e.g. obsoleted by kernel improvements), keep its code
|
||||||
|
# here so users who installed it in the past can still inspect what ran.
|
||||||
|
DEPRECATED_SOURCES = {
|
||||||
|
'configure_entropy': {
|
||||||
|
'script': 'customizable_post_install.sh (legacy)',
|
||||||
|
'source': '''# ─────────────────────────────────────────────────────────────────
|
||||||
|
# NOTE: This optimization has been REMOVED from current ProxMenux versions.
|
||||||
|
# Modern Linux kernels (5.6+, shipped with Proxmox VE 7.x and 8.x) include
|
||||||
|
# built-in entropy generation via the Jitter RNG and CRNG, making haveged
|
||||||
|
# unnecessary. The function below is preserved here for transparency so
|
||||||
|
# users who applied it in the past can see exactly what was installed.
|
||||||
|
# New ProxMenux installations no longer include this optimization.
|
||||||
|
# ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
configure_entropy() {
|
||||||
|
msg_info2 "$(translate "Configuring entropy generation to prevent slowdowns...")"
|
||||||
|
|
||||||
|
# Install haveged
|
||||||
|
msg_info "$(translate "Installing haveged...")"
|
||||||
|
/usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confdef' install haveged > /dev/null 2>&1
|
||||||
|
msg_ok "$(translate "haveged installed successfully")"
|
||||||
|
|
||||||
|
# Configure haveged
|
||||||
|
msg_info "$(translate "Configuring haveged...")"
|
||||||
|
cat <<EOF > /etc/default/haveged
|
||||||
|
# -w sets low entropy watermark (in bits)
|
||||||
|
DAEMON_ARGS="-w 1024"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Reload systemd daemon
|
||||||
|
systemctl daemon-reload > /dev/null 2>&1
|
||||||
|
|
||||||
|
# Enable haveged service
|
||||||
|
systemctl enable haveged > /dev/null 2>&1
|
||||||
|
msg_ok "$(translate "haveged service enabled successfully")"
|
||||||
|
|
||||||
|
register_tool "entropy" true
|
||||||
|
msg_success "$(translate "Entropy generation configuration completed")"
|
||||||
|
}
|
||||||
|
''',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
# Scripts to search for function source code (in order of preference)
|
# Scripts to search for function source code (in order of preference)
|
||||||
_SCRIPT_PATHS = [
|
_SCRIPT_PATHS = [
|
||||||
'/usr/local/share/proxmenux/scripts/post_install/customizable_post_install.sh',
|
'/usr/local/share/proxmenux/scripts/post_install/customizable_post_install.sh',
|
||||||
@@ -43,14 +93,26 @@ _SCRIPT_PATHS = [
|
|||||||
|
|
||||||
|
|
||||||
def _extract_bash_function(function_name: str) -> dict:
|
def _extract_bash_function(function_name: str) -> dict:
|
||||||
"""Extract a bash function's source code from the post-install scripts.
|
"""Extract a bash function's source code.
|
||||||
|
|
||||||
Searches each script for `function_name() {` and captures everything
|
Checks DEPRECATED_SOURCES first (for functions removed from active scripts),
|
||||||
until the matching closing `}` at column 0, respecting brace nesting.
|
then searches the live bash scripts for `function_name() {` and captures
|
||||||
|
everything until the matching closing `}`, respecting brace nesting.
|
||||||
|
|
||||||
Returns {'source': str, 'script': str, 'line_start': int, 'line_end': int}
|
Returns {'source': str, 'script': str, 'line_start': int, 'line_end': int}
|
||||||
or {'source': '', 'error': '...'} on failure.
|
or {'source': '', 'error': '...'} on failure.
|
||||||
"""
|
"""
|
||||||
|
# Check preserved deprecated source code first
|
||||||
|
if function_name in DEPRECATED_SOURCES:
|
||||||
|
entry = DEPRECATED_SOURCES[function_name]
|
||||||
|
source = entry['source']
|
||||||
|
return {
|
||||||
|
'source': source,
|
||||||
|
'script': entry['script'],
|
||||||
|
'line_start': 1,
|
||||||
|
'line_end': len(source.split('\n')),
|
||||||
|
}
|
||||||
|
|
||||||
for script_path in _SCRIPT_PATHS:
|
for script_path in _SCRIPT_PATHS:
|
||||||
if not os.path.isfile(script_path):
|
if not os.path.isfile(script_path):
|
||||||
continue
|
continue
|
||||||
@@ -158,6 +220,7 @@ def get_installed_tools():
|
|||||||
'enabled': enabled,
|
'enabled': enabled,
|
||||||
'version': meta.get('version', '1.0'),
|
'version': meta.get('version', '1.0'),
|
||||||
'has_source': bool(meta.get('function')),
|
'has_source': bool(meta.get('function')),
|
||||||
|
'deprecated': bool(meta.get('deprecated', False)),
|
||||||
})
|
})
|
||||||
|
|
||||||
# Sort alphabetically by name
|
# Sort alphabetically by name
|
||||||
@@ -218,6 +281,7 @@ def get_tool_source(tool_key):
|
|||||||
'tool': tool_key,
|
'tool': tool_key,
|
||||||
'name': meta['name'],
|
'name': meta['name'],
|
||||||
'version': meta.get('version', '1.0'),
|
'version': meta.get('version', '1.0'),
|
||||||
|
'deprecated': bool(meta.get('deprecated', False)),
|
||||||
'function': func_name,
|
'function': func_name,
|
||||||
'source': result['source'],
|
'source': result['source'],
|
||||||
'script': result['script'],
|
'script': result['script'],
|
||||||
|
|||||||
Reference in New Issue
Block a user