upgrader: Use "pending" deployment for origin by default
Until now, we always used the booted deployment, and would garbage collect the "pending" deployment. This is the way OSTree was designed, but I think for rpm-ostree given how mutable we are on the client side, there's a much stronger argument for being more stateful too. This is a relatively simple code change to split the "merge deployment" concept into two. There's now the "config merge deployment" and the "origin merge deployment". Basically, `rpm-ostree install foo; rpm-ostree install bar` will now install both `foo` and `bar`. But we will still use the booted deployment for `/etc`. Down the line, I think I'd like to drive into OSTree the concept of a "staged" deployment, that has the hardlink checkout done, but doesn't have the config merge. But we don't need to change the OSTree core for this yet; we can do it here in rpm-ostree, and this relatively simple code change fixes many issues at once. For example, `rpm-ostree upgrade && rpm-ostree install foo` now does what you expect as well. Obviously, we want to enable doing multiple things in *one* transaction, and we're not far away, but I think this is also the right thing to do now. I'm relatively confident it won't break anyone's workflow, as what we did before wasn't generally that useful. However, people will need to learn to `ostree admin undeploy 0` if they *don't* want this behavior. (We need to have `rpm-ostree cleanup`). Closes: https://github.com/projectatomic/rpm-ostree/issues/406 Closes: #611 Approved by: jlebon
This commit is contained in:
parent
a52cb7d78e
commit
0a1289ae38
@ -66,7 +66,8 @@ struct RpmOstreeSysrootUpgrader {
|
||||
char *osname;
|
||||
RpmOstreeSysrootUpgraderFlags flags;
|
||||
|
||||
OstreeDeployment *merge_deployment;
|
||||
OstreeDeployment *cfg_merge_deployment;
|
||||
OstreeDeployment *origin_merge_deployment;
|
||||
RpmOstreeOrigin *original_origin;
|
||||
RpmOstreeOrigin *origin;
|
||||
GHashTable *ignore_scripts;
|
||||
@ -132,6 +133,31 @@ parse_origin_deployment (RpmOstreeSysrootUpgrader *self,
|
||||
return parse_origin_keyfile (self, origin, cancellable, error);
|
||||
}
|
||||
|
||||
/* This is like ostree_sysroot_get_merge_deployment() except we explicitly
|
||||
* ignore the magical "booted" behavior. For rpm-ostree we're trying something
|
||||
* different now where we are a bit more stateful and pick up changes from the
|
||||
* pending root. This allows users to chain operations together naturally.
|
||||
*/
|
||||
static OstreeDeployment *
|
||||
get_origin_merge_deployment (OstreeSysroot *self,
|
||||
const char *osname)
|
||||
{
|
||||
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (self);
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < deployments->len; i++)
|
||||
{
|
||||
OstreeDeployment *deployment = deployments->pdata[i];
|
||||
|
||||
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
|
||||
continue;
|
||||
|
||||
return g_object_ref (deployment);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
@ -164,8 +190,9 @@ rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
|
||||
if (!ostree_sysroot_get_repo (self->sysroot, &self->repo, cancellable, error))
|
||||
goto out;
|
||||
|
||||
self->merge_deployment = ostree_sysroot_get_merge_deployment (self->sysroot, self->osname);
|
||||
if (self->merge_deployment == NULL)
|
||||
self->cfg_merge_deployment = ostree_sysroot_get_merge_deployment (self->sysroot, self->osname);
|
||||
self->origin_merge_deployment = get_origin_merge_deployment (self->sysroot, self->osname);
|
||||
if (self->cfg_merge_deployment == NULL || self->origin_merge_deployment == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"No previous deployment for OS '%s'", self->osname);
|
||||
@ -175,7 +202,7 @@ rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
|
||||
/* Should we consider requiring --discard-hotfix here?
|
||||
* See also `ostree admin upgrade` bits.
|
||||
*/
|
||||
if (!parse_origin_deployment (self, self->merge_deployment, cancellable, error))
|
||||
if (!parse_origin_deployment (self, self->origin_merge_deployment, cancellable, error))
|
||||
goto out;
|
||||
/* Retain the "original origin", since we may need to make determinations
|
||||
* based on the *old* state as compared to the new one.
|
||||
@ -188,13 +215,13 @@ rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
|
||||
*/
|
||||
if (rpmostree_origin_is_locally_assembled (self->original_origin))
|
||||
{
|
||||
self->final_revision = g_strdup (ostree_deployment_get_csum (self->merge_deployment));
|
||||
self->final_revision = g_strdup (ostree_deployment_get_csum (self->origin_merge_deployment));
|
||||
if (!commit_get_parent_csum (self->repo, self->final_revision, &self->base_revision, error))
|
||||
goto out;
|
||||
g_assert (self->base_revision);
|
||||
}
|
||||
else
|
||||
self->base_revision = g_strdup (ostree_deployment_get_csum (self->merge_deployment));
|
||||
self->base_revision = g_strdup (ostree_deployment_get_csum (self->origin_merge_deployment));
|
||||
|
||||
self->packages_to_add = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
@ -230,7 +257,8 @@ rpmostree_sysroot_upgrader_finalize (GObject *object)
|
||||
g_clear_object (&self->repo);
|
||||
g_free (self->osname);
|
||||
|
||||
g_clear_object (&self->merge_deployment);
|
||||
g_clear_object (&self->cfg_merge_deployment);
|
||||
g_clear_object (&self->origin_merge_deployment);
|
||||
g_clear_pointer (&self->original_origin, (GDestroyNotify)rpmostree_origin_unref);
|
||||
g_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
|
||||
g_hash_table_unref (self->packages_to_add);
|
||||
@ -473,7 +501,7 @@ rpmostree_sysroot_upgrader_get_packages (RpmOstreeSysrootUpgrader *self)
|
||||
OstreeDeployment*
|
||||
rpmostree_sysroot_upgrader_get_merge_deployment (RpmOstreeSysrootUpgrader *self)
|
||||
{
|
||||
return self->merge_deployment;
|
||||
return self->origin_merge_deployment;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -610,7 +638,7 @@ rpmostree_sysroot_upgrader_pull (RpmOstreeSysrootUpgrader *self,
|
||||
else
|
||||
refs_to_fetch[0] = origin_ref;
|
||||
|
||||
g_assert (self->merge_deployment);
|
||||
g_assert (self->origin_merge_deployment);
|
||||
if (origin_remote)
|
||||
{
|
||||
if (!ostree_repo_pull_one_dir (self->repo, origin_remote, dir_to_pull, refs_to_fetch,
|
||||
@ -955,7 +983,7 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
|
||||
g_file_get_path (ostree_sysroot_get_path (self->sysroot));
|
||||
g_autofree char *merge_deployment_dirpath =
|
||||
ostree_sysroot_get_deployment_dirpath (self->sysroot,
|
||||
self->merge_deployment);
|
||||
self->cfg_merge_deployment);
|
||||
g_autofree char *merge_deployment_root =
|
||||
g_build_filename (sysroot_path, merge_deployment_dirpath, NULL);
|
||||
g_autofree char *reposdir = g_build_filename (merge_deployment_root,
|
||||
@ -1431,7 +1459,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
if (!ostree_sysroot_deploy_tree (self->sysroot, self->osname,
|
||||
target_revision,
|
||||
rpmostree_origin_get_keyfile (self->origin),
|
||||
self->merge_deployment,
|
||||
self->cfg_merge_deployment,
|
||||
NULL,
|
||||
&new_deployment,
|
||||
cancellable, error))
|
||||
@ -1450,7 +1478,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
|
||||
if (!ostree_sysroot_simple_write_deployment (self->sysroot, self->osname,
|
||||
new_deployment,
|
||||
self->merge_deployment,
|
||||
self->cfg_merge_deployment,
|
||||
OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
@ -87,9 +87,30 @@ echo "ok pkg foo relayered on deploy"
|
||||
# REBASE
|
||||
|
||||
commit=$(vm_cmd ostree commit -b rebase_test --tree=ref=vmcheck)
|
||||
vm_rpmostree rebase rebase_test
|
||||
vm_rpmostree rebase --skip-purge rebase_test
|
||||
reboot_and_assert_base $commit
|
||||
echo "ok rebase"
|
||||
|
||||
vm_assert_layered_pkg foo present
|
||||
echo "ok pkg foo relayered on rebase"
|
||||
|
||||
# rollup: install/deploy/uninstall
|
||||
|
||||
vm_assert_status_jq ".deployments[0][\"base-checksum\"] == \"${commit}\"" \
|
||||
'.deployments[0]["packages"]|index("foo") >= 0' \
|
||||
'.deployments[0]["packages"]|index("nonrootcap")|not'
|
||||
vm_rpmostree install nonrootcap
|
||||
vm_assert_status_jq ".deployments[0][\"base-checksum\"] == \"${commit}\"" \
|
||||
'.deployments[0]["packages"]|index("foo") >= 0' \
|
||||
'.deployments[0]["packages"]|index("nonrootcap") >= 0'
|
||||
commit=$(vm_cmd ostree commit -b vmcheck \
|
||||
--tree=ref=vmcheck --add-metadata-string=version=my-commit2)
|
||||
vm_rpmostree rebase ${commit}
|
||||
vm_assert_status_jq ".deployments[0][\"base-checksum\"] == \"${commit}\"" \
|
||||
'.deployments[0]["packages"]|index("foo") >= 0' \
|
||||
'.deployments[0]["packages"]|index("nonrootcap") >= 0'
|
||||
vm_rpmostree uninstall foo
|
||||
vm_assert_status_jq ".deployments[0][\"base-checksum\"] == \"${commit}\"" \
|
||||
'.deployments[0]["packages"]|index("foo")|not' \
|
||||
'.deployments[0]["packages"]|index("nonrootcap") >= 0'
|
||||
echo "ok rollup"
|
||||
|
Loading…
Reference in New Issue
Block a user