Documentation
¶
Overview ¶
Package ovnstatus provides an OVNClient that returns structured NB/SB health. It prefers JSON outputs and falls back to minimal text parsing for "Servers".
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type ClusterServer ¶
type ClusterServer struct {
SID string `json:"sid,omitempty"`
Address string `json:"address,omitempty"`
Role string `json:"role,omitempty"`
Self bool `json:"self,omitempty"`
Connected bool `json:"connected,omitempty"`
LastMsgMs *int64 `json:"lastMsgMs,omitempty"`
NextIndex *int64 `json:"nextIndex,omitempty"` // NEW
MatchIndex *int64 `json:"matchIndex,omitempty"` // NEW
}
ClusterServer is an entry in the Servers list.
type ClusterStatus ¶
type ClusterStatus struct {
Name string `json:"name,omitempty"`
Role string `json:"role,omitempty"` // leader/follower (local)
Term int64 `json:"term,omitempty"`
Index int64 `json:"index,omitempty"`
Connected bool `json:"connected,omitempty"`
Servers []ClusterServer `json:"servers,omitempty"`
}
ClusterStatus is a structured view of cluster/status.
type ConsensusResult ¶
type ConsensusResult struct {
AllAgree bool // true if all views are identical
HasMajority bool // true if some view is held by >= quorum
QuorumSize int // floor(n/2)+1
MajorityKey string // canonical key of the majority view (if any)
MajorityMembers []string // SIDs of reporters in the majority
MinorityMembers []string // SIDs of reporters not in the majority
TruthView MemberView // the majority's canonical view (if HasMajority); empty otherwise
Diffs map[string]ViewDiff // per-reporter diffs vs TruthView (only meaningful if HasMajority)
}
ConsensusResult summarizes cluster agreement across views.
func AnalyzeConsensus ¶
func AnalyzeConsensus(views []MemberView) ConsensusResult
AnalyzeConsensus checks agreement across a slice of views for one cluster. It answers:
- do all views agree exactly?
- if not, is there a majority agreement?
- who’s in the minority, and how does each minority view differ?
func (ConsensusResult) String ¶
func (cr ConsensusResult) String() string
type ExtendedConsensusResult ¶
type ExtendedConsensusResult struct {
ConsensusResult
// Union across all views (what anyone reported).
UnionMembers []string // SIDs (sorted)
UnionIPs []string // IPs (sorted)
// Reporters (SIDs that produced a HealthSnapshot / self-view).
Reporters []string // SIDs (sorted)
// Members that appear in UnionMembers but for which we have no reporter snapshot.
MissingReporters []string // SIDs (sorted)
// IPs seen in union but NOT in hints.ExpectedIPs (if provided).
UnexpectedIPs []string // sorted
// Expected IPs that did NOT appear anywhere in union.
MissingExpectedIPs []string // sorted
// Size checks; MembersCount is distinct SIDs; DistinctIPCount is distinct IPs.
MembersCount int
DistinctIPCount int
TooManyMembers bool // MembersCount > ExpectedReplicas
TooFewMembers bool // MembersCount < ExpectedReplicas
ExpectedShortfall int // ExpectedReplicas - MembersCount (>=0)
ExpectedExcess int // MembersCount - ExpectedReplicas (>=0)
// IPConflicts: an IP mapped to multiple SIDs (shouldn’t happen if identity is clean).
IPConflicts map[string][]string // ip -> []sids
// SIDAddressDisagreements: number of distinct addresses observed for a SID.
SIDAddressDisagreements map[string]int // sid -> count(address variants)
// Suspect stale SIDs: candidates to kick (heuristic, IP-focused).
// Ranked by: (1) IP not expected, (2) not self-reporting, (3) lowest reference count.
SuspectStaleSIDs []string // sorted by suspicion
}
ExtendedConsensusResult augments ConsensusResult with IP-centric signals.
func AnalyzeConsensusWithIPHints ¶
func AnalyzeConsensusWithIPHints(views []MemberView, hints *Hints) ExtendedConsensusResult
AnalyzeConsensusWithIPHints extends AnalyzeConsensus using ExpectedIPs instead of ExpectedSIDs.
func (ExtendedConsensusResult) PrettyString ¶
func (res ExtendedConsensusResult) PrettyString() string
PrettyString renders a human-friendly multi-line summary of ExtendedConsensusResult. It combines consensus status with IP/SID hints.
type HealthSnapshot ¶
type HealthSnapshot struct {
DB DB
Local ServerLocalView
Full ClusterStatus
}
HealthSnapshot bundles both sources for easy checks.
func (HealthSnapshot) HasQuorum ¶
func (hs HealthSnapshot) HasQuorum() bool
HasQuorum returns whether the local server believes it has a majority.
func (HealthSnapshot) IsLeader ¶
func (hs HealthSnapshot) IsLeader() bool
IsLeader reports local leadership (per-DB).
func (HealthSnapshot) StaleMemberCount ¶
func (hs HealthSnapshot) StaleMemberCount(expectedReplicas int) int
StaleMemberCount returns how many configured servers exceed the expected replica count.
type Hints ¶
type Hints struct {
// ExpectedReplicas, if >0, is the intended cluster size; if 0 and ExpectedIPs provided,
// we derive ExpectedReplicas = len(ExpectedIPs).
ExpectedReplicas int
// ExpectedIPs is the set of node IPs you expect to participate (unique per member).
// Optional label can be a pod/node name for reporting (empty string is fine).
ExpectedIPs map[string]string // ip -> label
}
Hints about the cluster from outside OVN (e.g., Kubernetes).
type MemberView ¶
type MemberView struct {
FromSID string // the reporter's SID (hs.Local.SID)
FromAddress string // best-effort: address of self from Servers (if present)
Members map[string]string // SID -> Address (as reported by this member)
}
MemberView is a normalized membership view (from one member's perspective).
func BuildMemberView ¶
func BuildMemberView(hs HealthSnapshot) MemberView
BuildMemberView extracts a normalized view for one snapshot. It uses hs.Full.Servers as the authoritative list this reporter sees.
func NormalizeViews ¶
func NormalizeViews(views []MemberView) []MemberView
type OVNClient ¶
type OVNClient struct {
// Paths to local control sockets.
NBCTLPath string // e.g., /var/run/ovn/ovnnb_db.ctl
SBCTLPath string // e.g., /var/run/ovn/ovnsb_db.ctl
NBDBSock string // tcp:127.0.0.1:6641, unix:/var/run/ovn/ovnnb_db.sock, etc
SBDBSock string // tcp:127.0.0.1:6642, unix:/var/run/ovn/ovnsb_db.sock, etc
// TLS for ovsdb-client (used for _Server queries). ovn-appctl uses ctl socket, no TLS needed.
UseSSL bool
Key string
Cert string
CACert string
FreshLastMsgThreshold time.Duration
// Optional expected replica count for stale-member checks.
ExpectedReplicas int
// Runner is the pluggable command runner. If nil, a default runner is used.
Runner RunnerFunc
}
OVNClient holds config + runner and exposes health methods.
func (*OVNClient) ApplyDefaults ¶
func (o *OVNClient) ApplyDefaults()
func (*OVNClient) HealthBoth ¶
func (c *OVNClient) HealthBoth(ctx context.Context) (nb HealthSnapshot, sb HealthSnapshot, err1, err2 error)
HealthBoth returns snapshots for both NB and SB.
type RunnerFunc ¶
RunnerFunc allows dependency-injecting the command runner.
type ServerLocalView ¶
type ServerLocalView struct {
Leader bool `json:"leader"`
Connected bool `json:"connected"`
CID string `json:"cid"` // cluster UUID
SID string `json:"sid"` // this server UUID
Index int64 `json:"index"`
}
ServerLocalView is what the local ovsdb-server reports via _Server.Database.
type ViewDiff ¶
type ViewDiff struct {
MissingSIDs []string // SIDs absent in this view but present in truth
ExtraSIDs []string // SIDs present in this view but absent in truth
AddressMismatches map[string][2]string // SID -> [truthAddr, thisAddr] when both have SID but addresses differ
}
ViewDiff is the difference between one view and a chosen "truth" view.