-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Implement API to set NTP servers #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1388,6 +1388,51 @@ impl Redfish for Bmc { | |
| Ok(()) | ||
| }) | ||
| } | ||
|
|
||
| fn set_ntp_servers<'a>( | ||
| &'a self, | ||
| servers: &'a [String], | ||
| ) -> crate::RedfishFuture<'a, Result<(), RedfishError>> { | ||
| Box::pin(async move { | ||
| if servers.is_empty() { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let mut attrs = HashMap::new(); | ||
| attrs.insert("NTPConfigGroup.1.NTPEnable", "Enabled"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused slots keep stale values when fewer than 3 servers are passed into |
||
| if let Some(s1) = servers.first() { | ||
| attrs.insert("NTPConfigGroup.1.NTP1", s1.as_str()); | ||
| } | ||
| if let Some(s2) = servers.get(1) { | ||
| attrs.insert("NTPConfigGroup.1.NTP2", s2.as_str()); | ||
| } | ||
| if let Some(s3) = servers.get(2) { | ||
| attrs.insert("NTPConfigGroup.1.NTP3", s3.as_str()); | ||
| } | ||
|
|
||
| // Try standard path first | ||
| let body = HashMap::from([("Attributes", attrs)]); | ||
| let manager_id = self.s.manager_id(); | ||
| let standard_url = format!("Managers/{manager_id}/Attributes"); | ||
| match self.s.client.patch(&standard_url, &body).await { | ||
| Ok(_) => return Ok(()), | ||
| Err(RedfishError::HTTPErrorCode { | ||
| status_code: StatusCode::NOT_FOUND, | ||
| .. | ||
| }) => { | ||
| tracing::info!( | ||
| "Managers/Attributes not found, using OEM DellAttributes path for NTP server config" | ||
| ); | ||
| } | ||
| Err(e) => return Err(e), | ||
| } | ||
|
|
||
| // Fallback to OEM DellAttributes path | ||
| let oem_url = format!("Managers/{manager_id}/Oem/Dell/DellAttributes/{manager_id}"); | ||
| self.s.client.patch(&oem_url, body).await?; | ||
| Ok(()) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl Bmc { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1197,6 +1197,27 @@ impl Redfish for Bmc { | |
| fn set_utc_timezone<'a>(&'a self) -> crate::RedfishFuture<'a, Result<(), RedfishError>> { | ||
| Box::pin(async move { self.s.set_utc_timezone().await }) | ||
| } | ||
|
|
||
| fn set_ntp_servers<'a>( | ||
| &'a self, | ||
| servers: &'a [String], | ||
| ) -> crate::RedfishFuture<'a, Result<(), RedfishError>> { | ||
| Box::pin(async move { | ||
| if servers.is_empty() { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| // iLO supports at most 2 static NTP servers; extra entries are ignored. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can do something like this instead: Also we should log when a user passes in more than 2 servers: |
||
| let static_ntp_servers = vec![ | ||
| servers.first().cloned().unwrap_or_default(), | ||
| servers.get(1).cloned().unwrap_or_default(), | ||
| ]; | ||
|
|
||
| let url = format!("Managers/{}/DateTime", self.s.manager_id()); | ||
| let body = HashMap::from([("StaticNTPServers", static_ntp_servers)]); | ||
| self.s.client.patch(&url, body).await.map(|_resp| ()) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl Bmc { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1230,6 +1230,13 @@ impl Redfish for RedfishStandard { | |
| Ok(()) | ||
| }) | ||
| } | ||
|
|
||
| fn set_ntp_servers<'a>( | ||
| &'a self, | ||
| servers: &'a [String], | ||
| ) -> crate::RedfishFuture<'a, Result<(), RedfishError>> { | ||
| Box::pin(async move { self.set_manager_ntp_servers(servers).await }) | ||
| } | ||
| } | ||
|
|
||
| impl RedfishStandard { | ||
|
|
@@ -1624,6 +1631,23 @@ impl RedfishStandard { | |
| Ok(body) | ||
| } | ||
|
|
||
| /// Set NTP servers via the standard ManagerNetworkProtocol resource. | ||
| pub async fn set_manager_ntp_servers(&self, servers: &[String]) -> Result<(), RedfishError> { | ||
| if servers.is_empty() { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| let url = format!("Managers/{}/NetworkProtocol", self.manager_id(),); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra comma next to |
||
| let ntp_servers = HashMap::from([( | ||
| "NTP", | ||
| json!({ | ||
| "NTPServers": servers, | ||
| "ProtocolEnabled": true, | ||
| }), | ||
| )]); | ||
| self.client.patch(&url, ntp_servers).await.map(|_resp| ()) | ||
| } | ||
|
|
||
| pub async fn reset_manager( | ||
| &self, | ||
| reset_type: ManagerResetType, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AMI servers require
PATCH's to be sent with anIf-Matchheader. Instead of delegating it to the standard implementation, do the following: