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.
by banshee0 installations1 version
Published on October 27, 2026. First version.
// 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);
}