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