Permalink
...
Checking mergeability…
Don’t worry, you can still create the pull request.
Comparing changes
Open a pull request
- 1 commit
- 6 files changed
- 0 commit comments
- 1 contributor
Unified
Split
Showing
with
263 additions
and 169 deletions.
- +4 −3 overlord/ifacestate/handlers.go
- +11 −134 overlord/ifacestate/helpers.go
- +17 −2 overlord/ifacestate/ifacemgr.go
- +2 −30 overlord/ifacestate/implicit.go
- +204 −0 overlord/ifacestate/repo/repo.go
- +25 −0 tests/main/interfaces-snapd-control-with-manage/task.yaml
View
7
overlord/ifacestate/handlers.go
| @@ -30,6 +30,7 @@ import ( | ||
| "github.com/snapcore/snapd/interfaces" | ||
| "github.com/snapcore/snapd/interfaces/policy" | ||
| "github.com/snapcore/snapd/overlord/assertstate" | ||
| + "github.com/snapcore/snapd/overlord/ifacestate/repo" | ||
| "github.com/snapcore/snapd/overlord/snapstate" | ||
| "github.com/snapcore/snapd/overlord/state" | ||
| "github.com/snapcore/snapd/release" | ||
| @@ -292,7 +293,7 @@ func (m *InterfaceManager) doDiscardConns(task *state.Task, _ *tomb.Tomb) error | ||
| if err != nil { | ||
| return err | ||
| } | ||
| - removed := make(map[string]connState) | ||
| + removed := make(map[string]repo.ConnState) | ||
| for id := range conns { | ||
| connRef, err := interfaces.ParseConnRef(id) | ||
| if err != nil { | ||
| @@ -313,7 +314,7 @@ func (m *InterfaceManager) undoDiscardConns(task *state.Task, _ *tomb.Tomb) erro | ||
| st.Lock() | ||
| defer st.Unlock() | ||
| - var removed map[string]connState | ||
| + var removed map[string]repo.ConnState | ||
| err := task.Get("removed", &removed) | ||
| if err != nil && err != state.ErrNoState { | ||
| return err | ||
| @@ -423,7 +424,7 @@ func (m *InterfaceManager) doConnect(task *state.Task, _ *tomb.Tomb) error { | ||
| return err | ||
| } | ||
| - conns[connRef.ID()] = connState{Interface: plug.Interface} | ||
| + conns[connRef.ID()] = repo.ConnState{Interface: plug.Interface} | ||
| setConns(st, conns) | ||
| return nil | ||
View
145
overlord/ifacestate/helpers.go
| @@ -25,89 +25,25 @@ import ( | ||
| "github.com/snapcore/snapd/asserts" | ||
| "github.com/snapcore/snapd/interfaces" | ||
| - "github.com/snapcore/snapd/interfaces/backends" | ||
| - "github.com/snapcore/snapd/interfaces/builtin" | ||
| "github.com/snapcore/snapd/interfaces/policy" | ||
| "github.com/snapcore/snapd/logger" | ||
| "github.com/snapcore/snapd/overlord/assertstate" | ||
| + "github.com/snapcore/snapd/overlord/ifacestate/repo" | ||
| "github.com/snapcore/snapd/overlord/snapstate" | ||
| "github.com/snapcore/snapd/overlord/state" | ||
| "github.com/snapcore/snapd/snap" | ||
| ) | ||
| -func (m *InterfaceManager) initialize(extraInterfaces []interfaces.Interface, extraBackends []interfaces.SecurityBackend) error { | ||
| +func (m *InterfaceManager) initialize() error { | ||
| m.state.Lock() | ||
| defer m.state.Unlock() | ||
| - if err := m.addInterfaces(extraInterfaces); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.addBackends(extraBackends); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.addSnaps(); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.renameCorePlugConnection(); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.reloadConnections(""); err != nil { | ||
| - return err | ||
| - } | ||
| if err := m.regenerateAllSecurityProfiles(); err != nil { | ||
| return err | ||
| } | ||
| return nil | ||
| } | ||
| -func (m *InterfaceManager) addInterfaces(extra []interfaces.Interface) error { | ||
| - for _, iface := range builtin.Interfaces() { | ||
| - if err := m.repo.AddInterface(iface); err != nil { | ||
| - return err | ||
| - } | ||
| - } | ||
| - for _, iface := range extra { | ||
| - if err := m.repo.AddInterface(iface); err != nil { | ||
| - return err | ||
| - } | ||
| - } | ||
| - return nil | ||
| -} | ||
| - | ||
| -func (m *InterfaceManager) addBackends(extra []interfaces.SecurityBackend) error { | ||
| - for _, backend := range backends.All { | ||
| - if err := backend.Initialize(); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.repo.AddBackend(backend); err != nil { | ||
| - return err | ||
| - } | ||
| - } | ||
| - for _, backend := range extra { | ||
| - if err := backend.Initialize(); err != nil { | ||
| - return err | ||
| - } | ||
| - if err := m.repo.AddBackend(backend); err != nil { | ||
| - return err | ||
| - } | ||
| - } | ||
| - return nil | ||
| -} | ||
| - | ||
| -func (m *InterfaceManager) addSnaps() error { | ||
| - snaps, err := snapstate.ActiveInfos(m.state) | ||
| - if err != nil { | ||
| - return err | ||
| - } | ||
| - for _, snapInfo := range snaps { | ||
| - addImplicitSlots(snapInfo) | ||
| - if err := m.repo.AddSnap(snapInfo); err != nil { | ||
| - logger.Noticef("%s", err) | ||
| - } | ||
| - } | ||
| - return nil | ||
| -} | ||
| - | ||
| // regenerateAllSecurityProfiles will regenerate the security profiles | ||
| // for apparmor and seccomp. This is needed because: | ||
| // - for seccomp we may have "terms" on disk that the current snap-confine | ||
| @@ -159,56 +95,11 @@ func (m *InterfaceManager) regenerateAllSecurityProfiles() error { | ||
| return nil | ||
| } | ||
| -// renameCorePlugConnection renames one connection from "core-support" plug to | ||
| -// slot so that the plug name is "core-support-plug" while the slot is | ||
| -// unchanged. This matches a change introduced in 2.24, where the core snap no | ||
| -// longer has the "core-support" plug as that was clashing with the slot with | ||
| -// the same name. | ||
| -func (m *InterfaceManager) renameCorePlugConnection() error { | ||
| - conns, err := getConns(m.state) | ||
| - if err != nil { | ||
| - return err | ||
| - } | ||
| - const oldPlugName = "core-support" | ||
| - const newPlugName = "core-support-plug" | ||
| - // old connection, note that slotRef is the same in both | ||
| - slotRef := interfaces.SlotRef{Snap: "core", Name: oldPlugName} | ||
| - oldPlugRef := interfaces.PlugRef{Snap: "core", Name: oldPlugName} | ||
| - oldConnRef := interfaces.ConnRef{PlugRef: oldPlugRef, SlotRef: slotRef} | ||
| - oldID := oldConnRef.ID() | ||
| - // if the old connection is saved, replace it with the new connection | ||
| - if cState, ok := conns[oldID]; ok { | ||
| - newPlugRef := interfaces.PlugRef{Snap: "core", Name: newPlugName} | ||
| - newConnRef := interfaces.ConnRef{PlugRef: newPlugRef, SlotRef: slotRef} | ||
| - newID := newConnRef.ID() | ||
| - delete(conns, oldID) | ||
| - conns[newID] = cState | ||
| - setConns(m.state, conns) | ||
| - } | ||
| - return nil | ||
| -} | ||
| - | ||
| // reloadConnections reloads connections stored in the state in the repository. | ||
| // Using non-empty snapName the operation can be scoped to connections | ||
| // affecting a given snap. | ||
| func (m *InterfaceManager) reloadConnections(snapName string) error { | ||
| - conns, err := getConns(m.state) | ||
| - if err != nil { | ||
| - return err | ||
| - } | ||
| - for id := range conns { | ||
| - connRef, err := interfaces.ParseConnRef(id) | ||
| - if err != nil { | ||
| - return err | ||
| - } | ||
| - if snapName != "" && connRef.PlugRef.Snap != snapName && connRef.SlotRef.Snap != snapName { | ||
| - continue | ||
| - } | ||
| - if err := m.repo.Connect(connRef); err != nil { | ||
| - logger.Noticef("%s", err) | ||
| - } | ||
| - } | ||
| - return nil | ||
| + return repo.ReloadConnections(m.state, m.repo, snapName) | ||
| } | ||
| func (m *InterfaceManager) setupSnapSecurity(task *state.Task, snapInfo *snap.Info, opts interfaces.ConfinementOptions) error { | ||
| @@ -241,11 +132,6 @@ func (m *InterfaceManager) removeSnapSecurity(task *state.Task, snapName string) | ||
| return nil | ||
| } | ||
| -type connState struct { | ||
| - Auto bool `json:"auto,omitempty"` | ||
| - Interface string `json:"interface,omitempty"` | ||
| -} | ||
| - | ||
| type autoConnectChecker struct { | ||
| st *state.State | ||
| cache map[string]*asserts.SnapDeclaration | ||
| @@ -314,14 +200,14 @@ func (c *autoConnectChecker) check(plug *interfaces.Plug, slot *interfaces.Slot) | ||
| // of connected snap names. The blacklist can prevent auto-connection to | ||
| // specific interfaces (blacklist entries are plug or slot names). | ||
| func (m *InterfaceManager) autoConnect(task *state.Task, snapName string, blacklist map[string]bool) ([]string, error) { | ||
| - var conns map[string]connState | ||
| + var conns map[string]repo.ConnState | ||
| var affectedSnapNames []string | ||
| err := task.State().Get("conns", &conns) | ||
| if err != nil && err != state.ErrNoState { | ||
| return nil, err | ||
| } | ||
| if conns == nil { | ||
| - conns = make(map[string]connState) | ||
| + conns = make(map[string]repo.ConnState) | ||
| } | ||
| autochecker, err := newAutoConnectChecker(task.State()) | ||
| @@ -372,7 +258,7 @@ func (m *InterfaceManager) autoConnect(task *state.Task, snapName string, blackl | ||
| } | ||
| affectedSnapNames = append(affectedSnapNames, connRef.PlugRef.Snap) | ||
| affectedSnapNames = append(affectedSnapNames, connRef.SlotRef.Snap) | ||
| - conns[key] = connState{Interface: plug.Interface, Auto: true} | ||
| + conns[key] = repo.ConnState{Interface: plug.Interface, Auto: true} | ||
| } | ||
| // Auto-connect all the slots | ||
| for _, slot := range m.repo.Slots(snapName) { | ||
| @@ -412,7 +298,7 @@ func (m *InterfaceManager) autoConnect(task *state.Task, snapName string, blackl | ||
| } | ||
| affectedSnapNames = append(affectedSnapNames, connRef.PlugRef.Snap) | ||
| affectedSnapNames = append(affectedSnapNames, connRef.SlotRef.Snap) | ||
| - conns[key] = connState{Interface: plug.Interface, Auto: true} | ||
| + conns[key] = repo.ConnState{Interface: plug.Interface, Auto: true} | ||
| } | ||
| } | ||
| @@ -432,19 +318,10 @@ func getPlugAndSlotRefs(task *state.Task) (interfaces.PlugRef, interfaces.SlotRe | ||
| return plugRef, slotRef, nil | ||
| } | ||
| -func getConns(st *state.State) (map[string]connState, error) { | ||
| - // Get information about connections from the state | ||
| - var conns map[string]connState | ||
| - err := st.Get("conns", &conns) | ||
| - if err != nil && err != state.ErrNoState { | ||
| - return nil, fmt.Errorf("cannot obtain data about existing connections: %s", err) | ||
| - } | ||
| - if conns == nil { | ||
| - conns = make(map[string]connState) | ||
| - } | ||
| - return conns, nil | ||
| +func getConns(st *state.State) (map[string]repo.ConnState, error) { | ||
| + return repo.GetConns(st) | ||
| } | ||
| -func setConns(st *state.State, conns map[string]connState) { | ||
| - st.Set("conns", conns) | ||
| +func setConns(st *state.State, conns map[string]repo.ConnState) { | ||
| + repo.SetConns(st, conns) | ||
| } | ||
View
19
overlord/ifacestate/ifacemgr.go
| @@ -23,6 +23,8 @@ import ( | ||
| "github.com/snapcore/snapd/interfaces" | ||
| "github.com/snapcore/snapd/interfaces/backends" | ||
| "github.com/snapcore/snapd/overlord/hookstate" | ||
| + "github.com/snapcore/snapd/overlord/ifacestate/repo" | ||
| + "github.com/snapcore/snapd/overlord/snapstate" | ||
| "github.com/snapcore/snapd/overlord/state" | ||
| ) | ||
| @@ -45,14 +47,27 @@ func Manager(s *state.State, hookManager *hookstate.HookManager, extraInterfaces | ||
| setupHooks(hookManager) | ||
| } | ||
| + s.Lock() | ||
| + snaps, err := snapstate.ActiveInfos(s) | ||
| + s.Unlock() | ||
| + if err != nil { | ||
| + return nil, err | ||
| + } | ||
| + s.Lock() | ||
| + repo, err := repo.New(s, snaps, extraInterfaces, extraBackends) | ||
| + s.Unlock() | ||
| + if err != nil { | ||
| + return nil, err | ||
| + } | ||
| + | ||
| runner := state.NewTaskRunner(s) | ||
| m := &InterfaceManager{ | ||
| state: s, | ||
| runner: runner, | ||
| - repo: interfaces.NewRepository(), | ||
| + repo: repo, | ||
| } | ||
| - if err := m.initialize(extraInterfaces, extraBackends); err != nil { | ||
| + if err := m.initialize(); err != nil { | ||
| return nil, err | ||
| } | ||
View
32
overlord/ifacestate/implicit.go
| @@ -20,38 +20,10 @@ | ||
| package ifacestate | ||
| import ( | ||
| - "github.com/snapcore/snapd/interfaces" | ||
| - "github.com/snapcore/snapd/interfaces/builtin" | ||
| - "github.com/snapcore/snapd/release" | ||
| + "github.com/snapcore/snapd/overlord/ifacestate/repo" | ||
| "github.com/snapcore/snapd/snap" | ||
| ) | ||
| -// addImplicitSlots adds implicitly defined slots to a given snap. | ||
| -// | ||
| -// Only the OS snap has implicit slots. | ||
| -// | ||
| -// It is assumed that slots have names matching the interface name. Existing | ||
| -// slots are not changed, only missing slots are added. | ||
| func addImplicitSlots(snapInfo *snap.Info) { | ||
| - if snapInfo.Type != snap.TypeOS { | ||
| - return | ||
| - } | ||
| - // Ask each interface if it wants to be implcitly added. | ||
| - for _, iface := range builtin.Interfaces() { | ||
| - si := interfaces.StaticInfoOf(iface) | ||
| - if (release.OnClassic && si.ImplicitOnClassic) || (!release.OnClassic && si.ImplicitOnCore) { | ||
| - ifaceName := iface.Name() | ||
| - if _, ok := snapInfo.Slots[ifaceName]; !ok { | ||
| - snapInfo.Slots[ifaceName] = makeImplicitSlot(snapInfo, ifaceName) | ||
| - } | ||
| - } | ||
| - } | ||
| -} | ||
| - | ||
| -func makeImplicitSlot(snapInfo *snap.Info, ifaceName string) *snap.SlotInfo { | ||
| - return &snap.SlotInfo{ | ||
| - Name: ifaceName, | ||
| - Snap: snapInfo, | ||
| - Interface: ifaceName, | ||
| - } | ||
| + repo.AddImplicitSlots(snapInfo) | ||
| } | ||
Oops, something went wrong.