Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a "apply" (reboot) automatic update strategy #4392

Merged
merged 1 commit into from
May 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions man/rpm-ostreed.conf.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,22 @@ Boston, MA 02111-1307, USA.
<term><varname>AutomaticUpdatePolicy=</varname></term>

<listitem>
<para>Controls the automatic update policy. Currently "none", "check", or "stage".
<para>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 <command>rpm-ostree status</command>. Defaults to
"none". The <citerefentry><refentrytitle>rpm-ostreed-automatic.timer</refentrytitle><manvolnum>8</manvolnum></citerefentry>
unit determines the actual frequency of updates.</para>
<para>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
<para>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 <literal>ostree-finalize-staged.service</literal> systemd unit.
</para>
<para>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 <literal>systemd-inhibit bash</literal>; exiting the shell will lift the inhibitor.
</para>
</listitem>
</varlistentry>
<varlistentry>
Expand Down
20 changes: 13 additions & 7 deletions src/daemon/rpmostreed-os.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/libpriv/rpmostree-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/libpriv/rpmostree-util.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down
17 changes: 13 additions & 4 deletions tests/kolainst/destructive/container-image
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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