nv_redfish/
service_root.rs1use std::sync::Arc;
17
18use crate::bmc_quirks::BmcQuirks;
19use crate::core::Bmc;
20use crate::core::NavProperty;
21use crate::core::ODataId;
22use crate::schema::service_root::ServiceRoot as SchemaServiceRoot;
23use crate::Error;
24use crate::NvBmc;
25use crate::ProtocolFeatures;
26use crate::Resource;
27use crate::ResourceSchema;
28
29use tagged_types::TaggedType;
30
31#[cfg(feature = "accounts")]
32use crate::account::AccountService;
33#[cfg(feature = "chassis")]
34use crate::chassis::ChassisCollection;
35#[cfg(feature = "chassis")]
36use crate::chassis::ChassisLink;
37#[cfg(feature = "computer-systems")]
38use crate::computer_system::SystemCollection;
39#[cfg(feature = "event-service")]
40use crate::event_service::EventService;
41#[cfg(feature = "managers")]
42use crate::manager::ManagerCollection;
43#[cfg(feature = "oem-ami")]
44use crate::oem::ami::AmiServiceRoot;
45#[cfg(feature = "oem-hpe")]
46use crate::oem::hpe::HpeiLoServiceExt;
47#[cfg(feature = "power-equipment")]
48use crate::power_equipment::PowerEquipment;
49#[cfg(feature = "session-service")]
50use crate::session_service::SessionService;
51#[cfg(feature = "task-service")]
52use crate::task_service::TaskService;
53#[cfg(feature = "telemetry-service")]
54use crate::telemetry_service::TelemetryService;
55#[cfg(feature = "update-service")]
56use crate::update_service::UpdateService;
57
58pub type Vendor<T> = TaggedType<T, VendorTag>;
60#[doc(hidden)]
61#[derive(tagged_types::Tag)]
62#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
63#[transparent(Debug, Display, Serialize, Deserialize)]
64#[capability(inner_access, cloned)]
65pub enum VendorTag {}
66
67pub type Product<T> = TaggedType<T, ProductTag>;
69#[doc(hidden)]
70#[derive(tagged_types::Tag)]
71#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
72#[transparent(Debug, Display, Serialize, Deserialize)]
73#[capability(inner_access, cloned)]
74pub enum ProductTag {}
75
76pub type RedfishVersion<'a> = TaggedType<&'a str, RedfishVersionTag>;
78#[doc(hidden)]
79#[derive(tagged_types::Tag)]
80#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
81#[transparent(Debug, Display, Serialize, Deserialize)]
82#[capability(inner_access, cloned)]
83pub enum RedfishVersionTag {}
84
85pub struct ServiceRoot<B: Bmc> {
87 pub root: Arc<SchemaServiceRoot>,
89 #[allow(dead_code)] bmc: NvBmc<B>,
91}
92
93impl<B: Bmc> Clone for ServiceRoot<B> {
96 fn clone(&self) -> Self {
97 Self {
98 root: self.root.clone(),
99 bmc: self.bmc.clone(),
100 }
101 }
102}
103
104impl<B: Bmc> ServiceRoot<B> {
105 pub async fn new(bmc: Arc<B>) -> Result<Self, Error<B>> {
111 let root = NavProperty::<SchemaServiceRoot>::new_reference(ODataId::service_root())
112 .get(bmc.as_ref())
113 .await
114 .map_err(Error::Bmc)?;
115 let quirks = BmcQuirks::new(&root);
116 let mut protocol_features = root
117 .protocol_features_supported
118 .as_ref()
119 .map(ProtocolFeatures::new)
120 .unwrap_or_default();
121
122 if quirks.expand_is_not_working_properly() {
123 protocol_features.expand.expand_all = false;
124 protocol_features.expand.no_links = false;
125 }
126
127 let bmc = NvBmc::new(bmc, protocol_features, quirks);
128 Ok(Self { root, bmc })
129 }
130
131 #[must_use]
133 pub fn replace_bmc(self, bmc: Arc<B>) -> Self {
134 let root = self.root;
135 let bmc = self.bmc.replace_bmc(bmc);
136 Self { root, bmc }
137 }
138
139 #[must_use]
141 pub fn restrict_expand(self) -> Self {
142 let root = self.root;
143 let bmc = self.bmc.restrict_expand();
144 Self { root, bmc }
145 }
146
147 pub fn vendor(&self) -> Option<Vendor<&str>> {
149 self.root
150 .vendor
151 .as_ref()
152 .and_then(Option::as_ref)
153 .map(String::as_str)
154 .map(Vendor::new)
155 }
156
157 pub fn product(&self) -> Option<Product<&str>> {
159 self.root
160 .product
161 .as_ref()
162 .and_then(Option::as_ref)
163 .map(String::as_str)
164 .map(Product::new)
165 }
166
167 pub fn redfish_version(&self) -> Option<RedfishVersion<'_>> {
169 self.root
170 .redfish_version
171 .as_deref()
172 .map(RedfishVersion::new)
173 }
174
175 #[cfg(feature = "accounts")]
183 pub async fn account_service(&self) -> Result<Option<AccountService<B>>, Error<B>> {
184 AccountService::new(&self.bmc, self).await
185 }
186
187 #[cfg(feature = "chassis")]
195 pub async fn chassis(&self) -> Result<Option<ChassisCollection<B>>, Error<B>> {
196 ChassisCollection::new(&self.bmc, self).await
197 }
198
199 #[cfg(feature = "chassis")]
207 pub async fn chassis_links(&self) -> Result<Option<Vec<ChassisLink<B>>>, Error<B>> {
208 if let Some(collection) = &self.root.chassis {
209 let collection = collection
210 .get(self.bmc.as_ref())
211 .await
212 .map_err(Error::Bmc)?;
213 Ok(Some(
214 collection
215 .members
216 .iter()
217 .map(|member| {
218 ChassisLink::new(&self.bmc, NavProperty::new_reference(member.id().clone()))
219 })
220 .collect(),
221 ))
222 } else {
223 Ok(None)
224 }
225 }
226
227 #[cfg(feature = "computer-systems")]
235 pub async fn systems(&self) -> Result<Option<SystemCollection<B>>, Error<B>> {
236 SystemCollection::new(&self.bmc, self).await
237 }
238
239 #[cfg(feature = "update-service")]
247 pub async fn update_service(&self) -> Result<Option<UpdateService<B>>, Error<B>> {
248 UpdateService::new(&self.bmc, self).await
249 }
250
251 #[cfg(feature = "task-service")]
259 pub async fn task_service(&self) -> Result<Option<TaskService<B>>, Error<B>> {
260 TaskService::new(&self.bmc, self).await
261 }
262
263 #[cfg(feature = "event-service")]
271 pub async fn event_service(&self) -> Result<Option<EventService<B>>, Error<B>> {
272 EventService::new(&self.bmc, self).await
273 }
274
275 #[cfg(feature = "telemetry-service")]
283 pub async fn telemetry_service(&self) -> Result<Option<TelemetryService<B>>, Error<B>> {
284 TelemetryService::new(&self.bmc, self).await
285 }
286
287 #[cfg(feature = "session-service")]
295 pub async fn session_service(&self) -> Result<Option<SessionService<B>>, Error<B>> {
296 SessionService::new(&self.bmc, self).await
297 }
298
299 #[cfg(feature = "managers")]
307 pub async fn managers(&self) -> Result<Option<ManagerCollection<B>>, Error<B>> {
308 ManagerCollection::new(&self.bmc, self).await
309 }
310
311 #[cfg(feature = "power-equipment")]
319 pub async fn power_equipment(&self) -> Result<Option<PowerEquipment<B>>, Error<B>> {
320 PowerEquipment::new(&self.bmc, self).await
321 }
322
323 #[cfg(feature = "oem-hpe")]
331 pub fn oem_hpe_ilo_service_ext(&self) -> Result<Option<HpeiLoServiceExt<B>>, Error<B>> {
332 HpeiLoServiceExt::new(&self.root)
333 }
334
335 #[cfg(feature = "oem-ami")]
343 pub fn oem_ami_service_root(&self) -> Result<Option<AmiServiceRoot<B>>, Error<B>> {
344 AmiServiceRoot::new(&self.bmc, &self.root)
345 }
346}
347
348impl<B: Bmc> Resource for ServiceRoot<B> {
349 fn resource_ref(&self) -> &ResourceSchema {
350 &self.root.as_ref().base
351 }
352}