Skip to main content

resource_tracker/collector/clouds/
ovh.rs

1use crate::metrics::CloudInfo;
2use serde::Deserialize;
3
4use super::{imds_get, new_imds_agent};
5
6#[derive(Debug, Deserialize)]
7struct NetworkService {
8    #[serde(rename = "type")]
9    service_type: Option<String>,
10    address: Option<String>,
11}
12
13#[derive(Debug, Deserialize)]
14struct NetworkData {
15    services: Option<Vec<NetworkService>>,
16}
17
18#[derive(Debug, Deserialize)]
19struct MetaData {
20    availability_zone: Option<String>,
21}
22
23/// OVH Public Cloud via OpenStack metadata endpoints.
24///
25/// Identifies OVH by checking that a DNS service entry in `network_data.json`
26/// reports `213.186.33.99` (OVH's dedicated resolver). Region comes from
27/// `availability_zone` in `meta_data.json`; instance type from the
28/// EC2-compatible endpoint that OVH also exposes.
29///
30/// Reference: <https://docs.openstack.org/nova/latest/user/metadata.html>
31pub fn probe() -> Option<CloudInfo> {
32    let agent = new_imds_agent();
33
34    // Confirm OVH fingerprint: DNS address in OpenStack network_data.json.
35    let network_body = imds_get(
36        &agent,
37        "http://169.254.169.254/openstack/latest/network_data.json",
38    )?;
39    let network_data: NetworkData = serde_json::from_str(&network_body).ok()?;
40    let is_ovh = network_data
41        .services
42        .as_deref()
43        .unwrap_or_default()
44        .iter()
45        .any(|s| {
46            s.service_type.as_deref() == Some("dns")
47                && s.address.as_deref() == Some("213.186.33.99")
48        });
49    if !is_ovh {
50        return None;
51    }
52
53    // Region: availability_zone from OpenStack meta_data.json ("nova" is meaningless).
54    let cloud_region_id = imds_get(
55        &agent,
56        "http://169.254.169.254/openstack/latest/meta_data.json",
57    )
58    .and_then(|body| serde_json::from_str::<MetaData>(&body).ok())
59    .and_then(|m| m.availability_zone)
60    .filter(|az| !az.is_empty() && az != "unknown" && az != "nova");
61
62    // Instance type from the EC2-compatible endpoint OVH also exposes.
63    let cloud_instance_type = imds_get(
64        &agent,
65        "http://169.254.169.254/latest/meta-data/instance-type",
66    )
67    .filter(|s| !s.is_empty() && s != "unknown");
68
69    Some(CloudInfo {
70        cloud_vendor_id: Some("ovh".to_string()),
71        cloud_account_id: None,
72        cloud_region_id,
73        cloud_zone_id: None,
74        cloud_instance_type,
75    })
76}