Implementation of rollback functionality
(sysroot: &Storage)
| 1164 | |
| 1165 | /// Implementation of rollback functionality |
| 1166 | pub(crate) async fn rollback(sysroot: &Storage) -> Result<()> { |
| 1167 | let ostree = sysroot.get_ostree()?; |
| 1168 | let (booted_ostree, deployments, host) = crate::status::get_status_require_booted(ostree)?; |
| 1169 | |
| 1170 | let new_spec = { |
| 1171 | let mut new_spec = host.spec.clone(); |
| 1172 | new_spec.boot_order = new_spec.boot_order.swap(); |
| 1173 | new_spec |
| 1174 | }; |
| 1175 | |
| 1176 | let repo = &booted_ostree.repo(); |
| 1177 | |
| 1178 | // Just to be sure |
| 1179 | host.spec.verify_transition(&new_spec)?; |
| 1180 | |
| 1181 | let reverting = new_spec.boot_order == BootOrder::Default; |
| 1182 | if reverting { |
| 1183 | println!("notice: Reverting queued rollback state"); |
| 1184 | } |
| 1185 | let rollback_status = host |
| 1186 | .status |
| 1187 | .rollback |
| 1188 | .ok_or_else(|| anyhow!("No rollback available"))?; |
| 1189 | let rollback_image = rollback_status |
| 1190 | .query_image(repo)? |
| 1191 | .ok_or_else(|| anyhow!("Rollback is not container image based"))?; |
| 1192 | |
| 1193 | // Get current booted image for comparison |
| 1194 | let current_image = host |
| 1195 | .status |
| 1196 | .booted |
| 1197 | .as_ref() |
| 1198 | .and_then(|b| b.query_image(repo).ok()?); |
| 1199 | |
| 1200 | tracing::info!( |
| 1201 | message_id = ROLLBACK_JOURNAL_ID, |
| 1202 | bootc.manifest_digest = rollback_image.manifest_digest.as_ref(), |
| 1203 | bootc.ostree_commit = &rollback_image.merge_commit, |
| 1204 | bootc.rollback_type = if reverting { "revert" } else { "rollback" }, |
| 1205 | bootc.current_manifest_digest = current_image |
| 1206 | .as_ref() |
| 1207 | .map(|i| i.manifest_digest.as_ref()) |
| 1208 | .unwrap_or("none"), |
| 1209 | "Rolling back to image: {}", |
| 1210 | rollback_image.manifest_digest |
| 1211 | ); |
| 1212 | // SAFETY: If there's a rollback status, then there's a deployment |
| 1213 | let rollback_deployment = deployments.rollback.expect("rollback deployment"); |
| 1214 | let new_deployments = if reverting { |
| 1215 | [booted_ostree.deployment, rollback_deployment] |
| 1216 | } else { |
| 1217 | [rollback_deployment, booted_ostree.deployment] |
| 1218 | }; |
| 1219 | let new_deployments = new_deployments |
| 1220 | .into_iter() |
| 1221 | .chain(deployments.other) |
| 1222 | .collect::<Vec<_>>(); |
| 1223 | tracing::debug!("Writing new deployments: {new_deployments:?}"); |
nothing calls this directly
no test coverage detected