1use std::sync::Arc;
32
33use crate::schema::control::Control as ControlSchema;
34#[cfg(feature = "chassis")]
35use crate::schema::control_collection::ControlCollection as ControlCollectionSchema;
36use crate::Error;
37use crate::NvBmc;
38use crate::Resource;
39use crate::ResourceSchema;
40
41use nv_redfish_core::Bmc;
42use nv_redfish_core::EntityTypeRef as _;
43use nv_redfish_core::ModificationResponse;
44use nv_redfish_core::NavProperty;
45
46#[cfg(any(
47 feature = "chassis",
48 feature = "memory",
49 feature = "storages",
50 feature = "processors"
51))]
52use crate::schema::environment_metrics::EnvironmentMetrics;
53
54#[cfg(any(
55 feature = "chassis",
56 feature = "memory",
57 feature = "storages",
58 feature = "processors"
59))]
60use crate::core::ODataId;
61
62pub use crate::schema::control::ControlMode;
63pub use crate::schema::control::ControlType;
64pub use crate::schema::control::ControlUpdate;
65pub use crate::schema::control::ImplementationType;
66pub use crate::schema::control::SetPointType;
67
68#[cfg(feature = "chassis")]
84pub struct ControlCollection<B: Bmc> {
85 bmc: NvBmc<B>,
86 collection: Arc<ControlCollectionSchema>,
87}
88
89#[cfg(feature = "chassis")]
90impl<B: Bmc> ControlCollection<B> {
91 pub(crate) async fn new(
92 bmc: &NvBmc<B>,
93 nav: &NavProperty<ControlCollectionSchema>,
94 ) -> Result<Self, Error<B>> {
95 nav.get(bmc.as_ref())
97 .await
98 .map_err(Error::Bmc)
99 .map(|collection| Self {
100 bmc: bmc.clone(),
101 collection,
102 })
103 }
104
105 #[must_use]
107 pub fn raw(&self) -> Arc<ControlCollectionSchema> {
108 self.collection.clone()
109 }
110
111 pub async fn members(&self) -> Result<Vec<Control<B>>, Error<B>> {
117 let mut controls = Vec::with_capacity(self.collection.members.len());
118
119 for control in &self.collection.members {
120 controls.push(Control::new(&self.bmc, control).await?);
121 }
122
123 Ok(controls)
124 }
125}
126
127pub struct Control<B: Bmc> {
133 bmc: NvBmc<B>,
134 data: Arc<ControlSchema>,
135}
136
137impl<B: Bmc> Control<B> {
138 pub(crate) async fn new(
139 bmc: &NvBmc<B>,
140 nav: &NavProperty<ControlSchema>,
141 ) -> Result<Self, Error<B>> {
142 nav.get(bmc.as_ref())
143 .await
144 .map_err(Error::Bmc)
145 .map(|data| Self {
146 bmc: bmc.clone(),
147 data,
148 })
149 }
150
151 #[must_use]
153 pub fn raw(&self) -> Arc<ControlSchema> {
154 self.data.clone()
155 }
156
157 pub async fn update(
182 &self,
183 update: &ControlUpdate,
184 ) -> Result<ModificationResponse<Self>, Error<B>> {
185 match self
186 .bmc
187 .as_ref()
188 .update::<_, NavProperty<ControlSchema>>(self.data.odata_id(), self.data.etag(), update)
189 .await
190 .map_err(Error::Bmc)?
191 {
192 ModificationResponse::Entity(nav) => Self::new(&self.bmc, &nav)
193 .await
194 .map(ModificationResponse::Entity),
195 ModificationResponse::Task(task) => Ok(ModificationResponse::Task(task)),
196 ModificationResponse::Empty => Ok(ModificationResponse::Empty),
197 }
198 }
199}
200
201impl<B: Bmc> Resource for Control<B> {
202 fn resource_ref(&self) -> &ResourceSchema {
203 &self.data.as_ref().base
204 }
205}
206
207#[cfg(any(
208 feature = "chassis",
209 feature = "memory",
210 feature = "storages",
211 feature = "processors"
212))]
213pub(crate) async fn extract_environment_power_limit_control<B: Bmc>(
214 bmc: &NvBmc<B>,
215 metrics_ref: &NavProperty<EnvironmentMetrics>,
216) -> Result<Option<Control<B>>, Error<B>> {
217 let metrics = metrics_ref.get(bmc.as_ref()).await.map_err(Error::Bmc)?;
218
219 let Some(Some(uri)) = metrics
220 .power_limit_watts
221 .as_ref()
222 .and_then(|control| control.data_source_uri.as_ref())
223 else {
224 return Ok(None);
225 };
226
227 let control_ref = NavProperty::<ControlSchema>::new_reference(ODataId::from(uri.clone()));
228
229 Control::new(bmc, &control_ref).await.map(Some)
230}