Esempio n. 1
0
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
}
Esempio n. 2
0
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
}
Esempio n. 3
0
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
}
Esempio n. 4
0
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
}