func (m *InterfaceManager) doDisconnect(task *state.Task, _ *tomb.Tomb) error { st := task.State() st.Lock() defer st.Unlock() plugRef, slotRef, err := getPlugAndSlotRefs(task) if err != nil { return err } conns, err := getConns(st) if err != nil { return err } var affectedConns []interfaces.ConnRef if plugRef.Snap != "" && plugRef.Name != "" && slotRef.Snap != "" && slotRef.Name != "" { if err := m.repo.Disconnect(plugRef.Snap, plugRef.Name, slotRef.Snap, slotRef.Name); err != nil { return err } affectedConns = []interfaces.ConnRef{{plugRef, slotRef}} } else if plugRef.Name != "" && slotRef.Snap == "" && slotRef.Name == "" { // NOTE: plugRef.Snap can be either empty or not, Connected handles both affectedConns, err = m.repo.Connected(plugRef.Snap, plugRef.Name) if err != nil { return err } m.repo.DisconnectAll(affectedConns) } else if plugRef.Snap == "" && plugRef.Name == "" && slotRef.Name != "" { // Symmetrically, slotRef.Snap can be either empty or not affectedConns, err = m.repo.Connected(slotRef.Snap, slotRef.Name) if err != nil { return err } m.repo.DisconnectAll(affectedConns) } else { return fmt.Errorf("internal error, unhandled disconnect case plug: %q, slot: %q", plugRef, slotRef) } affectedSnaps := snapNamesFromConns(affectedConns) for _, snapName := range affectedSnaps { var snapst snapstate.SnapState if err := snapstate.Get(st, snapName, &snapst); err != nil { return err } snapInfo, err := snapst.CurrentInfo() if err != nil { return err } if err := setupSnapSecurity(task, snapInfo, snapst.DevModeAllowed(), m.repo); err != nil { return &state.Retry{} } } for _, conn := range affectedConns { delete(conns, conn.ID()) } setConns(st, conns) return nil }
func (m *InterfaceManager) doConnect(task *state.Task, _ *tomb.Tomb) error { st := task.State() st.Lock() defer st.Unlock() plugRef, slotRef, err := getPlugAndSlotRefs(task) if err != nil { return err } conns, err := getConns(st) if err != nil { return err } err = m.repo.Connect(plugRef.Snap, plugRef.Name, slotRef.Snap, slotRef.Name) if err != nil { return err } plug := m.repo.Plug(plugRef.Snap, plugRef.Name) var plugSnapst snapstate.SnapState if err := snapstate.Get(st, plugRef.Snap, &plugSnapst); err != nil { return err } slot := m.repo.Slot(slotRef.Snap, slotRef.Name) var slotSnapst snapstate.SnapState if err := snapstate.Get(st, slotRef.Snap, &slotSnapst); err != nil { return err } if err := setupSnapSecurity(task, plug.Snap, plugSnapst.DevModeAllowed(), m.repo); err != nil { return err } if err := setupSnapSecurity(task, slot.Snap, slotSnapst.DevModeAllowed(), m.repo); err != nil { return err } conns[connID(plugRef, slotRef)] = connState{Interface: plug.Interface} setConns(st, conns) return nil }
func (m *InterfaceManager) setupAffectedSnaps(task *state.Task, affectingSnap string, affectedSnaps []string) error { st := task.State() // Setup security of the affected snaps. for _, affectedSnapName := range affectedSnaps { // the snap that triggered the change needs to be skipped if affectedSnapName == affectingSnap { continue } var snapst snapstate.SnapState if err := snapstate.Get(st, affectedSnapName, &snapst); err != nil { return err } affectedSnapInfo, err := snapst.CurrentInfo() if err != nil { return err } snap.AddImplicitSlots(affectedSnapInfo) if err := setupSnapSecurity(task, affectedSnapInfo, snapst.DevModeAllowed(), m.repo); err != nil { return err } } return nil }
func (m *InterfaceManager) doConnect(task *state.Task, _ *tomb.Tomb) error { st := task.State() st.Lock() defer st.Unlock() plugRef, slotRef, err := getPlugAndSlotRefs(task) if err != nil { return err } conns, err := getConns(st) if err != nil { return err } connRef, err := m.repo.ResolveConnect(plugRef.Snap, plugRef.Name, slotRef.Snap, slotRef.Name) if err != nil { return err } plug := m.repo.Plug(connRef.PlugRef.Snap, connRef.PlugRef.Name) if plug == nil { return fmt.Errorf("snap %q has no %q plug", connRef.PlugRef.Snap, connRef.PlugRef.Name) } var plugDecl *asserts.SnapDeclaration if plug.Snap.SnapID != "" { var err error plugDecl, err = assertstate.SnapDeclaration(st, plug.Snap.SnapID) if err != nil { return fmt.Errorf("cannot find snap declaration for %q: %v", plug.Snap.Name(), err) } } slot := m.repo.Slot(connRef.SlotRef.Snap, connRef.SlotRef.Name) if slot == nil { return fmt.Errorf("snap %q has no %q slot", connRef.SlotRef.Snap, connRef.SlotRef.Name) } var slotDecl *asserts.SnapDeclaration if slot.Snap.SnapID != "" { var err error slotDecl, err = assertstate.SnapDeclaration(st, slot.Snap.SnapID) if err != nil { return fmt.Errorf("cannot find snap declaration for %q: %v", slot.Snap.Name(), err) } } baseDecl, err := assertstate.BaseDeclaration(st) if err != nil { return fmt.Errorf("internal error: cannot find base declaration: %v", err) } // check the connection against the declarations' rules ic := policy.ConnectCandidate{ Plug: plug.PlugInfo, PlugSnapDeclaration: plugDecl, Slot: slot.SlotInfo, SlotSnapDeclaration: slotDecl, BaseDeclaration: baseDecl, } err = ic.Check() if err != nil { return err } err = m.repo.Connect(connRef) if err != nil { return err } var plugSnapst snapstate.SnapState if err := snapstate.Get(st, connRef.PlugRef.Snap, &plugSnapst); err != nil { return err } var slotSnapst snapstate.SnapState if err := snapstate.Get(st, connRef.SlotRef.Snap, &slotSnapst); err != nil { return err } if err := setupSnapSecurity(task, slot.Snap, slotSnapst.DevModeAllowed(), m.repo); err != nil { return err } if err := setupSnapSecurity(task, plug.Snap, plugSnapst.DevModeAllowed(), m.repo); err != nil { return err } conns[connRef.ID()] = connState{Interface: plug.Interface} setConns(st, conns) return nil }