Skip to content

Commit 0162d7c

Browse files
committed
Add support for --remove-installed-kernel
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
1 parent 4ae616e commit 0162d7c

File tree

7 files changed

+106
-0
lines changed

7 files changed

+106
-0
lines changed

ci/test-container.sh

+8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ rpm -q ignition
107107
dnf -y uninstall kexec-tools
108108
if rpm -q kexec-tools; then fatal "failed to remove kexec-tools"; fi
109109

110+
rpm -q kernel
111+
# Fedora doesn't ship kernel variants, so we just install some other package
112+
rpm-ostree install --remove-installed-kernel strace
113+
if rpm -qa |grep -E '^kernel'; then
114+
fatal "Found installed kernel after --remove-installed-kernel"
115+
fi
116+
rpm -e strace
117+
110118
# test replacement by Koji URL
111119
rpm-ostree override replace $koji_url |& tee out.txt
112120
n_downloaded=$(grep Downloading out.txt | wc -l)

rpmostree-cxxrs.cxx

+20
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,8 @@ struct Treefile final : public ::rust::Opaque
17021702
bool remove_package_override_remove (::rust::Str package) noexcept;
17031703
bool has_packages_override_remove_name (::rust::Str name) const noexcept;
17041704
bool remove_all_overrides () noexcept;
1705+
bool has_remove_kernel () const noexcept;
1706+
bool set_remove_kernel (bool remove) noexcept;
17051707
::rust::Vec< ::rust::String> get_modules_enable () const noexcept;
17061708
bool has_modules_enable () const noexcept;
17071709
::rust::Vec< ::rust::String> get_modules_install () const noexcept;
@@ -2480,6 +2482,12 @@ extern "C"
24802482
bool
24812483
rpmostreecxx$cxxbridge1$Treefile$remove_all_overrides (::rpmostreecxx::Treefile &self) noexcept;
24822484

2485+
bool rpmostreecxx$cxxbridge1$Treefile$has_remove_kernel (
2486+
const ::rpmostreecxx::Treefile &self) noexcept;
2487+
2488+
bool rpmostreecxx$cxxbridge1$Treefile$set_remove_kernel (::rpmostreecxx::Treefile &self,
2489+
bool remove) noexcept;
2490+
24832491
void rpmostreecxx$cxxbridge1$Treefile$get_modules_enable (
24842492
const ::rpmostreecxx::Treefile &self, ::rust::Vec< ::rust::String> *return$) noexcept;
24852493

@@ -4877,6 +4885,18 @@ Treefile::remove_all_overrides () noexcept
48774885
return rpmostreecxx$cxxbridge1$Treefile$remove_all_overrides (*this);
48784886
}
48794887

4888+
bool
4889+
Treefile::has_remove_kernel () const noexcept
4890+
{
4891+
return rpmostreecxx$cxxbridge1$Treefile$has_remove_kernel (*this);
4892+
}
4893+
4894+
bool
4895+
Treefile::set_remove_kernel (bool remove) noexcept
4896+
{
4897+
return rpmostreecxx$cxxbridge1$Treefile$set_remove_kernel (*this, remove);
4898+
}
4899+
48804900
::rust::Vec< ::rust::String>
48814901
Treefile::get_modules_enable () const noexcept
48824902
{

rpmostree-cxxrs.h

+2
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,8 @@ struct Treefile final : public ::rust::Opaque
14841484
bool remove_package_override_remove (::rust::Str package) noexcept;
14851485
bool has_packages_override_remove_name (::rust::Str name) const noexcept;
14861486
bool remove_all_overrides () noexcept;
1487+
bool has_remove_kernel () const noexcept;
1488+
bool set_remove_kernel (bool remove) noexcept;
14871489
::rust::Vec< ::rust::String> get_modules_enable () const noexcept;
14881490
bool has_modules_enable () const noexcept;
14891491
::rust::Vec< ::rust::String> get_modules_install () const noexcept;

rust/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ pub mod ffi {
559559
fn remove_package_override_remove(&mut self, package: &str) -> bool;
560560
fn has_packages_override_remove_name(&self, name: &str) -> bool;
561561
fn remove_all_overrides(&mut self) -> bool;
562+
fn has_remove_kernel(&self) -> bool;
563+
fn set_remove_kernel(&mut self, remove: bool) -> bool;
562564
fn get_modules_enable(&self) -> Vec<String>;
563565
fn has_modules_enable(&self) -> bool;
564566
fn get_modules_install(&self) -> Vec<String>;

rust/src/treefile.rs

+39
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ fn treefile_merge(dest: &mut TreeComposeConfig, src: &mut TreeComposeConfig) {
486486
&mut dest.derive.override_replace,
487487
&mut src.derive.override_replace,
488488
);
489+
merge_basic_field(
490+
&mut dest.derive.override_remove_kernel,
491+
&mut src.derive.override_remove_kernel,
492+
);
489493
dest.handle_repo_packages_override_replacements();
490494
merge_map_field(
491495
&mut dest.derive.override_replace_local,
@@ -1024,6 +1028,15 @@ impl Treefile {
10241028
.unwrap_or_default()
10251029
}
10261030

1031+
/// Kernel removal is configured
1032+
pub(crate) fn has_remove_kernel(&self) -> bool {
1033+
self.parsed
1034+
.derive
1035+
.override_remove_kernel
1036+
.clone()
1037+
.unwrap_or_default()
1038+
}
1039+
10271040
// Check that the same overrides don't already exist. Of course, in the local replace
10281041
// case, this doesn't catch same pkg name but different EVRA; we'll just barf at that
10291042
// later on in the core. This is an early easy sanity check.
@@ -1119,6 +1132,21 @@ impl Treefile {
11191132
Some(old_map) != self.parsed.derive.override_replace
11201133
}
11211134

1135+
/// Change the state of kernel removal for derived images
1136+
pub(crate) fn set_remove_kernel(&mut self, remove: bool) -> bool {
1137+
let current = self
1138+
.parsed
1139+
.derive
1140+
.override_remove_kernel
1141+
.take()
1142+
.unwrap_or_default();
1143+
// Note we did .take() above, so this also canonicalizes false -> None
1144+
if remove {
1145+
self.parsed.derive.override_remove_kernel = Some(true);
1146+
}
1147+
current != remove
1148+
}
1149+
11221150
pub(crate) fn remove_package_override_replace(&mut self, package: &str) -> bool {
11231151
self.parsed
11241152
.derive
@@ -1180,6 +1208,7 @@ impl Treefile {
11801208
.map(|x| !x.is_empty())
11811209
.unwrap_or_default()
11821210
|| changed;
1211+
changed = self.set_remove_kernel(false) || changed;
11831212
changed
11841213
}
11851214

@@ -1600,6 +1629,7 @@ impl Treefile {
16001629
clone.override_replace.take();
16011630
clone.override_remove.take();
16021631
clone.override_replace_local.take();
1632+
clone.override_remove_kernel.take();
16031633
if clone != Default::default() {
16041634
let j = serde_json::to_string_pretty(&clone)?;
16051635
bail!(
@@ -1873,6 +1903,12 @@ impl Treefile {
18731903
.as_ref()
18741904
.and_then(|m| m.install.as_ref().map(|i| !i.is_empty()))
18751905
.unwrap_or_default()
1906+
|| self
1907+
.parsed
1908+
.derive
1909+
.override_remove_kernel
1910+
.clone()
1911+
.unwrap_or_default()
18761912
}
18771913

18781914
/// Derive RPM importer flags for a given package and treefile settings.
@@ -2693,6 +2729,9 @@ pub(crate) struct DeriveConfigFields {
26932729
pub(crate) packages_local_fileoverride: Option<BTreeMap<String, String>>,
26942730
#[serde(skip_serializing_if = "Option::is_none")]
26952731
pub(crate) override_remove: Option<BTreeSet<String>>,
2732+
/// Remove the kernel
2733+
#[serde(skip_serializing_if = "Option::is_none")]
2734+
pub(crate) override_remove_kernel: Option<bool>,
26962735
#[serde(rename = "ex-override-replace")]
26972736
#[serde(skip_serializing_if = "Option::is_none")]
26982737
pub(crate) override_replace: Option<Vec<RemoteOverrideReplace>>,

src/app/rpmostree-pkg-builtins.cxx

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static gboolean opt_apply_live;
3838
static gboolean opt_idempotent;
3939
static gchar **opt_install;
4040
static gboolean opt_assumeyes;
41+
static gboolean opt_remove_kernel;
4142
static gchar **opt_uninstall;
4243
static gboolean opt_cache_only;
4344
static gboolean opt_download_only;
@@ -81,6 +82,9 @@ static GOptionEntry install_option_entry[]
8182
"Just download latest ostree and RPM data, don't deploy", NULL },
8283
{ "apply-live", 'A', 0, G_OPTION_ARG_NONE, &opt_apply_live,
8384
"Apply changes to both pending deployment and running filesystem tree", NULL },
85+
{ "remove-installed-kernel", 0, 0, G_OPTION_ARG_NONE, &opt_remove_kernel,
86+
"Remove the installed kernel packages (usually helpful to install a different kernel)",
87+
NULL },
8488
{ "force-replacefiles", 0, 0, G_OPTION_ARG_NONE, &opt_force_replacefiles,
8589
"Allow package to replace files from other packages", NULL },
8690
{ NULL } };
@@ -236,6 +240,8 @@ rpmostree_builtin_install (int argc, char **argv, RpmOstreeCommandInvocation *in
236240
CXX_TRY (treefile->add_packages (v, true), error);
237241
}
238242
}
243+
if (opt_remove_kernel)
244+
treefile->set_remove_kernel (true);
239245
return rpmostree_container_rebuild (*treefile, cancellable, error);
240246
}
241247

src/libpriv/rpmostree-core.cxx

+29
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@
5454
#define RPMOSTREE_MESSAGE_PKG_IMPORT \
5555
SD_ID128_MAKE (df, 8b, b5, 4f, 04, fa, 47, 08, ac, 16, 11, 1b, bf, 4b, a3, 52)
5656

57+
// This is a copy of the defaults from libdnf because it's not public API
58+
// see INSTALLONLYPKGS there.
59+
static const char *KERNEL_PACKAGES[] = { "kernel",
60+
"kernel-PAE",
61+
"installonlypkg(kernel)",
62+
"installonlypkg(kernel-module)",
63+
"installonlypkg(vm)",
64+
"multiversion(kernel)" };
65+
5766
static OstreeRepo *get_pkgcache_repo (RpmOstreeContext *self);
5867

5968
static int
@@ -1734,6 +1743,7 @@ rpmostree_context_prepare (RpmOstreeContext *self, GCancellable *cancellable, GE
17341743
auto exclude_packages = self->treefile_rs->get_exclude_packages ();
17351744
auto modules_enable = self->treefile_rs->get_modules_enable ();
17361745
auto modules_install = self->treefile_rs->get_modules_install ();
1746+
auto remove_kernel = self->treefile_rs->has_remove_kernel ();
17371747

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

1958+
if (remove_kernel)
1959+
{
1960+
for (guint i = 0; i < G_N_ELEMENTS (KERNEL_PACKAGES); i++)
1961+
{
1962+
const char *pkg = KERNEL_PACKAGES[i];
1963+
hy_autoquery HyQuery query = hy_query_create (sack);
1964+
hy_query_filter (query, HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME);
1965+
hy_query_filter (query, HY_PKG_PROVIDES, HY_EQ, pkg);
1966+
g_autoptr (GPtrArray) packages = hy_query_run (query);
1967+
for (guint i = 0; i < packages->len; i++)
1968+
{
1969+
auto pkg = static_cast<DnfPackage *> (g_ptr_array_index (packages, i));
1970+
g_printerr ("Removing kernel pkg: %s\n", dnf_package_get_name (pkg));
1971+
g_ptr_array_add (removed_pkgnames, (gpointer)dnf_package_get_name (pkg));
1972+
hy_goal_erase (goal, pkg);
1973+
}
1974+
}
1975+
}
1976+
19481977
/* Then, handle local packages to install */
19491978
GLNX_HASH_TABLE_FOREACH_V (local_pkgs_to_install, DnfPackage *, pkg)
19501979
hy_goal_install (goal, pkg);

0 commit comments

Comments
 (0)