What should the auto-connect logic be like?

While fixing some recent issues with duplicate plugs/slots on the core snap we realized the algorithm for auto-connection is naive and can easily be incorrect.

Currently a connection between a plug and a slot, or slot and a plug, is made only if at the time of installation there’s exactly one candidate available to satisfy the connection and the assertion system and the interface itself allows this to happen. We can see why this is incorrect for slots. Typically slots are 1-to-N (e.g. the network slot) so one slot can be paired to many plugs at the same time.

Depending on the nature of the interface we should be more generic. E.g. installing a snap with shared runtime (e.g. java or qt) should connect to all otherwise unconnected snaps that can use such runtime. On the other hand installing an application while having two possible runtimes should not connect both runtimes. I’m sure there are more interesting examples we can make.

I think that we need a way to model this behaviour in the interface code itself, so that it can make useful suggestions to the core, during auto-connection analysis.

1 Like

We should make the obvious cases work well before worrying about rare ones. In particular:

That’s a pretty obvious bug which needs to be fixed. If there’s an allowed auto-connection which may be established with the core snap, the code should just do it, ignoring any duplicates elsewhere.

If there are duplicates elsewhere in other snaps, we can hold back for now and not connect, waiting for it to be manually established. This gives us room to implement the right behavior in the near future without breaking compatibility. We’ll likely need to support some additional metadata in the interfaces since there’s more than one right answer.

Is there any other case that needs to be fixed right now?

Not that I’m aware of. I think just the slot side to core is obviously broken.

We’re already affected by this issue:

In the screenly-client snap we have two plugs for the one udisks2:service slot and we’re getting

auto connect udisks2:service (slot auto-connection), candidates found: "screenly-client:udisks2, udisks2:client"

error message.

In this particular case we want both of them to connect to the slot.

In the other situation - we have three dbus slots and three dbus plugs, and each plug should be connected to its own slot. Currently, the system tries to connect to all of them and we’re getting the error message:

auto connect screenly-client:command-dbus-client (plug auto-connection), candidates found: "screenly-client:command-dbus-server, screenly-client:ping-dbus-server, screenly-client:playlist-dbus-server"

Is would be nice to have a way to select target slots for plugs in the snapcraft.yaml or in the snap’s declaration.

The way I decided to work around this is to have a service with a snapd-control interface connecting interfaces using the REST API.

At the moment we assume all slots accept many connections (this will not stay true but we will bridge that when we have ways to express those constraints or use hooks for that),

so if we have an installed producer exposing a slot with interface “auto”, and we install two consumers of “auto” they will both auto-connect (there is one slot candidate for each of them),

this should work the same if the installation order is reversed.

While I agree with this idea, we need to make sure that certain things are not auto-connected to more than one consumer. From the top of my head are the GPIOs and serial ports but I bet more will follow. Those are really 1-to-1 interfaces. Some are only such logically and it might be possible to have multiple connections (but I’d make it so it requires explicit connection) and others are really single use (e.g. a file is open by a process and other processes will not be allowed).

At the moment they will be multiply connected already. I really don’t know how we want to handle that.

I think they might actually not auto-connect at the interface layer. That would fix the immediate issue.

anyway at the moment I’m trying to fix the obvious bug (behavior starting from plugs is different than starting from slots), the rest is for later to pick up

1 Like

opened

https://github.com/snapcore/snapd/pull/3350

We need to extend the language so we can express these cases. Meanwhile, we may simply not auto-connect. GPIO and serial ports are both examples of things that are too general for them to be auto-connected in a sensible way.

I think Dell has cases were they are using or trying to use auto-connect with GPIO already.

I’d like to hear more, as I don’t think that’s generally sensible. @awe do you have more details?

discussing with @awe yesterday I discovered he never saw your question to him here, he might come back again to you

The use case that’s currently broken for is we have a gadget snap for a device with a branded store, which defines four gpio slots:

 slots:
    sku-bit-a:
        interface: gpio
        number: 345
    sku-bit-b:
        interface: gpio
        number: 368
    sku-bit-c:
        interface: gpio
        number: 347
    some-led:
        interface: gpio
        number: 346

There’s a snap hosted in the branded store which specifies the qualified (ie. named) gpio plugs it uses in its snapcraft.yaml. This snap is the only snap hosted in the branded store that uses the gadget slots involved. The expectation was that when the snap gets installed, all of these connections happen automatically.

apps:
  ledapp:
    command: ledcmd
    daemon: simple
    plugs:
    - some-led
    - sku-bit-a
      .
      .
plugs:
      some-led:
          interface: gpio
      sku-bit-a:
          interface: gpio
      .
      .

I’d been working with @pedronis and @jdstrand on adjustments to the snap-declarations of both the client snap, and the gadget snap to get this to work, but so far to date we’ve been unsuccessful. At this point, the only snap-declaration change that is live, is a Slots stanza for the gadget snap which grants permission to the client snap:

  "gpio": {
    "allow-auto-connection": {
      "plug-snap-id": [
        <snapId>
      ]
    }
  }

When the snap is installed today, the following error is output:

$ sudo snap install client-snap
2017-05-26T16:41:29-04:00 INFO cannot auto connect client-snap:sku-bit-c (plug auto-connection), candidates found: “gadget:sku-bit-a, gadget:some-led, gadget:sku-bit-b, gadgetc:sku-bit-c”

One more note, the most recent suggestion from @pedronis was to do the following:

What can be done is add an unspecified attribute both to the slots definitions in the gadget yaml and the plug definitions in the consumer snaps yaml:

example:

some-led:
      interface: gpio
      purpose: some-led

then the gadget slots rule can be changed:

slots:
      gpio:
        allow-auto-connection:
            plug-snap-id:
      ...
            plug-attributes:
                purpose: $SLOT(purpose)

So we would use this invented “purpose” attribute to be specified both on plugs and slots, to match on and do the connections we need and only those (this is a bit of an abuse as I said).

Note - I haven’t yet tested this approach, but hope to do so in the next day or so.

to be clear that suggestion is indeed a hack/abuse, but uses what we have today

Not just a hack, but a hack that can’t ever be removed because it will break that deployment. Let’s please make sure we understand the plan moving forward before we go there.

if they get the same things connected I don’t think it matters how, so not sure I see this point as never removed