blob: 4f785da4cb99c6a04ef9a4128b8b5a19c9fea449 [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/configuration"
22 "e2mgr/e2managererrors"
23 "e2mgr/logger"
24 "e2mgr/models"
is005q19e72a52019-08-26 17:56:18 +030025 "e2mgr/providers/httpmsghandlerprovider"
ss412g07ef76d2019-08-12 17:26:40 +030026 "e2mgr/rNibWriter"
rh362jf9e31bb2019-08-15 15:37:32 +030027 "e2mgr/services"
ss412g07ef76d2019-08-12 17:26:40 +030028 "encoding/json"
29 "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
30 "github.com/julienschmidt/httprouter"
31 "net/http"
32)
33
rh362jf9e31bb2019-08-15 15:37:32 +030034const (
35 ParamRanName = "ranName"
36)
is005q19e72a52019-08-26 17:56:18 +030037
ss412g07ef76d2019-08-12 17:26:40 +030038type Controller struct {
is005q19e72a52019-08-26 17:56:18 +030039 logger *logger.Logger
40 handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
ss412g07ef76d2019-08-12 17:26:40 +030041}
42
rh362jf9e31bb2019-08-15 15:37:32 +030043func NewController(logger *logger.Logger, rmrService *services.RmrService, rNibReaderProvider func() reader.RNibReader, rNibWriterProvider func() rNibWriter.RNibWriter,
irinad6deb7f2019-08-16 00:14:51 +030044 config *configuration.Configuration) *Controller {
ss412g07ef76d2019-08-12 17:26:40 +030045
is005q19e72a52019-08-26 17:56:18 +030046 provider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrService, config, rNibWriterProvider, rNibReaderProvider)
ss412g07ef76d2019-08-12 17:26:40 +030047 return &Controller{
is005q19e72a52019-08-26 17:56:18 +030048 logger: logger,
ss412g07ef76d2019-08-12 17:26:40 +030049 handlerProvider: provider,
ss412g07ef76d2019-08-12 17:26:40 +030050 }
51}
52
is005q19e72a52019-08-26 17:56:18 +030053func (c *Controller) ShutdownHandler(writer http.ResponseWriter, r *http.Request, params httprouter.Params) {
rh362j574c21e2019-08-19 15:25:50 +030054 c.logger.Infof("[Client -> E2 Manager] #controller.ShutdownHandler - request: %v", prettifyRequest(r))
is005q19e72a52019-08-26 17:56:18 +030055 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false, http.StatusNoContent)
ss412g07ef76d2019-08-12 17:26:40 +030056}
57
is005q19e72a52019-08-26 17:56:18 +030058func (c *Controller) X2ResetHandler(writer http.ResponseWriter, r *http.Request, params httprouter.Params) {
rh362j574c21e2019-08-19 15:25:50 +030059 c.logger.Infof("[Client -> E2 Manager] #controller.X2ResetHandler - request: %v", prettifyRequest(r))
is005q19e72a52019-08-26 17:56:18 +030060 request := models.ResetRequest{}
61 ranName := params.ByName(ParamRanName)
rh362j574c21e2019-08-19 15:25:50 +030062
is005q19e72a52019-08-26 17:56:18 +030063 if !c.extractJsonBody(r, &request, writer) {
rh362jf9e31bb2019-08-15 15:37:32 +030064 return
65 }
66 request.RanName = ranName
is005q19e72a52019-08-26 17:56:18 +030067 c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false, http.StatusNoContent)
rh362jf9e31bb2019-08-15 15:37:32 +030068}
69
is005q19e72a52019-08-26 17:56:18 +030070func (c *Controller) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
rh362j574c21e2019-08-19 15:25:50 +030071 if r.ContentLength <= 0 {
72 return true
73 }
74
75 decoder := json.NewDecoder(r.Body)
76 if err := decoder.Decode(request); err != nil {
rh362jf9e31bb2019-08-15 15:37:32 +030077 if err != nil {
78 c.logger.Errorf("[Client -> E2 Manager] #controller.extractJsonBody - unable to extract json body - error: %s", err)
rh362j549944e2019-08-25 12:56:55 +030079 c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
rh362jf9e31bb2019-08-15 15:37:32 +030080 return false
81 }
82 }
rh362j574c21e2019-08-19 15:25:50 +030083
rh362jf9e31bb2019-08-15 15:37:32 +030084 return true
85}
86
is005q19e72a52019-08-26 17:56:18 +030087func (c *Controller) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest,
rh362jf9e31bb2019-08-15 15:37:32 +030088 request models.Request, validateHeader bool, httpStatusResponse int) {
ss412g07ef76d2019-08-12 17:26:40 +030089
ss412g07ef76d2019-08-12 17:26:40 +030090 if validateHeader {
91
92 err := c.validateRequestHeader(header)
93 if err != nil {
94 c.handleErrorResponse(err, writer)
95 return
96 }
97 }
98
is005q19e72a52019-08-26 17:56:18 +030099 handler, err := c.handlerProvider.GetHandler(requestName)
ss412g07ef76d2019-08-12 17:26:40 +0300100 if err != nil {
101 c.handleErrorResponse(err, writer)
102 return
103 }
104
irinad6deb7f2019-08-16 00:14:51 +0300105 err = handler.Handle(c.logger, request)
ss412g07ef76d2019-08-12 17:26:40 +0300106
107 if err != nil {
108 c.handleErrorResponse(err, writer)
109 return
110 }
111
112 writer.WriteHeader(httpStatusResponse)
113 c.logger.Infof("[E2 Manager -> Client] #controller.handleRequest - status response: %v", httpStatusResponse)
114}
115
is005q19e72a52019-08-26 17:56:18 +0300116func (c *Controller) validateRequestHeader(header *http.Header) error {
ss412g07ef76d2019-08-12 17:26:40 +0300117
is005q19e72a52019-08-26 17:56:18 +0300118 if header.Get("Content-Type") != "application/json" {
ss412g07ef76d2019-08-12 17:26:40 +0300119 c.logger.Errorf("#controller.validateRequestHeader - validation failure, incorrect content type")
120
is005q19e72a52019-08-26 17:56:18 +0300121 return e2managererrors.NewHeaderValidationError()
ss412g07ef76d2019-08-12 17:26:40 +0300122 }
123 return nil
124}
125
is005q19e72a52019-08-26 17:56:18 +0300126func (c *Controller) handleErrorResponse(err error, writer http.ResponseWriter) {
ss412g07ef76d2019-08-12 17:26:40 +0300127
128 var errorResponseDetails models.ErrorResponse
129 var httpError int
130
131 if err != nil {
132 switch err.(type) {
133 case *e2managererrors.RnibDbError:
134 e2Error, _ := err.(*e2managererrors.RnibDbError)
135 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
136 httpError = http.StatusInternalServerError
137 case *e2managererrors.CommandAlreadyInProgressError:
138 e2Error, _ := err.(*e2managererrors.CommandAlreadyInProgressError)
139 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
140 httpError = http.StatusMethodNotAllowed
141 case *e2managererrors.HeaderValidationError:
142 e2Error, _ := err.(*e2managererrors.HeaderValidationError)
143 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
144 httpError = http.StatusUnsupportedMediaType
rh362jf9e31bb2019-08-15 15:37:32 +0300145 case *e2managererrors.WrongStateError:
146 e2Error, _ := err.(*e2managererrors.WrongStateError)
147 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
148 httpError = http.StatusBadRequest
149 case *e2managererrors.RequestValidationError:
150 e2Error, _ := err.(*e2managererrors.RequestValidationError)
151 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
152 httpError = http.StatusBadRequest
rh362j549944e2019-08-25 12:56:55 +0300153 case *e2managererrors.InvalidJsonError:
154 e2Error, _ := err.(*e2managererrors.InvalidJsonError)
155 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
156 httpError = http.StatusBadRequest
rh362jf9e31bb2019-08-15 15:37:32 +0300157 case *e2managererrors.RmrError:
158 e2Error, _ := err.(*e2managererrors.RmrError)
159 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
160 httpError = http.StatusInternalServerError
rh362ja2533f22019-08-15 22:24:32 +0300161 case *e2managererrors.ResourceNotFoundError:
162 e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
163 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
164 httpError = http.StatusNotFound
rh362jf9e31bb2019-08-15 15:37:32 +0300165
ss412g07ef76d2019-08-12 17:26:40 +0300166 default:
rh362j574c21e2019-08-19 15:25:50 +0300167 e2Error := e2managererrors.NewInternalError()
ss412g07ef76d2019-08-12 17:26:40 +0300168 errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
169 httpError = http.StatusInternalServerError
170 }
171 }
172 errorResponse, _ := json.Marshal(errorResponseDetails)
173
174 c.logger.Errorf("[E2 Manager -> Client] #controller.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
175
176 writer.Header().Set("Content-Type", "application/json")
177 writer.WriteHeader(httpError)
178 _, err = writer.Write(errorResponse)
179
180 if err != nil {
181 c.logger.Errorf("#controller.handleErrorResponse - Cannot send response. writer:%v", writer)
182 }
is005q19e72a52019-08-26 17:56:18 +0300183}