diff --git a/northbound/server/pnd.go b/northbound/server/pnd.go index 1c86280658c2d814c2a803329bded0aef5d29d57..5597f2e9a3d82f459690b13abb490143c495f2ab 100644 --- a/northbound/server/pnd.go +++ b/northbound/server/pnd.go @@ -2,12 +2,8 @@ package server import ( "context" - "reflect" "time" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - ppb "code.fbi.h-da.de/danet/api/go/gosdn/pnd" spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound" "code.fbi.h-da.de/danet/gosdn/interfaces/networkdomain" @@ -17,13 +13,15 @@ import ( "github.com/openconfig/ygot/ygot" "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) type pndServer struct { ppb.UnimplementedPndServiceServer } -func (p pndServer) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetResponse, error) { +func (p pndServer) GetOnd(ctx context.Context, request *ppb.GetOndRequest) (*ppb.GetOndResponse, error) { labels := prometheus.Labels{"service": "pnd", "rpc": "get"} start := metrics.StartHook(labels, grpcRequestsTotal) defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) @@ -31,146 +29,145 @@ func (p pndServer) Get(ctx context.Context, request *ppb.GetRequest) (*ppb.GetRe if err != nil { return nil, handleRPCError(labels, 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) - case *ppb.GetRequest_Path: - return handleGetPath(pid, req) - default: - return nil, handleRPCError(labels, errors.ErrOperationNotSupported{Op: reflect.TypeOf(request.Request)}) - } -} -func handleGetPnd(pid uuid.UUID) (*ppb.GetResponse, error) { pnd, err := pndc.GetPND(pid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - onds, err := fillOnds(pnd, true) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - sbis, err := fillSbis(pnd, true) + onds, err := fillOnds(pnd, false, request.Did...) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - changes, err := fillChanges(pnd, true) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - - return &ppb.GetResponse{ + return &ppb.GetOndResponse{ Timestamp: time.Now().UnixNano(), - Pnd: &ppb.PrincipalNetworkDomain{ - Id: pnd.ID().String(), - Name: pnd.GetName(), - Description: pnd.GetDescription(), - Ond: onds, - Sbi: sbis, - Change: changes, - }, + Ond: onds, }, nil } -func handleGetSbi(pid uuid.UUID, req *ppb.GetRequest_Sbi) (*ppb.GetResponse, error) { +func (p pndServer) GetOndList(ctx context.Context, request *ppb.GetOndListRequest) (*ppb.GetOndListResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + pnd, err := pndc.GetPND(pid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - sbis, err := fillSbis(pnd, req.Sbi.GetAll(), req.Sbi.Sid...) + onds, err := fillOnds(pnd, true, "") if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - return &ppb.GetResponse{ + return &ppb.GetOndListResponse{ Timestamp: time.Now().UnixNano(), - Sbi: sbis, + Ond: onds, }, nil } -func stringToUUID(sid []string) ([]uuid.UUID, error) { - UUIDs := make([]uuid.UUID, len(sid)) - for i, id := range sid { - parsed, err := uuid.Parse(id) +func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { + var ondList []uuid.UUID + var onds []*ppb.OrchestratedNetworkingDevice + + // all indicates if a client wants all devices or only a single one + switch all { + case true: + ondList = pnd.Devices() + onds = make([]*ppb.OrchestratedNetworkingDevice, len(ondList)) + for _, id := range ondList { + did = append(did, id.String()) + } + default: + if len(did) == 0 { + err := &errors.ErrInvalidParameters{ + Func: fillOnds, + Param: "length of 'did' cannot be '0' when 'all' is set to 'false'", + } + log.Error(err) + + return nil, err + } + + onds = make([]*ppb.OrchestratedNetworkingDevice, 1) + } + + for i, id := range did { + d, err := pnd.GetDevice(id) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - UUIDs[i] = parsed + cfg := ygot.GNMINotificationsConfig{} + dev, err := ygot.TogNMINotifications(d.Model(), time.Now().UnixNano(), cfg) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + onds[i] = &ppb.OrchestratedNetworkingDevice{ + Id: id, + Name: d.Name(), + Device: dev, + } } - return UUIDs, nil + + return onds, nil } -func handleGetOnd(pid uuid.UUID, req *ppb.GetRequest_Ond) (*ppb.GetResponse, error) { - pnd, err := pndc.GetPND(pid) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - onds, err := fillOnds(pnd, req.Ond.All, req.Ond.Did...) +func (p pndServer) GetSbi(ctx context.Context, request *ppb.GetSbiRequest) (*ppb.GetSbiResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) + return nil, handleRPCError(labels, err) } - return &ppb.GetResponse{ - Timestamp: time.Now().UnixNano(), - Ond: onds, - }, nil -} -func handleGetChange(pid uuid.UUID, req *ppb.GetRequest_Change) (*ppb.GetResponse, error) { pnd, err := pndc.GetPND(pid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - changes, err := fillChanges(pnd, req.Change.All, req.Change.Cuid...) + sbis, err := fillSbis(pnd, false, request.Sid...) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - return &ppb.GetResponse{ + return &ppb.GetSbiResponse{ Timestamp: time.Now().UnixNano(), - Change: changes, + Sbi: sbis, }, nil } -func handleGetPath(pid uuid.UUID, req *ppb.GetRequest_Path) (*ppb.GetResponse, error) { - pnd, err := pndc.GetPND(pid) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - duid, err := uuid.Parse(req.Path.Did) +func (p pndServer) GetSbiList(ctx context.Context, request *ppb.GetSbiListRequest) (*ppb.GetSbiListResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) + return nil, handleRPCError(labels, err) } - _, err = pnd.Request(duid, req.Path.Path) + + pnd, err := pndc.GetPND(pid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - ond, err := fillOnds(pnd, false, req.Path.Did) + sbis, err := fillSbis(pnd, true, "") if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - return &ppb.GetResponse{ + return &ppb.GetSbiListResponse{ Timestamp: time.Now().UnixNano(), - Ond: ond, + Sbi: sbis, }, nil + } func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) { @@ -208,52 +205,103 @@ func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb. return sbis, nil } -func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.OrchestratedNetworkingDevice, error) { - var ondList []uuid.UUID - var onds []*ppb.OrchestratedNetworkingDevice - - // all indicates if a client wants all devices or only a single one - switch all { - case true: - ondList = pnd.Devices() - onds = make([]*ppb.OrchestratedNetworkingDevice, len(ondList)) - for _, id := range ondList { - did = append(did, id.String()) - } - default: - if len(did) == 0 { - err := &errors.ErrInvalidParameters{ - Func: fillOnds, - Param: "length of 'did' cannot be '0' when 'all' is set to 'false'", - } +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 { log.Error(err) - - return nil, err + return nil, status.Errorf(codes.Aborted, "%v", err) } + UUIDs[i] = parsed + } + return UUIDs, nil +} - onds = make([]*ppb.OrchestratedNetworkingDevice, 1) +func (p pndServer) GetPath(ctx context.Context, request *ppb.GetPathRequest) (*ppb.GetPathResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) } - for i, id := range did { - d, err := pnd.GetDevice(id) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - cfg := ygot.GNMINotificationsConfig{} - dev, err := ygot.TogNMINotifications(d.Model(), time.Now().UnixNano(), cfg) - if err != nil { - log.Error(err) - return nil, status.Errorf(codes.Aborted, "%v", err) - } - onds[i] = &ppb.OrchestratedNetworkingDevice{ - Id: id, - Name: d.Name(), - Device: dev, - } + pnd, err := pndc.GetPND(pid) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + duid, err := uuid.Parse(request.Did) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) } + _, err = pnd.Request(duid, request.Path) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + ond, err := fillOnds(pnd, false, request.Did) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + return &ppb.GetPathResponse{ + Timestamp: time.Now().UnixNano(), + Device: ond[0].Device, + }, nil - return onds, nil +} + +func (p pndServer) GetChange(ctx context.Context, request *ppb.GetChangeRequest) (*ppb.GetChangeResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + pnd, err := pndc.GetPND(pid) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + changes, err := fillChanges(pnd, false, request.Cuid) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + return &ppb.GetChangeResponse{ + Timestamp: time.Now().UnixNano(), + Change: changes, + }, nil +} + +func (p pndServer) GetChangeList(ctx context.Context, request *ppb.GetChangeListRequest) (*ppb.GetChangeListResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "get"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + pnd, err := pndc.GetPND(pid) + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + changes, err := fillChanges(pnd, true, "") + if err != nil { + log.Error(err) + return nil, status.Errorf(codes.Aborted, "%v", err) + } + return &ppb.GetChangeListResponse{ + Timestamp: time.Now().UnixNano(), + Change: changes, + }, nil } func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*ppb.Change, error) { @@ -295,7 +343,7 @@ func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]* return changes, nil } -func (p pndServer) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) { +func (p pndServer) SetOndList(ctx context.Context, request *ppb.SetOndListRequest) (*ppb.SetOndListResponse, error) { labels := prometheus.Labels{"service": "pnd", "rpc": "set"} start := metrics.StartHook(labels, grpcRequestsTotal) defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) @@ -309,31 +357,7 @@ func (p pndServer) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetRe return nil, handleRPCError(labels, err) } - ondResp, err := handleSetOnd(pnd, request.Ond) - if err != nil { - return nil, handleRPCError(labels, err) - } - changeResp, err := handleSetChange(pnd, request.Change) - if err != nil { - return nil, handleRPCError(labels, err) - } - changeRequestResp, err := handleChangeRequest(pnd, request.ChangeRequest) - if err != nil { - return nil, handleRPCError(labels, err) - } - return &ppb.SetResponse{ - Timestamp: time.Now().UnixNano(), - Status: ppb.SetResponse_OK, - Responses: []*ppb.SetResponse{ - ondResp, - changeResp, - changeRequestResp, - }, - }, nil -} - -func handleSetOnd(pnd networkdomain.NetworkDomain, req []*ppb.SetOnd) (*ppb.SetResponse, error) { - for _, r := range req { + for _, r := range request.Ond { sid, err := uuid.Parse(r.Sbi.Id) if err != nil { log.Error(err) @@ -344,46 +368,81 @@ func handleSetOnd(pnd networkdomain.NetworkDomain, req []*ppb.SetOnd) (*ppb.SetR return nil, status.Errorf(codes.Aborted, "%v", err) } } - return &ppb.SetResponse{ + return &ppb.SetOndListResponse{ Timestamp: time.Now().UnixNano(), - Status: ppb.SetResponse_OK, + Status: ppb.Status_STATUS_OK, + Responses: []*ppb.SetResponse{ + &ppb.SetResponse{ + Status: ppb.Status_STATUS_OK, + }, + }, }, nil } -func handleSetChange(pnd networkdomain.NetworkDomain, req []*ppb.SetChange) (*ppb.SetResponse, error) { - for _, r := range req { +func (p pndServer) SetChangeList(ctx context.Context, request *ppb.SetChangeListRequest) (*ppb.SetChangeListResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "set"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + pnd, err := pndc.GetPND(pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + for _, r := range request.Change { cuid, err := uuid.Parse(r.Cuid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } switch r.Op { - case ppb.SetChange_COMMIT: + case ppb.Operation_OPERATION_COMMIT: if err := pnd.Commit(cuid); err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - case ppb.SetChange_CONFIRM: + case ppb.Operation_OPERATION_CONFIRM: if err := pnd.Confirm(cuid); err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } default: return nil, &errors.ErrInvalidParameters{ - Func: handleSetChange, Param: r.Op, } } } - return &ppb.SetResponse{ + return &ppb.SetChangeListResponse{ Timestamp: time.Now().UnixNano(), - Status: ppb.SetResponse_OK, + Status: ppb.Status_STATUS_OK, + Responses: []*ppb.SetResponse{ + &ppb.SetResponse{ + Status: ppb.Status_STATUS_OK, + }, + }, }, nil } -func handleChangeRequest(pnd networkdomain.NetworkDomain, req []*ppb.ChangeRequest) (*ppb.SetResponse, error) { - for _, r := range req { - did, err := uuid.Parse(r.Id) +func (p pndServer) SetPathList(ctx context.Context, request *ppb.SetPathListRequest) (*ppb.SetPathListResponse, error) { + labels := prometheus.Labels{"service": "pnd", "rpc": "set"} + start := metrics.StartHook(labels, grpcRequestsTotal) + defer metrics.FinishHook(labels, start, grpcRequestDurationSecondsTotal, grpcRequestDurationSeconds) + pid, err := uuid.Parse(request.Pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + pnd, err := pndc.GetPND(pid) + if err != nil { + return nil, handleRPCError(labels, err) + } + + for _, r := range request.ChangeRequest { + did, err := uuid.Parse(r.Did) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -395,14 +454,20 @@ func handleChangeRequest(pnd networkdomain.NetworkDomain, req []*ppb.ChangeReque return nil, status.Errorf(codes.Aborted, "%v", err) } } - return &ppb.SetResponse{ + return &ppb.SetPathListResponse{ Timestamp: time.Now().UnixNano(), - Status: ppb.SetResponse_OK, + Status: ppb.Status_STATUS_OK, + Responses: []*ppb.SetResponse{ + &ppb.SetResponse{ + Status: ppb.Status_STATUS_OK, + }, + }, }, nil + } -func (p pndServer) Delete(ctx context.Context, req *ppb.DeleteRequest) (*ppb.DeleteResponse, error) { - pid, err := uuid.Parse(req.Pid) +func (p pndServer) DeleteOnd(ctx context.Context, request *ppb.DeleteOndRequest) (*ppb.DeleteOndResponse, error) { + pid, err := uuid.Parse(request.Pid) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -413,7 +478,7 @@ func (p pndServer) Delete(ctx context.Context, req *ppb.DeleteRequest) (*ppb.Del return nil, status.Errorf(codes.Aborted, "%v", err) } - did, err := uuid.Parse(req.Uuid) + did, err := uuid.Parse(request.Did) if err != nil { log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) @@ -422,8 +487,9 @@ func (p pndServer) Delete(ctx context.Context, req *ppb.DeleteRequest) (*ppb.Del log.Error(err) return nil, status.Errorf(codes.Aborted, "%v", err) } - return &ppb.DeleteResponse{ + return &ppb.DeleteOndResponse{ Timestamp: time.Now().UnixNano(), - Status: ppb.DeleteResponse_OK, + Status: ppb.Status_STATUS_OK, }, nil + }