- CDN snapshot: batch merge после parallel fetch, без race на persist - ListRevisionPrefixes: лёгкая проверка revision вместо GetRevision - Jobs: timeout/cancel context для pipeline и deploy - HTTP server timeouts; кэш birdc для GET /peers - ListModules: batch DoH profiles одним запросом - Web: tab-scoped load на /operations, debounce job search, меньше over-fetch на dashboard Co-authored-by: Cursor <[email protected]>
98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
package birdfmt
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// ShowProtocols runs `birdc [-s socket] show protocols all` and returns stdout (BIRD 2).
|
|
func ShowProtocols(ctx context.Context, socket, birdcBin string) (string, error) {
|
|
if birdcBin == "" {
|
|
birdcBin = "birdc"
|
|
}
|
|
args := []string{"show", "protocols", "all"}
|
|
if s := strings.TrimSpace(socket); s != "" {
|
|
args = append([]string{"-s", s}, args...)
|
|
}
|
|
cmd := exec.CommandContext(ctx, birdcBin, args...)
|
|
var stdout, stderr bytes.Buffer
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
if err := cmd.Run(); err != nil {
|
|
msg := strings.TrimSpace(stderr.String())
|
|
if msg != "" {
|
|
return "", fmt.Errorf("birdc show protocols: %w: %s", err, msg)
|
|
}
|
|
return "", fmt.Errorf("birdc show protocols: %w", err)
|
|
}
|
|
return stdout.String(), nil
|
|
}
|
|
|
|
// CountEstablishedBGPSessions counts BGP protocol rows whose line contains "Established"
|
|
// (heuristic for `birdc show protocols` / `show protocols all` output).
|
|
func CountEstablishedBGPSessions(showProtocolsOutput string) int {
|
|
lines := strings.Split(showProtocolsOutput, "\n")
|
|
n := 0
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" || strings.HasPrefix(line, "name") || strings.HasPrefix(strings.ToLower(line), "table") {
|
|
continue
|
|
}
|
|
if !isBGPProtocolSummaryRow(line) {
|
|
continue
|
|
}
|
|
if strings.Contains(strings.ToLower(line), "established") {
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|
|
|
|
// ParseBGPProtocolStates parses `birdc show protocols all` summary rows into protocol_name -> state.
|
|
func ParseBGPProtocolStates(output string) map[string]string {
|
|
out := make(map[string]string)
|
|
for _, raw := range strings.Split(output, "\n") {
|
|
line := strings.TrimSpace(raw)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
low := strings.ToLower(line)
|
|
if strings.HasPrefix(low, "bird ") || strings.HasPrefix(low, "name ") || strings.HasPrefix(low, "table ") {
|
|
continue
|
|
}
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 4 {
|
|
continue
|
|
}
|
|
if !strings.EqualFold(fields[1], "BGP") {
|
|
continue
|
|
}
|
|
state := extractBGPSessionStateLine(line)
|
|
if state == "" {
|
|
state = fields[3]
|
|
}
|
|
out[fields[0]] = state
|
|
}
|
|
return out
|
|
}
|
|
|
|
func extractBGPSessionStateLine(line string) string {
|
|
known := []string{
|
|
"Established",
|
|
"Idle",
|
|
"Connect",
|
|
"Active",
|
|
"OpenSent",
|
|
"OpenConfirm",
|
|
}
|
|
for _, st := range known {
|
|
if strings.Contains(line, st) {
|
|
return st
|
|
}
|
|
}
|
|
return ""
|
|
}
|