[lxc-devel] [lxd/master] Trigger the upgrade script if we detect a dqlite client with higher version [WIP]
freeekanayaka on Github
lxc-bot at linuxcontainers.org
Tue May 21 19:18:56 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 363 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190521/52433645/attachment.bin>
-------------- next part --------------
From 4bf0346d36c38295488da59813466d285c7664a7 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 21 May 2019 13:48:24 +0200
Subject: [PATCH] Trigger the upgrade script if we detect a dqlite client with
higher version
Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
lxd/cluster/gateway.go | 30 ++++++++++++++++++++++++++++++
lxd/cluster/upgrade.go | 11 ++++++++---
2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/lxd/cluster/gateway.go b/lxd/cluster/gateway.go
index c34fdd1c0a..29d3337752 100644
--- a/lxd/cluster/gateway.go
+++ b/lxd/cluster/gateway.go
@@ -98,12 +98,19 @@ type Gateway struct {
// their version.
upgradeCh chan struct{}
+ // Used to track whether we already triggered an upgrade because we
+ // detected a peer with an higher version.
+ upgradeTriggered bool
+
// ServerStore wrapper.
store *dqliteServerStore
lock sync.RWMutex
}
+// Current dqlite protocol version.
+const dqliteVersion = 0
+
// HandlerFuncs returns the HTTP handlers that should be added to the REST API
// endpoint in order to handle database-related requests.
//
@@ -123,6 +130,29 @@ func (g *Gateway) HandlerFuncs() map[string]http.HandlerFunc {
return
}
+ // Compare the dqlite version of the connecting client
+ // with our own one.
+ versionHeader := r.Header.Get("X-Dqlite-Version")
+ if versionHeader == "" {
+ // No version header means an old pre dqlite 1.0 client.
+ versionHeader = "0"
+ }
+ version, err := strconv.Atoi(versionHeader)
+ if err != nil {
+ http.Error(w, "400 invalid dqlite version", http.StatusBadRequest)
+ return
+ }
+ if version != dqliteVersion {
+ if !g.upgradeTriggered && version > dqliteVersion {
+ err = triggerUpdate()
+ if err == nil {
+ g.upgradeTriggered = true
+ }
+ }
+ http.Error(w, "503 dqlite version mismatch", http.StatusServiceUnavailable)
+ return
+ }
+
// Handle heatbeats.
if r.Method == "PUT" {
var nodes []db.RaftNode
diff --git a/lxd/cluster/upgrade.go b/lxd/cluster/upgrade.go
index c4165343e4..df649da997 100644
--- a/lxd/cluster/upgrade.go
+++ b/lxd/cluster/upgrade.go
@@ -110,19 +110,24 @@ func maybeUpdate(state *state.State) {
return
}
+ triggerUpdate()
+}
+
+func triggerUpdate() error {
logger.Infof("Node is out-of-date with respect to other cluster nodes")
updateExecutable := os.Getenv("LXD_CLUSTER_UPDATE")
if updateExecutable == "" {
logger.Debug("No LXD_CLUSTER_UPDATE variable set, skipping auto-update")
- return
+ return nil
}
logger.Infof("Triggering cluster update using: %s", updateExecutable)
- _, err = shared.RunCommand(updateExecutable)
+ _, err := shared.RunCommand(updateExecutable)
if err != nil {
logger.Errorf("Cluster upgrade failed: '%v'", err.Error())
- return
+ return err
}
+ return nil
}
More information about the lxc-devel
mailing list