Ejemplo n.º 1
0
func (s *kernelOSSuite) TestSetNextBootForKernel(c *C) {
	restore := release.MockOnClassic(false)
	defer restore()

	info := &snap.Info{}
	info.Type = snap.TypeKernel
	info.RealName = "krnl"
	info.Revision = snap.R(42)

	err := boot.SetNextBoot(info)
	c.Assert(err, IsNil)

	c.Assert(s.bootloader.BootVars, DeepEquals, map[string]string{
		"snap_try_kernel": "krnl_42.snap",
		"snap_mode":       "try",
	})

	s.bootloader.BootVars["snap_kernel"] = "krnl_40.snap"
	s.bootloader.BootVars["snap_try_kernel"] = "krnl_42.snap"
	c.Check(boot.KernelOrOsRebootRequired(info), Equals, true)

	// simulate good boot
	s.bootloader.BootVars["snap_kernel"] = "krnl_42.snap"
	c.Check(boot.KernelOrOsRebootRequired(info), Equals, false)
}
Ejemplo n.º 2
0
func (s *kernelOSSuite) TestSetNextBootForCore(c *C) {
	restore := release.MockOnClassic(false)
	defer restore()

	info := &snap.Info{}
	info.Type = snap.TypeOS
	info.RealName = "core"
	info.Revision = snap.R(100)

	err := boot.SetNextBoot(info)
	c.Assert(err, IsNil)

	c.Assert(s.bootloader.BootVars, DeepEquals, map[string]string{
		"snap_try_core": "core_100.snap",
		"snap_mode":     "try",
	})

	c.Check(boot.KernelOrOsRebootRequired(info), Equals, true)
}
Ejemplo n.º 3
0
func (m *SnapManager) doLinkSnap(t *state.Task, _ *tomb.Tomb) error {
	st := t.State()

	st.Lock()
	defer st.Unlock()

	snapsup, snapst, err := snapSetupAndState(t)
	if err != nil {
		return err
	}

	cand := snapsup.SideInfo
	m.backend.Candidate(cand)

	oldCandidateIndex := snapst.LastIndex(cand.Revision)

	if oldCandidateIndex < 0 {
		snapst.Sequence = append(snapst.Sequence, cand)
	} else if !snapsup.Revert {
		// remove the old candidate from the sequence, add it at the end
		copy(snapst.Sequence[oldCandidateIndex:len(snapst.Sequence)-1], snapst.Sequence[oldCandidateIndex+1:])
		snapst.Sequence[len(snapst.Sequence)-1] = cand
	}

	oldCurrent := snapst.Current
	snapst.Current = cand.Revision
	snapst.Active = true
	oldChannel := snapst.Channel
	if snapsup.Channel != "" {
		snapst.Channel = snapsup.Channel
	}
	oldTryMode := snapst.TryMode
	snapst.TryMode = snapsup.TryMode
	oldDevMode := snapst.DevMode
	snapst.DevMode = snapsup.DevMode
	oldJailMode := snapst.JailMode
	snapst.JailMode = snapsup.JailMode
	oldClassic := snapst.Classic
	snapst.Classic = snapsup.Classic

	newInfo, err := readInfo(snapsup.Name(), cand)
	if err != nil {
		return err
	}

	// record type
	snapst.SetType(newInfo.Type)

	st.Unlock()
	// XXX: this block is slightly ugly, find a pattern when we have more examples
	err = m.backend.LinkSnap(newInfo)
	if err != nil {
		pb := &TaskProgressAdapter{task: t}
		err := m.backend.UnlinkSnap(newInfo, pb)
		if err != nil {
			st.Lock()
			t.Errorf("cannot cleanup failed attempt at making snap %q available to the system: %v", snapsup.Name(), err)
			st.Unlock()
		}
	}
	st.Lock()
	if err != nil {
		return err
	}

	// save for undoLinkSnap
	t.Set("old-trymode", oldTryMode)
	t.Set("old-devmode", oldDevMode)
	t.Set("old-jailmode", oldJailMode)
	t.Set("old-classic", oldClassic)
	t.Set("old-channel", oldChannel)
	t.Set("old-current", oldCurrent)
	t.Set("old-candidate-index", oldCandidateIndex)
	// Do at the end so we only preserve the new state if it worked.
	Set(st, snapsup.Name(), snapst)
	// Make sure if state commits and snapst is mutated we won't be rerun
	t.SetStatus(state.DoneStatus)

	// if we just installed a core snap, request a restart
	// so that we switch executing its snapd
	if release.OnClassic && newInfo.Type == snap.TypeOS {
		t.Logf("Requested daemon restart.")
		st.Unlock()
		st.RequestRestart(state.RestartDaemon)
		st.Lock()
	}
	if !release.OnClassic && boot.KernelOrOsRebootRequired(newInfo) {
		t.Logf("Requested system restart.")
		st.Unlock()
		st.RequestRestart(state.RestartSystem)
		st.Lock()
	}

	return nil
}