diff --git a/controller.go b/controller.go index 5adfd95a34442351b0f0b9044f9ba2350bc42c99..46d20105c9ea0371adabe81e874acb5275983c82 100644 --- a/controller.go +++ b/controller.go @@ -14,7 +14,7 @@ import ( 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/database" - "code.fbi.h-da.de/cocsn/gosdn/northbound" + nbi "code.fbi.h-da.de/cocsn/gosdn/northbound/server" "code.fbi.h-da.de/cocsn/gosdn/nucleus" "code.fbi.h-da.de/cocsn/gosdn/nucleus/types" "github.com/google/uuid" diff --git a/http.go b/http.go index 92ce1890a2a0d5585d0093f6614fa727d919184c..d672ababce485d7868ab4c6304e6890484a23fee 100644 --- a/http.go +++ b/http.go @@ -1,27 +1,13 @@ package gosdn import ( - "code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi" - "code.fbi.h-da.de/cocsn/gosdn/nucleus" - "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors" - "code.fbi.h-da.de/cocsn/gosdn/nucleus/types" "context" "fmt" - "github.com/google/uuid" - gpb "github.com/openconfig/gnmi/proto/gnmi" log "github.com/sirupsen/logrus" - "io" "net/http" - "net/url" "time" ) -var apiOpmap = map[string]types.Operation{ - "update": types.TransportUpdate, - "replace": types.TransportReplace, - "delete": types.TransportDelete, -} - func stopHttpServer() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() @@ -35,7 +21,6 @@ func registerHttpHandler() { fmt.Println("Recovered in f", r) } }() - http.HandleFunc("/api", httpApi) http.HandleFunc("/livez", healthCheck) http.HandleFunc("/readyz", readynessCheck) } @@ -55,190 +40,3 @@ func healthCheck(writer http.ResponseWriter, request *http.Request) { func readynessCheck(writer http.ResponseWriter, request *http.Request) { writer.WriteHeader(http.StatusOK) } - -// deprecated -// nolint -func httpApi(writer http.ResponseWriter, request *http.Request) { - log.WithFields(log.Fields{ - "request": request, - }).Debug("incoming request") - - query, err := url.ParseQuery(request.URL.RawQuery) - if err != nil { - log.Error(err) - writer.WriteHeader(http.StatusBadRequest) - return - } - - id, err := uuid.Parse(query.Get("uuid")) - if err != nil { - if err.Error() != "invalid UUID length: 0" { - log.Error(err) - } - } - - pid, err := uuid.Parse(query.Get("pnd")) - if err != nil { - if err.Error() != "invalid UUID length: 0" { - log.Error(err) - } - } - - sid, err := uuid.Parse(query.Get("sbi")) - if err != nil { - if err.Error() != "invalid UUID length: 0" { - log.Error(err) - } - } - - var httpPnd nucleus.PrincipalNetworkDomain - var httpSbi nucleus.SouthboundInterface - if query.Get("q") != "init" && query.Get("q") != "getIDs" { - httpPnd, err = c.pndc.Get(pid) - if err != nil { - handleServerError(writer, err) - return - } - sbic := httpPnd.GetSBIs() - httpSbi, err = sbic.(*nucleus.SbiStore).Get(sid) - if err != nil { - handleServerError(writer, err) - return - } - } - - switch q := query.Get("q"); q { - case "addDevice": - d, err := nucleus.NewDevice(httpSbi, &nucleus.GnmiTransportOptions{ - Config: gnmi.Config{ - Addr: query.Get("address"), - Password: query.Get("password"), - Username: query.Get("username"), - Encoding: gpb.Encoding_JSON_IETF, - }, - SetNode: httpSbi.SetNode(), - Unmarshal: httpSbi.(*nucleus.OpenConfig).Unmarshal(), - RespChan: make(chan *gpb.SubscribeResponse), - }) - err = httpPnd.AddDevice(d) - if err != nil { - writer.WriteHeader(http.StatusInternalServerError) - log.Error(err) - return - } - writer.WriteHeader(http.StatusCreated) - fmt.Fprintf(writer, "device added\n") - fmt.Fprintf(writer, "UUID: %v\n", d.UUID) - case "request": - err = httpPnd.Request(id, query.Get("path")) - if err != nil { - switch err.(type) { - case *errors.ErrNotFound: - writer.WriteHeader(http.StatusNotFound) - default: - writer.WriteHeader(http.StatusInternalServerError) - } - log.Error(err) - return - } - writer.WriteHeader(http.StatusOK) - case "requestAll": - err = httpPnd.RequestAll(query.Get("path")) - if err != nil { - switch err.(type) { - case *errors.ErrNotFound: - writer.WriteHeader(http.StatusNotFound) - default: - writer.WriteHeader(http.StatusInternalServerError) - } - log.Error(err) - return - } - writer.WriteHeader(http.StatusOK) - case "getDevice": - device, err := httpPnd.MarshalDevice(id) - if err != nil { - switch err.(type) { - case *errors.ErrNotFound: - writer.WriteHeader(http.StatusNotFound) - default: - writer.WriteHeader(http.StatusInternalServerError) - } - log.Error(err) - return - } - writer.Header().Set("Content-Type", "application/json") - fmt.Fprintf(writer, "%v", device) - case "getIDs": - - pnds := c.pndc.UUIDs() - writeIDs(writer, "PNDs", pnds) - writeIDs(writer, "SBIs", c.sbic.UUIDs()) - for _, id := range pnds { - p, err := c.pndc.Get(id) - if err != nil { - handleServerError(writer, err) - return - } - writeIDs(writer, "Devices", p.Devices()) - } - case "init": - writeIDs(writer, "PNDs", c.pndc.UUIDs()) - writeIDs(writer, "SBIs", c.sbic.UUIDs()) - case "update", "replace": - if err := httpPnd.ChangeOND(id, apiOpmap[q], query.Get("path"), query.Get("value")); err != nil { - handleServerError(writer, err) - return - } - writer.WriteHeader(http.StatusOK) - case "delete": - if err := httpPnd.ChangeOND(id, types.TransportDelete, query.Get("path")); err != nil { - handleServerError(writer, err) - return - } - writer.WriteHeader(http.StatusOK) - case "change-list": - changes := httpPnd.Committed() - writeIDs(writer, "Tentative changes", changes) - case "change-list-pending": - changes := httpPnd.Pending() - writeIDs(writer, "Pending changes", changes) - case "change-commit": - cuid, err := uuid.Parse(query.Get("cuid")) - if err != nil { - handleServerError(writer, err) - return - } - if err := httpPnd.Commit(cuid); err != nil { - handleServerError(writer, err) - return - } - writer.WriteHeader(http.StatusAccepted) - case "change-confirm": - cuid, err := uuid.Parse(query.Get("cuid")) - if err != nil { - handleServerError(writer, err) - return - } - if err := httpPnd.Confirm(cuid); err != nil { - handleServerError(writer, err) - return - } - writer.WriteHeader(http.StatusAccepted) - default: - writer.WriteHeader(http.StatusBadRequest) - } -} - -func writeIDs(w io.Writer, typ string, ids []uuid.UUID) { - fmt.Fprintf(w, "%v:\n", typ) - for i, id := range ids { - fmt.Fprintf(w, "%v: %v\n", i+1, id) - } -} - -func handleServerError(w http.ResponseWriter, err error) { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "error: %v", err) - log.Error(err) -} diff --git a/http_test.go b/http_test.go index 47a7a3e12ecc20da64c1f5476ea938d6783c44d7..94092e1ca63a862359cd9ca9ba4ad2fa753b4721 100644 --- a/http_test.go +++ b/http_test.go @@ -1,48 +1,10 @@ package gosdn import ( - "errors" "net/http" "testing" - - "code.fbi.h-da.de/cocsn/gosdn/nucleus/types" - - "code.fbi.h-da.de/cocsn/gosdn/mocks" - "code.fbi.h-da.de/cocsn/gosdn/nucleus" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "github.com/stretchr/testify/mock" ) -func testSetupHTTP() { - sbi = nucleus.NewSBI(types.Openconfig) - sbi.Schema() - defaultSbiID = sbi.ID() - var err error - httpTestPND, err = nucleus.NewPND("test", "test pnd", defaultPndID, sbi) - if err != nil { - log.Fatal(err) - } - httpTestDevice = mockDevice() - tr := httpTestDevice.Transport.(*mocks.Transport) - mockError := errors.New("mock error") - tr.On("Get", mockContext, "/system/config/hostname").Return(mock.Anything, nil) - tr.On("Get", mockContext, "error").Return(mock.Anything, mockError) - tr.On("Set", mockContext, mock.Anything).Return(mock.Anything, nil) - tr.On("ProcessResponse", mock.Anything, mock.Anything, mock.Anything).Return(nil) - if err := httpTestPND.AddDevice(&httpTestDevice); err != nil { - log.Fatal(err) - } - args = "&uuid=" + mdid.String() + "&pnd=" + defaultPndID.String() + "&sbi=" + defaultSbiID.String() - argsNotFound = "&uuid=" + uuid.New().String() + "&pnd=" + defaultPndID.String() + "&sbi=" + defaultSbiID.String() - if err := c.sbic.Add(sbi); err != nil { - log.Fatal(err) - } - if err := c.pndc.Add(httpTestPND); err != nil { - log.Fatal(err) - } -} - func Test_httpApi(t *testing.T) { tests := []struct { name string @@ -62,129 +24,6 @@ func Test_httpApi(t *testing.T) { want: &http.Response{StatusCode: http.StatusOK}, wantErr: false, }, - { - name: "init", - request: apiEndpoint + "/api?q=init", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "get-ids", - request: apiEndpoint + "/api?q=getIDs", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "add-device", - request: apiEndpoint + "/api?q=addDevice" + args, - want: &http.Response{StatusCode: http.StatusCreated}, - wantErr: false, - }, - { - name: "request", - request: apiEndpoint + "/api?q=request" + args + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "request not found", - request: apiEndpoint + "/api?q=request" + argsNotFound + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusNotFound}, - wantErr: false, - }, - { - name: "request internal server error", - request: apiEndpoint + "/api?q=request" + args + "&path=error", - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, - { - name: "request-all", - request: apiEndpoint + "/api?q=requestAll" + args + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "request-all internal server error", - request: apiEndpoint + "/api?q=requestAll" + args + "&path=error", - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, - - { - name: "get-device", - request: apiEndpoint + "/api?q=getDevice" + args, - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "get-device not found", - request: apiEndpoint + "/api?q=getDevice" + argsNotFound, - want: &http.Response{StatusCode: http.StatusNotFound}, - wantErr: false, - }, - { - name: "set", - request: apiEndpoint + "/api?q=update" + args + "&path=/system/config/hostname&value=ceos3000", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "replace", - request: apiEndpoint + "/api?q=replace" + args + "&path=/system/config/hostname&value=ceos3000", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "delete", - request: apiEndpoint + "/api?q=delete" + args + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "change list", - request: apiEndpoint + "/api?q=change-list" + args + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "change list pending", - request: apiEndpoint + "/api?q=change-list-pending" + args + "&path=/system/config/hostname", - want: &http.Response{StatusCode: http.StatusOK}, - wantErr: false, - }, - { - name: "change commit", - request: apiEndpoint + "/api?q=change-commit" + args + "&cuid=" + cuid.String(), - // TODO: Mock Change for testing - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, - { - name: "change confirm", - request: apiEndpoint + "/api?q=change-confirm" + args + "&cuid=" + cuid.String(), - // TODO: Mock Change for testing - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, - { - name: "bad request", - request: apiEndpoint + "/api?q=bad-request" + args, - want: &http.Response{StatusCode: http.StatusBadRequest}, - wantErr: false, - }, - { - name: "internal server errror: wrong pnd", - request: apiEndpoint + "/api?pnd=" + uuid.New().String(), - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, - { - name: "internal server errror: wrong sbi", - request: apiEndpoint + "/api?sbi=" + uuid.New().String(), - want: &http.Response{StatusCode: http.StatusInternalServerError}, - wantErr: false, - }, } coreLock.Lock() startHttpServer() @@ -199,16 +38,6 @@ func Test_httpApi(t *testing.T) { if got.StatusCode != tt.want.StatusCode { t.Errorf("httpApi() got: %v, want %v", got.StatusCode, tt.want.StatusCode) } - if tt.name == "add-device" { - for _, k := range httpTestPND.Devices() { - if k != mdid { - if err := httpTestPND.RemoveDevice(k); err != nil { - t.Error(err) - return - } - } - } - } }) } } diff --git a/initialise_test.go b/initialise_test.go index 5fbb298a7aa6a4cbc30aff8a80695aa1647eb34a..828a27730795b46353d71825c605828ab3316023 100644 --- a/initialise_test.go +++ b/initialise_test.go @@ -63,7 +63,6 @@ func TestMain(m *testing.M) { } readTestUUIDs() - testSetupHTTP() os.Exit(m.Run()) } diff --git a/northbound/client.go b/northbound/client.go deleted file mode 100644 index d0b2c91c94937844ed08444c7e8f53ea94583ffc..0000000000000000000000000000000000000000 --- a/northbound/client.go +++ /dev/null @@ -1 +0,0 @@ -package nbi diff --git a/northbound/client/client.go b/northbound/client/client.go new file mode 100644 index 0000000000000000000000000000000000000000..da13c8ef3ca33e1788a7b9560e0ade4e46b5f6f6 --- /dev/null +++ b/northbound/client/client.go @@ -0,0 +1 @@ +package client diff --git a/northbound/server.go b/northbound/server.go deleted file mode 100644 index 1463f95b9823b3e55321544867ea3a06b8687ba6..0000000000000000000000000000000000000000 --- a/northbound/server.go +++ /dev/null @@ -1,169 +0,0 @@ -package nbi - -import ( - 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 { - ppb.UnimplementedPndServer -} - -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) - sbiLock.RLock() - defer sbiLock.RUnlock() - 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 *ppb.SetRequest) (*ppb.SetResponse, error) { - panic("implement me") -} - -type gosdnServer struct { - pb.UnimplementedGosdnServer -} - -func (s gosdnServer) Get(ctx context.Context, request *pb.GetRequest) (*pb.GetResponse, error) { - panic("implement me") -} - -func (s gosdnServer) Set(ctx context.Context, request *pb.SetRequest) (*pb.SetResponse, error) { - panic("implement me") -} - -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 NorthboundInterface struct { - Pnd *pndServer - Controller *gosdnServer -} diff --git a/northbound/server/pnd.go b/northbound/server/pnd.go new file mode 100644 index 0000000000000000000000000000000000000000..f080fc1ac36035613f25c6050a35ccf99da3914a --- /dev/null +++ b/northbound/server/pnd.go @@ -0,0 +1,187 @@ +package server + +import ( + 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" + "reflect" + "time" +) + +type pndServer struct { + ppb.UnimplementedPndServer +} + +func (p pndServer) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse, error) { + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, err + } + switch req := request.Request.(type) { + case *ppb.GetRequest_Pnd: + return handleGetPnd(pid) + case *ppb.GetRequest_Ond: + return handleGetOnd(pid, req) + case *ppb.GetRequest_Sbi: + return handleGetSbi(pid, req) + case *ppb.GetRequest_Change: + return handleGetChange(pid, req) + default: + return nil, errors.ErrOperationNotSupported{Op: reflect.TypeOf(request.Request)} + } +} + +func handleGetPnd(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, true) + if err != nil { + return nil, err + } + sbis, err := fillSbis(pnd, true) + return &ppb.GetResponse{ + Timestamp: time.Now().UnixNano(), + Pnd: &ppb.PrincipalNetworkDomain{ + Id: "", + Name: "", + Description: "", + Ond: onds, + Sbi: sbis, + Change: nil, + }, + }, nil +} + +func handleGetSbi(pid uuid.UUID, req *ppb.GetRequest_Sbi) (*ppb.GetResponse, error) { + pndLock.RLock() + defer pndLock.RUnlock() + pnd, err := pndc.Get(pid) + if err != nil { + return nil, err + } + sbis, err := fillSbis(pnd, req.Sbi.GetAll(), req.Sbi.Sid...) + return &ppb.GetResponse{ + Timestamp: time.Now().UnixNano(), + Sbi: sbis, + }, nil +} + +func stringToUUID(sid []string) ([]uuid.UUID, error) { + UUIDs := make([]uuid.UUID, len(sid)) + for i, id := range sid { + parsed, err := uuid.Parse(id) + if err != nil { + return nil, err + } + UUIDs[i] = parsed + } + return UUIDs, nil +} + +func handleGetOnd(pid uuid.UUID, req *ppb.GetRequest_Ond) (*ppb.GetResponse, error) { + pndLock.RLock() + defer pndLock.RUnlock() + pnd, err := pndc.Get(pid) + if err != nil { + return nil, err + } + onds, err := fillOnds(pnd, req.Ond.All, req.Ond.Did...) + return &ppb.GetResponse{ + Timestamp: time.Now().UnixNano(), + Ond: onds, + }, nil +} + +func handleGetChange(pid uuid.UUID, req *ppb.GetRequest_Change) (*ppb.GetResponse, error) { + return nil, errors.ErrNotYetImplemented{} +} + +func fillSbis(pnd nucleus.PrincipalNetworkDomain, all bool, sid ...string) ([]*ppb.SouthboundInterface, error) { + var sbiList []uuid.UUID + + sbiStore := pnd.GetSBIs().(*nucleus.SbiStore) + switch all { + case true: + sbiList = sbiStore.UUIDs() + default: + var err error + if len(sid) == 0 { + return nil, &errors.ErrInvalidParameters{ + Func: fillSbis, + Param: "lenth of 'sid' cannot be '0' when 'all' is set to 'false'", + } + } + sbiList, err = stringToUUID(sid) + if err != nil { + return nil, err + } + } + sbis := make([]*ppb.SouthboundInterface, len(sbiStore.UUIDs())) + for i, id := range sbiList { + sbi, err := sbiStore.Get(id) + if err != nil { + return nil, err + } + sbis[i] = &ppb.SouthboundInterface{ + Id: id.String(), + Schema: sbi.Schema().RootSchema().Name, + } + } + return sbis, nil +} + +func fillOnds(pnd nucleus.PrincipalNetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { + var ondList []uuid.UUID + + switch all { + case true: + ondList = pnd.Devices() + default: + var err error + if len(did) == 0 { + return nil, &errors.ErrInvalidParameters{ + Func: fillOnds, + Param: "lenth of 'did' cannot be '0' when 'all' is set to 'false'", + } + } + ondList, err = stringToUUID(did) + if err != nil { + return nil, err + } + } + + onds := make([]*ppb.OrchestratedNetworkingDevice, len(pnd.Devices())) + for i, id := range ondList { + 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 + } + onds[i] = &ppb.OrchestratedNetworkingDevice{ + Id: id.String(), + Name: "", + Device: dev, + } + } + return onds, nil +} + +func fillChanges(pnd nucleus.PrincipalNetworkDomain) ([]*ppb.Change, error) { + // TODO: Allow access to changes + return nil, errors.ErrNotYetImplemented{} +} + +func (p pndServer) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) { + panic("implement me") +} diff --git a/northbound/server/server.go b/northbound/server/server.go new file mode 100644 index 0000000000000000000000000000000000000000..592504b0a42b79437f5581935386ccffeef03a73 --- /dev/null +++ b/northbound/server/server.go @@ -0,0 +1,41 @@ +package server + +import ( + pb "code.fbi.h-da.de/cocsn/api/proto/gosdn" + "code.fbi.h-da.de/cocsn/gosdn/nucleus" + "context" + "sync" +) + +var pndLock sync.RWMutex +var sbiLock sync.RWMutex +var pndc *nucleus.PndStore +var sbic *nucleus.SbiStore + +type gosdnServer struct { + pb.UnimplementedGosdnServer +} + +func (s gosdnServer) Get(ctx context.Context, request *pb.GetRequest) (*pb.GetResponse, error) { + panic("implement me") +} + +func (s gosdnServer) Set(ctx context.Context, request *pb.SetRequest) (*pb.SetResponse, error) { + panic("implement me") +} + +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 NorthboundInterface struct { + Pnd *pndServer + Controller *gosdnServer +} diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go index d5f7c369d40eb384de23049ea771e474d7d0a7fe..2ba89bf6fe2fc02c01124efb6d63e7d457ffd92a 100644 --- a/nucleus/gnmi_transport.go +++ b/nucleus/gnmi_transport.go @@ -79,7 +79,7 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error { } if len(args) == 0 { return &errors.ErrInvalidParameters{ - Func: "gnmi.Set()", + Func: "nucleus.Set()", Param: "no parameters provided", } } @@ -103,7 +103,7 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error { } } else if attrs == nil || len(attrs) == 0 { return &errors.ErrInvalidParameters{ - Func: "gnmi.Set()", + Func: "nucleus.Set()", Param: "no parameters provided", } } @@ -133,14 +133,14 @@ func (g *Gnmi) Set(ctx context.Context, args ...interface{}) error { exts = append(exts, p.(*gnmi_ext.Extension)) default: return &errors.ErrInvalidParameters{ - Func: "gnmi.Set()", + Func: "nucleus.Set()", Param: "args contain invalid type", } } } if len(ops) == 0 { return &errors.ErrInvalidParameters{ - Func: "gnmi.Set()", + Func: "nucleus.Set()", Param: "no operations provided", } }