func main() { tsdbFlag := flag.String("tsdb", "", "Address of the OpenTSDB server where to push telemetry to") textFlag := flag.Bool("text", false, "Print the output as simple text") configFlag := flag.String("config", "", "Config to turn OpenConfig telemetry into OpenTSDB put requests") username, password, subscriptions, addrs, opts := client.ParseFlags() if !(*tsdbFlag != "" || *textFlag) { glog.Fatal("Specify the address of the OpenTSDB server to write to with -tsdb") } else if *configFlag == "" { glog.Fatal("Specify a JSON configuration file with -config") } config, err := loadConfig(*configFlag) if err != nil { glog.Fatal(err) } // Ignore the default "subscribe-to-everything" subscription of the // -subscribe flag. if subscriptions[0] == "" { subscriptions = subscriptions[1:] } // Add the subscriptions from the config file. subscriptions = append(subscriptions, config.Subscriptions...) var c OpenTSDBConn if *textFlag { c = newTextDumper() } else { // TODO: support HTTP(S). c = newTelnetClient(*tsdbFlag) } wg := new(sync.WaitGroup) for _, addr := range addrs { wg.Add(1) publish := func(addr string, message proto.Message) { resp, ok := message.(*openconfig.SubscribeResponse) if !ok { glog.Errorf("Unexpected type of message: %T", message) return } if notif := resp.GetUpdate(); notif != nil { pushToOpenTSDB(addr, c, config, notif) } } c := client.New(username, password, addr, opts) go c.Subscribe(wg, subscriptions, publish) } wg.Wait() }
func main() { username, password, subscriptions, hostAddrs, opts := occlient.ParseFlags() if *redisFlag == "" { glog.Fatal("Specify the address of the Redis server to write to with -redis") } redisAddrs := strings.Split(*redisFlag, ",") if !*clusterMode && len(redisAddrs) > 1 { glog.Fatal("Please pass only 1 redis address in noncluster mode or enable cluster mode") } if *clusterMode { client = redis.NewClusterClient(&redis.ClusterOptions{ Addrs: redisAddrs, Password: *redisPassword, }) } else { client = redis.NewClient(&redis.Options{ Addr: *redisFlag, Password: *redisPassword, }) } defer client.Close() // TODO: Figure out ways to handle being in the wrong mode: // Connecting to cluster in non cluster mode - we get a MOVED error on the first HMSET // Connecting to a noncluster in cluster mode - we get stuck forever _, err := client.Ping().Result() if err != nil { glog.Fatal("Failed to connect to client: ", err) } ocPublish := func(addr string, message proto.Message) { resp, ok := message.(*openconfig.SubscribeResponse) if !ok { glog.Errorf("Unexpected type of message: %T", message) return } if notif := resp.GetUpdate(); notif != nil { bufferToRedis(addr, notif) } } wg := new(sync.WaitGroup) for _, hostAddr := range hostAddrs { wg.Add(1) c := occlient.New(username, password, hostAddr, opts) go c.Subscribe(wg, subscriptions, ocPublish) } wg.Wait() }
func main() { username, password, subscriptions, addrs, opts := client.ParseFlags() if *getFlag != "" { c := client.New(username, password, addrs[0], opts) for _, notification := range c.Get(*getFlag) { var notifStr string if *jsonFlag { var err error if notifStr, err = openconfig.NotificationToJSON(notification); err != nil { glog.Fatal(err) } } else { notifStr = notification.String() } fmt.Println(notifStr) } return } publish := func(addr string, message proto.Message) { resp, ok := message.(*pb.SubscribeResponse) if !ok { glog.Errorf("Unexpected type of message: %T", message) return } if resp.GetHeartbeat() != nil && !glog.V(1) { return // Log heartbeats with verbose logging only. } var respTxt string var err error if *jsonFlag { respTxt, err = openconfig.SubscribeResponseToJSON(resp) if err != nil { glog.Fatal(err) } } else { respTxt = proto.MarshalTextString(resp) } fmt.Println(respTxt) } wg := new(sync.WaitGroup) for _, addr := range addrs { wg.Add(1) c := client.New(username, password, addr, opts) go c.Subscribe(wg, subscriptions, publish) } wg.Wait() }
func pushToRedis(data *redisData) { _, err := client.Pipelined(func(pipe *redis.Pipeline) error { if data.hmset != nil { if reply := client.HMSet(data.key, data.hmset); reply.Err() != nil { glog.Fatal("Redis HMSET error: ", reply.Err()) } redisPublish(data.key, "updates", data.pub) } if data.hdel != nil { if reply := client.HDel(data.key, data.hdel...); reply.Err() != nil { glog.Fatal("Redis HDEL error: ", reply.Err()) } redisPublish(data.key, "deletes", data.hdel) } return nil }) if err != nil { glog.Fatal("Failed to send Pipelined commands: ", err) } }
func redisPublish(path, kind string, payload interface{}) { js, err := json.Marshal(map[string]interface{}{ "kind": kind, "payload": payload, }) if err != nil { glog.Fatalf("JSON error: %s", err) } if reply := client.Publish(path, string(js)); reply.Err() != nil { glog.Fatal("Redis PUBLISH error: ", reply.Err()) } }
// Run sets up the HTTP server and any handlers func (s *server) Run() { http.HandleFunc("/debug", debugHandler) http.HandleFunc("/debug/latency", latencyHandler) var listener net.Listener var listenErr error err := netns.Do(s.vrfName, func() { listener, listenErr = net.Listen("tcp", s.serverName) }) if err != nil { glog.Fatalf("Failed to go to network namespace for vrf %s: %s", s.vrfName, err) } if listenErr != nil { glog.Fatal("Could not start monitor server:", listenErr) } err = http.Serve(listener, nil) if err != nil { glog.Fatal("http serve returned with error:", err) } }
// ParseFlags registers some additional common flags, // parses the flags, and returns the resulting gRPC options, // and other settings to connect to the gRPC interface. func ParseFlags() (username string, password string, subscriptions, addrs []string, opts []grpc.DialOption) { var ( addrsFlag = flag.String("addrs", "localhost:6042", "Comma-separated list of addresses of OpenConfig gRPC servers") caFileFlag = flag.String("cafile", "", "Path to server TLS certificate file") certFileFlag = flag.String("certfile", "", "Path to client TLS certificate file") keyFileFlag = flag.String("keyfile", "", "Path to client TLS private key file") passwordFlag = flag.String("password", "", "Password to authenticate with") subscribeFlag = flag.String("subscribe", "", "Comma-separated list of paths to subscribe to upon connecting to the server") usernameFlag = flag.String("username", "", "Username to authenticate with") tlsFlag = flag.Bool("tls", false, "Enable TLS") ) flag.Parse() if *tlsFlag || *caFileFlag != "" || *certFileFlag != "" { config := &tls.Config{} if *caFileFlag != "" { b, err := ioutil.ReadFile(*caFileFlag) if err != nil { glog.Fatal(err) } cp := x509.NewCertPool() if !cp.AppendCertsFromPEM(b) { glog.Fatalf("credentials: failed to append certificates") } config.RootCAs = cp } else { config.InsecureSkipVerify = true } if *certFileFlag != "" { if *keyFileFlag == "" { glog.Fatalf("Please provide both -certfile and -keyfile") } cert, err := tls.LoadX509KeyPair(*certFileFlag, *keyFileFlag) if err != nil { glog.Fatal(err) } config.Certificates = []tls.Certificate{cert} } opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(config))) } else { opts = append(opts, grpc.WithInsecure()) } addrs = strings.Split(*addrsFlag, ",") subscriptions = strings.Split(*subscribeFlag, ",") return *usernameFlag, *passwordFlag, subscriptions, addrs, opts }