From a43d9ed7047acc3d8c8307872c75b031001f65f6 Mon Sep 17 00:00:00 2001 From: Andrew Phelps Date: Wed, 15 Jan 2025 14:50:59 -0500 Subject: [PATCH] o/snapstate: put MaybeReboot edges on link-snap in AddLinkNewBaseOrKernel and LinkNewBaseOrKernel Sometimes during a remodel, we need to create link-snap tasks for snaps that are already installed, but not yet considered boot participants. These tasks were missing reboot boundaries, which caused the tasks to be marked as done before the reboot completed. tests/nested/manual/remodel-offline exhibits this behavior, where core22 already is installed, but not the model's base snap. The link-snap task that was created during the remodel was being marked as done before the reboot that the task triggers completed. With this change, the entire remodel change will not be marked as done until that link-snap task triggers is completed --- overlord/snapstate/snapstate.go | 2 ++ overlord/snapstate/snapstate_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/overlord/snapstate/snapstate.go b/overlord/snapstate/snapstate.go index dc596b256cb..334387d67eb 100644 --- a/overlord/snapstate/snapstate.go +++ b/overlord/snapstate/snapstate.go @@ -3428,6 +3428,7 @@ func LinkNewBaseOrKernel(st *state.State, name string, fromChange string) (*stat linkSnap.Set("snap-setup-task", prepareSnap.ID()) linkSnap.WaitFor(prev) ts.AddTask(linkSnap) + ts.MarkEdge(linkSnap, MaybeRebootEdge) // prepare-snap is the last task that carries no system modifications ts.MarkEdge(prepareSnap, LastBeforeLocalModificationsEdge) ts.MarkEdge(prepareSnap, SnapSetupEdge) @@ -3490,6 +3491,7 @@ func AddLinkNewBaseOrKernel(st *state.State, ts *state.TaskSet) (*state.TaskSet, linkSnap.Set("snap-setup-task", snapSetupTask.ID()) linkSnap.WaitFor(prev) ts.AddTask(linkSnap) + ts.MarkEdge(linkSnap, MaybeRebootEdge) // make sure that remodel can identify which tasks introduce actual // changes to the system and order them correctly if edgeTask := ts.MaybeEdge(LastBeforeLocalModificationsEdge); edgeTask == nil { diff --git a/overlord/snapstate/snapstate_test.go b/overlord/snapstate/snapstate_test.go index f3a544bca54..decfb3708de 100644 --- a/overlord/snapstate/snapstate_test.go +++ b/overlord/snapstate/snapstate_test.go @@ -8162,6 +8162,7 @@ func (s *snapmgrTestSuite) testRemodelLinkNewBaseOrKernelHappy(c *C, model *asse c.Assert(tLink.Kind(), Equals, "link-snap") c.Assert(tLink.Summary(), Equals, `Make snap "some-kernel" (2) available to the system during remodel`) c.Assert(tLink.WaitTasks(), DeepEquals, []*state.Task{tUpdateGadgetAssets}) + c.Assert(ts.MaybeEdge(snapstate.MaybeRebootEdge), Equals, tLink) ts, err = snapstate.LinkNewBaseOrKernel(s.state, "some-base", "") c.Assert(err, IsNil) @@ -8175,6 +8176,7 @@ func (s *snapmgrTestSuite) testRemodelLinkNewBaseOrKernelHappy(c *C, model *asse c.Assert(tPrepare.Has("snap-setup"), Equals, true) c.Assert(tLink.Kind(), Equals, "link-snap") c.Assert(tLink.Summary(), Equals, `Make snap "some-base" (1) available to the system during remodel`) + c.Assert(ts.MaybeEdge(snapstate.MaybeRebootEdge), Equals, tLink) } func (s *snapmgrTestSuite) TestRemodelLinkNewBaseOrKernelBadType(c *C) { @@ -8291,6 +8293,7 @@ func (s *snapmgrTestSuite) testRemodelAddLinkNewBaseOrKernel(c *C, model *assert c.Assert(tsk.Get("snap-setup-task", &ssID), IsNil) c.Assert(ssID, Equals, tPrepare.ID()) } + c.Assert(tsNew.MaybeEdge(snapstate.MaybeRebootEdge), Equals, tLink) // try with base snap si = &snap.SideInfo{RealName: "some-base", Revision: snap.R(1)} @@ -8313,6 +8316,7 @@ func (s *snapmgrTestSuite) testRemodelAddLinkNewBaseOrKernel(c *C, model *assert var ssID string c.Assert(tLink.Get("snap-setup-task", &ssID), IsNil) c.Assert(ssID, Equals, tPrepare.ID()) + c.Assert(tsNew.MaybeEdge(snapstate.MaybeRebootEdge), Equals, tLink) // but bails when there is no task with snap setup ts = state.NewTaskSet()