2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
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
9 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 // This source code is part of the near-RT RIC (RAN Intelligent Controller)
18 // platform project (RICP).
23 "e2mgr/e2managererrors"
26 "e2mgr/providers/httpmsghandlerprovider"
28 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
29 "github.com/golang/protobuf/jsonpb"
30 "github.com/golang/protobuf/proto"
31 "github.com/gorilla/mux"
40 ParamRanName = "ranName"
43 const ApplicationJson = "application/json"
44 const ContentType = "Content-Type"
46 type INodebController interface {
47 Shutdown(writer http.ResponseWriter, r *http.Request)
48 X2Reset(writer http.ResponseWriter, r *http.Request)
49 GetNodeb(writer http.ResponseWriter, r *http.Request)
50 UpdateGnb(writer http.ResponseWriter, r *http.Request)
51 GetNodebIdList(writer http.ResponseWriter, r *http.Request)
52 SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request)
53 AddEnb(writer http.ResponseWriter, r *http.Request)
56 type NodebController struct {
58 handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
61 func NewNodebController(logger *logger.Logger, handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider) *NodebController {
62 return &NodebController{
64 handlerProvider: handlerProvider,
68 func (c *NodebController) GetNodebIdList(writer http.ResponseWriter, r *http.Request) {
69 c.logger.Infof("[Client -> E2 Manager] #NodebController.GetNodebIdList - request: %v", c.prettifyRequest(r))
71 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetNodebIdListRequest, nil, false, http.StatusOK)
74 func (c *NodebController) GetNodeb(writer http.ResponseWriter, r *http.Request) {
75 c.logger.Infof("[Client -> E2 Manager] #NodebController.GetNodeb - request: %v", c.prettifyRequest(r))
77 ranName := vars["ranName"]
78 request := models.GetNodebRequest{RanName: ranName}
79 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetNodebRequest, request, false, http.StatusOK)
82 func (c *NodebController) UpdateGnb(writer http.ResponseWriter, r *http.Request) {
83 c.logger.Infof("[Client -> E2 Manager] #NodebController.UpdateGnb - request: %v", c.prettifyRequest(r))
85 ranName := vars[ParamRanName]
87 request := models.UpdateGnbRequest{}
91 if !c.extractRequestBodyToProto(r, &gnb, writer) {
96 request.RanName = ranName
97 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateGnbRequest, request, true, http.StatusOK)
100 func (c *NodebController) AddEnb(writer http.ResponseWriter, r *http.Request) {
101 c.logger.Infof("[Client -> E2 Manager] #NodebController.AddEnb - request: %v", c.prettifyRequest(r))
104 body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
107 c.logger.Errorf("[Client -> E2 Manager] #NodebController.AddEnb - unable to read request body - error: %s", err)
108 c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
112 addEnbRequest := models.AddEnbRequest{}
113 err = json.Unmarshal(body, &addEnbRequest)
116 c.logger.Errorf("[Client -> E2 Manager] #NodebController.AddEnb - unable to unmarshal json - error: %s", err)
117 c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
121 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.AddEnbRequest, &addEnbRequest, true, http.StatusCreated)
124 func (c *NodebController) SetGeneralConfiguration(writer http.ResponseWriter, r *http.Request) {
125 c.logger.Infof("[Client -> E2 Manager] #NodebController.SetGeneralConfiguration - request: %v", c.prettifyRequest(r))
127 request := models.GeneralConfigurationRequest{}
129 if !c.extractJsonBodyDisallowUnknownFields(r, &request, writer) {
132 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.SetGeneralConfigurationRequest, request, false, http.StatusOK)
135 func (c *NodebController) Shutdown(writer http.ResponseWriter, r *http.Request) {
136 c.logger.Infof("[Client -> E2 Manager] #NodebController.Shutdown - request: %v", c.prettifyRequest(r))
137 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false, http.StatusNoContent)
140 func (c *NodebController) X2Reset(writer http.ResponseWriter, r *http.Request) {
141 c.logger.Infof("[Client -> E2 Manager] #NodebController.X2Reset - request: %v", c.prettifyRequest(r))
142 request := models.ResetRequest{}
144 ranName := vars[ParamRanName]
146 if err := c.extractJsonBody(r, &request); err != nil {
147 c.handleErrorResponse(err, writer)
150 request.RanName = ranName
151 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false, http.StatusNoContent)
154 func (c *NodebController) extractRequestBodyToProto(r *http.Request, pb proto.Message, writer http.ResponseWriter) bool {
157 err := jsonpb.Unmarshal(r.Body, pb)
160 c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
161 c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
168 func (c *NodebController) extractJsonBodyDisallowUnknownFields(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
171 decoder := json.NewDecoder(r.Body)
172 decoder.DisallowUnknownFields()
174 if err := decoder.Decode(&request); err != nil {
175 c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
176 c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
183 func (c *NodebController) extractJsonBody(r *http.Request, request models.Request) error {
185 body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
188 c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
189 return e2managererrors.NewInvalidJsonError()
192 err = json.Unmarshal(body, &request)
194 c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
195 return e2managererrors.NewInvalidJsonError()
201 func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateRequestHeaders bool, successStatusCode int) {
203 if validateRequestHeaders {
205 err := c.validateRequestHeader(header)
207 c.handleErrorResponse(err, writer)
212 handler, err := c.handlerProvider.GetHandler(requestName)
215 c.handleErrorResponse(err, writer)
219 response, err := handler.Handle(request)
222 c.handleErrorResponse(err, writer)
226 if successStatusCode == http.StatusNoContent {
227 writer.WriteHeader(successStatusCode)
228 c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - status response: %v", http.StatusNoContent)
232 result, err := response.Marshal()
235 c.handleErrorResponse(err, writer)
239 c.logger.Infof("[E2 Manager -> Client] #NodebController.handleRequest - response: %s", result)
240 writer.Header().Set(ContentType, ApplicationJson)
241 writer.WriteHeader(successStatusCode)
245 func (c *NodebController) validateRequestHeader(header *http.Header) error {
247 if header.Get(ContentType) != ApplicationJson {
248 c.logger.Errorf("#NodebController.validateRequestHeader - validation failure, incorrect content type")
250 return e2managererrors.NewHeaderValidationError()
255 func (c *NodebController) handleErrorResponse(err error, writer http.ResponseWriter) {
257 var errorResponseDetails models.ErrorResponse
262 case *e2managererrors.RnibDbError:
263 e2Error, _ := err.(*e2managererrors.RnibDbError)
264 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
265 httpError = http.StatusInternalServerError
266 case *e2managererrors.CommandAlreadyInProgressError:
267 e2Error, _ := err.(*e2managererrors.CommandAlreadyInProgressError)
268 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
269 httpError = http.StatusMethodNotAllowed
270 case *e2managererrors.HeaderValidationError:
271 e2Error, _ := err.(*e2managererrors.HeaderValidationError)
272 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
273 httpError = http.StatusUnsupportedMediaType
274 case *e2managererrors.WrongStateError:
275 e2Error, _ := err.(*e2managererrors.WrongStateError)
276 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
277 httpError = http.StatusBadRequest
278 case *e2managererrors.RequestValidationError:
279 e2Error, _ := err.(*e2managererrors.RequestValidationError)
280 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
281 httpError = http.StatusBadRequest
282 case *e2managererrors.InvalidJsonError:
283 e2Error, _ := err.(*e2managererrors.InvalidJsonError)
284 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
285 httpError = http.StatusBadRequest
286 case *e2managererrors.RmrError:
287 e2Error, _ := err.(*e2managererrors.RmrError)
288 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
289 httpError = http.StatusInternalServerError
290 case *e2managererrors.ResourceNotFoundError:
291 e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
292 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
293 httpError = http.StatusNotFound
294 case *e2managererrors.E2TInstanceAbsenceError:
295 e2Error, _ := err.(*e2managererrors.E2TInstanceAbsenceError)
296 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
297 httpError = http.StatusServiceUnavailable
298 case *e2managererrors.RoutingManagerError:
299 e2Error, _ := err.(*e2managererrors.RoutingManagerError)
300 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
301 httpError = http.StatusServiceUnavailable
303 e2Error := e2managererrors.NewInternalError()
304 errorResponseDetails = models.ErrorResponse{Code: e2Error.Code, Message: e2Error.Message}
305 httpError = http.StatusInternalServerError
308 errorResponse, _ := json.Marshal(errorResponseDetails)
310 c.logger.Errorf("[E2 Manager -> Client] #NodebController.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
312 writer.Header().Set(ContentType, ApplicationJson)
313 writer.WriteHeader(httpError)
314 _, err = writer.Write(errorResponse)
317 func (c *NodebController) prettifyRequest(request *http.Request) string {
318 dump, _ := httputil.DumpRequest(request, true)
319 requestPrettyPrint := strings.Replace(string(dump), "\r\n", " ", -1)
320 return strings.Replace(requestPrettyPrint, "\n", "", -1)