Add supoprt for D release use-case.
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / faults / faults_ves.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
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 #define _GNU_SOURCE
19
20 #include "faults.h"
21 #include "utils/log_utils.h"
22 #include "utils/rand_utils.h"
23 #include "utils/nts_utils.h"
24 #include "utils/sys_utils.h"
25 #include "utils/http_client.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29
30 #include "core/framework.h"
31 #include <cjson/cJSON.h>
32
33 static uint32_t *fault_ves_sequence_number = 0;
34
35 static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *alarm_object, const char *severity, const char *date_time, const char *specific_problem);
36 static int ves_message_send_internal(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem, int port, uint32_t *seq_id);
37
38 int faults_ves_init(void) {
39     fault_ves_sequence_number = (uint32_t *)malloc(sizeof(uint32_t) * (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections));
40     if(fault_ves_sequence_number == 0) {
41         log_error("malloc failed\n");
42         return NTS_ERR_FAILED; 
43     }
44
45     for(int i = 0; i < (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections); i++) {
46         fault_ves_sequence_number[i] = 0;
47     }
48
49     return NTS_ERR_OK;
50 }
51
52 void faults_ves_free(void) {
53     free(fault_ves_sequence_number);
54     fault_ves_sequence_number = 0;
55 }
56
57 int faults_ves_message_send(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem) {
58     assert(condition);
59     assert(object);
60     assert(severity);
61     assert(date_time);
62     assert(specific_problem);
63
64     int sequence_index = 0;
65     int ssh_base_port = 0;
66     int tls_base_port = 0;
67     nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(session);
68     if(mp == UNKNOWN_MAPPING) {
69         log_error("mount-point-addressing-method failed\n");
70         return NTS_ERR_FAILED;
71     }
72     else if(mp == DOCKER_MAPPING) {
73         ssh_base_port = STANDARD_NETCONF_PORT;
74         tls_base_port = ssh_base_port + framework_environment.settings.ssh_connections;
75     }
76     else {
77         ssh_base_port = framework_environment.host.ssh_base_port;
78         tls_base_port = framework_environment.host.tls_base_port;       
79     }
80
81     for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
82         uint32_t *seq_id = &fault_ves_sequence_number[sequence_index++];
83         int rc = ves_message_send_internal(session, condition, object, severity, date_time, specific_problem, port, seq_id);
84         if(rc != NTS_ERR_OK) {
85             log_error("ves_message_send_internal failed\n");
86         }
87     }
88
89     for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
90         uint32_t *seq_id = &fault_ves_sequence_number[sequence_index++];
91         int rc = ves_message_send_internal(session, condition, object, severity, date_time, specific_problem, port, seq_id);
92         if(rc != NTS_ERR_OK) {
93             log_error("ves_message_send_internal failed\n");
94         }
95     }
96
97     return NTS_ERR_OK;
98 }
99
100 static cJSON *ves_create_fault_fields(const char *alarm_condition, const char *alarm_object, const char *severity, const char *date_time, const char *specific_problem) {
101     assert(alarm_condition);
102     assert(alarm_object);
103     assert(severity);
104     assert(date_time);
105     assert(specific_problem);
106     
107     cJSON *faultFields = cJSON_CreateObject();
108     if(faultFields == 0) {
109         log_error("could not create JSON object: faultFields\n");
110         return 0;
111     }
112
113     if(cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == 0) {
114         log_error("could not create JSON object: faultFieldsVersion\n");
115         cJSON_Delete(faultFields);
116         return 0;
117     }
118
119     if(cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == 0) {
120         log_error("could not create JSON object: alarmCondition\n");
121         cJSON_Delete(faultFields);
122         return 0;
123     }
124
125     if(cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == 0) {
126         log_error("could not create JSON object: alarmInterfaceA\n");
127         cJSON_Delete(faultFields);
128         return 0;
129     }
130
131     if(cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == 0) {
132         log_error("could not create JSON object: eventSourceType\n");
133         cJSON_Delete(faultFields);
134         return 0;
135     }
136
137     if(cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == 0) {
138         log_error("could not create JSON object: specificProblem\n");
139         cJSON_Delete(faultFields);
140         return 0;
141     }
142
143     if(cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == 0) {
144         log_error("could not create JSON object: eventSeverity\n");
145         cJSON_Delete(faultFields);
146         return 0;
147     }
148
149     if(cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == 0) {
150         log_error("could not create JSON object: vfStatus\n");
151         cJSON_Delete(faultFields);
152         return 0;
153     }
154
155     cJSON *alarmAdditionalInformation = cJSON_CreateObject();
156     if(alarmAdditionalInformation == 0) {
157         log_error("could not create JSON object: alarmAdditionalInformation\n");
158         cJSON_Delete(faultFields);
159         return 0;
160     }
161     cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
162
163     if(cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == 0) {
164         log_error("could not create JSON object: eventTime\n");
165         cJSON_Delete(faultFields);
166         return 0;
167     }
168
169     if(cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == 0) {
170         log_error("could not create JSON object: equipType\n");
171         cJSON_Delete(faultFields);
172         return 0;
173     }
174
175     if(cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == 0) {
176         log_error("could not create JSON object: vendor\n");
177         cJSON_Delete(faultFields);
178         return 0;
179     }
180
181     if(cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == 0) {
182         log_error("could not create JSON object: model\n");
183         cJSON_Delete(faultFields);
184         return 0;
185     }
186
187     return faultFields;
188 }
189
190 static int ves_message_send_internal(sr_session_ctx_t *session, const char *condition, const char *object, const char *severity, const char *date_time, const char *specific_problem, int port, uint32_t *seq_id) {
191     assert(condition);
192     assert(object);
193     assert(severity);
194     assert(date_time);
195     assert(specific_problem);
196
197     char *hostname_string = framework_environment.settings.hostname;
198     cJSON *post_data_json = cJSON_CreateObject();
199     if(post_data_json == 0) {
200         log_error("cJSON_CreateObject failed\n");
201         return NTS_ERR_FAILED;
202     }
203
204     cJSON *event = cJSON_CreateObject();
205     if(event == 0) {
206         log_error("cJSON_CreateObject failed\n");
207         cJSON_Delete(post_data_json);
208         return NTS_ERR_FAILED;
209     }
210     cJSON_AddItemToObject(post_data_json, "event", event);
211
212     char *source_name = 0;
213     if (framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections == 1) {
214         // we don't want to append the port to the source name if we only expose one port
215         asprintf(&source_name, "%s", hostname_string);
216     }
217     else {
218         asprintf(&source_name, "%s_%d", hostname_string, port);
219     }
220     cJSON *common_event_header = ves_create_common_event_header("fault", "O_RAN_COMPONENT_Alarms", source_name, "Low", (*seq_id)++);
221     free(source_name);
222
223     if(common_event_header == 0) {
224         log_error("ves_create_common_event_header failed\n");
225         cJSON_Delete(post_data_json);
226         return NTS_ERR_FAILED;
227     }
228     cJSON_AddItemToObject(event, "commonEventHeader", common_event_header);
229
230     cJSON *fault_fields = ves_create_fault_fields(condition, object, severity, date_time, specific_problem);
231     if(fault_fields == 0) {
232         log_error("ves_create_fault_fields failed\n");
233         cJSON_Delete(post_data_json);
234         return NTS_ERR_FAILED;
235     }
236     cJSON_AddItemToObject(event, "faultFields", fault_fields);
237
238     char *post_data = cJSON_PrintUnformatted(post_data_json);
239     ves_details_t *ves_details = ves_endpoint_details_get(session);
240     if(!ves_details) {
241         log_error("ves_endpoint_details_get failed\n");
242         return NTS_ERR_FAILED;
243     }
244     
245     int rc = http_request(ves_details->url, ves_details->username, ves_details->password, "POST", post_data, 0, 0);
246     ves_details_free(ves_details);
247     cJSON_Delete(post_data_json);
248     free(post_data);
249     
250     if(rc != NTS_ERR_OK) {
251         log_error("http_request failed\n");
252         return NTS_ERR_FAILED;
253     }
254
255     return NTS_ERR_OK;
256 }