Skip to content

Commit aa1e947

Browse files
committed
fix: newer IDRACs seem to not configure a bios job when the settings an operator is trying to configure are already appended to the pending settings on d to the pending settings. if the bmc returns a 200 status code (OK) and does not include a bios job in the headers, consider it a success
1 parent 71c4357 commit aa1e947

1 file changed

Lines changed: 56 additions & 18 deletions

File tree

src/dell.rs

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,17 +353,9 @@ impl Redfish for Bmc {
353353
}
354354

355355
let url = format!("Systems/{}/Bios/Settings/", self.s.system_id());
356-
let bios_job_id = match self.s.client.patch(&url, set_machine_attrs).await? {
357-
(_, Some(headers)) => {
358-
let jid = self
359-
.parse_job_id_from_response_headers(&url, headers)
360-
.await?;
361-
Some(jid)
362-
}
363-
(_, None) => {
364-
return Err(RedfishError::NoHeader);
365-
}
366-
};
356+
let bios_job_id = self
357+
.patch_settings_for_job_id(&url, set_machine_attrs)
358+
.await?;
367359

368360
let oem_attrs = if let Some(dell) = oem_manager_profiles.get(&RedfishVendor::Dell) {
369361
let model = crate::model_coerce(
@@ -1145,13 +1137,7 @@ impl Redfish for Bmc {
11451137
HashMap::from([("BootOrder", vec![boot_option.id.clone()])]),
11461138
)]);
11471139

1148-
let job_id = match self.s.client.patch(&url, body).await? {
1149-
(_, Some(headers)) => {
1150-
self.parse_job_id_from_response_headers(&url, headers).await
1151-
}
1152-
(_, None) => Err(RedfishError::NoHeader),
1153-
}?;
1154-
return Ok(Some(job_id));
1140+
return self.patch_settings_for_job_id(&url, body).await;
11551141
}
11561142
}
11571143

@@ -2290,6 +2276,58 @@ impl Bmc {
22902276
self.import_system_configuration(system_configuration).await
22912277
}
22922278

2279+
/// PATCHes a Dell settings endpoint and resolves the optional config job
2280+
/// id from the response.
2281+
///
2282+
/// Dell responds to a settings PATCH in one of two ways:
2283+
/// - iDRAC9/iDRAC10 schedule a config job and return `202 Accepted` with a
2284+
/// `location` header pointing at the job; we parse and return its id so
2285+
/// the caller can wait on the job (`Some(job_id)`).
2286+
/// - Newer iDRAC (e.g. 17G PowerEdge R770), when the requested settings are
2287+
/// already staged in the pending-settings buffer, return `200 OK` with no
2288+
/// `location` header (message ID SYS011 "successfully committed", or
2289+
/// SYS413). No job was scheduled, so there is nothing to wait on and we
2290+
/// return `None`.
2291+
///
2292+
/// We deliberately do NOT parse the response message ID: it varies across
2293+
/// iDRAC versions and conditions (SYS011 vs SYS413, etc.), so gating on a
2294+
/// specific value is brittle. A `200` with no job `location` is unambiguous
2295+
/// on its own; any other status surfaces as [`RedfishError::NoHeader`].
2296+
async fn patch_settings_for_job_id<B>(
2297+
&self,
2298+
url: &str,
2299+
body: B,
2300+
) -> Result<Option<String>, RedfishError>
2301+
where
2302+
B: Serialize + std::fmt::Debug,
2303+
{
2304+
// Pass `body` by reference so it stays available to log on the no-job
2305+
// path below; serde implements `Serialize`/`Debug` for `&B`.
2306+
let (status_code, resp_headers) = self.s.client.patch(url, &body).await?;
2307+
2308+
match resp_headers
2309+
.as_ref()
2310+
.filter(|headers| headers.contains_key("location"))
2311+
{
2312+
Some(headers) => Ok(Some(
2313+
self.parse_job_id_from_response_headers(url, headers.clone())
2314+
.await?,
2315+
)),
2316+
None if status_code == StatusCode::OK => {
2317+
tracing::info!(
2318+
bmc_ip = %self.s.client.host(),
2319+
%url,
2320+
%status_code,
2321+
?resp_headers,
2322+
?body,
2323+
"Dell settings PATCH applied without scheduling a job (no location header); treating as success"
2324+
);
2325+
Ok(None)
2326+
}
2327+
None => Err(RedfishError::NoHeader),
2328+
}
2329+
}
2330+
22932331
async fn parse_job_id_from_response_headers(
22942332
&self,
22952333
url: &str,

0 commit comments

Comments
 (0)