nv_redfish_core/bmc.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//! Baseboard Management Controller (BMC) client abstraction
17//!
18//! This module defines the transport-agnostic [`Bmc`] trait — a minimal
19//! interface for interacting with Redfish services. Implementors provide
20//! asynchronous operations to retrieve and expand entities, create/update
21//! resources, delete entities, and invoke actions.
22//!
23//! Key concepts:
24//! - Entity identity: Every entity is identified by an `@odata.id` ([`crate::ODataId`]).
25//! - Entity reference: Generated types implement [`crate::EntityTypeRef`], which
26//! exposes `id()` and optional `etag()` accessors.
27//! - Arc-based sharing: Read operations return `Arc<T>` to enable cheap sharing
28//! and caching while keeping values immutable.
29//! - Expansion: [`crate::Expandable`] entities can request inline expansion using
30//! [`crate::query::ExpandQuery`], matching Redfish DSP0266 semantics for `$expand`.
31//! - Actions: Actions are described by [`crate::Action<T, R>`] and are invoked via
32//! the `action` method.
33//!
34//! Operation semantics:
35//! - `get` fetches the entity at the given `@odata.id`.
36//! - `expand` fetches the entity with the provided `$expand` query.
37//! - `create` typically performs a POST to a collection identified by `id` and
38//! returns the server-provided representation (`R`).
39//! - `update` typically performs a PATCH on an entity identified by `id` and
40//! returns the updated representation (`R`).
41//! - `delete` removes the entity at `id`.
42//! - `action` posts to an action endpoint (`Action.target`).
43//!
44//! Notes for implementors:
45//! - The trait is `Send + Sync` and returns `Send` futures to support use in
46//! async runtimes and multithreaded contexts.
47//! - Implementations may include client-side caching or conditional requests;
48//! these details are intentionally abstracted behind the trait.
49//! - Errors should implement `std::error::Error` and be safely transferable
50//! across threads.
51
52use serde::Deserialize;
53use serde::Serialize;
54
55use crate::query::ExpandQuery;
56use crate::Action;
57use crate::BoxTryStream;
58use crate::EntityTypeRef;
59use crate::Expandable;
60use crate::FilterQuery;
61use crate::ModificationResponse;
62use crate::ODataETag;
63use crate::ODataId;
64use std::error::Error as StdError;
65use std::future::Future;
66use std::sync::Arc;
67
68/// BMC trait defines access to a Baseboard Management Controller using
69/// the Redfish protocol.
70pub trait Bmc: Send + Sync {
71 /// BMC Error.
72 type Error: StdError + Send + Sync;
73
74 /// Expand any expandable object (navigation property or entity).
75 ///
76 /// `T` is structure that is used for return type.
77 fn expand<T: Expandable + Send + Sync + 'static>(
78 &self,
79 id: &ODataId,
80 query: ExpandQuery,
81 ) -> impl Future<Output = Result<Arc<T>, Self::Error>> + Send;
82
83 /// Get data of the object (navigation property or entity).
84 ///
85 /// `T` is structure that is used for return type.
86 fn get<T: EntityTypeRef + Sized + for<'a> Deserialize<'a> + 'static + Send + Sync>(
87 &self,
88 id: &ODataId,
89 ) -> impl Future<Output = Result<Arc<T>, Self::Error>> + Send;
90
91 /// Get and filters data of the object (navigation property or entity).
92 ///
93 /// `T` is structure that is used for return type.
94 fn filter<T: EntityTypeRef + Sized + for<'a> Deserialize<'a> + 'static + Send + Sync>(
95 &self,
96 id: &ODataId,
97 query: FilterQuery,
98 ) -> impl Future<Output = Result<Arc<T>, Self::Error>> + Send;
99
100 /// Creates element of the collection.
101 ///
102 /// `V` is structure that is used for create.
103 /// `R` is structure that is used for return type.
104 fn create<V: Sync + Send + Serialize, R: Send + Sync + Sized + for<'a> Deserialize<'a>>(
105 &self,
106 id: &ODataId,
107 query: &V,
108 ) -> impl Future<Output = Result<ModificationResponse<R>, Self::Error>> + Send;
109
110 /// Update entity.
111 ///
112 /// `V` is structure that is used for update.
113 /// `R` is structure that is used for return type (updated entity).
114 fn update<V: Sync + Send + Serialize, R: Send + Sync + Sized + for<'a> Deserialize<'a>>(
115 &self,
116 id: &ODataId,
117 etag: Option<&ODataETag>,
118 update: &V,
119 ) -> impl Future<Output = Result<ModificationResponse<R>, Self::Error>> + Send;
120
121 /// Delete entity.
122 fn delete<R: EntityTypeRef + Sync + Send + for<'de> Deserialize<'de>>(
123 &self,
124 id: &ODataId,
125 ) -> impl Future<Output = Result<ModificationResponse<R>, Self::Error>> + Send;
126
127 /// Run action.
128 ///
129 /// `T` is structure that contains action parameters.
130 /// `R` is structure with return type.
131 fn action<T: Send + Sync + Serialize, R: Send + Sync + Sized + for<'a> Deserialize<'a>>(
132 &self,
133 action: &Action<T, R>,
134 params: &T,
135 ) -> impl Future<Output = Result<ModificationResponse<R>, Self::Error>> + Send;
136
137 /// Stream data for the URI.
138 ///
139 /// `T` is structure that is used for the stream return type.
140 fn stream<T: Sized + for<'a> Deserialize<'a> + Send + 'static>(
141 &self,
142 uri: &str,
143 ) -> impl Future<Output = Result<BoxTryStream<T, Self::Error>, Self::Error>> + Send;
144}