Redesign and taking xapp-framework into use
[ric-plt/vespamgr.git] / cmd / vesmgr / vesmgr.go
diff --git a/cmd/vesmgr/vesmgr.go b/cmd/vesmgr/vesmgr.go
deleted file mode 100755 (executable)
index 5086098..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- *  Copyright (c) 2019 AT&T Intellectual Property.
- *  Copyright (c) 2018-2019 Nokia.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This source code is part of the near-RT RIC (RAN Intelligent Controller)
- *  platform project (RICP).
- *
- */
-
-package main
-
-import (
-       "errors"
-       "fmt"
-       "io/ioutil"
-       "net"
-       "net/http"
-       "os"
-       "time"
-
-       mdcloggo "gerrit.o-ran-sc.org/r/com/golog.git"
-)
-
-var appmgrDomain string
-
-const appmgrXAppConfigPath = "/ric/v1/config"
-const appmgrPort = "8080"
-
-// VesMgr contains runtime information of the vesmgr process
-type VesMgr struct {
-       myIPAddress         string
-       chXAppSubscriptions chan subscriptionNotification
-       chXAppNotifications chan []byte
-       chSupervision       chan chan string
-       chVesagent          chan error
-       vesagent            cmdRunner
-       httpServer          HTTPServer
-}
-
-type subscriptionNotification struct {
-       subscribed bool
-       err        error
-       subsID     string
-}
-
-var logger *mdcloggo.MdcLogger
-
-// Version information, which is filled during compilation
-// Version tag of vesmgr container
-var Version string
-
-// Hash of the git commit used in building
-var Hash string
-
-const vesmgrXappNotifPort = "8080"
-const vesmgrXappNotifPath = "/vesmgr_xappnotif/"
-const timeoutPostXAppSubscriptions = 5
-const vespaConfigFile = "/etc/ves-agent/ves-agent.yaml"
-
-func init() {
-       logger, _ = mdcloggo.InitLogger("vesmgr")
-}
-
-func getMyIP() (myIP string, retErr error) {
-       addrs, err := net.InterfaceAddrs()
-       if err != nil {
-               logger.Error("net.InterfaceAddrs failed: %s", err.Error())
-               return "", err
-       }
-       for _, addr := range addrs {
-               // check the address type and if it is not a loopback take it
-               if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
-                       if ipnet.IP.To4() != nil {
-                               logger.Info("My IP Address: %s", ipnet.IP.String())
-                               return ipnet.IP.String(), nil
-                       }
-               }
-       }
-       return "", nil
-}
-
-func createConf(fname string, xappMetrics []byte) {
-       f, err := os.Create(fname)
-       if err != nil {
-               logger.Error("Cannot create vespa conf file: %s", err.Error())
-               os.Exit(1)
-       }
-       defer f.Close()
-
-       createVespaConfig(f, xappMetrics)
-       logger.Info("Vespa config created")
-}
-
-func (vesmgr *VesMgr) subscribeXAppNotifications() {
-       xappNotifURL := "http://" + vesmgr.myIPAddress + ":" + vesmgrXappNotifPort + vesmgrXappNotifPath
-       subsURL := "http://" + appmgrDomain + ":" + appmgrPort + appmgrSubsPath
-       go subscribexAppNotifications(xappNotifURL, vesmgr.chXAppSubscriptions, timeoutPostXAppSubscriptions, subsURL)
-       logger.Info("xApp notifications subscribed from %s", subsURL)
-}
-
-// Init initializes the vesmgr
-func (vesmgr *VesMgr) Init(listenPort string) *VesMgr {
-       logger.Info("vesmgrInit")
-       logger.Info("version: %s (%s)", Version, Hash)
-
-       var err error
-       if vesmgr.myIPAddress, err = getMyIP(); err != nil || vesmgr.myIPAddress == "" {
-               logger.Error("Cannot get myIPAddress: IP %s", vesmgr.myIPAddress)
-               panic("Cannot get my IP address")
-       }
-
-       var ok bool
-       appmgrDomain, ok = os.LookupEnv("VESMGR_APPMGRDOMAIN")
-       if ok {
-               logger.Info("Using appmgrdomain %s", appmgrDomain)
-       } else {
-               pltnamespace := os.Getenv("PLT_NAMESPACE")
-               if pltnamespace == "" {
-                       pltnamespace = "ricplt"
-               }
-               appmgrDomain = fmt.Sprintf("service-%s-appmgr-http.%s.svc.cluster.local", pltnamespace, pltnamespace)
-               logger.Info("Using default appmgrdomain %s", appmgrDomain)
-       }
-       vesmgr.chXAppSubscriptions = make(chan subscriptionNotification)
-       // Create notifications as buffered channel so that
-       // xappmgr does not block if we are stuck somewhere
-       vesmgr.chXAppNotifications = make(chan []byte, 10)
-       vesmgr.chSupervision = make(chan chan string)
-       vesmgr.chVesagent = make(chan error)
-       vesmgr.httpServer = HTTPServer{}
-       vesmgr.httpServer.init(vesmgr.myIPAddress + ":" + listenPort)
-       vesmgr.vesagent = makeRunner("ves-agent", "-i", os.Getenv("VESMGR_HB_INTERVAL"),
-               "-m", os.Getenv("VESMGR_MEAS_INTERVAL"), "--Measurement.Prometheus.Address",
-               os.Getenv("VESMGR_PROMETHEUS_ADDR"), "--AlertManager.Bind", os.Getenv("VESMGR_ALERTMANAGER_BIND_ADDR"),
-               "--Debug")
-       return vesmgr
-}
-
-func (vesmgr *VesMgr) startVesagent() {
-       vesmgr.vesagent.run(vesmgr.chVesagent)
-}
-
-func (vesmgr *VesMgr) killVespa() error {
-       logger.Info("Killing vespa")
-       err := vesmgr.vesagent.kill()
-       if err != nil {
-               logger.Error("Cannot kill vespa: %s", err.Error())
-               return err
-       }
-       return <-vesmgr.chVesagent // wait vespa exit
-}
-
-func queryXAppsConfig(appmgrURL string, timeout time.Duration) ([]byte, error) {
-       emptyConfig := []byte("{}")
-       logger.Info("query xAppConfig started, url %s", appmgrURL)
-       req, err := http.NewRequest("GET", appmgrURL, nil)
-       if err != nil {
-               logger.Error("Failed to create a HTTP request: %s", err)
-               return emptyConfig, err
-       }
-       req.Header.Set("Content-Type", "application/json")
-       client := &http.Client{}
-       client.Timeout = time.Second * timeout
-       resp, err := client.Do(req)
-       if err != nil {
-               logger.Error("Query xApp config failed: %s", err)
-               return emptyConfig, err
-       }
-       defer resp.Body.Close()
-       if resp.StatusCode == http.StatusOK {
-               body, err := ioutil.ReadAll(resp.Body)
-               if err != nil {
-                       logger.Error("Failed to read xApp config body: %s", err)
-                       return emptyConfig, err
-               }
-               logger.Info("query xAppConfig completed")
-               return body, nil
-       }
-       logger.Error("Error from xApp config query: %s", resp.Status)
-       return emptyConfig, errors.New(resp.Status)
-}
-
-func queryConf() (appConfig []byte, err error) {
-       for i := 0; i < 10; i++ {
-               appConfig, err = queryXAppsConfig("http://"+appmgrDomain+":"+appmgrPort+appmgrXAppConfigPath, 10*time.Second)
-               if len(appConfig) > 0 {
-                       break
-               }
-               time.Sleep(5 * time.Second)
-       }
-       return appConfig, err
-}
-
-func (vesmgr *VesMgr) emptyNotificationsChannel() {
-       for {
-               select {
-               case <-vesmgr.chXAppNotifications:
-                       // we don't care the content
-               default:
-                       return
-               }
-       }
-}
-
-func (vesmgr *VesMgr) servRequest() {
-       select {
-       case supervision := <-vesmgr.chSupervision:
-               logger.Info("vesmgr: supervision")
-               supervision <- "OK"
-       case xAppNotif := <-vesmgr.chXAppNotifications:
-               logger.Info("vesmgr: xApp notification")
-               logger.Info(string(xAppNotif))
-               vesmgr.emptyNotificationsChannel()
-               /*
-               * If xapp config query fails then we cannot create
-               * a new configuration and kill vespa.
-               * In that case we assume that
-               * the situation is fixed when the next
-               * xapp notif comes
-                */
-               xappConfig, err := queryConf()
-               if err == nil {
-                       vesmgr.killVespa()
-                       createConf(vespaConfigFile, xappConfig)
-                       vesmgr.startVesagent()
-               }
-       case err := <-vesmgr.chVesagent:
-               logger.Error("Vesagent exited: " + err.Error())
-               os.Exit(1)
-       }
-}
-
-func (vesmgr *VesMgr) waitSubscriptionLoop() {
-       for {
-               select {
-               case supervision := <-vesmgr.chSupervision:
-                       logger.Info("vesmgr: supervision")
-                       supervision <- "OK"
-               case isSubscribed := <-vesmgr.chXAppSubscriptions:
-                       if isSubscribed.err != nil {
-                               logger.Error("Failed to make xApp subscriptions, vesmgr exiting: %s", isSubscribed.err)
-                               os.Exit(1)
-                       }
-                       return
-               }
-       }
-}
-
-// Run the vesmgr process main loop
-func (vesmgr *VesMgr) Run() {
-       logger.Info("vesmgr main loop ready")
-
-       vesmgr.httpServer.start(vesmgrXappNotifPath, vesmgr.chXAppNotifications, vesmgr.chSupervision)
-
-       vesmgr.subscribeXAppNotifications()
-
-       vesmgr.waitSubscriptionLoop()
-
-       xappConfig, _ := queryConf()
-
-       createConf(vespaConfigFile, xappConfig)
-
-       vesmgr.startVesagent()
-       for {
-               vesmgr.servRequest()
-       }
-}