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

dnf replay broken since 5.2.10.0-71-g3de835a49 #2183

Open
mtalexan opened this issue Apr 7, 2025 · 10 comments · May be fixed by #2189
Open

dnf replay broken since 5.2.10.0-71-g3de835a49 #2183

mtalexan opened this issue Apr 7, 2025 · 10 comments · May be fixed by #2189
Labels
Priority: MEDIUM Triaged Someone on the DNF 5 team has read the issue and determined the next steps to take

Comments

@mtalexan
Copy link

mtalexan commented Apr 7, 2025

The following is defined to work, and more complex versions of it seem to be a specifically supported workflow:

dnf install --assumeyes --store=mytransaction cowsay

# disconnect from all networks

dnf replay --assumeyes mytransaction

Up to and including 5.2.10.0 of dnf5 this worked as expected, with dnf replay using the RPMs downloaded into the mytransaction/packages/ folder that are also referenced within the mytransaction/transaction.json file itself.

However in 5.2.12.0 it does not work. Instead the dnf replay command ignores that the packages are already downloaded and available and attempts to download them again fresh. dnf replay is designed to be used on air-gapped/offline systems to install transactions that had their packages downloaded with them, so this is breakage of the command.

@mtalexan
Copy link
Author

mtalexan commented Apr 7, 2025

I can verify that if I run the dnf install --assumeyes --store=mytransaction cowsay command in two different (current/near current) Fedora containers that have the same repos enabled but have dnf5 5.2.12.0 and 5.2.10.0 respectively, they produce the same transaction.json contents and populate the mytransaction/packages/ folder with the same RPMs. So this is purely a dnf replay bug.


It can also be easier to test the dnf replay command by simply disabling all the repos rather than completely cutting network. Or if you're doing it manually, just don't include the --assumeyes option and visually verify that it has 0 MB to download (or not) when it prompts you.

@mtalexan
Copy link
Author

mtalexan commented Apr 7, 2025

Version 5.2.11.0 also has the same bug as 5.2.12.0.

Tested on Fedora 41 using the available dnf5 RPMs.

`dnf --version` output for broken 5.2.12.0 (`dnf-5.2.12.0-1.fc41.x86_64`) dnf5 version 5.2.12.0 dnf5 plugin API version 2.0 libdnf5 version 5.2.12.0 libdnf5 plugin API version 2.2

Loaded dnf5 plugins:
name: builddep
version: 1.0.0
API version: 2.0

name: changelog
version: 1.0.0
API version: 2.0

name: config-manager
version: 0.1.0
API version: 2.0

name: copr
version: 0.1.0
API version: 2.0

name: needs_restarting
version: 1.0.0
API version: 2.0

name: repoclosure
version: 1.0.0
API version: 2.0

name: reposync
version: 1.0.0
API version: 2.0

`dnf --version` output for broken 5.2.11.0 (`dnf-5.2.11.0-1.fc41.x86_64`) dnf5 version 5.2.11.0 dnf5 plugin API version 2.0 libdnf5 version 5.2.11.0 libdnf5 plugin API version 2.2

Loaded dnf5 plugins:
name: builddep
version: 1.0.0
API version: 2.0

name: changelog
version: 1.0.0
API version: 2.0

name: config-manager
version: 0.1.0
API version: 2.0

name: copr
version: 0.1.0
API version: 2.0

name: needs_restarting
version: 1.0.0
API version: 2.0

name: repoclosure
version: 1.0.0
API version: 2.0

name: reposync
version: 1.0.0
API version: 2.0

`dnf --version` output for working 5.2.10.0 (`dnf-5.2.10.0-2.fc41.x86_64`) dnf5 version 5.2.10.0 dnf5 plugin API version 2.0 libdnf5 version 5.2.10.0 libdnf5 plugin API version 2.1

Loaded dnf5 plugins:
name: builddep
version: 1.0.0
API version: 2.0

name: changelog
version: 1.0.0
API version: 2.0

name: config-manager
version: 0.1.0
API version: 2.0

name: copr
version: 0.1.0
API version: 2.0

name: needs_restarting
version: 1.0.0
API version: 2.0

name: repoclosure
version: 1.0.0
API version: 2.0

name: reposync
version: 1.0.0
API version: 2.0

@ppisar
Copy link
Contributor

ppisar commented Apr 8, 2025

Technically, the --store option is only documented in dnf5-replay(8) manual at there is nothing that implies that packages are predownloaded and that dnf replay is safe to run off-line.

Practically, I understand that predownloading packages is a handy feature. I will try to find which commit broke it.

@ppisar
Copy link
Contributor

ppisar commented Apr 8, 2025

For me "dnf5 replay /tmp/foo" does not work at all since 5.2.12.0: It this it needs to download the packages and it downloads them from a wrong URL:

# cat /tmp/foo/transaction.json 
{
  "rpms":[
    {
      "nevra":"dontpanic-1.02-18.fc42.x86_64",
      "action":"Reinstall",
      "reason":"User",
      "repo_id":"rawhide",
      "package_path":".\/packages\/dontpanic-1.02-18.fc42.x86_64.rpm"
    },
    {
      "nevra":"dontpanic-1.02-18.fc42.x86_64",
      "action":"Replaced",
      "reason":"User",
      "repo_id":"@System"
    }
  ],
  "version":"1.0"
root@fedora-43:~/repos/test # dnf5 replay /tmp/foo
Updating and loading repositories:
Repositories loaded.
 https://download.copr.fedorainfracloud.org/results/rpmsoftwaremanagement/dnf-nightly/pubkey.gpg                                                                          100% |  19.0 KiB/s |   1.0 KiB |  00m00s
 https://download.copr.fedorainfracloud.org/results/dcantrell/rpminspect/pubkey.gpg                                                                                       100% |  17.7 KiB/s |   1.0 KiB |  00m00s
Package                                                                 Arch            Version                                                                 Repository                                    Size
Reinstalling:
 dontpanic                                                              x86_64          1.02-18.fc42                                                            rawhide                                   49.3 KiB
   replacing dontpanic                                                  x86_64          1.02-18.fc42                                                            @stored_transaction                       49.3 KiB

Transaction Summary:
 Reinstalling:       1 package
 Replacing:          1 package

Total size of inbound packages is 21 KiB. Need to download 21 KiB.
After this operation, 0 B extra will be used (install 49 KiB, remove 49 KiB).
Is this ok [y/N]: y
[1/1] dontpanic-0:1.02-18.fc42.x86_64                                                                                                                  0% [<=>               ] | 127.4 KiB/s |   0.0   B |  00m00s
[1/1] dontpanic-0:1.02-18.fc42.x86_64                                                                                                                                       0% |   0.0   B/s |   0.0   B |  00m00s
>>> Status code: 404 for http://ftp.fi.muni.cz/pub/linux/fedora/linux/development/rawhide/Everything/x86_64/os/tmp/foo/packages/dontpanic-1.02-18.fc42.x86_64.rpm (IP: 147.251.48.205) - http://ftp.fi.muni.cz/pub

See that it appends a path to the predonwloaded package to a mirror base URL, creating an nonexistent file.

@ppisar
Copy link
Contributor

ppisar commented Apr 8, 2025

This regression is cause with 3de835a commit ("Use actual repository ID in stored transactions"). @m-blaha, could you look at it?

I'm curious why our dnf/transaction-sr/replay.feature pass.

@m-blaha
Copy link
Member

m-blaha commented Apr 8, 2025

Thanks for investigation! I'll take a look.

@ppisar
Copy link
Contributor

ppisar commented Apr 8, 2025

I'm curious why our dnf/transaction-sr/replay.feature pass.

Because the tests fake transaction.json without package_path item.

@ppisar ppisar added Priority: MEDIUM Triaged Someone on the DNF 5 team has read the issue and determined the next steps to take labels Apr 8, 2025
@ppisar ppisar changed the title dnf replay broken between 5.2.10.0 and 5.2.12.0 dnf replay broken between 5.2.10.0 and 5.2.11.0 Apr 8, 2025
@ppisar ppisar changed the title dnf replay broken between 5.2.10.0 and 5.2.11.0 dnf replay broken since 5.2.10.0-71-g3de835a49 Apr 8, 2025
@m-blaha
Copy link
Member

m-blaha commented Apr 8, 2025

OK, it looks like we'll need some more thorough testing.

I've identified the root cause of the issue, but I'm not sure it can be fully resolved without making some trade-offs. We're now dealing with two somewhat conflicting requirements:

  1. Retain the original repository names in replayed transactions.
  2. Avoid adding RPM files to regular repositories (i.e., any repository that isn't of type Repo::Type::COMMANDLINE).

This isn't a problem for offline transactions, since the offline command only creates COMMANDLINE repositories and doesn't have any AVAILABLE ones configured.
However, stored transactions - as per the documentation - can include not just pre-downloaded RPM files, but also packages from existing repositories. And that's where the complexity arises.

Let's take an example:

Suppose I run dnf install --store=mytransaction cowsay. The transaction is resolved and saved, and the cowsay package is downloaded from the fedora repository and stored under mytransaction/packages.

Then I run dnf replay mytransaction. DNF processes the stored transaction and finds that cowsay originally came from the fedora repository. So what should it do?

  • To retain the original repository name (fedora), it would need to add the cowsay RPM file to the existing regular fedora repo. But that repo isn't of type COMMANDLINE.
  • Alternatively, it could create a stored_transaction repo of type COMMANDLINE and place the package there - this is what version 5.2.10.0 did.

One possible solution might be to use a stored_transaction repository whenever the required original repository is not of type COMMANDLINE.
The downside is that commands like dnf repoquery --installed cowsay --queryformat="%{full_nevra} %{from_repo}" would then report the origin repository as stored_transaction (which is kind of true).

The other option is to allow RPM files to be added to AVAILABLE repositories - but there doesn't seem to be a consensus on this within the team.

It's also possible to not allow repository packages in the stored transaction, only downloaded RPM files. Then the situation would be similar to the offline command.

m-blaha added a commit that referenced this issue Apr 9, 2025
If there's an existing repository in the sack with a type different than
Repo::Type::COMMANDLINE, it cannot be used to add an RPM file.

In such cases, fall back to using STORED_TRANSACTION_NAME as the
repository ID instead.

Resolves: #2183
@kontura
Copy link
Contributor

kontura commented Apr 9, 2025

So what should it do?

In general this seems quite subtle to me, and I don't really have a strong preference here.

One possible solution might be to use a stored_transaction repository whenever the required original repository is not of type COMMANDLINE.
The downside is that commands like dnf repoquery --installed cowsay --queryformat="%{full_nevra} %{from_repo}" would then report the origin repository as stored_transaction (which is kind of true).

It is kind of true but when the package replay (transaction.json) contains repo_id value I believe it is more user friendly to make sure the from_repo is set to the repo_id.

I came up with one more possibility: create a new COMMANDLINE repo with given repo_id even if AVAILABLE repo of that repo_id already exists. This means that for that transaction repo_id is no longer unique identifier. I am not sure what kind of problems this could cause, I did test it out (only very quickly) and it seemed to work fine.

It's also possible to not allow repository packages in the stored transaction, only downloaded RPM files. Then the situation would be similar to the offline command.

This seems like the cleanest solution but we loose some functionality. dnf CLI currently cannot create such a stored transaction and although it is possible on the API it is marked as experimental so we might be able to change it if we decide to?

@m-blaha
Copy link
Member

m-blaha commented Apr 9, 2025

I came up with one more possibility: create a new COMMANDLINE repo with given repo_id even if AVAILABLE repo of that repo_id already exists. This means that for that transaction repo_id is no longer unique identifier. I am not sure what kind of problems this could cause, I did test it out (only very quickly) and it seemed to work fine.

He, I actually implemented this by mistake when preparing draft #2189 . I was surprised that it works :)
Anyway, I do not like this much, I always thought about repository ID as a unique identifier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority: MEDIUM Triaged Someone on the DNF 5 team has read the issue and determined the next steps to take
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants