package api import ( "context" "io" "time" 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" ) // AddDevice adds a new device to the controller. The device name is optional. // If no name is provided a name will be generated upon device creation. func AddDevice(ctx context.Context, addr, deviceName string, opt *tpb.TransportOption, sid, pid uuid.UUID) (*ppb.SetOndListResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.SetOndListRequest{ Timestamp: time.Now().UnixNano(), Ond: []*ppb.SetOnd{ { Address: opt.GetAddress(), Sbi: &spb.SouthboundInterface{ Id: sid.String(), }, DeviceName: deviceName, TransportOption: opt, }, }, Pid: pid.String(), } switch t := opt.Type; t { case spb.Type_TYPE_CONTAINERISED, spb.Type_TYPE_PLUGIN: req.Ond[0].Sbi.Id = uuid.Nil.String() req.Ond[0].Sbi.Type = t req.Ond[0].TransportOption.Type = t default: } return pndClient.SetOndList(ctx, req) } // GetDevice requests one device belonging to a given // PrincipalNetworkDomain from the controller. If no device identifier // is provided, an error is thrown. func GetDevice(ctx context.Context, addr, pid string, did ...string) (*ppb.GetOndResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } if len(did) == 0 { return nil, err } req := &ppb.GetOndRequest{ Timestamp: time.Now().UnixNano(), Did: did, Pid: pid, } return pndClient.GetOnd(ctx, req) } // GetSbiSchemaTree gets the sbi tree for a sbi func GetSbiSchemaTree(ctx context.Context, addr string, pid, sid uuid.UUID) (map[string]*yang.Entry, error) { sbiClient, err := nbi.SbiClient(addr, dialOptions...) if err != nil { return map[string]*yang.Entry{}, err } req := &spb.GetSchemaRequest{ Timestamp: time.Now().UnixNano(), Pid: pid.String(), Sid: sid.String(), } ctx, cancel := context.WithTimeout(ctx, time.Minute*10) defer cancel() sClient, err := sbiClient.GetSchema(ctx, req) if err != nil { return map[string]*yang.Entry{}, err } sTreeBytes := []byte{} for { payload, err := sClient.Recv() if err != nil { if err == io.EOF { break } log.Error(err) sClient.CloseSend() 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 } // GetDevices requests all devices belonging to a given // PrincipalNetworkDomain from the controller. func GetDevices(ctx context.Context, addr, pid string) (*ppb.GetOndListResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.GetOndListRequest{ Timestamp: time.Now().UnixNano(), Pid: pid, } return pndClient.GetOndList(ctx, req) } // GetPath requests a specific path func GetPath(ctx context.Context, addr, pid, did, path string) (*ppb.GetPathResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.GetPathRequest{ Timestamp: time.Now().UnixNano(), Did: did, Pid: pid, Path: path, } return pndClient.GetPath(ctx, req) } // DeleteDevice deletes a device func DeleteDevice(ctx context.Context, addr, pid, did string) (*ppb.DeleteOndResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { return nil, err } req := &ppb.DeleteOndRequest{ Timestamp: time.Now().UnixNano(), Did: did, Pid: pid, } return pndClient.DeleteOnd(ctx, req) }