nv_redfish/
service_root.rs1use crate::bmc_quirks::BmcQuirks;
17use crate::core::Bmc;
18use crate::core::NavProperty;
19use crate::core::ODataId;
20use crate::schema::service_root::ServiceRoot as SchemaServiceRoot;
21use crate::Error;
22use crate::NvBmc;
23use crate::ProtocolFeatures;
24use crate::Resource;
25use crate::ResourceSchema;
26use std::sync::Arc;
27use tagged_types::TaggedType;
28
29#[cfg(feature = "accounts")]
30use crate::account::AccountService;
31#[cfg(feature = "chassis")]
32use crate::chassis::ChassisCollection;
33#[cfg(feature = "chassis")]
34use crate::chassis::ChassisLink;
35#[cfg(feature = "computer-systems")]
36use crate::computer_system::SystemCollection;
37#[cfg(feature = "event-service")]
38use crate::event_service::EventService;
39#[cfg(feature = "managers")]
40use crate::manager::ManagerCollection;
41#[cfg(feature = "oem-hpe")]
42use crate::oem::hpe::HpeiLoServiceExt;
43#[cfg(feature = "session-service")]
44use crate::session_service::SessionService;
45#[cfg(feature = "telemetry-service")]
46use crate::telemetry_service::TelemetryService;
47#[cfg(feature = "update-service")]
48use crate::update_service::UpdateService;
49
50pub type Vendor<T> = TaggedType<T, VendorTag>;
52#[doc(hidden)]
53#[derive(tagged_types::Tag)]
54#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
55#[transparent(Debug, Display, Serialize, Deserialize)]
56#[capability(inner_access, cloned)]
57pub enum VendorTag {}
58
59pub type Product<T> = TaggedType<T, ProductTag>;
61#[doc(hidden)]
62#[derive(tagged_types::Tag)]
63#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
64#[transparent(Debug, Display, Serialize, Deserialize)]
65#[capability(inner_access, cloned)]
66pub enum ProductTag {}
67
68pub type RedfishVersion<'a> = TaggedType<&'a str, RedfishVersionTag>;
70#[doc(hidden)]
71#[derive(tagged_types::Tag)]
72#[implement(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
73#[transparent(Debug, Display, Serialize, Deserialize)]
74#[capability(inner_access, cloned)]
75pub enum RedfishVersionTag {}
76
77pub struct ServiceRoot<B: Bmc> {
79 pub root: Arc<SchemaServiceRoot>,
81 #[allow(dead_code)] bmc: NvBmc<B>,
83}
84
85impl<B: Bmc> Clone for ServiceRoot<B> {
88 fn clone(&self) -> Self {
89 Self {
90 root: self.root.clone(),
91 bmc: self.bmc.clone(),
92 }
93 }
94}
95
96impl<B: Bmc> ServiceRoot<B> {
97 pub async fn new(bmc: Arc<B>) -> Result<Self, Error<B>> {
103 let root = NavProperty::<SchemaServiceRoot>::new_reference(ODataId::service_root())
104 .get(bmc.as_ref())
105 .await
106 .map_err(Error::Bmc)?;
107 let quirks = BmcQuirks::new(&root);
108 let mut protocol_features = root
109 .protocol_features_supported
110 .as_ref()
111 .map(ProtocolFeatures::new)
112 .unwrap_or_default();
113
114 if quirks.expand_is_not_working_properly() {
115 protocol_features.expand.expand_all = false;
116 protocol_features.expand.no_links = false;
117 }
118
119 let bmc = NvBmc::new(bmc, protocol_features, quirks);
120 Ok(Self { root, bmc })
121 }
122
123 #[must_use]
125 pub fn replace_bmc(self, bmc: Arc<B>) -> Self {
126 let root = self.root;
127 let bmc = self.bmc.replace_bmc(bmc);
128 Self { root, bmc }
129 }
130
131 #[must_use]
133 pub fn restrict_expand(self) -> Self {
134 let root = self.root;
135 let bmc = self.bmc.restrict_expand();
136 Self { root, bmc }
137 }
138
139 pub fn vendor(&self) -> Option<Vendor<&str>> {
141 self.root
142 .vendor
143 .as_ref()
144 .and_then(Option::as_ref)
145 .map(String::as_str)
146 .map(Vendor::new)
147 }
148
149 pub fn product(&self) -> Option<Product<&str>> {
151 self.root
152 .product
153 .as_ref()
154 .and_then(Option::as_ref)
155 .map(String::as_str)
156 .map(Product::new)
157 }
158
159 pub fn redfish_version(&self) -> Option<RedfishVersion<'_>> {
161 self.root
162 .redfish_version
163 .as_deref()
164 .map(RedfishVersion::new)
165 }
166
167 #[cfg(feature = "accounts")]
175 pub async fn account_service(&self) -> Result<Option<AccountService<B>>, Error<B>> {
176 AccountService::new(&self.bmc, self).await
177 }
178
179 #[cfg(feature = "chassis")]
187 pub async fn chassis(&self) -> Result<Option<ChassisCollection<B>>, Error<B>> {
188 ChassisCollection::new(&self.bmc, self).await
189 }
190
191 #[cfg(feature = "chassis")]
199 pub async fn chassis_links(&self) -> Result<Option<Vec<ChassisLink<B>>>, Error<B>> {
200 if let Some(collection) = &self.root.chassis {
201 let collection = collection
202 .get(self.bmc.as_ref())
203 .await
204 .map_err(Error::Bmc)?;
205 Ok(Some(
206 collection
207 .members
208 .iter()
209 .map(|member| {
210 ChassisLink::new(&self.bmc, NavProperty::new_reference(member.id().clone()))
211 })
212 .collect(),
213 ))
214 } else {
215 Ok(None)
216 }
217 }
218
219 #[cfg(feature = "computer-systems")]
227 pub async fn systems(&self) -> Result<Option<SystemCollection<B>>, Error<B>> {
228 SystemCollection::new(&self.bmc, self).await
229 }
230
231 #[cfg(feature = "update-service")]
239 pub async fn update_service(&self) -> Result<Option<UpdateService<B>>, Error<B>> {
240 UpdateService::new(&self.bmc, self).await
241 }
242
243 #[cfg(feature = "event-service")]
251 pub async fn event_service(&self) -> Result<Option<EventService<B>>, Error<B>> {
252 EventService::new(&self.bmc, self).await
253 }
254
255 #[cfg(feature = "telemetry-service")]
263 pub async fn telemetry_service(&self) -> Result<Option<TelemetryService<B>>, Error<B>> {
264 TelemetryService::new(&self.bmc, self).await
265 }
266
267 #[cfg(feature = "session-service")]
275 pub async fn session_service(&self) -> Result<Option<SessionService<B>>, Error<B>> {
276 SessionService::new(&self.bmc, self).await
277 }
278
279 #[cfg(feature = "managers")]
287 pub async fn managers(&self) -> Result<Option<ManagerCollection<B>>, Error<B>> {
288 ManagerCollection::new(&self.bmc, self).await
289 }
290
291 #[cfg(feature = "oem-hpe")]
299 pub fn oem_hpe_ilo_service_ext(&self) -> Result<Option<HpeiLoServiceExt<B>>, Error<B>> {
300 HpeiLoServiceExt::new(&self.root)
301 }
302}
303
304impl<B: Bmc> Resource for ServiceRoot<B> {
305 fn resource_ref(&self) -> &ResourceSchema {
306 &self.root.as_ref().base
307 }
308}