Reverted subscription list retreival durng rtmgr startup
[ric-plt/rtmgr.git] / pkg / nbi / httprestful.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17
18
19    This source code is part of the near-RT RIC (RAN Intelligent Controller)
20    platform project (RICP).
21
22 ==================================================================================
23 */
24 /*
25   Mnemonic:     httprestful.go
26   Abstract:     HTTP Restful API NBI implementation
27                 Based on Swagger generated code
28   Date:         25 March 2019
29 */
30
31 package nbi
32
33 //noinspection GoUnresolvedReference,GoUnresolvedReference,GoUnresolvedReference,GoUnresolvedReference,GoUnresolvedReference,GoUnresolvedReference
34 import (
35         "encoding/json"
36         "errors"
37         "fmt"
38         xfmodel "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
39         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
40         "github.com/go-openapi/loads"
41         "github.com/go-openapi/runtime/middleware"
42         "net"
43         "net/url"
44         "os"
45         "routing-manager/pkg/models"
46         "routing-manager/pkg/restapi"
47         "routing-manager/pkg/restapi/operations"
48         "routing-manager/pkg/restapi/operations/debug"
49         "routing-manager/pkg/restapi/operations/handle"
50         "routing-manager/pkg/rpe"
51         "routing-manager/pkg/rtmgr"
52         "routing-manager/pkg/sdl"
53         "strconv"
54         "strings"
55         "sync"
56         "time"
57 )
58
59 //var myClient = &http.Client{Timeout: 1 * time.Second}
60
61 type HttpRestful struct {
62         Engine
63         LaunchRest                   LaunchRestHandler
64         RecvXappCallbackData         RecvXappCallbackDataHandler
65         RecvNewE2Tdata               RecvNewE2TdataHandler
66         ProvideXappHandleHandlerImpl ProvideXappHandleHandlerImpl
67         RetrieveStartupData          RetrieveStartupDataHandler
68 }
69
70 func NewHttpRestful() *HttpRestful {
71         instance := new(HttpRestful)
72         instance.LaunchRest = launchRest
73         instance.RecvXappCallbackData = recvXappCallbackData
74         instance.RecvNewE2Tdata = recvNewE2Tdata
75         instance.ProvideXappHandleHandlerImpl = provideXappHandleHandlerImpl
76         instance.RetrieveStartupData = retrieveStartupData
77         return instance
78 }
79
80 // ToDo: Use Range over channel. Read and return only the latest one.
81 func recvXappCallbackData(dataChannel <-chan *models.XappCallbackData) (*[]rtmgr.XApp, error) {
82         var xappData *models.XappCallbackData
83         // Drain the channel as we are only looking for the latest value until
84         // xapp manager sends all xapp data with every request.
85         length := len(dataChannel)
86         //xapp.Logger.Info(length)
87         for i := 0; i <= length; i++ {
88                 xapp.Logger.Info("data received")
89                 // If no data received from the REST, it blocks.
90                 xappData = <-dataChannel
91         }
92         if nil != xappData {
93                 var xapps []rtmgr.XApp
94                 err := json.Unmarshal([]byte(xappData.XApps), &xapps)
95                 return &xapps, err
96         } else {
97                 xapp.Logger.Info("No data")
98         }
99
100         xapp.Logger.Debug("Nothing received on the Http interface")
101         return nil, nil
102 }
103
104 func recvNewE2Tdata(dataChannel <-chan *models.E2tData) (*rtmgr.E2TInstance, string, error) {
105         var e2tData *models.E2tData
106         var str string
107         xapp.Logger.Info("data received")
108
109         e2tData = <-dataChannel
110
111         if nil != e2tData {
112
113                 e2tinst := rtmgr.E2TInstance{
114                         Ranlist: make([]string, len(e2tData.RanNamelist)),
115                 }
116
117                 e2tinst.Fqdn = *e2tData.E2TAddress
118                 e2tinst.Name = "E2TERMINST"
119                 copy(e2tinst.Ranlist, e2tData.RanNamelist)
120                 if len(e2tData.RanNamelist) > 0 {
121                         var meidar string
122                         for _, meid := range e2tData.RanNamelist {
123                                 meidar += meid + " "
124                         }
125                         str = "mme_ar|" + *e2tData.E2TAddress + "|" + strings.TrimSuffix(meidar, " ")
126                 }
127                 return &e2tinst, str, nil
128
129         } else {
130                 xapp.Logger.Info("No data")
131         }
132
133         xapp.Logger.Debug("Nothing received on the Http interface")
134         return nil, str, nil
135 }
136
137 func validateXappCallbackData(callbackData *models.XappCallbackData) error {
138         if len(callbackData.XApps) == 0 {
139                 return fmt.Errorf("invalid Data field: \"%s\"", callbackData.XApps)
140         }
141         var xapps []rtmgr.XApp
142         err := json.Unmarshal([]byte(callbackData.XApps), &xapps)
143         if err != nil {
144                 return fmt.Errorf("unmarshal failed: \"%s\"", err.Error())
145         }
146         return nil
147 }
148
149 func provideXappHandleHandlerImpl(datach chan<- *models.XappCallbackData, data *models.XappCallbackData) error {
150         if data != nil {
151                 xapp.Logger.Debug("Received callback data")
152         }
153         err := validateXappCallbackData(data)
154         if err != nil {
155                 xapp.Logger.Warn("XApp callback data validation failed: " + err.Error())
156                 return err
157         } else {
158                 datach <- data
159                 return nil
160         }
161 }
162
163 func validateXappSubscriptionData(data *models.XappSubscriptionData) error {
164         var err = fmt.Errorf("XApp instance not found: %v:%v", *data.Address, *data.Port)
165         for _, ep := range rtmgr.Eps {
166                 if ep.Ip == *data.Address && ep.Port == *data.Port {
167                         err = nil
168                         break
169                 }
170         }
171         return err
172 }
173
174 func validateE2tData(data *models.E2tData) error {
175
176         e2taddress_key := *data.E2TAddress
177         if e2taddress_key == "" {
178                 return fmt.Errorf("E2TAddress is empty!!!")
179         }
180         stringSlice := strings.Split(e2taddress_key, ":")
181         if len(stringSlice) == 1 {
182                 return fmt.Errorf("E2T E2TAddress is not a proper format like ip:port, %v", e2taddress_key)
183         }
184
185         _, err := net.LookupIP(stringSlice[0])
186         if err != nil {
187                 return fmt.Errorf("E2T E2TAddress DNS look up failed, E2TAddress: %v", stringSlice[0])
188         }
189
190         if checkValidaE2TAddress(e2taddress_key) {
191                 return fmt.Errorf("E2TAddress already exist!!!, E2TAddress: %v", e2taddress_key)
192         }
193
194         return nil
195 }
196
197 func validateDeleteE2tData(data *models.E2tDeleteData) error {
198
199         if *data.E2TAddress == "" {
200                 return fmt.Errorf("E2TAddress is empty!!!")
201         }
202
203         for _, element := range data.RanAssocList {
204                 e2taddress_key := *element.E2TAddress
205                 stringSlice := strings.Split(e2taddress_key, ":")
206
207                 if len(stringSlice) == 1 {
208                         return fmt.Errorf("E2T Delete - RanAssocList E2TAddress is not a proper format like ip:port, %v", e2taddress_key)
209                 }
210
211                 if !checkValidaE2TAddress(e2taddress_key) {
212                         return fmt.Errorf("E2TAddress doesn't exist!!!, E2TAddress: %v", e2taddress_key)
213                 }
214
215         }
216         return nil
217 }
218
219 func checkValidaE2TAddress(e2taddress string) bool {
220
221         _, exist := rtmgr.Eps[e2taddress]
222         return exist
223
224 }
225
226 func provideXappSubscriptionHandleImpl(subchan chan<- *models.XappSubscriptionData,
227         data *models.XappSubscriptionData) error {
228         xapp.Logger.Debug("Invoked provideXappSubscriptionHandleImpl")
229         err := validateXappSubscriptionData(data)
230         if err != nil {
231                 xapp.Logger.Error(err.Error())
232                 return err
233         }
234         subchan <- data
235         //var val = string(*data.Address + ":" + strconv.Itoa(int(*data.Port)))
236         xapp.Logger.Debug("Endpoints: %v", rtmgr.Eps)
237         return nil
238 }
239
240 func subscriptionExists(data *models.XappSubscriptionData) bool {
241         present := false
242         sub := rtmgr.Subscription{SubID: *data.SubscriptionID, Fqdn: *data.Address, Port: *data.Port}
243         for _, elem := range rtmgr.Subs {
244                 if elem == sub {
245                         present = true
246                         break
247                 }
248         }
249         return present
250 }
251
252 func deleteXappSubscriptionHandleImpl(subdelchan chan<- *models.XappSubscriptionData,
253         data *models.XappSubscriptionData) error {
254         xapp.Logger.Debug("Invoked deleteXappSubscriptionHandleImpl")
255         err := validateXappSubscriptionData(data)
256         if err != nil {
257                 xapp.Logger.Error(err.Error())
258                 return err
259         }
260
261         if !subscriptionExists(data) {
262                 xapp.Logger.Warn("subscription not found: %d", *data.SubscriptionID)
263                 err := fmt.Errorf("subscription not found: %d", *data.SubscriptionID)
264                 return err
265         }
266
267         subdelchan <- data
268         return nil
269 }
270
271 func updateXappSubscriptionHandleImpl(subupdatechan chan<- *rtmgr.XappList, data *models.XappList, subid uint16) error {
272         xapp.Logger.Debug("Invoked updateXappSubscriptionHandleImpl")
273
274         var fqdnlist []rtmgr.FqDn
275         for _, item := range *data {
276                 fqdnlist = append(fqdnlist, rtmgr.FqDn(*item))
277         }
278         xapplist := rtmgr.XappList{SubscriptionID: subid, FqdnList: fqdnlist}
279         var subdata models.XappSubscriptionData
280         var id int32
281         id = int32(subid)
282         subdata.SubscriptionID = &id
283         for _, items := range fqdnlist {
284                 subdata.Address = items.Address
285                 subdata.Port = items.Port
286                 err := validateXappSubscriptionData(&subdata)
287                 if err != nil {
288                         xapp.Logger.Error(err.Error())
289                         return err
290                 }
291         }
292         subupdatechan <- &xapplist
293         return nil
294 }
295
296 func createNewE2tHandleHandlerImpl(e2taddchan chan<- *models.E2tData,
297         data *models.E2tData) error {
298         xapp.Logger.Debug("Invoked createNewE2tHandleHandlerImpl")
299         err := validateE2tData(data)
300         if err != nil {
301                 xapp.Logger.Error(err.Error())
302                 return err
303         }
304         e2taddchan <- data
305         return nil
306 }
307
308 func validateE2TAddressRANListData(assRanE2tData models.RanE2tMap) error {
309
310         xapp.Logger.Debug("Invoked.validateE2TAddressRANListData : %v", assRanE2tData)
311
312         for _, element := range assRanE2tData {
313                 if *element.E2TAddress == "" {
314                         return fmt.Errorf("E2T Instance - E2TAddress is empty!!!")
315                 }
316
317                 e2taddress_key := *element.E2TAddress
318                 if !checkValidaE2TAddress(e2taddress_key) {
319                         return fmt.Errorf("E2TAddress doesn't exist!!!, E2TAddress: %v", e2taddress_key)
320                 }
321
322         }
323         return nil
324 }
325
326 func associateRanToE2THandlerImpl(assranchan chan<- models.RanE2tMap,
327         data models.RanE2tMap) error {
328         xapp.Logger.Debug("Invoked associateRanToE2THandlerImpl")
329         err := validateE2TAddressRANListData(data)
330         if err != nil {
331                 xapp.Logger.Warn(" Association of RAN to E2T Instance data validation failed: " + err.Error())
332                 return err
333         }
334         assranchan <- data
335         return nil
336 }
337
338 func disassociateRanToE2THandlerImpl(disassranchan chan<- models.RanE2tMap,
339         data models.RanE2tMap) error {
340         xapp.Logger.Debug("Invoked disassociateRanToE2THandlerImpl")
341         err := validateE2TAddressRANListData(data)
342         if err != nil {
343                 xapp.Logger.Warn(" Disassociation of RAN List from E2T Instance data validation failed: " + err.Error())
344                 return err
345         }
346         disassranchan <- data
347         return nil
348 }
349
350 func deleteE2tHandleHandlerImpl(e2tdelchan chan<- *models.E2tDeleteData,
351         data *models.E2tDeleteData) error {
352         xapp.Logger.Debug("Invoked deleteE2tHandleHandlerImpl")
353
354         err := validateDeleteE2tData(data)
355         if err != nil {
356                 xapp.Logger.Error(err.Error())
357                 return err
358         }
359
360         e2tdelchan <- data
361         return nil
362 }
363
364 func dumpDebugData() (models.Debuginfo, error) {
365         var response models.Debuginfo
366         sdlEngine, _ := sdl.GetSdl("file")
367         rpeEngine, _ := rpe.GetRpe("rmrpush")
368         data, err := sdlEngine.ReadAll(xapp.Config.GetString("rtfile"))
369         if err != nil || data == nil {
370                 xapp.Logger.Error("Cannot get data from sdl interface due to: " + err.Error())
371                 return response, err
372         }
373         response.RouteTable = *rpeEngine.GeneratePolicies(rtmgr.Eps, data)
374
375         prettyJSON, err := json.MarshalIndent(data, "", "")
376         response.RouteConfigs = string(prettyJSON)
377
378         return response, err
379 }
380
381 func launchRest(nbiif *string, datach chan<- *models.XappCallbackData, subchan chan<- *models.XappSubscriptionData, subupdatechan chan<- *rtmgr.XappList,
382         subdelchan chan<- *models.XappSubscriptionData, e2taddchan chan<- *models.E2tData, assranchan chan<- models.RanE2tMap, disassranchan chan<- models.RanE2tMap, e2tdelchan chan<- *models.E2tDeleteData) {
383         swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON)
384         if err != nil {
385                 //log.Fatalln(err)
386                 xapp.Logger.Error(err.Error())
387                 os.Exit(1)
388         }
389         nbiUrl, err := url.Parse(*nbiif)
390         if err != nil {
391                 xapp.Logger.Error(err.Error())
392                 os.Exit(1)
393         }
394         api := operations.NewRoutingManagerAPI(swaggerSpec)
395         server := restapi.NewServer(api)
396         defer server.Shutdown()
397
398         server.Port, err = strconv.Atoi(nbiUrl.Port())
399         if err != nil {
400                 xapp.Logger.Error("Invalid NBI RestAPI port")
401                 os.Exit(1)
402         }
403         server.Host = "0.0.0.0"
404         // set handlers
405         api.HandleProvideXappHandleHandler = handle.ProvideXappHandleHandlerFunc(
406                 func(params handle.ProvideXappHandleParams) middleware.Responder {
407                         xapp.Logger.Info("Data received on Http interface")
408                         err := provideXappHandleHandlerImpl(datach, params.XappCallbackData)
409                         if err != nil {
410                                 xapp.Logger.Error("Invalid XApp callback data: " + err.Error())
411                                 return handle.NewProvideXappHandleBadRequest()
412                         } else {
413                                 return handle.NewGetHandlesOK()
414                         }
415                 })
416         api.HandleProvideXappSubscriptionHandleHandler = handle.ProvideXappSubscriptionHandleHandlerFunc(
417                 func(params handle.ProvideXappSubscriptionHandleParams) middleware.Responder {
418                         err := provideXappSubscriptionHandleImpl(subchan, params.XappSubscriptionData)
419                         if err != nil {
420                                 return handle.NewProvideXappSubscriptionHandleBadRequest()
421                         } else {
422                                 //Delay the reponse as add subscription channel needs to update sdl and then sbi sends updated routes to all endpoints
423                                 time.Sleep(1 * time.Second)
424                                 return handle.NewGetHandlesOK()
425                         }
426                 })
427         api.HandleDeleteXappSubscriptionHandleHandler = handle.DeleteXappSubscriptionHandleHandlerFunc(
428                 func(params handle.DeleteXappSubscriptionHandleParams) middleware.Responder {
429                         err := deleteXappSubscriptionHandleImpl(subdelchan, params.XappSubscriptionData)
430                         if err != nil {
431                                 return handle.NewDeleteXappSubscriptionHandleNoContent()
432                         } else {
433                                 //Delay the reponse as delete subscription channel needs to update sdl and then sbi sends updated routes to all endpoints
434                                 time.Sleep(1 * time.Second)
435                                 return handle.NewGetHandlesOK()
436                         }
437                 })
438         api.HandleUpdateXappSubscriptionHandleHandler = handle.UpdateXappSubscriptionHandleHandlerFunc(
439                 func(params handle.UpdateXappSubscriptionHandleParams) middleware.Responder {
440                         err := updateXappSubscriptionHandleImpl(subupdatechan, &params.XappList, params.SubscriptionID)
441                         if err != nil {
442                                 return handle.NewUpdateXappSubscriptionHandleBadRequest()
443                         } else {
444                                 //Delay the reponse as delete subscription channel needs to update sdl and then sbi sends updated routes to all endpoints
445                                 time.Sleep(1 * time.Second)
446                                 return handle.NewUpdateXappSubscriptionHandleCreated()
447                         }
448                 })
449         api.HandleCreateNewE2tHandleHandler = handle.CreateNewE2tHandleHandlerFunc(
450                 func(params handle.CreateNewE2tHandleParams) middleware.Responder {
451                         err := createNewE2tHandleHandlerImpl(e2taddchan, params.E2tData)
452                         if err != nil {
453                                 return handle.NewCreateNewE2tHandleBadRequest()
454                         } else {
455                                 time.Sleep(1 * time.Second)
456                                 return handle.NewCreateNewE2tHandleCreated()
457                         }
458                 })
459
460         api.HandleAssociateRanToE2tHandleHandler = handle.AssociateRanToE2tHandleHandlerFunc(
461                 func(params handle.AssociateRanToE2tHandleParams) middleware.Responder {
462                         err := associateRanToE2THandlerImpl(assranchan, params.RanE2tList)
463                         if err != nil {
464                                 return handle.NewAssociateRanToE2tHandleBadRequest()
465                         } else {
466                                 time.Sleep(1 * time.Second)
467                                 return handle.NewAssociateRanToE2tHandleCreated()
468                         }
469                 })
470
471         api.HandleDissociateRanHandler = handle.DissociateRanHandlerFunc(
472                 func(params handle.DissociateRanParams) middleware.Responder {
473                         err := disassociateRanToE2THandlerImpl(disassranchan, params.DissociateList)
474                         if err != nil {
475                                 return handle.NewDissociateRanBadRequest()
476                         } else {
477                                 time.Sleep(1 * time.Second)
478                                 return handle.NewDissociateRanCreated()
479                         }
480                 })
481
482         api.HandleDeleteE2tHandleHandler = handle.DeleteE2tHandleHandlerFunc(
483                 func(params handle.DeleteE2tHandleParams) middleware.Responder {
484                         err := deleteE2tHandleHandlerImpl(e2tdelchan, params.E2tData)
485                         if err != nil {
486                                 return handle.NewDeleteE2tHandleBadRequest()
487                         } else {
488                                 time.Sleep(1 * time.Second)
489                                 return handle.NewDeleteE2tHandleCreated()
490                         }
491                 })
492         api.DebugGetDebuginfoHandler = debug.GetDebuginfoHandlerFunc(
493                 func(params debug.GetDebuginfoParams) middleware.Responder {
494                         response, err := dumpDebugData()
495                         if err != nil {
496                                 return debug.NewGetDebuginfoCreated()
497                         } else {
498                                 return debug.NewGetDebuginfoOK().WithPayload(&response)
499                         }
500                 })
501         // start to serve API
502         xapp.Logger.Info("Starting the HTTP Rest service")
503         if err := server.Serve(); err != nil {
504                 xapp.Logger.Error(err.Error())
505         }
506 }
507
508 func httpGetXApps(xmurl string) (*[]rtmgr.XApp, error) {
509         xapp.Logger.Info("Invoked httprestful.httpGetXApps: " + xmurl)
510         r, err := myClient.Get(xmurl)
511         if err != nil {
512                 return nil, err
513         }
514         defer r.Body.Close()
515
516         if r.StatusCode == 200 {
517                 xapp.Logger.Debug("http client raw response: %v", r)
518                 var xapps []rtmgr.XApp
519                 err = json.NewDecoder(r.Body).Decode(&xapps)
520                 if err != nil {
521                         xapp.Logger.Warn("Json decode failed: " + err.Error())
522                 }
523                 xapp.Logger.Info("HTTP GET: OK")
524                 xapp.Logger.Debug("httprestful.httpGetXApps returns: %v", xapps)
525                 return &xapps, err
526         }
527         xapp.Logger.Warn("httprestful got an unexpected http status code: %v", r.StatusCode)
528         return nil, nil
529 }
530
531 func httpGetE2TList(e2murl string) (*[]rtmgr.E2tIdentity, error) {
532         xapp.Logger.Info("Invoked httprestful.httpGetE2TList: " + e2murl)
533         r, err := myClient.Get(e2murl)
534         if err != nil {
535                 return nil, err
536         }
537         defer r.Body.Close()
538
539         if r.StatusCode == 200 {
540                 xapp.Logger.Debug("http client raw response: %v", r)
541                 var E2Tlist []rtmgr.E2tIdentity
542                 err = json.NewDecoder(r.Body).Decode(&E2Tlist)
543                 if err != nil {
544                         xapp.Logger.Warn("Json decode failed: " + err.Error())
545                 }
546                 xapp.Logger.Info("HTTP GET: OK")
547                 xapp.Logger.Debug("httprestful.httpGetXApps returns: %v", E2Tlist)
548                 return &E2Tlist, err
549         }
550         xapp.Logger.Warn("httprestful got an unexpected http status code: %v", r.StatusCode)
551         return nil, nil
552 }
553
554 func PopulateE2TMap(e2tDataList *[]rtmgr.E2tIdentity, e2ts map[string]rtmgr.E2TInstance, meids []string) {
555         xapp.Logger.Info("Invoked httprestful.PopulateE2TMap ")
556
557         for _, e2tData := range *e2tDataList {
558                 var str string
559
560                 e2tinst := rtmgr.E2TInstance{
561                         Ranlist: make([]string, len(e2tData.Rannames)),
562                 }
563
564                 e2tinst.Fqdn = e2tData.E2taddress
565                 e2tinst.Name = "E2TERMINST"
566                 copy(e2tinst.Ranlist, e2tData.Rannames)
567
568                 if len(e2tData.Rannames) > 0 {
569                         var meidar string
570                         for _, meid := range e2tData.Rannames {
571                                 meidar += meid + " "
572                         }
573                         str += "mme_ar|" + e2tData.E2taddress + "|" + strings.TrimSuffix(meidar, " ")
574                 }
575
576                 e2ts[e2tinst.Fqdn] = e2tinst
577                 meids = append(meids, str)
578         }
579 }
580
581 func retrieveStartupData(xmurl string, nbiif string, fileName string, configfile string, e2murl string, sdlEngine sdl.Engine) error {
582         xapp.Logger.Info("Invoked retrieveStartupData ")
583         var readErr error
584         var err error
585         var maxRetries = 10
586         var xappData *[]rtmgr.XApp
587         xappData = new([]rtmgr.XApp)
588         xapp.Logger.Info("Trying to fetch XApps data from XAPP manager")
589         for i := 1; i <= maxRetries; i++ {
590                 time.Sleep(2 * time.Second)
591
592                 readErr = nil
593                 xappData, err = httpGetXApps(xmurl)
594                 if xappData != nil && err == nil {
595                         break
596                 } else if err == nil {
597                         readErr = errors.New("unexpected HTTP status code")
598                 } else {
599                         xapp.Logger.Warn("cannot get xapp data due to: " + err.Error())
600                         readErr = err
601                 }
602         }
603
604         if readErr != nil {
605                 return readErr
606         }
607
608         var meids []string
609         e2ts := make(map[string]rtmgr.E2TInstance)
610         xapp.Logger.Info("Trying to fetch E2T data from E2manager")
611         for i := 1; i <= maxRetries; i++ {
612
613                 readErr = nil
614                 e2tDataList, err := httpGetE2TList(e2murl)
615                 if e2tDataList != nil && err == nil {
616                         PopulateE2TMap(e2tDataList, e2ts, meids[:])
617                         break
618                 } else if err == nil {
619                         readErr = errors.New("unexpected HTTP status code")
620                 } else {
621                         xapp.Logger.Warn("cannot get E2T data from E2M due to: " + err.Error())
622                         readErr = err
623                 }
624                 time.Sleep(2 * time.Second)
625         }
626
627         if readErr != nil {
628                 return readErr
629         }
630
631         pcData, confErr := rtmgr.GetPlatformComponents(configfile)
632         if confErr != nil {
633                 xapp.Logger.Error(confErr.Error())
634                 return confErr
635         }
636         xapp.Logger.Info("Recieved intial xapp data, E2T data and platform data, writing into SDL.")
637         // Combine the xapps data and platform data before writing to the SDL
638         ricData := &rtmgr.RicComponents{XApps: *xappData, Pcs: *pcData, E2Ts: e2ts, MeidMap: meids}
639         writeErr := sdlEngine.WriteAll(fileName, ricData)
640         if writeErr != nil {
641                 xapp.Logger.Error(writeErr.Error())
642         }
643
644         xapp.Logger.Info("Trying to fetch Subscriptions data from Subscription manager")
645         /*for i := 1; i <= maxRetries; i++ {
646                         readErr = nil
647                         sub_list, err := xapp.Subscription.QuerySubscriptions()
648
649                         if sub_list != nil && err == nil {
650                                 PopulateSubscription(sub_list)
651                                 break
652                         } else {
653                                 readErr = err
654                                 xapp.Logger.Warn("cannot get xapp data due to: " + readErr.Error())
655                 }
656                         time.Sleep(2 * time.Second)
657                 }
658
659         if readErr != nil {
660                 return readErr
661         }*/
662
663         // post subscription req to appmgr
664         readErr = PostSubReq(xmurl, nbiif)
665         if readErr == nil {
666                 return nil
667         }
668
669         return readErr
670 }
671
672 func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, configfile string, e2murl string,
673         sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool, m *sync.Mutex) error {
674         err := r.RetrieveStartupData(xmurl, nbiif, fileName, configfile, e2murl, sdlEngine)
675         if err != nil {
676                 xapp.Logger.Error("Exiting as nbi failed to get the initial startup data from the xapp manager: " + err.Error())
677                 return err
678         }
679
680         datach := make(chan *models.XappCallbackData, 10)
681         subschan := make(chan *models.XappSubscriptionData, 10)
682         subdelchan := make(chan *models.XappSubscriptionData, 10)
683         subupdatechan := make(chan *rtmgr.XappList, 10)
684         e2taddchan := make(chan *models.E2tData, 10)
685         associateranchan := make(chan models.RanE2tMap, 10)
686         disassociateranchan := make(chan models.RanE2tMap, 10)
687         e2tdelchan := make(chan *models.E2tDeleteData, 10)
688         xapp.Logger.Info("Launching Rest Http service")
689         go func() {
690                 r.LaunchRest(&nbiif, datach, subschan, subupdatechan, subdelchan, e2taddchan, associateranchan, disassociateranchan, e2tdelchan)
691         }()
692
693         go func() {
694                 for {
695                         data, err := r.RecvXappCallbackData(datach)
696                         if err != nil {
697                                 xapp.Logger.Error("cannot get data from rest api dute to: " + err.Error())
698                         } else if data != nil {
699                                 xapp.Logger.Debug("Fetching all xApps deployed in xApp Manager through GET operation.")
700                                 alldata, err1 := httpGetXApps(xmurl)
701                                 if alldata != nil && err1 == nil {
702                                         m.Lock()
703                                         sdlEngine.WriteXApps(fileName, alldata)
704                                         m.Unlock()
705                                         triggerSBI <- true
706                                 }
707                         }
708                 }
709         }()
710
711         go func() {
712                 for {
713                         data := <-subschan
714                         xapp.Logger.Debug("received XApp subscription data")
715                         addSubscription(&rtmgr.Subs, data)
716                         triggerSBI <- true
717                 }
718         }()
719
720         go func() {
721                 for {
722                         data := <-subdelchan
723                         xapp.Logger.Debug("received XApp subscription delete data")
724                         delSubscription(&rtmgr.Subs, data)
725                         triggerSBI <- true
726                 }
727         }()
728
729         go func() {
730                 for {
731                         data := <-subupdatechan
732                         xapp.Logger.Debug("received XApp subscription Merge data")
733                         updateSubscription(data)
734                         triggerSBI <- true
735                 }
736         }()
737
738         go func() {
739                 for {
740
741                         data, meiddata, _ := r.RecvNewE2Tdata(e2taddchan)
742                         if data != nil {
743                                 xapp.Logger.Debug("received create New E2T data")
744                                 m.Lock()
745                                 sdlEngine.WriteNewE2TInstance(fileName, data, meiddata)
746                                 m.Unlock()
747                                 triggerSBI <- true
748                         }
749                 }
750         }()
751
752         go func() {
753                 for {
754                         data := <-associateranchan
755                         xapp.Logger.Debug("received associate RAN list to E2T instance mapping from E2 Manager")
756                         m.Lock()
757                         sdlEngine.WriteAssRANToE2TInstance(fileName, data)
758                         m.Unlock()
759                         triggerSBI <- true
760                 }
761         }()
762
763         go func() {
764                 for {
765
766                         data := <-disassociateranchan
767                         xapp.Logger.Debug("received disassociate RANs from E2T instance")
768                         m.Lock()
769                         sdlEngine.WriteDisAssRANFromE2TInstance(fileName, data)
770                         m.Unlock()
771                         triggerSBI <- true
772                 }
773         }()
774
775         go func() {
776                 for {
777
778                         data := <-e2tdelchan
779                         xapp.Logger.Debug("received Delete E2T data")
780                         if data != nil {
781                                 m.Lock()
782                                 sdlEngine.WriteDeleteE2TInstance(fileName, data)
783                                 m.Unlock()
784                                 triggerSBI <- true
785                         }
786                 }
787         }()
788
789         return nil
790 }
791
792 func (r *HttpRestful) Terminate() error {
793         return nil
794 }
795
796 func addSubscription(subs *rtmgr.SubscriptionList, xappSubData *models.XappSubscriptionData) bool {
797         xapp.Logger.Debug("Adding the subscription into the subscriptions list")
798         var b = false
799         sub := rtmgr.Subscription{SubID: *xappSubData.SubscriptionID, Fqdn: *xappSubData.Address, Port: *xappSubData.Port}
800         for _, elem := range *subs {
801                 if elem == sub {
802                         xapp.Logger.Warn("rtmgr.addSubscription: Subscription already present: %v", elem)
803                         b = true
804                 }
805         }
806         if b == false {
807                 *subs = append(*subs, sub)
808         }
809         return b
810 }
811
812 func delSubscription(subs *rtmgr.SubscriptionList, xappSubData *models.XappSubscriptionData) bool {
813         xapp.Logger.Debug("Deleteing the subscription from the subscriptions list")
814         var present = false
815         sub := rtmgr.Subscription{SubID: *xappSubData.SubscriptionID, Fqdn: *xappSubData.Address, Port: *xappSubData.Port}
816         for i, elem := range *subs {
817                 if elem == sub {
818                         present = true
819                         // Since the order of the list is not important, we are swapping the last element
820                         // with the matching element and replacing the list with list(n-1) elements.
821                         (*subs)[len(*subs)-1], (*subs)[i] = (*subs)[i], (*subs)[len(*subs)-1]
822                         *subs = (*subs)[:len(*subs)-1]
823                         break
824                 }
825         }
826         if present == false {
827                 xapp.Logger.Warn("rtmgr.delSubscription: Subscription = %v, not present in the existing subscriptions", xappSubData)
828         }
829         return present
830 }
831
832 func updateSubscription(data *rtmgr.XappList) {
833
834         var subdata models.XappSubscriptionData
835         var id int32
836         var matchingsubid, deletecount uint8
837         id = int32(data.SubscriptionID)
838         subdata.SubscriptionID = &id
839         for _, subs := range rtmgr.Subs {
840                 if int32(data.SubscriptionID) == subs.SubID {
841                         matchingsubid++
842                 }
843         }
844
845         for deletecount < matchingsubid {
846                 for _, subs := range rtmgr.Subs {
847                         if int32(data.SubscriptionID) == subs.SubID {
848                                 subdata.SubscriptionID = &subs.SubID
849                                 subdata.Address = &subs.Fqdn
850                                 subdata.Port = &subs.Port
851                                 xapp.Logger.Debug("Deletion Subscription List has %v", subdata)
852                                 delSubscription(&rtmgr.Subs, &subdata)
853                                 break
854                         }
855                 }
856                 deletecount++
857         }
858
859         for _, items := range data.FqdnList {
860                 subdata.Address = items.Address
861                 subdata.Port = items.Port
862                 xapp.Logger.Debug("Adding Subscription List has %v", subdata)
863                 addSubscription(&rtmgr.Subs, &subdata)
864         }
865
866 }
867
868 func PopulateSubscription(sub_list xfmodel.SubscriptionList) {
869         for _, sub_row := range sub_list {
870                 var subdata models.XappSubscriptionData
871                 id := int32(sub_row.SubscriptionID)
872                 subdata.SubscriptionID = &id
873                 for _, ep := range sub_row.Endpoint {
874
875                         stringSlice := strings.Split(ep, ":")
876                         subdata.Address = &stringSlice[0]
877                         intportval, _ := strconv.Atoi(stringSlice[1])
878                         value := uint16(intportval)
879                         subdata.Port = &value
880                         xapp.Logger.Debug("Adding Subscription List has Address :%v, port :%v, SubscriptionID :%v ", subdata.Address, subdata.Address, subdata.SubscriptionID)
881                         addSubscription(&rtmgr.Subs, &subdata)
882                 }
883         }
884 }