Skip to main content

nv_redfish/computer_system/
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//! Computer System entities and collections.
17//!
18//! This module provides types for working with Redfish ComputerSystem resources
19//! and their sub-resources like processors, storage, memory, and drives.
20
21mod item;
22
23#[cfg(feature = "bios")]
24mod bios;
25#[cfg(feature = "boot-options")]
26mod boot_option;
27#[cfg(feature = "storages")]
28mod drive;
29#[cfg(feature = "memory")]
30mod memory;
31#[cfg(feature = "processors")]
32mod processor;
33#[cfg(feature = "secure-boot")]
34mod secure_boot;
35#[cfg(feature = "storages")]
36mod storage;
37
38use crate::patch_support::CollectionWithPatch;
39use crate::patch_support::JsonValue;
40use crate::patch_support::ReadPatchFn;
41use crate::resource::Resource as _;
42use crate::schema::redfish::computer_system::ComputerSystem as ComputerSystemSchema;
43use crate::schema::redfish::computer_system_collection::ComputerSystemCollection as ComputerSystemCollectionSchema;
44use crate::schema::redfish::resource::ResourceCollection;
45use crate::Error;
46use crate::NvBmc;
47use crate::ServiceRoot;
48use nv_redfish_core::Bmc;
49use nv_redfish_core::NavProperty;
50use std::sync::Arc;
51
52#[doc(inline)]
53pub use item::BootOptionReference;
54#[doc(inline)]
55pub use item::ComputerSystem;
56
57#[doc(inline)]
58#[cfg(feature = "bios")]
59pub use bios::Bios;
60#[doc(inline)]
61#[cfg(feature = "boot-options")]
62pub use boot_option::BootOption;
63#[doc(inline)]
64#[cfg(feature = "boot-options")]
65pub use boot_option::BootOptionCollection;
66#[doc(inline)]
67#[cfg(feature = "storages")]
68pub use drive::Drive;
69#[doc(inline)]
70#[cfg(feature = "memory")]
71pub use memory::Memory;
72#[doc(inline)]
73#[cfg(feature = "processors")]
74pub use processor::Processor;
75#[doc(inline)]
76#[cfg(feature = "secure-boot")]
77pub use secure_boot::SecureBoot;
78#[doc(inline)]
79#[cfg(feature = "secure-boot")]
80pub use secure_boot::SecureBootCurrentBootType;
81#[doc(inline)]
82#[cfg(feature = "storages")]
83pub use storage::Storage;
84
85/// Computer system collection.
86///
87/// Provides functions to access collection members.
88pub struct SystemCollection<B: Bmc> {
89    bmc: NvBmc<B>,
90    collection: Arc<ComputerSystemCollectionSchema>,
91    read_patch_fn: Option<ReadPatchFn>,
92}
93
94impl<B: Bmc> SystemCollection<B> {
95    pub(crate) async fn new(
96        bmc: &NvBmc<B>,
97        root: &ServiceRoot<B>,
98    ) -> Result<Option<Self>, Error<B>> {
99        let mut patches = Vec::new();
100        if root.computer_systems_wrong_last_reset_time() {
101            patches.push(computer_systems_wrong_last_reset_time);
102        }
103        let read_patch_fn = (!patches.is_empty())
104            .then(|| Arc::new(move |v| patches.iter().fold(v, |acc, f| f(acc))) as ReadPatchFn);
105
106        if let Some(collection_ref) = &root.root.systems {
107            Self::expand_collection(bmc, collection_ref, read_patch_fn.as_ref())
108                .await
109                .map(Some)
110        } else if root.bug_missing_root_nav_properties() {
111            bmc.expand_property(&NavProperty::new_reference(
112                format!("{}/Systems", root.odata_id()).into(),
113            ))
114            .await
115            .map(Some)
116        } else {
117            Ok(None)
118        }
119        .map(|c| {
120            c.map(|collection| Self {
121                bmc: bmc.clone(),
122                collection,
123                read_patch_fn,
124            })
125        })
126    }
127
128    /// List all computer systems available in this BMC.
129    ///
130    /// # Errors
131    ///
132    /// Returns an error if fetching system data fails.
133    pub async fn members(&self) -> Result<Vec<ComputerSystem<B>>, Error<B>> {
134        let mut members = Vec::new();
135        for m in &self.collection.members {
136            members.push(ComputerSystem::new(&self.bmc, m, self.read_patch_fn.as_ref()).await?);
137        }
138        Ok(members)
139    }
140}
141
142impl<B: Bmc> CollectionWithPatch<ComputerSystemCollectionSchema, ComputerSystemSchema, B>
143    for SystemCollection<B>
144{
145    fn convert_patched(
146        base: ResourceCollection,
147        members: Vec<NavProperty<ComputerSystemSchema>>,
148    ) -> ComputerSystemCollectionSchema {
149        ComputerSystemCollectionSchema { base, members }
150    }
151}
152
153// `LastResetTime` is marked as `edm.DateTimeOffset`, but some systems
154// puts "0000-00-00T00:00:00+00:00" as LastResetTime that is not
155// conform to ABNF of the DateTimeOffset. We delete such fields...
156fn computer_systems_wrong_last_reset_time(v: JsonValue) -> JsonValue {
157    if let JsonValue::Object(mut obj) = v {
158        if let Some(JsonValue::String(date)) = obj.get("LastResetTime") {
159            if date.starts_with("0000-00-00") {
160                obj.remove("LastResetTime");
161            }
162        }
163        JsonValue::Object(obj)
164    } else {
165        v
166    }
167}