reuse concretization: allow externals from remote when locally configured#35975
Conversation
|
@haampie I'm not competent to speak to the technical aspects of the implementation, but as you describe it I think this should do what we need, thank you! |
|
I've had chance to try this out and I've obtained encouraging results but they're not 100%. Procedure:
I should note that an environment created from I include within the attached spack-files.tgz:
If there were some way for me to trace the source of the divergence myself, please let me know and I would be happy to do the work of ascertaining whether this is PEBKAC, GIGO, or a limitation of this PR. |
|
@haampie What's the status on this, please? |
…rom-buildcache Port of spack#35975
|
@haampie Bump? |
|
@haampie What is necessary for this to be made ready to merge, please, and can I help? |
|
@haampie @scheibelp @tgamblin Ping? |
|
Hi @greenc-FNAL, this isn't moving forward cause other people have different preferences. @alalazo wants to avoid the intermediate step of externals in packages.yaml @becker33 wants to solve this as a special case of splicing (although not 100% sure if your use case was discussed explicitly in that context) In my opinion:
Since currently externals use abstract specs, and spack fills out the details in some way the user can't control, I don't see why filling out the blanks from a matching spec in a build cache is controversial. |
becker33
left a comment
There was a problem hiding this comment.
I'm in favor of this as a quicker fix for the simpler case. We will need splicing to support externals that satisfy but are installed to a different path, but there's no reason to block this for that effort.
In the long run, splicing may provide better provenance for cases where different OS providers patch system packages in different ways, but I think that's out of scope for this PR. We can revert it if necessary when we have a more general solution, or we can keep it as the simpler code path, whichever makes sense at that time.
|
|
||
| # and externals. | ||
| spec_list += [ | ||
| s for s in db.query_local(installed=False, in_buildcache=False) if s.external |
There was a problem hiding this comment.
I don't think that installed=False is what we want here, I think we want installed=any. The external can be reused whether or not it was "installed".
It would also be good if we could restrict this to externals that are depended on by one of the packages in spec_list.
There was a problem hiding this comment.
query_local isn't super helpful :) I've turned it into a single call to that with extra filtering afterwards.
It would also be good if we could restrict this to externals that are depended on by one of the packages in
spec_list.
I think this is a bit too niche to deal with. It's pretty unlikely an external without dependents enters a build cache, so if it happens it might have been on purpose
There was a problem hiding this comment.
This should only consider externals in possible_dependencies for the current solve.
lib/spack/spack/solver/asp.py
Outdated
| packages = spack.config.get("packages") | ||
| index = [ | ||
| s | ||
| for s in spack.binary_distribution.update_cache_and_get_specs() | ||
| if not s.external or _is_reusable_external(packages, s) | ||
| ] |
There was a problem hiding this comment.
This should have a comment explaining that making the dependency reusable/not effectively controls whether the dependent is reusable/not. It's too slick to go without a comment.
There's a fundamental misunderstanding here on what I want. I don't want For (3), that issue means to me that we should make it easier to deal with the DB. The DB contains anything that was concretized and is frozen, and in my opinion we shouldn't be able to change it from configuration. What we should be able to do is to update the DB on system updates, to reflect the current state. Hashes should change accordingly when we splice some new external spec because e.g. it bumped version. In #35975 (comment) and in #40843 (comment) it seems you suggest we should be less strict with externals, and allow people to fix the behavior of externals by editing a configuration file. How would you deal with that, and with the fact that hashes are frozen once something is installed? Footnotes
|
|
Regarding #35975 (comment), I'm not sure why auto-detected system packages should not appear in
|
Sure, but in the end an external has to be registered in the DB when a spec is concretized and installed, right? If that is the case, what does:
mean (see also discussion in #40843 (comment))? If it means that we should make external specification more loose, and allow changing a config file to also change the behavior of something that in the DB, then imo it's the wrong path - we would give less meaning to the hash in that way. As an example: the issue linked to this PR deals with adding / removing modules to an already installed external. What if the typo was in the version? Should we just proceed with editing the config file without modifications to the DB to fix that? |
This is another discussion, and a bit off-topic in this PR (so maybe it's better to discuss details in #36179). Briefly, the main reason is that a DB should be the ultimate source of truth for concrete specs, and externals are concrete specs.
|
|
@alalazo can we park this packages.yaml discussion? I disagree with many points, but since you're saying you don't want the config to go away, it shouldn't be a blocker for this PR. |
I think we need to decide what we want as a path forward for externals in general (let's discuss this tomorrow during the meeting?) If we want to move to externals in the DB like we discussed, then we also need to be clear how the semantic in |
4f4a345 to
3a92843
Compare
|
Can you list possible future conflicts of this change? I don't see any. |
|
Here you match on abstract specs in
Can you answer the questions above or in the issue #40843 (comment) how do you want to achieve that:
(which I guess is to be extended to other aspects of the spec) ? |
|
This should address your comments: Externals config as a filter on reusable externals from build caches as introduced in this PR can be extended to the local Issue #40843 is a huge usability problem and time waster, and we should fix it fast instead of getting stuck in hypotheticals about controversial changes in semantics of externals. The current state of things is that you need intricate knowledge of implementation details of Spack to understand that externals are picked up through config OR reuse concretization. The fact that externals are "installed" and can be "reused" as a consequence is an implementation detail and we shouldn't expect that's obvious to users, we should focus on their usability issues. You can't get rid of packages.yaml externals configuration cause there will always be undetectable or incorrectly detected packages you need to manually specify as external, and config is the obvious way to do that -- being able to modify this with a text editor is far superior to special spack commands. So, config + a database with reuse semantics continues to exist also with your ideas. Your suggestion of committing config to the database and only relying on reuse from that point on is not solving #40843 and only introduces more usability issues where users again have to be aware of this artificial concept of "uninstalling externals". If you take packages.yaml config for externals as a filter on reusable specs things are intuitive: modified config for a previously incorrectly configured external will apply to re-concretization. There's no need to be aware of the database which makes it easy. Yes, old "installs" of externals would continue to exist in the database even if they were misconfigured, but for users who install
"but misconfigured externals continue to exist in the database" is a non-problem imo when this filter logic is extended to the local dbs. |
c618946 to
c6b206e
Compare
|
@alalazo I think that the following: and specifically gets close to resolving #40843: if the user modifies the Are you concerned that after reconcretizing, we wouldn't actually reinstall the new spec with the new external modules (because it has the same hash)? I think that could be a problem, but I think we could infer that we need to overwrite the installed spec in that case. |
|
This also predates #40843 and I think it's still worth merging regardless of whether it resolves that issue (although I think it might be worth discussing here in case someone thinks these changes make it harder to fix that - I don't think they do). |
…ured
This looks to me like the best compromise regarding externals in a
build cache. I wouldn't want `spack install` on my machine to install
specs that were marked external on another. At the same time there are
centers that control the target systems on which spack is used, and
would want to use external in buildcaches.
As a solution, reuse concretization will now consider those externals
used in buildcaches that match a locally configured external in
packages.yaml.
So for example person A installs and pushes specs with this config:
```yaml
packages:
ncurses:
externals:
- spec: [email protected] +feature
prefix: /usr
```
and person B concretizes and installs using that buildcache with the
following config:
```yaml
packages:
ncurses:
externals:
- spec: ncurses@6
prefix: /usr
```
the spec will be reused (or rather, will be considered for reuse...)
c6b206e to
12f25a6
Compare
|
@scheibelp On your comment above, I am pretty sure this PR solves the issue in the description, and might solve #40843 if we use the abstract external specs as filter on the local DB. Abstract specs won't work with e.g. #30911 or with modifications that remove variants or other parts from the spec (cause the filter will be coarser). I'm not as confident as @becker33 that we can later revert this and its natural extension to solve #40843 without affecting users, if we want to pursue a model like in #36179 + splicing. That's why I suggested #35975 (comment). |
Could we store the abstract spec as part of the db record or as an attribute of a concretized external spec? In that case, we could require equality vs. depending on |
|
I don't think #36179 is strictly necessary for the issues it aims to solve. It does more than solving the referenced issues, and it's not the only solution to the them. For example for multi-valued variants the complaint is that Spack merges the list of values in config with the package defaults -- that's pretty weird, how about not doing that? Problem solved? Isn't that how package preferences for multi-valued variants work too? (I checked: that is how it works) Regarding multi-valued variants, I do think we have an issue though that prevents this PR from being useful: >>> spack.spec.Spec("gcc languages=c,c++").satisfies("gcc languages=c")
True
>>> spack.spec.Spec("gcc languages=c").satisfies("gcc languages=c,c++")
TrueAnd with explicit >>> MultiValuedVariant('languages', ('c')).satisfies(MultiValuedVariant('languages', ('c', 'c++')))
False
>>> MultiValuedVariant('languages', ('c', 'c++')).satisfies(MultiValuedVariant('languages', ('c')))
TrueI guess you could see this as |
becker33
left a comment
There was a problem hiding this comment.
Follow on PRs:
- filter reuseable_specs by what's in possible_dependencies
- exact-match
:=semantics for mutli-value variants
|
@becker33 Point 1 is already done: spack/lib/spack/spack/solver/asp.py Lines 2492 to 2496 in c1a8bb2 |
|
Thanks, missed that when I was looking through the code earlier |
…ured (spack#35975) This looks to me like the best compromise regarding externals in a build cache. I wouldn't want `spack install` on my machine to install specs that were marked external on another. At the same time there are centers that control the target systems on which spack is used, and would want to use external in buildcaches. As a solution, reuse concretization will now consider those externals used in buildcaches that match a locally configured external in packages.yaml. So for example person A installs and pushes specs with this config: ```yaml packages: ncurses: externals: - spec: [email protected] +feature prefix: /usr ``` and person B concretizes and installs using that buildcache with the following config: ```yaml packages: ncurses: externals: - spec: ncurses@6 prefix: /usr ``` the spec will be reused (or rather, will be considered for reuse...)
This looks to me like the best compromise regarding externals in a
buildcache. I wouldn't want
spack installon my machine to installarbitrary specs that were marked external on another. At the same time there
are centers that control the target systems on which spack is used, and
would want to use externals in buildcaches to speed up builds.
As a solution, reuse concretization will now consider those externals
used in buildcaches that match a locally configured external in
packages.yaml.
So for example person A installs and pushes specs with this config:
and person B concretizes and installs using that buildcache with the
following config:
the spec will be reused (or rather, will be considered for reuse...)
It won't be considered for reuse if person B has no externals
configured, or only non-matching specs like
ncurses@5, or theyhave
ncursesbut in a/different/prefix.Pinging @greenc-FNAL / @t-brown