fix: one source for the disk type and a config volume for SearXNG

This commit is contained in:
MacRimi
2026-11-02 17:28:31 +01:00
parent 41081121f8
commit 9f3fffd249
11 changed files with 208 additions and 53 deletions
+54
View File
@@ -0,0 +1,54 @@
"""Every view of a disk takes its rotation and type from disk_identity."""
from pathlib import Path
import sys
import tempfile
import types
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "AppImage/scripts"))
import disk_identity
import audit_inventory
class DiskMediaTypeTests(unittest.TestCase):
def setUp(self):
folder = tempfile.TemporaryDirectory()
self.addCleanup(folder.cleanup)
self.root = Path(folder.name)
for name, flag in (("sda", "1"), ("sdb", "0"), ("nvme0n1", "0")):
(self.root / name / "queue").mkdir(parents=True)
(self.root / name / "queue/rotational").write_text(flag + "\n")
sys_block = patch.object(disk_identity, "_SYS_BLOCK", str(self.root))
sys_block.start()
self.addCleanup(sys_block.stop)
def test_the_kernel_flag_answers_when_smartctl_did_not(self):
self.assertEqual(disk_identity.rotation_rate("sda"), -1)
self.assertEqual(disk_identity.rotation_rate("sdb"), 0)
self.assertEqual(disk_identity.rotation_rate("sdz"), 0)
def test_what_smartctl_reported_wins(self):
self.assertEqual(disk_identity.rotation_rate("sda", 0), 0)
self.assertEqual(disk_identity.rotation_rate("sdb", 5400), 5400)
self.assertEqual(disk_identity.rotation_rate("sda", None), -1)
def test_media_type(self):
self.assertEqual(disk_identity.media_type("sda", -1), "HDD")
self.assertEqual(disk_identity.media_type("sda", 7200), "HDD")
self.assertEqual(disk_identity.media_type("sdb", 0), "SSD")
self.assertEqual(disk_identity.media_type("nvme0n1", 0), "NVMe")
def test_the_inventory_agrees_with_the_monitor(self):
rows = ('NAME="sda" MODEL="WDC WD7500BPVT" SERIAL="WX1" SIZE="750156374016" ROTA="1" TRAN="usb" TYPE="disk"\n'
'NAME="sdb" MODEL="Samsung SSD" SERIAL="S1" SIZE="500107862016" ROTA="0" TRAN="sata" TYPE="disk"\n')
ctx = types.SimpleNamespace(run=lambda *a, **k: (0, rows),
monitor_snapshot={"smart": {"/dev/sda": [0, {"rotation_rate": 0}]}})
with patch.object(audit_inventory, "_disk_observations", return_value={}):
disks = {d["name"]: d["rotational"] for d in audit_inventory._physical_disks(ctx)}
# The USB bridge marks sda rotational; smartctl, through the Monitor, says solid state.
self.assertEqual(disks, {"sda": False, "sdb": False})
if __name__ == "__main__":
unittest.main()
+14 -1
View File
@@ -209,10 +209,16 @@ class QuietDiskIdentityTests(unittest.TestCase):
self.read = Mock(return_value={"model": "WDC WD40EFRX-68N32N0", "serial": "WD-WCC7K4FV37J0",
"rotation_rate": 5400, "health": "healthy", "temperature": 31})
self.cache = {}
self.backoff = {}
import disk_identity
sys_block = patch.object(disk_identity, "_SYS_BLOCK", str(root / "sys/block"))
sys_block.start()
self.addCleanup(sys_block.stop)
namespace = {"Path": lambda path: root / path.lstrip("/"), "time": __import__("time"),
"disk_identity": disk_identity,
"_smart_result_cache": self.cache, "_SMART_RESULT_TTL": 30, "_hdd_in_standby": self.standby,
"_get_smart_data_uncached": self.read, "_smart_data_useful": lambda data: data.get("model") != "Unknown",
"_smart_fail_backoff": {}, "_smart_fail_counts": {}, "_smart_probe_cache": {},
"_smart_fail_backoff": self.backoff, "_smart_fail_counts": {}, "_smart_probe_cache": {},
"_SMART_FAIL_THRESHOLD": 3, "_SMART_FAIL_BACKOFF_SEC": 3600}
tree = ast.parse((SCRIPTS / "flask_server.py").read_text())
nodes = [n for n in tree.body if isinstance(n, ast.FunctionDef)
@@ -240,6 +246,13 @@ class QuietDiskIdentityTests(unittest.TestCase):
self.read.assert_not_called()
self.assertEqual((data["model"], data["rotation_rate"], data["excluded"]), ("WDC WD40EFRX-68N32N0", -1, True))
def test_a_disk_smartctl_keeps_failing_on_keeps_its_identity(self):
self.backoff["sdb"] = __import__("time").time() + 3600
data = self.get("sdb")
self.read.assert_not_called()
self.assertEqual((data["model"], data["serial"], data["rotation_rate"]),
("WDC WD40EFRX-68N32N0", "WD-WCC7K4FV37J0", -1))
if __name__ == "__main__":
unittest.main()
+14 -1
View File
@@ -55,12 +55,15 @@ console.log('PASS: saved-data badge guards and actual provider fallback/translat
const report = source.statements.find(n => ts.isFunctionDeclaration(n) && n.name?.text === 'openSmartReport');
assert.ok(report);
let reportHtml;
const diskTypeModule = {};
new Function('exports', compile(read('AppImage/lib/disk-type.ts')))(diskTypeModule);
const openReport = new Function('window', 'Blob', 'URL', 'setTimeout', 'getDiskTempThresholdsSync', 'getNvmeSmartAttributeKey',
'resolveDiskType',
compile('const APP_VERSION = "fixture";\n' + emit(report, source)) + '\nreturn openSmartReport;')(
{location: {origin: 'http://fixture.invalid'}, open() {}},
class { constructor(parts) { reportHtml = parts.join(''); } },
{createObjectURL() { return 'blob:fixture'; }, revokeObjectURL() {}}, () => {},
() => ({warning: 55, critical: 65}), () => undefined);
() => ({warning: 55, critical: 65}), () => undefined, diskTypeModule.getDiskType);
const expectedReport = {
passedAssessment: 'The supplied SMART status is PASSED. This status alone does not establish that every attribute is within range or that the disk is free of faults. Power-on time shown: {uptime}. Temperature shown: {temperature}. {sectors}',
noReallocatedSectorsReported: 'The supplied reallocated-sector value is zero or unavailable; this does not establish that there are no bad sectors.',
@@ -107,5 +110,15 @@ translated.recommendations = {passedTitle: 'TRANSLATED_REC_TITLE', passedText: '
const localized = renderReport({}, 'passed', 'synthetic', {...catalogs, synthetic: {storage: {smartReport: translated}}});
for (const [, value] of leaves(translated)) assert.ok(localized.includes(value.split(' {')[0]), value);
assert.ok(renderReport({name: 'nvme0n1'}, 'passed', 'en', catalogs, {nvme_raw: {critical_warning: 0, media_errors: 7}}).includes(expectedReport.passedMeaning));
// One classifier for the report and the Storage page: a disk the kernel marks
// rotational without an RPM is an HDD, and a real model wins over "Unknown".
const typeCard = html => html.match(/labels\.type[^]*?card-value[^>]*>([^<]*)</)?.[1] ?? html.match(/>Type<\/div>\s*<div class="card-value"[^>]*>([^<]*)</)?.[1];
assert.equal(typeCard(renderReport({rotation_rate: -1})), 'HDD');
assert.equal(typeCard(renderReport({rotation_rate: 7200})), 'HDD 7200 RPM');
assert.equal(typeCard(renderReport({rotation_rate: 0})), 'SSD');
assert.ok(!renderReport({rotation_rate: -1}).includes('-1 RPM'));
assert.equal(typeCard(renderReport({rotation_rate: -1, connection_type: 'sas'})), 'SAS HDD');
const unknownModel = renderReport({model: 'Unknown', serial: 'Unknown'}, 'passed', 'en', catalogs, {model: 'WDC WD7500BPVT', serial: 'WX11A1234'});
assert.ok(unknownModel.includes('WDC WD7500BPVT') && unknownModel.includes('WX11A1234'));
if (process.env.STORAGE_REPORT_HTML) fs.writeFileSync(process.env.STORAGE_REPORT_HTML, renderReport());
console.log('PASS: actual printable report, passed/failed/unknown/warning, missing/zero/nonzero sectors, NVMe errors and provider fallback');