Skip to content
Snippets Groups Projects
topology.go 3.34 KiB
Newer Older
  • Learn to ignore specific revisions
  • package server
    
    import (
    	"context"
    	"time"
    
    	apb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology"
    	"code.fbi.h-da.de/danet/gosdn/controller/topology"
    	"code.fbi.h-da.de/danet/gosdn/controller/topology/links"
    	"code.fbi.h-da.de/danet/gosdn/controller/topology/nodes"
    	"code.fbi.h-da.de/danet/gosdn/controller/topology/ports"
    	"github.com/google/uuid"
    	"google.golang.org/grpc/codes"
    	"google.golang.org/grpc/status"
    )
    
    // Topology holds a topologyService and represents a TopologyServiceServer.
    type Topology struct {
    	apb.UnimplementedTopologyServiceServer
    
    André Sterba's avatar
    André Sterba committed
    	topologyService topology.TService
    
    André Sterba's avatar
    André Sterba committed
    // NewTopologyServer receives a topologyService and returns a new TopologyServer.
    func NewTopologyServer(service topology.TService) *Topology {
    
    	return &Topology{
    		topologyService: service,
    	}
    }
    
    // AddLink adds a new link to the topology
    func (t Topology) AddLink(ctx context.Context, request *apb.AddLinkRequest) (*apb.AddLinkResponse, error) {
    	sourceNode, sourcePort, err := t.ensureNodeAndPortExists(request.Link.SourceNode, request.Link.SourcePort)
    	if err != nil {
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	targetNode, targetPort, err := t.ensureNodeAndPortExists(request.Link.TargetNode, request.Link.TargetPort)
    	if err != nil {
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	link := links.Link{
    		ID:         uuid.New(),
    		Name:       request.Link.Name,
    		SourceNode: sourceNode,
    		SourcePort: sourcePort,
    		TargetNode: targetNode,
    		TargetPort: targetPort,
    	}
    
    André Sterba's avatar
    André Sterba committed
    	err = t.topologyService.AddLink(link)
    
    	if err != nil {
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	return &apb.AddLinkResponse{
    		Timestamp: time.Now().UnixNano(),
    		Status:    apb.Status_STATUS_OK,
    	}, nil
    }
    
    // GetTopology returns the current topology in the form of all links
    func (t Topology) GetTopology(ctx context.Context, request *apb.GetTopologyRequest) (*apb.GetTopologyResponse, error) {
    
    André Sterba's avatar
    André Sterba committed
    	topo, err := t.topologyService.GetAll()
    
    	if err != nil {
    		return nil, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	topology := &apb.Topology{}
    
    	for _, link := range topo {
    		topology.Links = append(topology.Links, &apb.Link{
    			Id:   link.ID.String(),
    			Name: link.Name,
    			SourceNode: &apb.Node{
    				Id:   link.SourceNode.ID.String(),
    				Name: link.SourceNode.Name,
    			},
    			SourcePort: &apb.Port{
    				Id: link.SourcePort.ID.String(),
    			},
    			TargetNode: &apb.Node{
    				Id:   link.TargetNode.ID.String(),
    				Name: link.TargetNode.Name,
    			},
    			TargetPort: &apb.Port{
    				Id: link.TargetPort.ID.String(),
    			},
    		})
    	}
    
    	return &apb.GetTopologyResponse{
    		Timestamp: time.Now().UnixNano(),
    		Status:    apb.Status_STATUS_OK,
    		Toplogy:   topology,
    	}, nil
    }
    
    func (t Topology) ensureNodeAndPortExists(incomingNode *apb.Node, incomingPort *apb.Port) (nodes.Node, ports.Port, error) {
    	node, err := nodeService.EnsureExists(
    		nodes.Node{
    			ID: getExistingOrCreateNewUUIDFromString(incomingNode.Id),
    		},
    	)
    	if err != nil {
    		return node, ports.Port{}, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	port, err := portService.EnsureExists(
    		ports.Port{
    			ID: getExistingOrCreateNewUUIDFromString(incomingPort.Id),
    		},
    	)
    	if err != nil {
    		return nodes.Node{}, port, status.Errorf(codes.Aborted, "%v", err)
    	}
    
    	return node, port, nil
    }
    
    func getExistingOrCreateNewUUIDFromString(id string) uuid.UUID {
    	parsedID, err := uuid.Parse(id)
    	if err != nil {
    		return uuid.Nil
    	}
    
    	return parsedID
    }