mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
api/leader: fix deadlock when namespace is set on leader calls (#24256)
* api/leader: fix deadlock when namespace is set on leader calls * Add cl
This commit is contained in:
4
changelog/24256.txt
Normal file
4
changelog/24256.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
```release-note:bug
|
||||||
|
api: Fix deadlock on calls to sys/leader with a namespace configured
|
||||||
|
on the request.
|
||||||
|
```
|
||||||
23
vault/ha.go
23
vault/ha.go
@@ -150,30 +150,41 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
|
|||||||
if c.Sealed() {
|
if c.Sealed() {
|
||||||
return false, "", "", consts.ErrSealed
|
return false, "", "", consts.ErrSealed
|
||||||
}
|
}
|
||||||
|
|
||||||
c.stateLock.RLock()
|
c.stateLock.RLock()
|
||||||
|
defer c.stateLock.RUnlock()
|
||||||
|
|
||||||
|
return c.LeaderLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) LeaderLocked() (isLeader bool, leaderAddr, clusterAddr string, err error) {
|
||||||
|
// Check if HA enabled. We don't need the lock for this check as it's set
|
||||||
|
// on startup and never modified
|
||||||
|
if c.ha == nil {
|
||||||
|
return false, "", "", ErrHANotEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if sealed
|
||||||
|
if c.Sealed() {
|
||||||
|
return false, "", "", consts.ErrSealed
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we are the leader
|
// Check if we are the leader
|
||||||
if !c.standby {
|
if !c.standby {
|
||||||
c.stateLock.RUnlock()
|
|
||||||
return true, c.redirectAddr, c.ClusterAddr(), nil
|
return true, c.redirectAddr, c.ClusterAddr(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a lock
|
// Initialize a lock
|
||||||
lock, err := c.ha.LockWith(CoreLockPath, "read")
|
lock, err := c.ha.LockWith(CoreLockPath, "read")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.stateLock.RUnlock()
|
|
||||||
return false, "", "", err
|
return false, "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the value
|
// Read the value
|
||||||
held, leaderUUID, err := lock.Value()
|
held, leaderUUID, err := lock.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.stateLock.RUnlock()
|
|
||||||
return false, "", "", err
|
return false, "", "", err
|
||||||
}
|
}
|
||||||
if !held {
|
if !held {
|
||||||
c.stateLock.RUnlock()
|
|
||||||
return false, "", "", nil
|
return false, "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,13 +199,11 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
|
|||||||
// If the leader hasn't changed, return the cached value; nothing changes
|
// If the leader hasn't changed, return the cached value; nothing changes
|
||||||
// mid-leadership, and the barrier caches anyways
|
// mid-leadership, and the barrier caches anyways
|
||||||
if leaderUUID == localLeaderUUID && localRedirectAddr != "" {
|
if leaderUUID == localLeaderUUID && localRedirectAddr != "" {
|
||||||
c.stateLock.RUnlock()
|
|
||||||
return false, localRedirectAddr, localClusterAddr, nil
|
return false, localRedirectAddr, localClusterAddr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Trace("found new active node information, refreshing")
|
c.logger.Trace("found new active node information, refreshing")
|
||||||
|
|
||||||
defer c.stateLock.RUnlock()
|
|
||||||
c.leaderParamsLock.Lock()
|
c.leaderParamsLock.Lock()
|
||||||
defer c.leaderParamsLock.Unlock()
|
defer c.leaderParamsLock.Unlock()
|
||||||
|
|
||||||
|
|||||||
@@ -5150,8 +5150,15 @@ type LeaderResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
|
func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
|
||||||
|
core.stateLock.RLock()
|
||||||
|
defer core.stateLock.RUnlock()
|
||||||
|
|
||||||
|
return core.GetLeaderStatusLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (core *Core) GetLeaderStatusLocked() (*LeaderResponse, error) {
|
||||||
haEnabled := true
|
haEnabled := true
|
||||||
isLeader, address, clusterAddr, err := core.Leader()
|
isLeader, address, clusterAddr, err := core.LeaderLocked()
|
||||||
if errwrap.Contains(err, ErrHANotEnabled.Error()) {
|
if errwrap.Contains(err, ErrHANotEnabled.Error()) {
|
||||||
haEnabled = false
|
haEnabled = false
|
||||||
err = nil
|
err = nil
|
||||||
@@ -5165,10 +5172,10 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
|
|||||||
IsSelf: isLeader,
|
IsSelf: isLeader,
|
||||||
LeaderAddress: address,
|
LeaderAddress: address,
|
||||||
LeaderClusterAddress: clusterAddr,
|
LeaderClusterAddress: clusterAddr,
|
||||||
PerfStandby: core.PerfStandby(),
|
PerfStandby: core.perfStandby,
|
||||||
}
|
}
|
||||||
if isLeader {
|
if isLeader {
|
||||||
resp.ActiveTime = core.ActiveTime()
|
resp.ActiveTime = core.activeTime
|
||||||
}
|
}
|
||||||
if resp.PerfStandby {
|
if resp.PerfStandby {
|
||||||
resp.PerfStandbyLastRemoteWAL = core.EntLastRemoteWAL()
|
resp.PerfStandbyLastRemoteWAL = core.EntLastRemoteWAL()
|
||||||
@@ -5176,7 +5183,7 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
|
|||||||
resp.LastWAL = core.EntLastWAL()
|
resp.LastWAL = core.EntLastWAL()
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexes()
|
resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexesLocked()
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5200,7 +5207,7 @@ func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
||||||
status, err := b.Core.GetLeaderStatus()
|
status, err := b.Core.GetLeaderStatusLocked()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ func (c *Core) GetRaftNodeID() string {
|
|||||||
func (c *Core) GetRaftIndexes() (committed uint64, applied uint64) {
|
func (c *Core) GetRaftIndexes() (committed uint64, applied uint64) {
|
||||||
c.stateLock.RLock()
|
c.stateLock.RLock()
|
||||||
defer c.stateLock.RUnlock()
|
defer c.stateLock.RUnlock()
|
||||||
|
return c.GetRaftIndexesLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) GetRaftIndexesLocked() (committed uint64, applied uint64) {
|
||||||
raftStorage, ok := c.underlyingPhysical.(*raft.RaftBackend)
|
raftStorage, ok := c.underlyingPhysical.(*raft.RaftBackend)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
|
|||||||
Reference in New Issue
Block a user