Skip to content

Commit

Permalink
Add support for --remove-installed-kernel
Browse files Browse the repository at this point in the history
Closes: #2542

Today anyone wanting to switch to a different kernel variant
such as `kernel-rt` must manually pass all the *current* kernel
packages to `--uninstall` (separately).  It's not just very unergonomic,
it also makes the calling code *operating system dependent* because
as just happened when C9S added a `kernel-modules-core` package,
that suddenly also needs to be specified.

xref https://issues.redhat.com/browse/OCPBUGS-8113
  • Loading branch information
cgwalters committed May 8, 2023
1 parent 32f62e4 commit 96dbbf4
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 0 deletions.
8 changes: 8 additions & 0 deletions ci/test-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ rpm -q ignition
dnf -y uninstall kexec-tools
if rpm -q kexec-tools; then fatal "failed to remove kexec-tools"; fi

rpm -q kernel
# Fedora doesn't ship kernel variants, so we just install some other package
rpm-ostree install --remove-installed-kernel strace
if rpm -qa |grep -E '^kernel'; then
fatal "Found installed kernel after --remove-installed-kernel"
fi
rpm -e strace

# test replacement by Koji URL
rpm-ostree override replace $koji_url |& tee out.txt
n_downloaded=$(grep Downloading out.txt | wc -l)
Expand Down
20 changes: 20 additions & 0 deletions rpmostree-cxxrs.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,8 @@ struct Treefile final : public ::rust::Opaque
bool remove_package_override_remove (::rust::Str package) noexcept;
bool has_packages_override_remove_name (::rust::Str name) const noexcept;
bool remove_all_overrides () noexcept;
bool has_remove_kernel () const noexcept;
bool set_remove_kernel (bool remove) noexcept;
::rust::Vec< ::rust::String> get_modules_enable () const noexcept;
bool has_modules_enable () const noexcept;
::rust::Vec< ::rust::String> get_modules_install () const noexcept;
Expand Down Expand Up @@ -2487,6 +2489,12 @@ extern "C"
bool
rpmostreecxx$cxxbridge1$Treefile$remove_all_overrides (::rpmostreecxx::Treefile &self) noexcept;

bool rpmostreecxx$cxxbridge1$Treefile$has_remove_kernel (
const ::rpmostreecxx::Treefile &self) noexcept;

bool rpmostreecxx$cxxbridge1$Treefile$set_remove_kernel (::rpmostreecxx::Treefile &self,
bool remove) noexcept;

void rpmostreecxx$cxxbridge1$Treefile$get_modules_enable (
const ::rpmostreecxx::Treefile &self, ::rust::Vec< ::rust::String> *return$) noexcept;

Expand Down Expand Up @@ -4902,6 +4910,18 @@ Treefile::remove_all_overrides () noexcept
return rpmostreecxx$cxxbridge1$Treefile$remove_all_overrides (*this);
}

bool
Treefile::has_remove_kernel () const noexcept
{
return rpmostreecxx$cxxbridge1$Treefile$has_remove_kernel (*this);
}

bool
Treefile::set_remove_kernel (bool remove) noexcept
{
return rpmostreecxx$cxxbridge1$Treefile$set_remove_kernel (*this, remove);
}

::rust::Vec< ::rust::String>
Treefile::get_modules_enable () const noexcept
{
Expand Down
2 changes: 2 additions & 0 deletions rpmostree-cxxrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1485,6 +1485,8 @@ struct Treefile final : public ::rust::Opaque
bool remove_package_override_remove (::rust::Str package) noexcept;
bool has_packages_override_remove_name (::rust::Str name) const noexcept;
bool remove_all_overrides () noexcept;
bool has_remove_kernel () const noexcept;
bool set_remove_kernel (bool remove) noexcept;
::rust::Vec< ::rust::String> get_modules_enable () const noexcept;
bool has_modules_enable () const noexcept;
::rust::Vec< ::rust::String> get_modules_install () const noexcept;
Expand Down
2 changes: 2 additions & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@ pub mod ffi {
fn remove_package_override_remove(&mut self, package: &str) -> bool;
fn has_packages_override_remove_name(&self, name: &str) -> bool;
fn remove_all_overrides(&mut self) -> bool;
fn has_remove_kernel(&self) -> bool;
fn set_remove_kernel(&mut self, remove: bool) -> bool;
fn get_modules_enable(&self) -> Vec<String>;
fn has_modules_enable(&self) -> bool;
fn get_modules_install(&self) -> Vec<String>;
Expand Down
39 changes: 39 additions & 0 deletions rust/src/treefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ fn treefile_merge(dest: &mut TreeComposeConfig, src: &mut TreeComposeConfig) {
&mut dest.derive.override_replace,
&mut src.derive.override_replace,
);
merge_basic_field(
&mut dest.derive.override_remove_kernel,
&mut src.derive.override_remove_kernel,
);
dest.handle_repo_packages_override_replacements();
merge_map_field(
&mut dest.derive.override_replace_local,
Expand Down Expand Up @@ -1040,6 +1044,15 @@ impl Treefile {
.unwrap_or_default()
}

/// Kernel removal is configured
pub(crate) fn has_remove_kernel(&self) -> bool {
self.parsed
.derive
.override_remove_kernel
.clone()
.unwrap_or_default()
}

// Check that the same overrides don't already exist. Of course, in the local replace
// case, this doesn't catch same pkg name but different EVRA; we'll just barf at that
// later on in the core. This is an early easy sanity check.
Expand Down Expand Up @@ -1135,6 +1148,21 @@ impl Treefile {
Some(old_map) != self.parsed.derive.override_replace
}

/// Change the state of kernel removal for derived images
pub(crate) fn set_remove_kernel(&mut self, remove: bool) -> bool {
let current = self
.parsed
.derive
.override_remove_kernel
.take()
.unwrap_or_default();
// Note we did .take() above, so this also canonicalizes false -> None
if remove {
self.parsed.derive.override_remove_kernel = Some(true);
}
current != remove
}

pub(crate) fn remove_package_override_replace(&mut self, package: &str) -> bool {
self.parsed
.derive
Expand Down Expand Up @@ -1196,6 +1224,7 @@ impl Treefile {
.map(|x| !x.is_empty())
.unwrap_or_default()
|| changed;
changed = self.set_remove_kernel(false) || changed;
changed
}

Expand Down Expand Up @@ -1621,6 +1650,7 @@ impl Treefile {
clone.override_replace.take();
clone.override_remove.take();
clone.override_replace_local.take();
clone.override_remove_kernel.take();
if clone != Default::default() {
let j = serde_json::to_string_pretty(&clone)?;
bail!(
Expand Down Expand Up @@ -1894,6 +1924,12 @@ impl Treefile {
.as_ref()
.and_then(|m| m.install.as_ref().map(|i| !i.is_empty()))
.unwrap_or_default()
|| self
.parsed
.derive
.override_remove_kernel
.clone()
.unwrap_or_default()
}

/// Derive RPM importer flags for a given package and treefile settings.
Expand Down Expand Up @@ -2714,6 +2750,9 @@ pub(crate) struct DeriveConfigFields {
pub(crate) packages_local_fileoverride: Option<BTreeMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) override_remove: Option<BTreeSet<String>>,
/// Remove the kernel
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) override_remove_kernel: Option<bool>,
#[serde(rename = "ex-override-replace")]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) override_replace: Option<Vec<RemoteOverrideReplace>>,
Expand Down
6 changes: 6 additions & 0 deletions src/app/rpmostree-pkg-builtins.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static gboolean opt_apply_live;
static gboolean opt_idempotent;
static gchar **opt_install;
static gboolean opt_assumeyes;
static gboolean opt_remove_kernel;
static gchar **opt_uninstall;
static gboolean opt_cache_only;
static gboolean opt_download_only;
Expand Down Expand Up @@ -90,6 +91,9 @@ static GOptionEntry install_option_entry[]
"Just download latest ostree and RPM data, don't deploy", NULL },
{ "apply-live", 'A', 0, G_OPTION_ARG_NONE, &opt_apply_live,
"Apply changes to both pending deployment and running filesystem tree", NULL },
{ "remove-installed-kernel", 0, 0, G_OPTION_ARG_NONE, &opt_remove_kernel,
"Remove the installed kernel packages (usually helpful to install a different kernel)",
NULL },
{ "force-replacefiles", 0, 0, G_OPTION_ARG_NONE, &opt_force_replacefiles,
"Allow package to replace files from other packages", NULL },
{ NULL } };
Expand Down Expand Up @@ -260,6 +264,8 @@ rpmostree_builtin_install (int argc, char **argv, RpmOstreeCommandInvocation *in
auto ver = rust::Str (*it);
treefile->set_releasever (ver);
}
if (opt_remove_kernel)
treefile->set_remove_kernel (true);
return rpmostree_container_rebuild (*treefile, cancellable, error);
}

Expand Down
29 changes: 29 additions & 0 deletions src/libpriv/rpmostree-core.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
#define RPMOSTREE_MESSAGE_PKG_IMPORT \
SD_ID128_MAKE (df, 8b, b5, 4f, 04, fa, 47, 08, ac, 16, 11, 1b, bf, 4b, a3, 52)

// This is a copy of the defaults from libdnf because it's not public API
// see INSTALLONLYPKGS there.
static const char *KERNEL_PACKAGES[] = { "kernel",
"kernel-PAE",
"installonlypkg(kernel)",
"installonlypkg(kernel-module)",
"installonlypkg(vm)",
"multiversion(kernel)" };

static OstreeRepo *get_pkgcache_repo (RpmOstreeContext *self);

static int
Expand Down Expand Up @@ -1734,6 +1743,7 @@ rpmostree_context_prepare (RpmOstreeContext *self, GCancellable *cancellable, GE
auto exclude_packages = self->treefile_rs->get_exclude_packages ();
auto modules_enable = self->treefile_rs->get_modules_enable ();
auto modules_install = self->treefile_rs->get_modules_install ();
auto remove_kernel = self->treefile_rs->has_remove_kernel ();

/* we only support pure installs for now (compose case) */
if (self->lockfile)
Expand Down Expand Up @@ -1945,6 +1955,25 @@ rpmostree_context_prepare (RpmOstreeContext *self, GCancellable *cancellable, GE
g_ptr_array_add (removed_pkgnames, (gpointer)pkgname);
}

if (remove_kernel)
{
for (guint i = 0; i < G_N_ELEMENTS (KERNEL_PACKAGES); i++)
{
const char *pkg = KERNEL_PACKAGES[i];
hy_autoquery HyQuery query = hy_query_create (sack);
hy_query_filter (query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
hy_query_filter (query, HY_PKG_PROVIDES, HY_EQ, pkg);
g_autoptr (GPtrArray) packages = hy_query_run (query);
for (guint i = 0; i < packages->len; i++)
{
auto pkg = static_cast<DnfPackage *> (g_ptr_array_index (packages, i));
g_printerr ("Removing kernel pkg: %s\n", dnf_package_get_name (pkg));
g_ptr_array_add (removed_pkgnames, (gpointer)dnf_package_get_name (pkg));
hy_goal_erase (goal, pkg);
}
}
}

/* Then, handle local packages to install */
GLNX_HASH_TABLE_FOREACH_V (local_pkgs_to_install, DnfPackage *, pkg)
hy_goal_install (goal, pkg);
Expand Down

0 comments on commit 96dbbf4

Please sign in to comment.