Hi folks! openQA caught a subtle issue in a systemd update over the
weekend, and I thought it would be worth flagging up here both to let
people know about it and also to see if anyone has a better solution
than the one I came up with.

The issue affects this systemd update for F32:
https://bodhi.fedoraproject.org/updates/FEDORA-2020-dd43dd05b1
that update provides systemd-245.6-1.fc32 . The stable release of
Fedora 32 contains systemd-245.4-1.fc32.

A key factor here is that, for any given Fedora release, the packages
that made up that release at the time it was initially released will
always be available to DNF, in the repository called 'fedora'. This
repository maps to the "frozen" release tree; for Fedora 32, for
instance, it maps to
https://dl.fedoraproject.org/pub/fedora/linux/releases/32/Everything/ .
If we release with foo-1.0-1, then send out foo-1.0-2 and then foo-1.0-
3 as updates, then when 1.0-3 goes stable, 1.0-2 is no longer visible
to DNF, because 1.0-3 replaced it in the 'updates' repository...but
1.0-1 is *always* visible to DNF, because it is in the 'fedora'
repository, and that repository never changes.

So the bug openQA caught is that, with the systemd update available,
upgrading from Fedora 31 to Fedora 32 no longer works if the package
u2f-hidraw-policy is installed. You can see the failure here:
https://openqa.fedoraproject.org/tests/608480#step/upgrade_run/54

On further investigation, I found the "culprit" is ultimately this
commit:
https://src.fedoraproject.org/rpms/systemd/c/80532792aa6f988d34f18ce1ffdfa992be9cb402?branch=master
which happened between 245.4-1.fc32. and 245.6-1.fc32. Before
that commit, the subpackage 'systemd' Obsoletes: u2f-hidraw-policy .
After that commit, the obsolete is moved to the 'systemd-udev'
subpackage. So systemd-245.4-1.fc32 Obsoletes: u2f-hidraw-policy ,
and so does systemd-udev-245.6-1.fc32 .

Now, as I noted above, 245.4-1.fc32 is in the frozen 'fedora' repo for
F32, so systemd-245.4-1.fc32 is always available to DNF. With this
update in play, systemd-udev-245.6-1.fc32 is also available to DNF.

Another factor here is that DNF's behaviour when multiple different
available packages obsolete an installed package on update is 'greedy'.
If 'bar', 'moo' and 'meep' all obsolete 'foo' and are available on
update, DNF will try to install *all three*. This is intentional and
necessary when e.g. a package is split in two and we want both the new
packages to be installed in place of the old one. (If it's just
multiple available versions of the *same* package that all obsolete an
installed package, DNF will simply try to select the newest one as part
of the update, which is fine).

So what DNF does when we try to upgrade is try to include *both*
systemd-245.4-1.fc32 and systemd-udev-245.6-1.fc32 in the operation,
because it sees both as available, F32 packages that obsolete an
installed package. And that blows up because of obvious dependency
problems (systemd-udev-245.6-1.fc32 requires systemd-245.6-1.fc32, but
we can't install both systemd-245.4-1.fc32 and systemd-245.6-1.fc32 at
the same time).

It was actually a bit tricky to come up with a solution for this. I
hacked up a minimal reproducer with empty packages, and experimented a
bit, and the solution I was able to find that works is to have systemd-
udev Obsoletes: systemd < 245.6-1. This seems to correctly clue DNF in
to the situation and cause it to leave out anything from 245.4-1.fc32
in the upgrade.

I was worried that if you had u2f-hidraw-policy and systemd installed,
but not systemd-udev, this Obsoletes: might lead to systemd-udev
getting installed on upgrade. However, it does not seem to: DNF is
happy just updating systemd to 245-6.1.fc32, which is not obsoleted by
the same-versioned systemd-udev, correctly realizing that this
satisfies all constraints and it doesn't need to pull in systemd-udev.

Another possible solution that would I guess work but be kinda finicky
would be to update u2f-hidraw-policy in F31 to 1.0.2-40.fc31, and then
bump the Obsoletes: in systemd-udev to < 1.0.2-50. That would
effectively "disarm" the `Obsoletes: u2f-hidraw-policy < 1.0.2-40` in
systemd-245.4-1.fc32. This fix would rely on people updating their F31
install before upgrading to F32, though (which we always say you're
supposed to do, but of course some people don't).

As a P.S., I've actually seen a variant of this problem before, where a
packager tried to "remove" an Obsoletes: with an update - that didn't
really work, because the Obsoletes: was still present in the version of
the package in the frozen 'fedora' repo, so removing the Obsoletes:
from a later build of the package in the 'updates' repo didn't actually
stop the other package being removed on upgrade to the release in
question. It still got removed, and replaced with the *older* version
of the 'replacement' package from the 'fedora' repo. Then on the next
`dnf update` the old version of the 'replacement' package would be
updated to the newer version from the 'updates' repo, from which the
Obsoletes: had been removed...

So, that's the story so far :) If anyone has thoughts, questions,
suggestions or concerns about my proposed fixes, please chip in! And
keep this kind of wrinkle in mind for the future :)
-- 
Adam Williamson
Fedora QA Community Monkey
IRC: adamw | Twitter: AdamW_Fedora | XMPP: adamw AT happyassassin . net
http://www.happyassassin.net
_______________________________________________
devel mailing list -- devel@lists.fedoraproject.org
To unsubscribe send an email to devel-le...@lists.fedoraproject.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org

Reply via email to