Skip to content

Commit 7b2c713

Browse files
o/snapstate, o/s/backend: move SortServices into Backend.StartServices (#16992)
Follows @pedronis's feedback at https://github.com/canonical/snapd/pull/16861/changes#r3137999181 As all callers of `Backend.StartServices` currently do (and will need to do) `snap.SortServices`, we just move the sorting into `Backend.StartServices`. [SNAPDENG-36831](https://warthogs.atlassian.net/browse/SNAPDENG-36831)
1 parent 8973825 commit 7b2c713

4 files changed

Lines changed: 56 additions & 28 deletions

File tree

overlord/snapstate/backend/link.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,24 +245,24 @@ func (b Backend) LinkComponent(cpi snap.ContainerPlaceInfo, snapRev snap.Revisio
245245
}
246246

247247
func (b Backend) StartServices(apps []*snap.AppInfo, disabledSvcs *wrappers.DisabledServices, meter progress.Meter, tm timings.Measurer) error {
248+
// Services need to be sorted according to their Before
249+
// and After requirements
250+
startupOrdered, err := snap.SortServices(apps)
251+
if err != nil {
252+
return err
253+
}
248254
opts := &wrappers.StartServicesOptions{Enable: true}
249-
return wrappersStartServices(apps, disabledSvcs, opts, meter, tm)
255+
return wrappersStartServices(startupOrdered, disabledSvcs, opts, meter, tm)
250256
}
251257

252258
func (b Backend) StopServices(apps []*snap.AppInfo, removedSvcs map[string]*snap.AppInfo, disabledSvcs *wrappers.DisabledServices, reason snap.ServiceStopReason, undoer Undoer, meter progress.Meter, tm timings.Measurer) error {
253259
// Register the undo before stopping so that services are
254260
// started again even when StopServices fails partway through
255261
// (some services stopped, then an error on a later one).
256262
undoer.AddUndo(func() error {
257-
// Services need to be sorted according to their Before
258-
// and After requirements
259-
startupOrdered, err := snap.SortServices(apps)
260-
if err != nil {
261-
return fmt.Errorf("cannot sort services for undo: %v", err)
262-
}
263263
// StartServices filters out disabled services, so only
264264
// previously enabled services will be started again.
265-
return b.StartServices(startupOrdered, disabledSvcs, meter, tm)
265+
return b.StartServices(apps, disabledSvcs, meter, tm)
266266
})
267267
return wrappersStopServices(apps, removedSvcs, nil, reason, meter, tm)
268268
}

overlord/snapstate/backend/link_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,44 @@ func (s *linkSuite) TestStartServices(c *C) {
12341234
c.Assert(called, Equals, 1)
12351235
}
12361236

1237+
func (s *linkSuite) TestStartServicesSortsServices(c *C) {
1238+
var sortedNames []string
1239+
restore := backend.MockWrappersStartServices(func(apps []*snap.AppInfo, disabledSvcs *wrappers.DisabledServices, opts *wrappers.StartServicesOptions, inter wrappers.Interacter, tm timings.Measurer) error {
1240+
sortedNames = make([]string, len(apps))
1241+
for i, app := range apps {
1242+
sortedNames[i] = app.Name
1243+
}
1244+
return nil
1245+
})
1246+
defer restore()
1247+
1248+
svc1 := &snap.AppInfo{Name: "svc1", Before: []string{"svc3"}}
1249+
svc2 := &snap.AppInfo{Name: "svc2", After: []string{"svc1"}}
1250+
svc3 := &snap.AppInfo{Name: "svc3", Before: []string{"svc2"}}
1251+
1252+
// pass in unsorted order
1253+
apps := []*snap.AppInfo{svc1, svc2, svc3}
1254+
err := s.be.StartServices(apps, nil, progress.Null, s.perfTimings)
1255+
c.Assert(err, IsNil)
1256+
// wrappers.StartServices should receive them sorted
1257+
c.Check(sortedNames, DeepEquals, []string{"svc1", "svc3", "svc2"})
1258+
}
1259+
1260+
func (s *linkSuite) TestStartServicesFailsOnCycle(c *C) {
1261+
restore := backend.MockWrappersStartServices(func(apps []*snap.AppInfo, disabledSvcs *wrappers.DisabledServices, opts *wrappers.StartServicesOptions, inter wrappers.Interacter, tm timings.Measurer) error {
1262+
c.Fatal("wrappers.StartServices should not be called when sorting fails")
1263+
return nil
1264+
})
1265+
defer restore()
1266+
1267+
svc1 := &snap.AppInfo{Name: "svc1", After: []string{"svc2"}}
1268+
svc2 := &snap.AppInfo{Name: "svc2", After: []string{"svc1"}}
1269+
1270+
apps := []*snap.AppInfo{svc1, svc2}
1271+
err := s.be.StartServices(apps, nil, progress.Null, s.perfTimings)
1272+
c.Assert(err, ErrorMatches, "applications are part of a before/after cycle: .*")
1273+
}
1274+
12371275
type nullUndoer struct{}
12381276

12391277
func (nu nullUndoer) AddUndo(f func() error) {}

overlord/snapstate/backend_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,13 +1464,17 @@ func svcSnapMountDir(svcs []*snap.AppInfo) string {
14641464
}
14651465

14661466
func (f *fakeSnappyBackend) StartServices(svcs []*snap.AppInfo, disabledSvcs *wrappers.DisabledServices, meter progress.Meter, tm timings.Measurer) error {
1467-
services := make([]string, 0, len(svcs))
1468-
for _, svc := range svcs {
1467+
startupOrdered, err := snap.SortServices(svcs)
1468+
if err != nil {
1469+
return err
1470+
}
1471+
services := make([]string, 0, len(startupOrdered))
1472+
for _, svc := range startupOrdered {
14691473
services = append(services, svc.Name)
14701474
}
14711475
op := fakeOp{
14721476
op: "start-snap-services",
1473-
path: svcSnapMountDir(svcs),
1477+
path: svcSnapMountDir(startupOrdered),
14741478
services: services,
14751479
}
14761480
// only add the services to the op if there's something to add
@@ -1509,11 +1513,7 @@ func (f *fakeSnappyBackend) StopServices(svcs []*snap.AppInfo, rmSvcs map[string
15091513
}
15101514

15111515
undoer.AddUndo(func() error {
1512-
startupOrdered, err := snap.SortServices(svcs)
1513-
if err != nil {
1514-
return fmt.Errorf("cannot sort services for undo: %v", err)
1515-
}
1516-
return f.StartServices(startupOrdered, disabledSvcs, meter, tm)
1516+
return f.StartServices(svcs, disabledSvcs, meter, tm)
15171517
})
15181518

15191519
f.appendOp(&fakeOp{

overlord/snapstate/handlers.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,15 +3505,10 @@ func (m *SnapManager) startSnapServices(t *state.Task, _ *tomb.Tomb) error {
35053505
return nil
35063506
}
35073507

3508-
startupOrdered, err := snap.SortServices(svcs)
3509-
if err != nil {
3510-
return err
3511-
}
3512-
35133508
pb := NewTaskProgressAdapterUnlocked(t)
35143509

35153510
st.Unlock()
3516-
err = m.backend.StartServices(startupOrdered, &wrappers.DisabledServices{
3511+
err = m.backend.StartServices(svcs, &wrappers.DisabledServices{
35173512
SystemServices: missingSvcsOverview.FoundSystemServices,
35183513
UserServices: missingSvcsOverview.FoundUserServices,
35193514
}, pb, perfTimings)
@@ -3715,11 +3710,6 @@ func (m *SnapManager) undoStopSnapServices(t *state.Task, _ *tomb.Tomb) error {
37153710
return nil
37163711
}
37173712

3718-
startupOrdered, err := snap.SortServices(svcs)
3719-
if err != nil {
3720-
return err
3721-
}
3722-
37233713
var oldLastActiveDisabledServices []string
37243714
var oldLastActiveDisabledUserServices map[int][]string
37253715
if err := t.Get("old-last-active-disabled-services", &oldLastActiveDisabledServices); err != nil && !errors.Is(err, state.ErrNoState) {
@@ -3738,7 +3728,7 @@ func (m *SnapManager) undoStopSnapServices(t *state.Task, _ *tomb.Tomb) error {
37383728
}
37393729

37403730
st.Unlock()
3741-
err = m.backend.StartServices(startupOrdered, &disabledServices, progress.Null, perfTimings)
3731+
err = m.backend.StartServices(svcs, &disabledServices, progress.Null, perfTimings)
37423732
st.Lock()
37433733
if err != nil {
37443734
return err

0 commit comments

Comments
 (0)