From 2627fbf868cccac6af9fb67e0d9e7cee87e0f609 Mon Sep 17 00:00:00 2001
From: Manuel Kieweg <manuel.kieweg@h-da.de>
Date: Fri, 7 May 2021 18:14:28 +0200
Subject: [PATCH] first gRPB NBI draft

---
 northbound/client.go |   2 +-
 northbound/server.go | 150 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 138 insertions(+), 14 deletions(-)

diff --git a/northbound/client.go b/northbound/client.go
index 040295490..d0b2c91c9 100644
--- a/northbound/client.go
+++ b/northbound/client.go
@@ -1 +1 @@
-package northbound
+package nbi
diff --git a/northbound/server.go b/northbound/server.go
index 75d6bdcc0..2e45ee2b9 100644
--- a/northbound/server.go
+++ b/northbound/server.go
@@ -1,43 +1,167 @@
-package northbound
+package nbi
 
 import (
-	"code.fbi.h-da.de/cocsn/api/proto/gosdn"
-	"code.fbi.h-da.de/cocsn/api/proto/gosdn/pnd"
+	pb "code.fbi.h-da.de/cocsn/api/proto/gosdn"
+	ppb "code.fbi.h-da.de/cocsn/api/proto/gosdn/pnd"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
 	"context"
+	"github.com/google/uuid"
+	"github.com/openconfig/ygot/ygot"
+	"sync"
+	"time"
 )
 
+var pndLock sync.RWMutex
+var sbiLock sync.RWMutex
+var pndc *nucleus.PndStore
+var sbic *nucleus.SbiStore
+
 type pndServer struct {
-	pnd.UnimplementedPndServer
+	ppb.UnimplementedPndServer
 }
 
-func (p pndServer) Get(ctx context.Context, request *pnd.GetRequest) (*pnd.GetResponse, error) {
-	panic("implement me")
+func (p pndServer) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse, error) {
+	switch request.Type {
+	case ppb.GetRequest_PND:
+		pid, err := uuid.Parse(request.Id)
+		if err != nil {
+			return nil, err
+		}
+		return handlePndRequest(pid)
+	case ppb.GetRequest_OND:
+		return handleOndRequest()
+	case ppb.GetRequest_ONDS:
+		return handleOndsRequest()
+	case ppb.GetRequest_SBI:
+		return handleSbiRequest()
+	case ppb.GetRequest_SBIS:
+		return handleSbisRequest()
+	case ppb.GetRequest_Changes:
+		return handleChangesRequest()
+	default:
+		return nil, errors.ErrOperationNotSupported{Op: request.Type}
+	}
+}
+
+func handlePndRequest(pid uuid.UUID) (*ppb.GetResponse, error) {
+	pndLock.RLock()
+	defer pndLock.RUnlock()
+	pnd, err := pndc.Get(pid)
+	if err != nil {
+		return nil, err
+	}
+	onds, err := fillOnds(pnd)
+	if err != nil {
+		return nil, err
+	}
+	sbis, err := fillSbis(pnd)
+	return &ppb.GetResponse{
+		Timestamp: time.Now().UnixNano(),
+		Payload: &ppb.GetResponse_Pnd{
+			Pnd: &ppb.PrincipalNetworkDomain{
+				Id:          pid.String(),
+				Name:        pnd.GetName(),
+				Description: pnd.GetDescription(),
+				Onds:        onds,
+				Sbis:        sbis,
+				Changes:     nil,
+			},
+		},
+	}, nil
+}
+
+func handleSbiRequest() (*ppb.GetResponse, error) {
+	return nil, errors.ErrNotYetImplemented{}
+}
+
+func handleSbisRequest() (*ppb.GetResponse, error) {
+	return nil, errors.ErrNotYetImplemented{}
+}
+
+func handleOndRequest() (*ppb.GetResponse, error) {
+	return nil, errors.ErrNotYetImplemented{}
+}
+
+func handleOndsRequest() (*ppb.GetResponse, error) {
+	return nil, errors.ErrNotYetImplemented{}
+}
+
+func handleChangesRequest() (*ppb.GetResponse, error) {
+	return nil, errors.ErrNotYetImplemented{}
+}
+
+func fillOnds(pnd nucleus.PrincipalNetworkDomain) (*ppb.OrchestratedNetworkingDevices, error) {
+	onds := make(map[string]*ppb.OrchestratedNetworkingDevice)
+	for _, id := range pnd.Devices() {
+		d, err := pnd.GetDevice(id)
+		if err != nil {
+			return nil, err
+		}
+		cfg := ygot.GNMINotificationsConfig{}
+		dev, err := ygot.TogNMINotifications(d, time.Now().UnixNano(), cfg)
+		if err != nil {
+			return nil, err
+		}
+		ond := &ppb.OrchestratedNetworkingDevice{
+			Id:     id.String(),
+			Name:   "",
+			Device: dev,
+		}
+		onds[id.String()] = ond
+	}
+	return &ppb.OrchestratedNetworkingDevices{Onds: onds}, nil
+}
+
+func fillSbis(pnd nucleus.PrincipalNetworkDomain) (*ppb.SouthboundInterfaces, error) {
+	sbis := make(map[string]*ppb.SouthboundInterface)
+	sbic := pnd.GetSBIs().(*nucleus.SbiStore)
+	for _,id := range sbic.UUIDs() {
+		sbi, err := sbic.Get(id)
+		if err != nil {
+			return nil, err
+		}
+		sbis[id.String()] = &ppb.SouthboundInterface{
+			Id:     id.String(),
+			Schema: sbi.Schema().RootSchema().Name,
+		}
+	}
+	return &ppb.SouthboundInterfaces{Sbis: sbis}, nil
+}
+
+func fillChanges(pnd nucleus.PrincipalNetworkDomain) (*ppb.Changes, error) {
+	// TODO: Allow access to change at leaso on
+	return nil, errors.ErrNotYetImplemented{}
 }
 
-func (p pndServer) Set(ctx context.Context, request *pnd.SetRequest) (*pnd.SetResponse, error) {
+func (p pndServer) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) {
 	panic("implement me")
 }
 
 type gosdnServer struct {
-	gosdn.UnimplementedGosdnServer
+	pb.UnimplementedGosdnServer
 }
 
-func (s gosdnServer) Get(ctx context.Context, request *gosdn.GetRequest) (*gosdn.GetResponse, error) {
+func (s gosdnServer) Get(ctx context.Context, request *pb.GetRequest) (*pb.GetResponse, error) {
 	panic("implement me")
 }
 
-func (s gosdnServer) Set(ctx context.Context, request *gosdn.SetRequest) (*gosdn.SetResponse, error) {
+func (s gosdnServer) Set(ctx context.Context, request *pb.SetRequest) (*pb.SetResponse, error) {
 	panic("implement me")
 }
 
-func NewServer() *Server {
-	return &Server{
+func NewNBI(pnds *nucleus.PndStore, sbis *nucleus.SbiStore) *NorthboundInterface {
+	pndc = pnds
+	sbic = sbis
+	pndLock = sync.RWMutex{}
+	sbiLock = sync.RWMutex{}
+	return &NorthboundInterface{
 		Pnd:        &pndServer{},
 		Controller: &gosdnServer{},
 	}
 }
 
-type Server struct {
+type NorthboundInterface struct {
 	Pnd        *pndServer
 	Controller *gosdnServer
 }
-- 
GitLab