New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
overlord/snapstate: on multi-snap refresh make sure bases and core are finished before dependent snaps #5018
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ import ( | |
"encoding/json" | ||
"fmt" | ||
"reflect" | ||
"sort" | ||
"strings" | ||
|
||
"golang.org/x/net/context" | ||
|
@@ -744,6 +745,16 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func | |
reportUpdated[snapName] = true | ||
} | ||
|
||
// first core, bases, then rest | ||
sort.Sort(byKind(updates)) | ||
prereqs := make(map[string]*state.TaskSet) | ||
waitPrereq := func(ts *state.TaskSet, prereqName string) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So |
||
preTs := prereqs[prereqName] | ||
if preTs != nil { | ||
ts.WaitAll(preTs) | ||
} | ||
} | ||
|
||
for _, update := range updates { | ||
channel, flags, snapst := params(update) | ||
|
||
|
@@ -786,6 +797,20 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func | |
} | ||
ts.JoinLane(st.NewLane()) | ||
|
||
if update.Type == snap.TypeOS || update.Type == snap.TypeBase { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please add a comment that this loop iterates over updates ordered by the priority and this makes this newly added code safe, that is, that we always have prerequisites by the time we need to read them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's was the intention of the comments inside the two if sides, but it seems they are not clear enough |
||
// prereq types come first in the updates, we | ||
// also assume bases don't have hooks, otherwise | ||
// they would need to wait on core | ||
prereqs[update.Name()] = ts | ||
} else { | ||
// prereqs were processed, wait for them as necessary | ||
// for the other kind of snaps | ||
waitPrereq(ts, defaultCoreSnapName) | ||
if update.Base != "" { | ||
waitPrereq(ts, update.Base) | ||
} | ||
} | ||
|
||
scheduleUpdate(update.Name(), ts) | ||
tasksets = append(tasksets, ts) | ||
} | ||
|
@@ -806,6 +831,22 @@ func doUpdate(st *state.State, names []string, updates []*snap.Info, params func | |
return updated, tasksets, nil | ||
} | ||
|
||
type byKind []*snap.Info | ||
|
||
func (bk byKind) Len() int { return len(bk) } | ||
func (bk byKind) Swap(i, j int) { bk[i], bk[j] = bk[j], bk[i] } | ||
|
||
var kindRevOrder = map[snap.Type]int{ | ||
snap.TypeOS: 2, | ||
snap.TypeBase: 1, | ||
} | ||
|
||
func (bk byKind) Less(i, j int) bool { | ||
iRevOrd := kindRevOrder[bk[i].Type] | ||
jRevOrd := kindRevOrder[bk[j].Type] | ||
return iRevOrd >= jRevOrd | ||
} | ||
|
||
func applyAutoAliasesDelta(st *state.State, delta map[string][]string, op string, refreshAll bool, linkTs func(snapName string, ts *state.TaskSet)) (*state.TaskSet, error) { | ||
applyTs := state.NewTaskSet() | ||
kind := "refresh-aliases" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this is a very good way to order snaps by kind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, do we need to put gadget ahead of apps here? Also kernel (probably)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not for the current problem, gadget or kernel shouldn't block running hooks in other snaps. Kernel provokes a reboot but that's a different issue.