nv_redfish/log_service/mod.rs
1// SPDX-FileCopyrightText: Copyright (c) 2025 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//! Log Service entities and collections.
17//!
18//! This module provides types for working with Redfish LogService resources
19//! and their log entries.
20
21use crate::schema::redfish::log_entry::LogEntry;
22use crate::schema::redfish::log_service::LogService as LogServiceSchema;
23use crate::Error;
24use crate::NvBmc;
25use crate::Resource;
26use crate::ResourceSchema;
27use nv_redfish_core::Bmc;
28use nv_redfish_core::ModificationResponse;
29use nv_redfish_core::NavProperty;
30use std::sync::Arc;
31
32/// Log service.
33///
34/// Provides functions to access log entries and perform log operations.
35pub struct LogService<B: Bmc> {
36 bmc: NvBmc<B>,
37 data: Arc<LogServiceSchema>,
38}
39
40impl<B: Bmc> LogService<B> {
41 /// Create a new log service handle.
42 pub(crate) async fn new(
43 bmc: &NvBmc<B>,
44 nav: &NavProperty<LogServiceSchema>,
45 ) -> Result<Self, Error<B>> {
46 nav.get(bmc.as_ref())
47 .await
48 .map_err(crate::Error::Bmc)
49 .map(|data| Self {
50 bmc: bmc.clone(),
51 data,
52 })
53 }
54
55 /// Get the raw schema data for this log service.
56 ///
57 /// Returns an `Arc` to the underlying schema, allowing cheap cloning
58 /// and sharing of the data.
59 #[must_use]
60 pub fn raw(&self) -> Arc<LogServiceSchema> {
61 self.data.clone()
62 }
63
64 /// List all log entries.
65 ///
66 /// # Errors
67 ///
68 /// Returns an error if:
69 /// - The log service does not have a log entries collection
70 /// - Fetching log entries data fails
71 pub async fn entries(&self) -> Result<Option<Vec<Arc<LogEntry>>>, Error<B>> {
72 if let Some(entries_ref) = &self.data.entries {
73 let entries_collection = self.bmc.expand_property(entries_ref).await?;
74 self.expand_entries(&entries_collection.members)
75 .await
76 .map(Some)
77 } else {
78 Ok(None)
79 }
80 }
81
82 /// Filter log entries using `OData` filter query.
83 ///
84 /// # Errors
85 ///
86 /// Returns an error if:
87 /// - The log service does not have a log entries collection
88 /// - Filtering log entries data fails
89 pub async fn filter_entries(
90 &self,
91 filter: nv_redfish_core::FilterQuery,
92 ) -> Result<Option<Vec<Arc<LogEntry>>>, Error<B>> {
93 if let Some(entries_ref) = &self.data.entries {
94 let entries_collection = entries_ref
95 .filter(self.bmc.as_ref(), filter)
96 .await
97 .map_err(Error::Bmc)?;
98
99 self.expand_entries(&entries_collection.members)
100 .await
101 .map(Some)
102 } else {
103 Ok(None)
104 }
105 }
106
107 /// Clear all log entries.
108 ///
109 /// # Arguments
110 ///
111 /// * `log_entry_codes` - Optional log entry codes to clear specific entries
112 ///
113 /// # Errors
114 ///
115 /// Returns an error if:
116 /// - The log service does not support the `ClearLog` action
117 /// - The action execution fails
118 pub async fn clear_log(
119 &self,
120 log_entry_codes: Option<String>,
121 ) -> Result<ModificationResponse<()>, Error<B>>
122 where
123 B::Error: nv_redfish_core::ActionError,
124 {
125 let actions = self
126 .data
127 .actions
128 .as_ref()
129 .ok_or(Error::ActionNotAvailable)?;
130
131 actions
132 .clear_log(self.bmc.as_ref(), log_entry_codes)
133 .await
134 .map_err(Error::Bmc)
135 }
136
137 /// This unwraps `NavProperty`, usually all BMC already have them expanded, so we do not expect network IO here
138 async fn expand_entries(
139 &self,
140 entry_refs: &[NavProperty<LogEntry>],
141 ) -> Result<Vec<Arc<LogEntry>>, Error<B>> {
142 let mut entries = Vec::new();
143 for entry_ref in entry_refs {
144 let entry = entry_ref.get(self.bmc.as_ref()).await.map_err(Error::Bmc)?;
145 entries.push(entry);
146 }
147 Ok(entries)
148 }
149}
150
151impl<B: Bmc> Resource for LogService<B> {
152 fn resource_ref(&self) -> &ResourceSchema {
153 &self.data.as_ref().base
154 }
155}