blob: d0448aa3efd22dbf5cb3af6aa4355d2b334c5776 [file] [log] [blame]
ss412g07ef76d2019-08-12 17:26:40 +03001//
2// Copyright 2019 AT&T Intellectual Property
3// Copyright 2019 Nokia
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
17
18package controllers
19
20import (
21 "e2mgr/logger"
22 "e2mgr/models"
23 "e2mgr/providers"
24 "e2mgr/rNibWriter"
25 "e2mgr/services"
26 "e2mgr/sessions"
27 "e2mgr/utils"
28 "encoding/json"
29 "errors"
30 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
31 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
32 "github.com/go-ozzo/ozzo-validation"
33 "github.com/go-ozzo/ozzo-validation/is"
34 "github.com/golang/protobuf/jsonpb"
35 "github.com/julienschmidt/httprouter"
36 "net/http"
37 "net/http/httputil"
38 "strings"
39 "sync"
40 "time"
41)
42
43const (
44 parseErrorCode int = 401
45 validationErrorCode int = 402
46 notFoundErrorCode int = 404
47 internalErrorCode int = 501
48 requiredInputErrorMessage = "Mandatory fields are missing"
49 validationFailedMessage = "Validation failed"
50 parseErrorMessage = "Parse failure"
51 notFoundErrorMessage = "Resource not found"
52 internalErrorMessage = "Internal Server Error. Please try again later"
53 sendMessageErrorMessage = "Failed to send message. For more information please check logs"
54)
55
56var E2Sessions = make(sessions.E2Sessions)
57
58var messageChannel chan *models.E2RequestMessage
59var errorChannel chan error
60
61type NodebController struct {
62 rmrService *services.RmrService
63 Logger *logger.Logger
64 rnibReaderProvider func() reader.RNibReader
65 rnibWriterProvider func() rNibWriter.RNibWriter
66}
67
68func NewNodebController(logger *logger.Logger, rmrService *services.RmrService, rnibReaderProvider func() reader.RNibReader,
69 rnibWriterProvider func() rNibWriter.RNibWriter) *NodebController {
70 messageChannel = make(chan *models.E2RequestMessage)
71 errorChannel = make(chan error)
72 return &NodebController{
73 rmrService: rmrService,
74 Logger: logger,
75 rnibReaderProvider: rnibReaderProvider,
76 rnibWriterProvider: rnibWriterProvider,
77 }
78}
79
80
81func prettifyRequest(request *http.Request) string {
82 dump, _ := httputil.DumpRequest(request, true)
83 requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
84 return strings.Replace(requestPrettyPrint, "\n", "", -1)
85}
86
87func (rc NodebController) HandleRequest(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
88 startTime := time.Now()
89 rc.Logger.Infof("[Client -> E2 Manager] #nodeb_controller.HandleRequest - request: %v", prettifyRequest(request))
90
91 messageTypeParam := params.ByName("messageType")
92 requestHandlerProvider := providers.NewRequestHandlerProvider(rc.rnibWriterProvider)
93 handler, err := requestHandlerProvider.GetHandler(rc.Logger, messageTypeParam)
94
95 if err != nil {
96 handleErrorResponse(rc.Logger, http.StatusNotFound, notFoundErrorCode, notFoundErrorMessage, writer, startTime)
97 return
98 }
99
100 requestDetails, err := parseJson(rc.Logger, request)
101
102 if err != nil {
103 handleErrorResponse(rc.Logger, http.StatusBadRequest, parseErrorCode, parseErrorMessage, writer, startTime)
104 return
105 }
106
107 rc.Logger.Infof("#nodeb_controller.HandleRequest - request: %+v", requestDetails)
108
109 if err := validateRequestDetails(rc.Logger, requestDetails); err != nil {
110 handleErrorResponse(rc.Logger, http.StatusBadRequest, validationErrorCode, requiredInputErrorMessage, writer, startTime)
111 return
112 }
113
114 err = handler.PreHandle(rc.Logger, &requestDetails)
115
116 if err != nil {
117 handleErrorResponse(rc.Logger, http.StatusInternalServerError, internalErrorCode, err.Error(), writer, startTime)
118 return
119 }
120
121 rc.Logger.Infof("[E2 Manager -> Client] #nodeb_controller.HandleRequest - http status: 200")
122 writer.WriteHeader(http.StatusOK)
123
124 var wg sync.WaitGroup
125
126 go handler.CreateMessage(rc.Logger, &requestDetails, messageChannel, E2Sessions, startTime, wg)
127
128 go rc.rmrService.SendMessage(handler.GetMessageType(), messageChannel, errorChannel, wg)
129
130 wg.Wait()
131
132 err = <-errorChannel
133
134 if err != nil {
135 handleErrorResponse(rc.Logger, http.StatusInternalServerError, internalErrorCode, sendMessageErrorMessage, writer, startTime)
136 return
137 }
138
139 printHandlingRequestElapsedTimeInMs(rc.Logger, startTime)
140}
141
142func (rc NodebController) GetNodebIdList (writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
143 startTime := time.Now()
144 rnibReaderService := services.NewRnibReaderService(rc.rnibReaderProvider())
145 nodebIdList, rnibError := rnibReaderService.GetNodebIdList()
146
147 if rnibError != nil {
148 rc.Logger.Errorf("%v", rnibError);
149 httpStatusCode, errorCode, errorMessage := rnibErrorToHttpError(rnibError)
150 handleErrorResponse(rc.Logger,httpStatusCode,errorCode,errorMessage,writer,startTime )
151 return;
152 }
153
154 pmList:= utils.ConvertNodebIdListToProtoMessageList(*nodebIdList)
155 result, err := utils.MarshalProtoMessageListToJsonArray(pmList)
156
157 if err != nil {
158 rc.Logger.Errorf("%v", err);
159 handleErrorResponse(rc.Logger,http.StatusInternalServerError,internalErrorCode,internalErrorMessage,writer,startTime )
160 return;
161 }
162
163 writer.Header().Set("Content-Type", "application/json")
164 rc.Logger.Infof("[E2 Manager -> Client] #nodeb_controller.GetNodebIdList - response: %s", result)
165 writer.Write([]byte(result))
166}
167
168func (rc NodebController) GetNodeb(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
169 startTime := time.Now()
170 ranName := params.ByName("ranName")
171 // WAS: respondingNode, rnibError := reader.GetRNibReader().GetNodeb(ranName)
172 rnibReaderService := services.NewRnibReaderService(rc.rnibReaderProvider());
173 respondingNode, rnibError := rnibReaderService.GetNodeb(ranName)
174 if rnibError != nil {
175 rc.Logger.Errorf("%v", rnibError)
176 httpStatusCode, errorCode, errorMessage := rnibErrorToHttpError(rnibError)
177 handleErrorResponse(rc.Logger, httpStatusCode, errorCode, errorMessage, writer, startTime)
178 return
179 }
180
181 m := jsonpb.Marshaler{}
182 result, err := m.MarshalToString(respondingNode)
183
184 if err != nil {
185 rc.Logger.Errorf("%v", err)
186 handleErrorResponse(rc.Logger, http.StatusInternalServerError, internalErrorCode, internalErrorMessage, writer, startTime)
187 return
188 }
189
190 writer.Header().Set("Content-Type", "application/json")
191 rc.Logger.Infof("[E2 Manager -> Client] #nodeb_controller.GetNodeb - response: %s", result)
192 writer.Write([]byte(result))
193}
194
195func (rc NodebController) HandleHealthCheckRequest(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {
196 //fmt.Println("[X-APP -> Client] #HandleHealthCheckRequest - http status: 200")
197 writer.WriteHeader(http.StatusOK)
198}
199
200func parseJson(logger *logger.Logger, request *http.Request) (models.RequestDetails, error) {
201 var requestDetails models.RequestDetails
202 if err := json.NewDecoder(request.Body).Decode(&requestDetails); err != nil {
203 logger.Errorf("#nodeb_controller.parseJson - cannot deserialize incoming request. request: %v, error: %v", request, err)
204 return requestDetails, err
205 }
206 return requestDetails, nil
207}
208
209func validateRequestDetails(logger *logger.Logger, requestDetails models.RequestDetails) error {
210
211 if requestDetails.RanPort == 0 {
212 logger.Errorf("#nodeb_controller.validateRequestDetails - validation failure: port cannot be zero")
213 return errors.New("port: cannot be blank")
214 }
215 err := validation.ValidateStruct(&requestDetails,
216 validation.Field(&requestDetails.RanIp, validation.Required, is.IP),
217 validation.Field(&requestDetails.RanName, validation.Required),
218 )
219 if err != nil {
220 logger.Errorf("#nodeb_controller.validateRequestDetails - validation failure, error: %v", err)
221 }
222
223 return err
224}
225
226func handleErrorResponse(logger *logger.Logger, httpStatus int, errorCode int, errorMessage string, writer http.ResponseWriter, startTime time.Time) {
227 errorResponseDetails := models.ErrorResponse{errorCode, errorMessage}
228 errorResponse, _ := json.Marshal(errorResponseDetails)
229 printHandlingRequestElapsedTimeInMs(logger, startTime)
230 logger.Infof("[E2 Manager -> Client] #nodeb_controller.handleErrorResponse - http status: %d, error response: %+v", httpStatus, errorResponseDetails)
231 writer.Header().Set("Content-Type", "application/json")
232 writer.WriteHeader(httpStatus)
233 _, err := writer.Write(errorResponse)
234
235 if err != nil {
236 logger.Errorf("#nodeb_controller.handleErrorResponse - Cannot send response. writer:%v", writer)
237 }
238}
239
240func printHandlingRequestElapsedTimeInMs(logger *logger.Logger, startTime time.Time) {
241 logger.Infof("Summary: #nodeb_controller.printElapsedTimeInMs - Elapsed time for handling request from client to E2 termination: %f ms",
242 float64(time.Since(startTime))/float64(time.Millisecond))
243}
244
245func rnibErrorToHttpError(rnibError common.IRNibError) (int, int, string) {
246 switch rnibError.GetCode() {
247 case common.RESOURCE_NOT_FOUND:
248 return http.StatusNotFound, notFoundErrorCode, notFoundErrorMessage
249 case common.INTERNAL_ERROR:
250 return http.StatusInternalServerError, internalErrorCode, internalErrorMessage
251 case common.VALIDATION_ERROR:
252 return http.StatusBadRequest, validationErrorCode, validationFailedMessage
253 default:
254 return http.StatusInternalServerError, internalErrorCode, internalErrorMessage
255 }
256}