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::schema::redfish::computer_system::ComputerSystem as ComputerSystemSchema;
30use crate::Error;
31use crate::NvBmc;
32use crate::Resource;
33use crate::ResourceSchema;
34
35use serde::Serialize;
36use std::convert::identity;
37use std::sync::Arc;
38use tagged_types::TaggedType;
39
40#[cfg(feature = "bios")]
41use crate::computer_system::Bios;
42#[cfg(feature = "boot-options")]
43use crate::computer_system::BootOptionCollection;
44#[cfg(feature = "memory")]
45use crate::computer_system::Memory;
46#[cfg(feature = "processors")]
47use crate::computer_system::Processor;
48#[cfg(feature = "secure-boot")]
49use crate::computer_system::SecureBoot;
50#[cfg(feature = "storages")]
51use crate::computer_system::Storage;
52#[cfg(feature = "ethernet-interfaces")]
53use crate::ethernet_interface::EthernetInterfaceCollection;
54#[cfg(feature = "log-services")]
55use crate::log_service::LogService;
56#[cfg(feature = "oem-lenovo")]
57use crate::oem::lenovo::computer_system::LenovoComputerSystem;
58#[cfg(feature = "oem-nvidia-bluefield")]
59use crate::oem::nvidia::bluefield::nvidia_computer_system::NvidiaComputerSystem;
60
61#[doc(hidden)]
62pub enum ComputerSystemTag {}
63
64pub type Manufacturer<T> = HardwareIdManufacturer<T, ComputerSystemTag>;
66
67pub type Model<T> = HardwareIdModel<T, ComputerSystemTag>;
69
70pub type PartNumber<T> = HardwareIdPartNumber<T, ComputerSystemTag>;
72
73pub type SerialNumber<T> = HardwareIdSerialNumber<T, ComputerSystemTag>;
75
76pub type Sku<T> = TaggedType<T, ComputerSystemSkuTag>;
78#[doc(hidden)]
79#[derive(tagged_types::Tag)]
80#[implement(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
81#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
82#[capability(inner_access, cloned)]
83pub enum ComputerSystemSkuTag {}
84
85pub type BootOptionReference<T> = TaggedType<T, BootOptionReferenceTag>;
87#[doc(hidden)]
88#[derive(tagged_types::Tag)]
89#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
90#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
91#[capability(inner_access, cloned)]
92pub enum BootOptionReferenceTag {}
93
94#[derive(Serialize)]
95struct BootPatch {
96 #[serde(rename = "BootOrder")]
97 boot_order: Vec<BootOptionReference<String>>,
98}
99
100#[derive(Serialize)]
101struct ComputerSystemBootOrderUpdate {
102 #[serde(rename = "Boot")]
103 boot: BootPatch,
104}
105
106pub struct ComputerSystem<B: Bmc> {
110 #[allow(dead_code)] bmc: NvBmc<B>,
112 data: Arc<ComputerSystemSchema>,
113}
114
115impl<B: Bmc> ComputerSystem<B> {
116 pub(crate) async fn new(
118 bmc: &NvBmc<B>,
119 nav: &NavProperty<ComputerSystemSchema>,
120 read_patch_fn: Option<&ReadPatchFn>,
121 ) -> Result<Self, Error<B>> {
122 if let Some(read_patch_fn) = read_patch_fn {
123 Payload::get(bmc.as_ref(), nav, read_patch_fn.as_ref()).await
124 } else {
125 nav.get(bmc.as_ref()).await.map_err(Error::Bmc)
126 }
127 .map(|data| Self {
128 bmc: bmc.clone(),
129 data,
130 })
131 }
132
133 #[must_use]
138 pub fn raw(&self) -> Arc<ComputerSystemSchema> {
139 self.data.clone()
140 }
141
142 #[must_use]
144 pub fn hardware_id(&self) -> HardwareIdRef<'_, ComputerSystemTag> {
145 HardwareIdRef {
146 manufacturer: self
147 .data
148 .manufacturer
149 .as_ref()
150 .and_then(Option::as_deref)
151 .map(Manufacturer::new),
152 model: self
153 .data
154 .model
155 .as_ref()
156 .and_then(Option::as_deref)
157 .map(Model::new),
158 part_number: self
159 .data
160 .part_number
161 .as_ref()
162 .and_then(Option::as_deref)
163 .map(PartNumber::new),
164 serial_number: self
165 .data
166 .serial_number
167 .as_ref()
168 .and_then(Option::as_deref)
169 .map(SerialNumber::new),
170 }
171 }
172
173 #[must_use]
175 pub fn sku(&self) -> Option<Sku<&str>> {
176 self.data
177 .sku
178 .as_ref()
179 .and_then(Option::as_ref)
180 .map(String::as_str)
181 .map(Sku::new)
182 }
183
184 #[must_use]
186 pub fn power_state(&self) -> Option<PowerState> {
187 self.data.power_state.and_then(identity)
188 }
189
190 #[must_use]
193 pub fn boot_order(&self) -> Option<Vec<BootOptionReference<&str>>> {
194 self.data
195 .as_ref()
196 .boot
197 .as_ref()
198 .and_then(|boot| boot.boot_order.as_ref().and_then(Option::as_ref))
199 .map(|v| {
200 v.iter()
201 .map(String::as_str)
202 .map(BootOptionReference::new)
203 .collect::<Vec<_>>()
204 })
205 }
206
207 pub async fn set_boot_order(
213 &self,
214 boot_order: Vec<BootOptionReference<String>>,
215 ) -> Result<Option<Self>, Error<B>> {
216 let update = ComputerSystemBootOrderUpdate {
217 boot: BootPatch { boot_order },
218 };
219
220 let settings = self.data.settings_object();
221
222 let update_odata = settings
223 .as_ref()
224 .map_or_else(|| self.data.odata_id(), |settings| settings.odata_id());
225
226 match self
227 .bmc
228 .as_ref()
229 .update::<_, NavProperty<ComputerSystemSchema>>(update_odata, None, &update)
230 .await
231 .map_err(Error::Bmc)?
232 {
233 ModificationResponse::Entity(nav) => {
234 let data = nav.get(self.bmc.as_ref()).await.map_err(Error::Bmc)?;
235 Ok(Some(Self {
236 bmc: self.bmc.clone(),
237 data,
238 }))
239 }
240 ModificationResponse::Task(_) | ModificationResponse::Empty => Ok(None),
241 }
242 }
243
244 #[cfg(feature = "bios")]
252 pub async fn bios(&self) -> Result<Option<Bios<B>>, Error<B>> {
253 if let Some(bios_ref) = &self.data.bios {
254 Bios::new(&self.bmc, bios_ref).await.map(Some)
255 } else {
256 Ok(None)
257 }
258 }
259
260 #[cfg(feature = "processors")]
269 pub async fn processors(&self) -> Result<Option<Vec<Processor<B>>>, Error<B>> {
270 if let Some(processors_ref) = &self.data.processors {
271 let processors_collection = self.bmc.expand_property(processors_ref).await?;
272
273 let mut processors = Vec::new();
274 for m in &processors_collection.members {
275 processors.push(Processor::new(&self.bmc, m).await?);
276 }
277
278 Ok(Some(processors))
279 } else {
280 Ok(None)
281 }
282 }
283
284 #[cfg(feature = "secure-boot")]
292 pub async fn secure_boot(&self) -> Result<Option<SecureBoot<B>>, Error<B>> {
293 if let Some(secure_boot_ref) = &self.data.secure_boot {
294 SecureBoot::new(&self.bmc, secure_boot_ref).await.map(Some)
295 } else {
296 Ok(None)
297 }
298 }
299
300 #[cfg(feature = "storages")]
309 pub async fn storage_controllers(&self) -> Result<Option<Vec<Storage<B>>>, Error<B>> {
310 if let Some(storage_ref) = &self.data.storage {
311 let storage_collection = self.bmc.expand_property(storage_ref).await?;
312
313 let mut storage_controllers = Vec::new();
314 for m in &storage_collection.members {
315 storage_controllers.push(Storage::new(&self.bmc, m).await?);
316 }
317
318 Ok(Some(storage_controllers))
319 } else {
320 Ok(None)
321 }
322 }
323
324 #[cfg(feature = "memory")]
333 pub async fn memory_modules(&self) -> Result<Option<Vec<Memory<B>>>, Error<B>> {
334 if let Some(memory_ref) = &self.data.memory {
335 let memory_collection = self.bmc.expand_property(memory_ref).await?;
336
337 let mut memory_modules = Vec::new();
338 for m in &memory_collection.members {
339 memory_modules.push(Memory::new(&self.bmc, m).await?);
340 }
341
342 Ok(Some(memory_modules))
343 } else {
344 Ok(None)
345 }
346 }
347
348 #[cfg(feature = "log-services")]
356 pub async fn log_services(&self) -> Result<Option<Vec<LogService<B>>>, Error<B>> {
357 if let Some(log_services_ref) = &self.data.log_services {
358 let log_services_collection = log_services_ref
359 .get(self.bmc.as_ref())
360 .await
361 .map_err(Error::Bmc)?;
362
363 let mut log_services = Vec::new();
364 for m in &log_services_collection.members {
365 log_services.push(LogService::new(&self.bmc, m).await?);
366 }
367
368 Ok(Some(log_services))
369 } else {
370 Ok(None)
371 }
372 }
373
374 #[cfg(feature = "ethernet-interfaces")]
382 pub async fn ethernet_interfaces(
383 &self,
384 ) -> Result<Option<EthernetInterfaceCollection<B>>, Error<B>> {
385 if let Some(p) = &self.data.ethernet_interfaces {
386 EthernetInterfaceCollection::new(&self.bmc, p)
387 .await
388 .map(Some)
389 } else {
390 Ok(None)
391 }
392 }
393
394 #[cfg(feature = "boot-options")]
402 pub async fn boot_options(&self) -> Result<Option<BootOptionCollection<B>>, Error<B>> {
403 if let Some(p) = &self
404 .data
405 .boot
406 .as_ref()
407 .and_then(|v| v.boot_options.as_ref())
408 {
409 BootOptionCollection::new(&self.bmc, p).await.map(Some)
410 } else {
411 Ok(None)
412 }
413 }
414
415 #[cfg(feature = "oem-nvidia-bluefield")]
423 pub async fn oem_nvidia_bluefield(&self) -> Result<Option<NvidiaComputerSystem<B>>, Error<B>> {
424 if let Some(oem) = self.data.base.base.oem.as_ref() {
425 NvidiaComputerSystem::new(&self.bmc, oem).await
426 } else {
427 Ok(None)
428 }
429 }
430
431 #[cfg(feature = "oem-lenovo")]
439 pub fn oem_lenovo(&self) -> Result<Option<LenovoComputerSystem<B>>, Error<B>> {
440 LenovoComputerSystem::new(&self.bmc, &self.data)
441 }
442}
443
444impl<B: Bmc> Resource for ComputerSystem<B> {
445 fn resource_ref(&self) -> &ResourceSchema {
446 &self.data.as_ref().base
447 }
448}