From 900ff9f4c24f015c7ea9b7a8b883fe9b61de4c3d Mon Sep 17 00:00:00 2001 From: Daniel Czerwonk Date: Mon, 19 Jun 2017 21:04:09 +0200 Subject: [PATCH] removed bird client dependency, using socket instead --- bird_client.go | 70 ++++++++++++++++++++++++++++++++++++++++++-------- main.go | 5 ++-- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/bird_client.go b/bird_client.go index 2a82c16..de642fc 100644 --- a/bird_client.go +++ b/bird_client.go @@ -1,16 +1,30 @@ package main import ( - "os/exec" + "net" + + "regexp" + + "time" "github.com/czerwonk/bird_exporter/protocol" + "github.com/prometheus/common/log" ) +const bufferSize = 4096 +const timeout = 30 + +var birdReturnCodeRegex *regexp.Regexp + +func init() { + birdReturnCodeRegex = regexp.MustCompile("\\d{4} \n$") +} + func getProtocols() ([]*protocol.Protocol, error) { protocols := make([]*protocol.Protocol, 0) if *birdEnabled { - s, err := getProtocolsFromBird(4) + s, err := getProtocolsFromBird(*birdSocket, 4) if err != nil { return nil, err } @@ -18,7 +32,7 @@ func getProtocols() ([]*protocol.Protocol, error) { } if *bird6Enabled { - s, err := getProtocolsFromBird(6) + s, err := getProtocolsFromBird(*bird6Socket, 6) if err != nil { return nil, err } @@ -28,14 +42,28 @@ func getProtocols() ([]*protocol.Protocol, error) { return protocols, nil } -func getProtocolsFromBird(ipVersion int) ([]*protocol.Protocol, error) { - client := *birdClient +func getProtocolsFromBird(socketPath string, ipVersion int) ([]*protocol.Protocol, error) { + conn, err := net.Dial("unix", socketPath) + if err != nil { + return nil, err + } + defer conn.Close() - if ipVersion == 6 { - client += "6" + conn.SetReadDeadline(time.Now().Add(timeout * time.Second)) + + buf := make([]byte, bufferSize) + n, err := conn.Read(buf[:]) + if err != nil { + return nil, err + } + log.Debug(string(buf[:n])) + + _, err = conn.Write([]byte("show protocols all\n")) + if err != nil { + return nil, err } - output, err := getBirdOutput(client) + output, err := readFromSocket(conn) if err != nil { return nil, err } @@ -43,6 +71,28 @@ func getProtocolsFromBird(ipVersion int) ([]*protocol.Protocol, error) { return parseOutput(output, ipVersion), nil } -func getBirdOutput(birdClient string) ([]byte, error) { - return exec.Command(birdClient, "show", "protocols", "all").Output() +func readFromSocket(conn net.Conn) ([]byte, error) { + b := make([]byte, 0) + buf := make([]byte, bufferSize) + + done := false + for !done { + n, err := conn.Read(buf[:]) + if err != nil { + return nil, err + } + + b = append(b, buf[:n]...) + done = endsWithBirdReturnCode(b) + } + + return b, nil +} + +func endsWithBirdReturnCode(b []byte) bool { + if len(b) < 6 { + return false + } + + return birdReturnCodeRegex.Match(b[len(b)-6:]) } diff --git a/main.go b/main.go index 8d3955b..80dd21f 100644 --- a/main.go +++ b/main.go @@ -11,13 +11,14 @@ import ( "github.com/prometheus/common/log" ) -const version string = "0.7.1" +const version string = "0.8.0" var ( showVersion = flag.Bool("version", false, "Print version information.") listenAddress = flag.String("web.listen-address", ":9324", "Address on which to expose metrics and web interface.") metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") - birdClient = flag.String("bird.client", "birdc", "Binary to communicate with the bird routing daemon") + birdSocket = flag.String("bird.socket", "/var/run/bird.ctl", "Socket to communicate with bird routing daemon") + bird6Socket = flag.String("bird.socket6", "/var/run/bird6.ctl", "Socket to communicate with bird6 routing daemon") birdEnabled = flag.Bool("bird.ipv4", true, "Get protocols from bird") bird6Enabled = flag.Bool("bird.ipv6", true, "Get protocols from bird6") )