diff --git a/man/rpm-ostreed.conf.xml b/man/rpm-ostreed.conf.xml index f06e83bb39..418c60abf4 100644 --- a/man/rpm-ostreed.conf.xml +++ b/man/rpm-ostreed.conf.xml @@ -71,15 +71,22 @@ Boston, MA 02111-1307, USA. AutomaticUpdatePolicy= - Controls the automatic update policy. Currently "none", "check", or "stage". + Controls the automatic update policy. Currently "none", "check", "stage", "apply". "none" disables automatic updates. "check" downloads just enough metadata to check for updates and display them in rpm-ostree status. Defaults to "none". The rpm-ostreed-automatic.timer8 unit determines the actual frequency of updates. - Finally, the "stage" policy downloads and unpacks the update, performing - any package layering. Only a small amount of work is left to be performed at + The "stage" policy downloads and unpacks the update, queuing it for the next boot. + This leaves initiating a reboot to other automation tools. + Only a small amount of work is left to be performed at shutdown time via the ostree-finalize-staged.service systemd unit. + Finally, the "apply" policy will currently always initiate a reboot. However, + in the future it may apply userspace-only fixes without a physical reboot. + Any reboots initiated via rpm-ostree will default to honoring active systemd inhibitors. + For example, to temporarily suppress automatic "apply" updates while debugging a system, + you can use systemd-inhibit bash; exiting the shell will lift the inhibitor. + diff --git a/src/daemon/rpmostreed-os.cxx b/src/daemon/rpmostreed-os.cxx index 8b15159ba4..8137fdd4cf 100644 --- a/src/daemon/rpmostreed-os.cxx +++ b/src/daemon/rpmostreed-os.cxx @@ -725,6 +725,13 @@ os_handle_automatic_update_trigger (RPMOSTreeOS *interface, GDBusMethodInvocatio } } + /* if output-to-self is not explicitly set, default to TRUE */ + g_autoptr (GVariant) arg_options_owned = NULL; + if (!g_variant_dict_contains (&dict, "output-to-self")) + { + g_variant_dict_insert (&dict, "output-to-self", "b", TRUE); + } + /* Now we translate policy into flags the deploy transaction understands. But avoid * starting it at all if we're not even on. The benefit of this approach is that we keep * the Deploy transaction simpler. */ @@ -744,17 +751,16 @@ os_handle_automatic_update_trigger (RPMOSTreeOS *interface, GDBusMethodInvocatio break; case RPMOSTREED_AUTOMATIC_UPDATE_POLICY_STAGE: break; + case RPMOSTREED_AUTOMATIC_UPDATE_POLICY_APPLY: + // For now, we always reboot for any change. In the future, we may start e.g. detecting + // the case where there are no kernel changes, and doing a fast userspace apply via systemd. + g_variant_dict_insert (&dict, "reboot", "b", TRUE); + break; default: g_assert_not_reached (); } - /* if output-to-self is not explicitly set, default to TRUE */ - g_autoptr (GVariant) arg_options_owned = NULL; - if (!g_variant_dict_contains (&dict, "output-to-self")) - { - g_variant_dict_insert (&dict, "output-to-self", "b", TRUE); - arg_options = arg_options_owned = g_variant_ref_sink (g_variant_dict_end (&dict)); - } + arg_options = arg_options_owned = g_variant_ref_sink (g_variant_dict_end (&dict)); (void)arg_options_owned; /* Pacify static analysis */ return os_merge_or_start_deployment_txn (interface, invocation, dfault, arg_options, NULL, NULL, diff --git a/src/libpriv/rpmostree-types.h b/src/libpriv/rpmostree-types.h index 903fddd6ff..5c400f2ab3 100644 --- a/src/libpriv/rpmostree-types.h +++ b/src/libpriv/rpmostree-types.h @@ -34,6 +34,7 @@ typedef enum RPMOSTREED_AUTOMATIC_UPDATE_POLICY_NONE, RPMOSTREED_AUTOMATIC_UPDATE_POLICY_CHECK, RPMOSTREED_AUTOMATIC_UPDATE_POLICY_STAGE, + RPMOSTREED_AUTOMATIC_UPDATE_POLICY_APPLY, } RpmostreedAutomaticUpdatePolicy; typedef enum diff --git a/src/libpriv/rpmostree-util.cxx b/src/libpriv/rpmostree-util.cxx index 8ee6943d7c..7aa2a84f20 100644 --- a/src/libpriv/rpmostree-util.cxx +++ b/src/libpriv/rpmostree-util.cxx @@ -1031,6 +1031,8 @@ rpmostree_auto_update_policy_to_str (RpmostreedAutomaticUpdatePolicy policy, GEr return "check"; case RPMOSTREED_AUTOMATIC_UPDATE_POLICY_STAGE: return "stage"; + case RPMOSTREED_AUTOMATIC_UPDATE_POLICY_APPLY: + return "apply"; default: return (char *)glnx_null_throw (error, "Invalid policy value %u", policy); } @@ -1047,6 +1049,8 @@ rpmostree_str_to_auto_update_policy (const char *str, RpmostreedAutomaticUpdateP *out_policy = RPMOSTREED_AUTOMATIC_UPDATE_POLICY_CHECK; else if (g_str_equal (str, "stage") || g_str_equal (str, "ex-stage") /* backcompat */) *out_policy = RPMOSTREED_AUTOMATIC_UPDATE_POLICY_STAGE; + else if (g_str_equal (str, "apply")) + *out_policy = RPMOSTREED_AUTOMATIC_UPDATE_POLICY_APPLY; else return glnx_throw (error, "Invalid value for AutomaticUpdatePolicy: '%s'", str); return TRUE; diff --git a/tests/kolainst/destructive/container-image b/tests/kolainst/destructive/container-image index 598fbef52a..e1358e0b1c 100755 --- a/tests/kolainst/destructive/container-image +++ b/tests/kolainst/destructive/container-image @@ -183,11 +183,20 @@ EOF ! rpm -q nano rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:derived\"" + # We'll test the "apply" automatic updates policy here + systemctl stop rpm-ostreed + cp /usr/etc/rpm-ostreed.conf /etc + echo -e "[Daemon]\nAutomaticUpdatePolicy=apply" > /etc/rpm-ostreed.conf + rpm-ostree reload + # Now revert back to the base image, but keep our layered package foo rm "${image_dir}" -rf - skopeo copy containers-storage:localhost/fcos ${image}:latest - rpm-ostree rebase ostree-unverified-image:${image}:latest - /tmp/autopkgtest-reboot 4 + timeout 5m skopeo copy containers-storage:localhost/fcos ${image}:derived + /tmp/autopkgtest-reboot-prepare 4 + cursor=$(journalctl -o json -n 1 | jq -r '.["__CURSOR"]') + systemctl start --no-block rpm-ostreed-automatic.service + echo "Blocking for reboot initiation" + journalctl --after-cursor="$cursor" -f -u rpm-ostreed ;; 4) # This should carry over @@ -198,7 +207,7 @@ EOF fatal "found $p" fi done - rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:latest\"" + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:derived\"" ;; *) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;; esac