[systemd-devel] Running packagekitd on shutdown

Lennart Poettering lennart at poettering.net
Tue Aug 23 17:04:23 PDT 2011


On Tue, 23.08.11 16:18, Richard Hughes (hughsient at gmail.com) wrote:

> Hello list, hello again Lennart,

Heya,

(just a couple of ideas I already uttered on IRC, just for the sake of
archiving and in case other folks are interested too..)
> 
> I'm trying to make the update experience in GNOME 3.2 much better; at
> the moment updating core services and libraries whilst everything is
> running is quite unpredictable and we really just want to update stuff
> like systemd, dbus and libc in shutdown when the system is in a known
> and quiet state.

Updating libc, dbus, systemd and so on from within the system is
probably always a bad idea. I'd very much prefer if we could do this
from an external environment, for example a rescue partition (like MacOS
does it) or even initrd. I think the way to go is to have a rescue
partition by default, but I see problems pushing that through.

I'd very much prefer if we could do the next best thing though to having
a rescue partition: do the upgrades on boot, not shutdown, i.e. in a
fully reset execution environment, no inheriting any kind of
configuration from an already running system.


> The UI we're going for can be seen in
> https://live.gnome.org/GnomeOS/Design/Whiteboards/SoftwareUpdates?action=AttachFile&do=get&target=SoftwareUpdates.png
> 
> So, basically I want to run packagekitd and use plymouth to show the
> shutdown status. I'm guessing I need to add a
> file/lib/systemd/system/poweroff.target.wants/packagekit-updates.service
> which has:

Hmm, this would be executed in parallel with other stuff which we want
to avoid. And I believe in upgrade-on-boot more than in
upgrade-on-shutdown (as mentioned).

> Note: packagekitd-shutdown will *only* be run if the user chooses the
> "Shutdown and install updates" option from the user menu (rather than
> 'Suspend') and if the updates have already been downloaded and put in
> the system cache. The packagekitd-shutdown process really only does
> the bare metal update part which is really quite quick unless you're
> updating 100's of packages.

Yupp, having user input before this is done is definitely a good idea
though I figure for university workstation setups you probably want
input-less upgrades too.

> Am I or the right lines, or am I on crack? systemd is still very magic
> to me. Thanks.

So if we go forward with this, this is what I'd like to see:

We define a new target "upgrade.target" or so which we can boot into,
instead of the usual "multi-user.target" or "graphical.target". When we
boot into this target we'd do all necessary upgrades and then simply
reboot again into the normal system.

Via a generator binary we'd dynamically at boot-time decide whether we
should boot into a normal system or into this upgrade target. Generators
are simple binaries systemd executes at very early boot which can
generate configuration from other configuration. For example, there's
currently a generator that translates /etc/crypttab into appropriate
units. That way we can dynamically extend the systemd unit tree without
having to patch systemd. So the idea would be that this upgrade
generator would override default.target (which decides what to boot into
and usually poitns to graphical.target/multi-user.target) in /run under
the condition that there's an upgrade pack waiting in
/var/lib/uprgade-packs/ or so.

This would be reasonably nice, and probably as good as we can do it
without a proper recovery partition.

However, there are a couple of caveats: since the generators are called
very very early at boot /var might not be around yet. So maybe the
upgrade packs should be placed somewhere in the rootfs (or in /boot?
that might be a good idea actually if it fits...). Split-off /var is
nothing we can get rid of, and makes a lot of sense to support.

And on kernel upgrades we*d have to reboot twice. Which is probably not
bad, given that MacOS does that too sometimes.

Soo yupp, If this is the way to go, all we'd have to do is:

1. Write this generator, which would be a tiny C program:

   if (!dir_is_empty("/boot/upgrade-packs") 
         symlink("/lib/systemd/system/upgrade.target", "/run/systemd/system/default.target");

2. Write upgrade.target:

   [Unit]
   Description=Upgrade mode
   Requires=basic.target
   Conflicts=rescue.service rescue.target
   After=basic.target rescue.service rescue.target
   AllowIsolate=yes

3. Write pk-upgrade.service or so:

   [Unit]
   Description=PK Upgrade
   
   [Service]
   ExecStart=/usr/bin/pk-upgrade

4. Write pk-upgrade.c:

   do_some_upgrades();
   remove_upgrade_packs("/boot/upgrade-packs");
   invoke_dbus_systemd_reboot();

Done!

I wonder if we should standardize step #2 in systemd itself, so that
this becomes a well known target or so. So that other folks can use that
too, for example if people use scripted upgrades or so (this usecase has
come up before on the ML, so maybe we should standardize this...). Or
maybe we shouldn't standardize this since only a recovery partition is
the correct way to handle this.

Lennart

-- 
Lennart Poettering - Red Hat, Inc.


More information about the systemd-devel mailing list