1 /*************************************************************************
3 * Copyright 2019 highstreet technologies GmbH and others
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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 ***************************************************************************/
26 #include <cjson/cJSON.h>
30 #include "sysrepo/values.h"
34 #define LINE_BUFSIZE 128
35 #define ORAN_FAULT_ALARMS_NUMBER 10
36 #define AFFECTED_OBJECTS_MAX_NUMBER 100
38 volatile int exit_application = 0;
40 static counterAlarms netconf_alarm_counter = {
47 static counterAlarms ves_alarm_counter= {
62 char* affectedObjects[AFFECTED_OBJECTS_MAX_NUMBER];
64 struct faultAlarms oran_fault_alarms[ORAN_FAULT_ALARMS_NUMBER] = {
65 {.faultId = 1, .faultSource = "jknsdfnui", .affectedObjects = {"akddconoj", "asodmnjvf", "roiemfkmods"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "sdnjosopnojnsd"},
66 {.faultId = 2, .faultSource = "onascokjnasc", .affectedObjects = {"sdouvncsjdfv13", "asjdn13ejlncd4"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "WARNING", .faultText = "4pionfcsofn42on"},
67 {.faultId = 3, .faultSource = "asonxpkn", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "sdjnonj32onjsa23"},
68 {.faultId = 4, .faultSource = "asnjcpkd", .affectedObjects = {"0j4fiwef320fd", "sdlvkmsdv-9023", "laksmdklmdas21"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "asdjln12osa453"},
69 {.faultId = 5, .faultSource = "dskmfl", .affectedObjects = {"sdkm31wdlk"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dknovrf34ekl"},
70 {.faultId = 6, .faultSource = "dsllkje232kl", .affectedObjects = {"sFKOM24KLMerw"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "frpkm24k lsd kmewfpm"},
71 {.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"},
72 {.faultId = 8, .faultSource = "dkom32", .affectedObjects = {"kmsdfkpm23ds", "sdmkp32"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "CRITICAL", .faultText = "dsonj32 don32 mdson32pk654"},
73 {.faultId = 9, .faultSource = "weflm3", .affectedObjects = {"klklm32kl3", "dsfln234poewj23-", "spmd32k"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MINOR", .faultText = "dsflknjwej32"},
74 {.faultId = 10, .faultSource = "fweiunvfrem32", .affectedObjects = {"sfkm23klsdf2343"}, .cleared = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, .faultSeverity = "MAJOR", .faultText = "dfskjnl4j dsfknl2 fodn54 65k"}
79 static int _init_curl()
81 curl = curl_easy_init();
84 printf("cURL initialization error! Aborting call!\n");
85 return SR_ERR_OPERATION_FAILED;
91 static int cleanup_curl()
95 curl_easy_cleanup(curl);
101 static int send_fault_ves_message(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem, int port)
104 static int sequence_id = 0;
105 int netconf_port_base = 0;
107 prepare_ves_message_curl(curl);
109 cJSON *postDataJson = cJSON_CreateObject();
111 cJSON *event = cJSON_CreateObject();
114 printf("Could not create JSON object: event\n");
115 return SR_ERR_OPERATION_FAILED;
117 cJSON_AddItemToObject(postDataJson, "event", event);
119 char *hostname = getenv("HOSTNAME");
121 netconf_port_base = getIntFromString(getenv("NETCONF_BASE"), 1);
122 netconf_port_base += port;
124 char source_name[100];
125 sprintf(source_name, "%s_%d", hostname, netconf_port_base);
127 cJSON *commonEventHeader = vesCreateCommonEventHeader("fault", "O_RAN_COMPONENT_Alarms", source_name, sequence_id++);
128 if (commonEventHeader == NULL)
130 printf("Could not create JSON object: commonEventHeader\n");
131 return SR_ERR_OPERATION_FAILED;
133 cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
135 cJSON *faultFields = vesCreateFaultFields(alarm_condition, alarm_object, severity, date_time, specific_problem);
136 if (faultFields == NULL)
138 printf("Could not create JSON object: faultFields\n");
139 if (postDataJson != NULL)
141 cJSON_Delete(postDataJson);
143 return SR_ERR_OPERATION_FAILED;
145 cJSON_AddItemToObject(event, "faultFields", faultFields);
147 char *post_data_string = NULL;
149 post_data_string = cJSON_PrintUnformatted(postDataJson);
151 printf("Post data JSON:\n%s\n", post_data_string);
153 if (postDataJson != NULL)
155 cJSON_Delete(postDataJson);
158 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
160 res = curl_easy_perform(curl);
164 printf("Failed to send cURL...\n");
165 return SR_ERR_OPERATION_FAILED;
171 static int send_dummy_notif(sr_session_ctx_t *sess)
175 char dateAndTime[256];
176 time_t t = time(NULL);
177 struct tm tm = *localtime(&t);
181 gettimeofday(&tv, NULL);
182 millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
184 { // Allow for rounding up to nearest second
189 sprintf(dateAndTime, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
190 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
191 tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
193 int ran = (int) random_at_most(ORAN_FAULT_ALARMS_NUMBER - 1);
195 //TODO we hardcode here the number of ports for each device, 10
196 int random_port = (int) random_at_most(9);
198 if (oran_fault_alarms[ran].cleared[random_port] == 1)
200 oran_fault_alarms[ran].cleared[random_port] = 0;
204 oran_fault_alarms[ran].cleared[random_port] = 1;
208 size_t current_num_of_values= 0;
210 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
212 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-id");
213 vnotif[current_num_of_values - 1].type = SR_UINT16_T;
214 vnotif[current_num_of_values - 1].data.uint16_val = oran_fault_alarms[ran].faultId;
216 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
218 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-source");
219 sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultSource);
221 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
223 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-severity");
224 sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_ENUM_T, oran_fault_alarms[ran].faultSeverity);
226 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
228 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/is-cleared");
229 vnotif[current_num_of_values - 1].type = SR_BOOL_T;
230 vnotif[current_num_of_values - 1].data.bool_val = oran_fault_alarms[ran].cleared[random_port];
232 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
234 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/fault-text");
235 sr_val_set_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, oran_fault_alarms[ran].faultText);
237 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
239 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", "/o-ran-fm:alarm-notif/event-time");
240 sr_val_build_str_data(&vnotif[current_num_of_values - 1], SR_STRING_T, "%s", dateAndTime);
242 for (int i = 0; i < AFFECTED_OBJECTS_MAX_NUMBER; ++i)
245 if (oran_fault_alarms[ran].affectedObjects[i] == NULL)
250 sprintf(path, "/o-ran-fm:alarm-notif/affected-objects[name='%s']", oran_fault_alarms[ran].affectedObjects[i]);
252 CREATE_NEW_VALUE(rc, vnotif, current_num_of_values);
254 sr_val_build_xpath(&vnotif[current_num_of_values - 1], "%s", path);
255 vnotif[current_num_of_values - 1].type = SR_LIST_T;
258 int isNetconfAvailable = getNetconfAvailableFromConfigJson();
259 int isVesAvailable = getVesAvailableFromConfigJson();
261 if (isNetconfAvailable)
263 rc = sr_event_notif_send(sess, "/o-ran-fm:alarm-notif", vnotif, current_num_of_values, SR_EV_NOTIF_DEFAULT);
266 printf("Failed to send notification send_dummy_notif\n");
267 return SR_ERR_OPERATION_FAILED;
269 if (oran_fault_alarms[ran].cleared[random_port])
271 netconf_alarm_counter.normal++;
275 if (strcmp(oran_fault_alarms[ran].faultSeverity, "WARNING") == 0)
277 netconf_alarm_counter.warning++;
279 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MINOR") == 0)
281 netconf_alarm_counter.minor++;
283 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MAJOR") == 0)
285 netconf_alarm_counter.major++;
287 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "CRITICAL") == 0)
289 netconf_alarm_counter.critical++;
293 printf("Successfully sent notification with timestamp=\"%s\"\n", dateAndTime);
298 sprintf(faultId, "%d", oran_fault_alarms[ran].faultId);
299 rc = send_fault_ves_message(faultId, oran_fault_alarms[ran].faultSource,
300 (oran_fault_alarms[ran].cleared[random_port]) ? "NORMAL" : oran_fault_alarms[ran].faultSeverity, dateAndTime, oran_fault_alarms[ran].faultText, random_port);
303 printf("Could not send Fault VES message\n");
305 if (oran_fault_alarms[ran].cleared[random_port])
307 ves_alarm_counter.normal++;
311 if (strcmp(oran_fault_alarms[ran].faultSeverity, "WARNING") == 0)
313 ves_alarm_counter.warning++;
315 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MINOR") == 0)
317 ves_alarm_counter.minor++;
319 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "MAJOR") == 0)
321 ves_alarm_counter.major++;
323 else if (strcmp(oran_fault_alarms[ran].faultSeverity, "CRITICAL") == 0)
325 ves_alarm_counter.critical++;
329 printf("Writing counters to file...\n");
330 rc = writeStatusNotificationCounters(ves_alarm_counter, netconf_alarm_counter);
333 printf("Could not write status to file...\n");
336 sr_free_values(vnotif, current_num_of_values);
342 sigint_handler(int signum)
344 exit_application = 1;
348 main(int argc, char **argv)
350 sr_conn_ctx_t *connection = NULL;
351 sr_session_ctx_t *session = NULL;
352 sr_subscription_ctx_t *subscription = NULL;
355 setbuf(stdout, NULL);
357 /* connect to sysrepo */
358 rc = sr_connect("oran_notifications", SR_CONN_DEFAULT, &connection);
359 if (SR_ERR_OK != rc) {
360 fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc));
365 rc = sr_session_start(connection, SR_DS_RUNNING, SR_SESS_DEFAULT, &session);
366 if (SR_ERR_OK != rc) {
367 fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc));
374 fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
378 /* loop until ctrl-c is pressed / SIGINT is received */
379 signal(SIGINT, sigint_handler);
380 signal(SIGPIPE, SIG_IGN);
382 while (!exit_application) {
383 int notif_delay[100], count = 0;
385 rc = getFaultNotificationDelayPeriodFromConfigJson(notif_delay, &count);
388 printf("Could not get fault notification delay period.");
395 for (int i = 0; i < count; ++i)
397 sleep(notif_delay[i]);
398 send_dummy_notif(session);
403 if (notif_delay[0] > 0)
405 sleep(notif_delay[0]);
406 send_dummy_notif(session);
411 // reset the counters when the notifciation delay period is switched back to 0
412 netconf_alarm_counter.normal = netconf_alarm_counter.warning = \
413 netconf_alarm_counter.minor = netconf_alarm_counter.major = \
414 netconf_alarm_counter.critical = 0;
416 ves_alarm_counter.normal = ves_alarm_counter.warning = \
417 ves_alarm_counter.minor = ves_alarm_counter.major = \
418 ves_alarm_counter.critical = 0;
424 printf("Application exit requested, exiting.\n");
427 if (NULL != subscription) {
428 sr_unsubscribe(session, subscription);
430 if (NULL != session) {
431 sr_session_stop(session);
433 if (NULL != connection) {
434 sr_disconnect(connection);
437 printf("Error encountered. Exiting...");