diff --git a/api/sys_leader.go b/api/sys_leader.go index 170a55ffb..dfef8345c 100644 --- a/api/sys_leader.go +++ b/api/sys_leader.go @@ -19,8 +19,10 @@ func (c *Sys) Leader() (*LeaderResponse, error) { } type LeaderResponse struct { - HAEnabled bool `json:"ha_enabled"` - IsSelf bool `json:"is_self"` - LeaderAddress string `json:"leader_address"` - LeaderClusterAddress string `json:"leader_cluster_address"` + HAEnabled bool `json:"ha_enabled"` + IsSelf bool `json:"is_self"` + LeaderAddress string `json:"leader_address"` + LeaderClusterAddress string `json:"leader_cluster_address"` + PerfStandby bool `json:"performance_standby"` + PerfStandbyLastRemoteWAL uint64 `json:"performance_standby_last_remote_wal"` } diff --git a/command/format.go b/command/format.go index 7e8230b08..2ef255663 100644 --- a/command/format.go +++ b/command/format.go @@ -367,6 +367,11 @@ func OutputSealStatus(ui cli.Ui, client *api.Client, status *api.SealStatusRespo if showLeaderAddr { out = append(out, fmt.Sprintf("Active Node Address | %s", leaderStatus.LeaderAddress)) } + + if leaderStatus.PerfStandby { + out = append(out, fmt.Sprintf("Performance Standby Node | %t", leaderStatus.PerfStandby)) + out = append(out, fmt.Sprintf("Performance Standby Last Remote WAL | %d", leaderStatus.PerfStandbyLastRemoteWAL)) + } } } diff --git a/http/sys_leader.go b/http/sys_leader.go index 98eb04ac1..0f5305a3f 100644 --- a/http/sys_leader.go +++ b/http/sys_leader.go @@ -29,18 +29,25 @@ func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, r *http.Request respondError(w, http.StatusInternalServerError, err) return } - - respondOk(w, &LeaderResponse{ + resp := &LeaderResponse{ HAEnabled: haEnabled, IsSelf: isLeader, LeaderAddress: address, LeaderClusterAddress: clusterAddr, - }) + PerfStandby: core.PerfStandby(), + } + if resp.PerfStandby { + resp.PerfStandbyLastRemoteWAL = vault.LastRemoteWAL(core) + } + + respondOk(w, resp) } type LeaderResponse struct { - HAEnabled bool `json:"ha_enabled"` - IsSelf bool `json:"is_self"` - LeaderAddress string `json:"leader_address"` - LeaderClusterAddress string `json:"leader_cluster_address"` + HAEnabled bool `json:"ha_enabled"` + IsSelf bool `json:"is_self"` + LeaderAddress string `json:"leader_address"` + LeaderClusterAddress string `json:"leader_cluster_address"` + PerfStandby bool `json:"performance_standby"` + PerfStandbyLastRemoteWAL uint64 `json:"performance_standby_last_remote_wal"` } diff --git a/http/sys_leader_test.go b/http/sys_leader_test.go index afe0dbdaa..6bf0e4a46 100644 --- a/http/sys_leader_test.go +++ b/http/sys_leader_test.go @@ -1,6 +1,7 @@ package http import ( + "encoding/json" "net/http" "reflect" "testing" @@ -20,10 +21,12 @@ func TestSysLeader_get(t *testing.T) { var actual map[string]interface{} expected := map[string]interface{}{ - "ha_enabled": false, - "is_self": false, - "leader_address": "", - "leader_cluster_address": "", + "ha_enabled": false, + "is_self": false, + "leader_address": "", + "leader_cluster_address": "", + "performance_standby": false, + "performance_standby_last_remote_wal": json.Number("0"), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) diff --git a/vault/core.go b/vault/core.go index b913a2a05..0c24e1921 100644 --- a/vault/core.go +++ b/vault/core.go @@ -169,6 +169,7 @@ type Core struct { sealed *uint32 standby bool + perfStandby bool standbyDoneCh chan struct{} standbyStopCh chan struct{} manualStepDownCh chan struct{} diff --git a/vault/ha.go b/vault/ha.go index 5e6f71b46..f13956eb9 100644 --- a/vault/ha.go +++ b/vault/ha.go @@ -61,6 +61,14 @@ func (c *Core) Standby() (bool, error) { return standby, nil } +// PerfStandby checks if the vault is a performance standby +func (c *Core) PerfStandby() bool { + c.stateLock.RLock() + perfStandby := c.perfStandby + c.stateLock.RUnlock() + return perfStandby +} + // Leader is used to get the current active leader func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err error) { // Check if HA enabled. We don't need the lock for this check as it's set