banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Virtualization

banshee/virtualization-collection/virtualization/proxmox/https/

storage

Whether each storage of a Proxmox VE cluster is available on each node, and its space, by its API.

  • virtualization
  • proxmox
  • pve
  • storage
  • https
  • api

by banshee1 installation2 versions

Keen 1.0.0 · 63 lines
// The storage of a Proxmox VE cluster, or a single Proxmox VE server, by its API behind an API token (GET
// /api2/json/cluster/resources?type=storage): whether each storage is available on each node, and its space.
// A storage is seen from each node that has it enabled, a shared one as well: it is named "<node>/<storage>".
// The address is any node of the cluster, the host's: https://<host:address>:<port>/api2/json/.
need('protocol:http');
$address = need('host:address');
$token = need('protocol:http:token');
$port = variable('proxmox:port', 'integer', array(
    'label'   => 'API port',
    'help'    => 'The port of the Proxmox VE API: 8006, unless a proxy serves it on another.',
    'default' => 8006,
));

per('storage', 'Storage');
output('state', 'text', array('label' => 'State', 'per' => 'storage'));
output('used', 'number', array('label' => 'Used space', 'unit' => '%', 'per' => 'storage'));
output('free', 'number', array('label' => 'Free space', 'unit' => 'GiB', 'per' => 'storage'));
output('size', 'number', array('label' => 'Size', 'unit' => 'GiB', 'per' => 'storage'));

watch.expect('not-available', 'Storage not available', 'state', array('critical' => array('available')));
watch.above('used', 'Used space', 'used', array('warning' => 85, 'critical' => 95));
watch.above('full-soon', 'Full within a week', 'used', array('warning' => 99, 'ahead' => '7 d'));
watch.missing('missing', 'Storage missing', 'state', array('enabled' => false));

// One GET, the token in the header Authorization: PVEAPIToken=<user>@<realm>!<token id>=<secret>. Proxmox VE
// answers {"data": ...}. The answer is not secret, its body having carried none.
function api_get($base, $path, $token) {
    $answer = http.get($base . $path, headers=array('Authorization' => 'PVEAPIToken=' . $token));
    if ($answer['status'] == 401) {
        fail('misconfigured', 'Proxmox VE refuses the API token, code 401');
    }
    if ($answer['status'] == 403) {
        fail('misconfigured', 'The API token may not read ' . $path . ', code 403');
    }
    if ($answer['status'] != 200) {
        fail('unreachable', 'Proxmox VE answers ' . $path . ' with code ' . $answer['status']);
    }
    $page = json.read($answer['body']);
    return $page['data'];
}

$base = 'https://' . $address . ':' . $port . '/api2/json';

// [{"id": "storage/pve1/local-zfs", "storage": "local-zfs", "node": "pve1", "type": "storage", "status":
// "available", "disk": 107374182400, "maxdisk": 429496729600, "shared": 0, "content": "images,rootdir",
// "plugintype": "zfspool"}], in bytes. The status is "available" when the node reports the storage, and
// "unknown" otherwise (inactive, unreachable, or the node down), without space.
$storages = api_get($base, '/cluster/resources?type=storage', $token);
if (list.count($storages) == 0) {
    fail('misconfigured', 'Proxmox VE lists no storage', 'The API token sees only the storage it has Datastore.Audit on.');
}
foreach ($storages as $storage) {
    $name = $storage['node'] . '/' . $storage['storage'];
    value('state', $storage['status'], $name);
    if (list.get($storage, 'maxdisk', 0) <= 0) {
        continue;
    }
    $size = $storage['maxdisk'];
    $used = list.get($storage, 'disk', 0);
    value('used', number.round(100 * $used / $size, 1), $name);
    value('free', number.round(($size - $used) / 1073741824, 1), $name);
    value('size', number.round($size / 1073741824, 1), $name);
}