Cloud
banshee/cloud-collection/cloud/ovh/https/
public-cloud-instances
The status of each instance of an OVHcloud Public Cloud project, every region at once, by the OVHcloud API.
by banshee0 installations1 version
Published on October 27, 2026. First version.
// The instances of an OVHcloud Public Cloud project, every region at once, by the OVHcloud API with an
// application's keys: the status of each instance.
// Reads GET <api>/cloud/project/<project>/instance, signed by ovh.sign.
need('protocol:http');
need('protocol:ovh');
$endpoint = need('protocol:ovh:endpoint');
$project = variable('ovh:project', 'text', array(
'label' => 'Project',
'help' => 'The ID of the Public Cloud project, 32 hexadecimal characters, as the Control Panel shows it under the name of the project.',
));
per('instance', 'Instances');
output('status', 'text', array('label' => 'Status', 'per' => 'instance'));
watch.expect('not-running', 'Instance not running', 'status', array('critical' => array('active'), 'for' => '2 runs'));
watch.missing('missing', 'Instance missing', 'status', 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);
// [{"id": "…", "name": "web-1", "region": "GRA11", "status": "ACTIVE", "flavorId": "…", …}]: every instance of
// the project. status is ACTIVE, BUILD, SHUTOFF, ERROR, RESCUE, SHELVED_OFFLOADED and the other states of
// OpenStack. The answer also holds the rescue password of an instance in rescue mode: it is never read.
// An instance is named by its name; two instances of one name each keep their own, the second carrying its id.
$instances = ovh_get($api, '/cloud/project/' . url.encode($project) . '/instance', 'the instances of the project');
$seen = array();
foreach ($instances as $instance) {
$name = $instance['name'];
if (list.has($seen, $name)) {
$name = $name . ' #' . $instance['id'];
}
$seen[$name] = true;
value('status', text.lower($instance['status']), $name);
}