forked from lf-edge/eve
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathforcefallback.go
More file actions
129 lines (113 loc) · 4.13 KB
/
forcefallback.go
File metadata and controls
129 lines (113 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright (c) 2020 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0
package baseosmgr
import (
"strconv"
"github.com/lf-edge/eve/pkg/pillar/types"
fileutils "github.com/lf-edge/eve/pkg/pillar/utils/file"
"github.com/lf-edge/eve/pkg/pillar/zboot"
)
const (
// XXX move to locationconst.go?
forcefallbackFilename = types.CheckpointDirname + "/forceFallbackCounter"
)
// handle zedagent status events to look if the ForceFallbackCounter changes
func handleZedAgentStatusCreate(ctxArg interface{}, key string,
statusArg interface{}) {
handleZedAgentStatusImpl(ctxArg, key, statusArg)
}
func handleZedAgentStatusModify(ctxArg interface{}, key string,
statusArg interface{}, oldStatusArg interface{}) {
handleZedAgentStatusImpl(ctxArg, key, statusArg)
}
func handleZedAgentStatusImpl(ctxArg interface{}, key string,
statusArg interface{}) {
ctxPtr := ctxArg.(*baseOsMgrContext)
status := statusArg.(types.ZedAgentStatus)
handleForceFallback(ctxPtr, status)
log.Functionf("handleZedAgentStatusImpl(%s) done", key)
}
func handleZedAgentStatusDelete(ctxArg interface{}, key string,
statusArg interface{}) {
// do nothing
log.Functionf("handleZedAgentStatusDelete(%s) done", key)
}
// handleForceFallback checks if we have a file with a ForceFallbackCounter
// and if so, if the counter has changed.
// If it has, then if the current partition is active, the other partition is
// unused and the other partition has some non-empty EVE version string,
// then it will mark the other partition as Updating.
// This update to ZbootStatus will make nodeagent trigger a reboot.
func handleForceFallback(ctxPtr *baseOsMgrContext, status types.ZedAgentStatus) {
counter, found := readForceFallbackCounter()
if !found {
// Just write the current value
log.Functionf("Saving initial ForceFallbackCounter %d",
status.ForceFallbackCounter)
writeForceFallbackCounter(status.ForceFallbackCounter)
return
}
if counter == status.ForceFallbackCounter {
log.Functionf("No change to ForceFallbackCounter %d", counter)
return
}
log.Noticef("Handle ForceFallbackCounter update from %d to %d",
counter, status.ForceFallbackCounter)
curPartName := zboot.GetCurrentPartition()
partStatus := getZbootStatus(ctxPtr, curPartName)
if partStatus == nil {
log.Warnf("No current partition status for %s; ignoring ForceFallback",
curPartName)
return
}
if partStatus.PartitionState != "active" {
log.Warnf("Current partition state %s not active; ignoring ForceFallback",
partStatus.PartitionState)
return
}
shortVerCurPart := partStatus.ShortVersion
otherPartName := zboot.GetOtherPartition()
partStatus = getZbootStatus(ctxPtr, otherPartName)
if partStatus == nil {
log.Warnf("No other partition status for %s; ignoring ForceFallback",
otherPartName)
return
}
shortVerOtherPart := partStatus.ShortVersion
if shortVerOtherPart == "" {
log.Warnf("Other partition has no version; ignoring ForceFallback")
return
}
if partStatus.PartitionState != "unused" {
log.Warnf("Other partition state %s not unused; ignoring ForceFallback",
partStatus.PartitionState)
return
}
log.Noticef("ForceFallback from %s to %s",
shortVerCurPart, shortVerOtherPart)
zboot.SetOtherPartitionStateUpdating(log)
updateAndPublishZbootStatus(ctxPtr,
partStatus.PartitionLabel, false)
baseOsStatus := lookupBaseOsStatusByPartLabel(ctxPtr, partStatus.PartitionLabel)
if baseOsStatus != nil {
baseOsSetPartitionInfoInStatus(ctxPtr, baseOsStatus,
partStatus.PartitionLabel)
publishBaseOsStatus(ctxPtr, baseOsStatus)
}
writeForceFallbackCounter(status.ForceFallbackCounter)
}
// readForceFallbackCounter reads the persistent file
// If the file doesn't exist or doesn't contain an integer it returns false
func readForceFallbackCounter() (int, bool) {
c, parsed := fileutils.ReadSavedCounter(log, forcefallbackFilename)
return int(c), parsed
}
// writeForceFallbackCounter writes the persistent file
// Errors are logged but otherwise ignored
func writeForceFallbackCounter(fallbackCounter int) {
b := []byte(strconv.Itoa(fallbackCounter))
err := fileutils.WriteRename(forcefallbackFilename, b)
if err != nil {
log.Errorf("writeForceFallbackCounter write: %s", err)
}
}