banshee est en développement actif : les collecteurs vont encore changer, et une version que vous publiez demandera sans doute des ajustements. Pour un usage stable, attendez la version 1.0.0.

Storage

banshee/storage-collection/storage/truenas/https/api-v2.0/

disks

The state and the error counts of each disk of the ZFS pools of a TrueNAS by its REST API v2.0.

  • storage
  • truenas
  • zfs
  • disk
  • https
  • api

par banshee1 installation1 version

v1Dernière

Publiée le 27 octobre 2026. First version.

Keen 1.0.0 · 67 lignes
// The state and the error counts of each disk of the ZFS pools of a TrueNAS, by its REST API v2.0
// (GET /api/v2.0/pool, the topology of each pool), behind an API key: what zpool status shows for each
// device. The REST API v2.0 answers on TrueNAS CORE 12 and 13 and on TrueNAS SCALE up to 25.10.
// A disk outside any pool is not read: ZFS knows nothing of it.
need('protocol:http');
$address = need('host:address');
$token = need('protocol:http:token');

per('disk', 'Disks');
output('state', 'text', array('label' => 'State', 'per' => 'disk'));
output('errors', 'number', array('label' => 'Read, write and checksum errors', 'per' => 'disk'));

watch.expect('not-online', 'Disk not online', 'state', array('warning' => array('online', 'avail')));
watch.state('failed', 'Disk failed', 'state', array('critical' => array('faulted', 'unavail', 'removed')));
watch.above('errors', 'Disk errors', 'errors', array('warning' => 0));
watch.missing('missing', 'Disk missing', 'state', array('enabled' => false));

// The key goes in a header: the answer is not secret, its body having carried none.
$answer = http.get('https://' . $address . '/api/v2.0/pool', headers=array('Authorization' => 'Bearer ' . $token));
if ($answer['status'] == 401 || $answer['status'] == 403) {
    fail('misconfigured', 'The TrueNAS API refuses the key, code ' . $answer['status']);
}
if ($answer['status'] != 200) {
    fail('unreachable', 'The TrueNAS API answers code ' . $answer['status'],
        'A TrueNAS 26 or later has no REST API: it answers 404.');
}

// Each pool has a topology: {"data": [...], "log": [...], "cache": [...], "spare": [...], "special": [...],
// "dedup": [...]}, each a list of devices {"name", "type", "status", "stats": {"read_errors",
// "write_errors", "checksum_errors"}, "children": [...]}. A mirror or a RAIDZ holds its disks in children,
// and a disk being replaced holds the old and the new one: the devices are walked through a list that
// grows, until none is left. Only a pool online or degraded is read: a failed pool may have no topology.
$pools = json.read($answer['body']);
$read = 0;
foreach ($pools as $pool) {
    $health = text.lower($pool['status']);
    if ($health != 'online' && $health != 'degraded') {
        continue;
    }
    foreach (array('data', 'log', 'cache', 'spare', 'special', 'dedup') as $group) {
        $pending = list.get($pool['topology'], $group, array());
        $i = 0;
        while ($i < list.count($pending)) {
            $device = $pending[$i];
            $i = $i + 1;
            $children = list.get($device, 'children', array());
            if (list.count($children) > 0) {
                foreach ($children as $child) {
                    $pending = list.add($pending, $child);
                }
                continue;
            }
            if ($device['type'] != 'DISK') {
                continue;
            }
            // The device's name is the one ZFS keeps, which a missing disk keeps too.
            $name = $pool['name'] . ': ' . $device['name'];
            $stats = $device['stats'];
            $read = $read + 1;
            value('state', text.lower($device['status']), $name);
            value('errors', $stats['read_errors'] + $stats['write_errors'] + $stats['checksum_errors'], $name);
        }
    }
}
if ($read == 0) {
    fail('misconfigured', 'The TrueNAS API shows no disk in an online or degraded pool');
}