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