/
gateway_prepare_shutdown_http.go
113 lines (96 loc) · 4.19 KB
/
gateway_prepare_shutdown_http.go
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
// SPDX-License-Identifier: AGPL-3.0-only
package storegateway
import (
"net/http"
"github.com/go-kit/log/level"
"github.com/grafana/dskit/services"
"github.com/pkg/errors"
"github.com/grafana/mimir/pkg/util"
"github.com/grafana/mimir/pkg/util/shutdownmarker"
)
// PrepareShutdownHandler possibly changes the configuration of the store-gateway in such a way
// that when it is stopped, it gets unregistered from the ring.
//
// Moreover, it creates a file on disk which is used to re-apply the desired configuration if the
// store-gateway crashes and restarts before being permanently shutdown.
//
// The following methods are possible:
// * `GET` shows the status of this configuration
// * `POST` enables this configuration
// * `DELETE` disables this configuration
func (g *StoreGateway) PrepareShutdownHandler(w http.ResponseWriter, req *http.Request) {
// Don't allow callers to change the shutdown configuration while we're in the middle
// of starting or shutting down.
if g.State() != services.Running {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
shutdownMarkerPath := shutdownmarker.GetPath(g.storageCfg.BucketStore.SyncDir)
switch req.Method {
case http.MethodGet:
exists, err := shutdownmarker.Exists(shutdownMarkerPath)
if err != nil {
level.Error(g.logger).Log("msg", "unable to check for prepare-shutdown marker file", "path", shutdownMarkerPath, "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if exists {
util.WriteTextResponse(w, "set\n")
} else {
util.WriteTextResponse(w, "unset\n")
}
case http.MethodPost:
if err := shutdownmarker.Create(shutdownMarkerPath); err != nil {
level.Error(g.logger).Log("msg", "unable to create prepare-shutdown marker file", "path", shutdownMarkerPath, "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
g.setPrepareShutdown()
level.Info(g.logger).Log("msg", "created prepare-shutdown marker file", "path", shutdownMarkerPath)
w.WriteHeader(http.StatusNoContent)
case http.MethodDelete:
if err := shutdownmarker.Remove(shutdownMarkerPath); err != nil {
level.Error(g.logger).Log("msg", "unable to remove prepare-shutdown marker file", "path", shutdownMarkerPath, "err", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
g.unsetPrepareShutdown()
level.Info(g.logger).Log("msg", "removed prepare-shutdown marker file", "path", shutdownMarkerPath)
w.WriteHeader(http.StatusNoContent)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
// setPrepareShutdown changes store-gateway lifecycler config to prepare for shutdown
func (g *StoreGateway) setPrepareShutdown() {
g.ringLifecycler.SetKeepInstanceInTheRingOnShutdown(false)
g.shutdownMarker.Set(1)
}
// unsetPrepareShutdown reverts to the shutdown settings to their default values
func (g *StoreGateway) unsetPrepareShutdown() {
g.ringLifecycler.SetKeepInstanceInTheRingOnShutdown(!g.gatewayCfg.ShardingRing.UnregisterOnShutdown)
g.shutdownMarker.Set(0)
}
// setPrepareShutdownFromShutdownMarker is executed on store-gateway start, and it calls setPrepareShutdown
// if shutdown marker is present. This is possible if the store-gateway crashes and restarts during a
// previous attempt to shut down.
func (g *StoreGateway) setPrepareShutdownFromShutdownMarker() error {
shutdownMarkerPath := shutdownmarker.GetPath(g.storageCfg.BucketStore.SyncDir)
shutdownMarkerFound, err := shutdownmarker.Exists(shutdownMarkerPath)
if err != nil {
return errors.Wrap(err, "failed to check store-gateway shutdown marker")
}
if shutdownMarkerFound {
level.Info(g.logger).Log("msg", "detected existing shutdown marker, setting unregister on shutdown", "path", shutdownMarkerPath)
g.setPrepareShutdown()
}
return nil
}
// unsetPrepareShutdownMarker is executed when the store-gateway successfully shuts down and removes the
// shutdown marker if it is present. It does not modify configuration in any way.
func (g *StoreGateway) unsetPrepareShutdownMarker() {
shutdownMarkerPath := shutdownmarker.GetPath(g.storageCfg.BucketStore.SyncDir)
if err := shutdownmarker.Remove(shutdownMarkerPath); err != nil {
level.Warn(g.logger).Log("msg", "failed to remove shutdown marker", "path", shutdownMarkerPath, "err", err)
}
}