Fix TLS issues. Fix VES faultNotification issues.
[sim/o1-interface.git] / ntsimulator / src / o-ran-notifications / o-ran-notifications.c
1 /*
2  * o-ran-notifications.c
3  *
4  *  Created on: Oct 23, 2019
5  *      Author: parallels
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <inttypes.h>
13 #include <time.h>
14 #include <math.h>
15 #include <sys/time.h>
16
17 #include "sysrepo.h"
18 #include "sysrepo/values.h"
19
20 #include "utils.h"
21
22 #define LINE_BUFSIZE 128
23 #define ORAN_FAULT_ALARMS_NUMBER 10
24 #define AFFECTED_OBJECTS_MAX_NUMBER 100
25
26 volatile int exit_application = 0;
27
28 struct faultAlarms
29 {
30         int             faultId;
31         char*           faultSource;
32         int             cleared[10];
33         char*           faultSeverity;
34         char*           faultText;
35         char*           affectedObjects[AFFECTED_OBJECTS_MAX_NUMBER];
36 };
37 struct faultAlarms oran_fault_alarms[ORAN_FAULT_ALARMS_NUMBER] = {
38                 {.faultId = 1, .faultSource = "jknsdfnui", .affectedObjects = {"akddconoj", "asodmnjvf", "roiemfkmods"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "sdnjosopnojnsd"},
39                 {.faultId = 2, .faultSource = "onascokjnasc", .affectedObjects = {"sdouvncsjdfv13", "asjdn13ejlncd4"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "WARNING", .faultText = "4pionfcsofn42on"},
40                 {.faultId = 3, .faultSource = "asonxpkn", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "sdjnonj32onjsa23"},
41                 {.faultId = 4, .faultSource = "asnjcpkd", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023", "laksmdklmdas21"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "asdjln12osa453"},
42                 {.faultId = 5, .faultSource = "dskmfl", .affectedObjects = {"sdkm31wdlk"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dknovrf34ekl"},
43                 {.faultId = 6, .faultSource = "dsllkje232kl", .affectedObjects = {"sFKOM24KLMerw"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "frpkm24k lsd     kmewfpm"},
44                 {.faultId = 7, .faultSource = "fvkdlsfjnwej23kloe", .affectedObjects = {"fvkm24km", "sdfk23d", "kmdfkmo32", "wekl2332"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "WARNING", .faultText = "dsm 2d 32j sdfmr32"},
45                 {.faultId = 8, .faultSource = "dkom32", .affectedObjects = {"kmsdfkpm23ds", "sdmkp32"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "dsonj32 don32 mdson32pk654"},
46                 {.faultId = 9, .faultSource = "weflm3", .affectedObjects = {"klklm32kl3", "dsfln234poewj23-", "spmd32k"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "dsflknjwej32"},
47                 {.faultId = 10, .faultSource = "fweiunvfrem32", .affectedObjects = {"sfkm23klsdf2343"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dfskjnl4j dsfknl2 fodn54 65k"}
48 };
49
50 static  CURL *curl;
51
52 static int _init_curl()
53 {
54         curl = curl_easy_init();
55
56         if (curl == NULL) {
57                 printf("cURL initialization error! Aborting call!\n");
58                 return SR_ERR_OPERATION_FAILED;
59         }
60
61         return SR_ERR_OK;
62 }
63
64 static int cleanup_curl()
65 {
66         if (curl != NULL)
67         {
68                 curl_easy_cleanup(curl);
69         }
70
71         return SR_ERR_OK;
72 }
73
74 static int send_fault_ves_message(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem, int port)
75 {
76         int rc = SR_ERR_OK;
77         CURLcode res;
78         static sequence_id = 0;
79         int netconf_port_base = 0;
80
81         prepare_ves_message_curl(curl);
82
83         cJSON *postDataJson = cJSON_CreateObject();
84
85         cJSON *event = cJSON_CreateObject();
86         if (event == NULL)
87         {
88                 printf("Could not create JSON object: event\n");
89                 return 1;
90         }
91         cJSON_AddItemToObject(postDataJson, "event", event);
92
93         char *hostname = getenv("HOSTNAME");
94         char *netconf_base_string = getenv("NETCONF_BASE");
95
96         if (netconf_base_string != NULL)
97         {
98                 rc = sscanf(netconf_base_string, "%d", &netconf_port_base);
99                 if (rc != 1)
100                 {
101                         printf("Could not find the NETCONF base port, aborting the PNF registration...\n");
102                         return 1;
103                 }
104                 netconf_port_base += port;
105         }
106
107         char source_name[100];
108         sprintf(source_name, "%s_%d", hostname, netconf_port_base);
109
110         cJSON *commonEventHeader = vesCreateCommonEventHeader("fault", "O_RAN_COMPONENT_Alarms", source_name, sequence_id++);
111         if (commonEventHeader == NULL)
112         {
113                 printf("Could not create JSON object: commonEventHeader\n");
114                 return 1;
115         }
116         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
117
118         cJSON *faultFields = vesCreateFaultFields(alarm_condition, alarm_object, severity, date_time, specific_problem);
119         if (faultFields == NULL)
120         {
121                 printf("Could not create JSON object: faultFields\n");
122                 return 1;
123         }
124         cJSON_AddItemToObject(event, "faultFields", faultFields);
125
126     char *post_data_string = NULL;
127
128         post_data_string = cJSON_PrintUnformatted(postDataJson);
129
130         printf("Post data JSON:\n%s\n", post_data_string);
131
132         if (postDataJson != NULL)
133         {
134                 cJSON_Delete(postDataJson);
135         }
136
137         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
138
139         res = curl_easy_perform(curl);
140
141         if (res != CURLE_OK)
142         {
143                 printf("Failed to send cURL...\n");
144                 return SR_ERR_OPERATION_FAILED;
145         }
146
147         return SR_ERR_OK;
148 }
149
150 static int send_dummy_notif_file_mgmt(sr_session_ctx_t *sess)
151 {
152         int rc;
153
154         sr_val_t *vnotif;
155         size_t current_num_of_values= 0;
156
157         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
158
159         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-file-management:file-upload-notification/local-logical-file-path");
160         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, "odsanzucjsdoj");
161
162         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
163
164         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-file-management:file-upload-notification/remote-file-path");
165         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, "jsdknvjnkfd");
166
167         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
168
169         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-file-management:file-upload-notification/status");
170         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_ENUM_T, "SUCCESS");
171
172         rc = sr_event_notif_send(sess, "/o-ran-file-management:file-upload-notification", vnotif, current_num_of_values, SR_EV_NOTIF_DEFAULT);
173         if (rc != SR_ERR_OK) {
174                 printf("Failed to send notification send_dummy_notif_file_mgmt\n");
175                 return SR_ERR_OPERATION_FAILED;
176         }
177
178         printf("Successfully sent notification...\n");
179
180         sr_free_values(vnotif, current_num_of_values);
181
182         return SR_ERR_OK;
183 }
184
185 static int send_dummy_notif(sr_session_ctx_t *sess)
186 {
187         int rc;
188
189     char dateAndTime[256];
190     time_t t = time(NULL);
191     struct tm tm = *localtime(&t);
192     struct timeval tv;
193     int millisec;
194
195     gettimeofday(&tv, NULL);
196     millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
197     if (millisec>=1000)
198     { // Allow for rounding up to nearest second
199         millisec -=1000;
200         tv.tv_sec++;
201         millisec /= 100;
202     }
203     sprintf(dateAndTime, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
204     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
205     tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
206
207     int ran = (int) random_at_most(ORAN_FAULT_ALARMS_NUMBER - 1);
208
209     //TODO we hardcode here the number of ports for each device, 10
210     int random_port = (int) random_at_most(9);
211
212     if (oran_fault_alarms[ran].cleared[random_port] == 1)
213     {
214         oran_fault_alarms[ran].cleared[random_port] = 0;
215     }
216     else
217     {
218         oran_fault_alarms[ran].cleared[random_port] = 1;
219     }
220
221         sr_val_t *vnotif;
222         size_t current_num_of_values= 0;
223
224         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
225
226         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-id");
227         vnotif[current_num_of_values - 1].type = SR_UINT16_T;
228         vnotif[current_num_of_values - 1].data.uint16_val = oran_fault_alarms[ran].faultId;
229
230         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
231
232         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-source");
233         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultSource);
234
235         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
236
237         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-severity");
238         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_ENUM_T, oran_fault_alarms[ran].faultSeverity);
239
240         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
241
242         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/is-cleared");
243         vnotif[current_num_of_values - 1].type = SR_BOOL_T;
244         vnotif[current_num_of_values - 1].data.bool_val = oran_fault_alarms[ran].cleared[random_port];
245
246         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
247
248         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-text");
249         sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultText);
250
251         CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
252
253         sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/event-time");
254         sr_val_build_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, "%s", dateAndTime);
255
256         for (int  i = 0; i < AFFECTED_OBJECTS_MAX_NUMBER; ++i)
257         {
258                 char path[400];
259                 if (oran_fault_alarms[ran].affectedObjects[i] == NULL)
260                 {
261                         break;
262                 }
263
264                 sprintf(path, "/o-ran-fm:alarm-notif/affected-objects[name='%s']", oran_fault_alarms[ran].affectedObjects[i]);
265
266                 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
267
268                 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", path);
269                 vnotif[current_num_of_values - 1].type = SR_LIST_T;
270         }
271
272         int isNetconfAvailable = getNetconfAvailableFromConfigJson();
273         int isVesAvailable = getVesAvailableFromConfigJson();
274
275         if (isNetconfAvailable)
276         {
277                 rc = sr_event_notif_send(sess, "/o-ran-fm:alarm-notif", vnotif, current_num_of_values, SR_EV_NOTIF_DEFAULT);
278                 if (rc != SR_ERR_OK)
279                 {
280                         printf("Failed to send notification send_dummy_notif\n");
281                         return SR_ERR_OPERATION_FAILED;
282                 }
283                 printf("Successfully sent notification with timestamp=\"%s\"\n", dateAndTime);
284         }
285         if (isVesAvailable)
286         {
287                 char faultId[10];
288                 sprintf(faultId, "%d", oran_fault_alarms[ran].faultId);
289                 rc = send_fault_ves_message(faultId, oran_fault_alarms[ran].faultSource,
290                                 (oran_fault_alarms[ran].cleared[random_port]) ? "NORMAL" : oran_fault_alarms[ran].faultSeverity, dateAndTime, oran_fault_alarms[ran].faultText, random_port);
291                 if (rc != SR_ERR_OK)
292                 {
293                         printf("Could not send Fault VES message\n");
294                 }
295         }
296
297         sr_free_values(vnotif, current_num_of_values);
298
299         return SR_ERR_OK;
300 }
301
302 static void
303 sigint_handler(int signum)
304 {
305     exit_application = 1;
306 }
307
308 int
309 main(int argc, char **argv)
310 {
311     sr_conn_ctx_t *connection = NULL;
312     sr_session_ctx_t *session = NULL;
313     sr_subscription_ctx_t *subscription = NULL;
314     int rc = SR_ERR_OK;
315     int notification_delay_period = 0; //seconds
316
317     setbuf(stdout, NULL);
318
319     /* connect to sysrepo */
320     rc = sr_connect("oran_notifications", SR_CONN_DEFAULT, &connection);
321     if (SR_ERR_OK != rc) {
322         fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
323         goto cleanup;
324     }
325
326     /* start session */
327     rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
328     if (SR_ERR_OK != rc) {
329         fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
330         goto cleanup;
331     }
332
333     rc = _init_curl();
334     if (rc != SR_ERR_OK)
335     {
336         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
337         goto cleanup;
338     }
339
340     /* loop until ctrl-c is pressed / SIGINT is received */
341     signal(SIGINT, sigint_handler);
342     signal(SIGPIPE, SIG_IGN);
343
344
345     while (!exit_application) {
346         notification_delay_period = getFaultNotificationDelayPeriodFromConfigJson();
347
348         if (notification_delay_period > 0)
349         {
350                 send_dummy_notif(session);
351 //              send_dummy_notif_file_mgmt(session);
352
353             sleep(notification_delay_period);
354         }
355         else
356         {
357                 sleep(1);
358         }
359
360     }
361
362     printf("Application exit requested, exiting.\n");
363
364 cleanup:
365     if (NULL != subscription) {
366         sr_unsubscribe(session, subscription);
367     }
368     if (NULL != session) {
369         sr_session_stop(session);
370     }
371     if (NULL != connection) {
372         sr_disconnect(connection);
373     }
374     cleanup_curl();
375     printf("Error encountered. Exiting...");
376     return rc;
377 }
378
379
380
381