Skip to content

Commit

Permalink
Add new ex initramfs-etc command
Browse files Browse the repository at this point in the history
This command allows users to cheaply inject configuration files in the
initramfs stage without having to regenerate the whole initramfs (or
even a new OSTree commit). This will be useful for configuring services
involved in bringing up the root block device.

```
$ echo 'hello world' > /etc/foobar
$ rpm-ostree ex initramfs-etc --track /etc/foobar
Staging deployment... done
Run "systemctl reboot" to start a reboot
$ rpm-ostree status
State: idle
Deployments:
  ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
              InitramfsEtc: /etc/foobar
                  Unlocked: development

● ostree://fedora:fedora/x86_64/coreos/testing-devel
                   Version: 32.20200716.dev.1 (2020-07-16T02:47:29Z)
                    Commit: 9a817d75bef81b955179be6e602d1e6ae350645b6323231a62ba2ee6e5b9644b
              GPGSignature: (unsigned)
$ reboot
(boot into rd.break)
sh-5.0# cat /etc/foobar
hello world
```

See the libostree side of this at:
ostreedev/ostree#2155

Lots more discussions in:
coreos/fedora-coreos-tracker#94
  • Loading branch information
jlebon committed Aug 13, 2020
1 parent 5975a59 commit de26f73
Show file tree
Hide file tree
Showing 17 changed files with 703 additions and 16 deletions.
1 change: 1 addition & 0 deletions Makefile-rpm-ostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ rpm_ostree_SOURCES = src/app/main.c \
src/app/rpmostree-builtin-cliwrap.c \
src/app/rpmostree-builtin-cleanup.c \
src/app/rpmostree-builtin-initramfs.c \
src/app/rpmostree-builtin-initramfs-etc.c \
src/app/rpmostree-builtin-livefs.c \
src/app/rpmostree-builtin-usroverlay.c \
src/app/rpmostree-builtin-override.c \
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ LIBS="$save_LIBS"
# Remember to update AM_CPPFLAGS in Makefile.am when bumping GIO req.
PKG_CHECK_MODULES(PKGDEP_GIO_UNIX, [gio-unix-2.0])
PKG_CHECK_MODULES(PKGDEP_RPMOSTREE, [gio-unix-2.0 >= 2.50.0 json-glib-1.0
ostree-1 >= 2020.1
ostree-1 >= 2020.5
libsystemd
polkit-gobject-1
rpm librepo libsolv
Expand Down
30 changes: 30 additions & 0 deletions man/rpm-ostree.xml
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,36 @@ Boston, MA 02111-1307, USA.
</listitem>
</varlistentry>

<varlistentry>
<term><command>ex initramfs-etc</command></term>

<listitem>
<para>
Experimental feature; subject to change.
</para>

<para>
Track/untrack additional files for the initramfs. This avoids a full
regeneration of the initramfs, but is limited to configuration files. This is
useful to be able to configure services backing the root block device in
a lightweight manner.
</para>

<para>
Use <command>--track</command> to start tracking a specific file. Can be
specified multiple times. A new deployment will be generated. Use
<command>--untrack</command> or <command>--untrack-all</command> to stop
tracking files.
</para>

<para>
When there are tracked files, any future created deployment (e.g. when doing an
upgrade) will ensure that they are synced. You can additionally use
<command>--force-sync</command> to simply generate a new deployment with the
latest versions of tracked files without upgrading.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

Expand Down
2 changes: 1 addition & 1 deletion packaging/rpm-ostree.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ BuildRequires: gnome-common
BuildRequires: /usr/bin/g-ir-scanner
# Core requirements
# One way to check this: `objdump -p /path/to/rpm-ostree | grep LIBOSTREE` and pick the highest (though that might miss e.g. new struct members)
BuildRequires: pkgconfig(ostree-1) >= 2019.2
BuildRequires: pkgconfig(ostree-1) >= 2020.5
BuildRequires: pkgconfig(polkit-gobject-1)
BuildRequires: pkgconfig(json-glib-1.0)
BuildRequires: pkgconfig(rpm)
Expand Down
2 changes: 2 additions & 0 deletions src/app/rpmostree-builtin-ex.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static RpmOstreeCommand ex_subcommands[] = {
"Convert an rpm-ostree rojig into an OSTree commit", rpmostree_ex_builtin_rojig2commit },
{ "history", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD,
"Inspect rpm-ostree history of the system", rpmostree_ex_builtin_history },
{ "initramfs-etc", RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
"Track/untrack initramfs configuration files", rpmostree_ex_builtin_initramfs_etc },
{ NULL, 0, NULL, NULL }
};

Expand Down
136 changes: 136 additions & 0 deletions src/app/rpmostree-builtin-initramfs-etc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2020 Jonathan Lebon <jonathan@jlebon.com>
*
* 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 <string.h>
#include <glib-unix.h>

#include "rpmostree-ex-builtins.h"
#include "rpmostree-libbuiltin.h"
#include "rpmostree-dbus-helpers.h"

#include <libglnx.h>

static char *opt_osname;
static gboolean opt_force_sync;
static char **opt_track;
static char **opt_untrack;
static gboolean opt_untrack_all;
static gboolean opt_reboot;
static gboolean opt_lock_finalization;
static gboolean opt_unchanged_exit_77;

static GOptionEntry option_entries[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" },
{ "force-sync", 0, 0, G_OPTION_ARG_NONE, &opt_force_sync, "Deploy a new tree with the latest tracked /etc files", NULL },
{ "track", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_track, "Track root /etc file", "FILE" },
{ "untrack", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_untrack, "Untrack root /etc file", "FILE" },
{ "untrack-all", 0, 0, G_OPTION_ARG_NONE, &opt_untrack_all, "Untrack all root /etc files", NULL },
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Initiate a reboot after operation is complete", NULL },
{ "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL },
{ "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no new deployment made, exit 77", NULL },

{ NULL }
};

gboolean
rpmostree_ex_builtin_initramfs_etc (int argc,
char **argv,
RpmOstreeCommandInvocation *invocation,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = g_option_context_new ("");

_cleanup_peer_ GPid peer_pid = 0;
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
if (!rpmostree_option_context_parse (context,
option_entries,
&argc, &argv,
invocation,
cancellable,
NULL, NULL,
&sysroot_proxy,
&peer_pid,
NULL,
error))
return FALSE;

glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname,
cancellable, &os_proxy, error))
return FALSE;

g_autoptr(GVariant) previous_deployment = rpmostree_os_dup_default_deployment (os_proxy);

if (!(opt_track || opt_untrack || opt_untrack_all || opt_force_sync))
{
/* XXX: could print state here like `rpm-ostree initramfs` */
return glnx_throw (error, "Must use at least one of --force-sync, --track, --untrack, or --untrack-all");
}
else
{
char *empty_strv[] = {NULL};
if (!opt_track)
opt_track = empty_strv;
if (!opt_untrack)
opt_untrack = empty_strv;

GVariantDict dict;
g_variant_dict_init (&dict, NULL);
g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
g_variant_dict_insert (&dict, "initiating-command-line", "s", invocation->command_line);
g_variant_dict_insert (&dict, "lock-finalization", "b", opt_lock_finalization);
g_autoptr(GVariant) options = g_variant_ref_sink (g_variant_dict_end (&dict));

g_autofree char *transaction_address = NULL;
if (!rpmostree_os_call_initramfs_etc_sync (os_proxy,
(const char *const*)opt_track,
(const char *const*)opt_untrack,
opt_untrack_all,
opt_force_sync,
options,
&transaction_address,
cancellable,
error))
return FALSE;

if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
transaction_address,
cancellable,
error))
return FALSE;

if (!opt_reboot)
{
if (!rpmostree_has_new_default_deployment (os_proxy, previous_deployment))
{
if (opt_unchanged_exit_77)
invocation->exit_code = RPM_OSTREE_EXIT_UNCHANGED;
return TRUE;
}

g_print ("Run \"systemctl reboot\" to start a reboot\n");
}
}

return TRUE;
}
7 changes: 7 additions & 0 deletions src/app/rpmostree-builtin-status.c
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,13 @@ print_one_deployment (RPMOSTreeSysroot *sysroot_proxy,
g_string_append (buf, "regenerate");
rpmostree_print_kv ("Initramfs", max_key_len, buf->str);
}

g_autofree char **initramfs_etc_files = NULL;
g_variant_dict_lookup (dict, "initramfs-etc", "^a&s", &initramfs_etc_files);
if (initramfs_etc_files && *initramfs_etc_files)
/* XXX: not really packages but it works... should just rename that function */
print_packages ("InitramfsEtc", max_key_len, (const char**)initramfs_etc_files, NULL);

gboolean pinned = FALSE;
g_variant_dict_lookup (dict, "pinned", "b", &pinned);
if (pinned)
Expand Down
1 change: 1 addition & 0 deletions src/app/rpmostree-ex-builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ BUILTINPROTO(livefs);
BUILTINPROTO(commit2rojig);
BUILTINPROTO(rojig2commit);
BUILTINPROTO(history);
BUILTINPROTO(initramfs_etc);

#undef BUILTINPROTO

Expand Down
9 changes: 9 additions & 0 deletions src/daemon/org.projectatomic.rpmostree1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,15 @@
<arg type="s" name="transaction_address" direction="out"/>
</method>

<method name="InitramfsEtc">
<arg type="as" name="track" direction="in"/>
<arg type="as" name="untrack" direction="in"/>
<arg type="b" name="untrack_all" direction="in"/>
<arg type="b" name="force_sync" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="s" name="transaction_address" direction="out"/>
</method>

<!-- Available options:
"reboot" (type 'b')
-->
Expand Down
2 changes: 2 additions & 0 deletions src/daemon/rpmostree-sysroot-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
* /run/ostree/staged-deployment path and company. */
#define _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED "/run/ostree/staged-deployment-locked"

#define RPMOSTREE_INITRAMFS_ETC_OVERLAY "/run/rpm-ostree/initramfs-etc-overlay.img"

gboolean
rpmostree_syscore_cleanup (OstreeSysroot *sysroot,
OstreeRepo *repo,
Expand Down
Loading

0 comments on commit de26f73

Please sign in to comment.