Newer
Older
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"
"github.com/google/uuid"
"github.com/openconfig/ygot/ygot"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
ppb.UnimplementedPndServiceServer
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)
pid, err := uuid.Parse(request.Pid)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
onds, err := fillOnds(pnd, false, request.Did...)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Ond: onds,
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)
}
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
onds, err := fillOnds(pnd, true)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Ond: onds,
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)
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,
}
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)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
sbis, err := fillSbis(pnd, false, request.Sid...)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Sbi: sbis,
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)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Sbi: sbis,
func fillSbis(pnd networkdomain.NetworkDomain, all bool, sid ...string) ([]*spb.SouthboundInterface, error) {
switch all {
case true:
sbiList = sbiStore.UUIDs()
default:
var err error
if len(sid) == 0 {
return nil, &errors.ErrInvalidParameters{
Func: fillSbis,
Param: "length of 'sid' cannot be '0' when 'all' is set to 'false'",
}
}
sbiList, err = stringToUUID(sid)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
}
sbis := make([]*spb.SouthboundInterface, len(sbiList))
for i, id := range sbiList {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
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, status.Errorf(codes.Aborted, "%v", err)
UUIDs[i] = parsed
}
return UUIDs, nil
}
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)
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)
// In case we get the path from grpc-gateway we have to replace
path := strings.ReplaceAll(request.Path, "||", "/")
_, err = pnd.Request(duid, 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(),
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Device: ond[0].Device,
}, 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(),
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
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(),
Pnd: &ppb.PrincipalNetworkDomain{
Id: pnd.ID().String(),
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Change: changes,
func fillChanges(pnd networkdomain.NetworkDomain, all bool, cuid ...string) ([]*ppb.Change, error) {
var changeList []uuid.UUID
switch all {
case true:
changeList = pnd.PendingChanges()
changeList = append(changeList, pnd.CommittedChanges()...)
default:
var err error
if len(cuid) == 0 {
return nil, &errors.ErrInvalidParameters{
Func: fillOnds,
Param: "length of 'did' cannot be '0' when 'all' is set to 'false'",
}
}
changeList, err = stringToUUID(cuid)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
}
changes := make([]*ppb.Change, len(changeList))
for i, ch := range changeList {
c, err := pnd.GetChange(ch)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
changes[i] = &ppb.Change{
Id: ch.String(),
Age: c.Age().Microseconds(),
State: c.State(),
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)
pid, err := uuid.Parse(request.Pid)
if err != nil {
sid, err := uuid.Parse(r.Sbi.Id)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
if err := pnd.AddDevice(r.DeviceName, r.TransportOption, sid); err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
Status: ppb.Status_STATUS_OK,
Responses: []*ppb.SetResponse{
Status: ppb.Status_STATUS_OK,
},
},
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)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
default:
return nil, &errors.ErrInvalidParameters{
Param: r.Op,
}
}
}
Status: ppb.Status_STATUS_OK,
Responses: []*ppb.SetResponse{
Status: ppb.Status_STATUS_OK,
},
},
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)
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
// TODO: Return CUID in API
_, err = pnd.ChangeOND(did, r.ApiOp, r.Path, r.Value)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
Status: ppb.Status_STATUS_OK,
Responses: []*ppb.SetResponse{
Status: ppb.Status_STATUS_OK,
},
},
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
func (p pndServer) SetSbiList(ctx context.Context, request *ppb.SetSbiListRequest) (*ppb.SetSbiListResponse, 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.Sbi {
sbiType := filterSbiType(r.SbiType)
sbi, err := nucleus.NewSBI(sbiType)
if err != nil {
return nil, handleRPCError(labels, err)
}
err = pnd.AddSbi(sbi)
if err != nil {
return nil, handleRPCError(labels, err)
}
}
return &ppb.SetSbiListResponse{
Timestamp: time.Now().UnixNano(),
Status: ppb.Status_STATUS_OK,
Responses: []*ppb.SetResponse{
{
Status: ppb.Status_STATUS_OK,
},
},
}, nil
}
func filterSbiType(sbiType ppb.SbiType) spb.Type {
var spbType spb.Type
switch sbiType {
case ppb.SbiType_SBI_TYPE_OPENCONFIG:
spbType = spb.Type_TYPE_OPENCONFIG
case ppb.SbiType_SBI_TYPE_CONTAINERISED:
spbType = spb.Type_TYPE_CONTAINERISED
case ppb.SbiType_SBI_TYPE_PLUGIN:
spbType = spb.Type_TYPE_PLUGIN
default:
spbType = spb.Type_TYPE_UNSPECIFIED
}
return spbType
}
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)
}
pnd, err := pndc.GetPND(pid)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
if err := pnd.RemoveDevice(did); err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}