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_definition;
22
23use crate::entity_link::EntityLink;
24use crate::schema::redfish::metric_definition::MetricDefinition as MetricDefinitionSchema;
25use crate::schema::redfish::metric_report::MetricReport as MetricReportSchema;
26use crate::schema::redfish::metric_report_definition::MetricReportDefinition as MetricReportDefinitionSchema;
27use crate::schema::redfish::telemetry_service::TelemetryService as TelemetryServiceSchema;
28use crate::schema::redfish::telemetry_service::TelemetryServiceUpdate;
29use crate::Error;
30use crate::NvBmc;
31use crate::Resource;
32use crate::ResourceSchema;
33use crate::ServiceRoot;
34use nv_redfish_core::Bmc;
35use nv_redfish_core::EntityTypeRef as _;
36use nv_redfish_core::ModificationResponse;
37use nv_redfish_core::NavProperty;
38use std::sync::Arc;
39
40#[doc(inline)]
41pub use metric_definition::MetricDefinition;
42#[doc(inline)]
43pub use metric_definition::MetricDefinitionCreate;
44#[doc(inline)]
45pub use metric_definition::MetricDefinitionUpdate;
46#[doc(inline)]
47pub use metric_report_definition::MetricReportDefinition;
48#[doc(inline)]
49pub use metric_report_definition::MetricReportDefinitionCreate;
50#[doc(inline)]
51pub use metric_report_definition::MetricReportDefinitionType;
52#[doc(inline)]
53pub use metric_report_definition::MetricReportDefinitionUpdate;
54#[doc(inline)]
55pub use metric_report_definition::ReportActionsEnum;
56#[doc(inline)]
57pub use metric_report_definition::Wildcard;
58#[doc(inline)]
59pub use metric_report_definition::WildcardUpdate;
60
61/// Metric report entity wrapper.
62pub type MetricReportLink<B> = EntityLink<B, MetricReportSchema>;
63
64/// Telemetry service.
65///
66/// Provides access to metric reports and metric definitions.
67pub struct TelemetryService<B: Bmc> {
68    data: Arc<TelemetryServiceSchema>,
69    bmc: NvBmc<B>,
70}
71
72impl<B: Bmc> TelemetryService<B> {
73    /// Create a new telemetry service handle.
74    pub(crate) async fn new(
75        bmc: &NvBmc<B>,
76        root: &ServiceRoot<B>,
77    ) -> Result<Option<Self>, Error<B>> {
78        if let Some(service_ref) = &root.root.telemetry_service {
79            let data = service_ref.get(bmc.as_ref()).await.map_err(Error::Bmc)?;
80            Ok(Some(Self {
81                data,
82                bmc: bmc.clone(),
83            }))
84        } else {
85            Ok(None)
86        }
87    }
88
89    /// Get the raw schema data for this telemetry service.
90    #[must_use]
91    pub fn raw(&self) -> Arc<TelemetryServiceSchema> {
92        self.data.clone()
93    }
94
95    /// Enable or disable telemetry service.
96    ///
97    /// # Errors
98    ///
99    /// Returns an error if updating telemetry service fails.
100    pub async fn set_enabled(&self, enabled: bool) -> Result<Option<Self>, Error<B>> {
101        let update = TelemetryServiceUpdate::builder()
102            .with_service_enabled(enabled)
103            .build();
104
105        match self
106            .bmc
107            .as_ref()
108            .update::<_, NavProperty<TelemetryServiceSchema>>(
109                self.data.odata_id(),
110                self.data.etag(),
111                &update,
112            )
113            .await
114            .map_err(Error::Bmc)?
115        {
116            ModificationResponse::Entity(nav) => {
117                let data = nav.get(self.bmc.as_ref()).await.map_err(Error::Bmc)?;
118                Ok(Some(Self {
119                    data,
120                    bmc: self.bmc.clone(),
121                }))
122            }
123            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
124        }
125    }
126
127    /// Get `Vec<MetricReportRef>` associated with this telemetry service.
128    ///
129    /// Fetches the metric report collection and returns a list of
130    /// [`MetricReportRef`] handles.
131    ///
132    /// # Errors
133    ///
134    /// Returns an error if:
135    /// - the telemetry service does not expose a `MetricReports` collection
136    /// - retrieving the collection fails
137    pub async fn metric_report_links(&self) -> Result<Option<Vec<MetricReportLink<B>>>, Error<B>> {
138        if let Some(collection_ref) = &self.data.metric_reports {
139            let collection = collection_ref
140                .get(self.bmc.as_ref())
141                .await
142                .map_err(Error::Bmc)?;
143
144            let mut items = Vec::with_capacity(collection.members.len());
145            for m in &collection.members {
146                items.push(MetricReportLink::new(
147                    &self.bmc,
148                    NavProperty::new_reference(m.id().clone()),
149                ));
150            }
151
152            Ok(Some(items))
153        } else {
154            Ok(None)
155        }
156    }
157
158    /// Get `Vec<MetricDefinition>` associated with this telemetry service.
159    ///
160    /// Fetches the metric definition collection and returns a list of [`MetricDefinition`] handles.
161    ///
162    /// # Errors
163    ///
164    /// Returns an error if:
165    /// - the telemetry service does not expose a `MetricDefinitions` collection
166    /// - retrieving the collection fails
167    pub async fn metric_definitions(&self) -> Result<Option<Vec<MetricDefinition<B>>>, Error<B>> {
168        if let Some(collection_ref) = &self.data.metric_definitions {
169            let collection = self.bmc.expand_property(collection_ref).await?;
170
171            let mut items = Vec::with_capacity(collection.members.len());
172            for m in &collection.members {
173                items.push(MetricDefinition::new(&self.bmc, m).await?);
174            }
175
176            Ok(Some(items))
177        } else {
178            Ok(None)
179        }
180    }
181
182    /// Get `Vec<MetricReportDefinition>` associated with this telemetry service.
183    ///
184    /// Fetches the metric report definition collection and returns a list of
185    /// [`MetricReportDefinition`] handles.
186    ///
187    /// # Errors
188    ///
189    /// Returns an error if:
190    /// - the telemetry service does not expose a `MetricReportDefinitions` collection
191    /// - retrieving the collection fails
192    pub async fn metric_report_definitions(
193        &self,
194    ) -> Result<Option<Vec<MetricReportDefinition<B>>>, Error<B>> {
195        if let Some(collection_ref) = &self.data.metric_report_definitions {
196            let collection = self.bmc.expand_property(collection_ref).await?;
197
198            let mut items = Vec::with_capacity(collection.members.len());
199            for m in &collection.members {
200                items.push(MetricReportDefinition::new(&self.bmc, m).await?);
201            }
202
203            Ok(Some(items))
204        } else {
205            Ok(None)
206        }
207    }
208
209    /// Create a metric definition.
210    ///
211    /// # Errors
212    ///
213    /// Returns an error if:
214    /// - the telemetry service does not expose a `MetricDefinitions` collection
215    /// - creating the entity fails
216    pub async fn create_metric_definition(
217        &self,
218        create: &MetricDefinitionCreate,
219    ) -> Result<Option<MetricDefinition<B>>, Error<B>> {
220        let collection_ref = self
221            .data
222            .metric_definitions
223            .as_ref()
224            .ok_or(Error::MetricDefinitionsNotAvailable)?;
225
226        match self
227            .bmc
228            .as_ref()
229            .create::<_, NavProperty<MetricDefinitionSchema>>(collection_ref.id(), create)
230            .await
231            .map_err(Error::Bmc)?
232        {
233            ModificationResponse::Entity(nav) => {
234                MetricDefinition::new(&self.bmc, &nav).await.map(Some)
235            }
236            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
237        }
238    }
239
240    /// Create a metric report definition.
241    ///
242    /// # Errors
243    ///
244    /// Returns an error if:
245    /// - the telemetry service does not expose a `MetricReportDefinitions` collection
246    /// - creating the entity fails
247    pub async fn create_metric_report_definition(
248        &self,
249        create: &MetricReportDefinitionCreate,
250    ) -> Result<Option<MetricReportDefinition<B>>, Error<B>> {
251        let collection_ref = self
252            .data
253            .metric_report_definitions
254            .as_ref()
255            .ok_or(Error::MetricReportDefinitionsNotAvailable)?;
256
257        match self
258            .bmc
259            .as_ref()
260            .create::<_, NavProperty<MetricReportDefinitionSchema>>(collection_ref.id(), create)
261            .await
262            .map_err(Error::Bmc)?
263        {
264            ModificationResponse::Entity(nav) => {
265                MetricReportDefinition::new(&self.bmc, &nav).await.map(Some)
266            }
267            ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
268        }
269    }
270}
271
272impl<B: Bmc> Resource for TelemetryService<B> {
273    fn resource_ref(&self) -> &ResourceSchema {
274        &self.data.as_ref().base
275    }
276}