Example xApp enhancement
[ric-plt/xapp-frame.git] / examples / cmd / example-xapp.go
1 /*
2 ==================================================================================
3   Copyright (c) 2020 AT&T Intellectual Property.
4   Copyright (c) 2020 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    This source code is part of the near-RT RIC (RAN Intelligent Controller)
19    platform project (RICP).
20 ==================================================================================
21 */
22 package main
23
24 import (
25         "gerrit.o-ran-sc.org/r/ric-plt/alarm-go.git/alarm"
26         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientmodel"
27         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
28         "net/http"
29 )
30
31 // This could be defined in types.go
32 type ExampleXapp struct {
33         stats                 map[string]xapp.Counter
34         rmrReady              bool
35         waitForSdl            bool
36         subscriptionInstances []*clientmodel.SubscriptionInstance
37         subscriptionId        *string
38 }
39
40 func (e *ExampleXapp) handleRICIndication(ranName string, r *xapp.RMRParams) {
41         // Just update metrics and store RMR message payload to SDL
42         e.stats["E2APIndicationsRx"].Inc()
43
44         xapp.Sdl.Store("myKey", r.Payload)
45 }
46
47 func (e *ExampleXapp) handleRICExampleMessage(ranName string, r *xapp.RMRParams) {
48         // Just update metrics and echo the message back (update the message type)
49         e.stats["RICExampleMessageRx"].Inc()
50
51         r.Mtype = r.Mtype + 1
52         if ok := xapp.Rmr.SendMsg(r); !ok {
53                 xapp.Logger.Info("Rmr.SendMsg failed ...")
54         }
55 }
56
57 func (e *ExampleXapp) Subscribe() {
58         // Setup response callback to handle subscription response from SubMgr
59         xapp.Subscription.SetResponseCB(func(resp *clientmodel.SubscriptionResponse) {
60                 if *e.subscriptionId == *resp.SubscriptionID {
61                         for _, s := range resp.SubscriptionInstances {
62                                 e.subscriptionInstances = append(e.subscriptionInstances, s)
63                         }
64                 }
65         })
66
67         // Fill subscription parameters: type=REPORT
68         ranName := "en-gnb:369-11105-aaaaa8"
69         functionId := int64(1)
70         clientEndpoint := "localhost:4560"
71
72         reportParams := clientmodel.ReportParams{
73                 Meid:           ranName,
74                 RANFunctionID:  &functionId,
75                 ClientEndpoint: &clientEndpoint,
76                 EventTriggers: clientmodel.EventTriggerList{
77                         &clientmodel.EventTrigger{
78                                 InterfaceDirection: int64(0),
79                                 ProcedureCode:      int64(27),
80                                 TypeOfMessage:      int64(1),
81                         },
82                 },
83         }
84
85         // Now subscribe ...
86         if resp, err := xapp.Subscription.SubscribeReport(&reportParams); err == nil {
87                 e.subscriptionId = resp.SubscriptionID
88                 xapp.Logger.Info("Subscriptions for RanName='%s' [subscriptionId=%s] done!", ranName, *resp.SubscriptionID)
89                 return
90         }
91
92         // Subscription failed, raise alarm (only for demo purpose!)
93         if err := xapp.Alarm.Raise(8006, alarm.SeverityCritical, ranName, "subscriptionFailed"); err != nil {
94                 xapp.Logger.Info("Raising alarm failed with error: %v", err)
95         }
96 }
97
98 func (e *ExampleXapp) Consume(msg *xapp.RMRParams) (err error) {
99         id := xapp.Rmr.GetRicMessageName(msg.Mtype)
100
101         xapp.Logger.Info("Message received: name=%s meid=%s subId=%d txid=%s len=%d", id, msg.Meid.RanName, msg.SubId, msg.Xid, msg.PayloadLen)
102
103         switch id {
104         case "RIC_INDICATION":
105                 e.handleRICIndication(msg.Meid.RanName, msg)
106         case "RIC_EXAMPLE_MESSAGE":
107                 e.handleRICExampleMessage(msg.Meid.RanName, msg)
108         default:
109                 xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype)
110         }
111
112         defer func() {
113                 xapp.Rmr.Free(msg.Mbuf)
114                 msg.Mbuf = nil
115         }()
116         return
117 }
118
119 func (u *ExampleXapp) TestRestHandler(w http.ResponseWriter, r *http.Request) {
120         xapp.Logger.Info("TestRestHandler called!")
121 }
122
123 func (u *ExampleXapp) ConfigChangeHandler(f string) {
124         xapp.Logger.Info("Config file changed, do something meaningful!")
125 }
126
127 func (u *ExampleXapp) StatusCB() bool {
128         xapp.Logger.Info("Status callback called, do something meaningful!")
129         return true
130 }
131
132 func (e *ExampleXapp) Run() {
133         // Set MDC (read: name visible in the logs)
134         xapp.Logger.SetMdc("example-xapp", "0.1.3")
135
136         // Register various callback functions for application management
137         xapp.SetReadyCB(func(d interface{}) { e.rmrReady = true }, true)
138         xapp.AddConfigChangeListener(e.ConfigChangeHandler)
139         xapp.Resource.InjectStatusCb(e.StatusCB)
140
141         // Inject own REST handler for testing purpose
142         xapp.Resource.InjectRoute("/ric/v1/testing", e.TestRestHandler, "POST")
143
144         xapp.RunWithParams(e, e.waitForSdl)
145 }
146
147 func GetMetricsOpts() []xapp.CounterOpts {
148         return []xapp.CounterOpts{
149                 {Name: "RICIndicationsRx", Help: "The total number of RIC inidcation events received"},
150                 {Name: "RICExampleMessageRx", Help: "The total number of RIC example messages received"},
151         }
152 }
153
154 func NewExampleXapp(rmrReady bool) *ExampleXapp {
155         metrics := GetMetricsOpts()
156         return &ExampleXapp{
157                 stats:      xapp.Metric.RegisterCounterGroup(metrics, "ExampleXapp"),
158                 rmrReady:   rmrReady,
159                 waitForSdl: xapp.Config.GetBool("db.waitForSdl"),
160         }
161 }
162
163 func main() {
164         NewExampleXapp(true).Run()
165 }