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

many: add cuda-driver-libs interface #15063

Merged

Conversation

alfonsosanchezbeato
Copy link
Member

Add cuda-driver-libs interface. This is the first interface using the ldconfig backend. Additionally, it is the first example of an implicit plug, so some changes in ifacestate are also part of this change.

Copy link

github-actions bot commented Feb 11, 2025

Tue Feb 25 15:14:27 UTC 2025
The following results are from: https://github.com/canonical/snapd/actions/runs/13502715560

Failures:

Preparing:

  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-15.6-64
  • openstack:opensuse-15.6-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64

Executing:

  • google-distro-1:amazon-linux-2-64:tests/main/progress
  • google-distro-2:arch-linux-64:tests/main/interfaces-network-status-classic
  • openstack:debian-sid-64:tests/main/auto-refresh-gating
  • google-arm:ubuntu-20.04-arm-64:tests/main/progress
  • google-arm:ubuntu-core-22-arm-64:tests/core/services
  • google:ubuntu-25.04-64:tests/main/snap-user-service-socket-activation
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups:uinput
  • google:ubuntu-25.04-64:tests/main/progress
  • google:ubuntu-25.04-64:tests/main/snap-ns-forward-compat
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-serial-port
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups:kmsg
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-helper
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-required-or-optional
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-self-manage
  • google:ubuntu-25.04-64:tests/main/cgroup-devices-v2
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-strict-enforced
  • google:ubuntu-16.04-64:tests/main/microk8s-smoke:edge

Restoring:

  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-15.6-64
  • openstack:opensuse-15.6-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • openstack:opensuse-tumbleweed-64
  • google:ubuntu-25.04-64:tests/main/security-device-cgroups-strict-enforced

Copy link

codecov bot commented Feb 12, 2025

Codecov Report

Attention: Patch coverage is 83.68794% with 23 lines in your changes missing coverage. Please review.

Please upload report for BASE (master@c4ff9e7). Learn more about missing BASE report.
Report is 267 commits behind head on master.

Files with missing lines Patch % Lines
interfaces/builtin/cuda_driver_libs.go 86.25% 8 Missing and 3 partials ⚠️
overlord/ifacestate/ifacestate.go 0.00% 2 Missing and 3 partials ⚠️
overlord/ifacestate/handlers.go 0.00% 0 Missing and 4 partials ⚠️
overlord/ifacestate/helpers.go 0.00% 0 Missing and 2 partials ⚠️
interfaces/ldconfig/spec.go 95.83% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master   #15063   +/-   ##
=========================================
  Coverage          ?   78.08%           
=========================================
  Files             ?     1184           
  Lines             ?   158105           
  Branches          ?        0           
=========================================
  Hits              ?   123457           
  Misses            ?    26976           
  Partials          ?     7672           
Flag Coverage Δ
unittests 78.08% <83.68%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

andrewphelpsj
andrewphelpsj previously approved these changes Feb 14, 2025
Copy link
Member

@andrewphelpsj andrewphelpsj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

if len(fields) != 1 && len(fields) != 3 {
return fmt.Errorf("wrong format for api-version: %q", versRange)
}
switch len(fields) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment here with examples of the expected input might be good. I think something like this?

// valid input examples:
// 1.2.3
// 1.2.3 .. 2.3.4

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I've added a comment

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did a first pass, don't we need a configfile part to this?

// For the moment only the system snap is supported - the
// snap.system.conf file is owned by it and the set-up of other snaps
// must not affect it.
if !interfaces.IsTheSystemSnap(appSet.InstanceName()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we discussed before that this doesn't make a lot of sense because of the two of the interface, why is it needed?

Copy link
Member Author

@alfonsosanchezbeato alfonsosanchezbeato Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actually needed, otherwise when the slot side builds its profiles after, say, a disconnection, it overrides the content of snap.system.conf. That file is owned by the system plug and no other plug/slot should touch it.

For instance, this is seen when there are 2 snaps providing slots, if one is removed, when reconstructing the slot profiles it sees no spec.libDirs and it removes the file, overriding what the plug profile wrote just before.

Copy link
Collaborator

@pedronis pedronis Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's talk about this in our 1-1, I'm really worried that these are the only interfaces that need this kind of behavior and they assume things about two levels up in the code from them

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

71aca8f adds behavior so instead of checking the snap name we check if the snap owns plugs that need configuration. We cannot rely only in the connected plugs unfortunately.

}
// Validate directories
for _, dir := range libDirs {
if !strings.HasPrefix(dir, "$SNAP") && !strings.HasPrefix(dir, "${SNAP}") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this also include the / ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, changed

@pedronis
Copy link
Collaborator

@alfonsosanchezbeato maybe it would make sense to make the changes to support implicit plugs their own PR?

Copy link
Member Author

@alfonsosanchezbeato alfonsosanchezbeato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedronis thanks for the review, comments addressed. Regarding configfile, no, for th cuda interface we do not have configuration files that we need to take care of.

// For the moment only the system snap is supported - the
// snap.system.conf file is owned by it and the set-up of other snaps
// must not affect it.
if !interfaces.IsTheSystemSnap(appSet.InstanceName()) {
Copy link
Member Author

@alfonsosanchezbeato alfonsosanchezbeato Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actually needed, otherwise when the slot side builds its profiles after, say, a disconnection, it overrides the content of snap.system.conf. That file is owned by the system plug and no other plug/slot should touch it.

For instance, this is seen when there are 2 snaps providing slots, if one is removed, when reconstructing the slot profiles it sees no spec.libDirs and it removes the file, overriding what the plug profile wrote just before.

}
// Validate directories
for _, dir := range libDirs {
if !strings.HasPrefix(dir, "$SNAP") && !strings.HasPrefix(dir, "${SNAP}") {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, changed

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the changes, one comment about a detail

@@ -61,10 +63,18 @@ func (spec *Specification) AddLibDirs(dirs []string) error {
return nil
}

func (spec *Specification) AddPlug(plug string) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't need to be public and done by the interfaces, we can do it for them in:

func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {

no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I've changed this now: a5b040c

@@ -59,6 +59,12 @@ func (b *Backend) Setup(appSet *interfaces.SnapAppSet, opts interfaces.Confineme
appSet.InstanceName(), err)
}

// Setup ldconfig only of the snap has plugs that require it. For the
// moment this is only the system snap.
if len(spec.(*Specification).plugs) == 0 {
Copy link
Collaborator

@pedronis pedronis Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: I would do this check in the helper, also because it gets the spec casted already

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question about the last change

@@ -102,6 +108,9 @@ func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *in

// AddPermanentPlug records ldconfig-specific side-effects of having a plug.
func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
// Keep track of interfaces using this backend on the consumer side
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we do this only if the interface has actually LdconfigPermanentPlug or LdconfigConnectedPlug implemented? otherwise I think this method is called for all plugs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I check now for LdconfigConnectedPlug, I want to avoid the interface to implement an empty LdconfigPermanentPlug.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought you mentioned you need to run things even if the plug is not connected? as I said you can check for either definer in AddPermantPlug

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, otherwise we do not know if we need to remove configuration if all connections are gone.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest commit checks the definer in AddPermantPlug

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

Comment on lines 93 to 95
if !interfaces.IsTheSystemSnap(plug.Snap().InstanceName()) {
return errors.New("internal error: ldconfig plugs can be defined only by the system snap")
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it make sense to move the check into the getConnectedPlugCallback ?

@pedronis pedronis dismissed andrewphelpsj’s stale review February 21, 2025 15:38

this has changed quite a bit since the initial review

Copy link
Member

@Meulengracht Meulengracht left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Grow test for interfaces that export libraries to the rootfs, like
cuda-driver-libs.
Make sure that Setup touches the ldconfig configuration only for the
system snap, as it is the owner of it. Otherwise the configuration
would be destroyed when the other snaps are configured.
Register snap plugs so we know when we need to generate an ldconfig
file.
interface wants to use the ldconfig backend.
slot *interfaces.ConnectedSlot) error
connectedPlugCallback, err := getConnectedPlugCallback(iface, plug.Snap().InstanceName())
if err != nil {
return err
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, it'd be nice if we could do this change for other things. It makes reading the code in this package harder when the interfaces are defined locally like this.

Copy link
Member

@andrewphelpsj andrewphelpsj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@alfonsosanchezbeato alfonsosanchezbeato merged commit 2e0be42 into canonical:master Feb 25, 2025
71 of 78 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants