blob: bf140c4ce9aef551bada531e22d2a1d705baa612 [file] [log] [blame]
Mohamed Abukar5120ec12020-02-04 11:01:24 +02001/*
2==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 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*/
19
20package xapp
21
22import (
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030023 "bytes"
Mohamed Abukar9568a2d2020-02-18 16:50:32 +020024 "encoding/json"
25 "fmt"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020026 "github.com/go-openapi/loads"
27 httptransport "github.com/go-openapi/runtime/client"
28 "github.com/go-openapi/runtime/middleware"
29 "github.com/go-openapi/strfmt"
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030030 "github.com/spf13/viper"
Mohamed Abukar9568a2d2020-02-18 16:50:32 +020031 "io/ioutil"
Mohamed Abukar47faec82020-04-09 22:08:19 +030032 "net"
Mohamed Abukar9568a2d2020-02-18 16:50:32 +020033 "net/http"
rangajalfd347862020-11-03 20:35:40 +030034 "os"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020035 "time"
wahidw413abf52020-12-15 12:17:09 +000036 //"errors"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020037
38 apiclient "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientapi"
Mohamed Abukar429da192020-02-26 16:46:34 +020039 apicommon "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientapi/common"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020040 apipolicy "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientapi/policy"
41 apireport "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientapi/report"
42 apimodel "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/clientmodel"
43
44 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
45 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi"
46 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations"
Mohamed Abukar429da192020-02-26 16:46:34 +020047 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/common"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020048 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/policy"
Mohamed Abukar9568a2d2020-02-18 16:50:32 +020049 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/query"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020050 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/report"
wahidw413abf52020-12-15 12:17:09 +000051 //"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/restapi/operations/xapp"
Mohamed Abukar5120ec12020-02-04 11:01:24 +020052)
53
Mohamed Abukarb6341a52020-03-23 08:55:05 +020054type SubscriptionHandler func(models.SubscriptionType, interface{}) (*models.SubscriptionResponse, error)
Mohamed Abukar9568a2d2020-02-18 16:50:32 +020055type SubscriptionQueryHandler func() (models.SubscriptionList, error)
Mohamed Abukar429da192020-02-26 16:46:34 +020056type SubscriptionDeleteHandler func(string) error
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030057type SubscriptionResponseCallback func(*apimodel.SubscriptionResponse)
Mohamed Abukar5120ec12020-02-04 11:01:24 +020058
59type Subscriber struct {
60 localAddr string
61 localPort int
62 remoteHost string
63 remoteUrl string
64 remoteProt []string
65 timeout time.Duration
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030066 clientUrl string
67 clientCB SubscriptionResponseCallback
Mohamed Abukar5120ec12020-02-04 11:01:24 +020068}
69
70func NewSubscriber(host string, timo int) *Subscriber {
71 if host == "" {
rangajalfd347862020-11-03 20:35:40 +030072 pltnamespace := os.Getenv("PLT_NAMESPACE")
73 if pltnamespace == "" {
74 pltnamespace = "ricplt"
75 }
76 host = fmt.Sprintf("service-%s-submgr-http.%s:8088", pltnamespace, pltnamespace)
Mohamed Abukar5120ec12020-02-04 11:01:24 +020077 }
78
79 if timo == 0 {
80 timo = 20
81 }
82
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030083 r := &Subscriber{
Mohamed Abukar5120ec12020-02-04 11:01:24 +020084 remoteHost: host,
85 remoteUrl: "/ric/v1",
86 remoteProt: []string{"http"},
87 timeout: time.Duration(timo) * time.Second,
88 localAddr: "0.0.0.0",
89 localPort: 8088,
Mohamed Abukar5953f7e2020-04-02 10:08:14 +030090 clientUrl: "/ric/v1/subscriptions/response",
91 }
92 Resource.InjectRoute(r.clientUrl, r.ResponseHandler, "POST")
93
94 return r
95}
96
97func (r *Subscriber) ResponseHandler(w http.ResponseWriter, req *http.Request) {
98 if req.Body != nil {
99 var resp apimodel.SubscriptionResponse
100 if err := json.NewDecoder(req.Body).Decode(&resp); err == nil {
101 if r.clientCB != nil {
102 r.clientCB(&resp)
103 }
104 }
105 req.Body.Close()
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200106 }
107}
108
109// Server interface: listen and receive subscription requests
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300110func (r *Subscriber) Listen(createSubscription SubscriptionHandler, getSubscription SubscriptionQueryHandler, delSubscription SubscriptionDeleteHandler) error {
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200111 swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON)
112 if err != nil {
113 return err
114 }
115
116 api := operations.NewXappFrameworkAPI(swaggerSpec)
117
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300118 // Subscription: Query
Mohamed Abukar9568a2d2020-02-18 16:50:32 +0200119 api.QueryGetAllSubscriptionsHandler = query.GetAllSubscriptionsHandlerFunc(
120 func(p query.GetAllSubscriptionsParams) middleware.Responder {
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300121 if resp, err := getSubscription(); err == nil {
Mohamed Abukar9568a2d2020-02-18 16:50:32 +0200122 return query.NewGetAllSubscriptionsOK().WithPayload(resp)
123 }
124 return query.NewGetAllSubscriptionsInternalServerError()
125 })
126
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200127 // SubscriptionType: Report
128 api.ReportSubscribeReportHandler = report.SubscribeReportHandlerFunc(
129 func(p report.SubscribeReportParams) middleware.Responder {
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300130 if resp, err := createSubscription(models.SubscriptionTypeReport, p.ReportParams); err == nil {
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200131 return report.NewSubscribeReportCreated().WithPayload(resp)
132 }
133 return report.NewSubscribeReportInternalServerError()
134 })
135
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300136 // SubscriptionType: Policy
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200137 api.PolicySubscribePolicyHandler = policy.SubscribePolicyHandlerFunc(
138 func(p policy.SubscribePolicyParams) middleware.Responder {
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300139 if resp, err := createSubscription(models.SubscriptionTypePolicy, p.PolicyParams); err == nil {
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200140 return policy.NewSubscribePolicyCreated().WithPayload(resp)
141 }
142 return policy.NewSubscribePolicyInternalServerError()
143 })
144
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300145 // SubscriptionType: Delete
Mohamed Abukar429da192020-02-26 16:46:34 +0200146 api.CommonUnsubscribeHandler = common.UnsubscribeHandlerFunc(
147 func(p common.UnsubscribeParams) middleware.Responder {
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300148 if err := delSubscription(p.SubscriptionID); err == nil {
Mohamed Abukar429da192020-02-26 16:46:34 +0200149 return common.NewUnsubscribeNoContent()
150 }
151 return common.NewUnsubscribeInternalServerError()
152 })
153
wahidw413abf52020-12-15 12:17:09 +0000154 // XApp: Get Config
155 /*api.XappGetXappConfigListHandler = xapp.GetXappConfigListHandlerFunc(
156 func(p xapp.GetXappConfigListParams) middleware.Responder {
157 Logger.Info("Hitting xapp config")
158 if resp,err := r.getXappConfig(); err == nil {
159 return xapp.NewGetXappConfigListOK().WithPayload(resp)
160 }
161 return xapp.NewGetXappConfigListInternalServerError()
162 })*/
163
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200164 server := restapi.NewServer(api)
165 defer server.Shutdown()
166 server.Host = r.localAddr
167 server.Port = r.localPort
168
169 Logger.Info("Serving subscriptions on %s:%d\n", server.Host, server.Port)
170 if err := server.Serve(); err != nil {
171 return err
172 }
173 return nil
174}
175
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300176// Server interface: send notification to client
177func (r *Subscriber) Notify(resp *models.SubscriptionResponse, clientEndpoint string) (err error) {
178 respData, err := json.Marshal(resp)
179 if err != nil {
180 Logger.Error("json.Marshal failed: %v", err)
181 return err
182 }
183
Mohamed Abukar47faec82020-04-09 22:08:19 +0300184 ep, _, _ := net.SplitHostPort(clientEndpoint)
Mohamed Abukarb8b191f2020-11-07 11:22:56 +0200185 _, port, _ := net.SplitHostPort(fmt.Sprintf(":%d", GetPortData("http").Port))
Mohamed Abukar47faec82020-04-09 22:08:19 +0300186 clientUrl := fmt.Sprintf("http://%s:%s%s", ep, port, r.clientUrl)
Mohamed Abukar5953f7e2020-04-02 10:08:14 +0300187
188 retries := viper.GetInt("subscription.retryCount")
189 if retries == 0 {
190 retries = 10
191 }
192
193 delay := viper.GetInt("subscription.retryDelay")
194 if delay == 0 {
195 delay = 5
196 }
197
198 for i := 0; i < retries; i++ {
199 r, err := http.Post(clientUrl, "application/json", bytes.NewBuffer(respData))
200 if err == nil && (r != nil && r.StatusCode == http.StatusOK) {
201 break
202 }
203
204 if err != nil {
205 Logger.Error("%v", err)
206 }
207 if r != nil && r.StatusCode != http.StatusOK {
208 Logger.Error("clientUrl=%s statusCode=%d", clientUrl, r.StatusCode)
209 }
210 time.Sleep(time.Duration(delay) * time.Second)
211 }
212
213 return err
214}
215
216// Subscription interface for xApp: Response callback
217func (r *Subscriber) SetResponseCB(c SubscriptionResponseCallback) {
218 r.clientCB = c
219}
220
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200221// Subscription interface for xApp: REPORT
Mohamed Abukarb6341a52020-03-23 08:55:05 +0200222func (r *Subscriber) SubscribeReport(p *apimodel.ReportParams) (*apimodel.SubscriptionResponse, error) {
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200223 params := apireport.NewSubscribeReportParamsWithTimeout(r.timeout).WithReportParams(p)
224 result, err := r.CreateTransport().Report.SubscribeReport(params)
225 if err != nil {
Mohamed Abukarb6341a52020-03-23 08:55:05 +0200226 return &apimodel.SubscriptionResponse{}, err
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200227 }
228
229 return result.Payload, err
230}
231
232// Subscription interface for xApp: POLICY
Mohamed Abukarb6341a52020-03-23 08:55:05 +0200233func (r *Subscriber) SubscribePolicy(p *apimodel.PolicyParams) (*apimodel.SubscriptionResponse, error) {
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200234 params := apipolicy.NewSubscribePolicyParamsWithTimeout(r.timeout).WithPolicyParams(p)
235 result, err := r.CreateTransport().Policy.SubscribePolicy(params)
236 if err != nil {
Mohamed Abukarb6341a52020-03-23 08:55:05 +0200237 return &apimodel.SubscriptionResponse{}, err
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200238 }
239
240 return result.Payload, err
241}
242
Mohamed Abukar429da192020-02-26 16:46:34 +0200243// Subscription interface for xApp: DELETE
244func (r *Subscriber) UnSubscribe(subId string) error {
245 params := apicommon.NewUnsubscribeParamsWithTimeout(r.timeout).WithSubscriptionID(subId)
246 _, err := r.CreateTransport().Common.Unsubscribe(params)
247
248 return err
249}
250
Mohamed Abukar9568a2d2020-02-18 16:50:32 +0200251// Subscription interface for xApp: QUERY
252func (r *Subscriber) QuerySubscriptions() (models.SubscriptionList, error) {
253 resp, err := http.Get(fmt.Sprintf("http://%s/%s/subscriptions", r.remoteHost, r.remoteUrl))
254 if err != nil {
255 return models.SubscriptionList{}, err
256 }
257
258 defer resp.Body.Close()
259
260 contents, err := ioutil.ReadAll(resp.Body)
261 if err != nil {
262 return models.SubscriptionList{}, err
263 }
264
265 subscriptions := models.SubscriptionList{}
266 err = json.Unmarshal([]byte(string(contents)), &subscriptions)
267 if err != nil {
268 return models.SubscriptionList{}, err
269 }
270
271 return subscriptions, nil
272}
273
274func (r *Subscriber) CreateTransport() *apiclient.RICSubscription {
275 return apiclient.New(httptransport.New(r.remoteHost, r.remoteUrl, r.remoteProt), strfmt.Default)
Mohamed Abukar5120ec12020-02-04 11:01:24 +0200276}
wahidw413abf52020-12-15 12:17:09 +0000277
278/*func (r *Subscriber) getXappConfig() (appconfig models.XappConfigList, err error) {
279
280 Logger.Error("Inside getXappConfig")
281
282 var metadata models.ConfigMetadata
283 var xappconfig models.XAppConfig
284 name := viper.GetString("name")
285 configtype := "json"
286 metadata.XappName = &name
287 metadata.ConfigType = &configtype
288
289 configFile, err := os.Open("/opt/ric/config/config-file.json")
290 if err != nil {
291 Logger.Error("Cannot open config file: %v", err)
292 return nil,errors.New("Could Not parse the config file")
293 }
294
295 body, err := ioutil.ReadAll(configFile)
296
297 defer configFile.Close()
298
299 xappconfig.Metadata = &metadata
300 xappconfig.Config = body
301
302 appconfig = append(appconfig,&xappconfig)
303
304 return appconfig,nil
305}*/