func (a *Agent) Start() { var err error go a.WSServer.ListenAndServe() addr, port, err := config.GetAnalyzerClientAddr() if err != nil { logging.GetLogger().Errorf("Unable to parse analyzer client %s", err.Error()) os.Exit(1) } if addr != "" { authOptions := &shttp.AuthenticationOpts{ Username: config.GetConfig().GetString("agent.analyzer_username"), Password: config.GetConfig().GetString("agent.analyzer_password"), } authClient := waitAnalyzer(addr, port, authOptions) a.WSClient, err = shttp.NewWSAsyncClientFromConfig("skydive-agent", addr, port, "/ws", authClient) if err != nil { logging.GetLogger().Errorf("Unable to instantiate analyzer client %s", err.Error()) os.Exit(1) } graph.NewForwarder(a.WSClient, a.Graph, config.GetConfig().GetString("host_id")) a.WSClient.Connect() } a.TopologyProbeBundle, err = NewTopologyProbeBundleFromConfig(a.Graph, a.Root, a.WSClient) if err != nil { logging.GetLogger().Errorf("Unable to instantiate topology probes: %s", err.Error()) os.Exit(1) } a.TopologyProbeBundle.Start() go a.HTTPServer.ListenAndServe() if addr != "" { a.EtcdClient, err = etcd.NewEtcdClientFromConfig() if err != nil { logging.GetLogger().Errorf("Unable to start etcd client %s", err.Error()) os.Exit(1) } for { flowtableUpdate, err := a.EtcdClient.GetInt64("/agent/config/flowtable_update") if err != nil { time.Sleep(time.Second) continue } flowtableExpire, err := a.EtcdClient.GetInt64("/agent/config/flowtable_expire") if err != nil { time.Sleep(time.Second) continue } updateTime := time.Duration(flowtableUpdate) * time.Second expireTime := time.Duration(flowtableExpire) * time.Second a.FlowTableAllocator = flow.NewTableAllocator(updateTime, expireTime) // expose a flow server through the client connection flow.NewServer(a.FlowTableAllocator, a.WSClient) packet_injector.NewServer(a.WSClient, a.Graph) a.FlowProbeBundle = fprobes.NewFlowProbeBundleFromConfig(a.TopologyProbeBundle, a.Graph, a.FlowTableAllocator) a.FlowProbeBundle.Start() l, err := ondemand.NewOnDemandProbeServer(a.FlowProbeBundle, a.Graph, a.WSClient) if err != nil { logging.GetLogger().Errorf("Unable to start on-demand flow probe %s", err.Error()) os.Exit(1) } a.OnDemandProbeServer = l a.OnDemandProbeServer.Start() break } } }
func TestFlowQuery(t *testing.T) { delay := 500 * time.Second al := flow.NewTableAllocator(delay, delay) f := func(flows []*flow.Flow) {} ft1 := al.Alloc(f) flow.GenerateTestFlows(t, ft1, 1, "probe-tid1") flows1 := flow.GenerateTestFlows(t, ft1, 2, "probe-tid2") ft2 := al.Alloc(f) flows2 := flow.GenerateTestFlows(t, ft2, 3, "probe-tid2") ft1.Start() ft2.Start() time.Sleep(time.Second) obj, _ := proto.Marshal(&flow.FlowSearchQuery{ Filter: &flow.Filter{ BoolFilter: &flow.BoolFilter{ Op: flow.BoolFilterOp_OR, Filters: []*flow.Filter{ &flow.Filter{ TermStringFilter: &flow.TermStringFilter{Key: "NodeTID", Value: "probe-tid2"}, }, &flow.Filter{ TermStringFilter: &flow.TermStringFilter{Key: "ANodeTID", Value: "probe-tid2"}, }, &flow.Filter{ TermStringFilter: &flow.TermStringFilter{Key: "BNodeTID", Value: "probe-tid2"}, }, }, }, }, }) query := &flow.TableQuery{ Type: "FlowSearchQuery", Obj: obj, } reply := al.QueryTable(query) ft1.Stop() ft2.Stop() flowset := flow.NewFlowSet() for _, r := range reply.Obj { var fsr flow.FlowSearchReply if err := proto.Unmarshal(r, &fsr); err != nil { t.Fatal(err.Error()) } flowset.Merge(fsr.FlowSet, flow.MergeContext{}) } if len(flowset.Flows) != len(flows1)+len(flows2) { t.Fatalf("FlowQuery should return at least one flow") } for _, flow := range flowset.Flows { if flow.NodeTID != "probe-tid2" { t.Fatalf("FlowQuery should only return flows with probe-tid2, got: %s", flow) } } }
func (a *Agent) Start() { var err error go a.WSServer.ListenAndServe() addr, port, err := config.GetAnalyzerClientAddr() if err != nil { logging.GetLogger().Errorf("Unable to parse analyzer client %s", err.Error()) os.Exit(1) } if addr != "" { authOptions := &shttp.AuthenticationOpts{ Username: config.GetConfig().GetString("agent.analyzer_username"), Password: config.GetConfig().GetString("agent.analyzer_password"), } authClient := waitAnalyzer(addr, port, authOptions) a.WSClient, err = shttp.NewWSAsyncClientFromConfig("skydive-agent", addr, port, "/ws", authClient) if err != nil { logging.GetLogger().Errorf("Unable to instantiate analyzer client %s", err.Error()) os.Exit(1) } graph.NewForwarder(a.WSClient, a.Graph, a.Root) a.WSClient.Connect() // send a first reset event to the analyzers a.Graph.DelSubGraph(a.Root) } a.TopologyProbeBundle = tprobes.NewTopologyProbeBundleFromConfig(a.Graph, a.Root) a.TopologyProbeBundle.Start() go a.HTTPServer.ListenAndServe() if addr != "" { a.EtcdClient, err = etcd.NewEtcdClientFromConfig() if err != nil { logging.GetLogger().Errorf("Unable to start etcd client %s", err.Error()) os.Exit(1) } captureApiHandler := &api.CaptureApiHandler{ BasicApiHandler: api.BasicApiHandler{ ResourceHandler: &api.CaptureResourceHandler{}, EtcdKeyAPI: a.EtcdClient.KeysApi, }, Graph: a.Graph, } for { flowtableUpdate, err := a.EtcdClient.GetInt64("/agent/config/flowtable_update") if err != nil { time.Sleep(time.Second) continue } flowtableExpire, err := a.EtcdClient.GetInt64("/agent/config/flowtable_expire") if err != nil { time.Sleep(time.Second) continue } updateTime := time.Duration(flowtableUpdate) * time.Second expireTime := time.Duration(flowtableExpire) * time.Second a.FlowTableAllocator = flow.NewTableAllocator(updateTime, expireTime) // expose a flow server through the client connection flow.NewServer(a.FlowTableAllocator, a.WSClient) a.FlowProbeBundle = fprobes.NewFlowProbeBundleFromConfig(a.TopologyProbeBundle, a.Graph, a.FlowTableAllocator) a.FlowProbeBundle.Start() l, err := fprobes.NewOnDemandProbeListener(a.FlowProbeBundle, a.Graph, captureApiHandler) if err != nil { logging.GetLogger().Errorf("Unable to start on-demand flow probe %s", err.Error()) os.Exit(1) } a.OnDemandProbeListener = l a.OnDemandProbeListener.Start() break } } }