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.

Cloud

banshee/cloud-collection/cloud/ovh/https/

dedicated-servers

The state, the power and the planned interventions of each OVHcloud dedicated server of an account, by the OVHcloud API.

  • cloud
  • ovhcloud
  • ovh
  • dedicated-servers
  • bare-metal
  • interventions
  • https
  • api

by banshee0 installations1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 75 lines
// The dedicated servers of an OVHcloud account, by the OVHcloud API with an application's keys: for each server,
// its state as OVHcloud sees it, its power, and the planned interventions of the datacentre still to do or in
// progress.
// Reads GET <api>/dedicated/server, then for each server GET <api>/dedicated/server/<name> and
// <api>/dedicated/server/<name>/plannedIntervention, each signed by ovh.sign.
need('protocol:http');
need('protocol:ovh');
$endpoint = need('protocol:ovh:endpoint');

per('server', 'Dedicated servers');
output('state', 'text', array('label' => 'State', 'per' => 'server'));
output('power', 'text', array('label' => 'Power', 'per' => 'server'));
output('interventions', 'number', array('label' => 'Planned interventions to do or in progress', 'per' => 'server'));

watch.state('failing', 'Server in error', 'state', array(
    'help'     => 'Raises when OVHcloud marks the server in error, or hacked and cut off from the network.',
    'critical' => array('error', 'hacked', 'hackedBlocked'),
));
watch.state('powered-off', 'Server powered off', 'power', array('critical' => array('poweroff'), 'for' => '2 runs'));
watch.above('intervention', 'Datacentre intervention', 'interventions', array('warning' => 0));
watch.missing('missing', 'Server missing', 'state', array('enabled' => false));

// The address of the API set on the probe, checked: https:// only, its host and its version, without a final
// slash, https://eu.api.ovh.com/1.0. The signed headers go there and nowhere else.
function ovh_api($endpoint) {
    if (list.count(text.match($endpoint, '^https://[A-Za-z0-9.-]+/[0-9.]+$')) == 0) {
        fail('misconfigured', 'The address of the OVHcloud API is not written https://<host>/<version>',
            'For instance https://eu.api.ovh.com/1.0, https://ca.api.ovh.com/1.0 or https://api.us.ovhcloud.com/1.0.');
    }
    return $endpoint;
}

// One signed GET on the OVHcloud API: ovh.sign gives the headers that carry the application key, the consumer
// key and the signature; the application secret never leaves.
function ovh_get($api, $path, $what) {
    $url = $api . $path;
    $answer = http.get($url, headers=ovh.sign('GET', $url, ''));
    if ($answer['status'] == 401) {
        fail('misconfigured', 'OVHcloud refuses the keys, code 401',
            'The application key, its secret or the consumer key is wrong, expired or revoked, or the clock of the poller is off.');
    }
    if ($answer['status'] == 403) {
        fail('misconfigured', 'The consumer key may not read ' . $what . ', code 403',
            'Its access rules must allow GET on the routes the documentation of the collector names.');
    }
    if ($answer['status'] == 400 || $answer['status'] == 404) {
        fail('misconfigured', 'OVHcloud refuses to read ' . $what . ', code ' . $answer['status']);
    }
    if ($answer['status'] != 200) {
        fail('unreachable', 'OVHcloud answers the reading of ' . $what . ' with code ' . $answer['status']);
    }
    return json.read($answer['body']);
}

$api = ovh_api($endpoint);

// ["ns3000000.ip-203-0-113.eu", …]: the names of the servers, each the serviceName of its routes. A server:
// {"name": "ns3000000.ip-203-0-113.eu", "state": "ok", "powerState": "poweron", "datacenter": "rbx8", …};
// state is error, hacked, hackedBlocked or ok, powerState poweroff or poweron. A planned intervention:
// {"id": 12, "status": "todo", "type": "HARDWARE_UPGRADE_ON_ACTIVE_SERVER", "wantedStartDate": "…", …}, status
// todo, doing or done.
foreach (ovh_get($api, '/dedicated/server', 'the dedicated servers') as $name) {
    $path = '/dedicated/server/' . url.encode($name);
    $server = ovh_get($api, $path, 'the server ' . $name);
    value('state', $server['state'], $name);
    value('power', $server['powerState'], $name);
    $open = 0;
    foreach (ovh_get($api, $path . '/plannedIntervention', 'the interventions of ' . $name) as $id) {
        $intervention = ovh_get($api, $path . '/plannedIntervention/' . $id, 'an intervention of ' . $name);
        if ($intervention['status'] == 'todo' || $intervention['status'] == 'doing') {
            $open = $open + 1;
        }
    }
    value('interventions', $open, $name);
}