compose: Add rpmdb option, default to bdb

The design of https://fedoraproject.org/wiki/Changes/Sqlite_Rpmdb
is problematic for us for multiple reasons.  The first big reason
is that rpm-ostree is designed for "cross" builds and e.g. today
we use a Fedora-derived container to build RHEL CoreOS images.

However the default database lives inside the `rpm` package which
means that if we e.g. upgrade the coreos-assembler container to F33
it will suddenly try to use sqlite for RHCOS which is obviously broken.

Related to this, rebases from f32 to f33 w/layered packages
are broken: https://bugzilla.redhat.com/show_bug.cgi?id=1876194#c3

With this we can configure things to continue to use bdb for f33
for ostree-based systems, so that by enforcing an upgrade order
f32 → f33 [bdb] → f34 [sqlite] ... the intermediate f33 w/bdb
still understands sqlite and hence rebases will work.
This commit is contained in:
Colin Walters 2020-09-10 00:33:11 +00:00 committed by OpenShift Merge Robot
parent cdf2c47b46
commit 456a3ec7c2
4 changed files with 47 additions and 0 deletions

View File

@ -94,6 +94,10 @@ It supports the following parameters:
specific filesystem drivers are included. If not specified, specific filesystem drivers are included. If not specified,
`--no-hostonly` will be used. `--no-hostonly` will be used.
* `rpmdb`: String, optional: The RPM database backend. Can be one of
`bdb`, `ndb`, or `sqlite`. If unspecified, defaults to `bdb` for
compatibility.
* `cliwrap`: boolean, optional. Defaults to `false`. If enabled, * `cliwrap`: boolean, optional. Defaults to `false`. If enabled,
rpm-ostree will replace binaries such as `/usr/bin/rpm` with rpm-ostree will replace binaries such as `/usr/bin/rpm` with
wrappers that intercept unsafe operations, or adjust functionality. wrappers that intercept unsafe operations, or adjust functionality.

View File

@ -306,6 +306,7 @@ fn treefile_merge(dest: &mut TreeComposeConfig, src: &mut TreeComposeConfig) {
releasever, releasever,
automatic_version_prefix, automatic_version_prefix,
automatic_version_suffix, automatic_version_suffix,
rpmdb,
mutate_os_release, mutate_os_release,
preserve_passwd, preserve_passwd,
check_passwd, check_passwd,
@ -681,6 +682,16 @@ enum Include {
Multiple(Vec<String>), Multiple(Vec<String>),
} }
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
/// The database backend; see https://github.com/coreos/fedora-coreos-tracker/issues/609
/// and https://fedoraproject.org/wiki/Changes/Sqlite_Rpmdb
enum RpmdbBackend {
BDB,
Sqlite,
NDB,
}
// Because of how we handle includes, *everything* here has to be // Because of how we handle includes, *everything* here has to be
// Option<T>. The defaults live in the code (e.g. machineid-compat defaults // Option<T>. The defaults live in the code (e.g. machineid-compat defaults
// to `true`). // to `true`).
@ -821,6 +832,10 @@ struct TreeComposeConfig {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "add-commit-metadata")] #[serde(rename = "add-commit-metadata")]
add_commit_metadata: Option<BTreeMap<String, serde_json::Value>>, add_commit_metadata: Option<BTreeMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "rpmdb")]
// The database backend
rpmdb: Option<RpmdbBackend>,
#[serde(flatten)] #[serde(flatten)]
legacy_fields: LegacyTreeComposeConfigFields, legacy_fields: LegacyTreeComposeConfigFields,
@ -1026,6 +1041,7 @@ mutate-os-release: ${releasever}
assert!(treefile.releasever.unwrap() == "30"); assert!(treefile.releasever.unwrap() == "30");
assert!(treefile.automatic_version_prefix.unwrap() == "30"); assert!(treefile.automatic_version_prefix.unwrap() == "30");
assert!(treefile.mutate_os_release.unwrap() == "30"); assert!(treefile.mutate_os_release.unwrap() == "30");
assert!(treefile.rpmdb.is_none());
} }
#[test] #[test]
@ -1043,12 +1059,14 @@ gpg_key: foo
boot_location: new boot_location: new
default_target: bar default_target: bar
automatic_version_prefix: baz automatic_version_prefix: baz
rpmdb: sqlite
", ",
); );
assert!(treefile.gpg_key.unwrap() == "foo"); assert!(treefile.gpg_key.unwrap() == "foo");
assert!(treefile.boot_location.unwrap() == BootLocation::New); assert!(treefile.boot_location.unwrap() == BootLocation::New);
assert!(treefile.default_target.unwrap() == "bar"); assert!(treefile.default_target.unwrap() == "bar");
assert!(treefile.automatic_version_prefix.unwrap() == "baz"); assert!(treefile.automatic_version_prefix.unwrap() == "baz");
assert!(treefile.rpmdb.unwrap() == RpmdbBackend::Sqlite);
} }
#[test] #[test]
@ -1512,6 +1530,17 @@ mod ffi {
tf.parsed.readonly_executables.unwrap_or(false) tf.parsed.readonly_executables.unwrap_or(false)
} }
#[no_mangle]
pub extern "C" fn ror_treefile_get_rpmdb(tf: *mut Treefile) -> *mut libc::c_char {
let tf = ref_from_raw_ptr(tf);
let s: &str = match tf.parsed.rpmdb.as_ref().unwrap_or(&RpmdbBackend::BDB) {
RpmdbBackend::BDB => "bdb",
RpmdbBackend::Sqlite => "sqlite",
RpmdbBackend::NDB => "ndb",
};
s.to_string().to_glib_full()
}
#[no_mangle] #[no_mangle]
pub extern "C" fn ror_treefile_free(tf: *mut Treefile) { pub extern "C" fn ror_treefile_free(tf: *mut Treefile) {
if tf.is_null() { if tf.is_null() {

View File

@ -753,6 +753,15 @@ rpmostree_context_setup (RpmOstreeContext *self,
/* This is what we use as default. */ /* This is what we use as default. */
dnf_context_set_rpm_macro (self->dnfctx, "_dbpath", "/" RPMOSTREE_RPMDB_LOCATION); 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.
*/
if (self->treefile_rs)
{
g_autofree char *rpmdb_backend = ror_treefile_get_rpmdb (self->treefile_rs);
dnf_context_set_rpm_macro (self->dnfctx, "_db_backend", rpmdb_backend);
}
if (!dnf_context_setup (self->dnfctx, cancellable, error)) if (!dnf_context_setup (self->dnfctx, cancellable, error))
return FALSE; return FALSE;

View File

@ -95,6 +95,11 @@ ostree --repo=${repo} ls -R ${treeref} /usr/etc/selinux > ls.txt
assert_not_file_has_content ls.txt 'LOCK' assert_not_file_has_content ls.txt 'LOCK'
echo "ok no leftover files" echo "ok no leftover files"
ostree --repo=${repo} ls ${treeref} /usr/share/rpm > ls.txt
assert_file_has_content ls.txt /usr/share/rpm/Packages
assert_not_file_has_content ls.txt rpmdb.sqlite
echo "ok rpmdb is bdb"
ostree --repo=${repo} show ${treeref} \ ostree --repo=${repo} show ${treeref} \
--print-metadata-key rpmostree.rpmdb.pkglist > pkglist.txt --print-metadata-key rpmostree.rpmdb.pkglist > pkglist.txt
assert_file_has_content pkglist.txt 'systemd' assert_file_has_content pkglist.txt 'systemd'