blob: 40ad8d24d1f098b58fffa98f6c654cfa70063d4a [file] [log] [blame]
Mohamed Abukar2e78e422019-06-02 11:45:52 +03001/*
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 (
23 "encoding/json"
Mohamed Abukar0ce03382021-02-24 10:52:25 +020024 "fmt"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030025 "github.com/gorilla/mux"
wahidw413abf52020-12-15 12:17:09 +000026 "github.com/spf13/viper"
Mohamed Abukarf4668932020-09-15 09:40:07 +030027 "io/ioutil"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030028 "net/http"
wahidw413abf52020-12-15 12:17:09 +000029 "os"
30
31 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030032)
33
34const (
wahidw413abf52020-12-15 12:17:09 +000035 ReadyURL = "/ric/v1/health/ready"
36 AliveURL = "/ric/v1/health/alive"
37 ConfigURL = "/ric/v1/cm/{name}"
38 AppConfigURL = "/ric/v1/config"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030039)
40
Mohamed Abukar256c3042020-12-30 17:48:12 +020041var (
42 healthReady bool
43)
44
Mohamed Abukar2e78e422019-06-02 11:45:52 +030045type StatusCb func() bool
46
47type Router struct {
48 router *mux.Router
49 cbMap []StatusCb
50}
51
52func NewRouter() *Router {
53 r := &Router{
54 router: mux.NewRouter().StrictSlash(true),
55 cbMap: make([]StatusCb, 0),
56 }
57
58 // Inject default routes for health probes
59 r.InjectRoute(ReadyURL, readyHandler, "GET")
60 r.InjectRoute(AliveURL, aliveHandler, "GET")
Mohamed Abukarf4668932020-09-15 09:40:07 +030061 r.InjectRoute(ConfigURL, configHandler, "POST")
wahidw413abf52020-12-15 12:17:09 +000062 r.InjectRoute(AppConfigURL, appconfigHandler, "GET")
Mohamed Abukar2e78e422019-06-02 11:45:52 +030063
64 return r
65}
66
67func (r *Router) serviceChecker(inner http.HandlerFunc) http.HandlerFunc {
68 return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
69 Logger.Info("restapi: method=%s url=%s", req.Method, req.URL.RequestURI())
Mohamed Abukar9cfde092020-04-28 17:11:33 +030070 if req.URL.RequestURI() == AliveURL || r.CheckStatus() {
Mohamed Abukar2e78e422019-06-02 11:45:52 +030071 inner.ServeHTTP(w, req)
72 } else {
73 respondWithJSON(w, http.StatusServiceUnavailable, nil)
74 }
75 })
76}
77
78func (r *Router) InjectRoute(url string, handler http.HandlerFunc, method string) *mux.Route {
Juha Hyttinen5bd72732020-08-14 11:38:06 +030079 return r.router.Path(url).HandlerFunc(r.serviceChecker(handler)).Methods(method)
Mohamed Abukar2e78e422019-06-02 11:45:52 +030080}
81
82func (r *Router) InjectQueryRoute(url string, h http.HandlerFunc, m string, q ...string) *mux.Route {
Juha Hyttinen5bd72732020-08-14 11:38:06 +030083 return r.router.Path(url).HandlerFunc(r.serviceChecker(h)).Methods(m).Queries(q...)
84}
85
86func (r *Router) InjectRoutePrefix(prefix string, handler http.HandlerFunc) *mux.Route {
87 return r.router.PathPrefix(prefix).HandlerFunc(r.serviceChecker(handler))
Mohamed Abukar2e78e422019-06-02 11:45:52 +030088}
89
90func (r *Router) InjectStatusCb(f StatusCb) {
91 r.cbMap = append(r.cbMap, f)
92}
93
94func (r *Router) CheckStatus() (status bool) {
95 if len(r.cbMap) == 0 {
96 return true
97 }
98
99 for _, f := range r.cbMap {
100 status = f()
101 }
102 return
103}
104
Mohamed Abukar0ce03382021-02-24 10:52:25 +0200105func (r *Router) GetSymptomDataParams(w http.ResponseWriter, req *http.Request) SymptomDataParams {
106 params := SymptomDataParams{}
107 queryParams := req.URL.Query()
108
109 for p := range queryParams {
110 if p == "timeout" {
111 fmt.Sscanf(p, "%d", &params.Timeout)
112 }
113 if p == "fromtime" {
114 fmt.Sscanf(p, "%d", &params.FromTime)
115 }
116 if p == "totime" {
117 fmt.Sscanf(p, "%d", &params.ToTime)
118 }
119 }
120 return params
121}
122
123func (r *Router) SendSymptomDataJson(w http.ResponseWriter, req *http.Request, data interface{}, n string) {
124 w.Header().Set("Content-Type", "application/json")
125 w.Header().Set("Content-Disposition", "attachment; filename="+n)
126 w.WriteHeader(http.StatusOK)
127 if data != nil {
128 response, _ := json.Marshal(data)
129 w.Write(response)
130 }
131}
132
133func (r *Router) SendSymptomDataFile(w http.ResponseWriter, req *http.Request, baseDir, zipFile string) {
134 // Compress and reply with attachment
135 tmpFile, err := ioutil.TempFile("", "symptom")
136 if err != nil {
137 r.SendSymptomDataError(w, req, "Failed to create a tmp file: "+err.Error())
138 return
139 }
140 defer os.Remove(tmpFile.Name())
141
142 var fileList []string
143 fileList = Util.FetchFiles(baseDir, fileList)
144 err = Util.ZipFiles(tmpFile, baseDir, fileList)
145 if err != nil {
146 r.SendSymptomDataError(w, req, "Failed to zip the files: "+err.Error())
147 return
148 }
149
150 w.Header().Set("Content-Disposition", "attachment; filename="+zipFile)
151 http.ServeFile(w, req, tmpFile.Name())
152}
153
154func (r *Router) SendSymptomDataError(w http.ResponseWriter, req *http.Request, message string) {
155 w.Header().Set("Content-Disposition", "attachment; filename=error_status.txt")
156 http.Error(w, message, http.StatusInternalServerError)
157}
158
Mohamed Abukar256c3042020-12-30 17:48:12 +0200159func IsHealthProbeReady() bool {
160 return healthReady
161}
162
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300163func readyHandler(w http.ResponseWriter, r *http.Request) {
Mohamed Abukar256c3042020-12-30 17:48:12 +0200164 healthReady = true
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300165 respondWithJSON(w, http.StatusOK, nil)
166}
167
168func aliveHandler(w http.ResponseWriter, r *http.Request) {
169 respondWithJSON(w, http.StatusOK, nil)
170}
171
Mohamed Abukarf4668932020-09-15 09:40:07 +0300172func configHandler(w http.ResponseWriter, r *http.Request) {
173 xappName := mux.Vars(r)["name"]
174 if xappName == "" || r.Body == nil {
175 respondWithJSON(w, http.StatusBadRequest, nil)
176 return
177 }
178 defer r.Body.Close()
179
180 body, err := ioutil.ReadAll(r.Body)
181 if err != nil {
182 Logger.Error("ioutil.ReadAll failed: %v", err)
183 respondWithJSON(w, http.StatusInternalServerError, nil)
184 return
185 }
186
187 if err := PublishConfigChange(xappName, string(body)); err != nil {
188 respondWithJSON(w, http.StatusInternalServerError, nil)
189 return
190 }
191
192 respondWithJSON(w, http.StatusOK, nil)
193}
194
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300195func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
196 w.Header().Set("Content-Type", "application/json")
197 w.WriteHeader(code)
198 if payload != nil {
199 response, _ := json.Marshal(payload)
200 w.Write(response)
201 }
202}
wahidw413abf52020-12-15 12:17:09 +0000203
204func appconfigHandler(w http.ResponseWriter, r *http.Request) {
205
206 Logger.Info("Inside appconfigHandler")
207
208 var appconfig models.XappConfigList
209 var metadata models.ConfigMetadata
210 var xappconfig models.XAppConfig
211 name := viper.GetString("name")
212 configtype := "json"
213 metadata.XappName = &name
214 metadata.ConfigType = &configtype
215
216 configFile, err := os.Open("/opt/ric/config/config-file.json")
217 if err != nil {
218 Logger.Error("Cannot open config file: %v", err)
219 respondWithJSON(w, http.StatusInternalServerError, nil)
220 // return nil,errors.New("Could Not parse the config file")
221 }
222
223 body, err := ioutil.ReadAll(configFile)
224
225 defer configFile.Close()
226
227 xappconfig.Metadata = &metadata
228 xappconfig.Config = string(body)
229
230 appconfig = append(appconfig, &xappconfig)
231
232 respondWithJSON(w, http.StatusOK, appconfig)
233
234 //return appconfig,nil
235}