github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/overlord/ifacestate/implicit.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package ifacestate 21 22 import ( 23 "fmt" 24 25 "github.com/snapcore/snapd/interfaces" 26 "github.com/snapcore/snapd/interfaces/builtin" 27 "github.com/snapcore/snapd/overlord/state" 28 "github.com/snapcore/snapd/release" 29 "github.com/snapcore/snapd/snap" 30 ) 31 32 func shouldSnapdHostImplicitSlots(mapper SnapMapper) bool { 33 _, ok := mapper.(*CoreSnapdSystemMapper) 34 return ok 35 } 36 37 // addImplicitSlots adds implicitly defined slots and hotplug slots to a given snap. 38 // 39 // Only the OS snap has implicit and hotplug slots. 40 // 41 // It is assumed that slots have names matching the interface name. Existing 42 // slots are not changed, only missing slots are added. 43 func addImplicitSlots(st *state.State, snapInfo *snap.Info) error { 44 // Implicit slots can be added to the special "snapd" snap or to snaps with 45 // type "os". Currently there are no other snaps that gain implicit 46 // interfaces. 47 if snapInfo.Type() != snap.TypeOS && snapInfo.Type() != snap.TypeSnapd { 48 return nil 49 } 50 51 // If the manager has chosen to put implicit slots on the "snapd" snap 52 // then stop adding them to any other core snaps. 53 if shouldSnapdHostImplicitSlots(mapper) && snapInfo.Type() != snap.TypeSnapd { 54 return nil 55 } 56 57 hotplugSlots, err := getHotplugSlots(st) 58 if err != nil { 59 return err 60 } 61 62 // Ask each interface if it wants to be implicitly added. 63 for _, iface := range builtin.Interfaces() { 64 si := interfaces.StaticInfoOf(iface) 65 if (release.OnClassic && si.ImplicitOnClassic) || (!release.OnClassic && si.ImplicitOnCore) { 66 ifaceName := iface.Name() 67 if _, ok := snapInfo.Slots[ifaceName]; !ok { 68 snapInfo.Slots[ifaceName] = makeImplicitSlot(snapInfo, ifaceName) 69 } 70 } 71 } 72 73 // Add hotplug slots 74 for _, hslotInfo := range hotplugSlots { 75 if _, ok := snapInfo.Slots[hslotInfo.Name]; ok { 76 return fmt.Errorf("cannot add hotplug slot %s: slot already exists", hslotInfo.Name) 77 } 78 if hslotInfo.HotplugGone { 79 continue 80 } 81 snapInfo.Slots[hslotInfo.Name] = &snap.SlotInfo{ 82 Name: hslotInfo.Name, 83 Snap: snapInfo, 84 Interface: hslotInfo.Interface, 85 Attrs: hslotInfo.StaticAttrs, 86 HotplugKey: hslotInfo.HotplugKey, 87 } 88 } 89 90 return nil 91 } 92 93 func makeImplicitSlot(snapInfo *snap.Info, ifaceName string) *snap.SlotInfo { 94 return &snap.SlotInfo{ 95 Name: ifaceName, 96 Snap: snapInfo, 97 Interface: ifaceName, 98 } 99 }