From 8c533c5aab948fff3ebef12a6d965c9303302c35 Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Thu, 17 Jun 2021 08:30:00 +0000 Subject: [PATCH 1/3] builtin/tree: inject _dbpath macro file in postprocessing step This wires the _dbpath macro injection logic to `compose postprocess`, in order to make sure that the rpm configuration in the commit matches the location of the rpmdb database. --- rust/src/composepost.rs | 12 +++++++++--- rust/src/lib.rs | 1 + src/libpriv/rpmostree-postprocess.cxx | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/rust/src/composepost.rs b/rust/src/composepost.rs index c63ca8fa5..4e000a97e 100644 --- a/rust/src/composepost.rs +++ b/rust/src/composepost.rs @@ -172,9 +172,15 @@ fn postprocess_presets(rootfs_dfd: &openat::Dir) -> Result<()> { Ok(()) } -// We keep hitting issues with the ostree-remount preset not being -// enabled; let's just do this rather than trying to propagate the -// preset everywhere. +/// Write an RPM macro file to ensure the rpmdb path is set on the client side. +pub fn compose_postprocess_rpm_macro(rootfs_dfd: i32) -> CxxResult<()> { + let rootfs = &crate::ffiutil::ffi_view_openat_dir(rootfs_dfd); + postprocess_rpm_macro(rootfs)?; + Ok(()) +} + +/// Ensure our own `_dbpath` macro exists in the tree. +#[context("Writing _dbpath RPM macro")] fn postprocess_rpm_macro(rootfs_dfd: &openat::Dir) -> Result<()> { let rpm_macros_dir = "usr/lib/rpm/macros.d"; rootfs_dfd.ensure_dir_all(rpm_macros_dir, 0o755)?; diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 4c328fe4c..658a7fa95 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -160,6 +160,7 @@ pub mod ffi { rootfs_dfd: i32, cancellable: Pin<&mut GCancellable>, ) -> Result<()>; + fn compose_postprocess_rpm_macro(rootfs_dfd: i32) -> Result<()>; } // A grab-bag of metadata from the deployment's ostree commit diff --git a/src/libpriv/rpmostree-postprocess.cxx b/src/libpriv/rpmostree-postprocess.cxx index 42aa0b569..781c3a15c 100644 --- a/src/libpriv/rpmostree-postprocess.cxx +++ b/src/libpriv/rpmostree-postprocess.cxx @@ -649,6 +649,9 @@ rpmostree_rootfs_postprocess_common (int rootfs_fd, } } + /* Make sure there is an RPM macro in place pointing to the rpmdb in /usr */ + rpmostreecxx::compose_postprocess_rpm_macro(rootfs_fd); + if (!rpmostree_cleanup_leftover_rpmdb_files (rootfs_fd, cancellable, error)) return FALSE; From ac7c64428594726a5420b1c11d7b6d6a48ffc0a8 Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Sun, 13 Jun 2021 13:50:39 +0000 Subject: [PATCH 2/3] libpriv/core: set _dbpath macro in dnf context This ensures that the `_dbpath` macro is always in all dnf contexts, in order to use the rpmdb under /usr. Setting it explicitly makes sure that there is no logic implicitly relying on host configuration. This is particularly relevant in server-side compose cases, which are more likely to be running in an environment without rpm-ostree macro file. --- src/libpriv/rpmostree-core.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx index 12381e20e..ab0e0ef54 100644 --- a/src/libpriv/rpmostree-core.cxx +++ b/src/libpriv/rpmostree-core.cxx @@ -379,6 +379,9 @@ rpmostree_context_new_client (OstreeRepo *repo) dnf_context_set_zchunk (self->dnfctx, FALSE); #endif + /* The rpmdb is at /usr/share/rpm */ + dnf_context_set_rpm_macro (self->dnfctx, "_dbpath", "/" RPMOSTREE_RPMDB_LOCATION); + return self; } From bfdebee9f8b0bf7c4488bcfe723b12faed784da8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 11 Jun 2021 15:33:30 +0000 Subject: [PATCH 3/3] builtin/tree: explicitly set _dbpath macro in global libdnf initialization This ensures that the `_dbpath` macro is always in all dnf contexts, in order to use the rpmdb under /usr. Setting it explicitly makes sure that there is no logic implicitly relying on host configuration. This is particularly relevant in server-side compose cases, which are more likely to be running in an environment without rpm-ostree macro file. --- src/app/rpmostree-compose-builtin-tree.cxx | 2 ++ src/libpriv/rpmostree-core.cxx | 32 +++++++++++++++++++--- src/libpriv/rpmostree-core.h | 4 +++ src/libpriv/rpmostree-rpm-util.cxx | 2 ++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/app/rpmostree-compose-builtin-tree.cxx b/src/app/rpmostree-compose-builtin-tree.cxx index 4d88ee95f..d6eef2c44 100644 --- a/src/app/rpmostree-compose-builtin-tree.cxx +++ b/src/app/rpmostree-compose-builtin-tree.cxx @@ -574,6 +574,8 @@ rpm_ostree_compose_context_new (const char *treefile_pathstr, { g_autoptr(RpmOstreeTreeComposeContext) self = g_new0 (RpmOstreeTreeComposeContext, 1); + rpmostreecxx::core_libdnf_process_global_init(); + /* Init fds to -1 */ self->workdir_dfd = self->rootfs_dfd = self->cachedir_dfd = -1; /* Test whether or not bwrap is going to work - we will fail inside e.g. a Docker diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx index ab0e0ef54..e142ccd76 100644 --- a/src/libpriv/rpmostree-core.cxx +++ b/src/libpriv/rpmostree-core.cxx @@ -653,6 +653,32 @@ rpmostree_context_set_treespec (RpmOstreeContext *self, RpmOstreeTreespec *trees self->spec = (RpmOstreeTreespec*)g_object_ref (treespec); } +namespace rpmostreecxx { +// Sadly, like most of librpm, macros are a process-global state. +// For rpm-ostree, the dbpath must be overriden. +void +core_libdnf_process_global_init() +{ + static gsize initialized = 0; + + if (g_once_init_enter (&initialized)) + { + g_autoptr(GError) error = NULL; + /* Fatally error out if this fails */ + if (!dnf_context_globals_init (&error)) + g_error ("%s", error->message); + + /* This is what we use as default. Note we should be able to drop this in the + * future on the *client side* now that we inject a macro to set that value in our OSTrees. + */ + free (rpmExpand ("%define _dbpath /" RPMOSTREE_RPMDB_LOCATION, NULL)); + + g_once_init_leave (&initialized, 1); + } +} + +} /* namespace */ + /* Wraps `dnf_context_setup()`, and initializes state based on the treespec * @spec. Another way to say it is we pair `DnfContext` with an * `RpmOstreeTreespec`. For example, we handle "instlangs", set the rpmdb root @@ -674,6 +700,8 @@ rpmostree_context_setup (RpmOstreeContext *self, /* This exists (as a canonically empty dir) at least on RHEL7+ */ static const char emptydir_path[] = "/usr/share/empty"; + rpmostreecxx::core_libdnf_process_global_init(); + /* Auto-synthesize a spec for now; this will be removed */ if (!self->spec) rpmostree_context_set_treespec (self, NULL); @@ -710,10 +738,6 @@ rpmostree_context_setup (RpmOstreeContext *self, dnf_context_set_rpm_macro (self->dnfctx, "_install_langs", instlangs.c_str()); } - /* This is what we use as default. Note we should be able to drop this in the - * future now that we inject a macro to set that value in our OSTrees. */ - dnf_context_set_rpm_macro (self->dnfctx, "_dbpath", "/" RPMOSTREE_RPMDB_LOCATION); - /* Set the database backend only in the compose path. It then becomes the default * for any client side layering. */ diff --git a/src/libpriv/rpmostree-core.h b/src/libpriv/rpmostree-core.h index 1db1014cd..cea97028e 100644 --- a/src/libpriv/rpmostree-core.h +++ b/src/libpriv/rpmostree-core.h @@ -78,6 +78,10 @@ char* rpmostree_refspec_to_string (RpmOstreeRefspecType reftype, char* rpmostree_refspec_canonicalize (const char *orig_refspec, GError **error); +namespace rpmostreecxx { +void core_libdnf_process_global_init(); +} + RpmOstreeContext *rpmostree_context_new_client (OstreeRepo *repo); RpmOstreeContext *rpmostree_context_new_compose (int basedir_dfd, diff --git a/src/libpriv/rpmostree-rpm-util.cxx b/src/libpriv/rpmostree-rpm-util.cxx index 57bdda4ed..19640b864 100644 --- a/src/libpriv/rpmostree-rpm-util.cxx +++ b/src/libpriv/rpmostree-rpm-util.cxx @@ -851,6 +851,8 @@ get_sack_for_root (int dfd, GLNX_AUTO_PREFIX_ERROR ("Loading sack", error); g_assert (out_sack != NULL); + rpmostreecxx::core_libdnf_process_global_init(); + g_autofree char *fullpath = glnx_fdrel_abspath (dfd, path); g_autoptr(DnfSack) sack = dnf_sack_new ();