diff --git a/src/app/rpmostree-builtin-initramfs.c b/src/app/rpmostree-builtin-initramfs.c index d0d4952c85..110b285e7d 100644 --- a/src/app/rpmostree-builtin-initramfs.c +++ b/src/app/rpmostree-builtin-initramfs.c @@ -34,6 +34,7 @@ static gboolean opt_enable; static gboolean opt_disable; static char **opt_add_arg; static gboolean opt_reboot; +static gboolean opt_lock_finalization; static GOptionEntry option_entries[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" }, @@ -41,6 +42,7 @@ static GOptionEntry option_entries[] = { { "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 }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -136,6 +138,7 @@ rpmostree_builtin_initramfs (int argc, 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; diff --git a/src/app/rpmostree-builtin-kargs.c b/src/app/rpmostree-builtin-kargs.c index fcfb727a2d..ce84c78cc4 100644 --- a/src/app/rpmostree-builtin-kargs.c +++ b/src/app/rpmostree-builtin-kargs.c @@ -35,6 +35,7 @@ static char **opt_kernel_append_strings; static char **opt_kernel_replace_strings; static char *opt_osname; static char *opt_deploy_index; +static gboolean opt_lock_finalization; static GOptionEntry option_entries[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operation on provided OSNAME", "OSNAME" }, @@ -45,6 +46,7 @@ static GOptionEntry option_entries[] = { { "delete", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_delete_strings, "Delete a specific kernel argument key/val pair or an entire argument with a single key/value pair", "KEY=VALUE"}, { "import-proc-cmdline", 0, 0, G_OPTION_ARG_NONE, &opt_import_proc_cmdline, "Instead of modifying old kernel arguments, we modify args from current /proc/cmdline (the booted deployment)", NULL }, { "editor", 0, 0, G_OPTION_ARG_NONE, &opt_editor, "Use an editor to modify the kernel arguments", NULL }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -265,6 +267,7 @@ rpmostree_builtin_kargs (int argc, 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)); if (opt_editor) diff --git a/src/app/rpmostree-builtin-rebase.c b/src/app/rpmostree-builtin-rebase.c index 6046ef9ee4..71c40533dd 100644 --- a/src/app/rpmostree-builtin-rebase.c +++ b/src/app/rpmostree-builtin-rebase.c @@ -42,6 +42,7 @@ static gboolean opt_cache_only; static gboolean opt_download_only; static gboolean opt_experimental; static gboolean opt_disallow_downgrade; +static gboolean opt_lock_finalization; static GOptionEntry option_entries[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" }, @@ -55,6 +56,7 @@ static GOptionEntry option_entries[] = { { "custom-origin-url", 0, 0, G_OPTION_ARG_STRING, &opt_custom_origin_url, "Machine-readable description of custom origin", NULL }, { "experimental", 0, 0, G_OPTION_ARG_NONE, &opt_experimental, "Enable experimental features", NULL }, { "disallow-downgrade", 0, 0, G_OPTION_ARG_NONE, &opt_disallow_downgrade, "Forbid deployment of chronologically older trees", NULL }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -168,6 +170,7 @@ rpmostree_builtin_rebase (int argc, g_variant_dict_insert (&dict, "download-only", "b", opt_download_only); g_variant_dict_insert (&dict, "skip-purge", "b", opt_skip_purge); g_variant_dict_insert (&dict, "initiating-command-line", "s", invocation->command_line); + g_variant_dict_insert (&dict, "lock-finalization", "b", opt_lock_finalization); if (opt_custom_origin_url) { if (!opt_custom_origin_description) diff --git a/src/app/rpmostree-builtin-reset.c b/src/app/rpmostree-builtin-reset.c index c24a4e1b4d..d962083115 100644 --- a/src/app/rpmostree-builtin-reset.c +++ b/src/app/rpmostree-builtin-reset.c @@ -35,6 +35,7 @@ static gboolean opt_reboot; static gboolean opt_overlays; static gboolean opt_overrides; static gboolean opt_initramfs; +static gboolean opt_lock_finalization; static GOptionEntry option_entries[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" }, @@ -42,6 +43,7 @@ static GOptionEntry option_entries[] = { { "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 }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -101,6 +103,7 @@ rpmostree_builtin_reset (int argc, g_variant_dict_insert (&dict, "no-initramfs", "b", opt_initramfs); g_variant_dict_insert (&dict, "cache-only", "b", cache_only); 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)); if (!rpmostree_update_deployment (os_proxy, NULL, NULL, install_pkgs, uninstall_pkgs, diff --git a/src/app/rpmostree-override-builtins.c b/src/app/rpmostree-override-builtins.c index 50e132e928..7a555e2e22 100644 --- a/src/app/rpmostree-override-builtins.c +++ b/src/app/rpmostree-override-builtins.c @@ -33,11 +33,13 @@ static const char *const *opt_remove_pkgs; static const char *const *opt_replace_pkgs; static const char *const *install_pkgs; static const char *const *uninstall_pkgs; +static gboolean opt_lock_finalization; 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 operation is complete", NULL }, { "dry-run", 'n', 0, G_OPTION_ARG_NONE, &opt_dry_run, "Exit after printing the transaction", NULL }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -83,6 +85,7 @@ handle_override (RPMOSTreeSysroot *sysroot_proxy, g_variant_dict_insert (&dict, "dry-run", "b", opt_dry_run); g_variant_dict_insert (&dict, "no-overrides", "b", opt_reset_all); 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_autoptr(GVariant) previous_deployment = rpmostree_os_dup_default_deployment (os_proxy); diff --git a/src/app/rpmostree-pkg-builtins.c b/src/app/rpmostree-pkg-builtins.c index 623ab96cda..87576a493e 100644 --- a/src/app/rpmostree-pkg-builtins.c +++ b/src/app/rpmostree-pkg-builtins.c @@ -40,6 +40,7 @@ static gboolean opt_download_only; static gboolean opt_allow_inactive; static gboolean opt_uninstall_all; static gboolean opt_unchanged_exit_77; +static gboolean opt_lock_finalization; static GOptionEntry option_entries[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Operate on provided OSNAME", "OSNAME" }, @@ -48,6 +49,7 @@ static GOptionEntry option_entries[] = { { "allow-inactive", 0, 0, G_OPTION_ARG_NONE, &opt_allow_inactive, "Allow inactive package requests", NULL }, { "idempotent", 0, 0, G_OPTION_ARG_NONE, &opt_idempotent, "Do nothing if package already (un)installed", NULL }, { "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no overlays were changed, exit 77", NULL }, + { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { NULL } }; @@ -97,6 +99,7 @@ pkg_change (RpmOstreeCommandInvocation *invocation, g_variant_dict_insert (&dict, "no-layering", "b", opt_uninstall_all); g_variant_dict_insert (&dict, "idempotent-layering", "b", opt_idempotent); 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)); gboolean met_local_pkg = FALSE; diff --git a/src/daemon/rpmostreed-transaction-types.c b/src/daemon/rpmostreed-transaction-types.c index 62292c0056..5a6048f808 100644 --- a/src/daemon/rpmostreed-transaction-types.c +++ b/src/daemon/rpmostreed-transaction-types.c @@ -1735,8 +1735,12 @@ initramfs_state_transaction_execute (RpmostreedTransaction *transaction, rpmostree_transaction_set_title ((RPMOSTreeTransaction*)self, command_line ?: "initramfs"); + RpmOstreeSysrootUpgraderFlags upgrader_flags = 0; + if (vardict_lookup_bool (self->options, "lock-finalization", FALSE)) + upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_LOCK_FINALIZATION; + g_autoptr(RpmOstreeSysrootUpgrader) upgrader = - rpmostree_sysroot_upgrader_new (sysroot, self->osname, 0, cancellable, error); + rpmostree_sysroot_upgrader_new (sysroot, self->osname, upgrader_flags, cancellable, error); if (upgrader == NULL) return FALSE; @@ -2426,6 +2430,8 @@ kernel_arg_transaction_execute (RpmostreedTransaction *transaction, /* don't want to pull new content for this */ upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_SYNTHETIC_PULL; upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGCACHE_ONLY; + if (vardict_lookup_bool (self->options, "lock-finalization", FALSE)) + upgrader_flags |= RPMOSTREE_SYSROOT_UPGRADER_FLAGS_LOCK_FINALIZATION; rpmostree_transaction_set_title ((RPMOSTreeTransaction*)self, command_line ?: "kargs"); diff --git a/tests/vmcheck/test-misc-2.sh b/tests/vmcheck/test-misc-2.sh index 5a458ba876..7577902108 100755 --- a/tests/vmcheck/test-misc-2.sh +++ b/tests/vmcheck/test-misc-2.sh @@ -35,7 +35,14 @@ cursor=$(vm_get_journal_cursor) vm_reboot assert_streq "$(vm_get_booted_csum)" "${booted_csum}" vm_assert_journal_has_content $cursor 'Not finalizing; found /run/ostree/staged-deployment-locked' -echo "ok locked staging" +echo "ok locked deploy staging" +vm_rpmostree rebase :"${commit}" --lock-finalization --skip-purge +vm_cmd test -f /run/ostree/staged-deployment-locked +cursor=$(vm_get_journal_cursor) +vm_reboot +assert_streq "$(vm_get_booted_csum)" "${booted_csum}" +vm_assert_journal_has_content $cursor 'Not finalizing; found /run/ostree/staged-deployment-locked' +echo "ok locked rebase staging" vm_rpmostree deploy revision="${commit}" --lock-finalization vm_cmd test -f /run/ostree/staged-deployment-locked