package api import ( "context" "errors" "io" "time" pipb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-internal" ppb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd" spb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/southbound" tpb "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/transport" nbi "code.fbi.h-da.de/danet/gosdn/controller/northbound/client" "github.com/google/uuid" "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" log "github.com/sirupsen/logrus" ) // AddNetworkElement adds a new network element to the controller. The network element name is optional. // If no name is provided a name will be generated upon network element creation. func AddNetworkElement(ctx context.Context, addr, mneName string, opt *tpb.TransportOption, pluginID, pid uuid.UUID) (*ppb.SetMneListResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.SetMneListRequest{ Timestamp: time.Now().UnixNano(), Mne: []*ppb.SetMne{ { Address: opt.GetAddress(), MneName: mneName, PluginId: pluginID.String(), Pid: pid.String(), TransportOption: opt, }, }, Pid: pid.String(), } switch t := opt.Type; t { case spb.Type_TYPE_CONTAINERISED, spb.Type_TYPE_PLUGIN: req.Mne[0].TransportOption.Type = t default: } return pndClient.SetMneList(ctx, req) } // GetNetworkElement requests one network element belonging to a given // PrincipalNetworkDomain from the controller. If no network element identifier // is provided, an error is thrown. func GetNetworkElement(ctx context.Context, addr, pid string, mneid string) (*ppb.GetMneResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } if len(mneid) == 0 { return nil, err } req := &ppb.GetMneRequest{ Timestamp: time.Now().UnixNano(), Mneid: mneid, Pid: pid, } return pndClient.GetMne(ctx, req) } // GetPluginSchemaTree gets the schema tree for a plugin. func GetPluginSchemaTree(ctx context.Context, addr string, pluginID uuid.UUID) (map[string]*yang.Entry, error) { pluginClient, err := nbi.PluginClient(addr, dialOptions...) if err != nil { return map[string]*yang.Entry{}, err } req := &pipb.GetPluginSchemaRequest{ Timestamp: time.Now().UnixNano(), Pid: pluginID.String(), } ctx, cancel := context.WithTimeout(ctx, time.Minute*10) defer cancel() sClient, err := pluginClient.GetPluginSchema(ctx, req) if err != nil { return map[string]*yang.Entry{}, err } sTreeBytes := []byte{} for { payload, err := sClient.Recv() if err != nil { if errors.Is(err, io.EOF) { break } log.Error(err) closeErr := sClient.CloseSend() if closeErr != nil { return nil, err } return map[string]*yang.Entry{}, err } sTreeBytes = append(sTreeBytes, payload.Chunk...) } sTreeMap, err := ygot.GzipToSchema(sTreeBytes) if err != nil { return map[string]*yang.Entry{}, err } return sTreeMap, nil } // GetFlattenedNetworkElement requests a network elements belonging to a given // PrincipalNetworkDomain from the controller. func GetFlattenedNetworkElement(ctx context.Context, addr, pid string, mneid string) (*ppb.GetFlattenedMneResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.GetMneRequest{ Timestamp: time.Now().UnixNano(), Mneid: mneid, Pid: pid, } return pndClient.GetFlattenedMne(ctx, req) } // GetFlattenedNetworkElements requests all network elements belonging to a given // PrincipalNetworkDomain from the controller. func GetFlattenedNetworkElements(ctx context.Context, addr, pid string) (*ppb.GetFlattenedMneListResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.GetMneListRequest{ Timestamp: time.Now().UnixNano(), Pid: pid, } return pndClient.GetFlattenedMneList(ctx, req) } // GetPath requests a specific path. func GetPath(ctx context.Context, addr, pid, mneid, path string) (*ppb.GetPathResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.GetPathRequest{ Timestamp: time.Now().UnixNano(), Mneid: mneid, Pid: pid, Path: path, } return pndClient.GetPath(ctx, req) } // SubscribePath subscribes to paths on a network element. func SubscribePath(ctx context.Context, addr, pid, mneid string, slist *ppb.SubscriptionList) (ppb.PndService_SubscribePathClient, error) { log.Println("subscribePath called") pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.SubscribePathRequest{ Timestamp: time.Now().UnixNano(), Mneid: mneid, Pid: pid, Sublist: slist, } return pndClient.SubscribePath(ctx, req) } // DeleteNetworkElement deletes a network element. func DeleteNetworkElement(ctx context.Context, addr, pid, mneid string) (*ppb.DeleteMneResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.DeleteMneRequest{ Timestamp: time.Now().UnixNano(), Mneid: mneid, Pid: pid, } return pndClient.DeleteMne(ctx, req) }