15bb4260cd3d095049546ea52a2e6928515e0f15
[sim/o1-interface.git] / ntsimulator / src / utils / utils.c
1 /*************************************************************************
2 *
3 * Copyright 2019 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 #include "utils.h"
19
20 #include <math.h>
21 #include <time.h>
22 #include <sys/time.h>
23 #include <stdio.h>
24 #include <string.h>
25
26 void set_curl_common_info_ves(CURL *curl)
27 {
28         struct curl_slist *chunk = NULL;
29         chunk = curl_slist_append(chunk, "Content-Type: application/json");
30         chunk = curl_slist_append(chunk, "Accept: application/json");
31
32     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
33
34     curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L); // seconds timeout for a connection
35     curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); //seconds timeout for an operation
36
37     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
38 }
39
40 void getCurrentDateAndTime(char *date_and_time)
41 {
42         time_t t = time(NULL);
43         struct tm tm = *localtime(&t);
44         struct timeval tv;
45         int millisec;
46
47         gettimeofday(&tv, NULL);
48         millisec = lrint(tv.tv_usec/1000.0); // Round to nearest millisec
49         if (millisec>=1000)
50         { // Allow for rounding up to nearest second
51                 millisec -=1000;
52                 tv.tv_sec++;
53                 millisec /= 100;
54         }
55         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.%01dZ",
56         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
57         tm.tm_hour, tm.tm_min, tm.tm_sec, millisec/100);
58
59         return;
60 }
61
62 void    generateRandomMacAddress(char *mac_address)
63 {
64         long rand1, rand2, rand3, rand4, rand5, rand6;
65         rand1 = random_at_most(255);
66         rand2 = random_at_most(255);
67         rand3 = random_at_most(255);
68         rand4 = random_at_most(255);
69         rand5 = random_at_most(255);
70         rand6 = random_at_most(255);
71
72         sprintf(mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", rand1, rand2, rand3, rand4, rand5, rand6);
73
74         return;
75 }
76
77 long random_at_most(long max) 
78 {
79     unsigned long
80         // max <= RAND_MAX < ULONG_MAX, so this is okay.
81         num_bins = (unsigned long) max + 1,
82         num_rand = (unsigned long) RAND_MAX + 1,
83         bin_size = num_rand / num_bins,
84         defect   = num_rand % num_bins;
85
86     unsigned int seed;
87     FILE* urandom = fopen("/dev/urandom", "r");
88     fread(&seed, sizeof(int), 1, urandom);
89     fclose(urandom);
90     srandom(seed);
91
92     long x;
93     do 
94     {
95         x = random();
96     }
97     // This is carefully written not to overflow
98     while (num_rand - defect <= (unsigned long)x);
99
100     // Truncated division is intentional
101     return x/bin_size;
102 }
103
104 int getSecondsFromLastQuarterInterval(void)
105 {
106         time_t t = time(NULL);
107         time_t t_past = time(NULL);
108         struct tm tm = *localtime(&t);
109         struct tm tm_15_min_ago = tm;
110
111         //round to the last quarter hour
112         tm_15_min_ago.tm_min -= (tm_15_min_ago.tm_min % 15);
113         tm_15_min_ago.tm_sec = 0;
114
115         t=mktime(&tm_15_min_ago);
116         t_past=mktime(&tm);
117
118         double seconds = difftime(t_past, t);
119
120         return (int)seconds;
121 }
122
123 int getSecondsFromLastDayInterval(void)
124 {
125         time_t t = time(NULL);
126         time_t t_past = time(NULL);
127         struct tm tm = *localtime(&t);
128         struct tm tm_day_ago = tm;
129
130         //round to the last quarter hour
131         tm_day_ago.tm_hour = 0;
132         tm_day_ago.tm_min = 0;
133         tm_day_ago.tm_sec = 0;
134
135         t=mktime(&tm_day_ago);
136         t_past=mktime(&tm);
137
138         double seconds = difftime(t_past, t);
139
140         return (int)seconds;
141 }
142
143 void getPreviousQuarterInterval(int number_of_intervals, char *date_and_time)
144 {
145         time_t t = time(NULL);
146         t -= 15 * 60 * number_of_intervals;
147         struct tm tm = *localtime(&t);
148
149         tm.tm_min -= (tm.tm_min % 15);
150         tm.tm_sec = 0;
151
152         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
153         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
154         tm.tm_hour, tm.tm_min, tm.tm_sec);
155
156         return;
157 }
158
159 void getPreviousDayPmTimestamp(int number_of_intervals, char *date_and_time)
160 {
161         time_t t = time(NULL);
162         t -= 24 * 60 * 60 * number_of_intervals;
163         struct tm tm = *localtime(&t);
164
165         tm.tm_hour = 0;
166         tm.tm_min = 0;
167         tm.tm_sec = 0;
168
169         sprintf(date_and_time, "%04d-%02d-%02dT%02d:%02d:%02d.0Z",
170         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
171         tm.tm_hour, tm.tm_min, tm.tm_sec);
172
173         return;
174 }
175
176 long int getMicrosecondsSinceEpoch(void)
177 {
178         time_t t = time(NULL);
179         struct timeval tv;
180         long int useconds;
181
182         gettimeofday(&tv, NULL);
183         useconds = t*1000 + tv.tv_usec; //add the microseconds to the seconds
184
185         return useconds;
186 }
187
188 //TODO need to implement other authentication methods as well, not only no-auth
189 void prepare_ves_message_curl(CURL *curl)
190 {
191         curl_easy_reset(curl);
192         set_curl_common_info_ves(curl);
193
194         char *ves_ip = getVesIpFromConfigJson();
195         int ves_port = getVesPortFromConfigJson();
196
197         char url[100];
198         sprintf(url, "http://%s:%d/eventListener/v7", ves_ip, ves_port);
199         curl_easy_setopt(curl, CURLOPT_URL, url);
200
201         free(ves_ip);
202
203         return;
204 }
205
206 /*
207  * Dynamically allocated memory;
208  * Caller needs to free the memory after it uses the value.
209  *
210 */
211 cJSON*  vesCreateCommonEventHeader(char *domain, char *event_type, char *source_name, int seq_id)
212 {
213         char dateAndTime[50];
214         getCurrentDateAndTime(dateAndTime);
215
216         long useconds = getMicrosecondsSinceEpoch();
217
218         cJSON *commonEventHeader = cJSON_CreateObject();
219         if (commonEventHeader == NULL)
220         {
221                 printf("Could not create JSON object: commonEventHeader\n");
222                 return NULL;
223         }
224
225         if (cJSON_AddStringToObject(commonEventHeader, "domain", domain) == NULL)
226         {
227                 printf("Could not create JSON object: domain\n");
228                 cJSON_Delete(commonEventHeader);
229                 return NULL;
230         }
231
232         char eventId[200];
233         sprintf(eventId, "%s_%s", source_name, dateAndTime);
234
235         if (cJSON_AddStringToObject(commonEventHeader, "eventId", eventId) == NULL)
236         {
237                 printf("Could not create JSON object: eventId\n");
238                 cJSON_Delete(commonEventHeader);
239                 return NULL;
240         }
241
242         char event_name[200];
243         sprintf(event_name, "%s_%s", domain, event_type);
244
245         if (cJSON_AddStringToObject(commonEventHeader, "eventName", event_name) == NULL)
246         {
247                 printf("Could not create JSON object: eventName\n");
248                 cJSON_Delete(commonEventHeader);
249                 return NULL;
250         }
251
252         if (cJSON_AddStringToObject(commonEventHeader, "eventType", event_type) == NULL)
253         {
254                 printf("Could not create JSON object: eventType\n");
255                 cJSON_Delete(commonEventHeader);
256                 return NULL;
257         }
258
259         if (cJSON_AddNumberToObject(commonEventHeader, "sequence", (double)(seq_id)) == NULL)
260         {
261                 printf("Could not create JSON object: sequence\n");
262                 cJSON_Delete(commonEventHeader);
263                 return NULL;
264         }
265
266         if (cJSON_AddStringToObject(commonEventHeader, "priority", "Low") == NULL)
267         {
268                 printf("Could not create JSON object: priority\n");
269                 cJSON_Delete(commonEventHeader);
270                 return NULL;
271         }
272
273         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityId", "") == NULL)
274         {
275                 printf("Could not create JSON object: reportingEntityId\n");
276                 cJSON_Delete(commonEventHeader);
277                 return NULL;
278         }
279
280         if (cJSON_AddStringToObject(commonEventHeader, "reportingEntityName", source_name) == NULL)
281         {
282                 printf("Could not create JSON object: reportingEntityName\n");
283                 cJSON_Delete(commonEventHeader);
284                 return NULL;
285         }
286
287         if (cJSON_AddStringToObject(commonEventHeader, "sourceId", "") == NULL)
288         {
289                 printf("Could not create JSON object: sourceId\n");
290                 cJSON_Delete(commonEventHeader);
291                 return NULL;
292         }
293
294         if (cJSON_AddStringToObject(commonEventHeader, "sourceName", source_name) == NULL)
295         {
296                 printf("Could not create JSON object: sourceName\n");
297                 cJSON_Delete(commonEventHeader);
298                 return NULL;
299         }
300
301         if (cJSON_AddNumberToObject(commonEventHeader, "startEpochMicrosec", (double)(useconds)) == NULL)
302         {
303                 printf("Could not create JSON object: startEpochMicrosec\n");
304                 cJSON_Delete(commonEventHeader);
305                 return NULL;
306         }
307
308         if (cJSON_AddNumberToObject(commonEventHeader, "lastEpochMicrosec", (double)(useconds)) == NULL)
309         {
310                 printf("Could not create JSON object: lastEpochMicrosec\n");
311                 cJSON_Delete(commonEventHeader);
312                 return NULL;
313         }
314
315         if (cJSON_AddStringToObject(commonEventHeader, "nfNamingCode", "sdn controller") == NULL)
316         {
317                 printf("Could not create JSON object: nfNamingCode\n");
318                 cJSON_Delete(commonEventHeader);
319                 return NULL;
320         }
321
322         if (cJSON_AddStringToObject(commonEventHeader, "nfVendorName", "sdn") == NULL)
323         {
324                 printf("Could not create JSON object: nfVendorName\n");
325                 cJSON_Delete(commonEventHeader);
326                 return NULL;
327         }
328
329         if (cJSON_AddStringToObject(commonEventHeader, "timeZoneOffset", "+00:00") == NULL)
330         {
331                 printf("Could not create JSON object: timeZoneOffset\n");
332                 cJSON_Delete(commonEventHeader);
333                 return NULL;
334         }
335
336         if (cJSON_AddStringToObject(commonEventHeader, "version", "4.0.1") == NULL)
337         {
338                 printf("Could not create JSON object: version\n");
339                 cJSON_Delete(commonEventHeader);
340                 return NULL;
341         }
342
343         if (cJSON_AddStringToObject(commonEventHeader, "vesEventListenerVersion", "7.0.1") == NULL)
344         {
345                 printf("Could not create JSON object: vesEventListenerVersion\n");
346                 cJSON_Delete(commonEventHeader);
347                 return NULL;
348         }
349
350         return commonEventHeader;
351 }
352
353 /*
354  * Dynamically allocated memory;
355  * Caller needs to free the memory after it uses the value.
356  *
357 */
358 cJSON*  vesCreateHeartbeatFields(int heartbeat_interval)
359 {
360         char dateAndTime[50];
361         getCurrentDateAndTime(dateAndTime);
362
363         cJSON *heartbeatFields = cJSON_CreateObject();
364         if (heartbeatFields == NULL)
365         {
366                 printf("Could not create JSON object: heartbeatFields\n");
367                 return NULL;
368         }
369
370         if (cJSON_AddStringToObject(heartbeatFields, "heartbeatFieldsVersion", "3.0") == NULL)
371         {
372                 printf("Could not create JSON object: heartbeatFieldsVersion\n");
373                 cJSON_Delete(heartbeatFields);
374                 return NULL;
375         }
376
377         if (cJSON_AddNumberToObject(heartbeatFields, "heartbeatInterval", (double)(heartbeat_interval)) == NULL)
378         {
379                 printf("Could not create JSON object: heartbeatInterval\n");
380                 cJSON_Delete(heartbeatFields);
381                 return NULL;
382         }
383
384         cJSON *additionalFields = cJSON_CreateObject();
385         if (additionalFields == NULL)
386         {
387                 printf("Could not create JSON object: additionalFields\n");
388                 cJSON_Delete(heartbeatFields);
389                 return NULL;
390         }
391         cJSON_AddItemToObject(heartbeatFields, "additionalFields", additionalFields);
392
393         if (cJSON_AddStringToObject(additionalFields, "eventTime", dateAndTime) == NULL)
394         {
395                 printf("Could not create JSON object: eventTime\n");
396                 cJSON_Delete(heartbeatFields);
397                 return NULL;
398         }
399
400         return heartbeatFields;
401 }
402
403 /*
404  * Dynamically allocated memory;
405  * Caller needs to free the memory after it uses the value.
406  *
407 */
408 char*   readConfigFileInString(void)
409 {
410         char * buffer = 0;
411         long length;
412         char config_file[200];
413         sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
414         FILE * f = fopen (config_file, "rb");
415
416         if (f)
417         {
418           fseek (f, 0, SEEK_END);
419           length = ftell (f);
420           fseek (f, 0, SEEK_SET);
421           buffer = malloc (length + 1);
422           if (buffer)
423           {
424             fread (buffer, 1, length, f);
425           }
426           fclose (f);
427           buffer[length] = '\0';
428         }
429
430         if (buffer)
431         {
432           return buffer;
433         }
434
435         return NULL;
436 }
437
438 void    writeConfigFile(char *config)
439 {
440         char config_file[200];
441         sprintf(config_file, "%s/configuration.json", getenv("SCRIPTS_DIR"));
442         FILE * f = fopen (config_file, "w");
443
444         if (f)
445         {
446                 fputs(config, f);
447                 fclose(f);
448         }
449         else
450         {
451                 printf("Could not write configuration file");
452         }
453 }
454
455 int getFaultNotificationDelayPeriodFromConfigJson(int *period_array, int *count)
456 {
457         char *stringConfig = readConfigFileInString();
458         int notificationDelay = 0;
459
460         if (stringConfig == NULL)
461         {
462                 printf("Could not read JSON configuration file in string.");
463                 return 0;
464         }
465
466         cJSON *jsonConfig = cJSON_Parse(stringConfig);
467         if (jsonConfig == NULL)
468         {
469                 free(stringConfig);
470                 const char *error_ptr = cJSON_GetErrorPtr();
471                 if (error_ptr != NULL)
472                 {
473                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
474                 }
475                 return SR_ERR_OPERATION_FAILED;
476         }
477         //we don't need the string anymore
478         free(stringConfig);
479         stringConfig = NULL;
480
481         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
482         if (!cJSON_IsObject(notifConfig))
483         {
484                 printf("Configuration JSON is not as expected: notification-config is not an object");
485                 cJSON_Delete(jsonConfig);
486                 return SR_ERR_OPERATION_FAILED;
487         }
488
489         cJSON *faultNotifDelay = cJSON_GetObjectItemCaseSensitive(notifConfig, "fault-notification-delay-period");
490         if (!cJSON_IsArray(faultNotifDelay))
491         {
492                 printf("Configuration JSON is not as expected: fault-notification-delay-period is not an array.");
493                 cJSON_Delete(jsonConfig);
494                 return SR_ERR_OPERATION_FAILED;
495         }
496
497     cJSON *iterator = NULL;
498     *count = 0;
499     int i = 0;
500
501     cJSON_ArrayForEach(iterator, faultNotifDelay) 
502     {
503         if (cJSON_IsNumber(iterator)) 
504         {
505             period_array[i++] = iterator->valueint;
506         } 
507         else 
508         {
509             printf("Invalid number in array!");
510         }
511     }
512
513     *count = i;
514
515         cJSON_Delete(jsonConfig);
516
517         return SR_ERR_OK;
518 }
519
520 int     getVesHeartbeatPeriodFromConfigJson(void)
521 {
522         char *stringConfig = readConfigFileInString();
523         int vesHeartbeat = 0;
524
525         if (stringConfig == NULL)
526         {
527                 printf("Could not read JSON configuration file in string.");
528                 return 0;
529         }
530
531         cJSON *jsonConfig = cJSON_Parse(stringConfig);
532         if (jsonConfig == NULL)
533         {
534                 free(stringConfig);
535                 const char *error_ptr = cJSON_GetErrorPtr();
536                 if (error_ptr != NULL)
537                 {
538                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
539                 }
540                 return SR_ERR_OPERATION_FAILED;
541         }
542         //we don't need the string anymore
543         free(stringConfig);
544         stringConfig = NULL;
545
546         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
547         if (!cJSON_IsObject(notifConfig))
548         {
549                 printf("Configuration JSON is not as expected: notification-config is not an object");
550                 cJSON_Delete(jsonConfig);
551                 return SR_ERR_OPERATION_FAILED;
552         }
553
554         cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
555         if (!cJSON_IsNumber(vesHeartbeatPeriod))
556         {
557                 printf("Configuration JSON is not as expected: ves-heartbeat-period is not a number");
558                 cJSON_Delete(jsonConfig);
559                 return SR_ERR_OPERATION_FAILED;
560         }
561
562         vesHeartbeat = (int)(vesHeartbeatPeriod->valuedouble);
563
564         cJSON_Delete(jsonConfig);
565
566         return vesHeartbeat;
567 }
568
569
570 /*
571  * Dynamically allocated memory;
572  * Caller needs to free the memory after it uses the value.
573  *
574 */
575 char*   getVesAuthMethodFromConfigJson(void)
576 {
577         char *stringConfig = readConfigFileInString();
578
579         if (stringConfig == NULL)
580         {
581                 printf("Could not read JSON configuration file in string.");
582                 return 0;
583         }
584
585         cJSON *jsonConfig = cJSON_Parse(stringConfig);
586         if (jsonConfig == NULL)
587         {
588                 free(stringConfig);
589                 const char *error_ptr = cJSON_GetErrorPtr();
590                 if (error_ptr != NULL)
591                 {
592                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
593                 }
594                 return NULL;
595         }
596         //we don't need the string anymore
597         free(stringConfig);
598         stringConfig = NULL;
599
600         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
601         if (!cJSON_IsObject(vesDetails))
602         {
603                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
604                 cJSON_Delete(jsonConfig);
605                 return NULL;
606         }
607
608         cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
609         if (!cJSON_IsString(vesAuthMethod))
610         {
611                 printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not an object");
612                 cJSON_Delete(jsonConfig);
613                 return NULL;
614         }
615
616         char *auth_method_string = strdup(cJSON_GetStringValue(vesAuthMethod));
617
618         cJSON_Delete(jsonConfig);
619
620         return auth_method_string;
621 }
622
623 /*
624  * Dynamically allocated memory;
625  * Caller needs to free the memory after it uses the value.
626  *
627 */
628 char*   getVesIpFromConfigJson(void)
629 {
630         char *stringConfig = readConfigFileInString();
631
632         if (stringConfig == NULL)
633         {
634                 printf("Could not read JSON configuration file in string.");
635                 return 0;
636         }
637
638         cJSON *jsonConfig = cJSON_Parse(stringConfig);
639         if (jsonConfig == NULL)
640         {
641                 free(stringConfig);
642                 const char *error_ptr = cJSON_GetErrorPtr();
643                 if (error_ptr != NULL)
644                 {
645                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
646                 }
647                 return NULL;
648         }
649         //we don't need the string anymore
650         free(stringConfig);
651         stringConfig = NULL;
652
653         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
654         if (!cJSON_IsObject(vesDetails))
655         {
656                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
657                 cJSON_Delete(jsonConfig);
658                 return NULL;
659         }
660
661         cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
662         if (!cJSON_IsString(vesIp))
663         {
664                 printf("Configuration JSON is not as expected: ves-endpoint-ip is not an object");
665                 cJSON_Delete(jsonConfig);
666                 return NULL;
667         }
668
669         char *ves_ip = strdup(cJSON_GetStringValue(vesIp));
670
671         cJSON_Delete(jsonConfig);
672
673         return ves_ip;
674 }
675
676 int     getVesPortFromConfigJson(void)
677 {
678         char *stringConfig = readConfigFileInString();
679
680         if (stringConfig == NULL)
681         {
682                 printf("Could not read JSON configuration file in string.");
683                 return 0;
684         }
685
686         cJSON *jsonConfig = cJSON_Parse(stringConfig);
687         if (jsonConfig == NULL)
688         {
689                 free(stringConfig);
690                 const char *error_ptr = cJSON_GetErrorPtr();
691                 if (error_ptr != NULL)
692                 {
693                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
694                 }
695                 return SR_ERR_OPERATION_FAILED;
696         }
697         //we don't need the string anymore
698         free(stringConfig);
699         stringConfig = NULL;
700
701         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
702         if (!cJSON_IsObject(vesDetails))
703         {
704                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
705                 cJSON_Delete(jsonConfig);
706                 return SR_ERR_OPERATION_FAILED;
707         }
708
709         cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
710         if (!cJSON_IsNumber(vesPort))
711         {
712                 printf("Configuration JSON is not as expected: ves-endpoint-port is not an object");
713                 cJSON_Delete(jsonConfig);
714                 return SR_ERR_OPERATION_FAILED;
715         }
716
717         int port = (int)(vesPort->valuedouble);
718
719         cJSON_Delete(jsonConfig);
720
721         return port;
722 }
723
724 int     getVesRegistrationFromConfigJson(void)
725 {
726         char *stringConfig = readConfigFileInString();
727
728         if (stringConfig == NULL)
729         {
730                 printf("Could not read JSON configuration file in string.");
731                 return 0;
732         }
733
734         cJSON *jsonConfig = cJSON_Parse(stringConfig);
735         if (jsonConfig == NULL)
736         {
737                 free(stringConfig);
738                 const char *error_ptr = cJSON_GetErrorPtr();
739                 if (error_ptr != NULL)
740                 {
741                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
742                 }
743                 return SR_ERR_OPERATION_FAILED;
744         }
745         //we don't need the string anymore
746         free(stringConfig);
747         stringConfig = NULL;
748
749         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
750         if (!cJSON_IsObject(vesDetails))
751         {
752                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
753                 cJSON_Delete(jsonConfig);
754                 return SR_ERR_OPERATION_FAILED;
755         }
756
757         cJSON *vesReg = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
758         if (!cJSON_IsBool(vesReg))
759         {
760                 printf("Configuration JSON is not as expected: ves-registration is not an object");
761                 cJSON_Delete(jsonConfig);
762                 return SR_ERR_OPERATION_FAILED;
763         }
764
765         int is_ves_reg = (cJSON_IsTrue(vesReg)) ? TRUE : FALSE;
766
767         cJSON_Delete(jsonConfig);
768
769         return is_ves_reg;
770 }
771
772 /*
773  * Dynamically allocated memory;
774  * Caller needs to free the memory after it uses the value.
775  *
776 */
777 cJSON*  vesCreatePnfRegistrationFields(int port, bool is_tls)
778 {
779         cJSON *pnfRegistrationFields = cJSON_CreateObject();
780         if (pnfRegistrationFields == NULL)
781         {
782                 printf("Could not create JSON object: pnfRegistrationFields\n");
783                 return NULL;
784         }
785
786         if (cJSON_AddStringToObject(pnfRegistrationFields, "pnfRegistrationFieldsVersion", "2.0") == NULL)
787         {
788                 printf("Could not create JSON object: pnfRegistrationFieldsVersion\n");
789                 cJSON_Delete(pnfRegistrationFields);
790                 return NULL;
791         }
792
793         if (cJSON_AddStringToObject(pnfRegistrationFields, "lastServiceDate", "2019-08-16") == NULL)
794         {
795                 printf("Could not create JSON object: lastServiceDate\n");
796                 cJSON_Delete(pnfRegistrationFields);
797                 return NULL;
798         }
799
800         char mac_addr[40];
801         generateRandomMacAddress(mac_addr);
802
803         if (cJSON_AddStringToObject(pnfRegistrationFields, "macAddress", mac_addr) == NULL)
804         {
805                 printf("Could not create JSON object: macAddress\n");
806                 cJSON_Delete(pnfRegistrationFields);
807                 return NULL;
808         }
809
810         if (cJSON_AddStringToObject(pnfRegistrationFields, "manufactureDate", "2019-08-16") == NULL)
811         {
812                 printf("Could not create JSON object: manufactureDate\n");
813                 cJSON_Delete(pnfRegistrationFields);
814                 return NULL;
815         }
816
817         if (cJSON_AddStringToObject(pnfRegistrationFields, "modelNumber", "Simulated Device Melacon") == NULL)
818         {
819                 printf("Could not create JSON object: manufactureDate\n");
820                 cJSON_Delete(pnfRegistrationFields);
821                 return NULL;
822         }
823
824         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV4IpAddress", getenv("NTS_IP")) == NULL)
825         {
826                 printf("Could not create JSON object: oamV4IpAddress\n");
827                 cJSON_Delete(pnfRegistrationFields);
828                 return NULL;
829         }
830
831         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == NULL)
832         {
833                 printf("Could not create JSON object: oamV6IpAddress\n");
834                 cJSON_Delete(pnfRegistrationFields);
835                 return NULL;
836         }
837
838         char serial_number[100];
839         sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", getenv("HOSTNAME"), getenv("NTS_IP"), port);
840
841         if (cJSON_AddStringToObject(pnfRegistrationFields, "serialNumber", serial_number) == NULL)
842         {
843                 printf("Could not create JSON object: serialNumber\n");
844                 cJSON_Delete(pnfRegistrationFields);
845                 return NULL;
846         }
847
848         if (cJSON_AddStringToObject(pnfRegistrationFields, "softwareVersion", "2.3.5") == NULL)
849         {
850                 printf("Could not create JSON object: softwareVersion\n");
851                 cJSON_Delete(pnfRegistrationFields);
852                 return NULL;
853         }
854
855         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitFamily", "Simulated Device") == NULL)
856         {
857                 printf("Could not create JSON object: unitFamily\n");
858                 cJSON_Delete(pnfRegistrationFields);
859                 return NULL;
860         }
861
862         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitType", "O-RAN-sim") == NULL)
863         {
864                 printf("Could not create JSON object: unitType\n");
865                 cJSON_Delete(pnfRegistrationFields);
866                 return NULL;
867         }
868
869         if (cJSON_AddStringToObject(pnfRegistrationFields, "vendorName", "Melacon") == NULL)
870         {
871                 printf("Could not create JSON object: vendorName\n");
872                 cJSON_Delete(pnfRegistrationFields);
873                 return NULL;
874         }
875
876         cJSON *additionalFields = cJSON_CreateObject();
877         if (additionalFields == NULL)
878         {
879                 printf("Could not create JSON object: additionalFields\n");
880                 cJSON_Delete(pnfRegistrationFields);
881                 return NULL;
882         }
883         cJSON_AddItemToObject(pnfRegistrationFields, "additionalFields", additionalFields);
884
885         char portString[10];
886         sprintf(portString, "%d", port);
887
888         if (cJSON_AddStringToObject(additionalFields, "oamPort", portString) == NULL)
889         {
890                 printf("Could not create JSON object: oamPort\n");
891                 cJSON_Delete(pnfRegistrationFields);
892                 return NULL;
893         }
894
895         if (is_tls)
896         {
897                 //TLS specific configuration
898                 if (cJSON_AddStringToObject(additionalFields, "protocol", "TLS") == NULL)
899                 {
900                         printf("Could not create JSON object: protocol\n");
901                         cJSON_Delete(pnfRegistrationFields);
902                         return NULL;
903                 }
904
905                 //TODO here we have the username from the docker container hardcoded: netconf
906                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
907                 {
908                         printf("Could not create JSON object: username\n");
909                         cJSON_Delete(pnfRegistrationFields);
910                         return NULL;
911                 }
912
913                 if (cJSON_AddStringToObject(additionalFields, "keyId", "device-key") == NULL)
914                 {
915                         printf("Could not create JSON object: keyId\n");
916                         cJSON_Delete(pnfRegistrationFields);
917                         return NULL;
918                 }
919         }
920         else
921         {
922                 //SSH specific configuration
923                 if (cJSON_AddStringToObject(additionalFields, "protocol", "SSH") == NULL)
924                 {
925                         printf("Could not create JSON object: protocol\n");
926                         cJSON_Delete(pnfRegistrationFields);
927                         return NULL;
928                 }
929
930                 //TODO here we have the username from the docker container hardcoded: netconf
931                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
932                 {
933                         printf("Could not create JSON object: username\n");
934                         cJSON_Delete(pnfRegistrationFields);
935                         return NULL;
936                 }
937
938                 //TODO here we have the password from the docker container hardcoded: netconf
939                 if (cJSON_AddStringToObject(additionalFields, "password", "netconf") == NULL)
940                 {
941                         printf("Could not create JSON object: password\n");
942                         cJSON_Delete(pnfRegistrationFields);
943                         return NULL;
944                 }
945         }
946
947         if (cJSON_AddStringToObject(additionalFields, "reconnectOnChangedSchema", "false") == NULL)
948         {
949                 printf("Could not create JSON object: reconnectOnChangedSchema\n");
950                 cJSON_Delete(pnfRegistrationFields);
951                 return NULL;
952         }
953
954         if (cJSON_AddStringToObject(additionalFields, "sleep-factor", "1.5") == NULL)
955         {
956                 printf("Could not create JSON object: sleep-factor\n");
957                 cJSON_Delete(pnfRegistrationFields);
958                 return NULL;
959         }
960
961         if (cJSON_AddStringToObject(additionalFields, "tcpOnly", "false") == NULL)
962         {
963                 printf("Could not create JSON object: tcpOnly\n");
964                 cJSON_Delete(pnfRegistrationFields);
965                 return NULL;
966         }
967
968         if (cJSON_AddStringToObject(additionalFields, "connectionTimeout", "20000") == NULL)
969         {
970                 printf("Could not create JSON object: connectionTimeout\n");
971                 cJSON_Delete(pnfRegistrationFields);
972                 return NULL;
973         }
974
975         if (cJSON_AddStringToObject(additionalFields, "maxConnectionAttempts", "100") == NULL)
976         {
977                 printf("Could not create JSON object: maxConnectionAttempts\n");
978                 cJSON_Delete(pnfRegistrationFields);
979                 return NULL;
980         }
981
982         if (cJSON_AddStringToObject(additionalFields, "betweenAttemptsTimeout", "2000") == NULL)
983         {
984                 printf("Could not create JSON object: betweenAttemptsTimeout\n");
985                 cJSON_Delete(pnfRegistrationFields);
986                 return NULL;
987         }
988
989         if (cJSON_AddStringToObject(additionalFields, "keepaliveDelay", "120") == NULL)
990         {
991                 printf("Could not create JSON object: keepaliveDelay\n");
992                 cJSON_Delete(pnfRegistrationFields);
993                 return NULL;
994         }
995
996         return pnfRegistrationFields;
997 }
998
999 int     getNetconfAvailableFromConfigJson(void)
1000 {
1001         char *stringConfig = readConfigFileInString();
1002
1003         if (stringConfig == NULL)
1004         {
1005                 printf("Could not read JSON configuration file in string.");
1006                 return 0;
1007         }
1008
1009         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1010         if (jsonConfig == NULL)
1011         {
1012                 free(stringConfig);
1013                 const char *error_ptr = cJSON_GetErrorPtr();
1014                 if (error_ptr != NULL)
1015                 {
1016                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1017                 }
1018                 return SR_ERR_OPERATION_FAILED;
1019         }
1020         //we don't need the string anymore
1021         free(stringConfig);
1022         stringConfig = NULL;
1023
1024         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1025         if (!cJSON_IsObject(notifDetails))
1026         {
1027                 printf("Configuration JSON is not as expected: notification-config is not an object");
1028                 cJSON_Delete(jsonConfig);
1029                 return SR_ERR_OPERATION_FAILED;
1030         }
1031
1032         cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-netconf-available");
1033         if (!cJSON_IsBool(isNetconfAvailable))
1034         {
1035                 printf("Configuration JSON is not as expected: is-netconf-available is not an object");
1036                 cJSON_Delete(jsonConfig);
1037                 return SR_ERR_OPERATION_FAILED;
1038         }
1039
1040         int is_netconf_available = (cJSON_IsTrue(isNetconfAvailable)) ? TRUE : FALSE;
1041
1042         cJSON_Delete(jsonConfig);
1043
1044         return is_netconf_available;
1045 }
1046
1047 int     getVesAvailableFromConfigJson(void)
1048 {
1049         char *stringConfig = readConfigFileInString();
1050
1051         if (stringConfig == NULL)
1052         {
1053                 printf("Could not read JSON configuration file in string.");
1054                 return 0;
1055         }
1056
1057         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1058         if (jsonConfig == NULL)
1059         {
1060                 free(stringConfig);
1061                 const char *error_ptr = cJSON_GetErrorPtr();
1062                 if (error_ptr != NULL)
1063                 {
1064                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1065                 }
1066                 return SR_ERR_OPERATION_FAILED;
1067         }
1068         //we don't need the string anymore
1069         free(stringConfig);
1070         stringConfig = NULL;
1071
1072         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1073         if (!cJSON_IsObject(notifDetails))
1074         {
1075                 printf("Configuration JSON is not as expected: notification-config is not an object");
1076                 cJSON_Delete(jsonConfig);
1077                 return SR_ERR_OPERATION_FAILED;
1078         }
1079
1080         cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-ves-available");
1081         if (!cJSON_IsBool(isVesAvailable))
1082         {
1083                 printf("Configuration JSON is not as expected: is-ves-available is not an object");
1084                 cJSON_Delete(jsonConfig);
1085                 return SR_ERR_OPERATION_FAILED;
1086         }
1087
1088         int is_netconf_available = (cJSON_IsTrue(isVesAvailable)) ? TRUE : FALSE;
1089
1090         cJSON_Delete(jsonConfig);
1091
1092         return is_netconf_available;
1093 }
1094
1095 /*
1096  * Dynamically allocated memory;
1097  * Caller needs to free the memory after it uses the value.
1098  *
1099 */
1100 cJSON*  vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem)
1101 {
1102         cJSON *faultFields = cJSON_CreateObject();
1103         if (faultFields == NULL)
1104         {
1105                 printf("Could not create JSON object: faultFields\n");
1106                 return NULL;
1107         }
1108
1109         if (cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == NULL)
1110         {
1111                 printf("Could not create JSON object: faultFieldsVersion\n");
1112                 cJSON_Delete(faultFields);
1113                 return NULL;
1114         }
1115
1116         if (cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == NULL)
1117         {
1118                 printf("Could not create JSON object: alarmCondition\n");
1119                 cJSON_Delete(faultFields);
1120                 return NULL;
1121         }
1122
1123         if (cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == NULL)
1124         {
1125                 printf("Could not create JSON object: alarmInterfaceA\n");
1126                 cJSON_Delete(faultFields);
1127                 return NULL;
1128         }
1129
1130         if (cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == NULL)
1131         {
1132                 printf("Could not create JSON object: eventSourceType\n");
1133                 cJSON_Delete(faultFields);
1134                 return NULL;
1135         }
1136
1137         if (cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == NULL)
1138         {
1139                 printf("Could not create JSON object: specificProblem\n");
1140                 cJSON_Delete(faultFields);
1141                 return NULL;
1142         }
1143
1144         if (cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == NULL)
1145         {
1146                 printf("Could not create JSON object: eventSeverity\n");
1147                 cJSON_Delete(faultFields);
1148                 return NULL;
1149         }
1150
1151         if (cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == NULL)
1152         {
1153                 printf("Could not create JSON object: vfStatus\n");
1154                 cJSON_Delete(faultFields);
1155                 return NULL;
1156         }
1157
1158         cJSON *alarmAdditionalInformation = cJSON_CreateObject();
1159         if (alarmAdditionalInformation == NULL)
1160         {
1161                 printf("Could not create JSON object: alarmAdditionalInformation\n");
1162                 cJSON_Delete(faultFields);
1163                 return NULL;
1164         }
1165         cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
1166
1167         if (cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == NULL)
1168         {
1169                 printf("Could not create JSON object: eventTime\n");
1170                 cJSON_Delete(faultFields);
1171                 return NULL;
1172         }
1173
1174         if (cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == NULL)
1175         {
1176                 printf("Could not create JSON object: equipType\n");
1177                 cJSON_Delete(faultFields);
1178                 return NULL;
1179         }
1180
1181         if (cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == NULL)
1182         {
1183                 printf("Could not create JSON object: vendor\n");
1184                 cJSON_Delete(faultFields);
1185                 return NULL;
1186         }
1187
1188         if (cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == NULL)
1189         {
1190                 printf("Could not create JSON object: model\n");
1191                 cJSON_Delete(faultFields);
1192                 return NULL;
1193         }
1194
1195         return faultFields;
1196 }
1197
1198 static cJSON* createSeverityCounters(counterAlarms count)
1199 {
1200     cJSON *severityCounters = cJSON_CreateObject();
1201     if (severityCounters == NULL)
1202     {
1203         printf("Could not create JSON object: severityCounters\n");
1204         return NULL;
1205     }
1206
1207     if (cJSON_AddNumberToObject(severityCounters, "severity-normal", count.normal) == NULL)
1208     {
1209         printf("Could not create JSON object: severity-normal\n");
1210         return NULL;
1211     }
1212
1213     if (cJSON_AddNumberToObject(severityCounters, "severity-warning", count.warning) == NULL)
1214     {
1215         printf("Could not create JSON object: severity-warning\n");
1216         return NULL;
1217     }
1218
1219     if (cJSON_AddNumberToObject(severityCounters, "severity-minor", count.minor) == NULL)
1220     {
1221         printf("Could not create JSON object: severity-minor\n");
1222         return NULL;
1223     }
1224
1225     if (cJSON_AddNumberToObject(severityCounters, "severity-major", count.major) == NULL)
1226     {
1227         printf("Could not create JSON object: severity-major\n");
1228         return NULL;
1229     }
1230
1231     if (cJSON_AddNumberToObject(severityCounters, "severity-critical", count.critical) == NULL)
1232     {
1233         printf("Could not create JSON object: severity-critical\n");
1234         return NULL;
1235     }
1236
1237     return severityCounters;
1238 }
1239
1240 void writeStatusFile(char *status)
1241 {
1242         char status_file[200];
1243         sprintf(status_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1244         FILE * f = fopen (status_file, "w");
1245
1246         if (f)
1247         {
1248                 fputs(status, f);
1249                 fclose(f);
1250         }
1251         else
1252         {
1253                 printf("Could not write status file!\n");
1254         }
1255 }
1256
1257 int     writeSkeletonStatusFile()
1258 {
1259     cJSON *statusObject = cJSON_CreateObject();
1260     if (statusObject == NULL)
1261     {
1262         printf("Could not create JSON object: statusObject\n");
1263         return SR_ERR_OPERATION_FAILED;
1264     }
1265
1266     // counterAlarms counter = {
1267     //     .normal = 0,
1268     //     .warning = 0,
1269     //     .minor = 0,
1270     //     .major = 0,
1271     //     .critical = 0
1272     // };
1273
1274     // cJSON *totalVesNotifications = createSeverityCounters(counter);
1275     // if (totalVesNotifications == NULL)
1276     // {
1277     //     printf("Could not create JSON object: totalVesNotifications\n");
1278     //     cJSON_Delete(statusObject);
1279     //     return SR_ERR_OPERATION_FAILED;
1280     // }
1281     // cJSON_AddItemToObject(statusObject, "total-ves-notifications-sent", totalVesNotifications);
1282
1283     // cJSON *totalNetconfNotifications = createSeverityCounters(counter);
1284     // if (totalNetconfNotifications == NULL)
1285     // {
1286     //     printf("Could not create JSON object: totalNetconfNotifications\n");
1287     //     cJSON_Delete(statusObject);
1288     //     return SR_ERR_OPERATION_FAILED;
1289     // }
1290     // cJSON_AddItemToObject(statusObject, "total-netconf-notifications-sent", totalNetconfNotifications);
1291
1292     cJSON *deviceList = cJSON_CreateArray();
1293     if (deviceList == NULL)
1294     {
1295         printf("Could not create JSON object: deviceList\n");
1296         cJSON_Delete(statusObject);
1297         return SR_ERR_OPERATION_FAILED;
1298         }
1299     cJSON_AddItemToObject(statusObject, "device-list", deviceList);
1300
1301     char *status_string = NULL;
1302
1303     status_string = cJSON_PrintUnformatted(statusObject);
1304
1305     writeStatusFile(status_string);
1306
1307     return SR_ERR_OK;
1308 }
1309
1310 /*
1311  * Dynamically allocated memory;
1312  * Caller needs to free the memory after it uses the value.
1313  *
1314 */
1315 char*   readStatusFileInString(void)
1316 {
1317         char * buffer = 0;
1318         long length;
1319         char config_file[200];
1320         sprintf(config_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1321         FILE * f = fopen (config_file, "rb");
1322
1323         if (f)
1324         {
1325           fseek (f, 0, SEEK_END);
1326           length = ftell (f);
1327           fseek (f, 0, SEEK_SET);
1328           buffer = malloc (length + 1);
1329           if (buffer)
1330           {
1331             fread (buffer, 1, length, f);
1332           }
1333           fclose (f);
1334           buffer[length] = '\0';
1335         }
1336
1337         if (buffer)
1338         {
1339           return buffer;
1340         }
1341
1342         return NULL;
1343 }
1344
1345 /*
1346  * Dynamically allocated memory;
1347  * Caller needs to free the memory after it uses the value.
1348  *
1349 */
1350 cJSON*  getDeviceListFromStatusFile(void)
1351 {
1352     char *stringStatus = readStatusFileInString();
1353
1354         if (stringStatus == NULL)
1355         {
1356                 printf("Could not read status file!\n");
1357                 return NULL;
1358         }
1359
1360         cJSON *jsonStatus = cJSON_Parse(stringStatus);
1361         if (jsonStatus == NULL)
1362         {
1363                 free(stringStatus);
1364                 const char *error_ptr = cJSON_GetErrorPtr();
1365                 if (error_ptr != NULL)
1366                 {
1367                         fprintf(stderr, "Could not parse JSON status! Error before: %s\n", error_ptr);
1368                 }
1369                 return NULL;
1370         }
1371         //we don't need the string anymore
1372         free(stringStatus);
1373         stringStatus = NULL;
1374
1375     return jsonStatus;
1376 }
1377
1378 cJSON* createDeviceListEntry(counterAlarms ves_counter, counterAlarms netconf_counter)
1379 {
1380     cJSON *deviceListEntry = cJSON_CreateObject();
1381     if (deviceListEntry == NULL)
1382     {
1383         printf("Could not create JSON object: deviceListEntry\n");
1384         return NULL;
1385     }
1386
1387     char hostname[100];
1388     sprintf(hostname, "%s", getenv("HOSTNAME"));
1389
1390     if (cJSON_AddStringToObject(deviceListEntry, "device-name", hostname) == NULL)
1391     {
1392         printf("Could not create JSON object: device-name\n");
1393         cJSON_Delete(deviceListEntry);
1394         return NULL;
1395     }
1396
1397     cJSON *vesNotificationsSent = createSeverityCounters(ves_counter);
1398     if (vesNotificationsSent == NULL)
1399     {
1400         printf("Could not create JSON object: vesNotificationsSent\n");
1401         cJSON_Delete(deviceListEntry);
1402         return NULL;
1403     }
1404     cJSON_AddItemToObject(deviceListEntry, "ves-notifications-sent", vesNotificationsSent);
1405
1406     cJSON *netconfNotificationsSent = createSeverityCounters(netconf_counter);
1407     if (netconfNotificationsSent == NULL)
1408     {
1409         printf("Could not create JSON object: netconfNotificationsSent\n");
1410         cJSON_Delete(deviceListEntry);
1411         return NULL;
1412     }
1413     cJSON_AddItemToObject(deviceListEntry, "netconf-notifications-sent", netconfNotificationsSent);
1414
1415     return deviceListEntry;
1416 }
1417
1418 static void modifySeverityCounters(cJSON **severityCounters, counterAlarms count)
1419 {
1420     cJSON *severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-normal");
1421     if (!cJSON_IsNumber(severity))
1422     {
1423         printf("Status JSON is not as expected: severity-normal is not an number");
1424         return;
1425     }
1426     //we set the value of the severity-normal object
1427     cJSON_SetNumberValue(severity, count.normal);
1428
1429     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-warning");
1430     if (!cJSON_IsNumber(severity))
1431     {
1432         printf("Status JSON is not as expected: severity-warning is not an number");
1433         return;
1434     }
1435     //we set the value of the severity-warning object
1436     cJSON_SetNumberValue(severity, count.warning);
1437
1438     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-minor");
1439     if (!cJSON_IsNumber(severity))
1440     {
1441         printf("Status JSON is not as expected: severity-minor is not an number");
1442         return;
1443     }
1444     //we set the value of the severity-minor object
1445     cJSON_SetNumberValue(severity, count.minor);
1446
1447     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-major");
1448     if (!cJSON_IsNumber(severity))
1449     {
1450         printf("Status JSON is not as expected: severity-major is not an number");
1451         return;
1452     }
1453     //we set the value of the severity-major object
1454         cJSON_SetNumberValue(severity, count.major);
1455
1456     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-critical");
1457     if (!cJSON_IsNumber(severity))
1458     {
1459         printf("Status JSON is not as expected: severity-critical is not an number");
1460         return;
1461     }
1462     //we set the value of the severity-critical object
1463         cJSON_SetNumberValue(severity, count.critical);
1464
1465     return;
1466 }
1467
1468 static void modifyDeviceListEntry(cJSON **deviceListEntry, counterAlarms ves_counter, counterAlarms netconf_counter)
1469 {
1470     cJSON *vesNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "ves-notifications-sent");
1471     if (!cJSON_IsObject(vesNotificationsSent))
1472     {
1473         printf("Status JSON is not as expected: ves-notifications-sent is not a object");
1474         return;
1475     }
1476
1477     modifySeverityCounters(&vesNotificationsSent, ves_counter);
1478
1479     cJSON *netconfNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "netconf-notifications-sent");
1480     if (!cJSON_IsObject(netconfNotificationsSent))
1481     {
1482         printf("Status JSON is not as expected: netconf-notifications-sent is not a object");
1483         return;
1484     }
1485
1486     modifySeverityCounters(&netconfNotificationsSent, netconf_counter);
1487 }
1488
1489 int writeStatusNotificationCounters(counterAlarms ves_counter, counterAlarms netconf_counter)
1490 {
1491         cJSON *jsonStatus = getDeviceListFromStatusFile();
1492
1493         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1494         if (!cJSON_IsArray(deviceList))
1495         {
1496                 printf("Status JSON is not as expected: device-list is not an object");
1497                 cJSON_Delete(jsonStatus);
1498                 return SR_ERR_OPERATION_FAILED;
1499         }
1500
1501     int array_size = cJSON_GetArraySize(deviceList);
1502
1503     int found = 0;
1504     for (int i=0; i<array_size; ++i)
1505     {
1506         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1507         char hostname[100];
1508         sprintf(hostname, "%s", getenv("HOSTNAME"));
1509
1510         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1511         if (!cJSON_IsString(deviceName))
1512         {
1513             printf("Status JSON is not as expected: device-name is not a string.");
1514             cJSON_Delete(jsonStatus);
1515             return SR_ERR_OPERATION_FAILED;
1516         }
1517         char *deviceNameString = cJSON_GetStringValue(deviceName);
1518
1519         if (strcmp(hostname, deviceNameString) == 0)
1520         {
1521             modifyDeviceListEntry(&deviceListEntry, ves_counter, netconf_counter);
1522             found = 1;
1523             break;
1524         }
1525     }
1526     if (found == 0)
1527     {
1528         cJSON* deviceListEntry = createDeviceListEntry(ves_counter, netconf_counter);
1529     
1530         cJSON_AddItemToArray(deviceList, deviceListEntry);  
1531     }
1532
1533         //writing the new JSON to the configuration file
1534         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1535         writeStatusFile(stringStatus);
1536
1537         cJSON_Delete(jsonStatus);
1538
1539         return SR_ERR_OK;
1540 }
1541
1542
1543 int removeDeviceEntryFromStatusFile(char *containerId)
1544 {
1545     cJSON *jsonStatus = getDeviceListFromStatusFile();
1546
1547         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1548         if (!cJSON_IsArray(deviceList))
1549         {
1550                 printf("Status JSON is not as expected: device-list is not an object");
1551                 cJSON_Delete(jsonStatus);
1552                 return SR_ERR_OPERATION_FAILED;
1553         }
1554
1555     int array_size = cJSON_GetArraySize(deviceList);
1556     int found = array_size;
1557
1558     for (int i=0; i<array_size; ++i)
1559     {
1560         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1561         char hostname[100];
1562         sprintf(hostname, "%s", getenv("HOSTNAME"));
1563
1564         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1565         if (!cJSON_IsString(deviceName))
1566         {
1567             printf("Status JSON is not as expected: device-name is not a string.");
1568             cJSON_Delete(jsonStatus);
1569             return SR_ERR_OPERATION_FAILED;
1570         }
1571         char *deviceNameString = cJSON_GetStringValue(deviceName);
1572
1573         if (strcmp(containerId, deviceNameString) == 0)
1574         {
1575             found = i;
1576             break;
1577         }
1578     }
1579
1580     if (found < array_size)
1581     {
1582         cJSON_DeleteItemFromArray(deviceList, found);
1583     }
1584     else
1585     {
1586         printf("Could not find status file entry for device with id=\"%s\"", containerId);
1587     }
1588
1589         //writing the new JSON to the configuration file
1590         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1591         writeStatusFile(stringStatus);
1592
1593         cJSON_Delete(jsonStatus);
1594
1595         return SR_ERR_OK;
1596 }
1597
1598 int compute_notifications_count(counterAlarms *ves_counter, counterAlarms *netconf_counter)
1599 {
1600     ves_counter->normal = ves_counter->warning = \
1601             ves_counter->minor = ves_counter->major = \
1602             ves_counter->critical = 0;
1603     netconf_counter->normal = netconf_counter->warning = \
1604             netconf_counter->minor = netconf_counter->major = \
1605             netconf_counter->critical = 0;
1606
1607     cJSON *jsonStatus = getDeviceListFromStatusFile();
1608
1609     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1610         if (!cJSON_IsArray(deviceList))
1611         {
1612                 printf("Status JSON is not as expected: device-list is not an object");
1613                 cJSON_Delete(jsonStatus);
1614                 return SR_ERR_OPERATION_FAILED;
1615         }
1616
1617     int array_size = cJSON_GetArraySize(deviceList);
1618
1619     for (int i=0; i<array_size; ++i)
1620     {
1621         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1622
1623         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1624         if (!cJSON_IsObject(vesNotifications))
1625         {
1626             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1627             cJSON_Delete(jsonStatus);
1628             return SR_ERR_OPERATION_FAILED;
1629         }
1630
1631         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1632         if (!cJSON_IsNumber(severity))
1633         {
1634             printf("Status JSON is not as expected: severity-normal is not a string.");
1635             cJSON_Delete(jsonStatus);
1636             return SR_ERR_OPERATION_FAILED;
1637         }
1638         int counter = (int)(severity->valuedouble);
1639         ves_counter->normal += counter;
1640
1641         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1642         if (!cJSON_IsNumber(severity))
1643         {
1644             printf("Status JSON is not as expected: severity-warning is not a string.");
1645             cJSON_Delete(jsonStatus);
1646             return SR_ERR_OPERATION_FAILED;
1647         }
1648         counter = (int)(severity->valuedouble);
1649         ves_counter->warning += counter;
1650
1651         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
1652         if (!cJSON_IsNumber(severity))
1653         {
1654             printf("Status JSON is not as expected: severity-minor is not a string.");
1655             cJSON_Delete(jsonStatus);
1656             return SR_ERR_OPERATION_FAILED;
1657         }
1658         counter = (int)(severity->valuedouble);
1659         ves_counter->minor += counter;
1660
1661         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
1662         if (!cJSON_IsNumber(severity))
1663         {
1664             printf("Status JSON is not as expected: severity-major is not a string.");
1665             cJSON_Delete(jsonStatus);
1666             return SR_ERR_OPERATION_FAILED;
1667         }
1668         counter = (int)(severity->valuedouble);
1669         ves_counter->major += counter;
1670
1671         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
1672         if (!cJSON_IsNumber(severity))
1673         {
1674             printf("Status JSON is not as expected: severity-critical is not a string.");
1675             cJSON_Delete(jsonStatus);
1676             return SR_ERR_OPERATION_FAILED;
1677         }
1678         counter = (int)(severity->valuedouble);
1679         ves_counter->critical += counter;
1680
1681         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
1682         if (!cJSON_IsObject(netconfNotifications))
1683         {
1684             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
1685             cJSON_Delete(jsonStatus);
1686             return SR_ERR_OPERATION_FAILED;
1687         }
1688
1689         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
1690         if (!cJSON_IsNumber(severity))
1691         {
1692             printf("Status JSON is not as expected: severity-normal is not a string.");
1693             cJSON_Delete(jsonStatus);
1694             return SR_ERR_OPERATION_FAILED;
1695         }
1696         
1697         counter = (int)(severity->valuedouble);
1698         netconf_counter->normal += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1699
1700         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
1701         if (!cJSON_IsNumber(severity))
1702         {
1703             printf("Status JSON is not as expected: severity-warning is not a string.");
1704             cJSON_Delete(jsonStatus);
1705             return SR_ERR_OPERATION_FAILED;
1706         }
1707         counter = (int)(severity->valuedouble);
1708         netconf_counter->warning += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1709
1710         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
1711         if (!cJSON_IsNumber(severity))
1712         {
1713             printf("Status JSON is not as expected: severity-minor is not a string.");
1714             cJSON_Delete(jsonStatus);
1715             return SR_ERR_OPERATION_FAILED;
1716         }
1717         counter = (int)(severity->valuedouble);
1718         netconf_counter->minor += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1719
1720         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
1721         if (!cJSON_IsNumber(severity))
1722         {
1723             printf("Status JSON is not as expected: severity-major is not a string.");
1724             cJSON_Delete(jsonStatus);
1725             return SR_ERR_OPERATION_FAILED;
1726         }
1727         counter = (int)(severity->valuedouble);
1728         netconf_counter->major += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1729
1730         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
1731         if (!cJSON_IsNumber(severity))
1732         {
1733             printf("Status JSON is not as expected: severity-critical is not a string.");
1734             cJSON_Delete(jsonStatus);
1735             return SR_ERR_OPERATION_FAILED;
1736         }
1737         counter = (int)(severity->valuedouble);
1738         netconf_counter->critical += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1739     }
1740
1741     cJSON_Delete(jsonStatus);
1742
1743     return SR_ERR_OK;
1744 }
1745
1746 int getDeviceCounters(char *containerId, counterAlarms *ves_counter, counterAlarms *netconf_counter)
1747 {
1748     cJSON *jsonStatus = getDeviceListFromStatusFile();
1749
1750     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1751         if (!cJSON_IsArray(deviceList))
1752         {
1753                 printf("Status JSON is not as expected: device-list is not an object");
1754                 cJSON_Delete(jsonStatus);
1755                 return SR_ERR_OPERATION_FAILED;
1756         }
1757
1758     int array_size = cJSON_GetArraySize(deviceList);
1759
1760     for (int i=0; i<array_size; ++i)
1761     {
1762         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1763
1764         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1765         if (!cJSON_IsString(deviceName))
1766         {
1767             printf("Status JSON is not as expected: device-name is not a string.");
1768             cJSON_Delete(jsonStatus);
1769             return SR_ERR_OPERATION_FAILED;
1770         }
1771         char *deviceNameString = cJSON_GetStringValue(deviceName);
1772
1773         if (strcmp(deviceNameString, containerId) != 0)
1774         {
1775             continue;
1776         }
1777
1778         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1779         if (!cJSON_IsObject(vesNotifications))
1780         {
1781             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1782             cJSON_Delete(jsonStatus);
1783             return SR_ERR_OPERATION_FAILED;
1784         }
1785
1786         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1787         if (!cJSON_IsNumber(severity))
1788         {
1789             printf("Status JSON is not as expected: severity-normal is not a string.");
1790             cJSON_Delete(jsonStatus);
1791             return SR_ERR_OPERATION_FAILED;
1792         }
1793         int counter = (int)(severity->valuedouble);
1794         ves_counter->normal = counter;
1795
1796         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1797         if (!cJSON_IsNumber(severity))
1798         {
1799             printf("Status JSON is not as expected: severity-warning is not a string.");
1800             cJSON_Delete(jsonStatus);
1801             return SR_ERR_OPERATION_FAILED;
1802         }
1803         counter = (int)(severity->valuedouble);
1804         ves_counter->warning = counter;
1805
1806         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
1807         if (!cJSON_IsNumber(severity))
1808         {
1809             printf("Status JSON is not as expected: severity-minor is not a string.");
1810             cJSON_Delete(jsonStatus);
1811             return SR_ERR_OPERATION_FAILED;
1812         }
1813         counter = (int)(severity->valuedouble);
1814         ves_counter->minor = counter;
1815
1816         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
1817         if (!cJSON_IsNumber(severity))
1818         {
1819             printf("Status JSON is not as expected: severity-major is not a string.");
1820             cJSON_Delete(jsonStatus);
1821             return SR_ERR_OPERATION_FAILED;
1822         }
1823         counter = (int)(severity->valuedouble);
1824         ves_counter->major = counter;
1825
1826         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
1827         if (!cJSON_IsNumber(severity))
1828         {
1829             printf("Status JSON is not as expected: severity-critical is not a string.");
1830             cJSON_Delete(jsonStatus);
1831             return SR_ERR_OPERATION_FAILED;
1832         }
1833         counter = (int)(severity->valuedouble);
1834         ves_counter->critical = counter;
1835
1836         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
1837         if (!cJSON_IsObject(netconfNotifications))
1838         {
1839             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
1840             cJSON_Delete(jsonStatus);
1841             return SR_ERR_OPERATION_FAILED;
1842         }
1843
1844         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
1845         if (!cJSON_IsNumber(severity))
1846         {
1847             printf("Status JSON is not as expected: severity-normal is not a string.");
1848             cJSON_Delete(jsonStatus);
1849             return SR_ERR_OPERATION_FAILED;
1850         }
1851         
1852         counter = (int)(severity->valuedouble);
1853         netconf_counter->normal = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1854
1855         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
1856         if (!cJSON_IsNumber(severity))
1857         {
1858             printf("Status JSON is not as expected: severity-warning is not a string.");
1859             cJSON_Delete(jsonStatus);
1860             return SR_ERR_OPERATION_FAILED;
1861         }
1862         counter = (int)(severity->valuedouble);
1863         netconf_counter->warning = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1864
1865         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
1866         if (!cJSON_IsNumber(severity))
1867         {
1868             printf("Status JSON is not as expected: severity-minor is not a string.");
1869             cJSON_Delete(jsonStatus);
1870             return SR_ERR_OPERATION_FAILED;
1871         }
1872         counter = (int)(severity->valuedouble);
1873         netconf_counter->minor = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1874
1875         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
1876         if (!cJSON_IsNumber(severity))
1877         {
1878             printf("Status JSON is not as expected: severity-major is not a string.");
1879             cJSON_Delete(jsonStatus);
1880             return SR_ERR_OPERATION_FAILED;
1881         }
1882         counter = (int)(severity->valuedouble);
1883         netconf_counter->major = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1884
1885         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
1886         if (!cJSON_IsNumber(severity))
1887         {
1888             printf("Status JSON is not as expected: severity-critical is not a string.");
1889             cJSON_Delete(jsonStatus);
1890             return SR_ERR_OPERATION_FAILED;
1891         }
1892         counter = (int)(severity->valuedouble);
1893         netconf_counter->critical = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1894     }
1895
1896     cJSON_Delete(jsonStatus);
1897
1898     return SR_ERR_OK;
1899 }