x2_reset_response.go was added
[ric-plt/e2mgr.git] / E2Manager / controllers / controller.go
1 //
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
18 package controllers
19
20 import (
21         "e2mgr/configuration"
22         "e2mgr/e2managererrors"
23         "e2mgr/logger"
24         "e2mgr/models"
25         "e2mgr/providers/httpmsghandlerprovider"
26         "e2mgr/rNibWriter"
27         "e2mgr/services"
28         "encoding/json"
29         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader"
30         "github.com/gorilla/mux"
31         "net/http"
32 )
33
34 const (
35         ParamRanName = "ranName"
36 )
37
38 type IController interface {
39         ShutdownHandler(writer http.ResponseWriter, r *http.Request)
40         X2ResetHandler(writer http.ResponseWriter, r *http.Request)
41 }
42
43 type Controller struct {
44         logger          *logger.Logger
45         handlerProvider *httpmsghandlerprovider.IncomingRequestHandlerProvider
46 }
47
48 func NewController(logger *logger.Logger, rmrService *services.RmrService, rNibReaderProvider func() reader.RNibReader, rNibWriterProvider func() rNibWriter.RNibWriter,
49         config *configuration.Configuration) *Controller {
50
51         provider := httpmsghandlerprovider.NewIncomingRequestHandlerProvider(logger, rmrService, config, rNibWriterProvider, rNibReaderProvider)
52         return &Controller{
53                 logger:          logger,
54                 handlerProvider: provider,
55         }
56 }
57
58 func (c *Controller) ShutdownHandler(writer http.ResponseWriter, r *http.Request) {
59         c.logger.Infof("[Client -> E2 Manager] #controller.ShutdownHandler - request: %v", prettifyRequest(r))
60         c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false, http.StatusNoContent)
61 }
62
63 func (c *Controller) X2ResetHandler(writer http.ResponseWriter, r *http.Request) {
64         c.logger.Infof("[Client -> E2 Manager] #controller.X2ResetHandler - request: %v", prettifyRequest(r))
65         request := models.ResetRequest{}
66         vars := mux.Vars(r)
67         ranName := vars[ParamRanName]
68
69         if !c.extractJsonBody(r, &request, writer) {
70                 return
71         }
72         request.RanName = ranName
73         c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ResetRequest, request, false, http.StatusNoContent)
74 }
75
76 func (c *Controller) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
77         if r.ContentLength <= 0 {
78                 return true
79         }
80
81         decoder := json.NewDecoder(r.Body)
82         if err := decoder.Decode(request); err != nil {
83                 if err != nil {
84                         c.logger.Errorf("[Client -> E2 Manager] #controller.extractJsonBody - unable to extract json body - error: %s", err)
85                         c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
86                         return false
87                 }
88         }
89
90         return true
91 }
92
93 func (c *Controller) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest,
94         request models.Request, validateHeader bool, httpStatusResponse int) {
95
96         if validateHeader {
97
98                 err := c.validateRequestHeader(header)
99                 if err != nil {
100                         c.handleErrorResponse(err, writer)
101                         return
102                 }
103         }
104
105         handler, err := c.handlerProvider.GetHandler(requestName)
106         if err != nil {
107                 c.handleErrorResponse(err, writer)
108                 return
109         }
110
111         err = handler.Handle(c.logger, request)
112
113         if err != nil {
114                 c.handleErrorResponse(err, writer)
115                 return
116         }
117
118         writer.WriteHeader(httpStatusResponse)
119         c.logger.Infof("[E2 Manager -> Client] #controller.handleRequest - status response: %v", httpStatusResponse)
120 }
121
122 func (c *Controller) validateRequestHeader(header *http.Header) error {
123
124         if header.Get("Content-Type") != "application/json" {
125                 c.logger.Errorf("#controller.validateRequestHeader - validation failure, incorrect content type")
126
127                 return e2managererrors.NewHeaderValidationError()
128         }
129         return nil
130 }
131
132 func (c *Controller) handleErrorResponse(err error, writer http.ResponseWriter) {
133
134         var errorResponseDetails models.ErrorResponse
135         var httpError int
136
137         if err != nil {
138                 switch err.(type) {
139                 case *e2managererrors.RnibDbError:
140                         e2Error, _ := err.(*e2managererrors.RnibDbError)
141                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
142                         httpError = http.StatusInternalServerError
143                 case *e2managererrors.CommandAlreadyInProgressError:
144                         e2Error, _ := err.(*e2managererrors.CommandAlreadyInProgressError)
145                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
146                         httpError = http.StatusMethodNotAllowed
147                 case *e2managererrors.HeaderValidationError:
148                         e2Error, _ := err.(*e2managererrors.HeaderValidationError)
149                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
150                         httpError = http.StatusUnsupportedMediaType
151                 case *e2managererrors.WrongStateError:
152                         e2Error, _ := err.(*e2managererrors.WrongStateError)
153                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
154                         httpError = http.StatusBadRequest
155                 case *e2managererrors.RequestValidationError:
156                         e2Error, _ := err.(*e2managererrors.RequestValidationError)
157                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
158                         httpError = http.StatusBadRequest
159                 case *e2managererrors.InvalidJsonError:
160                         e2Error, _ := err.(*e2managererrors.InvalidJsonError)
161                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
162                         httpError = http.StatusBadRequest
163                 case *e2managererrors.RmrError:
164                         e2Error, _ := err.(*e2managererrors.RmrError)
165                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
166                         httpError = http.StatusInternalServerError
167                 case *e2managererrors.ResourceNotFoundError:
168                         e2Error, _ := err.(*e2managererrors.ResourceNotFoundError)
169                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
170                         httpError = http.StatusNotFound
171
172                 default:
173                         e2Error := e2managererrors.NewInternalError()
174                         errorResponseDetails = models.ErrorResponse{Code: e2Error.Err.Code, Message: e2Error.Err.Message}
175                         httpError = http.StatusInternalServerError
176                 }
177         }
178         errorResponse, _ := json.Marshal(errorResponseDetails)
179
180         c.logger.Errorf("[E2 Manager -> Client] #controller.handleErrorResponse - http status: %d, error response: %+v", httpError, errorResponseDetails)
181
182         writer.Header().Set("Content-Type", "application/json")
183         writer.WriteHeader(httpError)
184         _, err = writer.Write(errorResponse)
185
186         if err != nil {
187                 c.logger.Errorf("#controller.handleErrorResponse - Cannot send response. writer:%v", writer)
188         }
189 }