Exemple #1
0
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
}
Exemple #3
0
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
}
Exemple #4
0
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)
}
Exemple #6
0
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
}
Exemple #7
0
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
}
Exemple #8
0
func CleanGraph(g *graph.Graph) {
	g.Lock()
	defer g.Unlock()
	hostname, _ := os.Hostname()
	g.DelHostGraph(hostname)
}
Exemple #9
0
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
}
Exemple #11
0
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
}