From 012aa022b79dc91684c64fff0342fd1daba9215b Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 20 Jan 2022 12:13:24 -0500 Subject: [PATCH] Add `rpm-ostree ex rebuild` command This command reads treefile dropins in `/etc` and applies it to the system. Only the OSTree container flow is supported for now. For the client-side flow, see #2326. In the container flow, only `packages` is currently supported. But this paves the way for supporting more derivation fields as well as making currently "base" fields only become valid derivation fields too (by promoting it from the `BaseComposeConfigFields` struct to `TreeComposeConfig`). What we're doing here is providing a "container" backend for derivation treefiles, but #2326 will provide a "client" backend which uses the core more fully. But the inputs themselves are the exact same, hence providing symmetry between the two flows. (See also discussions about this in https://github.com/coreos/fedora-coreos-tracker/issues/1054). This will also allow us to drop the `microdnf` dependency which will be done in a following patch. --- Makefile-libpriv.am | 2 + Makefile-rpm-ostree.am | 1 + rust/src/lib.rs | 1 + rust/src/treefile.rs | 9 +++ src/app/rpmostree-builtin-ex.cxx | 4 ++ src/app/rpmostree-builtin-rebuild.cxx | 83 +++++++++++++++++++++++++++ src/app/rpmostree-ex-builtins.h | 1 + src/libpriv/rpmostree-container.cxx | 62 ++++++++++++++++++++ src/libpriv/rpmostree-container.h | 30 ++++++++++ 9 files changed, 193 insertions(+) create mode 100644 src/app/rpmostree-builtin-rebuild.cxx create mode 100644 src/libpriv/rpmostree-container.cxx create mode 100644 src/libpriv/rpmostree-container.h diff --git a/Makefile-libpriv.am b/Makefile-libpriv.am index dc52afdb72..364d5f6c91 100644 --- a/Makefile-libpriv.am +++ b/Makefile-libpriv.am @@ -25,6 +25,8 @@ librpmostreepriv_sources = \ src/libpriv/rpmostree-types.h \ src/libpriv/rpmostree-refts.h \ src/libpriv/rpmostree-refts.cxx \ + src/libpriv/rpmostree-container.cxx \ + src/libpriv/rpmostree-container.h \ src/libpriv/rpmostree-core.cxx \ src/libpriv/rpmostree-core.h \ src/libpriv/rpmostree-core-private.h \ diff --git a/Makefile-rpm-ostree.am b/Makefile-rpm-ostree.am index 170d6b38a0..84aa85531b 100644 --- a/Makefile-rpm-ostree.am +++ b/Makefile-rpm-ostree.am @@ -59,6 +59,7 @@ librpmostreeinternals_la_SOURCES = \ src/app/rpmostree-composeutil.cxx \ src/app/rpmostree-composeutil.h \ src/app/rpmostree-builtin-compose.cxx \ + src/app/rpmostree-builtin-rebuild.cxx \ $(librpmostreed_sources) \ $(librpmostreepriv_sources) \ $(librpmostree_1_la_SOURCES) \ diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 4ee4c8cf12..0a9a7e2de8 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -393,6 +393,7 @@ pub mod ffi { ) -> Result>; fn treefile_new_client(filename: &str, basearch: &str) -> Result>; fn treefile_new_client_from_etc(basearch: &str) -> Result>; + fn treefile_delete_client_etc() -> Result<()>; fn get_workdir(&self) -> i32; fn get_passwd_fd(&mut self) -> i32; diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index 72a49acf75..4851be9a3b 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -2289,3 +2289,12 @@ pub(crate) fn treefile_new_client_from_etc(basearch: &str) -> CxxResult CxxResult<()> { + // To be nice we don't delete the directory itself; just matching files. + for entry in glob(CLIENT_TREEFILES_GLOB).map_err(anyhow::Error::msg)? { + let cfg = entry.map_err(anyhow::Error::msg)?; + std::fs::remove_file(&cfg)?; + } + Ok(()) +} diff --git a/src/app/rpmostree-builtin-ex.cxx b/src/app/rpmostree-builtin-ex.cxx index d6e70127dc..6e810f87dc 100644 --- a/src/app/rpmostree-builtin-ex.cxx +++ b/src/app/rpmostree-builtin-ex.cxx @@ -33,6 +33,10 @@ static RpmOstreeCommand ex_subcommands[] = { "Inspect rpm-ostree history of the system", rpmostree_ex_builtin_history }, { "initramfs-etc", (RpmOstreeBuiltinFlags)0, "Track initramfs configuration files", rpmostree_ex_builtin_initramfs_etc }, + /* This is currently only for CoreOS layering; so hide it to not confuse + * users. */ + { "rebuild", (RpmOstreeBuiltinFlags)(RPM_OSTREE_BUILTIN_FLAG_HIDDEN), + "Rebuild system based on configuration", rpmostree_ex_builtin_rebuild }, /* To graduate out of experimental, simply revert: * https://github.com/coreos/rpm-ostree/pull/3078 */ { "module", static_cast(0), diff --git a/src/app/rpmostree-builtin-rebuild.cxx b/src/app/rpmostree-builtin-rebuild.cxx new file mode 100644 index 0000000000..53cd127528 --- /dev/null +++ b/src/app/rpmostree-builtin-rebuild.cxx @@ -0,0 +1,83 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include + +#include "rpmostree-ex-builtins.h" +#include "rpmostree-libbuiltin.h" +#include "rpmostree-clientlib.h" +#include "rpmostree-container.h" + +#include + +gboolean +rpmostree_ex_builtin_rebuild (int argc, + char **argv, + RpmOstreeCommandInvocation *invocation, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GOptionContext) context = g_option_context_new (""); + + if (!rpmostree_option_context_parse (context, + NULL, + &argc, &argv, + invocation, + cancellable, + NULL, NULL, NULL, + error)) + return FALSE; + + bool in_container = false; + if (rpmostreecxx::running_in_container()) + { + auto is_ostree_container = CXX_TRY_VAL(is_ostree_container(), error); + if (!is_ostree_container) + return glnx_throw (error, "This command can only run in an OSTree container."); + in_container = true; + } + + auto basearch = rpmostreecxx::get_rpm_basearch(); + auto treefile = CXX_TRY_VAL(treefile_new_client_from_etc (basearch), error); + + /* This is the big switch: we support running this command in two modes: + * "client containers", where the effect takes place in the active rootfs, and + * possibly eventually "client host systems", where the effect takes place in + * a new deployment. */ + if (in_container) + { + if (!rpmostree_container_rebuild (*treefile, cancellable, error)) + return FALSE; + + /* In the container flow, we effectively "consume" the treefiles after + * modifying the rootfs. */ + CXX_TRY(treefile_delete_client_etc (), error); + } + else + { + return glnx_throw (error, "This command is not yet supported on host systems. " + "See https://github.com/coreos/rpm-ostree/issues/2326."); + } + + return TRUE; +} diff --git a/src/app/rpmostree-ex-builtins.h b/src/app/rpmostree-ex-builtins.h index 27ac685897..70c321f8ef 100644 --- a/src/app/rpmostree-ex-builtins.h +++ b/src/app/rpmostree-ex-builtins.h @@ -35,6 +35,7 @@ BUILTINPROTO(apply_live); BUILTINPROTO(history); BUILTINPROTO(initramfs_etc); BUILTINPROTO(module); +BUILTINPROTO(rebuild); #undef BUILTINPROTO diff --git a/src/libpriv/rpmostree-container.cxx b/src/libpriv/rpmostree-container.cxx new file mode 100644 index 0000000000..0aa5e16ad0 --- /dev/null +++ b/src/libpriv/rpmostree-container.cxx @@ -0,0 +1,62 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include + +#include "rpmostree-core.h" +#include "rpmostree-container.h" + +#include + +gboolean +rpmostree_container_rebuild (rpmostreecxx::Treefile &treefile, + GCancellable *cancellable, + GError **error) +{ + auto packages = treefile.get_packages(); + + /* for now, we only support package installs */ + if (packages.empty()) + return TRUE; + + g_autoptr(RpmOstreeContext) ctx = rpmostree_context_new_container (); + rpmostree_context_set_treefile (ctx, treefile); + + if (!rpmostree_context_setup (ctx, "/", "/", cancellable, error)) + return FALSE; + + if (!rpmostree_context_prepare (ctx, cancellable, error)) + return FALSE; + + if (!rpmostree_context_download (ctx, cancellable, error)) + return FALSE; + + DnfContext *dnfctx = rpmostree_context_get_dnf (ctx); + + /* can't use cancellable here because it wants to re-set it on the state, + * which will trigger an assertion; XXX: tweak libdnf */ + if (!dnf_context_run (dnfctx, NULL, error)) + return FALSE; + + return TRUE; +} diff --git a/src/libpriv/rpmostree-container.h b/src/libpriv/rpmostree-container.h new file mode 100644 index 0000000000..349a027e5f --- /dev/null +++ b/src/libpriv/rpmostree-container.h @@ -0,0 +1,30 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +G_BEGIN_DECLS + +gboolean +rpmostree_container_rebuild (rpmostreecxx::Treefile &treefile, + GCancellable *cancellable, + GError **error); + +G_END_DECLS