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/

guests

The state, node and high availability of each virtual machine and container of a Proxmox VE cluster by its API.

  • virtualization
  • proxmox
  • pve
  • vm
  • container
  • lxc
  • qemu
  • https
  • api

by banshee1 installation1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 78 lines
// The guests of a Proxmox VE cluster, or a single Proxmox VE server, by its API behind an API token (GET
// /api2/json/cluster/resources?type=vm): the state of each virtual machine and container, its name, the node
// it runs on, and its high-availability state when it has one. The watches of the expected state are not
// checked by default: only the administrator knows which guests must run and which must stay stopped, and
// says it by the selection of the probe, one probe for each.
// A guest is named by its id (VMID), unique in the cluster: its name is not, and Proxmox VE stops giving it
// when the guest's node is down, the moment the guest must still be seen under the same name.
// 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('guest', 'Guests');
output('state', 'text', array('label' => 'State', 'per' => 'guest'));
output('name', 'text', array('label' => 'Name', 'per' => 'guest'));
output('node', 'text', array('label' => 'Node', 'per' => 'guest'));
output('ha', 'text', array('label' => 'High availability', 'per' => 'guest'));

watch.expect('not-running', 'Guest not running', 'state', array(
    'help'     => 'For a selection of the guests that must run: critical when one is stopped or paused.',
    'critical' => array('running'),
    'enabled'  => false,
));
watch.expect('not-stopped', 'Guest not stopped', 'state', array(
    'help'    => 'For a selection of the guests that must stay stopped: warning when one runs.',
    'warning' => array('stopped'),
    'enabled' => false,
));
watch.state('ha-error', 'High availability in error', 'ha', array(
    'warning'  => array('fence', 'recovery'),
    'critical' => array('error'),
));
watch.missing('missing', 'Guest 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": "qemu/101", "vmid": 101, "name": "web01", "type": "qemu", "node": "pve1", "status": "running",
// "template": 0, "hastate": "started", ...}]. The status is running or stopped, and unknown, without name,
// for the guest of a node down. A template, never started, reads "template". hastate is given for a guest
// under high availability only.
$guests = api_get($base, '/cluster/resources?type=vm', $token);
foreach ($guests as $guest) {
    $id = '' . $guest['vmid'];
    $state = list.get($guest, 'status', 'unknown');
    if (list.get($guest, 'template', 0) == 1) {
        $state = 'template';
    }
    value('state', $state, $id);
    if (list.get($guest, 'name', '') != '') {
        value('name', $guest['name'], $id);
    }
    value('node', $guest['node'], $id);
    if (list.get($guest, 'hastate', '') != '') {
        value('ha', $guest['hastate'], $id);
    }
}