Add new reset command

Add a new `reset` command that makes it easy to blow away all
customizations: overlays, overrides, and initramfs. One can use flags to
only reset some of the customizations.

I placed this under `ex` out of conservatism. It's a pretty simple
command with simple behaviour, though the features it relies on
(no-layering, no-initramfs) are brand new. We can move it out of there
in a release or two?

Closes: #1387

Closes: #1419
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2018-06-26 10:30:32 -04:00 committed by Atomic Bot
parent c84b8b81db
commit 07ecfca3d9
9 changed files with 242 additions and 4 deletions

View File

@ -35,6 +35,7 @@ rpm_ostree_SOURCES = src/app/main.c \
src/app/rpmostree-builtin-usroverlay.c \
src/app/rpmostree-builtin-override.c \
src/app/rpmostree-builtin-refresh-md.c \
src/app/rpmostree-builtin-reset.c \
src/app/rpmostree-pkg-builtins.c \
src/app/rpmostree-builtin-status.c \
src/app/rpmostree-builtin-ex.c \

View File

@ -70,7 +70,7 @@ static RpmOstreeCommand commands[] = {
rpmostree_builtin_usroverlay },
/* Let's be "cognitively" compatible with `ostree admin unlock` */
{ "unlock", RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
"",
NULL,
rpmostree_builtin_usroverlay },
{ "cancel", 0,
"Cancel an active transaction",
@ -105,7 +105,8 @@ static RpmOstreeCommand commands[] = {
/* Hidden */
{ "ex", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD |
RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
"Experimental commands that may change or be removed in the future", rpmostree_builtin_ex },
"Experimental commands that may change or be removed in the future",
rpmostree_builtin_ex },
{ "start-daemon", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD |
RPM_OSTREE_BUILTIN_FLAG_REQUIRES_ROOT |
RPM_OSTREE_BUILTIN_FLAG_HIDDEN,

View File

@ -32,6 +32,9 @@ static RpmOstreeCommand ex_subcommands[] = {
"Convert an OSTree commit into an rpm-ostree rojig", rpmostree_ex_builtin_commit2rojig },
{ "rojig2commit", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD,
"Convert an rpm-ostree rojig into an OSTree commit", rpmostree_ex_builtin_rojig2commit },
{ "reset", RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS,
"Remove all mutations",
rpmostree_ex_builtin_reset },
/* temporary aliases; nuke in next version */
{ "kargs", RPM_OSTREE_BUILTIN_FLAG_HIDDEN,
NULL, rpmostree_builtin_kargs },

View File

@ -0,0 +1,115 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2018 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-util.h"
#include "rpmostree-libbuiltin.h"
#include "rpmostree-dbus-helpers.h"
#include <libglnx.h>
static char *opt_osname;
static gboolean opt_reboot;
static gboolean opt_overlays;
static gboolean opt_overrides;
static gboolean opt_initramfs;
static GOptionEntry option_entries[] = {
{ "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" },
{ "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Initiate a reboot after transaction is complete", NULL },
{ "overlays", 'l', 0, G_OPTION_ARG_NONE, &opt_overlays, "Remove all overlayed packages", NULL },
{ "overrides", 'o', 0, G_OPTION_ARG_NONE, &opt_overrides, "Remove all overrides", NULL },
{ "initramfs", 'i', 0, G_OPTION_ARG_NONE, &opt_initramfs, "Stop regenerating initramfs", NULL },
{ NULL }
};
gboolean
rpmostree_ex_builtin_reset (int argc,
char **argv,
RpmOstreeCommandInvocation *invocation,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = g_option_context_new ("");
glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL;
g_autofree char *transaction_address = NULL;
_cleanup_peer_ GPid peer_pid = 0;
const char *const *install_pkgs = NULL;
const char *const *uninstall_pkgs = NULL;
if (!rpmostree_option_context_parse (context,
option_entries,
&argc, &argv,
invocation,
cancellable,
&install_pkgs,
&uninstall_pkgs,
&sysroot_proxy,
&peer_pid,
NULL,
error))
return FALSE;
if (argc < 1 || argc > 2)
{
rpmostree_usage_error (context, "Too few or too many arguments", error);
return FALSE;
}
/* default to resetting all if no specificiers */
if (!opt_overlays && !opt_overrides && !opt_initramfs)
opt_overlays = opt_overrides = opt_initramfs = TRUE;
/* If we don't also have to install pkgs, do resets offline */
gboolean cache_only = (install_pkgs == NULL);
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);
GVariantDict dict;
g_variant_dict_init (&dict, NULL);
g_variant_dict_insert (&dict, "reboot", "b", opt_reboot);
g_variant_dict_insert (&dict, "no-pull-base", "b", TRUE);
g_variant_dict_insert (&dict, "no-layering", "b", opt_overlays);
g_variant_dict_insert (&dict, "no-overrides", "b", opt_overrides);
g_variant_dict_insert (&dict, "no-initramfs", "b", opt_initramfs);
g_variant_dict_insert (&dict, "cache-only", "b", cache_only);
g_autoptr(GVariant) options = g_variant_ref_sink (g_variant_dict_end (&dict));
if (!rpmostree_update_deployment (os_proxy, NULL, NULL, install_pkgs, uninstall_pkgs,
NULL, NULL, NULL, options, &transaction_address,
cancellable, error))
return FALSE;
return rpmostree_transaction_client_run (invocation, sysroot_proxy, os_proxy,
options, FALSE,
transaction_address,
previous_deployment,
cancellable, error);
}

View File

@ -34,6 +34,7 @@ BUILTINPROTO(unpack);
BUILTINPROTO(livefs);
BUILTINPROTO(commit2rojig);
BUILTINPROTO(rojig2commit);
BUILTINPROTO(reset);
#undef BUILTINPROTO

View File

@ -187,6 +187,9 @@ os_authorize_method (GDBusInterfaceSkeleton *interface,
gboolean no_layering =
vardict_lookup_bool (&options_dict, "no-layering", FALSE);
if (vardict_lookup_bool (&options_dict, "no-initramfs", FALSE))
g_ptr_array_add (actions, "org.projectatomic.rpmostree1.bootconfig");
if (refspec != NULL)
g_ptr_array_add (actions, "org.projectatomic.rpmostree1.rebase");
else if (revision != NULL)

View File

@ -754,6 +754,7 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
((self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DRY_RUN) > 0);
const gboolean no_overrides = deploy_has_bool_option (self, "no-overrides");
const gboolean no_layering = deploy_has_bool_option (self, "no-layering");
const gboolean no_initramfs = deploy_has_bool_option (self, "no-initramfs");
const gboolean cache_only = deploy_has_bool_option (self, "cache-only");
const gboolean download_only =
((self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DOWNLOAD_ONLY) > 0);
@ -896,6 +897,12 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
g_string_append (txn_title, " (download only)");
gboolean changed = FALSE;
if (no_initramfs && rpmostree_origin_get_regenerate_initramfs (origin))
{
rpmostree_origin_set_regenerate_initramfs (origin, FALSE, NULL);
changed = TRUE;
}
if (no_layering)
{
gboolean layering_changed = FALSE;

View File

@ -409,8 +409,7 @@ rpmostree_origin_set_regenerate_initramfs (RpmOstreeOrigin *origin,
}
origin->cached_initramfs_args =
g_key_file_get_string_list (origin->kf, "rpmostree", "initramfs-args",
NULL, NULL);
g_key_file_get_string_list (origin->kf, "rpmostree", "initramfs-args", NULL, NULL);
}
void

108
tests/vmcheck/test-reset.sh Executable file
View File

@ -0,0 +1,108 @@
#!/bin/bash
#
# Copyright (C) 2018 Jonathan Lebon <jonathan@jlebon.com>
#
# 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 -euo pipefail
. ${commondir}/libtest.sh
. ${commondir}/libvm.sh
set -x
# add a builtin foobar
vm_build_rpm foo
vm_rpmostree install foo
vm_cmd ostree refs $(vm_get_pending_csum) --create vmcheck_tmp/with_foo
vm_rpmostree cleanup -p
vm_cmd ostree commit -b vmcheck --tree=ref=vmcheck_tmp/with_foo
vm_rpmostree upgrade
# now do some layering, overrides, and initramfs
vm_build_rpm foo version 2.0
vm_build_rpm bar
vm_build_rpm baz
vm_rpmostree override replace --install bar \
--install /tmp/vmcheck/yumrepo/packages/x86_64/baz-1.0-1.x86_64.rpm \
/tmp/vmcheck/yumrepo/packages/x86_64/foo-2.0-1.x86_64.rpm
vm_rpmostree initramfs --enable
vm_reboot
vm_assert_status_jq \
'.deployments[0].booted' \
'.deployments[0]["packages"]|length == 1' \
'.deployments[0]["requested-packages"]|length == 1' \
'.deployments[0]["requested-local-packages"]|length == 1' \
'.deployments[0]["base-local-replacements"]|length == 1' \
'.deployments[0]["regenerate-initramfs"]'
echo "ok setup"
# check removing layering only
vm_rpmostree ex reset --overlays
vm_assert_status_jq \
'.deployments[0]["packages"]|length == 0' \
'.deployments[0]["requested-packages"]|length == 0' \
'.deployments[0]["requested-local-packages"]|length == 0' \
'.deployments[0]["base-local-replacements"]|length == 1' \
'.deployments[0]["regenerate-initramfs"]'
vm_rpmostree cleanup -p
echo "ok reset overlays"
# check removing overrides only
vm_rpmostree ex reset --overrides
vm_assert_status_jq \
'.deployments[0]["packages"]|length == 1' \
'.deployments[0]["requested-packages"]|length == 1' \
'.deployments[0]["requested-local-packages"]|length == 1' \
'.deployments[0]["base-local-replacements"]|length == 0' \
'.deployments[0]["regenerate-initramfs"]'
vm_rpmostree cleanup -p
echo "ok reset overrides"
# check stopping initramfs only
vm_rpmostree ex reset --initramfs
vm_assert_status_jq \
'.deployments[0]["packages"]|length == 1' \
'.deployments[0]["requested-packages"]|length == 1' \
'.deployments[0]["requested-local-packages"]|length == 1' \
'.deployments[0]["base-local-replacements"]|length == 1' \
'.deployments[0]["regenerate-initramfs"]|not'
vm_rpmostree cleanup -p
echo "ok reset initramfs"
# all together now
vm_rpmostree ex reset
vm_assert_status_jq \
'.deployments[0]["packages"]|length == 0' \
'.deployments[0]["requested-packages"]|length == 0' \
'.deployments[0]["requested-local-packages"]|length == 0' \
'.deployments[0]["base-local-replacements"]|length == 0' \
'.deployments[0]["regenerate-initramfs"]|not'
vm_rpmostree cleanup -p
echo "ok reset EVERYTHING"
# reset everything and overlay at the same time
vm_build_rpm a-new-package
vm_rpmostree ex reset --install a-new-package
vm_assert_status_jq \
'.deployments[0]["packages"]|length == 1' \
'.deployments[0]["packages"]|index("a-new-package") >= 0' \
'.deployments[0]["requested-packages"]|length == 1' \
'.deployments[0]["requested-local-packages"]|length == 0' \
'.deployments[0]["base-local-replacements"]|length == 0' \
'.deployments[0]["regenerate-initramfs"]|not'
echo "ok reset --install"