Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Commit

Permalink
container: Add deployed commits into set of GC roots
Browse files Browse the repository at this point in the history
Prep for handling image pruning better.  The way things
are kind of expected to work today is that for a deployed ostree
commit, we have *two* refs which point to it - one like e.g.
`fedora:fedora/x86_64/coreos/stable`, as well as the "deployment ref"
like "ostree/0/1/1" which is a synthetic ref generated by the
sysroot core.

We want to be able to remove the container image refs - but
doing so today subjects the *layer* branches to garbage collection.

Fix this by looking at the deployment refs as well as the set of
images when computing the set of references for container images.
  • Loading branch information
cgwalters committed Nov 10, 2022
1 parent b2e3e56 commit c8d4c24
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ci/priv-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ for img in "${image}"; do
ostree-ext-cli container image deploy --sysroot "${sysroot}" \
--stateroot "${stateroot}" --imgref ostree-unverified-registry:"${img}"
ostree admin --sysroot="${sysroot}" status
initial_refs=$(ostree --repo="${sysroot}/ostree/repo" refs | wc -l)
ostree-ext-cli container image remove --repo "${sysroot}/ostree/repo" registry:"${img}"
pruned_refs=$(ostree --repo="${sysroot}/ostree/repo" refs | wc -l)
# Removing the image should only drop the image reference, not its layers
test "$(($initial_refs - 1))" = "$pruned_refs"
ostree admin --sysroot="${sysroot}" undeploy 0
ostree --repo="${sysroot}/ostree/repo" refs > refs.txt
if test "$(wc -l < refs.txt)" -ne 0; then
Expand Down
36 changes: 36 additions & 0 deletions lib/src/container/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,40 @@ pub async fn copy(
Ok(())
}

/// Iterate over deployment commits, returning the manifests from
/// commits which point to a container image.
fn list_container_deployment_manifests(
repo: &ostree::Repo,
cancellable: Option<&gio::Cancellable>,
) -> Result<Vec<ImageManifest>> {
let commits = repo
.list_refs_ext(
Some("ostree/0"),
ostree::RepoListRefsExtFlags::empty(),
cancellable,
)?
.into_iter()
.chain(repo.list_refs_ext(
Some("ostree/1"),
ostree::RepoListRefsExtFlags::empty(),
cancellable,
)?)
.map(|v| v.1);
let mut r = Vec::new();
for commit in commits {
let commit_obj = repo.load_commit(&commit)?.0;
let commit_meta = &glib::VariantDict::new(Some(&commit_obj.child_value(0)));
if commit_meta
.lookup::<String>(META_MANIFEST_DIGEST)?
.is_some()
{
let manifest = manifest_data_from_commitmeta(commit_meta)?.0;
r.push(manifest);
}
}
Ok(r)
}

/// Garbage collect unused image layer references.
///
/// This function assumes no transaction is active on the repository.
Expand All @@ -998,11 +1032,13 @@ fn gc_image_layers_impl(
cancellable: Option<&gio::Cancellable>,
) -> Result<u32> {
let all_images = list_images(repo)?;
let deployment_commits = list_container_deployment_manifests(repo, cancellable)?;
let all_manifests = all_images
.into_iter()
.map(|img| {
ImageReference::try_from(img.as_str()).and_then(|ir| manifest_for_image(repo, &ir))
})
.chain(deployment_commits.into_iter().map(Ok))
.collect::<Result<Vec<_>>>()?;
let mut referenced_layers = BTreeSet::new();
for m in all_manifests.iter() {
Expand Down

0 comments on commit c8d4c24

Please sign in to comment.