feat(widgets): add disks widget (#4445)

Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-01-23 16:23:42 +01:00
1 parent 15119b66e9
commit 62caa71a48
11 files changed
+206 -3

No files matched your search

@@ -55,7 +55,7 @@ export class DashDotIntegration extends Integration implements ISystemHealthMoni
cpuTemp: cpuLoad.averageTemperature,
availablePkgUpdates: 0,
rebootRequired: false,
smart: [],
smart: [], // API endpoint does not provide S.M.A.R.T data.
uptime: info.uptime,
version: `${info.operatingSystemVersion}`,
loadAverage: {
@@ -29,6 +29,7 @@ export interface SystemHealthMonitoring {
deviceName: string;
temperature: number | null;
overallStatus: string;
healthy: boolean;
}[];
}
@@ -33,6 +33,7 @@ export class SystemHealthMonitoringMockService implements ISystemHealthMonitorin
deviceName: "Mock Device",
temperature: Math.floor(Math.random() * 100), // Random temperature between 0 and 99
overallStatus: "OK",
healthy: true,
},
],
});
@@ -62,6 +62,8 @@ export class OpenMediaVaultIntegration extends Integration implements ISystemHea
const smart = smartResult.data.response.map((smart) => ({
deviceName: smart.devicename,
temperature: smart.temperature,
// https://github.com/openmediavault/openmediavault/blob/2eb871d05cec6ff49603134d3acead561da01e4d/deb/openmediavault/usr/share/php/openmediavault/system/storage/smartinformation.inc#L592-L605
healthy: smart.overallstatus === "GOOD",
overallStatus: smart.overallstatus,
}));
@@ -112,6 +112,27 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
});
}
private async getPoolsAsync() {
logger.debug("Retrieving pools", {
url: this.wsUrl(),
});
const response = await this.requestAsync("pool.query", [
[],
{
extra: {
is_upgraded: true,
},
},
]);
const result = await poolSchema.parseAsync(response);
logger.debug("Retrieved pools", {
url: this.wsUrl(),
count: result.length,
});
return result;
}
/**
* Retrieves data using the reporting method
* @see https://www.truenas.com/docs/api/scale_websocket_api.html#reporting
@@ -225,6 +246,7 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
const cpuData = this.extractLatestReportingData(reporting, "cpu");
const cpuTempData = this.extractLatestReportingData(reporting, "cputemp");
const memoryData = this.extractLatestReportingData(reporting, "memory");
const datasets = await this.getPoolsAsync();
const netdata = await this.getReportingNetdataAsync();
@@ -236,14 +258,24 @@ export class TrueNasIntegration extends Integration implements ISystemHealthMoni
cpuTemp: Math.max(...cpuTempData.filter((_item, i) => i > 0)),
memAvailableInBytes: systemInformation.physmem,
memUsedInBytes: memoryData[1] ?? 0, // Index 0 is UNIX timestamp, Index 1 is free space in bytes
fileSystem: [],
fileSystem: datasets.map((dataset) => ({
deviceName: dataset.name,
available: `${dataset.size}`, // TODO: can we use number instead of string here?
used: `${dataset.allocated}`,
percentage: (dataset.allocated / dataset.size) * 100,
})),
availablePkgUpdates: 0,
network: {
up: upload * NETWORK_MULTIPLIER,
down: download * NETWORK_MULTIPLIER,
},
loadAverage: null,
smart: [],
smart: datasets.map((dataset) => ({
deviceName: dataset.name,
healthy: dataset.healthy,
overallStatus: dataset.status,
temperature: null,
})),
uptime: systemInformation.uptime_seconds,
version: systemInformation.version,
cpuModelName: systemInformation.model,
@@ -351,6 +383,17 @@ const reportingItemSchema = z.object({
type ReportingItem = z.infer<typeof reportingItemSchema>;
const poolSchema = z.array(
z.object({
name: z.string(),
status: z.string(),
healthy: z.boolean(),
free: z.number().min(0),
size: z.number(),
allocated: z.number(),
}),
);
const reportingNetDataSchema = z.array(
z.object({
name: z.string(),
@@ -67,6 +67,8 @@ export class UnraidIntegration extends Integration implements ISystemHealthMonit
deviceName: disk.name,
temperature: disk.temp ?? null,
overallStatus: disk.status,
// See ArrayDiskStatus from https://studio.apollographql.com/public/Unraid-API/variant/current/explorer
healthy: disk.status === "DISK_OK",
})),
};
}