Support "system/regenerate-initramfs=true" flag in origin
Currently we push for a model where the initramfs is generated (in non-hostonly mode), and merely replicated. However, to support a few unfortunate corner cases like dm-multipath which wants to inject a config file into the initramfs, we need to support regenerating it client side too. Down the line, we'll need this to support overriding the kernel too. This changes things in the core to add the concept of an "empty" `RpmOstreeContext`. I initially tried skipping it, but that was too much duplication. We still want all of the core ostree-related logic that lives in that code too. The treespec bits barfed if the spec didn't have a `tree/packages` key. It was simplest to change that to allow it - and because that was the only case where we errored out in parsing, I dropped the error handling. There was another place in the upgrader that now needed to be fixed to handle transitioning from just regenerating initramfs to not. Closes: #574 Approved by: jlebon
This commit is contained in:
parent
b099680d1d
commit
cac4522e5b
@ -77,6 +77,8 @@ artifacts:
|
||||
- vmcheck.log
|
||||
- vmcheck-journal.txt
|
||||
|
||||
timeout: 1h
|
||||
|
||||
---
|
||||
|
||||
context: compose
|
||||
|
@ -27,6 +27,7 @@ rpm_ostree_SOURCES = src/app/main.c \
|
||||
src/app/rpmostree-builtin-rollback.c \
|
||||
src/app/rpmostree-builtin-deploy.c \
|
||||
src/app/rpmostree-builtin-rebase.c \
|
||||
src/app/rpmostree-builtin-initramfs.c \
|
||||
src/app/rpmostree-pkg-builtins.c \
|
||||
src/app/rpmostree-builtin-status.c \
|
||||
src/app/rpmostree-builtin-internals.c \
|
||||
|
@ -334,6 +334,38 @@ Boston, MA 02111-1307, USA.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>initramfs</command></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
By default, the primary use case mode for rpm-ostree is to replicate
|
||||
an initramfs as part of a base layer. However, some use cases
|
||||
require locally regenerating it to add configuration or drivers. Use
|
||||
<command>rpm-ostree initramfs</command> to inspect the current
|
||||
status.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Use <command>--enable</command> to turn on client side initramfs
|
||||
regeneration. A new deployment will be generated, and after reboot,
|
||||
further upgrades will continue regenerating. You must reboot for the
|
||||
new initramfs to take effect.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To append additional custom arguments to the initramfs program
|
||||
(currently dracut), use <command>--arg</command>. For example,
|
||||
<command>--arg=-I --arg=/etc/someconfigfile</command>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <command>--disable</command> option will disable
|
||||
regeneration. You must reboot for the change to take effect.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -43,6 +43,7 @@ static RpmOstreeCommand supported_commands[] = {
|
||||
{ "rollback", rpmostree_builtin_rollback },
|
||||
{ "status", rpmostree_builtin_status },
|
||||
{ "upgrade", rpmostree_builtin_upgrade },
|
||||
{ "initramfs", rpmostree_builtin_initramfs },
|
||||
{ "install", rpmostree_builtin_pkg_add },
|
||||
{ "uninstall", rpmostree_builtin_pkg_remove },
|
||||
{ NULL }
|
||||
|
172
src/app/rpmostree-builtin-initramfs.c
Normal file
172
src/app/rpmostree-builtin-initramfs.c
Normal file
@ -0,0 +1,172 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2017 Colin Walters <walters@verbum.org>
|
||||
*
|
||||
* 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-builtins.h"
|
||||
#include "rpmostree-libbuiltin.h"
|
||||
#include "rpmostree-dbus-helpers.h"
|
||||
|
||||
#include <libglnx.h>
|
||||
|
||||
static gboolean opt_enable;
|
||||
static gboolean opt_disable;
|
||||
static char **opt_add_arg;
|
||||
static gboolean opt_reboot;
|
||||
|
||||
static GOptionEntry option_entries[] = {
|
||||
{ "enable", 0, 0, G_OPTION_ARG_NONE, &opt_enable, "Enable regenerating initramfs locally", NULL },
|
||||
{ "arg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_add_arg, "Append ARG to the dracut arguments", "ARG" },
|
||||
{ "disable", 0, 0, G_OPTION_ARG_NONE, &opt_disable, "Disable regenerating initramfs locally", NULL },
|
||||
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Initiate a reboot after operation is complete", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static GVariant *
|
||||
get_args_variant (void)
|
||||
{
|
||||
GVariantDict dict;
|
||||
|
||||
g_variant_dict_init (&dict, NULL);
|
||||
g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
|
||||
|
||||
return g_variant_dict_end (&dict);
|
||||
}
|
||||
|
||||
int
|
||||
rpmostree_builtin_initramfs (int argc,
|
||||
char **argv,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
int exit_status = EXIT_FAILURE;
|
||||
g_autoptr(GOptionContext) context = g_option_context_new ("- Enable or disable local initramfs regeneration");
|
||||
glnx_unref_object RPMOSTreeOS *os_proxy = NULL;
|
||||
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
|
||||
g_autofree char *transaction_address = NULL;
|
||||
|
||||
if (!rpmostree_option_context_parse (context,
|
||||
option_entries,
|
||||
&argc, &argv,
|
||||
RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT,
|
||||
cancellable,
|
||||
&sysroot_proxy,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_load_os_proxy (sysroot_proxy, NULL,
|
||||
cancellable, &os_proxy, error))
|
||||
goto out;
|
||||
|
||||
if (!(opt_enable || opt_disable))
|
||||
{
|
||||
GVariantIter iter;
|
||||
g_autoptr(GVariant) deployments = rpmostree_sysroot_dup_deployments (sysroot_proxy);
|
||||
|
||||
if (opt_reboot)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"--reboot must be used with --enable or --disable");
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_variant_iter_init (&iter, deployments);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
gboolean cur_regenerate;
|
||||
g_autoptr(GVariant) child = g_variant_iter_next_value (&iter);
|
||||
g_autoptr(GVariantDict) dict = NULL;
|
||||
g_autofree char **initramfs_args = NULL;
|
||||
gboolean is_booted;
|
||||
|
||||
if (child == NULL)
|
||||
break;
|
||||
|
||||
dict = g_variant_dict_new (child);
|
||||
|
||||
if (!g_variant_dict_lookup (dict, "booted", "b", &is_booted))
|
||||
continue;
|
||||
if (!is_booted)
|
||||
continue;
|
||||
|
||||
if (!g_variant_dict_lookup (dict, "regenerate-initramfs", "b", &cur_regenerate))
|
||||
cur_regenerate = FALSE;
|
||||
if (cur_regenerate)
|
||||
{
|
||||
g_variant_dict_lookup (dict, "initramfs-args", "^a&s", &initramfs_args);
|
||||
}
|
||||
|
||||
g_print ("Initramfs regeneration: %s\n", cur_regenerate ? "enabled" : "disabled");
|
||||
if (initramfs_args)
|
||||
{
|
||||
g_print ("Initramfs args: ");
|
||||
for (char **iter = initramfs_args; iter && *iter; iter++)
|
||||
g_print ("%s ", *iter);
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (opt_enable && opt_disable)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Cannot simultaenously specify --enable and --disable");
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *empty_strv[] = {NULL};
|
||||
if (opt_disable && opt_add_arg)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Cannot simultaenously specify --disable and --arg");
|
||||
goto out;
|
||||
}
|
||||
if (!opt_add_arg)
|
||||
opt_add_arg = empty_strv;
|
||||
if (!rpmostree_os_call_set_initramfs_state_sync (os_proxy,
|
||||
opt_enable,
|
||||
(const char *const*)opt_add_arg,
|
||||
get_args_variant (),
|
||||
&transaction_address,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_transaction_get_response_sync (sysroot_proxy,
|
||||
transaction_address,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
g_print ("Initramfs regeneration is now: %s\n", opt_enable ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
exit_status = EXIT_SUCCESS;
|
||||
|
||||
out:
|
||||
/* Does nothing if using the message bus. */
|
||||
rpmostree_cleanup_peer ();
|
||||
|
||||
return exit_status;
|
||||
}
|
@ -119,6 +119,7 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
|
||||
const gchar *version_string;
|
||||
const gchar *unlocked;
|
||||
gboolean gpg_enabled;
|
||||
gboolean regenerate_initramfs;
|
||||
guint64 t = 0;
|
||||
int serial;
|
||||
gboolean is_booted;
|
||||
@ -165,6 +166,9 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
|
||||
if (!g_variant_dict_lookup (dict, "unlocked", "&s", &unlocked))
|
||||
unlocked = NULL;
|
||||
|
||||
if (!g_variant_dict_lookup (dict, "regenerate-initramfs", "b", ®enerate_initramfs))
|
||||
regenerate_initramfs = FALSE;
|
||||
|
||||
signatures = g_variant_dict_lookup_value (dict, "signatures",
|
||||
G_VARIANT_TYPE ("av"));
|
||||
|
||||
@ -194,7 +198,7 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
|
||||
{
|
||||
print_kv ("Timestamp", max_key_len, timestamp_string);
|
||||
}
|
||||
if (origin_packages)
|
||||
if (origin_packages || regenerate_initramfs)
|
||||
{
|
||||
const char *base_checksum;
|
||||
g_assert (g_variant_dict_lookup (dict, "base-checksum", "&s", &base_checksum));
|
||||
@ -238,7 +242,24 @@ status_generic (RPMOSTreeSysroot *sysroot_proxy,
|
||||
packages_joined = g_strjoinv (" ", (char**)origin_packages_sorted->pdata);
|
||||
print_kv ("Packages", max_key_len, packages_joined);
|
||||
}
|
||||
|
||||
|
||||
if (regenerate_initramfs)
|
||||
{
|
||||
g_autoptr(GString) buf = g_string_new ("");
|
||||
g_autofree char **initramfs_args = NULL;
|
||||
|
||||
g_variant_dict_lookup (dict, "initramfs-args", "^a&s", &initramfs_args);
|
||||
|
||||
for (char **iter = initramfs_args; iter && *iter; iter++)
|
||||
{
|
||||
g_string_append (buf, *iter);
|
||||
g_string_append_c (buf, ' ');
|
||||
}
|
||||
if (buf->len == 0)
|
||||
g_string_append (buf, "regenerate");
|
||||
print_kv ("Initramfs", max_key_len, buf->str);
|
||||
}
|
||||
|
||||
if (unlocked && g_strcmp0 (unlocked, "none") != 0)
|
||||
{
|
||||
g_print ("%s%s", red_prefix, bold_prefix);
|
||||
|
@ -47,6 +47,7 @@ BUILTINPROTO(upgrade);
|
||||
BUILTINPROTO(deploy);
|
||||
BUILTINPROTO(rebase);
|
||||
BUILTINPROTO(rollback);
|
||||
BUILTINPROTO(initramfs);
|
||||
BUILTINPROTO(status);
|
||||
BUILTINPROTO(db);
|
||||
BUILTINPROTO(internals);
|
||||
|
@ -181,6 +181,13 @@
|
||||
<arg type="s" name="transaction_address" direction="out"/>
|
||||
</method>
|
||||
|
||||
<method name="SetInitramfsState">
|
||||
<arg type="b" name="regenerate" direction="in"/>
|
||||
<arg type="as" name="args" direction="in"/>
|
||||
<arg type="a{sv}" name="options" direction="in"/>
|
||||
<arg type="s" name="transaction_address" direction="out"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="org.projectatomic.rpmostree1.Transaction">
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "rpmostree-sysroot-upgrader.h"
|
||||
#include "rpmostree-core.h"
|
||||
#include "rpmostree-origin.h"
|
||||
#include "rpmostree-kernel.h"
|
||||
#include "rpmostree-rpm-util.h"
|
||||
#include "rpmostree-postprocess.h"
|
||||
#include "rpmostree-output.h"
|
||||
@ -93,12 +94,12 @@ parse_origin_keyfile (RpmOstreeSysrootUpgrader *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
RpmOstreeOriginFlags origin_flags = 0;
|
||||
RpmOstreeOriginParseFlags origin_flags = 0;
|
||||
|
||||
g_clear_pointer (&self->origin, (GDestroyNotify)rpmostree_origin_unref);
|
||||
|
||||
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_IGNORE_UNCONFIGURED)
|
||||
origin_flags |= RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED;
|
||||
origin_flags |= RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED;
|
||||
self->origin = rpmostree_origin_parse_keyfile (origin, origin_flags, error);
|
||||
if (!self->origin)
|
||||
return FALSE;
|
||||
@ -939,6 +940,7 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
|
||||
g_autoptr(RpmOstreeTreespec) treespec = NULL;
|
||||
g_autoptr(RpmOstreeInstall) install = {0,};
|
||||
g_autoptr(GHashTable) pkgset = hashset_from_strv (rpmostree_origin_get_packages (self->origin));
|
||||
const gboolean have_packages = g_hash_table_size (pkgset) > 0;
|
||||
glnx_unref_object OstreeRepo *pkgcache_repo = NULL;
|
||||
|
||||
ctx = rpmostree_context_new_system (cancellable, error);
|
||||
@ -995,41 +997,96 @@ overlay_final_pkgset (RpmOstreeSysrootUpgrader *self,
|
||||
|
||||
rpmostree_context_set_repos (ctx, repo, pkgcache_repo);
|
||||
|
||||
/* --- Downloading metadata --- */
|
||||
if (!rpmostree_context_download_metadata (ctx, cancellable, error))
|
||||
goto out;
|
||||
if (have_packages)
|
||||
{
|
||||
/* --- Downloading metadata --- */
|
||||
if (!rpmostree_context_download_metadata (ctx, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* --- Resolving dependencies --- */
|
||||
if (!rpmostree_context_prepare_install (ctx, &install, cancellable, error))
|
||||
goto out;
|
||||
/* --- Resolving dependencies --- */
|
||||
if (!rpmostree_context_prepare_install (ctx, &install, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
rpmostree_context_set_is_empty (ctx);
|
||||
|
||||
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGOVERLAY_DRY_RUN)
|
||||
{
|
||||
g_assert (have_packages);
|
||||
rpmostree_print_transaction (rpmostree_context_get_hif (ctx));
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* --- Download as necessary --- */
|
||||
if (!rpmostree_context_download (ctx, install, cancellable, error))
|
||||
if (have_packages)
|
||||
{
|
||||
/* --- Download as necessary --- */
|
||||
if (!rpmostree_context_download (ctx, install, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* --- Import as necessary --- */
|
||||
if (!rpmostree_context_import (ctx, install, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* --- Relabel as necessary --- */
|
||||
if (!rpmostree_context_relabel (ctx, install, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* --- Overlay and commit --- */
|
||||
|
||||
g_clear_pointer (&self->final_revision, g_free);
|
||||
if (!rpmostree_context_assemble_tmprootfs (ctx, tmprootfs_dfd, devino_cache,
|
||||
RPMOSTREE_ASSEMBLE_TYPE_CLIENT_LAYERING,
|
||||
(self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGOVERLAY_NOSCRIPTS) > 0,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!rpmostree_rootfs_postprocess_common (tmprootfs_dfd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
/* --- Import as necessary --- */
|
||||
if (!rpmostree_context_import (ctx, install, cancellable, error))
|
||||
goto out;
|
||||
if (rpmostree_origin_get_regenerate_initramfs (self->origin))
|
||||
{
|
||||
glnx_fd_close int initramfs_tmp_fd = -1;
|
||||
g_autofree char *initramfs_tmp_path = NULL;
|
||||
const char *bootdir;
|
||||
const char *kver;
|
||||
const char *kernel_path;
|
||||
const char *initramfs_path;
|
||||
g_autoptr(GVariant) kernel_state = NULL;
|
||||
g_auto(GStrv) add_dracut_argv = NULL;
|
||||
|
||||
/* --- Relabel as necessary --- */
|
||||
if (!rpmostree_context_relabel (ctx, install, cancellable, error))
|
||||
goto out;
|
||||
add_dracut_argv = rpmostree_origin_get_initramfs_args (self->origin);
|
||||
|
||||
/* --- Overlay and commit --- */
|
||||
g_clear_pointer (&self->final_revision, g_free);
|
||||
if (!rpmostree_context_assemble_commit (ctx, tmprootfs_dfd, devino_cache,
|
||||
self->base_revision,
|
||||
RPMOSTREE_ASSEMBLE_TYPE_CLIENT_LAYERING,
|
||||
(self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGOVERLAY_NOSCRIPTS) > 0,
|
||||
&self->final_revision,
|
||||
cancellable, error))
|
||||
rpmostree_output_task_begin ("Generating initramfs");
|
||||
|
||||
kernel_state = rpmostree_find_kernel (tmprootfs_dfd, cancellable, error);
|
||||
if (!kernel_state)
|
||||
goto out;
|
||||
g_variant_get (kernel_state, "(&s&s&sm&s)",
|
||||
&kver, &bootdir,
|
||||
&kernel_path, &initramfs_path);
|
||||
g_assert (initramfs_path);
|
||||
|
||||
if (!rpmostree_run_dracut (tmprootfs_dfd, add_dracut_argv, initramfs_path,
|
||||
&initramfs_tmp_fd, &initramfs_tmp_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_finalize_kernel (tmprootfs_dfd, bootdir, kver,
|
||||
kernel_path,
|
||||
initramfs_tmp_path, initramfs_tmp_fd,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
rpmostree_output_task_end ("done");
|
||||
}
|
||||
|
||||
if (!rpmostree_context_commit_tmprootfs (ctx, tmprootfs_dfd, devino_cache,
|
||||
self->base_revision,
|
||||
RPMOSTREE_ASSEMBLE_TYPE_CLIENT_LAYERING,
|
||||
&self->final_revision,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
@ -1376,8 +1433,12 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
|
||||
if (rpmostree_origin_is_locally_assembled (self->origin) ||
|
||||
(g_hash_table_size (self->packages_to_add) > 0) ||
|
||||
(g_hash_table_size (self->packages_to_delete) > 0))
|
||||
if (!overlay_packages (self, cancellable, error))
|
||||
goto out;
|
||||
{
|
||||
if (!overlay_packages (self, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
g_clear_pointer (&self->final_revision, g_free);
|
||||
|
||||
if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGOVERLAY_DRY_RUN)
|
||||
{
|
||||
|
@ -219,6 +219,13 @@ rpmostreed_deployment_generate_variant (OstreeDeployment *deployment,
|
||||
g_variant_dict_insert (&dict, "unlocked", "s",
|
||||
ostree_deployment_unlocked_state_to_string (ostree_deployment_get_unlocked (deployment)));
|
||||
|
||||
g_variant_dict_insert (&dict, "regenerate-initramfs", "b",
|
||||
rpmostree_origin_get_regenerate_initramfs (origin));
|
||||
{ g_auto(GStrv) args = rpmostree_origin_get_initramfs_args (origin);
|
||||
if (args && *args)
|
||||
g_variant_dict_insert (&dict, "initramfs-args", "^as", args);
|
||||
}
|
||||
|
||||
if (booted_id != NULL)
|
||||
g_variant_dict_insert (&dict, "booted", "b", g_strcmp0 (booted_id, id) == 0);
|
||||
|
||||
|
@ -770,6 +770,66 @@ out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
os_handle_set_initramfs_state (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gboolean regenerate,
|
||||
const char *const*args,
|
||||
GVariant *arg_options)
|
||||
{
|
||||
RpmostreedOS *self = RPMOSTREED_OS (interface);
|
||||
glnx_unref_object RpmostreedTransaction *transaction = NULL;
|
||||
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
|
||||
g_autoptr(GCancellable) cancellable = g_cancellable_new ();
|
||||
g_autoptr(GVariantDict) dict = NULL;
|
||||
const char *osname;
|
||||
gboolean reboot = FALSE;
|
||||
GError *local_error = NULL;
|
||||
|
||||
transaction = merge_compatible_txn (self, invocation);
|
||||
if (transaction)
|
||||
goto out;
|
||||
|
||||
if (!rpmostreed_sysroot_load_state (rpmostreed_sysroot_get (),
|
||||
cancellable,
|
||||
&ot_sysroot,
|
||||
NULL,
|
||||
&local_error))
|
||||
goto out;
|
||||
|
||||
osname = rpmostree_os_get_name (interface);
|
||||
|
||||
dict = g_variant_dict_new (arg_options);
|
||||
g_variant_dict_lookup (dict, "reboot", "b", &reboot);
|
||||
|
||||
transaction = rpmostreed_transaction_new_initramfs_state (invocation,
|
||||
ot_sysroot,
|
||||
osname,
|
||||
regenerate,
|
||||
(char**)args,
|
||||
reboot,
|
||||
cancellable,
|
||||
&local_error);
|
||||
if (transaction == NULL)
|
||||
goto out;
|
||||
|
||||
rpmostreed_transaction_monitor_add (self->transaction_monitor, transaction);
|
||||
|
||||
out:
|
||||
if (local_error != NULL)
|
||||
{
|
||||
g_dbus_method_invocation_take_error (invocation, local_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *client_address;
|
||||
client_address = rpmostreed_transaction_get_client_address (transaction);
|
||||
rpmostree_os_complete_pkg_change (interface, invocation, client_address);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
os_handle_get_cached_rebase_rpm_diff (RPMOSTreeOS *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
@ -1154,6 +1214,7 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface)
|
||||
iface->handle_clear_rollback_target = os_handle_clear_rollback_target;
|
||||
iface->handle_rebase = os_handle_rebase;
|
||||
iface->handle_pkg_change = os_handle_pkg_change;
|
||||
iface->handle_set_initramfs_state = os_handle_set_initramfs_state;
|
||||
iface->handle_get_cached_rebase_rpm_diff = os_handle_get_cached_rebase_rpm_diff;
|
||||
iface->handle_download_rebase_rpm_diff = os_handle_download_rebase_rpm_diff;
|
||||
iface->handle_get_cached_deploy_rpm_diff = os_handle_get_cached_deploy_rpm_diff;
|
||||
|
@ -1050,3 +1050,134 @@ rpmostreed_transaction_new_deploy (GDBusMethodInvocation *invocation,
|
||||
|
||||
return (RpmostreedTransaction *) self;
|
||||
}
|
||||
|
||||
/* ================================ InitramfsState ================================ */
|
||||
|
||||
typedef struct {
|
||||
RpmostreedTransaction parent;
|
||||
char *osname;
|
||||
gboolean regenerate;
|
||||
char **args;
|
||||
gboolean reboot;
|
||||
} InitramfsStateTransaction;
|
||||
|
||||
typedef RpmostreedTransactionClass InitramfsStateTransactionClass;
|
||||
|
||||
GType initramfs_state_transaction_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (InitramfsStateTransaction,
|
||||
initramfs_state_transaction,
|
||||
RPMOSTREED_TYPE_TRANSACTION)
|
||||
|
||||
static void
|
||||
initramfs_state_transaction_finalize (GObject *object)
|
||||
{
|
||||
InitramfsStateTransaction *self;
|
||||
|
||||
self = (InitramfsStateTransaction *) object;
|
||||
g_free (self->osname);
|
||||
g_strfreev (self->args);
|
||||
|
||||
G_OBJECT_CLASS (initramfs_state_transaction_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
initramfs_state_transaction_execute (RpmostreedTransaction *transaction,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
InitramfsStateTransaction *self;
|
||||
OstreeSysroot *sysroot;
|
||||
glnx_unref_object RpmOstreeSysrootUpgrader *upgrader = NULL;
|
||||
RpmOstreeOrigin *origin = NULL; /* Owned by upgrader */
|
||||
g_autoptr(GKeyFile) new_origin = NULL;
|
||||
g_auto(GStrv) current_initramfs_args = NULL;
|
||||
gboolean current_regenerate;
|
||||
|
||||
self = (InitramfsStateTransaction *) transaction;
|
||||
|
||||
sysroot = rpmostreed_transaction_get_sysroot (transaction);
|
||||
|
||||
upgrader = rpmostree_sysroot_upgrader_new (sysroot, self->osname, 0,
|
||||
cancellable, error);
|
||||
if (upgrader == NULL)
|
||||
return FALSE;
|
||||
|
||||
origin = rpmostree_sysroot_upgrader_get_origin (upgrader);
|
||||
current_regenerate = rpmostree_origin_get_regenerate_initramfs (origin);
|
||||
current_initramfs_args = rpmostree_origin_get_initramfs_args (origin);
|
||||
/* We don't deep-compare the args right now, we assume if you were using them
|
||||
* you want to rerun. This can be important if you edited a config file, which
|
||||
* we can't really track without actually regenerating anyways.
|
||||
*/
|
||||
if (current_regenerate == self->regenerate
|
||||
&& (current_initramfs_args == NULL || !*current_initramfs_args)
|
||||
&& (self->args == NULL || !*self->args))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"initramfs regeneration state is already %s",
|
||||
current_regenerate ? "enabled" : "disabled");
|
||||
return FALSE;
|
||||
}
|
||||
new_origin = rpmostree_origin_dup_keyfile (origin);
|
||||
rpmostree_origin_set_regenerate_initramfs (new_origin, self->regenerate, self->args);
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!rpmostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (self->reboot)
|
||||
rpmostreed_reboot (cancellable, error);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
initramfs_state_transaction_class_init (InitramfsStateTransactionClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = G_OBJECT_CLASS (class);
|
||||
object_class->finalize = initramfs_state_transaction_finalize;
|
||||
|
||||
class->execute = initramfs_state_transaction_execute;
|
||||
}
|
||||
|
||||
static void
|
||||
initramfs_state_transaction_init (InitramfsStateTransaction *self)
|
||||
{
|
||||
}
|
||||
|
||||
RpmostreedTransaction *
|
||||
rpmostreed_transaction_new_initramfs_state (GDBusMethodInvocation *invocation,
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
gboolean regenerate,
|
||||
char **args,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
InitramfsStateTransaction *self;
|
||||
|
||||
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
||||
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);
|
||||
|
||||
self = g_initable_new (initramfs_state_transaction_get_type (),
|
||||
cancellable, error,
|
||||
"invocation", invocation,
|
||||
"sysroot-path", gs_file_get_path_cached (ostree_sysroot_get_path (sysroot)),
|
||||
NULL);
|
||||
|
||||
if (self != NULL)
|
||||
{
|
||||
self->osname = g_strdup (osname);
|
||||
self->regenerate = regenerate;
|
||||
self->args = g_strdupv (args);
|
||||
self->reboot = reboot;
|
||||
}
|
||||
|
||||
return (RpmostreedTransaction *) self;
|
||||
}
|
||||
|
@ -90,3 +90,12 @@ RpmostreedTransaction *
|
||||
RpmOstreeTransactionPkgFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
RpmostreedTransaction *
|
||||
rpmostreed_transaction_new_initramfs_state (GDBusMethodInvocation *invocation,
|
||||
OstreeSysroot *sysroot,
|
||||
const char *osname,
|
||||
gboolean regenerate,
|
||||
char **args,
|
||||
gboolean reboot,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
@ -90,38 +90,25 @@ qsort_cmpstr (const void*ap, const void *bp, gpointer data)
|
||||
return strcmp (a, b);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
add_canonicalized_string_array (GVariantBuilder *builder,
|
||||
const char *key,
|
||||
const char *notfound_key,
|
||||
GKeyFile *keyfile,
|
||||
GError **error)
|
||||
GKeyFile *keyfile)
|
||||
{
|
||||
g_auto(GStrv) input = NULL;
|
||||
g_autoptr(GHashTable) set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
g_autofree char **sorted = NULL;
|
||||
guint count;
|
||||
char **iter;
|
||||
g_autoptr(GError) temp_error = NULL;
|
||||
|
||||
input = g_key_file_get_string_list (keyfile, "tree", key, NULL, &temp_error);
|
||||
input = g_key_file_get_string_list (keyfile, "tree", key, NULL, NULL);
|
||||
if (!(input && *input))
|
||||
{
|
||||
if (notfound_key)
|
||||
{
|
||||
g_variant_builder_add (builder, "{sv}", notfound_key, g_variant_new_boolean (TRUE));
|
||||
return TRUE;
|
||||
}
|
||||
else if (temp_error)
|
||||
{
|
||||
g_propagate_error (error, g_steal_pointer (&temp_error));
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Key %s is empty", key);
|
||||
return FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +124,6 @@ add_canonicalized_string_array (GVariantBuilder *builder,
|
||||
|
||||
g_variant_builder_add (builder, "{sv}", key,
|
||||
g_variant_new_strv ((const char*const*)sorted, g_strv_length (sorted)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@ -157,23 +143,15 @@ rpmostree_treespec_new_from_keyfile (GKeyFile *keyfile,
|
||||
g_variant_builder_add (&builder, "{sv}", "ref", g_variant_new_string (ref));
|
||||
}
|
||||
|
||||
if (!add_canonicalized_string_array (&builder, "packages", NULL, keyfile, error))
|
||||
return NULL;
|
||||
|
||||
add_canonicalized_string_array (&builder, "packages", NULL, keyfile);
|
||||
/* We allow the "repo" key to be missing. This means that we rely on hif's
|
||||
* normal behaviour (i.e. look at repos in repodir with enabled=1). */
|
||||
{ g_auto(GStrv) val = g_key_file_get_string_list (keyfile, "tree", "repos",
|
||||
NULL, NULL);
|
||||
if (val && *val &&
|
||||
!add_canonicalized_string_array (&builder, "repos", "", keyfile, error))
|
||||
return NULL;
|
||||
{ g_auto(GStrv) val = g_key_file_get_string_list (keyfile, "tree", "repos", NULL, NULL);
|
||||
if (val && *val)
|
||||
add_canonicalized_string_array (&builder, "repos", NULL, keyfile);
|
||||
}
|
||||
|
||||
if (!add_canonicalized_string_array (&builder, "instlangs", "instlangs-all", keyfile, error))
|
||||
return NULL;
|
||||
|
||||
if (!add_canonicalized_string_array (&builder, "ignore-scripts", "", keyfile, error))
|
||||
return NULL;
|
||||
add_canonicalized_string_array (&builder, "instlangs", "instlangs-all", keyfile);
|
||||
add_canonicalized_string_array (&builder, "ignore-scripts", NULL, keyfile);
|
||||
|
||||
{ gboolean documentation = TRUE;
|
||||
g_autofree char *value = g_key_file_get_value (keyfile, "tree", "documentation", NULL);
|
||||
@ -280,6 +258,7 @@ struct _RpmOstreeContext {
|
||||
GObject parent;
|
||||
|
||||
RpmOstreeTreespec *spec;
|
||||
gboolean empty;
|
||||
DnfContext *hifctx;
|
||||
GHashTable *ignore_scripts;
|
||||
OstreeRepo *ostreerepo;
|
||||
@ -444,6 +423,14 @@ rpmostree_context_new_unprivileged (int basedir_dfd,
|
||||
return rpmostree_context_new_internal (basedir_dfd, TRUE, cancellable, error);
|
||||
}
|
||||
|
||||
/* Use this if no packages will be installed, and we just want a "dummy" run.
|
||||
*/
|
||||
void
|
||||
rpmostree_context_set_is_empty (RpmOstreeContext *self)
|
||||
{
|
||||
self->empty = TRUE;
|
||||
}
|
||||
|
||||
/* XXX: or put this in new_system() instead? */
|
||||
void
|
||||
rpmostree_context_set_repos (RpmOstreeContext *self,
|
||||
@ -691,6 +678,8 @@ rpmostree_context_download_metadata (RpmOstreeContext *self,
|
||||
guint progress_sigid;
|
||||
glnx_unref_object DnfState *hifstate = dnf_state_new ();
|
||||
|
||||
g_assert (!self->empty);
|
||||
|
||||
progress_sigid = g_signal_connect (hifstate, "percentage-changed",
|
||||
G_CALLBACK (on_hifstate_percentage_changed),
|
||||
"Downloading metadata:");
|
||||
@ -980,6 +969,7 @@ rpmostree_context_prepare_install (RpmOstreeContext *self,
|
||||
g_autoptr(RpmOstreeInstall) ret_install = g_object_new (RPMOSTREE_TYPE_INSTALL, NULL);
|
||||
|
||||
g_assert (g_variant_dict_lookup (self->spec->dict, "packages", "^a&s", &pkgnames));
|
||||
g_assert (!self->empty);
|
||||
|
||||
ret_install->packages_requested = g_ptr_array_new_with_free_func (g_free);
|
||||
|
||||
@ -1058,7 +1048,8 @@ rpmostree_context_get_state_sha512 (RpmOstreeContext *self)
|
||||
g_checksum_update (state_checksum, g_variant_get_data (self->spec->spec),
|
||||
g_variant_get_size (self->spec->spec));
|
||||
|
||||
rpmostree_dnf_add_checksum_goal (state_checksum, dnf_context_get_goal (self->hifctx));
|
||||
if (!self->empty)
|
||||
rpmostree_dnf_add_checksum_goal (state_checksum, dnf_context_get_goal (self->hifctx));
|
||||
return g_strdup (g_checksum_get_string (state_checksum));
|
||||
}
|
||||
|
||||
@ -2403,9 +2394,6 @@ rpmostree_context_assemble_tmprootfs (RpmOstreeContext *self,
|
||||
|
||||
rpmostree_output_task_end ("done");
|
||||
|
||||
if (!rpmostree_rootfs_postprocess_common (tmprootfs_dfd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (ordering_ts)
|
||||
@ -2543,6 +2531,10 @@ rpmostree_context_assemble_commit (RpmOstreeContext *self,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
||||
if (!rpmostree_rootfs_postprocess_common (tmprootfs_dfd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!rpmostree_context_commit_tmprootfs (self, tmprootfs_dfd, devino_cache,
|
||||
parent, assemble_type,
|
||||
out_commit,
|
||||
|
@ -64,6 +64,8 @@ gboolean rpmostree_context_setup (RpmOstreeContext *self,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void rpmostree_context_set_is_empty (RpmOstreeContext *self);
|
||||
|
||||
void rpmostree_context_set_repos (RpmOstreeContext *self,
|
||||
OstreeRepo *base_repo,
|
||||
OstreeRepo *pkgcache_repo);
|
||||
|
@ -169,13 +169,27 @@ rpmostree_find_kernel (int rootfs_dfd,
|
||||
g_autofree char* initramfs_path = NULL;
|
||||
const char *kver = NULL; /* May point to kver_owned */
|
||||
g_autofree char *kver_owned = NULL;
|
||||
g_autofree char *bootdir = g_strdup ("boot");
|
||||
g_autofree char *bootdir = g_strdup ("usr/lib/ostree-boot");
|
||||
|
||||
/* First, look in the canonical ostree directory */
|
||||
if (!find_kernel_and_initramfs_in_bootdir (rootfs_dfd, bootdir,
|
||||
&kernel_path, &initramfs_path,
|
||||
cancellable, error))
|
||||
return NULL;
|
||||
|
||||
/* Next, the traditional /boot */
|
||||
if (kernel_path == NULL)
|
||||
{
|
||||
g_free (bootdir);
|
||||
bootdir = g_strdup ("boot");
|
||||
|
||||
if (!find_kernel_and_initramfs_in_bootdir (rootfs_dfd, bootdir,
|
||||
&kernel_path, &initramfs_path,
|
||||
cancellable, error))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finally, the newer model of having the kernel with the modules */
|
||||
if (kernel_path == NULL)
|
||||
{
|
||||
g_autofree char* modversion_dir = NULL;
|
||||
@ -282,6 +296,7 @@ dracut_child_setup (gpointer data)
|
||||
gboolean
|
||||
rpmostree_run_dracut (int rootfs_dfd,
|
||||
char **argv,
|
||||
const char *rebuild_from_initramfs,
|
||||
int *out_initramfs_tmpfd,
|
||||
char **out_initramfs_tmppath,
|
||||
GCancellable *cancellable,
|
||||
@ -303,6 +318,23 @@ rpmostree_run_dracut (int rootfs_dfd,
|
||||
glnx_fd_close int tmp_fd = -1;
|
||||
g_autofree char *tmpfile_path = NULL;
|
||||
g_autoptr(RpmOstreeBwrap) bwrap = NULL;
|
||||
g_autoptr(GPtrArray) rebuild_argv = NULL;
|
||||
|
||||
g_assert (argv != NULL || rebuild_from_initramfs != NULL);
|
||||
|
||||
if (rebuild_from_initramfs)
|
||||
{
|
||||
rebuild_argv = g_ptr_array_new ();
|
||||
g_ptr_array_add (rebuild_argv, "--rebuild");
|
||||
g_ptr_array_add (rebuild_argv, (char*)rebuild_from_initramfs);
|
||||
/* In this case, any args specified in argv are *additional*
|
||||
* to the rebuild from the base.
|
||||
*/
|
||||
for (char **iter = argv; iter && *iter; iter++)
|
||||
g_ptr_array_add (rebuild_argv, *iter);
|
||||
g_ptr_array_add (rebuild_argv, NULL);
|
||||
argv = (char**)rebuild_argv->pdata;
|
||||
}
|
||||
|
||||
/* First tempfile is just our shell script */
|
||||
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "usr/bin",
|
||||
@ -324,14 +356,23 @@ rpmostree_run_dracut (int rootfs_dfd,
|
||||
/* We need to close the writable FD now to be able to exec it */
|
||||
close (tmp_fd); tmp_fd = -1;
|
||||
|
||||
/* Second tempfile is the initramfs contents */
|
||||
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, "tmp",
|
||||
/* Second tempfile is the initramfs contents. Note we generate the tmpfile
|
||||
* in . since in the current rpm-ostree design the temporary rootfs may not have tmp/
|
||||
* as a real mountpoint.
|
||||
*/
|
||||
if (!glnx_open_tmpfile_linkable_at (rootfs_dfd, ".",
|
||||
O_RDWR | O_CLOEXEC,
|
||||
&tmp_fd, &tmpfile_path,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
bwrap = rpmostree_bwrap_new (rootfs_dfd, RPMOSTREE_BWRAP_IMMUTABLE, error, NULL);
|
||||
if (rebuild_from_initramfs)
|
||||
bwrap = rpmostree_bwrap_new (rootfs_dfd, RPMOSTREE_BWRAP_IMMUTABLE, error,
|
||||
"--ro-bind", "/etc", "/etc",
|
||||
NULL);
|
||||
else
|
||||
bwrap = rpmostree_bwrap_new (rootfs_dfd, RPMOSTREE_BWRAP_IMMUTABLE, error,
|
||||
NULL);
|
||||
if (!bwrap)
|
||||
return FALSE;
|
||||
|
||||
@ -345,6 +386,9 @@ rpmostree_run_dracut (int rootfs_dfd,
|
||||
if (!rpmostree_bwrap_run (bwrap, error))
|
||||
goto out;
|
||||
|
||||
if (rebuild_from_initramfs)
|
||||
(void) unlinkat (rootfs_dfd, rebuild_from_initramfs, 0);
|
||||
|
||||
ret = TRUE;
|
||||
*out_initramfs_tmpfd = tmp_fd; tmp_fd = -1;
|
||||
*out_initramfs_tmppath = g_steal_pointer (&tmpfile_path);
|
||||
|
@ -40,6 +40,7 @@ rpmostree_finalize_kernel (int rootfs_dfd,
|
||||
gboolean
|
||||
rpmostree_run_dracut (int rootfs_dfd,
|
||||
char **argv,
|
||||
const char *rebuild_from_initramfs,
|
||||
int *out_initramfs_tmpfd,
|
||||
char **out_initramfs_tmppath,
|
||||
GCancellable *cancellable,
|
||||
|
@ -45,7 +45,7 @@ keyfile_dup (GKeyFile *kf)
|
||||
|
||||
RpmOstreeOrigin *
|
||||
rpmostree_origin_parse_keyfile (GKeyFile *origin,
|
||||
RpmOstreeOriginFlags flags,
|
||||
RpmOstreeOriginParseFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(RpmOstreeOrigin) ret = NULL;
|
||||
@ -57,7 +57,7 @@ rpmostree_origin_parse_keyfile (GKeyFile *origin,
|
||||
/* NOTE hack here - see https://github.com/ostreedev/ostree/pull/343 */
|
||||
g_key_file_remove_key (ret->kf, "origin", "unlocked", NULL);
|
||||
|
||||
if ((flags & RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED) == 0)
|
||||
if ((flags & RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED) == 0)
|
||||
{
|
||||
g_autofree char *unconfigured_state = NULL;
|
||||
|
||||
@ -116,7 +116,21 @@ gboolean
|
||||
rpmostree_origin_is_locally_assembled (RpmOstreeOrigin *origin)
|
||||
{
|
||||
g_assert (origin);
|
||||
return g_strv_length (origin->packages) > 0;
|
||||
|
||||
return g_strv_length (origin->packages) > 0 ||
|
||||
rpmostree_origin_get_regenerate_initramfs (origin);
|
||||
}
|
||||
|
||||
gboolean
|
||||
rpmostree_origin_get_regenerate_initramfs (RpmOstreeOrigin *origin)
|
||||
{
|
||||
return g_key_file_get_boolean (origin->kf, "rpmostree", "regenerate-initramfs", NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
rpmostree_origin_get_initramfs_args (RpmOstreeOrigin *origin)
|
||||
{
|
||||
return g_key_file_get_string_list (origin->kf, "rpmostree", "initramfs-args", NULL, NULL);
|
||||
}
|
||||
|
||||
GKeyFile *
|
||||
@ -159,3 +173,27 @@ rpmostree_origin_unref (RpmOstreeOrigin *origin)
|
||||
g_strfreev (origin->packages);
|
||||
g_free (origin);
|
||||
}
|
||||
|
||||
void
|
||||
rpmostree_origin_set_regenerate_initramfs (GKeyFile *mutable_origin,
|
||||
gboolean regenerate,
|
||||
char **args)
|
||||
{
|
||||
const char *section = "rpmostree";
|
||||
const char *regeneratek = "regenerate-initramfs";
|
||||
const char *argsk = "initramfs-args";
|
||||
if (regenerate)
|
||||
{
|
||||
g_key_file_set_boolean (mutable_origin, section, regeneratek, TRUE);
|
||||
if (args && *args)
|
||||
g_key_file_set_string_list (mutable_origin, section, argsk,
|
||||
(const char *const*)args, g_strv_length (args));
|
||||
else
|
||||
g_key_file_remove_key (mutable_origin, section, argsk, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_key_file_remove_key (mutable_origin, section, regeneratek, NULL);
|
||||
g_key_file_remove_key (mutable_origin, section, argsk, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -28,18 +28,18 @@ void rpmostree_origin_unref (RpmOstreeOrigin *origin);
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(RpmOstreeOrigin, rpmostree_origin_unref)
|
||||
|
||||
typedef enum {
|
||||
RPMOSTREE_ORIGIN_FLAGS_IGNORE_UNCONFIGURED = (1 << 0)
|
||||
} RpmOstreeOriginFlags;
|
||||
RPMOSTREE_ORIGIN_PARSE_FLAGS_IGNORE_UNCONFIGURED = (1 << 0)
|
||||
} RpmOstreeOriginParseFlags;
|
||||
|
||||
RpmOstreeOrigin *
|
||||
rpmostree_origin_parse_keyfile (GKeyFile *keyfile,
|
||||
RpmOstreeOriginFlags flags,
|
||||
RpmOstreeOriginParseFlags flags,
|
||||
GError **error);
|
||||
|
||||
static inline
|
||||
RpmOstreeOrigin *
|
||||
rpmostree_origin_parse_deployment_ex (OstreeDeployment *deployment,
|
||||
RpmOstreeOriginFlags flags,
|
||||
RpmOstreeOriginParseFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
GKeyFile *origin = ostree_deployment_get_origin (deployment);
|
||||
@ -74,6 +74,12 @@ rpmostree_origin_get_packages (RpmOstreeOrigin *origin);
|
||||
const char *
|
||||
rpmostree_origin_get_override_commit (RpmOstreeOrigin *origin);
|
||||
|
||||
gboolean
|
||||
rpmostree_origin_get_regenerate_initramfs (RpmOstreeOrigin *origin);
|
||||
|
||||
char **
|
||||
rpmostree_origin_get_initramfs_args (RpmOstreeOrigin *origin);
|
||||
|
||||
char *
|
||||
rpmostree_origin_get_string (RpmOstreeOrigin *origin,
|
||||
const char *section,
|
||||
@ -84,3 +90,6 @@ rpmostree_origin_get_keyfile (RpmOstreeOrigin *origin);
|
||||
GKeyFile *
|
||||
rpmostree_origin_dup_keyfile (RpmOstreeOrigin *origin);
|
||||
|
||||
void rpmostree_origin_set_regenerate_initramfs (GKeyFile *mutable_origin,
|
||||
gboolean regenerate,
|
||||
char **args);
|
||||
|
@ -206,7 +206,7 @@ do_kernel_prep (int rootfs_dfd,
|
||||
}
|
||||
g_ptr_array_add (dracut_argv, NULL);
|
||||
|
||||
if (!rpmostree_run_dracut (rootfs_dfd, (char**)dracut_argv->pdata,
|
||||
if (!rpmostree_run_dracut (rootfs_dfd, (char**)dracut_argv->pdata, NULL,
|
||||
&initramfs_tmp_fd, &initramfs_tmp_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
@ -112,12 +112,17 @@ vm_get_boot_id() {
|
||||
vm_cmd cat /proc/sys/kernel/random/boot_id
|
||||
}
|
||||
|
||||
# Run a command in the VM that will cause a reboot
|
||||
vm_reboot_cmd() {
|
||||
vm_cmd sync
|
||||
bootid=$(vm_get_boot_id 2>/dev/null)
|
||||
vm_cmd $@ || :
|
||||
vm_ssh_wait 120 $bootid
|
||||
}
|
||||
|
||||
# reboot the vm
|
||||
vm_reboot() {
|
||||
vm_cmd sync
|
||||
bootid=$(vm_get_boot_id 2>/dev/null)
|
||||
vm_cmd systemctl reboot || :
|
||||
vm_ssh_wait 120 $bootid
|
||||
vm_reboot_cmd systemctl reboot
|
||||
}
|
||||
|
||||
# check that the given files/dirs exist on the VM
|
||||
|
126
tests/vmcheck/test-initramfs.sh
Executable file
126
tests/vmcheck/test-initramfs.sh
Executable file
@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2017 Red Hat, Inc.
|
||||
#
|
||||
# This library 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 License, 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.
|
||||
|
||||
set -e
|
||||
|
||||
. ${commondir}/libtest.sh
|
||||
. ${commondir}/libvm.sh
|
||||
|
||||
set -x
|
||||
|
||||
# SUMMARY: Tests for the `initramfs` functionality
|
||||
|
||||
assert_jq() {
|
||||
expression=$1
|
||||
jsonfile=$2
|
||||
|
||||
if ! jq -e "${expression}" >/dev/null < $jsonfile; then
|
||||
jq . < $jsonfile | sed -e 's/^/# /' >&2
|
||||
echo 1>&2 "${expression} failed to match in $jsonfile"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
vm_send_test_repo
|
||||
base=$(vm_get_booted_csum)
|
||||
|
||||
vm_rpmostree initramfs > initramfs.txt
|
||||
assert_file_has_content initramfs.txt "Initramfs regeneration.*disabled"
|
||||
echo "ok initramfs status"
|
||||
|
||||
if vm_rpmostree initramfs --disable 2>err.txt; then
|
||||
assert_not_reached "Unexpectedly succeeded at disabling"
|
||||
fi
|
||||
assert_file_has_content err.txt "already.*disabled"
|
||||
if vm_rpmostree initramfs --reboot 2>err.txt; then
|
||||
assert_not_reached "reboot worked?"
|
||||
fi
|
||||
assert_file_has_content err.txt "reboot.*used with.*enable"
|
||||
echo "ok initramfs state"
|
||||
|
||||
vm_rpmostree initramfs --enable
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[1].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]' status.json
|
||||
assert_jq '.deployments[1]["regenerate-initramfs"]|not' status.json
|
||||
|
||||
vm_reboot
|
||||
|
||||
assert_not_streq $base $(vm_get_booted_csum)
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[0].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]' status.json
|
||||
assert_jq '.deployments[0]["initramfs-args"]|length == 0' status.json
|
||||
assert_jq '.deployments[1]["regenerate-initramfs"]|not' status.json
|
||||
assert_jq '.deployments[1]["initramfs-args"]|not' status.json
|
||||
|
||||
if vm_rpmostree initramfs --enable 2>err.txt; then
|
||||
assert_not_reached "Unexpectedly succeeded at enabling"
|
||||
fi
|
||||
assert_file_has_content err.txt "already.*enabled"
|
||||
echo "ok initramfs enabled"
|
||||
|
||||
vm_rpmostree initramfs --disable
|
||||
vm_reboot
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[0].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]|not' status.json
|
||||
assert_jq '.deployments[1]["regenerate-initramfs"]' status.json
|
||||
|
||||
echo "ok initramfs disabled"
|
||||
|
||||
vm_reboot_cmd rpm-ostree initramfs --enable --reboot
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[0].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]' status.json
|
||||
assert_jq '.deployments[1]["regenerate-initramfs"]|not' status.json
|
||||
|
||||
vm_reboot_cmd rpm-ostree initramfs --disable --reboot
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[0].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]|not' status.json
|
||||
assert_jq '.deployments[1]["regenerate-initramfs"]' status.json
|
||||
|
||||
echo "ok initramfs enable disable reboot"
|
||||
|
||||
assert_streq $base $(vm_get_booted_csum)
|
||||
for file in first second; do
|
||||
vm_cmd touch /etc/rpmostree-initramfs-testing-$file
|
||||
vm_rpmostree initramfs --enable --arg="-I" --arg="/etc/rpmostree-initramfs-testing-$file"
|
||||
vm_reboot
|
||||
vm_rpmostree status --json > status.json
|
||||
assert_jq '.deployments[0].booted' status.json
|
||||
assert_jq '.deployments[0]["regenerate-initramfs"]' status.json
|
||||
assert_jq '.deployments[0]["initramfs-args"]|index("-I") == 0' status.json
|
||||
assert_jq '.deployments[0]["initramfs-args"]|index("/etc/rpmostree-initramfs-testing-'${file}'") == 1' status.json
|
||||
assert_jq '.deployments[0]["initramfs-args"]|length == 2' status.json
|
||||
initramfs=$(vm_cmd grep ^initrd /boot/loader/entries/ostree-fedora-atomic-0.conf | sed -e 's,initrd ,/boot/,')
|
||||
test -n "${initramfs}"
|
||||
vm_cmd lsinitrd $initramfs > lsinitrd.txt
|
||||
assert_file_has_content lsinitrd.txt /etc/rpmostree-initramfs-testing-${file}
|
||||
done
|
||||
|
||||
vm_rpmostree initramfs --disable
|
||||
|
||||
initramfs=$(vm_cmd grep ^initrd /boot/loader/entries/ostree-fedora-atomic-0.conf | sed -e 's,initrd ,/boot/,')
|
||||
test -n "${initramfs}"
|
||||
vm_cmd lsinitrd $initramfs > lsinitrd.txt
|
||||
assert_not_file_has_content lsinitrd.txt /etc/rpmostree-initramfs-testing
|
||||
|
||||
echo "ok initramfs args"
|
Loading…
x
Reference in New Issue
Block a user