diff --git a/Dockerfile b/Dockerfile index 4652071..487577b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM nexus3.o-ran-sc.org:10004/o-ran-sc/bldr-ubuntu18-c-go:1.9.0 as kpimonbuild +FROM nexus3.o-ran-sc.org:10002/o-ran-sc/bldr-ubuntu18-c-go:1.9.0 as kpimonbuild ENV PATH $PATH:/usr/local/bin ENV GOPATH /go @@ -14,9 +14,11 @@ RUN wget --content-disposition ${RMRLIBURL} && dpkg -i rmr_${RMRVERSION}_amd64.d RUN wget --content-disposition ${RMRDEVURL} && dpkg -i rmr-dev_${RMRVERSION}_amd64.deb RUN rm -f rmr_${RMRVERSION}_amd64.deb rmr-dev_${RMRVERSION}_amd64.deb +RUN apt update && apt install ca-certificates libgnutls30 -y + ARG XAPPFRAMEVERSION=v0.4.11 WORKDIR /go/src/gerrit.o-ran-sc.org/r/ric-plt -RUN git clone "https://gerrit.o-ran-sc.org/r/ric-plt/sdlgo" +RUN git clone -b cherry "https://gerrit.o-ran-sc.org/r/ric-plt/sdlgo" RUN git clone -b ${XAPPFRAMEVERSION} "https://gerrit.o-ran-sc.org/r/ric-plt/xapp-frame" RUN cd xapp-frame && \ GO111MODULE=on go mod vendor -v && \ @@ -55,6 +57,14 @@ RUN go build ./cmd/kpimon.go && pwd && ls -lat FROM ubuntu:18.04 + +ENV PATH $PATH:/usr/local/bin +ENV GOPATH /go +ENV GOBIN /go/bin +ENV RMR_SEED_RT /opt/routes.txt + +COPY routes.txt /opt/routes.txt + COPY --from=kpimonbuild /usr/local/lib /usr/local/lib COPY --from=kpimonbuild /usr/local/include/e2ap/*.h /usr/local/include/e2ap/ COPY --from=kpimonbuild /usr/local/include/e2sm/*.h /usr/local/include/e2sm/ @@ -64,3 +74,5 @@ COPY --from=kpimonbuild /go/src/gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/config/ WORKDIR /go/src/gerrit.o-ran-sc.org/r/scp/ric-app/kpimon COPY --from=kpimonbuild /go/src/gerrit.o-ran-sc.org/r/scp/ric-app/kpimon/kpimon . + +CMD sleep infinity \ No newline at end of file diff --git a/README.md b/README.md index e792a4e..12051d5 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,5 @@ This xApp can be onboarded through the xApp Onboarder. The xapp descriptor is under the xapp-descriptor/ directory. Then the xapp can be deployed through the App Manager. + +rte|12010|service-ricplt-e2term-rmr-alpha.ricplt:38000 \ No newline at end of file diff --git a/cmd/kpimon.go b/cmd/kpimon.go index 2fec0dc..19e8698 100644 --- a/cmd/kpimon.go +++ b/cmd/kpimon.go @@ -1,11 +1,147 @@ package main import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "os" + "strings" + "time" + "gerrit.o-ran-sc.org/r/scp/ric-app/kpimon/control" ) func main() { + response_deregister, err := deRegisterXApp() + if err != nil { + print("Error: " + err.Error()) + } + responseDeRegisterString := string(response_deregister) + + print("RESPONSE DEREGISTER POST: ") + println(responseDeRegisterString) + + time.Sleep(5 * time.Second) + + response, err := registerXApp() + if err != nil { + print("Error: " + err.Error()) + } + responseString := string(response) + + print("RESPONSE REGISTER POST: ") + println(responseString) + + time.Sleep(5 * time.Second) + c := control.NewControl() c.Run() } +func registerXApp() ([]byte, error) { + + url := "http://service-ricplt-appmgr-http.ricplt:8080/ric/v1/register" + + // Read payload from config-file.json + payload, err := ioutil.ReadFile("/opt/ric/config/config-file.json") + if err != nil { + print("Error READ CONF: " + err.Error()) + } + + hostname := os.Getenv("HOSTNAME") + XAPP_NAME := hostname + XAPP_VERSION := "1.0.0" + // RICPLT_NAMESPACE := "ricplt" + XAPP_NAMESPACE := "ricxapp" + + // http_endpoint := "SERVICE_" + strings.ToUpper(XAPP_NAMESPACE) + "_" + strings.ToUpper(XAPP_NAME) + "_HTTP_PORT" + rmr_os_key := "SERVICE_" + strings.ToUpper(XAPP_NAMESPACE) + "_" + strings.ToUpper(XAPP_NAME) + "_RMR_PORT" + rmr_endpoint := strings.Split(os.Getenv(rmr_os_key), "//")[1] + + config := string(payload) + + // Create new JSON + request := map[string]interface{}{ + "appName": hostname, + "appVersion": XAPP_VERSION, + "configPath": "", + "appInstanceName": XAPP_NAME, + "httpEndpoint": "", + "rmrEndpoint": rmr_endpoint, + "config": config, + } + + // Encode the JSON object as a string + requestString, err := json.Marshal(request) + if err != nil { + fmt.Println("Error encoding JSON:", err) + return nil, err + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestString)) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} + +func deRegisterXApp() ([]byte, error) { + + url := "http://service-ricplt-appmgr-http.ricplt:8080/ric/v1/deregister" + + hostname := os.Getenv("HOSTNAME") + XAPP_NAME := hostname + + // Create new JSON + request := map[string]interface{}{ + "appName": hostname, + "appInstanceName": XAPP_NAME, + } + + // Encode the JSON object as a string + requestString, err := json.Marshal(request) + if err != nil { + fmt.Println("Error encoding JSON:", err) + return nil, err + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestString)) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/json") + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil +} diff --git a/control/control.go b/control/control.go index 45acb6b..9007bd0 100644 --- a/control/control.go +++ b/control/control.go @@ -15,15 +15,15 @@ import ( ) type Control struct { - ranList []string //nodeB list - eventCreateExpired int32 //maximum time for the RIC Subscription Request event creation procedure in the E2 Node - eventDeleteExpired int32 //maximum time for the RIC Subscription Request event deletion procedure in the E2 Node - rcChan chan *xapp.RMRParams //channel for receiving rmr message + ranList []string //nodeB list + eventCreateExpired int32 //maximum time for the RIC Subscription Request event creation procedure in the E2 Node + eventDeleteExpired int32 //maximum time for the RIC Subscription Request event deletion procedure in the E2 Node + rcChan chan *xapp.RMRParams //channel for receiving rmr message //client *redis.Client //redis client - eventCreateExpiredMap map[string]bool //map for recording the RIC Subscription Request event creation procedure is expired or not - eventDeleteExpiredMap map[string]bool //map for recording the RIC Subscription Request event deletion procedure is expired or not - eventCreateExpiredMu *sync.Mutex //mutex for eventCreateExpiredMap - eventDeleteExpiredMu *sync.Mutex //mutex for eventDeleteExpiredMap + eventCreateExpiredMap map[string]bool //map for recording the RIC Subscription Request event creation procedure is expired or not + eventDeleteExpiredMap map[string]bool //map for recording the RIC Subscription Request event deletion procedure is expired or not + eventCreateExpiredMu *sync.Mutex //mutex for eventCreateExpiredMap + eventDeleteExpiredMu *sync.Mutex //mutex for eventDeleteExpiredMap sdl *sdlgo.SdlInstance } @@ -40,7 +40,11 @@ func init() { } func NewControl() Control { - str := os.Getenv("ranList") + println("Starting new control.") + // str := os.Getenv("ranList") + str := "gnb_131_133_31000000,gnb_131_133_32000000,gnb_131_133_33000000,gnb_131_133_34000000,gnb_131_133_35000000" + println("Ran list is " + str + " ---- ") + return Control{strings.Split(str, ","), 5, 5, make(chan *xapp.RMRParams), @@ -90,7 +94,7 @@ func (c *Control) startTimerSubReq() { count++ xapp.Logger.Debug("send RIC_SUB_REQ to gNodeB with cnt=%d", count) log.Printf("send RIC_SUB_REQ to gNodeB with cnt=%d", count) - err := c.sendRicSubRequest(1001, 1001, 0) + err := c.sendRicSubRequest(1001, 200, 0) if err != nil && count < MAX_SUBSCRIPTION_ATTEMPTS { t.Reset(5 * time.Second) } else { @@ -666,7 +670,7 @@ func (c *Control) handleIndication(params *xapp.RMRParams) (err error) { ueMetrics.UeID = ueID log.Printf("UeID: %d", ueMetrics.UeID) - ueMetrics.ServingCellID = servingCellID + ueMetrics.ServingCellID = servingCellID log.Printf("ServingCellID: %s", ueMetrics.ServingCellID) ueMetrics.MeasPeriodRF = 20 @@ -1121,8 +1125,8 @@ func (c *Control) setEventCreateExpiredTimer(ranName string) { delete(c.eventCreateExpiredMap, ranName) c.eventCreateExpiredMu.Unlock() if !isResponsed { - xapp.Logger.Debug("RIC_SUB_REQ[%s]: RIC Event Create Timer experied!", ranName) - log.Printf("RIC_SUB_REQ[%s]: RIC Event Create Timer experied!", ranName) + xapp.Logger.Debug("RIC_SUB_REQ[%s]: RIC Event Create Timer expired!", ranName) + log.Printf("RIC_SUB_REQ[%s]: RIC Event Create Timer expired!", ranName) // c.sendRicSubDelRequest(subID, requestSN, funcID) return } @@ -1162,8 +1166,8 @@ func (c *Control) setEventDeleteExpiredTimer(ranName string) { delete(c.eventDeleteExpiredMap, ranName) c.eventDeleteExpiredMu.Unlock() if !isResponsed { - xapp.Logger.Debug("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer experied!", ranName) - log.Printf("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer experied!", ranName) + xapp.Logger.Debug("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer expired!", ranName) + log.Printf("RIC_SUB_DEL_REQ[%s]: RIC Event Delete Timer expired!", ranName) return } default: diff --git a/launch_app.sh b/launch_app.sh new file mode 100755 index 0000000..52a7686 --- /dev/null +++ b/launch_app.sh @@ -0,0 +1,23 @@ +#!/bin/bash +#set -x + +export CHART_REPO_URL=http://0.0.0.0:8090 + +dms_cli uninstall xappkpimon ricxapp + +docker build . -f Dockerfile -t 127.0.0.1:5000/kpimon_master:1.0.0 # --no-cache + +docker push 127.0.0.1:5000/kpimon_master:1.0.0 + +# dms_cli onboard config.json schema.json + +dms_cli install xappkpimon 1.0.0 ricxapp + +echo "Wait for 10 seconds" +sleep 10 + +unset $pod_name + +pod_name=$(kubectl get pods -n ricxapp --no-headers -o custom-columns=":metadata.name") + +kubectl exec -ti -n ricxapp $pod_name bash diff --git a/routes.txt b/routes.txt index e69de29..2f2fc7e 100644 --- a/routes.txt +++ b/routes.txt @@ -0,0 +1,5 @@ +newrt|start +rte|20011|service-ricplt-a1mediator-rmr.ricplt:4562 +rte|20012|service-ricplt-a1mediator-rmr.ricplt:4562 +rte|12010|service-ricplt-submgr-rmr.ricplt:4560 +newrt|end \ No newline at end of file diff --git a/xapp-descriptor/config.json b/xapp-descriptor/config.json index a621e99..922acbc 100644 --- a/xapp-descriptor/config.json +++ b/xapp-descriptor/config.json @@ -5,8 +5,8 @@ { "name": "xappkpimon", "image": { - "registry": "nexus3.o-ran-sc.org:10002", - "name": "o-ran-sc/scp-ric-app-kpimon", + "registry": "127.0.0.1:5000", + "name": "kpimon_master", "tag": "1.0.0" } } diff --git a/xapp-descriptor/config_sleep.json b/xapp-descriptor/config_sleep.json new file mode 100644 index 0000000..b448d3b --- /dev/null +++ b/xapp-descriptor/config_sleep.json @@ -0,0 +1,41 @@ +{ + "xapp_name": "xappkpimon", + "version": "1.0.0", + "containers": [ + { + "name": "xappkpimon", + "image": { + "registry": "127.0.0.1:5000", + "name": "kpimon_sleep", + "tag": "1.0.0" + } + } + ], + "messaging": { + "ports": [ + { + "name": "rmr-data", + "container": "xappkpimon", + "port": 4560, + "rxMessages": ["RIC_SUB_RESP", "RIC_INDICATION"], + "txMessages": ["RIC_SUB_REQ"], + "policies": [], + "description": "rmr receive data port for xappkpimon" + }, + { + "name": "rmr-route", + "container": "xappkpimon", + "port": 4561, + "description": "rmr route port for xappkpimon" + } + ] + }, + "rmr": { + "protPort": "tcp:4560", + "maxSize": 2072, + "numWorkers": 1, + "rxMessages": ["RIC_SUB_RESP", "RIC_INDICATION"], + "txMessages": ["RIC_SUB_REQ"], + "policies": [] + } +} diff --git a/xapp-descriptor/schema.json b/xapp-descriptor/schema.json new file mode 100755 index 0000000..f7b8ce4 --- /dev/null +++ b/xapp-descriptor/schema.json @@ -0,0 +1,62 @@ +{ + "definitions": {}, + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://example.com/root.json", + "type": "object", + "title": "The Root Schema", + "required": [ + "active", + "interfaceId" + ], + "properties": { + "active": { + "$id": "#/properties/active", + "type": "boolean", + "title": "The Active Schema", + "default": false, + "examples": [ + false + ] + }, + "interfaceId": { + "$id": "#/properties/interfaceId", + "type": "object", + "title": "The Interfaceid Schema", + "required": [ + "globalENBId" + ], + "properties": { + "globalENBId": { + "$id": "#/properties/interfaceId/properties/globalENBId", + "type": "object", + "title": "The Globalenbid Schema", + "required": [ + "plmnId", + "eNBId" + ], + "properties": { + "plmnId": { + "$id": "#/properties/interfaceId/properties/globalENBId/properties/plmnId", + "type": "string", + "title": "The Plmnid Schema", + "default": "", + "examples": [ + "310150" + ], + "pattern": "^(.*)$" + }, + "eNBId": { + "$id": "#/properties/interfaceId/properties/globalENBId/properties/eNBId", + "type": "integer", + "title": "The Enbid Schema", + "default": 0, + "examples": [ + 202251 + ] + } + } + } + } + } + } +}