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/

public-cloud-instances

The status of each instance of an OVHcloud Public Cloud project, every region at once, by the OVHcloud API.

  • cloud
  • ovhcloud
  • ovh
  • public-cloud
  • openstack
  • instances
  • https
  • api

by banshee0 installations1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 65 lines
// 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);
}