Skip to content
Snippets Groups Projects

WIP: Develop

Merged Ghost User requested to merge develop into master
2 files
+ 231
5
Compare changes
  • Side-by-side
  • Inline
Files
2
@@ -12,7 +12,9 @@ import (
"code.fbi.h-da.de/danet/gosdn/controller/nucleus"
"code.fbi.h-da.de/danet/gosdn/controller/nucleus/errors"
"github.com/google/uuid"
"github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
@@ -139,6 +141,100 @@ func fillOnds(pnd networkdomain.NetworkDomain, all bool, did ...string) ([]*ppb.
return onds, nil
}
func fillOndBySpecificPath(pnd networkdomain.NetworkDomain, did string, path string) (*ppb.OrchestratedNetworkingDevice, error) {
d, err := pnd.GetDevice(did)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
gnmiPath, err := ygot.StringToPath(path, ygot.StructuredPath)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
opts := []ytypes.GetNodeOpt{&ytypes.GetHandleWildcards{}}
nodes, err := ytypes.GetNode(d.SBI().Schema().RootSchema(), d.Model(), gnmiPath, opts...)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
// we should be fine to access nodes[0] here, since ytypes.GetNode() throws
// an error if there are no matches for the path.
nodeEntry := nodes[0].Schema
node := nodes[0].Data
var dev []*gnmi.Notification
if nodeEntry.IsDir() {
validatedNode, ok := nodes[0].Data.(ygot.ValidatedGoStruct)
if !ok {
return nil, status.Errorf(codes.Aborted, "%v", errors.ErrInvalidTypeAssertion{
Value: node,
Type: (ygot.ValidatedGoStruct)(nil),
})
}
cfg := ygot.GNMINotificationsConfig{}
dev, err = ygot.TogNMINotifications(validatedNode, time.Now().UnixNano(), cfg)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
} else if nodeEntry.IsLeaf() {
dev, err = genGnmiNotificationForLeaf(gnmiPath, node)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
}
sbi := spb.SouthboundInterface{}
if d.SBI() != nil {
sbi.Id = d.SBI().ID().String()
sbi.Type = d.SBI().Type()
}
ond := &ppb.OrchestratedNetworkingDevice{
Id: d.ID().String(),
Name: d.Name(),
Device: dev,
Sbi: &sbi,
}
return ond, nil
}
func genGnmiNotificationForLeaf(path *gnmi.Path, val any) ([]*gnmi.Notification, error) {
typedVal, err := ygot.EncodeTypedValue(val, gnmi.Encoding_PROTO)
if err != nil {
return nil, err
}
pathElem := path.GetElem()[len(path.GetElem())-1].GetName()
ppath := []string{pathElem}
return []*gnmi.Notification{
{
Timestamp: time.Now().UnixNano(),
Update: []*gnmi.Update{
{
Path: &gnmi.Path{
// NOTE: This is dirty and should be changed as soon as
// ygot.TogNMINotifications does not return
// notifications with `Element`!
// `Element` is marked as deprecated, but since
// ygot.TogNMINotifications returns `Element`, we will
// keep using it for now and to maintain consistency.
// Only returning the last element here, since we
// request a path node.
Element: ppath,
},
Val: typedVal,
},
},
},
}, nil
}
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)
@@ -276,11 +372,13 @@ func (p pndServer) GetPath(ctx context.Context, request *ppb.GetPathRequest) (*p
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
ond, err := fillOnds(pnd, false, request.Did)
ond, err := fillOndBySpecificPath(pnd, request.Did, path)
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
return &ppb.GetPathResponse{
Timestamp: time.Now().UnixNano(),
Pnd: &ppb.PrincipalNetworkDomain{
@@ -288,7 +386,7 @@ func (p pndServer) GetPath(ctx context.Context, request *ppb.GetPathRequest) (*p
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
Device: ond[0].Device,
Device: ond.Device,
}, nil
}
Loading