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-hpe")]
44use crate::oem::hpe::HpeiLoServiceExt;
45#[cfg(feature = "session-service")]
46use crate::session_service::SessionService;
47#[cfg(feature = "task-service")]
48use crate::task_service::TaskService;
49#[cfg(feature = "telemetry-service")]
50use crate::telemetry_service::TelemetryService;
51#[cfg(feature = "update-service")]
52use crate::update_service::UpdateService;
53
54pub type Vendor<T> = TaggedType<T, VendorTag>;
56#[doc(hidden)]
57#[derive(tagged_types::Tag)]
58#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
59#[transparent(Debug, Display, Serialize, Deserialize)]
60#[capability(inner_access, cloned)]
61pub enum VendorTag {}
62
63pub type Product<T> = TaggedType<T, ProductTag>;
65#[doc(hidden)]
66#[derive(tagged_types::Tag)]
67#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
68#[transparent(Debug, Display, Serialize, Deserialize)]
69#[capability(inner_access, cloned)]
70pub enum ProductTag {}
71
72pub type RedfishVersion<'a> = TaggedType<&'a str, RedfishVersionTag>;
74#[doc(hidden)]
75#[derive(tagged_types::Tag)]
76#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
77#[transparent(Debug, Display, Serialize, Deserialize)]
78#[capability(inner_access, cloned)]
79pub enum RedfishVersionTag {}
80
81pub struct ServiceRoot<B: Bmc> {
83 pub root: Arc<SchemaServiceRoot>,
85 #[allow(dead_code)] bmc: NvBmc<B>,
87}
88
89impl<B: Bmc> Clone for ServiceRoot<B> {
92 fn clone(&self) -> Self {
93 Self {
94 root: self.root.clone(),
95 bmc: self.bmc.clone(),
96 }
97 }
98}
99
100impl<B: Bmc> ServiceRoot<B> {
101 pub async fn new(bmc: Arc<B>) -> Result<Self, Error<B>> {
107 let root = NavProperty::<SchemaServiceRoot>::new_reference(ODataId::service_root())
108 .get(bmc.as_ref())
109 .await
110 .map_err(Error::Bmc)?;
111 let quirks = BmcQuirks::new(&root);
112 let mut protocol_features = root
113 .protocol_features_supported
114 .as_ref()
115 .map(ProtocolFeatures::new)
116 .unwrap_or_default();
117
118 if quirks.expand_is_not_working_properly() {
119 protocol_features.expand.expand_all = false;
120 protocol_features.expand.no_links = false;
121 }
122
123 let bmc = NvBmc::new(bmc, protocol_features, quirks);
124 Ok(Self { root, bmc })
125 }
126
127 #[must_use]
129 pub fn replace_bmc(self, bmc: Arc<B>) -> Self {
130 let root = self.root;
131 let bmc = self.bmc.replace_bmc(bmc);
132 Self { root, bmc }
133 }
134
135 #[must_use]
137 pub fn restrict_expand(self) -> Self {
138 let root = self.root;
139 let bmc = self.bmc.restrict_expand();
140 Self { root, bmc }
141 }
142
143 pub fn vendor(&self) -> Option<Vendor<&str>> {
145 self.root
146 .vendor
147 .as_ref()
148 .and_then(Option::as_ref)
149 .map(String::as_str)
150 .map(Vendor::new)
151 }
152
153 pub fn product(&self) -> Option<Product<&str>> {
155 self.root
156 .product
157 .as_ref()
158 .and_then(Option::as_ref)
159 .map(String::as_str)
160 .map(Product::new)
161 }
162
163 pub fn redfish_version(&self) -> Option<RedfishVersion<'_>> {
165 self.root
166 .redfish_version
167 .as_deref()
168 .map(RedfishVersion::new)
169 }
170
171 #[cfg(feature = "accounts")]
179 pub async fn account_service(&self) -> Result<Option<AccountService<B>>, Error<B>> {
180 AccountService::new(&self.bmc, self).await
181 }
182
183 #[cfg(feature = "chassis")]
191 pub async fn chassis(&self) -> Result<Option<ChassisCollection<B>>, Error<B>> {
192 ChassisCollection::new(&self.bmc, self).await
193 }
194
195 #[cfg(feature = "chassis")]
203 pub async fn chassis_links(&self) -> Result<Option<Vec<ChassisLink<B>>>, Error<B>> {
204 if let Some(collection) = &self.root.chassis {
205 let collection = collection
206 .get(self.bmc.as_ref())
207 .await
208 .map_err(Error::Bmc)?;
209 Ok(Some(
210 collection
211 .members
212 .iter()
213 .map(|member| {
214 ChassisLink::new(&self.bmc, NavProperty::new_reference(member.id().clone()))
215 })
216 .collect(),
217 ))
218 } else {
219 Ok(None)
220 }
221 }
222
223 #[cfg(feature = "computer-systems")]
231 pub async fn systems(&self) -> Result<Option<SystemCollection<B>>, Error<B>> {
232 SystemCollection::new(&self.bmc, self).await
233 }
234
235 #[cfg(feature = "update-service")]
243 pub async fn update_service(&self) -> Result<Option<UpdateService<B>>, Error<B>> {
244 UpdateService::new(&self.bmc, self).await
245 }
246
247 #[cfg(feature = "task-service")]
255 pub async fn task_service(&self) -> Result<Option<TaskService<B>>, Error<B>> {
256 TaskService::new(&self.bmc, self).await
257 }
258
259 #[cfg(feature = "event-service")]
267 pub async fn event_service(&self) -> Result<Option<EventService<B>>, Error<B>> {
268 EventService::new(&self.bmc, self).await
269 }
270
271 #[cfg(feature = "telemetry-service")]
279 pub async fn telemetry_service(&self) -> Result<Option<TelemetryService<B>>, Error<B>> {
280 TelemetryService::new(&self.bmc, self).await
281 }
282
283 #[cfg(feature = "session-service")]
291 pub async fn session_service(&self) -> Result<Option<SessionService<B>>, Error<B>> {
292 SessionService::new(&self.bmc, self).await
293 }
294
295 #[cfg(feature = "managers")]
303 pub async fn managers(&self) -> Result<Option<ManagerCollection<B>>, Error<B>> {
304 ManagerCollection::new(&self.bmc, self).await
305 }
306
307 #[cfg(feature = "oem-hpe")]
315 pub fn oem_hpe_ilo_service_ext(&self) -> Result<Option<HpeiLoServiceExt<B>>, Error<B>> {
316 HpeiLoServiceExt::new(&self.root)
317 }
318}
319
320impl<B: Bmc> Resource for ServiceRoot<B> {
321 fn resource_ref(&self) -> &ResourceSchema {
322 &self.root.as_ref().base
323 }
324}