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) }
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) }
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 }