v0.80.0: disk card shows + acts on the stable path, not the raw host mount

The storage card displayed each external drive's raw host PVE mount (/mnt/<name>,
which doesn't exist in the guest) instead of the stable in-guest path
(/mnt/felhom-drives/<name> = guest_path) the registry/HDD_PATH/FileBrowser use.
The eject/wipe buttons also posted the raw path, so they would unmount the drive
but leave the stable registry entry orphaned, and the impact warning found no apps.

Fix: card sub-line + eject/wipe buttons use the stable path (regKey); type-to-confirm
name uses the basename; register keeps the raw path. handleStorageWipe maps to raw
via agentWhere() for the agent eject (matching handleStorageEject). Agent ops
unchanged (same raw paths); display + registry bookkeeping corrected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PsnU2ASocYrvzqE82YDYW
This commit is contained in:
2026-06-23 17:54:21 +02:00
parent 9596c8e563
commit fc94d91d15
4 changed files with 78 additions and 47 deletions
+20 -11
View File
@@ -477,17 +477,19 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
function actions(d, registered){
// Destructive controls ONLY for user-data drives that are mounted under /mnt. System/backup get none.
if(d.role!=='user-data' || !d.mount_path || d.mount_path.indexOf('/mnt/')!==0) return '';
var dev = esc(d.backing_device||''), mp = esc(d.mount_path);
var dev = esc(d.backing_device||''), mpRaw = esc(d.mount_path), reg = esc(regKey(d));
var btns = '';
// A mounted-but-unregistered user-data drive: the natural intent is to USE it → Regisztrálás is
// the PRIMARY action (no format, no eject). Leválasztás/Törlés stay available but secondary.
// Registration is keyed on the STABLE path (regKey) — the registry stores that, not the raw mp;
// registerDrive() still posts the RAW mp (the agent operates on raw, the handler maps to stable).
// Two distinct path arguments (the intermediary model):
// - registerDrive posts the RAW mount_path — its agent guest-attach operates on the raw mount
// (handleStorageRegister maps it to the stable path for the registry).
// - eject/wipe post the STABLE (registered) path — their handlers map it to raw for the agent via
// agentWhere() AND deregister it from the registry (which stores the stable path). Posting the
// raw path here would unmount the drive but leave the stable registry entry orphaned.
if(!registered[regKey(d)]){
btns += '<button class="btn btn-xs btn-primary" onclick="registerDrive(\''+mp+'\')">Regisztrálás</button> ';
btns += '<button class="btn btn-xs btn-primary" onclick="registerDrive(\''+mpRaw+'\')">Regisztrálás</button> ';
}
btns += '<button class="btn btn-xs btn-danger-outline" onclick="confirmEject(\''+mp+'\')">Leválasztás</button>';
if(d.backing_device){ btns += ' <button class="btn btn-xs btn-danger-outline" onclick="confirmWipe(\''+dev+'\',\''+mp+'\')">Törlés…</button>'; }
btns += '<button class="btn btn-xs btn-danger-outline" onclick="confirmEject(\''+reg+'\')">Leválasztás</button>';
if(d.backing_device){ btns += ' <button class="btn btn-xs btn-danger-outline" onclick="confirmWipe(\''+dev+'\',\''+reg+'\')">Törlés…</button>'; }
return '<div class="drive-actions">'+btns+'</div>';
}
async function load(){
@@ -502,7 +504,11 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
var html='<p class="drive-tiering-note">Az alkalmazások rendszere és adatbázisai a belső SSD-n (local-lvm), a nagy méretű fájljaik a külső adattárolókon tárolódnak.</p>';
html+='<div class="drive-list">';
disks.forEach(function(d){
var sub = esc(d.type)+' · '+esc(d.backing_device||'—')+(d.mount_path?' · '+esc(d.mount_path):'');
// Show the path the customer's system actually uses: the STABLE in-guest path
// (/mnt/felhom-drives/<name>, = guest_path) for an external drive, not the raw host PVE mount
// (/mnt/<name>) which doesn't exist inside the guest. regKey falls back to mount_path for
// non-intermediary drives (system/local).
var sub = esc(d.type)+' · '+esc(d.backing_device||'—')+(d.mount_path?' · '+esc(regKey(d)):'');
var badges = roleBadge(d.role)+appBackingTag(d)+classBadge(d)+dataBadge(d)+regBadge(d,registered);
var purpose = purposeDesc(d);
html+='<div class="drive-card role-'+esc(d.role||'system')+'">'
@@ -569,7 +575,9 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
setTimeout(function(){location.reload();}, 45000);
};
window.confirmEject=function(where){
var name=where.replace(/^\/mnt\//,'');
// The confirm name is the drive BASENAME (matches the server's path.Base(where) check); `where` may
// be the stable /mnt/felhom-drives/<name> path, so strip the whole directory, not just the /mnt/ prefix.
var name=where.split('/').filter(Boolean).pop()||where;
openConfirm({title:'Meghajtó leválasztása', mount:where, mountName:name,
danger:'A meghajtó leválasztásra kerül. Az adatok megmaradnak, de az ott tárolt alkalmazások elvesztik a tárhelyüket, amíg újra nem csatolja.',
onConfirm:async function(){
@@ -582,7 +590,8 @@ window.__registeredPaths=[{{range .StoragePaths}}{{if .Path}}"{{.Path}}",{{end}}
}});
};
window.confirmWipe=function(device, where){
var name=where.replace(/^\/mnt\//,'');
// Basename (matches the server's path.Base(where) type-to-confirm check); `where` may be the stable path.
var name=where.split('/').filter(Boolean).pop()||where;
openConfirm({title:'Meghajtó törlése (formázás)', mount:where, mountName:name,
danger:'FIGYELEM: a meghajtón lévő ÖSSZES ADAT véglegesen törlődik (formázás). Ez nem vonható vissza.',
onConfirm:async function(){