Skip to main content

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}