use crate::oem::nvidia::schema::nvidia_computer_system::NvidiaComputerSystem as NvidiaComputerSystemSchema;
use crate::patch_support::JsonValue;
use crate::patch_support::Payload;
use crate::schema::resource::Oem as ResourceOemSchema;
use crate::Error;
use crate::NvBmc;
use nv_redfish_core::Bmc;
use nv_redfish_core::ODataId;
use std::marker::PhantomData;
use std::sync::Arc;
use tagged_types::TaggedType;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Mode {
NicMode,
DpuMode,
UnsupportedValue,
}
impl Mode {
fn parse(v: &str) -> Self {
match v {
"NicMode" => Self::NicMode,
"DpuMode" => Self::DpuMode,
_ => Self::UnsupportedValue,
}
}
}
pub type BaseMac<T> = TaggedType<T, BaseMacTag>;
#[doc(hidden)]
#[derive(tagged_types::Tag)]
#[implement(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[transparent(Debug, Display, FromStr, Serialize, Deserialize)]
#[capability(inner_access, cloned)]
pub enum BaseMacTag {}
pub struct NvidiaComputerSystem<B: Bmc> {
data: Arc<NvidiaComputerSystemSchema>,
dpu_body: Option<Arc<JsonValue>>,
_marker: PhantomData<B>,
}
impl<B: Bmc> NvidiaComputerSystem<B> {
pub(crate) async fn new(
bmc: &NvBmc<B>,
oem: &ResourceOemSchema,
) -> Result<Option<Self>, Error<B>> {
let Some(nvidia) = oem.additional_properties.get("Nvidia") else {
return Ok(None);
};
if bmc.quirks.bug_dpu_oem_computer_system() {
let Some(id) = nvidia.get("@odata.id").and_then(JsonValue::as_str) else {
return Ok(None);
};
let body = Payload::get_raw(bmc.as_ref(), &ODataId::from(id.to_owned())).await?;
let data = serde_json::from_value(body.clone()).map_err(Error::Json)?;
return Ok(Some(Self {
data: Arc::new(data),
dpu_body: Some(Arc::new(body)),
_marker: PhantomData,
}));
}
let data = serde_json::from_value(nvidia.clone()).map_err(Error::Json)?;
Ok(Some(Self {
data: Arc::new(data),
dpu_body: None,
_marker: PhantomData,
}))
}
#[must_use]
pub fn raw(&self) -> Arc<NvidiaComputerSystemSchema> {
self.data.clone()
}
#[must_use]
pub fn base_mac(&self) -> Option<BaseMac<&str>> {
self.dpu_body
.as_ref()?
.get("BaseMAC")
.and_then(JsonValue::as_str)
.map(BaseMac::new)
}
#[must_use]
pub fn mode(&self) -> Option<Mode> {
self.dpu_body
.as_ref()?
.get("Mode")
.and_then(JsonValue::as_str)
.map(Mode::parse)
}
}