f47034ea683df7266b501595fb2eddfcce050d77
[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         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
39         xfmodel "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
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 maxRetries = 10
585         var xappData *[]rtmgr.XApp
586         xappData = new([]rtmgr.XApp)
587         xapp.Logger.Info("Trying to fetch XApps data from XAPP manager")
588         for i := 1; i <= maxRetries; i++ {
589                 time.Sleep(2 * time.Second)
590
591                 readErr = nil
592                 xappData, err := httpGetXApps(xmurl)
593                 if xappData != nil && err == nil {
594                         break
595                 } else if err == nil {
596                         readErr = errors.New("unexpected HTTP status code")
597                 } else {
598                         xapp.Logger.Warn("cannot get xapp data due to: " + err.Error())
599                         readErr = err
600                 }
601         }
602
603         if ( readErr != nil) {
604                 return readErr
605         }
606
607         var meids []string
608         e2ts := make(map[string]rtmgr.E2TInstance)
609         xapp.Logger.Info("Trying to fetch E2T data from E2manager")
610         for i := 1; i <= maxRetries; i++ {
611
612                 readErr = nil
613                 e2tDataList, err := httpGetE2TList(e2murl)
614                 if e2tDataList != nil && err == nil {
615                         PopulateE2TMap(e2tDataList, e2ts, meids[:])
616                         break
617                 } else if err == nil {
618                         readErr = errors.New("unexpected HTTP status code")
619                 } else {
620                         xapp.Logger.Warn("cannot get E2T data from E2M due to: " + err.Error())
621                         readErr = err
622                 }
623        time.Sleep(2 * time.Second)
624         }
625
626         if ( readErr != nil) {
627                 return readErr
628         }
629
630         pcData, confErr := rtmgr.GetPlatformComponents(configfile)
631     if confErr != nil {
632             xapp.Logger.Error(confErr.Error())
633             return confErr
634     }
635     xapp.Logger.Info("Recieved intial xapp data, E2T data and platform data, writing into SDL.")
636     // Combine the xapps data and platform data before writing to the SDL
637         ricData := &rtmgr.RicComponents{XApps: *xappData, Pcs: *pcData, E2Ts: e2ts, MeidMap: meids}
638     writeErr := sdlEngine.WriteAll(fileName, ricData)
639     if writeErr != nil {
640             xapp.Logger.Error(writeErr.Error())
641     }
642
643         xapp.Logger.Info("Trying to fetch Subscriptions data from Subscription manager")
644     for i := 1; i <= maxRetries; i++ {
645                 readErr = nil
646                 sub_list, err := xapp.Subscription.QuerySubscriptions()
647
648                 if sub_list != nil && err == nil {
649                         PopulateSubscription(sub_list)
650                         break
651                 } else {
652                         readErr = err
653                         xapp.Logger.Warn("cannot get xapp data due to: " + readErr.Error())
654         }
655                 time.Sleep(2 * time.Second)
656         }
657
658         if (readErr != nil) {
659         return readErr
660         }
661
662     // post subscription req to appmgr
663     readErr = PostSubReq(xmurl, nbiif)
664     if readErr == nil {
665             return nil
666     }
667         return readErr
668 }
669
670 func (r *HttpRestful) Initialize(xmurl string, nbiif string, fileName string, configfile string, e2murl string,
671         sdlEngine sdl.Engine, rpeEngine rpe.Engine, triggerSBI chan<- bool, m *sync.Mutex) error {
672         err := r.RetrieveStartupData(xmurl, nbiif, fileName, configfile, e2murl, sdlEngine)
673         if err != nil {
674                 xapp.Logger.Error("Exiting as nbi failed to get the initial startup data from the xapp manager: " + err.Error())
675                 return err
676         }
677
678         datach := make(chan *models.XappCallbackData, 10)
679         subschan := make(chan *models.XappSubscriptionData, 10)
680         subdelchan := make(chan *models.XappSubscriptionData, 10)
681         subupdatechan := make(chan *rtmgr.XappList, 10)
682         e2taddchan := make(chan *models.E2tData, 10)
683         associateranchan := make(chan models.RanE2tMap, 10)
684         disassociateranchan := make(chan models.RanE2tMap, 10)
685         e2tdelchan := make(chan *models.E2tDeleteData, 10)
686         xapp.Logger.Info("Launching Rest Http service")
687         go func() {
688                 r.LaunchRest(&nbiif, datach, subschan, subupdatechan, subdelchan, e2taddchan, associateranchan, disassociateranchan, e2tdelchan)
689         }()
690
691         go func() {
692                 for {
693                         data, err := r.RecvXappCallbackData(datach)
694                         if err != nil {
695                                 xapp.Logger.Error("cannot get data from rest api dute to: " + err.Error())
696                         } else if data != nil {
697                                 xapp.Logger.Debug("Fetching all xApps deployed in xApp Manager through GET operation.")
698                                 alldata, err1 := httpGetXApps(xmurl)
699                                 if alldata != nil && err1 == nil {
700                                         m.Lock()
701                                         sdlEngine.WriteXApps(fileName, alldata)
702                                         m.Unlock()
703                                         triggerSBI <- true
704                                 }
705                         }
706                 }
707         }()
708
709         go func() {
710                 for {
711                         data := <-subschan
712                         xapp.Logger.Debug("received XApp subscription data")
713                         addSubscription(&rtmgr.Subs, data)
714                         triggerSBI <- true
715                 }
716         }()
717
718         go func() {
719                 for {
720                         data := <-subdelchan
721                         xapp.Logger.Debug("received XApp subscription delete data")
722                         delSubscription(&rtmgr.Subs, data)
723                         triggerSBI <- true
724                 }
725         }()
726
727         go func() {
728                 for {
729                         data := <-subupdatechan
730                         xapp.Logger.Debug("received XApp subscription Merge data")
731                         updateSubscription(data)
732                         triggerSBI <- true
733                 }
734         }()
735
736         go func() {
737                 for {
738
739                         data, meiddata, _ := r.RecvNewE2Tdata(e2taddchan)
740                         if data != nil {
741                                 xapp.Logger.Debug("received create New E2T data")
742                                 m.Lock()
743                                 sdlEngine.WriteNewE2TInstance(fileName, data, meiddata)
744                                 m.Unlock()
745                                 triggerSBI <- true
746                         }
747                 }
748         }()
749
750         go func() {
751                 for {
752                         data := <-associateranchan
753                         xapp.Logger.Debug("received associate RAN list to E2T instance mapping from E2 Manager")
754                         m.Lock()
755                         sdlEngine.WriteAssRANToE2TInstance(fileName, data)
756                         m.Unlock()
757                         triggerSBI <- true
758                 }
759         }()
760
761         go func() {
762                 for {
763
764                         data := <-disassociateranchan
765                         xapp.Logger.Debug("received disassociate RANs from E2T instance")
766                         m.Lock()
767                         sdlEngine.WriteDisAssRANFromE2TInstance(fileName, data)
768                         m.Unlock()
769                         triggerSBI <- true
770                 }
771         }()
772
773         go func() {
774                 for {
775
776                         data := <-e2tdelchan
777                         xapp.Logger.Debug("received Delete E2T data")
778                         if data != nil {
779                                 m.Lock()
780                                 sdlEngine.WriteDeleteE2TInstance(fileName, data)
781                                 m.Unlock()
782                                 triggerSBI <- true
783                         }
784                 }
785         }()
786
787         return nil
788 }
789
790 func (r *HttpRestful) Terminate() error {
791         return nil
792 }
793
794 func addSubscription(subs *rtmgr.SubscriptionList, xappSubData *models.XappSubscriptionData) bool {
795         xapp.Logger.Debug("Adding the subscription into the subscriptions list")
796         var b = false
797         sub := rtmgr.Subscription{SubID: *xappSubData.SubscriptionID, Fqdn: *xappSubData.Address, Port: *xappSubData.Port}
798         for _, elem := range *subs {
799                 if elem == sub {
800                         xapp.Logger.Warn("rtmgr.addSubscription: Subscription already present: %v", elem)
801                         b = true
802                 }
803         }
804         if b == false {
805                 *subs = append(*subs, sub)
806         }
807         return b
808 }
809
810 func delSubscription(subs *rtmgr.SubscriptionList, xappSubData *models.XappSubscriptionData) bool {
811         xapp.Logger.Debug("Deleteing the subscription from the subscriptions list")
812         var present = false
813         sub := rtmgr.Subscription{SubID: *xappSubData.SubscriptionID, Fqdn: *xappSubData.Address, Port: *xappSubData.Port}
814         for i, elem := range *subs {
815                 if elem == sub {
816                         present = true
817                         // Since the order of the list is not important, we are swapping the last element
818                         // with the matching element and replacing the list with list(n-1) elements.
819                         (*subs)[len(*subs)-1], (*subs)[i] = (*subs)[i], (*subs)[len(*subs)-1]
820                         *subs = (*subs)[:len(*subs)-1]
821                         break
822                 }
823         }
824         if present == false {
825                 xapp.Logger.Warn("rtmgr.delSubscription: Subscription = %v, not present in the existing subscriptions", xappSubData)
826         }
827         return present
828 }
829
830 func updateSubscription(data *rtmgr.XappList) {
831
832         var subdata models.XappSubscriptionData
833         var id int32
834         var matchingsubid, deletecount uint8
835         id = int32(data.SubscriptionID)
836         subdata.SubscriptionID = &id
837         for _, subs := range rtmgr.Subs {
838                 if int32(data.SubscriptionID) == subs.SubID {
839                         matchingsubid++
840                 }
841         }
842
843         for deletecount < matchingsubid {
844                 for _, subs := range rtmgr.Subs {
845                         if int32(data.SubscriptionID) == subs.SubID {
846                                 subdata.SubscriptionID = &subs.SubID
847                                 subdata.Address = &subs.Fqdn
848                                 subdata.Port = &subs.Port
849                                 xapp.Logger.Debug("Deletion Subscription List has %v", subdata)
850                                 delSubscription(&rtmgr.Subs, &subdata)
851                                 break
852                         }
853                 }
854                 deletecount++
855         }
856
857         for _, items := range data.FqdnList {
858                 subdata.Address = items.Address
859                 subdata.Port = items.Port
860                 xapp.Logger.Debug("Adding Subscription List has %v", subdata)
861                 addSubscription(&rtmgr.Subs, &subdata)
862         }
863
864 }
865
866 func PopulateSubscription(sub_list xfmodel.SubscriptionList) {
867         for _, sub_row := range sub_list {
868                 var subdata models.XappSubscriptionData
869                 id := int32(sub_row.SubscriptionID)
870                 subdata.SubscriptionID = &id
871                 for _, ep := range sub_row.Endpoint {
872
873                         stringSlice := strings.Split(ep, ":")
874                         subdata.Address = &stringSlice[0]
875                         intportval, _ := strconv.Atoi( stringSlice[1])
876                         value := uint16(intportval)
877                         subdata.Port = &value
878                         xapp.Logger.Debug("Adding Subscription List has Address :%v, port :%v, SubscriptionID :%v ", subdata.Address, subdata.Address, subdata.SubscriptionID)
879                         addSubscription(&rtmgr.Subs, &subdata)
880                 }
881         }
882 }