Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2020 AT&T Intellectual Property. |
| 3 | * Copyright (c) 2020 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 | * This source code is part of the near-RT RIC (RAN Intelligent Controller) |
| 18 | * platform project (RICP). |
| 19 | */ |
| 20 | |
| 21 | package main |
| 22 | |
| 23 | import ( |
| 24 | "encoding/json" |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 25 | "gerrit.o-ran-sc.org/r/ric-plt/alarm-go/alarm" |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 26 | app "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp" |
vipin | 54a3a4f | 2020-09-23 12:19:58 +0000 | [diff] [blame] | 27 | "github.com/gorilla/mux" |
| 28 | "net/http" |
| 29 | "strconv" |
| 30 | "time" |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 31 | ) |
| 32 | |
vipin | 54a3a4f | 2020-09-23 12:19:58 +0000 | [diff] [blame] | 33 | func (a *AlarmManager) respondWithError(w http.ResponseWriter, code int, message string) { |
| 34 | a.respondWithJSON(w, code, map[string]string{"error": message}) |
| 35 | } |
| 36 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 37 | func (a *AlarmManager) respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 38 | w.Header().Set("Content-Type", "application/json") |
| 39 | w.WriteHeader(code) |
| 40 | if payload != nil { |
| 41 | response, _ := json.Marshal(payload) |
| 42 | w.Write(response) |
| 43 | } |
| 44 | } |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 45 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 46 | func (a *AlarmManager) GetActiveAlarms(w http.ResponseWriter, r *http.Request) { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 47 | app.Logger.Info("GetActiveAlarms: %+v", a.activeAlarms) |
| 48 | a.respondWithJSON(w, http.StatusOK, a.activeAlarms) |
| 49 | } |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 50 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 51 | func (a *AlarmManager) GetAlarmHistory(w http.ResponseWriter, r *http.Request) { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 52 | app.Logger.Info("GetAlarmHistory: %+v", a.alarmHistory) |
| 53 | a.respondWithJSON(w, http.StatusOK, a.alarmHistory) |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 54 | } |
| 55 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 56 | func (a *AlarmManager) RaiseAlarm(w http.ResponseWriter, r *http.Request) { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 57 | if err := a.doAction(w, r, true); err != nil { |
| 58 | a.respondWithJSON(w, http.StatusOK, err) |
| 59 | } |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 60 | } |
| 61 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 62 | func (a *AlarmManager) ClearAlarm(w http.ResponseWriter, r *http.Request) { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 63 | if err := a.doAction(w, r, false); err != nil { |
| 64 | a.respondWithJSON(w, http.StatusOK, err) |
| 65 | } |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 66 | } |
| 67 | |
vipin | 54a3a4f | 2020-09-23 12:19:58 +0000 | [diff] [blame] | 68 | func (a *AlarmManager) SetAlarmDefinition(w http.ResponseWriter, r *http.Request) { |
| 69 | |
| 70 | app.Logger.Debug("POST arrived for creating alarm definition ") |
| 71 | /* If body is nil then return error */ |
| 72 | if r.Body == nil { |
| 73 | app.Logger.Error("POST - body is empty") |
| 74 | a.respondWithError(w, http.StatusBadRequest, "No data in request body.") |
| 75 | return |
| 76 | } |
| 77 | defer r.Body.Close() |
| 78 | |
| 79 | /* Parameters are available. Check if they are valid */ |
| 80 | var alarmDefinitions RicAlarmDefinitions |
| 81 | err := json.NewDecoder(r.Body).Decode(&alarmDefinitions) |
| 82 | if err != nil { |
| 83 | app.Logger.Error("POST - received alarm definition parameters are invalid - " + err.Error()) |
| 84 | a.respondWithError(w, http.StatusBadRequest, "Invalid data in request body.") |
| 85 | return |
| 86 | } |
| 87 | |
| 88 | for _, alarmDefinition := range alarmDefinitions.AlarmDefinitions { |
| 89 | _, exists := alarm.RICAlarmDefinitions[alarmDefinition.AlarmId] |
| 90 | if exists { |
| 91 | app.Logger.Error("POST - alarm definition already exists for %v", alarmDefinition.AlarmId) |
| 92 | } else { |
| 93 | ricAlarmDefintion := new(alarm.AlarmDefinition) |
| 94 | ricAlarmDefintion.AlarmId = alarmDefinition.AlarmId |
| 95 | ricAlarmDefintion.AlarmText = alarmDefinition.AlarmText |
| 96 | ricAlarmDefintion.EventType = alarmDefinition.EventType |
| 97 | ricAlarmDefintion.OperationInstructions = alarmDefinition.OperationInstructions |
| 98 | alarm.RICAlarmDefinitions[alarmDefinition.AlarmId] = ricAlarmDefintion |
vipin | 6f73fa3 | 2020-10-06 06:51:53 +0000 | [diff] [blame] | 99 | app.Logger.Debug("POST - alarm definition added for alarm id %v", alarmDefinition.AlarmId) |
vipin | 54a3a4f | 2020-09-23 12:19:58 +0000 | [diff] [blame] | 100 | } |
| 101 | } |
| 102 | |
| 103 | a.respondWithJSON(w, http.StatusOK, nil) |
| 104 | return |
| 105 | } |
| 106 | |
| 107 | func (a *AlarmManager) DeleteAlarmDefinition(w http.ResponseWriter, r *http.Request) { |
| 108 | pathParams := mux.Vars(r) |
| 109 | alarmId, alarmIdok := pathParams["alarmId"] |
| 110 | if alarmIdok { |
| 111 | if ialarmId, err := strconv.Atoi(alarmId); err == nil { |
| 112 | delete(alarm.RICAlarmDefinitions, ialarmId) |
vipin | 4cedd50 | 2020-09-25 05:58:31 +0000 | [diff] [blame] | 113 | app.Logger.Debug("DELETE - alarm definition deleted for alarmId %v", ialarmId) |
vipin | 54a3a4f | 2020-09-23 12:19:58 +0000 | [diff] [blame] | 114 | } else { |
| 115 | app.Logger.Error("DELETE - alarmId string to int conversion failed %v", alarmId) |
| 116 | a.respondWithError(w, http.StatusBadRequest, "Invalid path parameter") |
| 117 | return |
| 118 | } |
| 119 | } else { |
| 120 | app.Logger.Error("DELETE - alarmId does not exist %v", alarmId) |
| 121 | a.respondWithError(w, http.StatusBadRequest, "Invalid path parameter") |
| 122 | return |
| 123 | |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | func (a *AlarmManager) GetAlarmDefinition(w http.ResponseWriter, r *http.Request) { |
| 128 | var ricAlarmDefinitions RicAlarmDefinitions |
| 129 | pathParams := mux.Vars(r) |
| 130 | alarmId, alarmIdok := pathParams["alarmId"] |
| 131 | if alarmIdok { |
| 132 | if ialarmId, err := strconv.Atoi(alarmId); err == nil { |
| 133 | alarmDefinition, ok := alarm.RICAlarmDefinitions[ialarmId] |
| 134 | if ok { |
| 135 | app.Logger.Debug("Successfully returned alarm defintion for alarm id %v", ialarmId) |
| 136 | a.respondWithJSON(w, http.StatusOK, alarmDefinition) |
| 137 | return |
| 138 | |
| 139 | } else { |
| 140 | app.Logger.Error("Requested alarm id not found %v", ialarmId) |
| 141 | a.respondWithError(w, http.StatusBadRequest, "Non existent alarmId") |
| 142 | return |
| 143 | } |
| 144 | } else { |
| 145 | app.Logger.Error("alarmId string to int conversion failed %v", alarmId) |
| 146 | a.respondWithError(w, http.StatusBadRequest, "Invalid alarmId") |
| 147 | return |
| 148 | } |
| 149 | } else { |
| 150 | app.Logger.Debug("GET arrived for all alarm definitions ") |
| 151 | for _, alarmDefinition := range alarm.RICAlarmDefinitions { |
| 152 | ricAlarmDefinitions.AlarmDefinitions = append(ricAlarmDefinitions.AlarmDefinitions, alarmDefinition) |
| 153 | } |
| 154 | app.Logger.Debug("Successfully returned all alarm definitions") |
| 155 | a.respondWithJSON(w, http.StatusOK, ricAlarmDefinitions) |
| 156 | } |
| 157 | } |
| 158 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 159 | func (a *AlarmManager) doAction(w http.ResponseWriter, r *http.Request, isRaiseAlarm bool) error { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 160 | app.Logger.Info("doAction: request received = %t", isRaiseAlarm) |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 161 | |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 162 | if r.Body == nil { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 163 | app.Logger.Error("Error: Invalid message body!") |
| 164 | return nil |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 165 | } |
| 166 | defer r.Body.Close() |
| 167 | |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 168 | var m alarm.AlarmMessage |
| 169 | if err := json.NewDecoder(r.Body).Decode(&m); err != nil { |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 170 | app.Logger.Error("json.NewDecoder failed: %v", err) |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 171 | return err |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 172 | } |
| 173 | |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 174 | if m.Alarm.ManagedObjectId == "" || m.Alarm.ApplicationId == "" || m.AlarmAction == "" { |
| 175 | app.Logger.Error("Error: Mandatory parameters missing!") |
| 176 | return nil |
| 177 | } |
| 178 | |
| 179 | if m.AlarmTime == 0 { |
Anssi Mannila | 2be5ac5 | 2020-09-22 12:17:05 +0300 | [diff] [blame] | 180 | m.AlarmTime = time.Now().UnixNano() |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | _, err := a.ProcessAlarm(&m) |
| 184 | return err |
| 185 | } |
| 186 | |
Abukar Mohamed | 121e8b6 | 2020-09-18 11:41:33 +0000 | [diff] [blame] | 187 | func (a *AlarmManager) HandleViaRmr(d alarm.Alarm, isRaiseAlarm bool) error { |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 188 | alarmClient, err := alarm.InitAlarm(d.ManagedObjectId, d.ApplicationId) |
| 189 | if err != nil { |
| 190 | app.Logger.Error("json.NewDecoder failed: %v", err) |
| 191 | return err |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | alarmData := alarmClient.NewAlarm(d.SpecificProblem, d.PerceivedSeverity, d.AdditionalInfo, d.IdentifyingInfo) |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 195 | if isRaiseAlarm { |
Mohamed Abukar | af0c570 | 2020-03-11 10:29:40 +0200 | [diff] [blame] | 196 | alarmClient.Raise(alarmData) |
| 197 | } else { |
| 198 | alarmClient.Clear(alarmData) |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 199 | } |
Mohamed Abukar | 540ceee | 2020-09-09 08:07:40 +0300 | [diff] [blame] | 200 | |
| 201 | return nil |
Mohamed Abukar | 61bdef5 | 2020-03-09 16:46:12 +0200 | [diff] [blame] | 202 | } |
vipin | 541eb50 | 2020-09-22 12:04:59 +0000 | [diff] [blame] | 203 | |
| 204 | func (a *AlarmManager) SetAlarmConfig(w http.ResponseWriter, r *http.Request) { |
| 205 | var m alarm.AlarmConfigParams |
| 206 | if err := json.NewDecoder(r.Body).Decode(&m); err != nil { |
| 207 | app.Logger.Error("json.NewDecoder failed: %v", err) |
| 208 | } else { |
| 209 | a.maxActiveAlarms = m.MaxActiveAlarms |
| 210 | a.maxAlarmHistory = m.MaxAlarmHistory |
| 211 | app.Logger.Debug("new maxActiveAlarms = %v", a.maxActiveAlarms) |
| 212 | app.Logger.Debug("new maxAlarmHistory = %v", a.maxAlarmHistory) |
| 213 | a.respondWithJSON(w, http.StatusOK, err) |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | func (a *AlarmManager) GetAlarmConfig(w http.ResponseWriter, r *http.Request) { |
| 218 | var m alarm.AlarmConfigParams |
| 219 | |
| 220 | m.MaxActiveAlarms = a.maxActiveAlarms |
| 221 | m.MaxAlarmHistory = a.maxAlarmHistory |
| 222 | |
| 223 | a.respondWithJSON(w, http.StatusOK, m) |
| 224 | return |
| 225 | } |