func GraphPath(g *graph.Graph, n *graph.Node) string { nodes := g.LookupShortestPath(n, graph.Metadata{"Type": "host"}, graph.Metadata{"RelationType": "ownership"}) if len(nodes) > 0 { return NodePath(nodes).Marshal() } return "" }
func startTopologyClient(t *testing.T, g *graph.Graph, onReady func(*websocket.Conn), onChange func(*websocket.Conn)) error { // ready when got a first ping ws, err := connectToAgent(5, onReady) if err != nil { return err } for { _, m, err := ws.ReadMessage() if err != nil { break } err = processGraphMessage(g, m) if err != nil { return err } logging.GetLogger().Debugf("%s", string(m)) logging.GetLogger().Debugf("%s", g.String()) onChange(ws) } return nil }
func NewOpenContrailMapper(g *graph.Graph, r *graph.Node) *OpenContrailMapper { host := config.GetConfig().GetString("opencontrail.host") port := config.GetConfig().GetInt("opencontrail.port") if host == "" { host = "localhost" } if port == 0 { port = 8085 } mapper := &OpenContrailMapper{graph: g, root: r, agentHost: host, agentPort: port} mapper.nodeUpdaterChan = make(chan graph.Identifier, 500) g.AddEventListener(mapper) return mapper }
func CreateRootNode(g *graph.Graph) *graph.Node { hostID := config.GetConfig().GetString("host_id") m := graph.Metadata{"Name": hostID, "Type": "host"} if config.GetConfig().IsSet("agent.metadata") { subtree := config.GetConfig().Sub("agent.metadata") for key, value := range subtree.AllSettings() { m[key] = value } } buffer, err := ioutil.ReadFile("/var/lib/cloud/data/instance-id") if err == nil { m["InstanceID"] = strings.TrimSpace(string(buffer)) } u, _ := uuid.NewV5(uuid.NamespaceOID, []byte(hostID)) return g.NewNode(graph.Identifier(u.String()), m) }
func testCleanup(t *testing.T, g *graph.Graph, cmds []helper.Cmd, names []string) { // cleanup side on the test testPassed := false onChange := func(ws *websocket.Conn) { g.Lock() defer g.Unlock() if !testPassed { clean := true for _, name := range names { n := g.LookupFirstNode(graph.Metadata{"Name": name}) if n != nil { clean = false break } } if clean { testPassed = true ws.Close() } } } testTopology(t, g, cmds, onChange) if !testPassed { t.Error("test not executed or failed") } helper.CleanGraph(g) }
func NewNeutronMapper(g *graph.Graph, wsClient *shttp.WSAsyncClient, authURL, username, password, tenantName, regionName, domainName string, availability gophercloud.Availability) (*NeutronMapper, error) { mapper := &NeutronMapper{graph: g, wsClient: wsClient} opts := gophercloud.AuthOptions{ IdentityEndpoint: authURL, Username: username, Password: password, TenantName: tenantName, DomainName: domainName, AllowReauth: true, } provider, err := openstack.AuthenticatedClient(opts) if err != nil { return nil, err } client, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ Name: "neutron", Region: regionName, Availability: availability, }) if err != nil { return nil, err } mapper.client = client // Create a cache with a default expiration time of 5 minutes, and which // purges expired items every 30 seconds expire := config.GetConfig().GetInt("cache.expire") cleanup := config.GetConfig().GetInt("cache.cleanup") mapper.cache = cache.New(time.Duration(expire)*time.Second, time.Duration(cleanup)*time.Second) mapper.nodeUpdaterChan = make(chan graph.Identifier, 500) g.AddEventListener(mapper) return mapper, nil }
func NewNetNSContextByNode(g *graph.Graph, n *graph.Node) (*common.NetNSContext, error) { name, ok := n.Metadata()["Name"] if !ok || name == "" { return nil, fmt.Errorf("No name for node %v", n) } ifName := name.(string) nodes := g.LookupShortestPath(n, graph.Metadata{"Type": "host"}, graph.Metadata{"RelationType": "ownership"}) if len(nodes) == 0 { return nil, fmt.Errorf("Failed to determine probePath for %s", ifName) } for _, node := range nodes { if node.Metadata()["Type"] == "netns" { name := node.Metadata()["Name"].(string) path := node.Metadata()["Path"].(string) logging.GetLogger().Debugf("Switching to namespace %s (path: %s)", name, path) return common.NewNetNsContext(path) } } return nil, nil }
func CleanGraph(g *graph.Graph) { g.Lock() defer g.Unlock() hostname, _ := os.Hostname() g.DelHostGraph(hostname) }
func NewFabricProbe(g *graph.Graph) *FabricProbe { fb := &FabricProbe{ Graph: g, links: make(map[*graph.Node]fabricLink), } g.AddEventListener(fb) fb.Graph.Lock() defer fb.Graph.Unlock() list := config.GetConfig().GetStringSlice("agent.topology.fabric") for _, link := range list { pc := strings.Split(link, "->") if len(pc) != 2 { logging.GetLogger().Errorf("FabricProbe link definition should have two endpoint: %s", link) continue } parentDef := strings.TrimSpace(pc[0]) childDef := strings.TrimSpace(pc[1]) if strings.HasPrefix(parentDef, "local/") { logging.GetLogger().Error("FabricProbe doesn't support local node as parent node") continue } if strings.HasPrefix(childDef, "local/") { // Fabric Node to Local Node childDef = strings.TrimPrefix(childDef, "local/") parentNode, err := fb.addFabricNodeFromDef(parentDef) if err != nil { logging.GetLogger().Error(err.Error()) continue } _, childMetadata, err := nodeDefToMetadata(childDef) if err != nil { logging.GetLogger().Error(err.Error()) continue } // queue it as the local doesn't exist at start fb.links[parentNode] = fabricLink{metadata: childMetadata} } else { // Fabric Node to Fabric Node node1, err := fb.addFabricNodeFromDef(parentDef) if err != nil { logging.GetLogger().Error(err.Error()) continue } node2, err := fb.addFabricNodeFromDef(childDef) if err != nil { logging.GetLogger().Error(err.Error()) continue } if !fb.Graph.AreLinked(node1, node2) { fb.Graph.Link(node1, node2, graph.Metadata{"RelationType": "layer2", "Type": "fabric"}) } } } return fb }
func InjectPacket(pp *PacketParams, g *graph.Graph) error { srcdata := pp.SrcNode.Metadata() dstdata := pp.DstNode.Metadata() if _, ok := srcdata["IPV4"]; !ok { return errors.New("Source Node doesn't have an IP") } srcIP := getIP(srcdata["IPV4"].(string)) if srcIP == nil { return errors.New("Source Node doesn't have proper IP") } if _, ok := dstdata["IPV4"]; !ok { return errors.New("Destination Node doesn't have an IP") } dstIP := getIP(dstdata["IPV4"].(string)) if dstIP == nil { return errors.New("Destination Node doesn't have proper IP") } srcMAC, err := net.ParseMAC(srcdata["MAC"].(string)) if err != nil || srcMAC == nil { return errors.New("Source Node doesn't have proper MAC") } dstMAC, err := net.ParseMAC(dstdata["MAC"].(string)) if err != nil || dstMAC == nil { return errors.New("Destination Node doesn't have proper MAC") } //create packet buffer := gopacket.NewSerializeBuffer() ipLayer := &layers.IPv4{Version: 4, SrcIP: srcIP, DstIP: dstIP} ethLayer := &layers.Ethernet{EthernetType: layers.EthernetTypeIPv4, SrcMAC: srcMAC, DstMAC: dstMAC} switch pp.Type { case "icmp": ipLayer.Protocol = layers.IPProtocolICMPv4 gopacket.SerializeLayers(buffer, options, ethLayer, ipLayer, &layers.ICMPv4{ TypeCode: layers.CreateICMPv4TypeCode(layers.ICMPv4TypeEchoRequest, 0), }, gopacket.Payload([]byte(pp.Payload)), ) default: return fmt.Errorf("Unsupported traffic type '%s'", pp.Type) } g.RLock() srcNode := g.GetNode(pp.SrcNode.ID) if srcNode == nil { g.RUnlock() return errors.New("Unable to find source node") } nscontext, err := topology.NewNetNSContextByNode(g, srcNode) defer nscontext.Close() g.RUnlock() if err != nil { return err } handle, err := pcap.OpenLive(srcdata["Name"].(string), 1024, false, 2000) if err != nil { return fmt.Errorf("Unable to open the source node: %s", err.Error()) } defer handle.Close() packet := buffer.Bytes() for i := 0; i < pp.Count; i++ { if err := handle.WritePacketData(packet); err != nil { return fmt.Errorf("Write error: %s", err.Error()) } } return nil }
func (p *GoPacketProbe) run(g *graph.Graph, n *graph.Node, capture *api.Capture) error { atomic.StoreInt64(&p.state, common.RunningState) g.RLock() ifName := n.Metadata()["Name"].(string) firstLayerType := getGoPacketFirstLayerType(n) nscontext, err := topology.NewNetNSContextByNode(g, n) g.RUnlock() defer nscontext.Close() if err != nil { return err } switch capture.Type { case "pcap": handle, err := pcap.OpenLive(ifName, snaplen, true, time.Second) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } if err := handle.SetBPFFilter(capture.BPFFilter); err != nil { return fmt.Errorf("BPF Filter failed: %s", err) } p.handle = handle p.packetSource = gopacket.NewPacketSource(handle, handle.LinkType()) logging.GetLogger().Infof("PCAP Capture started on %s with First layer: %s", ifName, firstLayerType) default: var handle *AFPacketHandle fnc := func() error { handle, err = NewAFPacketHandle(ifName, snaplen) if err != nil { return fmt.Errorf("Error while opening device %s: %s", ifName, err.Error()) } return nil } if err = common.Retry(fnc, 2, 100*time.Millisecond); err != nil { return err } p.handle = handle p.packetSource = gopacket.NewPacketSource(handle, firstLayerType) logging.GetLogger().Infof("AfPacket Capture started on %s with First layer: %s", ifName, firstLayerType) } // leave the namespace, stay lock in the current thread nscontext.Quit() packetsChan := p.flowTable.Start() defer p.flowTable.Stop() p.feedFlowTable(packetsChan) return nil }
func processGraphMessage(g *graph.Graph, m []byte) error { g.Lock() defer g.Unlock() var msg shttp.WSMessage if err := json.Unmarshal(m, &msg); err != nil { return err } if msg.Namespace != "Graph" { return nil } msgType, obj, err := graph.UnmarshalWSMessage(msg) if err != nil { return err } switch msgType { case "NodeUpdated": n := obj.(*graph.Node) node := g.GetNode(n.ID) if node != nil { g.SetMetadata(node, n.Metadata()) } case "NodeDeleted": g.DelNode(obj.(*graph.Node)) case "NodeAdded": n := obj.(*graph.Node) if g.GetNode(n.ID) == nil { g.AddNode(n) } case "EdgeUpdated": e := obj.(*graph.Edge) edge := g.GetEdge(e.ID) if edge != nil { g.SetMetadata(edge, e.Metadata()) } case "EdgeDeleted": g.DelEdge(obj.(*graph.Edge)) case "EdgeAdded": e := obj.(*graph.Edge) if g.GetEdge(e.ID) == nil { g.AddEdge(e) } } return nil }