setup: stop calling the app-data drive "System disk" when it is not
The wizard's Storage step builds its first entry from primaryRoot() — the app-data root — and labelled it "System disk". On a default install those are the same drive and the name is honest. Installed with --containers-dir on its own disk they are not, and the step then showed the DATA drive's size under the system disk's name while the actual system disk never appeared in the list. Seen on a matrix case-2 install (apps on a 29.4G test disk, system on a 912G root): "System disk — 26.7G free of 29.4G". The generator now reports whether that root is really on the OS disk (is_os_disk, by st_dev against /), and the wizard labels it from that: "System disk" when they coincide, otherwise the mount point. The "system" badge stays — it marks the default location, which is still what it is. Also add lp-shot --token / --cookie-js. A screenshot answers "does it render"; "does this wizard step work" needs clicking, which needs a real browser, which needs the session lp-shot already knows how to mint from the stored jwtSecret. This bug was found that way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
864059ab83
commit
7ed8539af7
@ -527,6 +527,16 @@ class SetupWizard {
|
|||||||
//
|
//
|
||||||
// The badge carries severity and Details carries the explanation, so the card
|
// The badge carries severity and Details carries the explanation, so the card
|
||||||
// stays a single row.
|
// stays a single row.
|
||||||
|
// What to call the default app-data location. It is the OS disk on a normal
|
||||||
|
// install, but --containers-dir can put it on its own drive, and calling that
|
||||||
|
// "System disk" showed the data drive's size under the system disk's name
|
||||||
|
// while the actual system disk was absent from the list.
|
||||||
|
_primaryLabel() {
|
||||||
|
const s = this.storageSystem;
|
||||||
|
if (!s || s.is_os_disk !== false) return 'System disk';
|
||||||
|
return s.mount && s.mount !== '/' ? s.mount : (s.path || 'Default location');
|
||||||
|
}
|
||||||
|
|
||||||
_storageCard(c, key, opts) {
|
_storageCard(c, key, opts) {
|
||||||
const o = opts || {};
|
const o = opts || {};
|
||||||
const refused = c.verdict === 'refuse';
|
const refused = c.verdict === 'refuse';
|
||||||
@ -535,7 +545,7 @@ class SetupWizard {
|
|||||||
: (refused ? '<span class="setup-storage-badge setup-storage-badge-bad">can\u2019t be used</span>'
|
: (refused ? '<span class="setup-storage-badge setup-storage-badge-bad">can\u2019t be used</span>'
|
||||||
: (c.verdict === 'warn' ? '<span class="setup-storage-badge setup-storage-badge-warn">needs care</span>' : ''));
|
: (c.verdict === 'warn' ? '<span class="setup-storage-badge setup-storage-badge-warn">needs care</span>' : ''));
|
||||||
|
|
||||||
const title = o.system ? 'System disk' : c.path;
|
const title = o.system ? this._primaryLabel() : c.path;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="setup-app setup-storage-card${refused ? ' setup-storage-disabled' : ''} setup-storage-locked">
|
<div class="setup-app setup-storage-card${refused ? ' setup-storage-disabled' : ''} setup-storage-locked">
|
||||||
@ -553,7 +563,7 @@ class SetupWizard {
|
|||||||
|
|
||||||
// Every place a root could go: the system disk, plus each usable candidate.
|
// Every place a root could go: the system disk, plus each usable candidate.
|
||||||
_storageChoices() {
|
_storageChoices() {
|
||||||
const opts = [{ value: 'primary', label: 'System disk' }];
|
const opts = [{ value: 'primary', label: this._primaryLabel() }];
|
||||||
this.storageCandidates
|
this.storageCandidates
|
||||||
.filter(c => c.verdict !== 'refuse')
|
.filter(c => c.verdict !== 'refuse')
|
||||||
.forEach(c => opts.push({ value: c.path, label: c.path }));
|
.forEach(c => opts.push({ value: c.path, label: c.path }));
|
||||||
@ -681,7 +691,7 @@ class SetupWizard {
|
|||||||
this.storageCandidates
|
this.storageCandidates
|
||||||
.filter(c => c.verdict !== 'refuse')
|
.filter(c => c.verdict !== 'refuse')
|
||||||
.forEach(c => opts.push({ value: c.path, label: c.path, shared: c.path === appTarget }));
|
.forEach(c => opts.push({ value: c.path, label: c.path, shared: c.path === appTarget }));
|
||||||
opts.push({ value: 'primary', label: 'System disk', shared: this.storageDefault === 'primary' });
|
opts.push({ value: 'primary', label: this._primaryLabel(), shared: this.storageDefault === 'primary' });
|
||||||
|
|
||||||
box.innerHTML = `
|
box.innerHTML = `
|
||||||
<div class="setup-storage-choice">
|
<div class="setup-storage-choice">
|
||||||
@ -890,7 +900,7 @@ class SetupWizard {
|
|||||||
const m = window.openEoModal({
|
const m = window.openEoModal({
|
||||||
id: 'lp-storage-details',
|
id: 'lp-storage-details',
|
||||||
size: 'md',
|
size: 'md',
|
||||||
title: isSystem ? 'System disk' : c.path,
|
title: isSystem ? this._primaryLabel() : c.path,
|
||||||
desc: `${c.size} drive \u00b7 ${c.free} free \u00b7 ${c.fstype}${c.removable ? ' \u00b7 removable' : ''}`,
|
desc: `${c.size} drive \u00b7 ${c.free} free \u00b7 ${c.fstype}${c.removable ? ' \u00b7 removable' : ''}`,
|
||||||
body: parts.join(''),
|
body: parts.join(''),
|
||||||
actions: [{ label: 'Close', variant: 'secondary' }],
|
actions: [{ label: 'Close', variant: 'secondary' }],
|
||||||
|
|||||||
@ -358,6 +358,24 @@ class CDP:
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
# Print a session cookie and exit. A screenshot is enough for "does it
|
||||||
|
# render", but not for "does this wizard step work" — that needs clicking,
|
||||||
|
# which means driving a real browser, which needs the same session lp-shot
|
||||||
|
# already knows how to mint. Without this the only way in is typing the
|
||||||
|
# admin password into the login form.
|
||||||
|
#
|
||||||
|
# lp-shot --token -> the raw cookie VALUE
|
||||||
|
# lp-shot --cookie-js -> a document.cookie assignment to paste/eval
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] in ("--token", "--cookie-js"):
|
||||||
|
token, src = mint_token()
|
||||||
|
if os.environ.get("LP_SHOT_VERBOSE"):
|
||||||
|
print(f"signed from {src}", file=sys.stderr)
|
||||||
|
if sys.argv[1] == "--token":
|
||||||
|
print(token)
|
||||||
|
else:
|
||||||
|
print(f'document.cookie = "{COOKIE}={token}; path=/"')
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
|
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
|
||||||
print(__doc__.strip())
|
print(__doc__.strip())
|
||||||
sys.exit(0 if len(sys.argv) > 1 else 2)
|
sys.exit(0 if len(sys.argv) > 1 else 2)
|
||||||
|
|||||||
@ -73,6 +73,14 @@ webuiGenerateStorageCandidates()
|
|||||||
local sys_pct; sys_pct=$(df -Pk "$sys_root" 2>/dev/null | awk 'NR==2 {gsub("%","",$5); print $5}')
|
local sys_pct; sys_pct=$(df -Pk "$sys_root" 2>/dev/null | awk 'NR==2 {gsub("%","",$5); print $5}')
|
||||||
system_json+=",\"used_pct\":${sys_pct:-0}"
|
system_json+=",\"used_pct\":${sys_pct:-0}"
|
||||||
system_json+=",\"removable\":false"
|
system_json+=",\"removable\":false"
|
||||||
|
# Is this entry actually the OS disk? On a default install the app-data root
|
||||||
|
# sits on /, and "System disk" is the honest name for it. Installed with
|
||||||
|
# --containers-dir on another drive it does not, and calling that the system
|
||||||
|
# disk reports the WRONG size (the data drive's) while the real system disk
|
||||||
|
# never appears in the list at all.
|
||||||
|
local sys_is_os=false
|
||||||
|
[[ "$(stat -c '%d' -- "$sys_root" 2>/dev/null)" == "$(stat -c '%d' -- / 2>/dev/null)" ]] && sys_is_os=true
|
||||||
|
system_json+=",\"is_os_disk\":$sys_is_os"
|
||||||
system_json+=",\"apps\":\"$(_lpJsonEsc "$(storageAppsOnRoot "$sys_root" 2>/dev/null | paste -sd, -)")\""
|
system_json+=",\"apps\":\"$(_lpJsonEsc "$(storageAppsOnRoot "$sys_root" 2>/dev/null | paste -sd, -)")\""
|
||||||
system_json+=",\"checks\":$sys_checks}"
|
system_json+=",\"checks\":$sys_checks}"
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user