Skip to main content

nv_redfish/telemetry_service/
mod.rs

1// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! Telemetry Service entities and helpers.
17//!
18//! This module provides typed access to Redfish `TelemetryService`.
19
20mod metric_definition;
21mod metric_report;
22mod metric_report_definition;
23
24use crate::schema::redfish::metric_definition::MetricDefinition as MetricDefinitionSchema;
25use crate::schema::redfish::metric_report_definition::MetricReportDefinition as MetricReportDefinitionSchema;
26use crate::schema::redfish::telemetry_service::TelemetryService as TelemetryServiceSchema;
27use crate::schema::redfish::telemetry_service::TelemetryServiceUpdate;
28use crate::Error;
29use crate::NvBmc;
30use crate::Resource;
31use crate::ResourceSchema;
32use crate::ServiceRoot;
33use nv_redfish_core::Bmc;
34use nv_redfish_core::EntityTypeRef as _;
35use nv_redfish_core::ModificationResponse;
36use nv_redfish_core::NavProperty;
37use std::sync::Arc;
38
39#[doc(inline)]
40pub use metric_definition::MetricDefinition;
41#[doc(inline)]
42pub use metric_definition::MetricDefinitionCreate;
43#[doc(inline)]
44pub use metric_definition::MetricDefinitionUpdate;
45#[doc(inline)]
46pub use metric_report::MetricReportRef;
47#[doc(inline)]
48pub use metric_report_definition::MetricReportDefinition;
49#[doc(inline)]
50pub use metric_report_definition::MetricReportDefinitionCreate;
51#[doc(inline)]
52pub use metric_report_definition::MetricReportDefinitionType;
53#[doc(inline)]
54pub use metric_report_definition::MetricReportDefinitionUpdate;
55#[doc(inline)]
56pub use metric_report_definition::ReportActionsEnum;
57#[doc(inline)]
58pub use metric_report_definition::Wildcard;
59#[doc(inline)]
60pub use metric_report_definition::WildcardUpdate;
61
62/// Telemetry service.
63///
64/// Provides access to metric reports and metric definitions.
65pub struct TelemetryService<B: Bmc> {
66    data: Arc<TelemetryServiceSchema>,
67    bmc: NvBmc<B>,
68}
69
70impl<B: Bmc> TelemetryService<B> {
71    /// Create a new telemetry service handle.
72    pub(crate) async fn new(
73        bmc: &NvBmc<B>,
74        root: &ServiceRoot<B>,
75    ) -> Result<Option<Self>, Error<B>> {
76        if let Some(service_ref) = &root.root.telemetry_service {
77            let data = service_ref.get(bmc.as_ref()).await.map_err(Error::Bmc)?;
78            Ok(Some(Self {
79                data,
80                bmc: bmc.clone(),
81            }))
82        } else {
83            Ok(None)
84        }
85    }
86
87    /// Get the raw schema data for this telemetry service.
88    #[must_use]
89    pub fn raw(&self) -> Arc<TelemetryServiceSchema> {
90        self.data.clone()
91    }
92
93    /// Enable or disable telemetry service.
94    ///
95    /// # Errors
96    ///
97    /// Returns an error if updating telemetry service fails.
98    pub async fn set_enabled(&self, enabled: bool) -> Result<Option<Self>, Error<B>> {
99        let update = TelemetryServiceUpdate::builder()
100            .with_service_enabled(enabled)
101            .build();
102
103        match self
104            .bmc
105            .as_ref()
106            .update::<_, NavProperty<TelemetryServiceSchema>>(
107                self.data.odata_id(),
108                self.data.etag(),
109                &update,
110            )
111            .await
112            .map_err(Error::Bmc)?
113        {
114            ModificationResponse::Entity(nav) => {
115                let data = nav.get(self.bmc.as_ref()).await.map_err(Error::Bmc)?;
116                Ok(Some(Self {
117                    data,
118                    bmc: self.bmc.clone(),
119                }))
120            }
121            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
122        }
123    }
124
125    /// Get `Vec<MetricReportRef>` associated with this telemetry service.
126    ///
127    /// Fetches the metric report collection and returns a list of
128    /// [`MetricReportRef`] handles.
129    ///
130    /// # Errors
131    ///
132    /// Returns an error if:
133    /// - the telemetry service does not expose a `MetricReports` collection
134    /// - retrieving the collection fails
135    pub async fn metric_reports(&self) -> Result<Option<Vec<MetricReportRef<B>>>, Error<B>> {
136        if let Some(collection_ref) = &self.data.metric_reports {
137            let collection = collection_ref
138                .get(self.bmc.as_ref())
139                .await
140                .map_err(Error::Bmc)?;
141
142            let mut items = Vec::with_capacity(collection.members.len());
143            for m in &collection.members {
144                items.push(MetricReportRef::new(
145                    &self.bmc,
146                    NavProperty::new_reference(m.id().clone()),
147                ));
148            }
149
150            Ok(Some(items))
151        } else {
152            Ok(None)
153        }
154    }
155
156    /// Get `Vec<MetricDefinition>` associated with this telemetry service.
157    ///
158    /// Fetches the metric definition collection and returns a list of [`MetricDefinition`] handles.
159    ///
160    /// # Errors
161    ///
162    /// Returns an error if:
163    /// - the telemetry service does not expose a `MetricDefinitions` collection
164    /// - retrieving the collection fails
165    pub async fn metric_definitions(&self) -> Result<Option<Vec<MetricDefinition<B>>>, Error<B>> {
166        if let Some(collection_ref) = &self.data.metric_definitions {
167            let collection = self.bmc.expand_property(collection_ref).await?;
168
169            let mut items = Vec::with_capacity(collection.members.len());
170            for m in &collection.members {
171                items.push(MetricDefinition::new(&self.bmc, m).await?);
172            }
173
174            Ok(Some(items))
175        } else {
176            Ok(None)
177        }
178    }
179
180    /// Get `Vec<MetricReportDefinition>` associated with this telemetry service.
181    ///
182    /// Fetches the metric report definition collection and returns a list of
183    /// [`MetricReportDefinition`] handles.
184    ///
185    /// # Errors
186    ///
187    /// Returns an error if:
188    /// - the telemetry service does not expose a `MetricReportDefinitions` collection
189    /// - retrieving the collection fails
190    pub async fn metric_report_definitions(
191        &self,
192    ) -> Result<Option<Vec<MetricReportDefinition<B>>>, Error<B>> {
193        if let Some(collection_ref) = &self.data.metric_report_definitions {
194            let collection = self.bmc.expand_property(collection_ref).await?;
195
196            let mut items = Vec::with_capacity(collection.members.len());
197            for m in &collection.members {
198                items.push(MetricReportDefinition::new(&self.bmc, m).await?);
199            }
200
201            Ok(Some(items))
202        } else {
203            Ok(None)
204        }
205    }
206
207    /// Create a metric definition.
208    ///
209    /// # Errors
210    ///
211    /// Returns an error if:
212    /// - the telemetry service does not expose a `MetricDefinitions` collection
213    /// - creating the entity fails
214    pub async fn create_metric_definition(
215        &self,
216        create: &MetricDefinitionCreate,
217    ) -> Result<Option<MetricDefinition<B>>, Error<B>> {
218        let collection_ref = self
219            .data
220            .metric_definitions
221            .as_ref()
222            .ok_or(Error::MetricDefinitionsNotAvailable)?;
223
224        match self
225            .bmc
226            .as_ref()
227            .create::<_, NavProperty<MetricDefinitionSchema>>(collection_ref.id(), create)
228            .await
229            .map_err(Error::Bmc)?
230        {
231            ModificationResponse::Entity(nav) => {
232                MetricDefinition::new(&self.bmc, &nav).await.map(Some)
233            }
234            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
235        }
236    }
237
238    /// Create a metric report definition.
239    ///
240    /// # Errors
241    ///
242    /// Returns an error if:
243    /// - the telemetry service does not expose a `MetricReportDefinitions` collection
244    /// - creating the entity fails
245    pub async fn create_metric_report_definition(
246        &self,
247        create: &MetricReportDefinitionCreate,
248    ) -> Result<Option<MetricReportDefinition<B>>, Error<B>> {
249        let collection_ref = self
250            .data
251            .metric_report_definitions
252            .as_ref()
253            .ok_or(Error::MetricReportDefinitionsNotAvailable)?;
254
255        match self
256            .bmc
257            .as_ref()
258            .create::<_, NavProperty<MetricReportDefinitionSchema>>(collection_ref.id(), create)
259            .await
260            .map_err(Error::Bmc)?
261        {
262            ModificationResponse::Entity(nav) => {
263                MetricReportDefinition::new(&self.bmc, &nav).await.map(Some)
264            }
265            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
266        }
267    }
268}
269
270impl<B: Bmc> Resource for TelemetryService<B> {
271    fn resource_ref(&self) -> &ResourceSchema {
272        &self.data.as_ref().base
273    }
274}