sysupdate: Support major OS upgrades#33706
Conversation
51866c2 to
1c0f395
Compare
128229b to
47a8345
Compare
Right now components aren't particularly well documented. Let's make the feature a bit more visible.
Overriding settings of systemd-sysupdate is quite dangerous - OS vendor might make a change that is incompatible with the settings in /etc, and unlike most other config incompatibilities this has the potential to accidentally wipe the wrong partition during an update. Not good. So let's warn admins.
Basically, distros that maintain more than one release stream (i.e. multiple stable versions, a beta channel, etc) can put the others' transfer definitions into /usr/lib/sysupdate@$STREAM.d/, and the admin can pass --stream= on the CLI to switch to this new stream. Part of systemd#33345 SQUASHME: s/--next/--streams=<stream>/
47a8345 to
3e2b6fd
Compare
| <para>System Administrators must take <emphasis>extreme</emphasis> care when overriding any transfer or | ||
| optional feature definitions, other than to turn on or off features! | ||
| As with any configuration defined in <filename>/usr</filename> and overridden in | ||
| <filename>/etc</filename>, an update to the host system can break the administrator overrides. |
There was a problem hiding this comment.
we typically suffix dirs with / in our docs. i.e. /usr → /usr/ and /etc → /etc/. It conveys a tiny bit of additional information to readers.
| partition. | ||
| Distributions must take care to avoid breaking systems where overrides exist only to turn on or off | ||
| optional features; supporting (or choosing not to) everything else is up to distribution policy. | ||
| <emphasis>You have been warned.</emphasis></para> |
There was a problem hiding this comment.
i am fine with warning, but I find this a bit too strong. i.e. the "extreme" and stuff is a bit too much.
What about this: let's use docbook's native constructs for this. i.e. <caution><title>Warning!</title><para>…</para></caution>
And then remove the <emphasis>extreme</emphasize> and the `You have been warned.
or in otherwords, let the typesetter solve this problem, not the text contents so much.
By toning this a bit down but at the same time offsetting this a bit from the rest of the text I think we get the message across quite well and appear a bit more professional I guess ;-)
| @@ -190,6 +190,17 @@ | |||
| <xi:include href="version-info.xml" xpointer="v251"/></listitem> | |||
There was a problem hiding this comment.
the commit msg has some "SQUASHME" thing in it
| and have corresponding override directories for administrators (i.e. | ||
| <filename>/etc/sysupdate.<replaceable>component</replaceable>.d/</filename>, etc).</para> | ||
|
|
||
| <para>Some distributions may wish to maintain multiple update "streams" at a time, for example to offer |
There was a problem hiding this comment.
maybe call this "release streams" instead of just "streams"?
| a beta/nightly update channel, or to distribute security updates to multiple major versions at a time. | ||
| Users of such distributions may wish to remain on their current stream, and switch streams at some future | ||
| point in time. | ||
| A distribution with multiple update streams should ship the transfer definitions for each stream in the |
There was a problem hiding this comment.
i figure there are a bunch of </para><para> missing here.
| the search logic for transfer definitions to look in | ||
| <filename>/usr/lib/sysupdate@<replaceable>stream</replaceable>.d/</filename> and | ||
| <filename>/var/cache/systemd/sysupdate@<replaceable>stream</replaceable>.d/</filename> instead of | ||
| <filename>/usr/lib/sysupdate.d</filename>. |
There was a problem hiding this comment.
as mentioned elsewhere, please suffix the path with /
| <term><option>streams</option></term> | ||
|
|
||
| <listitem><para>Lists streams that can be updated. This enumerates the | ||
| <filename>/var/cache/systemd/sysupdate@*.d/</filename> and <filename>/usr/lib/sysupdate@*.d/</filename> |
There was a problem hiding this comment.
Yeah. It's something that needs to be cleaned up and go away after the OS update. It's not supposed to be persistent. Frankly, maybe I need to build in the IMAGE_VERSION into the path to make sure that it's not considered anymore after an upgrade. So something like /var/cache/$IMAGE_VERSION/systemd/sysudpate@*.d/, and then we can have a tmpfile rule that cleans those up based on age.
|
hmm, i am not too much of a fan of this model tbh. hmm, wouldn#t it be nicer if we'd model this much closer to the features model. i.e.:
|
The whole point of having separate release streams is that you have distinct transfer definitions for each stream. Different update URLs. Possibly different servers. Different delta updates (nightlies might not have deltas). And so on. A stream is a different place you can get different updates from. So in practice, there will be no sharing of transfers between streams. So ultimately you're asking that this: turns into this: To me that's a lot more complicated to understand, and for unclear benefit. Another wrench in the works: features will vary between streams too! They may appear or they may disappear between updates. I'm not sure of the best way to represent that. Maybe a feature that has no transfer definitions (for a given stream) just doesn't exist on that stream? Or the features themselves need a And one more wrench in the works: how are we supposed to handle streams for sysupdate components? Components don't have their own streams; they use the host's streams (since the whole component definition is replaced when you switch to a different stream). Defining streams inside of the sysupdate.d/ directory opens that can of worms, because it enables you to define streams in sysupdate.$component.d/. I guess the solution is to just bail if the component has stream definitions? Why not just make the situation un-representable in the first place?
I think I like the idea of defining a .stream file, but not necessarily for the purposes of putting all streams together into a single directory. There is some metadata that we've shoehorned into transfer definitions that really doesn't belong there. Specifically: appstream metadata, and the changelog. Right now, we put that into the transfers because we had nowhere else. But if we define these .stream files, we could put that metadata in there. Then we'll always return just one appstream URL or just one changelog URL via the DBus API. We'd just have a "one-.stream-file-per-directory" rule. An alternate idea:Maybe we can also let .stream files carry the defaults for the This would make me a lot more open to the single-directory idea, because it would enable us to share all the .transfer files between all of the streams. This is kinda similar to what I was hoping to implement over on the packaging side: I was going to have a single shared collection of .transfer files with templating in them, and then each stream would be a collection of values to place in there. Putting the functionality directly into sysupdate removes the templating step. However it doesn't solve all problems. For one, it doesn't solve what to do with features, nor does it solve the components issue. It also introduces its own problems: it wouldn't allow different streams to have different sets of .transfer files (maybe some streams drop additional files next to the UKI on the ESP, but others don't!). Transfers don't necessarily all pull from the network either (maybe you have a mix of url-file and local-file transfers, though I can't think of a real use-case for this) - how do we handle that? Ultimately, I think having individual directories per stream is most flexible. GNOME OS might not need quite so much flexibility and we could get away without it, but others might not have it so lucky.
I don't think we should allow redefining which stream default.stream is pointing to. Allowing this makes switching streams non-atomic: first you have to update the symlink in /etc, and then you need to actually apply the update. Things can go bad in between there. It's also possible for streams to be empty; the existence of a stream doesn't imply that there are updates available there. We could release GNOME OS 47 with a GNOME OS 48 stream already baked in, before any GNOME OS 48 release has been made. If the user tries tries to switch to the 48 stream, they'll first have to redefine If, on top of that, the stream definition is broken and unable to actually find or apply the GNOME 48 updates, this user will never get the patch to fix the broken definitions, and they'll never get any more updates on this system. They'd have to know to redirect Ultimately, switching streams switches the contents of /usr, and thus replaces /usr/lib/sysupdate.d/default.stream; so the active stream is always the one in /usr and that's what we must rely on to make this atomic. The one situation I can think of where a symlink makes sense is when two different streams are actually the exact same stream, and the user wants to pick which one they'd like to keep using if the streams diverge. Let's say that we're on GNOME OS Nightly, which currently is a development snapshot of GNOME OS 48. Right now, the 48 stream and the Nightly stream are one in the same. But eventually, GNOME 48 will branch from GNOME Nightly, and the stream definitions will diverge. At that point, the symlink can be used to decide which one the user intended to stay on: 48 or nightly. I don't know if supporting this use-case is worth the footguns the symlink introduces...
Ultimately I think this is what I dislike the most about the single-directory idea. I don't mind a single directory if transfers take some of their settings from the stream definition and all streams share the same transfers. But if we're going to have stream-specific transfer definitions I see no reason to put them all into one directory. |
Many distributions have multiple update streams. For instance, Fedora has:
This PR makes sysupdate aware of this functionality, so that this situation can be represented. Update streams are defined by the OS vendor by creating
/usr/lib/sysupdate@<stream>.d/with transfer and optional feature definitions. You can switch streams viasystemd-sysupdate --stream=<stream>Switching the stream replaces the /usr partition, and thus will bring new stream definitions. Effectively, you can think of
/usr/lib/sysupdate.d/as the "current" stream (which is anonymous as far as the system is concerned), and all of/usr/lib/sysupdate@*.d/as streams you can switch to. Thus: each /usr partition in each stream should define available streams to switch to. This gives the distributor lots of flexibility. For instance, let's say you're on Fedora 40 (thef40stream) and switch torawhide, which will effectively upgrade the system past the Fedora 41 branchpoint. Therawhideversion of /usr will not containf40norf41streams, but will contain anf42stream. Users can switch to thef42stream to recieve updates for what will eventually become Fedora 42, but they cannot downgrade to Fedora 41 or 40. Oncef42branches off ofrawhide, then the stream can be removed fromrawhide, removing the upgrade path.Streams have strange config load paths. They're loaded from
/usr/lib/sysupdate@<stream>.d/, but then administrator overrides come from/etc/sysupdate.d/. This seems strange, but it's implemented like this to prevent footguns. Basically, if you use the transfers in/usr/lib/sysupdate@<stream>.d., then once the update is successful those transfers move to/usr/lib/sysupdate.d/. This means that the administrator overrides would be inactive while switching streams, but then activate themselves once that's done. Ultimately, this is a footgun if the administrator overrides cause problems: switching to a different stream might work fine, but the moment that's done updates may break.Streams are also loaded from
/var/cache/systemd/sysupdate@<stream>.d/. This allows for stream definitions to be dynamically downloaded from a server, instead of hard-coding them into/usr. This allows new streams to be pushed to existing installations without requiring a full OS upgrade.This will be hooked into sysupdated and updatectl in subsequent PRs.
Partial fix of #33345