-
Notifications
You must be signed in to change notification settings - Fork 117
Add kexec support #1076
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
base: main
Are you sure you want to change the base?
Add kexec support #1076
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 |
---|---|---|
|
@@ -478,6 +478,27 @@ pub(crate) fn get_base_commit(repo: &ostree::Repo, commit: &str) -> Result<Optio | |
Ok(r) | ||
} | ||
|
||
#[context("Loading deployment into kexec")] | ||
async fn kexec_load(sysroot: &Storage, deployment: &Deployment) -> Result<()> { | ||
// Clone all the things to move to worker thread | ||
let sysroot = sysroot.sysroot.clone(); | ||
// ostree::Deployment is incorrently !Send 😢 so convert it to an integer | ||
let deployment_index = deployment.index() as usize; | ||
|
||
async_task_with_spinner( | ||
"Deploying", | ||
spawn_blocking_cancellable_flatten(move |cancellable| -> Result<()> { | ||
let deployments = sysroot.deployments(); | ||
let deployment = &deployments[deployment_index]; | ||
|
||
sysroot.deployment_kexec_load(&deployment, Some(cancellable))?; | ||
Ok(()) | ||
}), | ||
) | ||
.await?; | ||
Ok(()) | ||
} | ||
|
||
#[context("Writing deployment")] | ||
async fn deploy( | ||
sysroot: &Storage, | ||
|
@@ -552,6 +573,12 @@ fn origin_from_imageref(imgref: &ImageReference) -> Result<glib::KeyFile> { | |
Ok(origin) | ||
} | ||
|
||
#[derive(Debug, Clone, Default)] | ||
#[non_exhaustive] | ||
pub(crate) struct StageOptions { | ||
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. Not opposed but this feels slightly overkill at this point - we don't have that many parameters to the function. (And if we did we may as well move the progress writer in?) I think a simple |
||
pub(crate) deploy_kexec: bool, | ||
} | ||
|
||
/// Stage (queue deployment of) a fetched container image. | ||
#[context("Staging")] | ||
pub(crate) async fn stage( | ||
|
@@ -560,7 +587,11 @@ pub(crate) async fn stage( | |
image: &ImageState, | ||
spec: &RequiredHostSpec<'_>, | ||
prog: ProgressWriter, | ||
StageOptions { deploy_kexec }: StageOptions, | ||
) -> Result<()> { | ||
let steps_total = 4 + (deploy_kexec as u64); | ||
let mut steps = 0; | ||
Comment on lines
+592
to
+593
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. How about:
? Feels like it will "scale" a bit more cleanly if we have more conditionals later. (This all said, I'd really like to have higher level wrappers for the progress API because the numbers here are SO easy to mess up) 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. Yeah, that's pretty much the same idea, but I see how that would be cleaner. 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. I think I originally arrived at this from:
|
||
|
||
let mut subtask = SubTaskStep { | ||
subtask: "merging".into(), | ||
description: "Merging Image".into(), | ||
|
@@ -574,7 +605,7 @@ pub(crate) async fn stage( | |
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps: 0, | ||
steps_total: 3, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
|
@@ -590,13 +621,14 @@ pub(crate) async fn stage( | |
subtask.id = "deploying".into(); | ||
subtask.description = "Deploying Image".into(); | ||
subtask.completed = false; | ||
steps += 1; | ||
prog.send(Event::ProgressSteps { | ||
task: "staging".into(), | ||
description: "Deploying Image".into(), | ||
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps: 1, | ||
steps_total: 3, | ||
steps, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
|
@@ -620,13 +652,14 @@ pub(crate) async fn stage( | |
subtask.id = "bound_images".into(); | ||
subtask.description = "Pulling Bound Images".into(); | ||
subtask.completed = false; | ||
steps += 1; | ||
prog.send(Event::ProgressSteps { | ||
task: "staging".into(), | ||
description: "Deploying Image".into(), | ||
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps: 1, | ||
steps_total: 3, | ||
steps, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
|
@@ -642,13 +675,14 @@ pub(crate) async fn stage( | |
subtask.id = "cleanup".into(); | ||
subtask.description = "Removing old images".into(); | ||
subtask.completed = false; | ||
steps += 1; | ||
prog.send(Event::ProgressSteps { | ||
task: "staging".into(), | ||
description: "Deploying Image".into(), | ||
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps: 2, | ||
steps_total: 3, | ||
steps, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
|
@@ -663,15 +697,42 @@ pub(crate) async fn stage( | |
} | ||
println!(" Digest: {}", image.manifest_digest); | ||
|
||
if deploy_kexec { | ||
subtask.completed = true; | ||
subtasks.push(subtask.clone()); | ||
subtask.subtask = "kexec".into(); | ||
subtask.id = "kexec".into(); | ||
subtask.description = "Loading image into kexec".into(); | ||
subtask.completed = false; | ||
steps += 1; | ||
prog.send(Event::ProgressSteps { | ||
task: "staging".into(), | ||
description: "Deploying Image".into(), | ||
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
.chain([subtask.clone()]) | ||
.collect(), | ||
}) | ||
.await; | ||
crate::deploy::kexec_load(sysroot, &deployment).await?; | ||
println!(" Next reboot will kexec into this deployment!"); | ||
} | ||
|
||
subtask.completed = true; | ||
subtasks.push(subtask.clone()); | ||
steps += 1; | ||
prog.send(Event::ProgressSteps { | ||
task: "staging".into(), | ||
description: "Deploying Image".into(), | ||
id: image.manifest_digest.clone().as_ref().into(), | ||
steps_cached: 0, | ||
steps: 3, | ||
steps_total: 3, | ||
steps, | ||
steps_total, | ||
subtasks: subtasks | ||
.clone() | ||
.into_iter() | ||
|
Uh oh!
There was an error while loading. Please reload this page.