nv_redfish/computer_system/
item.rs1use crate::core::Bmc;
17use crate::core::EntityTypeRef as _;
18use crate::core::ModificationResponse;
19use crate::core::NavProperty;
20use crate::core::RedfishSettings as _;
21use crate::hardware_id::HardwareIdRef;
22use crate::hardware_id::Manufacturer as HardwareIdManufacturer;
23use crate::hardware_id::Model as HardwareIdModel;
24use crate::hardware_id::PartNumber as HardwareIdPartNumber;
25use crate::hardware_id::SerialNumber as HardwareIdSerialNumber;
26use crate::patch_support::Payload;
27use crate::patch_support::ReadPatchFn;
28use crate::resource::PowerState;
29use crate::resource::ResetType;
30use crate::schema::computer_system::ComputerSystem as ComputerSystemSchema;
31use crate::Error;
32use crate::NvBmc;
33use crate::Resource;
34use crate::ResourceSchema;
35
36use serde::Serialize;
37use std::convert::identity;
38use std::sync::Arc;
39use tagged_types::TaggedType;
40
41#[cfg(feature = "bios")]
42use crate::computer_system::Bios;
43#[cfg(feature = "boot-options")]
44use crate::computer_system::BootOptionCollection;
45#[cfg(feature = "memory")]
46use crate::computer_system::Memory;
47#[cfg(feature = "processors")]
48use crate::computer_system::Processor;
49#[cfg(feature = "secure-boot")]
50use crate::computer_system::SecureBoot;
51#[cfg(feature = "storages")]
52use crate::computer_system::Storage;
53#[cfg(feature = "ethernet-interfaces")]
54use crate::ethernet_interface::EthernetInterfaceCollection;
55#[cfg(feature = "log-services")]
56use crate::log_service::LogService;
57#[cfg(feature = "oem-lenovo")]
58use crate::oem::lenovo::computer_system::LenovoComputerSystem;
59#[cfg(feature = "oem-nvidia-bluefield")]
60use crate::oem::nvidia::bluefield::nvidia_computer_system::NvidiaComputerSystem;
61
62#[doc(hidden)]
63pub enum ComputerSystemTag {}
64
65pub type Manufacturer<T> = HardwareIdManufacturer<T, ComputerSystemTag>;
67
68pub type Model<T> = HardwareIdModel<T, ComputerSystemTag>;
70
71pub type PartNumber<T> = HardwareIdPartNumber<T, ComputerSystemTag>;
73
74pub type SerialNumber<T> = HardwareIdSerialNumber<T, ComputerSystemTag>;
76
77pub type Sku<T> = TaggedType<T, ComputerSystemSkuTag>;
79#[doc(hidden)]
80#[derive(tagged_types::Tag)]
81#[implement(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
82#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
83#[capability(inner_access, cloned)]
84pub enum ComputerSystemSkuTag {}
85
86pub type BootOptionReference<T> = TaggedType<T, BootOptionReferenceTag>;
88#[doc(hidden)]
89#[derive(tagged_types::Tag)]
90#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
91#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
92#[capability(inner_access, cloned)]
93pub enum BootOptionReferenceTag {}
94
95#[derive(Serialize)]
96struct BootPatch {
97 #[serde(rename = "BootOrder")]
98 boot_order: Vec<BootOptionReference<String>>,
99}
100
101#[derive(Serialize)]
102struct ComputerSystemBootOrderUpdate {
103 #[serde(rename = "Boot")]
104 boot: BootPatch,
105}
106
107pub struct ComputerSystem<B: Bmc> {
111 #[allow(dead_code)] bmc: NvBmc<B>,
113 data: Arc<ComputerSystemSchema>,
114}
115
116impl<B: Bmc> ComputerSystem<B> {
117 pub(crate) async fn new(
119 bmc: &NvBmc<B>,
120 nav: &NavProperty<ComputerSystemSchema>,
121 read_patch_fn: Option<&ReadPatchFn>,
122 ) -> Result<Self, Error<B>> {
123 if let Some(read_patch_fn) = read_patch_fn {
124 Payload::get(bmc.as_ref(), nav, read_patch_fn.as_ref()).await
125 } else {
126 nav.get(bmc.as_ref()).await.map_err(Error::Bmc)
127 }
128 .map(|data| Self {
129 bmc: bmc.clone(),
130 data,
131 })
132 }
133
134 #[must_use]
139 pub fn raw(&self) -> Arc<ComputerSystemSchema> {
140 self.data.clone()
141 }
142
143 #[must_use]
145 pub fn hardware_id(&self) -> HardwareIdRef<'_, ComputerSystemTag> {
146 HardwareIdRef {
147 manufacturer: self
148 .data
149 .manufacturer
150 .as_ref()
151 .and_then(Option::as_deref)
152 .map(Manufacturer::new),
153 model: self
154 .data
155 .model
156 .as_ref()
157 .and_then(Option::as_deref)
158 .map(Model::new),
159 part_number: self
160 .data
161 .part_number
162 .as_ref()
163 .and_then(Option::as_deref)
164 .map(PartNumber::new),
165 serial_number: self
166 .data
167 .serial_number
168 .as_ref()
169 .and_then(Option::as_deref)
170 .map(SerialNumber::new),
171 }
172 }
173
174 #[must_use]
176 pub fn sku(&self) -> Option<Sku<&str>> {
177 self.data
178 .sku
179 .as_ref()
180 .and_then(Option::as_ref)
181 .map(String::as_str)
182 .map(Sku::new)
183 }
184
185 #[must_use]
187 pub fn power_state(&self) -> Option<PowerState> {
188 self.data.power_state.and_then(identity)
189 }
190
191 pub async fn reset(
198 &self,
199 reset_type: Option<ResetType>,
200 ) -> Result<ModificationResponse<()>, Error<B>>
201 where
202 B::Error: nv_redfish_core::ActionError,
203 {
204 let actions = self
205 .data
206 .actions
207 .as_ref()
208 .ok_or(Error::ActionNotAvailable)?;
209
210 if actions.reset.is_none() {
211 return Err(Error::ActionNotAvailable);
212 }
213
214 actions
215 .reset(self.bmc.as_ref(), reset_type)
216 .await
217 .map_err(Error::Bmc)
218 }
219
220 #[must_use]
223 pub fn boot_order(&self) -> Option<Vec<BootOptionReference<&str>>> {
224 self.data
225 .as_ref()
226 .boot
227 .as_ref()
228 .and_then(|boot| boot.boot_order.as_ref().and_then(Option::as_ref))
229 .map(|v| {
230 v.iter()
231 .map(String::as_str)
232 .map(BootOptionReference::new)
233 .collect::<Vec<_>>()
234 })
235 }
236
237 pub async fn set_boot_order(
250 &self,
251 boot_order: Vec<BootOptionReference<String>>,
252 ) -> Result<ModificationResponse<Self>, Error<B>> {
253 let update = ComputerSystemBootOrderUpdate {
254 boot: BootPatch { boot_order },
255 };
256
257 let settings = self.data.settings_object();
258
259 let update_odata = settings
260 .as_ref()
261 .map_or_else(|| self.data.odata_id(), |settings| settings.odata_id());
262
263 self.bmc
264 .as_ref()
265 .update::<_, NavProperty<ComputerSystemSchema>>(update_odata, None, &update)
266 .await
267 .map_err(Error::Bmc)?
268 .try_map_entity_async(|nav| async move {
269 let data = nav.get(self.bmc.as_ref()).await.map_err(Error::Bmc)?;
270
271 Ok(Self {
272 bmc: self.bmc.clone(),
273 data,
274 })
275 })
276 .await
277 }
278
279 #[cfg(feature = "bios")]
287 pub async fn bios(&self) -> Result<Option<Bios<B>>, Error<B>> {
288 if let Some(bios_ref) = &self.data.bios {
289 Bios::new(&self.bmc, bios_ref).await.map(Some)
290 } else {
291 Ok(None)
292 }
293 }
294
295 #[cfg(feature = "processors")]
304 pub async fn processors(&self) -> Result<Option<Vec<Processor<B>>>, Error<B>> {
305 if let Some(processors_ref) = &self.data.processors {
306 let processors_collection = self.bmc.expand_property(processors_ref).await?;
307
308 let mut processors = Vec::new();
309 for m in &processors_collection.members {
310 processors.push(Processor::new(&self.bmc, m).await?);
311 }
312
313 Ok(Some(processors))
314 } else {
315 Ok(None)
316 }
317 }
318
319 #[cfg(feature = "secure-boot")]
327 pub async fn secure_boot(&self) -> Result<Option<SecureBoot<B>>, Error<B>> {
328 if let Some(secure_boot_ref) = &self.data.secure_boot {
329 SecureBoot::new(&self.bmc, secure_boot_ref).await.map(Some)
330 } else {
331 Ok(None)
332 }
333 }
334
335 #[cfg(feature = "storages")]
344 pub async fn storage_controllers(&self) -> Result<Option<Vec<Storage<B>>>, Error<B>> {
345 if let Some(storage_ref) = &self.data.storage {
346 let storage_collection = self.bmc.expand_property(storage_ref).await?;
347
348 let mut storage_controllers = Vec::new();
349 for m in &storage_collection.members {
350 storage_controllers.push(Storage::new(&self.bmc, m).await?);
351 }
352
353 Ok(Some(storage_controllers))
354 } else {
355 Ok(None)
356 }
357 }
358
359 #[cfg(feature = "memory")]
368 pub async fn memory_modules(&self) -> Result<Option<Vec<Memory<B>>>, Error<B>> {
369 if let Some(memory_ref) = &self.data.memory {
370 let memory_collection = self.bmc.expand_property(memory_ref).await?;
371
372 let mut memory_modules = Vec::new();
373 for m in &memory_collection.members {
374 memory_modules.push(Memory::new(&self.bmc, m).await?);
375 }
376
377 Ok(Some(memory_modules))
378 } else {
379 Ok(None)
380 }
381 }
382
383 #[cfg(feature = "log-services")]
391 pub async fn log_services(&self) -> Result<Option<Vec<LogService<B>>>, Error<B>> {
392 if let Some(log_services_ref) = &self.data.log_services {
393 let log_services_collection = log_services_ref
394 .get(self.bmc.as_ref())
395 .await
396 .map_err(Error::Bmc)?;
397
398 let mut log_services = Vec::new();
399 for m in &log_services_collection.members {
400 log_services.push(LogService::new(&self.bmc, m).await?);
401 }
402
403 Ok(Some(log_services))
404 } else {
405 Ok(None)
406 }
407 }
408
409 #[cfg(feature = "ethernet-interfaces")]
417 pub async fn ethernet_interfaces(
418 &self,
419 ) -> Result<Option<EthernetInterfaceCollection<B>>, Error<B>> {
420 if let Some(p) = &self.data.ethernet_interfaces {
421 EthernetInterfaceCollection::new(&self.bmc, p)
422 .await
423 .map(Some)
424 } else {
425 Ok(None)
426 }
427 }
428
429 #[cfg(feature = "boot-options")]
437 pub async fn boot_options(&self) -> Result<Option<BootOptionCollection<B>>, Error<B>> {
438 if let Some(p) = &self
439 .data
440 .boot
441 .as_ref()
442 .and_then(|v| v.boot_options.as_ref())
443 {
444 BootOptionCollection::new(&self.bmc, p).await.map(Some)
445 } else {
446 Ok(None)
447 }
448 }
449
450 #[cfg(feature = "oem-nvidia-bluefield")]
458 pub async fn oem_nvidia_bluefield(&self) -> Result<Option<NvidiaComputerSystem<B>>, Error<B>> {
459 if let Some(oem) = self.data.base.base.oem.as_ref() {
460 NvidiaComputerSystem::new(&self.bmc, oem).await
461 } else {
462 Ok(None)
463 }
464 }
465
466 #[cfg(feature = "oem-lenovo")]
474 pub fn oem_lenovo(&self) -> Result<Option<LenovoComputerSystem<B>>, Error<B>> {
475 LenovoComputerSystem::new(&self.bmc, &self.data)
476 }
477}
478
479impl<B: Bmc> Resource for ComputerSystem<B> {
480 fn resource_ref(&self) -> &ResourceSchema {
481 &self.data.as_ref().base
482 }
483}