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
Resolve rpm (rich) dependencies via libsolv #1122
Conversation
|
Hello @dparalen! Thanks for updating the PR. Cheers ! There are no PEP8 issues in this Pull Request. 🍻 Comment last updated on July 16, 2018 at 16:39 Hours UTC |
28aa4c2
to
0bf8349
Compare
|
Can one of the admins verify this patch? |
1 similar comment
|
Can one of the admins verify this patch? |
0bf8349
to
7da685f
Compare
|
I'm looking for this. |
| elif unit_flags == 'GE': | ||
| rel_flags = solv.REL_EQ | solv.REL_GT | ||
| else: | ||
| # fancier flags; might not be needed actually |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, this should be an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack; will raise something here instead
| pool = solvable.repo.pool | ||
| if unit_name.startswith('('): | ||
| # the Rich/Boolean dependencies have just the 'name' attribute | ||
| # this is always in the form: '(foo >= 1.2 AND bar != 0.9)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(foo >= 1.2 with foo < 2.0) should be better example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right; will update
| def find_dependent_rpms(self, units): | ||
| solver = self.pool.Solver() | ||
| if self.target_repo: | ||
| # to avoid dependency conflicts between units being copied into a repository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh, sounds hacky
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IKR O:-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so I guess since we don't really track these in the Mongo I can drop it actually
a8657e8
to
c8bd2d4
Compare
| '_content_type_id', | ||
| 'id', | ||
| ]) | ||
| rpm_exclude_fields = set([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing is, RPM.objects.only('provides').as_pymongo() doesn't expand the list of provides objects. I couldn't get it working in any other way than RPM.objects.exclude(...).as_pymongo() :-/
45ad7f7
to
e7b058c
Compare
|
we might have to consider implementing the i.e there might be issues in the users repo content that could be considered repo copy regressions by them if we only provide the --->%---EDITED--- Turns out I'm not processing directories in |
e7b058c
to
a00f62b
Compare
| repodata = solvable.repo.first_repodata() | ||
| unit_dirs = unit.get('files', {}).get('dir', []) | ||
| for dirname in unit_dirs: | ||
| repodata.str2dir(dirname.encode('utf-8'), create=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here you need just /, and then use add_dirstr() with the directory.
a00f62b
to
87750d6
Compare
|
@dparalen i think it will actually be fairly 'normal' for repos to not completely solve. Things like epel, optional, or extras do not provide all their dependencies, they depend on some base os repo which would not be part of the solver. I think we still have to copy what we know about in those instances. |
|
@jlsherrill yeah, I thought so. My implementation is more strict right now but These tricks will affect the set of the reported dependent packages. Once we implement weak dependency processing in Pulp, pulling-in all the recommended dependencies all the time because of the My gut feeling is though to expose these behaviour options as settings thru the REST API to the user to chose their preferred solver behaviour for a particular (repository) case. Folks might as well be interested in seeing what particular content would have been mocked to satisfy the dependencies for some sort of content sanity checking. But it may be out of scope for this PR. What do you think? Thanks, |
|
I'll investigate how to just ignore the problems the solver reported... |
87750d6
to
bd14f71
Compare
|
So it seems it's fine to just "ignore" the problems ;) |
31e96f8
to
97c72ff
Compare
| """A specific, rpm-unit-type filelist attribute conversion.""" | ||
| repodata = solvable.repo.first_repodata() | ||
| unit_files = unit.get('files', {}).get('file', []) | ||
| unit_files.extend(unit.get('files', {}).get('dir', [])) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both the rpm.files['file'] and rpm.files['dir'] have to be processed the same os.path.dirname(); os.path.basename() way for libsolv to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me.
However, I don't think we can merge this until the required changes for libsolv Python bindings have been released. If we merge this now, our nightly test runners will start failing until the newer libsolv bindings are available for EL7 and F28. We also will not be able to release this code until that dependency is available.
|
Jenkins tests are failing for |
|
@dralley, thanks a lot for test! |
The Pulp RPM plugin switches depsolving implementation to a libsolv-based one[1]. This patch adds a dependency on the python2 libsolv bindings that include necessary functionality, esp. the file-provides Python libsolv API. [1] pulp/pulp_rpm#1122
|
OK test |
|
ok test |
1 similar comment
|
ok test |
97c72ff
to
960eab9
Compare
|
ok test |
| plain_attribute_factory('arch'), | ||
| plain_attribute_factory('vendor'), | ||
| rpm_dependency_attribute_factory('requires'), | ||
| rpm_dependency_attribute_factory('conflicts'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shall remove the unused fields for now; if in the future required, we'd better add on an as-needed basis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come that conflicts do not exist?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't track these in Mongo so it has no effect; Can a repo have conflicting units inside? I guess it can, or?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for putting this together.
I tested using pulp-smash tests for recursively copying units between repos.
|
Please add a release note stating that we added libsolv as a dependency and that it's now being used when RPMs are being copied recursively between repos. |
b176364
to
0d718dd
Compare
|
OK, so I had a private chat with @ignatenkobrain and turns out we have to process the "negative" dependencies too:
This unfortunately is the case with the current code so I hope I'm not making it worse. Thanks @ignatenkobrain for pointing it out |
Missing And also you missed some input that |
|
We should file an issue in pulp.plan.io about this. This is not a regression. |
|
@dkliban, I've just created https://pulp.plan.io/issues/3853 |
| * The rich/boolean dependency solving is now supported when e.g recursively | ||
| copying RPM content between repositories. | ||
|
|
||
| * More conservative dependency solving is now supported when e.g recursively |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you explain 'conservative dependency solving'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a literal copy from the related issue headline; would you like me rephrasing it in the release note?
| solver = pulp_solv.Solver(source_repo, target_repo=dest_repo) | ||
| solver.load() | ||
| else: | ||
| solver = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about getting rid of unnecessary if statement on L#52 and:
if recursive:
solver = pulp_solv.Solver(source_repo, target_repo=dest_repo)
solver.load()
else:
solver = None
recursive = False
in my understanding this option is a boolean which is whether true or false.
in addition i noticed that this option is not documented in technical reference at all https://docs.pulpproject.org/plugins/pulp_rpm/tech-reference/yum-plugins.html#yum-importer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd also set a default value to False:
# get config items that we care about
recursive = config.get(constants.CONFIG_RECURSIVE, False)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lemme update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you could also update the tech. reference docs would be great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I'll check it
|
|
||
| # FIXME: not really true anymore: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you just remove the fixme since it's a not a problem and just leaving the note of silent skip of unresolvable deps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do
| repo_controller.associate_single_unit(repository=dest_repo, unit=unit) | ||
| unit_set.add(unit) | ||
| _LOGGER.debug('Copying unit: %s', unit) | ||
| # FIXME: this should be done in bulks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the status of this fixme?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will call it TODO:
|
@ipanova thanks for the review! |
0d718dd
to
14c7338
Compare
Pulp now uses libsolv as a dependency solver to address recursive RPM unit dependency solving during e.g unit copy Fixes: #3715 https://pulp.plan.io/issues/3715 Fixes: pulp#2478 https://pulp.plan.io/issues/2478
14c7338
to
f85007c
Compare
|
updated; hopefully I didn't miss anything |
|
ok test |
Please note this requires a libsolv version exposing Python bindings necessary to support
fileprovidesdeps. @ignatenkobrain made an F26 build with which I was able to test this PR manually.Without it will just blow-up O:-)