From: prabhukaliswamy Date: Mon, 23 Dec 2019 09:51:01 +0000 (+0000) Subject: Multiple E2T instance feature - Introduced APIs Delete E2T Instance and associate... X-Git-Tag: 0.4.9~5 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=e110ee0d197cd7d61faf4ad761ebad3bf0c68121;p=ric-plt%2Frtmgr.git Multiple E2T instance feature - Introduced APIs Delete E2T Instance and associate RANs to E2T & disassociate RANs from E2T Instance Change-Id: Ic3380caee22e53daf46ffc8a26a828003d218f3b Signed-off-by: prabhukaliswamy --- diff --git a/Dockerfile b/Dockerfile index e69fc75..faec945 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ # a Docker tag from the string in file container-tag.yaml #FROM golang:1.12.1 as rtmgrbuild -FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu18-c-go:2-u18.04-nng as rtmgrbuild +FROM nexus3.o-ran-sc.org:10004/bldr-ubuntu18-c-go:3-u18.04-nng as rtmgrbuild # Install RMr shared library RUN wget --content-disposition https://packagecloud.io/o-ran-sc/staging/packages/debian/stretch/rmr_1.10.2_amd64.deb/download.deb && dpkg -i rmr_1.10.2_amd64.deb && rm -rf rmr_1.10.2_amd64.deb diff --git a/RELNOTES b/RELNOTES index 20b981c..f7946db 100644 --- a/RELNOTES +++ b/RELNOTES @@ -1,3 +1,6 @@ +### v0.4.5 +* Multiple E2T instance Feature: Introduced APIs Delete E2T Instance, associate RANs to E2T and disassociate RANs from E2T Instance. + ### v0.4.4 * Create E2T Instance API introduced for Multiple E2T Feature diff --git a/cmd/rtmgr.go b/cmd/rtmgr.go index a33437a..ceb28e8 100644 --- a/cmd/rtmgr.go +++ b/cmd/rtmgr.go @@ -45,6 +45,7 @@ import ( "routing-manager/pkg/sdl" "syscall" "time" + "sync" ) const SERVICENAME = "rtmgr" @@ -63,16 +64,18 @@ func initRtmgr() (nbiEngine nbi.Engine, sbiEngine sbi.Engine, sdlEngine sdl.Engi return nil, nil, nil, nil, err } -func serveSBI(triggerSBI <-chan bool, sbiEngine sbi.Engine, sdlEngine sdl.Engine, rpeEngine rpe.Engine) { +func serveSBI(triggerSBI <-chan bool, sbiEngine sbi.Engine, sdlEngine sdl.Engine, rpeEngine rpe.Engine, m *sync.Mutex) { for { if <-triggerSBI { + m.Lock() data, err := sdlEngine.ReadAll(xapp.Config.GetString("rtfile")) + m.Unlock() if err != nil || data == nil { xapp.Logger.Error("Cannot get data from sdl interface due to: " + err.Error()) continue } sbiEngine.UpdateEndpoints(data) - policies := rpeEngine.GeneratePolicies(rtmgr.Eps) + policies := rpeEngine.GeneratePolicies(rtmgr.Eps, data) err = sbiEngine.DistributeAll(policies) if err != nil { xapp.Logger.Error("Routing table cannot be published due to: " + err.Error()) @@ -81,12 +84,12 @@ func serveSBI(triggerSBI <-chan bool, sbiEngine sbi.Engine, sdlEngine sdl.Engine } } -func serve(nbiEngine nbi.Engine, sbiEngine sbi.Engine, sdlEngine sdl.Engine, rpeEngine rpe.Engine) { +func serve(nbiEngine nbi.Engine, sbiEngine sbi.Engine, sdlEngine sdl.Engine, rpeEngine rpe.Engine, m *sync.Mutex) { triggerSBI := make(chan bool) nbiErr := nbiEngine.Initialize(xapp.Config.GetString("xmurl"), xapp.Config.GetString("nbiurl"), xapp.Config.GetString("rtfile"), xapp.Config.GetString("cfgfile"), - sdlEngine, rpeEngine, triggerSBI) + sdlEngine, rpeEngine, triggerSBI, m) if nbiErr != nil { xapp.Logger.Error("Failed to initialize nbi due to: " + nbiErr.Error()) return @@ -101,7 +104,7 @@ func serve(nbiEngine nbi.Engine, sbiEngine sbi.Engine, sdlEngine sdl.Engine, rpe defer sbiEngine.Terminate() // This SBI Go routine is trtiggered by periodic main loop and when data is recieved on REST interface. - go serveSBI(triggerSBI, sbiEngine, sdlEngine, rpeEngine) + go serveSBI(triggerSBI, sbiEngine, sdlEngine, rpeEngine, m) for { if xapp.Config.GetString("nbi") == "httpGetter" { @@ -139,6 +142,9 @@ func main() { SetupCloseHandler() xapp.Logger.Info("Start " + SERVICENAME + " service") rtmgr.Eps = make(rtmgr.Endpoints) - serve(nbiEngine, sbiEngine, sdlEngine, rpeEngine) + + var m sync.Mutex + + serve(nbiEngine, sbiEngine, sdlEngine, rpeEngine, &m) os.Exit(0) } diff --git a/container-tag.yaml b/container-tag.yaml index cfdbfb8..a89789a 100644 --- a/container-tag.yaml +++ b/container-tag.yaml @@ -2,4 +2,4 @@ # By default this file is in the docker build directory, # but the location can configured in the JJB template. --- -tag: 0.4.4 +tag: 0.4.5 diff --git a/pkg/nbi/httpgetter.go b/pkg/nbi/httpgetter.go index fca48f4..5d7b818 100644 --- a/pkg/nbi/httpgetter.go +++ b/pkg/nbi/httpgetter.go @@ -38,6 +38,7 @@ import ( "routing-manager/pkg/rtmgr" "routing-manager/pkg/sdl" "time" + "sync" ) type HttpGetter struct { @@ -77,7 +78,7 @@ func fetchAllXApps(xmurl string) (*[]rtmgr.XApp, error) { } func (g *HttpGetter) Initialize(xmurl string, nbiif string, fileName string, configfile string, - sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool) error { + sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool, m *sync.Mutex) error { return nil } diff --git a/pkg/nbi/httprestful.go b/pkg/nbi/httprestful.go index 5e90bfa..2e14690 100644 --- a/pkg/nbi/httprestful.go +++ b/pkg/nbi/httprestful.go @@ -49,6 +49,8 @@ import ( "routing-manager/pkg/sdl" "strconv" "time" + "sync" + "strings" ) //var myClient = &http.Client{Timeout: 1 * time.Second} @@ -57,8 +59,7 @@ type HttpRestful struct { Engine LaunchRest LaunchRestHandler RecvXappCallbackData RecvXappCallbackDataHandler - RecvNewE2Tdata RecvNewE2TdataHandler - + RecvNewE2Tdata RecvNewE2TdataHandler ProvideXappHandleHandlerImpl ProvideXappHandleHandlerImpl RetrieveStartupData RetrieveStartupDataHandler } @@ -104,10 +105,17 @@ func recvNewE2Tdata(dataChannel <-chan *models.E2tData) (*rtmgr.E2TInstance, err e2tData = <-dataChannel if nil != e2tData { - var e2tinst rtmgr.E2TInstance - e2tinst.Fqdn = *e2tData.E2TAddress - e2tinst.Name = "E2TERMINST" - return &e2tinst,nil + + e2tinst := rtmgr.E2TInstance { + Ranlist : make([]string, len(e2tData.RanNamelist)), + } + + e2tinst.Fqdn = *e2tData.E2TAddress + e2tinst.Name = "E2TERMINST" + copy(e2tinst.Ranlist, e2tData.RanNamelist) + + return &e2tinst,nil + } else { xapp.Logger.Info("No data") } @@ -116,9 +124,6 @@ func recvNewE2Tdata(dataChannel <-chan *models.E2tData) (*rtmgr.E2TInstance, err return nil, nil } - - - func validateXappCallbackData(callbackData *models.XappCallbackData) error { if len(callbackData.XApps) == 0 { return fmt.Errorf("invalid Data field: \"%s\"", callbackData.XApps) @@ -157,18 +162,51 @@ func validateXappSubscriptionData(data *models.XappSubscriptionData) error { } func validateE2tData(data *models.E2tData) error { - var err = fmt.Errorf("E2T E2TAddress is not proper: %v", *data.E2TAddress) -/* for _, ep := range rtmgr.Eps { - if ep.Ip == *data.Address && ep.Port == *data.Port { - err = nil - break - } - }*/ - if (*data.E2TAddress != "") { - err = nil + e2taddress_key := *data.E2TAddress + if (e2taddress_key == "") { + return fmt.Errorf("E2TAddress is empty!!!") } - return err + stringSlice := strings.Split(e2taddress_key, ":") + if (len(stringSlice) == 1) { + return fmt.Errorf("E2T E2TAddress is not a proper format like ip:port, %v", e2taddress_key ) + } + + if checkValidaE2TAddress(e2taddress_key) { + return fmt.Errorf("E2TAddress already exist!!!, E2TAddress: %v",e2taddress_key) + } + + return nil +} + +func validateDeleteE2tData(data *models.E2tDeleteData) error { + + if (*data.E2TAddress == "") { + return fmt.Errorf("E2TAddress is empty!!!") + } + + for _, element := range data.RanAssocList { + e2taddress_key := *element.E2TAddress + stringSlice := strings.Split(e2taddress_key, ":") + + if (len(stringSlice) == 1) { + return fmt.Errorf("E2T Delete - RanAssocList E2TAddress is not a proper format like ip:port, %v", e2taddress_key) + } + + + if !checkValidaE2TAddress(e2taddress_key) { + return fmt.Errorf("E2TAddress doesn't exist!!!, E2TAddress: %v",e2taddress_key) + } + + } + return nil +} + +func checkValidaE2TAddress(e2taddress string) bool { + + _, exist := rtmgr.Eps[e2taddress] + return exist + } func provideXappSubscriptionHandleImpl(subchan chan<- *models.XappSubscriptionData, @@ -224,13 +262,68 @@ func createNewE2tHandleHandlerImpl(e2taddchan chan<- *models.E2tData, xapp.Logger.Error(err.Error()) return err } - e2taddchan <- data return nil } +func validateE2TAddressRANListData(assRanE2tData models.RanE2tMap) error { + + xapp.Logger.Debug("Invoked.validateE2TAddressRANListData : %v", assRanE2tData) + + for _, element := range assRanE2tData { + if *element.E2TAddress == "" { + return fmt.Errorf("E2T Instance - E2TAddress is empty!!!") + } + + e2taddress_key := *element.E2TAddress + if !checkValidaE2TAddress(e2taddress_key) { + return fmt.Errorf("E2TAddress doesn't exist!!!, E2TAddress: %v",e2taddress_key) + } + + } + return nil +} + +func associateRanToE2THandlerImpl(assranchan chan<- models.RanE2tMap, + data models.RanE2tMap) error { + xapp.Logger.Debug("Invoked associateRanToE2THandlerImpl") + err := validateE2TAddressRANListData(data) + if err != nil { + xapp.Logger.Warn(" Association of RAN to E2T Instance data validation failed: " + err.Error()) + return err + } + assranchan <- data + return nil +} + +func disassociateRanToE2THandlerImpl(disassranchan chan<- models.RanE2tMap, + data models.RanE2tMap) error { + xapp.Logger.Debug("Invoked disassociateRanToE2THandlerImpl") + err := validateE2TAddressRANListData(data) + if err != nil { + xapp.Logger.Warn(" Disassociation of RAN List from E2T Instance data validation failed: " + err.Error()) + return err + } + disassranchan <- data + return nil +} + +func deleteE2tHandleHandlerImpl(e2tdelchan chan<- *models.E2tDeleteData, + data *models.E2tDeleteData) error { + xapp.Logger.Debug("Invoked deleteE2tHandleHandlerImpl") + + err := validateDeleteE2tData(data) + if err != nil { + xapp.Logger.Error(err.Error()) + return err + } + + e2tdelchan <- data + return nil +} + func launchRest(nbiif *string, datach chan<- *models.XappCallbackData, subchan chan<- *models.XappSubscriptionData, - subdelchan chan<- *models.XappSubscriptionData, e2taddchan chan<- *models.E2tData) { + subdelchan chan<- *models.XappSubscriptionData, e2taddchan chan<- *models.E2tData, assranchan chan<- models.RanE2tMap, disassranchan chan<- models.RanE2tMap, e2tdelchan chan<- *models.E2tDeleteData) { swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON) if err != nil { //log.Fatalln(err) @@ -297,6 +390,38 @@ func launchRest(nbiif *string, datach chan<- *models.XappCallbackData, subchan c } }) + api.HandleAssociateRanToE2tHandleHandler = handle.AssociateRanToE2tHandleHandlerFunc( + func(params handle.AssociateRanToE2tHandleParams) middleware.Responder { + err := associateRanToE2THandlerImpl(assranchan, params.RanE2tList) + if err != nil { + return handle.NewAssociateRanToE2tHandleBadRequest() + } else { + time.Sleep(1 * time.Second) + return handle.NewAssociateRanToE2tHandleCreated() + } + }) + + api.HandleDissociateRanHandler = handle.DissociateRanHandlerFunc( + func(params handle.DissociateRanParams) middleware.Responder { + err := disassociateRanToE2THandlerImpl(disassranchan, params.DissociateList) + if err != nil { + return handle.NewDissociateRanBadRequest() + } else { + time.Sleep(1 * time.Second) + return handle.NewDissociateRanCreated() + } + }) + + api.HandleDeleteE2tHandleHandler = handle.DeleteE2tHandleHandlerFunc( + func(params handle.DeleteE2tHandleParams) middleware.Responder { + err := deleteE2tHandleHandlerImpl(e2tdelchan, params.E2tData) + if err != nil { + return handle.NewDeleteE2tHandleBadRequest() + } else { + time.Sleep(1 * time.Second) + return handle.NewDeleteE2tHandleCreated() + } + }) // start to serve API xapp.Logger.Info("Starting the HTTP Rest service") if err := server.Serve(); err != nil { @@ -362,7 +487,7 @@ func retrieveStartupData(xmurl string, nbiif string, fileName string, configfile } func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, configfile string, - sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool) error { + sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool, m *sync.Mutex) error { err := r.RetrieveStartupData(xmurl, nbiif, fileName, configfile, sdlEngine) if err != nil { xapp.Logger.Error("Exiting as nbi failed to get the initial startup data from the xapp manager: " + err.Error()) @@ -373,9 +498,12 @@ func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, co subschan := make(chan *models.XappSubscriptionData, 10) subdelchan := make(chan *models.XappSubscriptionData, 10) e2taddchan := make(chan *models.E2tData, 10) + associateranchan := make(chan models.RanE2tMap, 10) + disassociateranchan := make(chan models.RanE2tMap, 10) + e2tdelchan := make(chan *models.E2tDeleteData, 10) xapp.Logger.Info("Launching Rest Http service") go func() { - r.LaunchRest(&nbiif, datach, subschan, subdelchan, e2taddchan) + r.LaunchRest(&nbiif, datach, subschan, subdelchan, e2taddchan, associateranchan, disassociateranchan, e2tdelchan) }() go func() { @@ -387,7 +515,9 @@ func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, co xapp.Logger.Debug("Fetching all xApps deployed in xApp Manager through GET operation.") alldata, err1 := httpGetXApps(xmurl) if alldata != nil && err1 == nil { + m.Lock() sdlEngine.WriteXApps(fileName, alldata) + m.Unlock() triggerSBI <- true } } @@ -416,11 +546,48 @@ func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, co for { xapp.Logger.Debug("received create New E2T data") - data, err := r.RecvNewE2Tdata(e2taddchan) - if err != nil { - xapp.Logger.Error("cannot get data from rest api dute to: " + err.Error()) - } else if data != nil { + data, _ := r.RecvNewE2Tdata(e2taddchan) + if data != nil { + m.Lock() sdlEngine.WriteNewE2TInstance(fileName, data) + m.Unlock() + triggerSBI <- true + } + } + }() + + go func() { + for { + data := <-associateranchan + xapp.Logger.Debug("received associate RAN list to E2T instance mapping from E2 Manager") + m.Lock() + sdlEngine.WriteAssRANToE2TInstance(fileName, data) + m.Unlock() + triggerSBI <- true + } + }() + + go func() { + for { + + data := <-disassociateranchan + xapp.Logger.Debug("received disassociate RANs from E2T instance") + m.Lock() + sdlEngine.WriteDisAssRANFromE2TInstance(fileName, data) + m.Unlock() + triggerSBI <- true + } + }() + + go func() { + for { + xapp.Logger.Debug("received Delete E2T data") + + data := <-e2tdelchan + if data != nil { + m.Lock() + sdlEngine.WriteDeleteE2TInstance(fileName, data) + m.Unlock() triggerSBI <- true } } diff --git a/pkg/nbi/httprestful_test.go b/pkg/nbi/httprestful_test.go index cfa644e..465f17b 100644 --- a/pkg/nbi/httprestful_test.go +++ b/pkg/nbi/httprestful_test.go @@ -44,6 +44,7 @@ import ( "routing-manager/pkg/stub" "testing" "time" + "sync" "github.com/go-openapi/swag" ) @@ -172,7 +173,8 @@ func TestHttpInstance(t *testing.T) { //ts := createMockAppmgrWithData("127.0.0.1:3000", BasicXAppLists, nil) //ts.Start() //defer ts.Close() - err = httpinstance.Initialize(XMURL, "httpgetter", "rt.json", "config.json", sdlEngine, rpeEngine, triggerSBI) + var m sync.Mutex + err = httpinstance.Initialize(XMURL, "httpgetter", "rt.json", "config.json", sdlEngine, rpeEngine, triggerSBI, &m) } func TestXappCallbackDataChannelwithdata(t *testing.T) { diff --git a/pkg/nbi/types.go b/pkg/nbi/types.go index 78f99a5..085486c 100644 --- a/pkg/nbi/types.go +++ b/pkg/nbi/types.go @@ -34,12 +34,13 @@ import ( "routing-manager/pkg/rpe" "routing-manager/pkg/rtmgr" "routing-manager/pkg/sdl" + "sync" ) type FetchAllXAppsHandler func(string) (*[]rtmgr.XApp, error) type RecvXappCallbackDataHandler func(<-chan *models.XappCallbackData) (*[]rtmgr.XApp, error) type RecvNewE2TdataHandler func(<-chan *models.E2tData) (*rtmgr.E2TInstance, error) -type LaunchRestHandler func(*string, chan<- *models.XappCallbackData, chan<- *models.XappSubscriptionData, chan<- *models.XappSubscriptionData, chan<- *models.E2tData) +type LaunchRestHandler func(*string, chan<- *models.XappCallbackData, chan<- *models.XappSubscriptionData, chan<- *models.XappSubscriptionData, chan<- *models.E2tData, chan<- models.RanE2tMap, chan<- models.RanE2tMap, chan<- *models.E2tDeleteData) type ProvideXappHandleHandlerImpl func(chan<- *models.XappCallbackData, *models.XappCallbackData) error type RetrieveStartupDataHandler func(string, string, string, string, sdl.Engine) error @@ -52,6 +53,6 @@ type EngineConfig struct { } type Engine interface { - Initialize(string, string, string, string, sdl.Engine, rpe.Engine, chan<- bool) error + Initialize(string, string, string, string, sdl.Engine, rpe.Engine, chan<- bool, *sync.Mutex) error Terminate() error } diff --git a/pkg/rpe/rmr.go b/pkg/rpe/rmr.go index 6fc8c9f..80323a3 100644 --- a/pkg/rpe/rmr.go +++ b/pkg/rpe/rmr.go @@ -34,6 +34,7 @@ import ( "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" "routing-manager/pkg/rtmgr" "strconv" + "strings" ) type Rmr struct { @@ -52,7 +53,7 @@ func NewRmrPush() *RmrPush { /* Produces the raw route message consumable by RMR */ -func (r *Rmr) generateRMRPolicies(eps rtmgr.Endpoints, key string) *[]string { +func (r *Rmr) generateRMRPolicies(eps rtmgr.Endpoints, rcs *rtmgr.RicComponents, key string) *[]string { rawrt := []string{key + "newrt|start\n"} rt := r.generateRouteTable(eps) for _, rte := range *rt { @@ -86,18 +87,31 @@ func (r *Rmr) generateRMRPolicies(eps rtmgr.Endpoints, key string) *[]string { rawrt = append(rawrt, rawrte+"\n") } rawrt = append(rawrt, key+"newrt|end\n") - count := 0 - rawrt = append(rawrt, key+"meid_map|start\n") - rawrt = append(rawrt, key+"meid_map|end|" + strconv.Itoa(count) +"\n") + meidrt := key +"meid_map|start\n" + for e2tkey, value := range rcs.E2Ts { + xapp.Logger.Debug("rmr.E2T Key: %v", e2tkey) + xapp.Logger.Debug("rmr.E2T Value: %v", value) + xapp.Logger.Debug("rmr.E2T RAN List: %v", rcs.E2Ts[e2tkey].Ranlist) + if ( len(rcs.E2Ts[e2tkey].Ranlist) != 0 ) { + ranList := strings.Join(rcs.E2Ts[e2tkey].Ranlist, " ") + meidrt += key + "mme_ar|" + e2tkey + "|" + ranList + "\n" + count++ + } else { + xapp.Logger.Debug("rmr.E2T Empty RAN LIST for FQDN: %v", e2tkey) + } + } + meidrt += key+"meid_map|end|" + strconv.Itoa(count) +"\n" + rawrt = append(rawrt, meidrt) xapp.Logger.Debug("rmr.GeneratePolicies returns: %v", rawrt) + xapp.Logger.Debug("rmr.GeneratePolicies returns: %v", rcs) return &rawrt } -func (r *RmrPush) GeneratePolicies(eps rtmgr.Endpoints) *[]string { +func (r *RmrPush) GeneratePolicies(eps rtmgr.Endpoints, rcs *rtmgr.RicComponents) *[]string { xapp.Logger.Debug("Invoked rmr.GeneratePolicies, args: %v: ", eps) - return r.generateRMRPolicies(eps, "") + return r.generateRMRPolicies(eps, rcs, "") } func (r *RmrPush) GenerateRouteTable(eps rtmgr.Endpoints) *rtmgr.RouteTable { diff --git a/pkg/rpe/rmr_test.go b/pkg/rpe/rmr_test.go index 4538d97..da8da06 100644 --- a/pkg/rpe/rmr_test.go +++ b/pkg/rpe/rmr_test.go @@ -47,11 +47,12 @@ RmrPush.GeneratePolicies() method is tested for happy path case */ func TestRmrPushGeneratePolicies(t *testing.T) { var rmrpush = RmrPush{} + var pcs rtmgr.RicComponents resetTestDataset(stub.ValidEndpoints) stub.ValidPlatformComponents = nil rtmgr.Subs = *stub.ValidSubscriptions - rawrt := rmrpush.GeneratePolicies(rtmgr.Eps) + rawrt := rmrpush.GeneratePolicies(rtmgr.Eps, &pcs) t.Log(rawrt) } diff --git a/pkg/rpe/rpe.go b/pkg/rpe/rpe.go index 9a963c7..11440db 100644 --- a/pkg/rpe/rpe.go +++ b/pkg/rpe/rpe.go @@ -163,10 +163,13 @@ func (r *Rpe) generateXappRoutes(xAppEp *rtmgr.Endpoint, e2TermEp *rtmgr.Endpoin r.addRoute("RIC_SUB_REQ", xAppEp, subManEp, routeTable, -1, "") r.addRoute("RIC_SUB_DEL_REQ", xAppEp, subManEp, routeTable, -1, "") //xApp -> E2 Termination - r.addRoute("RIC_CONTROL_REQ", xAppEp, e2TermEp, routeTable, -1, "") +// r.addRoute("RIC_CONTROL_REQ", xAppEp, e2TermEp, routeTable, -1, "") + r.addRoute("RIC_CONTROL_REQ", xAppEp, nil, routeTable, -1, "%meid") //E2 Termination -> xApp - r.addRoute("RIC_CONTROL_ACK", e2TermEp, xAppEp, routeTable, -1, "") - r.addRoute("RIC_CONTROL_FAILURE", e2TermEp, xAppEp, routeTable, -1, "") +/// r.addRoute("RIC_CONTROL_ACK", e2TermEp, xAppEp, routeTable, -1, "") +/// r.addRoute("RIC_CONTROL_FAILURE", e2TermEp, xAppEp, routeTable, -1, "") + r.addRoute("RIC_CONTROL_ACK", nil, xAppEp, routeTable, -1, "") + r.addRoute("RIC_CONTROL_FAILURE", nil, xAppEp, routeTable, -1, "") } //xApp->A1Mediator if xAppEp.XAppType != sbi.PlatformType && len(xAppEp.Policies) > 0 { diff --git a/pkg/rpe/types.go b/pkg/rpe/types.go index 626213e..4a5b9fc 100644 --- a/pkg/rpe/types.go +++ b/pkg/rpe/types.go @@ -43,6 +43,6 @@ type EngineConfig struct { } type Engine interface { - GeneratePolicies(rtmgr.Endpoints) *[]string + GeneratePolicies(rtmgr.Endpoints, *rtmgr.RicComponents) *[]string GenerateRouteTable(rtmgr.Endpoints) *rtmgr.RouteTable } diff --git a/pkg/sdl/file.go b/pkg/sdl/file.go index b4f1e8e..969f7bd 100644 --- a/pkg/sdl/file.go +++ b/pkg/sdl/file.go @@ -35,6 +35,7 @@ import ( "io/ioutil" "os" "routing-manager/pkg/rtmgr" + "routing-manager/pkg/models" ) /* @@ -60,11 +61,11 @@ func (f *File) ReadAll(file string) (*rtmgr.RicComponents, error) { return nil, errors.New("cannot open the file due to: " + err.Error()) } defer jsonFile.Close() - byteValue, err := ioutil.ReadAll(jsonFile) if err != nil { return nil, errors.New("cannot read the file due to: " + err.Error()) } + err = json.Unmarshal(byteValue, &rcs) if err != nil { return nil, errors.New("cannot parse data due to: " + err.Error()) @@ -133,3 +134,127 @@ func (f *File) WriteNewE2TInstance(file string, E2TInst *rtmgr.E2TInstance) erro } return nil } + +func (f *File) WriteAssRANToE2TInstance(file string, rane2tmap models.RanE2tMap) error { + xapp.Logger.Debug("Invoked sdl.WriteAssRANToE2TInstance") + xapp.Logger.Debug("file.WriteAssRANToE2TInstance writes into file: " + file) + xapp.Logger.Debug("file.WriteAssRANToE2TInstance writes data: %v", rane2tmap) + + ricData, err := NewFile().ReadAll(file) + if err != nil { + xapp.Logger.Error("cannot get data from sdl interface due to: " + err.Error()) + return errors.New("cannot read full ric data to modify xApps data, due to: " + err.Error()) + } + for _, element := range rane2tmap { + xapp.Logger.Info("data received") + for key, _ := range ricData.E2Ts { + if key == *element.E2TAddress { + var estObj rtmgr.E2TInstance + estObj = ricData.E2Ts[key] + estObj.Ranlist = append(ricData.E2Ts[key].Ranlist, element.RanNamelist...) + ricData.E2Ts[key]= estObj + } + } + } + + byteValue, err := json.Marshal(ricData) + if err != nil { + return errors.New("cannot convert data due to: " + err.Error()) + } + err = ioutil.WriteFile(file, byteValue, 0644) + if err != nil { + return errors.New("cannot write file due to: " + err.Error()) + } + return nil +} + +func (f *File) WriteDisAssRANFromE2TInstance(file string, disassranmap models.RanE2tMap) error { + xapp.Logger.Debug("Invoked sdl.WriteDisAssRANFromE2TInstance") + xapp.Logger.Debug("file.WriteDisAssRANFromE2TInstance writes into file: " + file) + xapp.Logger.Debug("file.WriteDisAssRANFromE2TInstance writes data: %v", disassranmap) + + ricData, err := NewFile().ReadAll(file) + if err != nil { + xapp.Logger.Error("cannot get data from sdl interface due to: " + err.Error()) + return errors.New("cannot read full ric data to modify xApps data, due to: " + err.Error()) + } + for _, element := range disassranmap { + xapp.Logger.Info("data received") + e2taddress_key := *element.E2TAddress + //Check whether the provided E2T Address is available in SDL as a key. + //If exist, proceed further to check RAN list, Otherwise move to next E2T Instance + if _, exist := ricData.E2Ts[e2taddress_key]; exist { + var estObj rtmgr.E2TInstance + estObj = ricData.E2Ts[e2taddress_key] + // If RAN list is empty, then routing manager assumes that all RANs attached associated to the particular E2T Instance to be removed. + if len(element.RanNamelist) == 0 { + xapp.Logger.Debug("RAN List is empty. So disassociating all RANs from the E2T Instance: %v ", *element.E2TAddress) + estObj.Ranlist = []string{} + } else { + xapp.Logger.Debug("Remove only selected rans from E2T Instance: %v and %v ", ricData.E2Ts[e2taddress_key].Ranlist, element.RanNamelist) + for _, disRanValue := range element.RanNamelist { + for ranIndex, ranValue := range ricData.E2Ts[e2taddress_key].Ranlist { + if disRanValue == ranValue { + estObj.Ranlist[ranIndex] = estObj.Ranlist[len(estObj.Ranlist)-1] + estObj.Ranlist[len(estObj.Ranlist)-1] = "" + estObj.Ranlist = estObj.Ranlist[:len(estObj.Ranlist)-1] + } + } + } + } + ricData.E2Ts[e2taddress_key]= estObj + } + } + + xapp.Logger.Debug("Final data after disassociate: %v", ricData) + + byteValue, err := json.Marshal(ricData) + if err != nil { + return errors.New("cannot convert data due to: " + err.Error()) + } + err = ioutil.WriteFile(file, byteValue, 0644) + if err != nil { + return errors.New("cannot write file due to: " + err.Error()) + } + return nil +} + +func (f *File) WriteDeleteE2TInstance(file string, E2TInst *models.E2tDeleteData) error { + xapp.Logger.Debug("Invoked sdl.WriteDeleteE2TInstance") + xapp.Logger.Debug("file.WriteDeleteE2TInstance writes into file: " + file) + xapp.Logger.Debug("file.WriteDeleteE2TInstance writes data: %v", *E2TInst) + + ricData, err := NewFile().ReadAll(file) + if err != nil { + xapp.Logger.Error("cannot get data from sdl interface due to: " + err.Error()) + return errors.New("cannot read full ric data to modify xApps data, due to: " + err.Error()) + } + + delete(ricData.E2Ts, *E2TInst.E2TAddress) + + + for _, element := range E2TInst.RanAssocList { + xapp.Logger.Info("data received") + key := *element.E2TAddress + + if val, ok := ricData.E2Ts[key]; ok { + var estObj rtmgr.E2TInstance + estObj = val + estObj.Ranlist = append(ricData.E2Ts[key].Ranlist, element.RanNamelist...) + ricData.E2Ts[key]= estObj + } else { + xapp.Logger.Error("file.WriteDeleteE2TInstance E2T instance is not found for provided E2TAddress : %v", errors.New(key).Error()) + } + + } + + byteValue, err := json.Marshal(ricData) + if err != nil { + return errors.New("cannot convert data due to: " + err.Error()) + } + err = ioutil.WriteFile(file, byteValue, 0644) + if err != nil { + return errors.New("cannot write file due to: " + err.Error()) + } + return nil +} diff --git a/pkg/sdl/types.go b/pkg/sdl/types.go index f94557e..f4a9125 100644 --- a/pkg/sdl/types.go +++ b/pkg/sdl/types.go @@ -28,6 +28,7 @@ package sdl import "routing-manager/pkg/rtmgr" +import "routing-manager/pkg/models" //type readAll func(string) (*rtmgr.RicComponents, error) //type writeAll func(string, *rtmgr.RicComponents) error @@ -45,4 +46,7 @@ type Engine interface { WriteAll(string, *rtmgr.RicComponents) error WriteXApps(string, *[]rtmgr.XApp) error WriteNewE2TInstance(string, *rtmgr.E2TInstance) error + WriteAssRANToE2TInstance(string, models.RanE2tMap) error + WriteDisAssRANFromE2TInstance(string, models.RanE2tMap) error + WriteDeleteE2TInstance(string, *models.E2tDeleteData) error }