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