Skip to content
Snippets Groups Projects

Resolve "Refactor how PNDs are implemented in the code"

Merged Fabian Seidl requested to merge 243-refactor-how-pnds-are-implemented-in-the-code into develop
1 file
+ 191
112
Compare changes
  • Side-by-side
  • Inline
@@ -20,7 +20,8 @@ import (
"code.fbi.h-da.de/danet/gosdn/controller/store"
aGNMI "code.fbi.h-da.de/danet/gosdn/forks/goarista/gnmi"
"github.com/google/uuid"
"github.com/openconfig/gnmi/proto/gnmi"
gpb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/ygot/ygot"
"github.com/openconfig/ygot/ytypes"
"github.com/prometheus/client_golang/prometheus"
@@ -47,110 +48,188 @@ func NewNetworkElementServer(mneService networkelement.Service, pndService netwo
}
}
// // Add adds a new network element.
// func (n *NetworkElementServer) Add(ctx context.Context, request *mnepb.AddNetworkElementRequest) (*mnepb.AddNetworkElementResponse, error) {
// sbiID, err := uuid.Parse(request.NetworkElement.Sbi.Id)
// if err != nil {
// return nil, status.Errorf(codes.Aborted, "%v", err)
// }
// id, err := n.networkDomain.AddNetworkElement(
// request.NetworkElement.NetworkElementName,
// request.NetworkElement.TransportOption,
// sbiID,
// )
// if err != nil {
// return nil, status.Errorf(codes.Aborted, "%v", err)
// }
// return &mnepb.AddNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// NetworkElementId: id.String(),
// }, nil
// }
// func (n *NetworkElementServer) addNetworkElement(name string, transportOpt *tpb.TransportOption, sbiID uuid.UUID) (uuid.UUID, error) {
// }
// // GetAll returns all stored network elements.
// func (n *NetworkElementServer) GetAll(ctx context.Context, request *mnepb.GetAllNetworkElementRequest) (*mnepb.GetAllNetworkElementResponse, error) {
// networkElements := n.networkDomain.NetworkElements()
// mnes := []*mnepb.NetworkElement{}
// for _, mne := range networkElements {
// ygotStructAsJSON, err := mne.GetModelAsString()
// if err != nil {
// log.Error(err)
// return nil, status.Errorf(codes.Aborted, "%v", err)
// }
// mnes = append(mnes, &mnepb.NetworkElement{
// Id: mne.ID().String(),
// Name: mne.Name(),
// Model: ygotStructAsJSON,
// })
// }
// return &mnepb.GetAllNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// NetworkElement: mnes,
// }, nil
// }
// // Get returns a network element.
// func (n *NetworkElementServer) Get(ctx context.Context, request *mnepb.GetNetworkElementRequest) (*mnepb.GetNetworkElementResponse, error) {
// mne, err := n.networkDomain.GetNetworkElement(request.NetworkElementId)
// if err != nil {
// return nil, status.Errorf(codes.Aborted, "%v", err)
// }
// ygotStructAsJSON, err := mne.GetModelAsString()
// if err != nil {
// log.Error(err)
// return nil, status.Errorf(codes.Aborted, "%v", err)
// }
// networkElement := &mnepb.NetworkElement{
// Id: mne.ID().String(),
// Name: mne.Name(),
// Model: ygotStructAsJSON,
// TransportAddress: mne.TransportAddress(),
// }
// return &mnepb.GetNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// NetworkElement: networkElement,
// }, nil
// }
// // Update updates a network element.
// func (n *NetworkElementServer) Update(ctx context.Context, request *mnepb.UpdateNetworkElementRequest) (*mnepb.UpdateNetworkElementResponse, error) {
// mneID, err := uuid.Parse(request.NetworkElement.Id)
// if err != nil {
// return &mnepb.UpdateNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// }, err
// }
// err = n.networkDomain.UpdateNetworkElement(mneID, request.NetworkElement.Model)
// if err != nil {
// return &mnepb.UpdateNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// }, err
// }
// return &mnepb.UpdateNetworkElementResponse{
// Timestamp: time.Now().UnixNano(),
// Status: mnepb.Status_STATUS_OK,
// }, nil
// }
// Add adds a new network element.
func (n *NetworkElementServer) Add(ctx context.Context, request *mnepb.AddNetworkElementRequest) (*mnepb.AddNetworkElementResponse, error) {
sbiID, err := uuid.Parse(request.NetworkElement.Sbi.Id)
if err != nil {
return nil, status.Errorf(codes.Aborted, "%v", err)
}
id, err := n.addNetworkElement(ctx, request.NetworkElement.NetworkElementName, request.NetworkElement.TransportOption, sbiID)
if err != nil {
return nil, status.Errorf(codes.Aborted, "%v", err)
}
return &mnepb.AddNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_OK,
NetworkElementId: id.String(),
}, nil
}
func (n *NetworkElementServer) addNetworkElement(ctx context.Context, name string, transportOpt *tpb.TransportOption, sbiID uuid.UUID) (uuid.UUID, error) {
var sbi southbound.SouthboundInterface
var err error
// TODO(PND): figure out how to handle cSBI stuff?!
// switch t := opt.Type; t {
// case spb.Type_TYPE_CONTAINERISED:
// return pnd.handleCsbiEnrolment(name, opt)
// case spb.Type_TYPE_PLUGIN:
// sbi, err = pnd.requestPlugin(name, opt)
// if err != nil {
// return uuid.Nil, err
// }
// default:
// var err error
// sbi, err = n.sbiService.Get(store.Query{ID: sbiID})
// if err != nil {
// return uuid.Nil, err
// }
// }
sbi, err = n.sbiService.Get(store.Query{ID: sbiID})
if err != nil {
return uuid.Nil, err
}
mne, err := nucleus.NewNetworkElement(name, uuid.Nil, transportOpt, sbi, conflict.Metadata{ResourceVersion: 0})
if err != nil {
return uuid.Nil, err
}
err = n.mneService.Add(mne)
if err != nil {
return uuid.Nil, err
}
if mne.IsTransportValid() {
_, err = n.getPath(ctx, mne.ID(), "/interfaces")
if err != nil {
return uuid.Nil, err
}
}
return mne.ID(), nil
}
// GetAll returns all stored network elements.
func (n *NetworkElementServer) GetAll(ctx context.Context, request *mnepb.GetAllNetworkElementRequest) (*mnepb.GetAllNetworkElementResponse, error) {
networkElements, err := n.mneService.GetAll()
if err != nil {
return nil, err
}
mnes := []*mnepb.NetworkElement{}
for _, mne := range networkElements {
ygotStructAsJSON, err := mne.GetModelAsString()
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
mnes = append(mnes, &mnepb.NetworkElement{
Id: mne.ID().String(),
Name: mne.Name(),
Model: ygotStructAsJSON,
})
}
return &mnepb.GetAllNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_OK,
NetworkElement: mnes,
}, nil
}
// Get returns a network element.
func (n *NetworkElementServer) Get(ctx context.Context, request *mnepb.GetNetworkElementRequest) (*mnepb.GetNetworkElementResponse, error) {
mne, err := n.mneService.Get(store.Query{ID: uuid.MustParse(request.NetworkElementId)})
if err != nil {
return nil, err
}
ygotStructAsJSON, err := mne.GetModelAsString()
if err != nil {
log.Error(err)
return nil, status.Errorf(codes.Aborted, "%v", err)
}
networkElement := &mnepb.NetworkElement{
Id: mne.ID().String(),
Name: mne.Name(),
Model: ygotStructAsJSON,
TransportAddress: mne.TransportAddress(),
}
return &mnepb.GetNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_OK,
NetworkElement: networkElement,
}, nil
}
// Update updates a network element.
func (n *NetworkElementServer) Update(ctx context.Context, request *mnepb.UpdateNetworkElementRequest) (*mnepb.UpdateNetworkElementResponse, error) {
mneID, err := uuid.Parse(request.NetworkElement.Id)
if err != nil {
return &mnepb.UpdateNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_ERROR,
}, err
}
err = n.mneService.UpdateModel(mneID, request.NetworkElement.Model)
if err != nil {
return &mnepb.UpdateNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_OK,
}, err
}
err = n.ensureIntendedConfigurationIsAppliedOnNetworkElement(mneID)
return &mnepb.UpdateNetworkElementResponse{
Timestamp: time.Now().UnixNano(),
Status: mnepb.Status_STATUS_OK,
}, nil
}
func (n *NetworkElementServer) ensureIntendedConfigurationIsAppliedOnNetworkElement(mneID uuid.UUID) error {
mne, err := n.mneService.Get(store.Query{
ID: mneID,
})
if err != nil {
return err
}
model, err := mne.GetModelAsString()
if err != nil {
return err
}
req := &gpb.SetRequest{}
path, err := ygot.StringToStructuredPath("/")
if err != nil {
return err
}
req.Update = []*gpb.Update{{
Path: path,
Val: &gpb.TypedValue{
Value: &gpb.TypedValue_JsonIetfVal{JsonIetfVal: []byte(model)},
},
}}
response, err := mne.Transport().CustomSet(context.Background(), req)
if err != nil {
log.Errorf("Failed to apply model of network element err=%+v, response=%+v", err, response)
return err
}
return nil
}
// GetMne gets a specific mne.
func (n *NetworkElementServer) GetMne(ctx context.Context, request *mnepb.GetMneRequest) (*mnepb.GetMneResponse, error) {
@@ -316,7 +395,7 @@ func fillMneBySpecificPath(nme networkelement.NetworkElement, path string) (*mne
return nil, status.Errorf(codes.Aborted, "%v", err)
}
notifications := make([]*gnmi.Notification, len(nodes))
notifications := make([]*gpb.Notification, len(nodes))
for i, node := range nodes {
mneNotification, err := genGnmiNotification(gnmiPath, node.Data)
if err != nil {
@@ -343,16 +422,16 @@ func fillMneBySpecificPath(nme networkelement.NetworkElement, path string) (*mne
return mne, nil
}
func genGnmiNotification(path *gnmi.Path, val any) (*gnmi.Notification, error) {
typedVal, err := ygot.EncodeTypedValue(val, gnmi.Encoding_JSON_IETF)
func genGnmiNotification(path *gpb.Path, val any) (*gpb.Notification, error) {
typedVal, err := ygot.EncodeTypedValue(val, gpb.Encoding_JSON_IETF)
if err != nil {
return nil, err
}
return &gnmi.Notification{
return &gpb.Notification{
Timestamp: time.Now().UnixNano(),
Update: []*gnmi.Update{
Update: []*gpb.Update{
{
Path: &gnmi.Path{
Path: &gpb.Path{
Elem: path.GetElem(),
},
Val: typedVal,
@@ -400,7 +479,7 @@ func (n *NetworkElementServer) GetPath(ctx context.Context, request *mnepb.GetPa
Name: pnd.GetName(),
Description: pnd.GetDescription(),
},
MneNotification: resp.(*gnmi.GetResponse).Notification,
MneNotification: resp.(*gpb.GetResponse).Notification,
}, nil
}
Loading