RIC:1060: Change in PTL
[ric-plt/xapp-frame.git] / pkg / xapp / xapp.go
index ab5aeb6..72a8d32 100755 (executable)
@@ -23,40 +23,67 @@ import (
        "bytes"
        "encoding/json"
        "fmt"
-       "github.com/spf13/viper"
+       "net"
        "net/http"
        "os"
        "os/signal"
        "strings"
        "sync/atomic"
        "syscall"
+       "testing"
        "time"
+
+       "github.com/spf13/viper"
 )
 
+// For testing purpose go version 1.13 ->
+
+var _ = func() bool {
+       testing.Init()
+       return true
+}()
+
 type ReadyCB func(interface{})
 type ShutdownCB func()
 
 var (
        // XApp is an application instance
-       Rmr           *RMRClient
-       Sdl           *SDLClient
-       Rnib          *RNIBClient
-       Resource      *Router
-       Metric        *Metrics
-       Logger        *Log
-       Config        Configurator
-       Subscription  *Subscriber
-       Alarm         *AlarmClient
-       Util          *Utils
-       readyCb       ReadyCB
-       readyCbParams interface{}
-       shutdownCb    ShutdownCB
-       shutdownFlag  int32
-       shutdownCnt   int32
+       Rmr                *RMRClient
+       Sdl                *SDLClient
+       SdlStorage         *SDLStorage
+       Rnib               *RNIBClient
+       Resource           *Router
+       Metric             *Metrics
+       Logger             *Log
+       Config             Configurator
+       Subscription       *Subscriber
+       Alarm              *AlarmClient
+       Util               *Utils
+       readyCb            ReadyCB
+       readyCbParams      interface{}
+       shutdownCb         ShutdownCB
+       shutdownFlag       int32
+       shutdownCnt        int32
+       disableAlarmClient bool
+       isRegistered       bool
 )
 
+var startTime time.Time
+
+func XappUpTime() time.Duration {
+       return time.Since(startTime)
+}
+
+func init() {
+       startTime = time.Now()
+}
+
 func IsReady() bool {
-       return Rmr != nil && Rmr.IsReady() && Sdl != nil && Sdl.IsReady()
+       return Rmr != nil && Rmr.IsReady() && SdlStorage != nil && SdlStorage.IsReady()
+}
+
+func IsRegistered() bool {
+       return isRegistered
 }
 
 func SetReadyCB(cb ReadyCB, params interface{}) {
@@ -65,7 +92,9 @@ func SetReadyCB(cb ReadyCB, params interface{}) {
 }
 
 func XappReadyCb(params interface{}) {
-       Alarm = NewAlarmClient(viper.GetString("moId"), viper.GetString("name"))
+       if disableAlarmClient == false {
+               Alarm = NewAlarmClient(viper.GetString("moId"), viper.GetString("name"))
+       }
        if readyCb != nil {
                readyCb(readyCbParams)
        }
@@ -85,18 +114,21 @@ func XappShutdownCb() {
        if shutdownCb != nil {
                shutdownCb()
        }
+
+       isRegistered = false
 }
 
 func registerXapp() {
        for {
                time.Sleep(5 * time.Second)
                if !IsHealthProbeReady() {
-                       Logger.Info("Application='%s' is not ready yet, waiting ...", viper.GetString("name"))
+                       Logger.Debug("Application='%s' is not ready yet, waiting ...", viper.GetString("name"))
                        continue
                }
 
                Logger.Debug("Application='%s' is now up and ready, continue with registration ...", viper.GetString("name"))
                if err := doRegister(); err == nil {
+                       isRegistered = true
                        Logger.Info("Registration done, proceeding with startup ...")
                        break
                }
@@ -111,6 +143,8 @@ func getService(host, service string) string {
 
        svc := fmt.Sprintf(service, strings.ToUpper(appnamespace), strings.ToUpper(host))
        url := strings.Split(os.Getenv(strings.Replace(svc, "-", "_", -1)), "//")
+
+       Logger.Info("getService: %+v %+v", svc, url)
        if len(url) > 1 {
                return url[1]
        }
@@ -129,9 +163,21 @@ func getPltNamespace(envName, defVal string) string {
 func doPost(pltNs, url string, msg []byte, status int) error {
        resp, err := http.Post(fmt.Sprintf(url, pltNs, pltNs), "application/json", bytes.NewBuffer(msg))
        if err != nil || resp == nil || resp.StatusCode != status {
-               Logger.Info("http.Post to '%s' failed with error: %v", fmt.Sprintf(url, pltNs, pltNs), err)
-               return err
+               logdesc := fmt.Sprintf("http.Post to '%s' failed with", fmt.Sprintf(url, pltNs, pltNs))
+               if resp != nil {
+                       logdesc += fmt.Sprintf(" status: %d != %d", resp.StatusCode, status)
+               } else {
+                       logdesc += fmt.Sprintf(" resp: nil")
+               }
+               if err != nil {
+                       logdesc += fmt.Sprintf(" err: %s", err.Error())
+               } else {
+                       logdesc += fmt.Sprintf(" err: nil")
+               }
+               Logger.Info(logdesc)
+               return fmt.Errorf(logdesc)
        }
+
        Logger.Info("Post to '%s' done, status:%v", fmt.Sprintf(url, pltNs, pltNs), resp.Status)
 
        return err
@@ -143,6 +189,7 @@ func doRegister() error {
        xappversion := viper.GetString("version")
        pltNs := getPltNamespace("PLT_NAMESPACE", DEFAULT_PLT_NS)
 
+       //httpEp, rmrEp := getService(xappname, SERVICE_HTTP), getService(xappname, SERVICE_RMR)
        httpEp, rmrEp := getService(host, SERVICE_HTTP), getService(host, SERVICE_RMR)
        if httpEp == "" || rmrEp == "" {
                Logger.Warn("Couldn't resolve service endpoints: httpEp=%s rmrEp=%s", httpEp, rmrEp)
@@ -251,31 +298,77 @@ func init() {
        Resource = NewRouter()
        Config = Configurator{}
        Metric = NewMetrics(viper.GetString("metrics.url"), viper.GetString("metrics.namespace"), Resource.router)
-       Subscription = NewSubscriber(viper.GetString("subscription.host"), viper.GetInt("subscription.timeout"))
+       Subscription = NewSubscriber(viper.GetString("controls.subscription.host"), viper.GetInt("controls.subscription.timeout"))
+       SdlStorage = NewSdlStorage()
        Sdl = NewSDLClient(viper.GetString("controls.db.namespace"))
-       Rnib = NewRNIBClient()
+       Rnib = GetNewRnibClient(SdlStorage.db)
        Util = NewUtils()
 
        InstallSignalHandler()
 }
 
-func RunWithParams(c MessageConsumer, sdlcheck bool) {
+func GetIpAddress() (string, error) {
+       ifname := os.Getenv("INTERFACE_NAME")
+       itf, err := net.InterfaceByName(ifname)
+       if err != nil {
+               return "<nil>", fmt.Errorf("Interface (%s) %w", ifname, err)
+       }
+       item, err := itf.Addrs()
+       if err != nil {
+               return "<nil>", fmt.Errorf("Interface (%s) %w", ifname, err)
+       }
+       for _, addr := range item {
+               switch v := addr.(type) {
+               case *net.IPNet:
+                       if !v.IP.IsLinkLocalUnicast() {
+                               return v.IP.String(), nil
+                       }
+               }
+       }
+       return "<nil>", fmt.Errorf("Interface (%s) couldn't find ip", ifname)
+}
+
+type RunParams struct {
+       SdlCheck           bool
+       DisableAlarmClient bool
+}
+
+func RunWithRunParams(c MessageConsumer, params RunParams) {
+
+       if params.DisableAlarmClient {
+               disableAlarmClient = true
+       } else {
+               disableAlarmClient = false
+       }
+
        Rmr = NewRMRClient()
 
        Rmr.SetReadyCB(XappReadyCb, nil)
-
-       host := fmt.Sprintf(":%d", GetPortData("http").Port)
+       ipString, err := GetIpAddress()
+       if err != nil {
+               Logger.Info("IP address is not able to resolve " + err.Error())
+       }
+       var host string
+       if ipString == "<nil>" {
+               host = fmt.Sprintf(":%d", GetPortData("http").Port)
+       } else {
+               host = fmt.Sprintf("[%s]:%d", ipString, GetPortData("http").Port)
+       }
        go http.ListenAndServe(host, Resource.router)
        Logger.Info(fmt.Sprintf("Xapp started, listening on: %s", host))
 
-       if sdlcheck {
-               Sdl.TestConnection()
+       if params.SdlCheck {
+               SdlStorage.TestConnection(viper.GetString("controls.db.namespace"))
        }
        go registerXapp()
 
        Rmr.Start(c)
 }
 
+func RunWithParams(c MessageConsumer, sdlcheck bool) {
+       RunWithRunParams(c, RunParams{SdlCheck: sdlcheck, DisableAlarmClient: false})
+}
+
 func Run(c MessageConsumer) {
        RunWithParams(c, true)
 }