Add counters for generated notifications.
[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(void)
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_IsNumber(faultNotifDelay))
491         {
492                 printf("Configuration JSON is not as expected: fault-notification-delay-period is not a number");
493                 cJSON_Delete(jsonConfig);
494                 return SR_ERR_OPERATION_FAILED;
495         }
496
497         notificationDelay = (int)(faultNotifDelay->valuedouble);
498
499         cJSON_Delete(jsonConfig);
500
501         return notificationDelay;
502 }
503
504 int     getVesHeartbeatPeriodFromConfigJson(void)
505 {
506         char *stringConfig = readConfigFileInString();
507         int vesHeartbeat = 0;
508
509         if (stringConfig == NULL)
510         {
511                 printf("Could not read JSON configuration file in string.");
512                 return 0;
513         }
514
515         cJSON *jsonConfig = cJSON_Parse(stringConfig);
516         if (jsonConfig == NULL)
517         {
518                 free(stringConfig);
519                 const char *error_ptr = cJSON_GetErrorPtr();
520                 if (error_ptr != NULL)
521                 {
522                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
523                 }
524                 return SR_ERR_OPERATION_FAILED;
525         }
526         //we don't need the string anymore
527         free(stringConfig);
528         stringConfig = NULL;
529
530         cJSON *notifConfig = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
531         if (!cJSON_IsObject(notifConfig))
532         {
533                 printf("Configuration JSON is not as expected: notification-config is not an object");
534                 cJSON_Delete(jsonConfig);
535                 return SR_ERR_OPERATION_FAILED;
536         }
537
538         cJSON *vesHeartbeatPeriod = cJSON_GetObjectItemCaseSensitive(notifConfig, "ves-heartbeat-period");
539         if (!cJSON_IsNumber(vesHeartbeatPeriod))
540         {
541                 printf("Configuration JSON is not as expected: ves-heartbeat-period is not a number");
542                 cJSON_Delete(jsonConfig);
543                 return SR_ERR_OPERATION_FAILED;
544         }
545
546         vesHeartbeat = (int)(vesHeartbeatPeriod->valuedouble);
547
548         cJSON_Delete(jsonConfig);
549
550         return vesHeartbeat;
551 }
552
553
554 /*
555  * Dynamically allocated memory;
556  * Caller needs to free the memory after it uses the value.
557  *
558 */
559 char*   getVesAuthMethodFromConfigJson(void)
560 {
561         char *stringConfig = readConfigFileInString();
562
563         if (stringConfig == NULL)
564         {
565                 printf("Could not read JSON configuration file in string.");
566                 return 0;
567         }
568
569         cJSON *jsonConfig = cJSON_Parse(stringConfig);
570         if (jsonConfig == NULL)
571         {
572                 free(stringConfig);
573                 const char *error_ptr = cJSON_GetErrorPtr();
574                 if (error_ptr != NULL)
575                 {
576                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
577                 }
578                 return NULL;
579         }
580         //we don't need the string anymore
581         free(stringConfig);
582         stringConfig = NULL;
583
584         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
585         if (!cJSON_IsObject(vesDetails))
586         {
587                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
588                 cJSON_Delete(jsonConfig);
589                 return NULL;
590         }
591
592         cJSON *vesAuthMethod = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-auth-method");
593         if (!cJSON_IsString(vesAuthMethod))
594         {
595                 printf("Configuration JSON is not as expected: ves-endpoint-auth-method is not an object");
596                 cJSON_Delete(jsonConfig);
597                 return NULL;
598         }
599
600         char *auth_method_string = strdup(cJSON_GetStringValue(vesAuthMethod));
601
602         cJSON_Delete(jsonConfig);
603
604         return auth_method_string;
605 }
606
607 /*
608  * Dynamically allocated memory;
609  * Caller needs to free the memory after it uses the value.
610  *
611 */
612 char*   getVesIpFromConfigJson(void)
613 {
614         char *stringConfig = readConfigFileInString();
615
616         if (stringConfig == NULL)
617         {
618                 printf("Could not read JSON configuration file in string.");
619                 return 0;
620         }
621
622         cJSON *jsonConfig = cJSON_Parse(stringConfig);
623         if (jsonConfig == NULL)
624         {
625                 free(stringConfig);
626                 const char *error_ptr = cJSON_GetErrorPtr();
627                 if (error_ptr != NULL)
628                 {
629                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
630                 }
631                 return NULL;
632         }
633         //we don't need the string anymore
634         free(stringConfig);
635         stringConfig = NULL;
636
637         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
638         if (!cJSON_IsObject(vesDetails))
639         {
640                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
641                 cJSON_Delete(jsonConfig);
642                 return NULL;
643         }
644
645         cJSON *vesIp = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-ip");
646         if (!cJSON_IsString(vesIp))
647         {
648                 printf("Configuration JSON is not as expected: ves-endpoint-ip is not an object");
649                 cJSON_Delete(jsonConfig);
650                 return NULL;
651         }
652
653         char *ves_ip = strdup(cJSON_GetStringValue(vesIp));
654
655         cJSON_Delete(jsonConfig);
656
657         return ves_ip;
658 }
659
660 int     getVesPortFromConfigJson(void)
661 {
662         char *stringConfig = readConfigFileInString();
663
664         if (stringConfig == NULL)
665         {
666                 printf("Could not read JSON configuration file in string.");
667                 return 0;
668         }
669
670         cJSON *jsonConfig = cJSON_Parse(stringConfig);
671         if (jsonConfig == NULL)
672         {
673                 free(stringConfig);
674                 const char *error_ptr = cJSON_GetErrorPtr();
675                 if (error_ptr != NULL)
676                 {
677                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
678                 }
679                 return SR_ERR_OPERATION_FAILED;
680         }
681         //we don't need the string anymore
682         free(stringConfig);
683         stringConfig = NULL;
684
685         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
686         if (!cJSON_IsObject(vesDetails))
687         {
688                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
689                 cJSON_Delete(jsonConfig);
690                 return SR_ERR_OPERATION_FAILED;
691         }
692
693         cJSON *vesPort = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-endpoint-port");
694         if (!cJSON_IsNumber(vesPort))
695         {
696                 printf("Configuration JSON is not as expected: ves-endpoint-port is not an object");
697                 cJSON_Delete(jsonConfig);
698                 return SR_ERR_OPERATION_FAILED;
699         }
700
701         int port = (int)(vesPort->valuedouble);
702
703         cJSON_Delete(jsonConfig);
704
705         return port;
706 }
707
708 int     getVesRegistrationFromConfigJson(void)
709 {
710         char *stringConfig = readConfigFileInString();
711
712         if (stringConfig == NULL)
713         {
714                 printf("Could not read JSON configuration file in string.");
715                 return 0;
716         }
717
718         cJSON *jsonConfig = cJSON_Parse(stringConfig);
719         if (jsonConfig == NULL)
720         {
721                 free(stringConfig);
722                 const char *error_ptr = cJSON_GetErrorPtr();
723                 if (error_ptr != NULL)
724                 {
725                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
726                 }
727                 return SR_ERR_OPERATION_FAILED;
728         }
729         //we don't need the string anymore
730         free(stringConfig);
731         stringConfig = NULL;
732
733         cJSON *vesDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "ves-endpoint-details");
734         if (!cJSON_IsObject(vesDetails))
735         {
736                 printf("Configuration JSON is not as expected: ves-endpoint-details is not an object");
737                 cJSON_Delete(jsonConfig);
738                 return SR_ERR_OPERATION_FAILED;
739         }
740
741         cJSON *vesReg = cJSON_GetObjectItemCaseSensitive(vesDetails, "ves-registration");
742         if (!cJSON_IsBool(vesReg))
743         {
744                 printf("Configuration JSON is not as expected: ves-registration is not an object");
745                 cJSON_Delete(jsonConfig);
746                 return SR_ERR_OPERATION_FAILED;
747         }
748
749         int is_ves_reg = (cJSON_IsTrue(vesReg)) ? TRUE : FALSE;
750
751         cJSON_Delete(jsonConfig);
752
753         return is_ves_reg;
754 }
755
756 /*
757  * Dynamically allocated memory;
758  * Caller needs to free the memory after it uses the value.
759  *
760 */
761 cJSON*  vesCreatePnfRegistrationFields(int port, bool is_tls)
762 {
763         cJSON *pnfRegistrationFields = cJSON_CreateObject();
764         if (pnfRegistrationFields == NULL)
765         {
766                 printf("Could not create JSON object: pnfRegistrationFields\n");
767                 return NULL;
768         }
769
770         if (cJSON_AddStringToObject(pnfRegistrationFields, "pnfRegistrationFieldsVersion", "2.0") == NULL)
771         {
772                 printf("Could not create JSON object: pnfRegistrationFieldsVersion\n");
773                 cJSON_Delete(pnfRegistrationFields);
774                 return NULL;
775         }
776
777         if (cJSON_AddStringToObject(pnfRegistrationFields, "lastServiceDate", "2019-08-16") == NULL)
778         {
779                 printf("Could not create JSON object: lastServiceDate\n");
780                 cJSON_Delete(pnfRegistrationFields);
781                 return NULL;
782         }
783
784         char mac_addr[40];
785         generateRandomMacAddress(mac_addr);
786
787         if (cJSON_AddStringToObject(pnfRegistrationFields, "macAddress", mac_addr) == NULL)
788         {
789                 printf("Could not create JSON object: macAddress\n");
790                 cJSON_Delete(pnfRegistrationFields);
791                 return NULL;
792         }
793
794         if (cJSON_AddStringToObject(pnfRegistrationFields, "manufactureDate", "2019-08-16") == NULL)
795         {
796                 printf("Could not create JSON object: manufactureDate\n");
797                 cJSON_Delete(pnfRegistrationFields);
798                 return NULL;
799         }
800
801         if (cJSON_AddStringToObject(pnfRegistrationFields, "modelNumber", "Simulated Device Melacon") == NULL)
802         {
803                 printf("Could not create JSON object: manufactureDate\n");
804                 cJSON_Delete(pnfRegistrationFields);
805                 return NULL;
806         }
807
808         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV4IpAddress", getenv("NTS_IP")) == NULL)
809         {
810                 printf("Could not create JSON object: oamV4IpAddress\n");
811                 cJSON_Delete(pnfRegistrationFields);
812                 return NULL;
813         }
814
815         if (cJSON_AddStringToObject(pnfRegistrationFields, "oamV6IpAddress", "0:0:0:0:0:ffff:a0a:011") == NULL)
816         {
817                 printf("Could not create JSON object: oamV6IpAddress\n");
818                 cJSON_Delete(pnfRegistrationFields);
819                 return NULL;
820         }
821
822         char serial_number[100];
823         sprintf(serial_number, "%s-%s-%d-Simulated Device Melacon", getenv("HOSTNAME"), getenv("NTS_IP"), port);
824
825         if (cJSON_AddStringToObject(pnfRegistrationFields, "serialNumber", serial_number) == NULL)
826         {
827                 printf("Could not create JSON object: serialNumber\n");
828                 cJSON_Delete(pnfRegistrationFields);
829                 return NULL;
830         }
831
832         if (cJSON_AddStringToObject(pnfRegistrationFields, "softwareVersion", "2.3.5") == NULL)
833         {
834                 printf("Could not create JSON object: softwareVersion\n");
835                 cJSON_Delete(pnfRegistrationFields);
836                 return NULL;
837         }
838
839         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitFamily", "Simulated Device") == NULL)
840         {
841                 printf("Could not create JSON object: unitFamily\n");
842                 cJSON_Delete(pnfRegistrationFields);
843                 return NULL;
844         }
845
846         if (cJSON_AddStringToObject(pnfRegistrationFields, "unitType", "O-RAN-sim") == NULL)
847         {
848                 printf("Could not create JSON object: unitType\n");
849                 cJSON_Delete(pnfRegistrationFields);
850                 return NULL;
851         }
852
853         if (cJSON_AddStringToObject(pnfRegistrationFields, "vendorName", "Melacon") == NULL)
854         {
855                 printf("Could not create JSON object: vendorName\n");
856                 cJSON_Delete(pnfRegistrationFields);
857                 return NULL;
858         }
859
860         cJSON *additionalFields = cJSON_CreateObject();
861         if (additionalFields == NULL)
862         {
863                 printf("Could not create JSON object: additionalFields\n");
864                 cJSON_Delete(pnfRegistrationFields);
865                 return NULL;
866         }
867         cJSON_AddItemToObject(pnfRegistrationFields, "additionalFields", additionalFields);
868
869         char portString[10];
870         sprintf(portString, "%d", port);
871
872         if (cJSON_AddStringToObject(additionalFields, "oamPort", portString) == NULL)
873         {
874                 printf("Could not create JSON object: oamPort\n");
875                 cJSON_Delete(pnfRegistrationFields);
876                 return NULL;
877         }
878
879         if (is_tls)
880         {
881                 //TLS specific configuration
882                 if (cJSON_AddStringToObject(additionalFields, "protocol", "TLS") == NULL)
883                 {
884                         printf("Could not create JSON object: protocol\n");
885                         cJSON_Delete(pnfRegistrationFields);
886                         return NULL;
887                 }
888
889                 //TODO here we have the username from the docker container hardcoded: netconf
890                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
891                 {
892                         printf("Could not create JSON object: username\n");
893                         cJSON_Delete(pnfRegistrationFields);
894                         return NULL;
895                 }
896
897                 if (cJSON_AddStringToObject(additionalFields, "keyId", "device-key") == NULL)
898                 {
899                         printf("Could not create JSON object: keyId\n");
900                         cJSON_Delete(pnfRegistrationFields);
901                         return NULL;
902                 }
903         }
904         else
905         {
906                 //SSH specific configuration
907                 if (cJSON_AddStringToObject(additionalFields, "protocol", "SSH") == NULL)
908                 {
909                         printf("Could not create JSON object: protocol\n");
910                         cJSON_Delete(pnfRegistrationFields);
911                         return NULL;
912                 }
913
914                 //TODO here we have the username from the docker container hardcoded: netconf
915                 if (cJSON_AddStringToObject(additionalFields, "username", "netconf") == NULL)
916                 {
917                         printf("Could not create JSON object: username\n");
918                         cJSON_Delete(pnfRegistrationFields);
919                         return NULL;
920                 }
921
922                 //TODO here we have the password from the docker container hardcoded: netconf
923                 if (cJSON_AddStringToObject(additionalFields, "password", "netconf") == NULL)
924                 {
925                         printf("Could not create JSON object: password\n");
926                         cJSON_Delete(pnfRegistrationFields);
927                         return NULL;
928                 }
929         }
930
931         if (cJSON_AddStringToObject(additionalFields, "reconnectOnChangedSchema", "false") == NULL)
932         {
933                 printf("Could not create JSON object: reconnectOnChangedSchema\n");
934                 cJSON_Delete(pnfRegistrationFields);
935                 return NULL;
936         }
937
938         if (cJSON_AddStringToObject(additionalFields, "sleep-factor", "1.5") == NULL)
939         {
940                 printf("Could not create JSON object: sleep-factor\n");
941                 cJSON_Delete(pnfRegistrationFields);
942                 return NULL;
943         }
944
945         if (cJSON_AddStringToObject(additionalFields, "tcpOnly", "false") == NULL)
946         {
947                 printf("Could not create JSON object: tcpOnly\n");
948                 cJSON_Delete(pnfRegistrationFields);
949                 return NULL;
950         }
951
952         if (cJSON_AddStringToObject(additionalFields, "connectionTimeout", "20000") == NULL)
953         {
954                 printf("Could not create JSON object: connectionTimeout\n");
955                 cJSON_Delete(pnfRegistrationFields);
956                 return NULL;
957         }
958
959         if (cJSON_AddStringToObject(additionalFields, "maxConnectionAttempts", "100") == NULL)
960         {
961                 printf("Could not create JSON object: maxConnectionAttempts\n");
962                 cJSON_Delete(pnfRegistrationFields);
963                 return NULL;
964         }
965
966         if (cJSON_AddStringToObject(additionalFields, "betweenAttemptsTimeout", "2000") == NULL)
967         {
968                 printf("Could not create JSON object: betweenAttemptsTimeout\n");
969                 cJSON_Delete(pnfRegistrationFields);
970                 return NULL;
971         }
972
973         if (cJSON_AddStringToObject(additionalFields, "keepaliveDelay", "120") == NULL)
974         {
975                 printf("Could not create JSON object: keepaliveDelay\n");
976                 cJSON_Delete(pnfRegistrationFields);
977                 return NULL;
978         }
979
980         return pnfRegistrationFields;
981 }
982
983 int     getNetconfAvailableFromConfigJson(void)
984 {
985         char *stringConfig = readConfigFileInString();
986
987         if (stringConfig == NULL)
988         {
989                 printf("Could not read JSON configuration file in string.");
990                 return 0;
991         }
992
993         cJSON *jsonConfig = cJSON_Parse(stringConfig);
994         if (jsonConfig == NULL)
995         {
996                 free(stringConfig);
997                 const char *error_ptr = cJSON_GetErrorPtr();
998                 if (error_ptr != NULL)
999                 {
1000                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1001                 }
1002                 return SR_ERR_OPERATION_FAILED;
1003         }
1004         //we don't need the string anymore
1005         free(stringConfig);
1006         stringConfig = NULL;
1007
1008         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1009         if (!cJSON_IsObject(notifDetails))
1010         {
1011                 printf("Configuration JSON is not as expected: notification-config is not an object");
1012                 cJSON_Delete(jsonConfig);
1013                 return SR_ERR_OPERATION_FAILED;
1014         }
1015
1016         cJSON *isNetconfAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-netconf-available");
1017         if (!cJSON_IsBool(isNetconfAvailable))
1018         {
1019                 printf("Configuration JSON is not as expected: is-netconf-available is not an object");
1020                 cJSON_Delete(jsonConfig);
1021                 return SR_ERR_OPERATION_FAILED;
1022         }
1023
1024         int is_netconf_available = (cJSON_IsTrue(isNetconfAvailable)) ? TRUE : FALSE;
1025
1026         cJSON_Delete(jsonConfig);
1027
1028         return is_netconf_available;
1029 }
1030
1031 int     getVesAvailableFromConfigJson(void)
1032 {
1033         char *stringConfig = readConfigFileInString();
1034
1035         if (stringConfig == NULL)
1036         {
1037                 printf("Could not read JSON configuration file in string.");
1038                 return 0;
1039         }
1040
1041         cJSON *jsonConfig = cJSON_Parse(stringConfig);
1042         if (jsonConfig == NULL)
1043         {
1044                 free(stringConfig);
1045                 const char *error_ptr = cJSON_GetErrorPtr();
1046                 if (error_ptr != NULL)
1047                 {
1048                         fprintf(stderr, "Could not parse JSON configuration! Error before: %s\n", error_ptr);
1049                 }
1050                 return SR_ERR_OPERATION_FAILED;
1051         }
1052         //we don't need the string anymore
1053         free(stringConfig);
1054         stringConfig = NULL;
1055
1056         cJSON *notifDetails = cJSON_GetObjectItemCaseSensitive(jsonConfig, "notification-config");
1057         if (!cJSON_IsObject(notifDetails))
1058         {
1059                 printf("Configuration JSON is not as expected: notification-config is not an object");
1060                 cJSON_Delete(jsonConfig);
1061                 return SR_ERR_OPERATION_FAILED;
1062         }
1063
1064         cJSON *isVesAvailable = cJSON_GetObjectItemCaseSensitive(notifDetails, "is-ves-available");
1065         if (!cJSON_IsBool(isVesAvailable))
1066         {
1067                 printf("Configuration JSON is not as expected: is-ves-available is not an object");
1068                 cJSON_Delete(jsonConfig);
1069                 return SR_ERR_OPERATION_FAILED;
1070         }
1071
1072         int is_netconf_available = (cJSON_IsTrue(isVesAvailable)) ? TRUE : FALSE;
1073
1074         cJSON_Delete(jsonConfig);
1075
1076         return is_netconf_available;
1077 }
1078
1079 /*
1080  * Dynamically allocated memory;
1081  * Caller needs to free the memory after it uses the value.
1082  *
1083 */
1084 cJSON*  vesCreateFaultFields(char *alarm_condition, char *alarm_object, char *severity, char *date_time, char *specific_problem)
1085 {
1086         cJSON *faultFields = cJSON_CreateObject();
1087         if (faultFields == NULL)
1088         {
1089                 printf("Could not create JSON object: faultFields\n");
1090                 return NULL;
1091         }
1092
1093         if (cJSON_AddStringToObject(faultFields, "faultFieldsVersion", "4.0") == NULL)
1094         {
1095                 printf("Could not create JSON object: faultFieldsVersion\n");
1096                 cJSON_Delete(faultFields);
1097                 return NULL;
1098         }
1099
1100         if (cJSON_AddStringToObject(faultFields, "alarmCondition", alarm_condition) == NULL)
1101         {
1102                 printf("Could not create JSON object: alarmCondition\n");
1103                 cJSON_Delete(faultFields);
1104                 return NULL;
1105         }
1106
1107         if (cJSON_AddStringToObject(faultFields, "alarmInterfaceA", alarm_object) == NULL)
1108         {
1109                 printf("Could not create JSON object: alarmInterfaceA\n");
1110                 cJSON_Delete(faultFields);
1111                 return NULL;
1112         }
1113
1114         if (cJSON_AddStringToObject(faultFields, "eventSourceType", "O_RAN_COMPONENT") == NULL)
1115         {
1116                 printf("Could not create JSON object: eventSourceType\n");
1117                 cJSON_Delete(faultFields);
1118                 return NULL;
1119         }
1120
1121         if (cJSON_AddStringToObject(faultFields, "specificProblem", specific_problem) == NULL)
1122         {
1123                 printf("Could not create JSON object: specificProblem\n");
1124                 cJSON_Delete(faultFields);
1125                 return NULL;
1126         }
1127
1128         if (cJSON_AddStringToObject(faultFields, "eventSeverity", severity) == NULL)
1129         {
1130                 printf("Could not create JSON object: eventSeverity\n");
1131                 cJSON_Delete(faultFields);
1132                 return NULL;
1133         }
1134
1135         if (cJSON_AddStringToObject(faultFields, "vfStatus", "Active") == NULL)
1136         {
1137                 printf("Could not create JSON object: vfStatus\n");
1138                 cJSON_Delete(faultFields);
1139                 return NULL;
1140         }
1141
1142         cJSON *alarmAdditionalInformation = cJSON_CreateObject();
1143         if (alarmAdditionalInformation == NULL)
1144         {
1145                 printf("Could not create JSON object: alarmAdditionalInformation\n");
1146                 cJSON_Delete(faultFields);
1147                 return NULL;
1148         }
1149         cJSON_AddItemToObject(faultFields, "alarmAdditionalInformation", alarmAdditionalInformation);
1150
1151         if (cJSON_AddStringToObject(alarmAdditionalInformation, "eventTime", date_time) == NULL)
1152         {
1153                 printf("Could not create JSON object: eventTime\n");
1154                 cJSON_Delete(faultFields);
1155                 return NULL;
1156         }
1157
1158         if (cJSON_AddStringToObject(alarmAdditionalInformation, "equipType", "O-RAN-sim") == NULL)
1159         {
1160                 printf("Could not create JSON object: equipType\n");
1161                 cJSON_Delete(faultFields);
1162                 return NULL;
1163         }
1164
1165         if (cJSON_AddStringToObject(alarmAdditionalInformation, "vendor", "Melacon") == NULL)
1166         {
1167                 printf("Could not create JSON object: vendor\n");
1168                 cJSON_Delete(faultFields);
1169                 return NULL;
1170         }
1171
1172         if (cJSON_AddStringToObject(alarmAdditionalInformation, "model", "Simulated Device") == NULL)
1173         {
1174                 printf("Could not create JSON object: model\n");
1175                 cJSON_Delete(faultFields);
1176                 return NULL;
1177         }
1178
1179         return faultFields;
1180 }
1181
1182 static cJSON* createSeverityCounters(counterAlarms count)
1183 {
1184     cJSON *severityCounters = cJSON_CreateObject();
1185     if (severityCounters == NULL)
1186     {
1187         printf("Could not create JSON object: severityCounters\n");
1188         return NULL;
1189     }
1190
1191     if (cJSON_AddNumberToObject(severityCounters, "severity-normal", count.normal) == NULL)
1192     {
1193         printf("Could not create JSON object: severity-normal\n");
1194         return NULL;
1195     }
1196
1197     if (cJSON_AddNumberToObject(severityCounters, "severity-warning", count.warning) == NULL)
1198     {
1199         printf("Could not create JSON object: severity-warning\n");
1200         return NULL;
1201     }
1202
1203     if (cJSON_AddNumberToObject(severityCounters, "severity-minor", count.minor) == NULL)
1204     {
1205         printf("Could not create JSON object: severity-minor\n");
1206         return NULL;
1207     }
1208
1209     if (cJSON_AddNumberToObject(severityCounters, "severity-major", count.major) == NULL)
1210     {
1211         printf("Could not create JSON object: severity-major\n");
1212         return NULL;
1213     }
1214
1215     if (cJSON_AddNumberToObject(severityCounters, "severity-critical", count.critical) == NULL)
1216     {
1217         printf("Could not create JSON object: severity-critical\n");
1218         return NULL;
1219     }
1220
1221     return severityCounters;
1222 }
1223
1224 void writeStatusFile(char *status)
1225 {
1226         char status_file[200];
1227         sprintf(status_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1228         FILE * f = fopen (status_file, "w");
1229
1230         if (f)
1231         {
1232                 fputs(status, f);
1233                 fclose(f);
1234         }
1235         else
1236         {
1237                 printf("Could not write status file!\n");
1238         }
1239 }
1240
1241 int     writeSkeletonStatusFile()
1242 {
1243     cJSON *statusObject = cJSON_CreateObject();
1244     if (statusObject == NULL)
1245     {
1246         printf("Could not create JSON object: statusObject\n");
1247         return SR_ERR_OPERATION_FAILED;
1248     }
1249
1250     // counterAlarms counter = {
1251     //     .normal = 0,
1252     //     .warning = 0,
1253     //     .minor = 0,
1254     //     .major = 0,
1255     //     .critical = 0
1256     // };
1257
1258     // cJSON *totalVesNotifications = createSeverityCounters(counter);
1259     // if (totalVesNotifications == NULL)
1260     // {
1261     //     printf("Could not create JSON object: totalVesNotifications\n");
1262     //     cJSON_Delete(statusObject);
1263     //     return SR_ERR_OPERATION_FAILED;
1264     // }
1265     // cJSON_AddItemToObject(statusObject, "total-ves-notifications-sent", totalVesNotifications);
1266
1267     // cJSON *totalNetconfNotifications = createSeverityCounters(counter);
1268     // if (totalNetconfNotifications == NULL)
1269     // {
1270     //     printf("Could not create JSON object: totalNetconfNotifications\n");
1271     //     cJSON_Delete(statusObject);
1272     //     return SR_ERR_OPERATION_FAILED;
1273     // }
1274     // cJSON_AddItemToObject(statusObject, "total-netconf-notifications-sent", totalNetconfNotifications);
1275
1276     cJSON *deviceList = cJSON_CreateArray();
1277     if (deviceList == NULL)
1278     {
1279         printf("Could not create JSON object: deviceList\n");
1280         cJSON_Delete(statusObject);
1281         return SR_ERR_OPERATION_FAILED;
1282         }
1283     cJSON_AddItemToObject(statusObject, "device-list", deviceList);
1284
1285     char *status_string = NULL;
1286
1287     status_string = cJSON_PrintUnformatted(statusObject);
1288
1289     writeStatusFile(status_string);
1290
1291     return SR_ERR_OK;
1292 }
1293
1294 /*
1295  * Dynamically allocated memory;
1296  * Caller needs to free the memory after it uses the value.
1297  *
1298 */
1299 char*   readStatusFileInString(void)
1300 {
1301         char * buffer = 0;
1302         long length;
1303         char config_file[200];
1304         sprintf(config_file, "%s/status.json", getenv("SCRIPTS_DIR"));
1305         FILE * f = fopen (config_file, "rb");
1306
1307         if (f)
1308         {
1309           fseek (f, 0, SEEK_END);
1310           length = ftell (f);
1311           fseek (f, 0, SEEK_SET);
1312           buffer = malloc (length + 1);
1313           if (buffer)
1314           {
1315             fread (buffer, 1, length, f);
1316           }
1317           fclose (f);
1318           buffer[length] = '\0';
1319         }
1320
1321         if (buffer)
1322         {
1323           return buffer;
1324         }
1325
1326         return NULL;
1327 }
1328
1329 /*
1330  * Dynamically allocated memory;
1331  * Caller needs to free the memory after it uses the value.
1332  *
1333 */
1334 cJSON*  getDeviceListFromStatusFile(void)
1335 {
1336     char *stringStatus = readStatusFileInString();
1337
1338         if (stringStatus == NULL)
1339         {
1340                 printf("Could not read status file!\n");
1341                 return NULL;
1342         }
1343
1344         cJSON *jsonStatus = cJSON_Parse(stringStatus);
1345         if (jsonStatus == NULL)
1346         {
1347                 free(stringStatus);
1348                 const char *error_ptr = cJSON_GetErrorPtr();
1349                 if (error_ptr != NULL)
1350                 {
1351                         fprintf(stderr, "Could not parse JSON status! Error before: %s\n", error_ptr);
1352                 }
1353                 return NULL;
1354         }
1355         //we don't need the string anymore
1356         free(stringStatus);
1357         stringStatus = NULL;
1358
1359     return jsonStatus;
1360 }
1361
1362 cJSON* createDeviceListEntry(counterAlarms ves_counter, counterAlarms netconf_counter)
1363 {
1364     cJSON *deviceListEntry = cJSON_CreateObject();
1365     if (deviceListEntry == NULL)
1366     {
1367         printf("Could not create JSON object: deviceListEntry\n");
1368         return NULL;
1369     }
1370
1371     char hostname[100];
1372     sprintf(hostname, "%s", getenv("HOSTNAME"));
1373
1374     if (cJSON_AddStringToObject(deviceListEntry, "device-name", hostname) == NULL)
1375     {
1376         printf("Could not create JSON object: device-name\n");
1377         cJSON_Delete(deviceListEntry);
1378         return NULL;
1379     }
1380
1381     cJSON *vesNotificationsSent = createSeverityCounters(ves_counter);
1382     if (vesNotificationsSent == NULL)
1383     {
1384         printf("Could not create JSON object: vesNotificationsSent\n");
1385         cJSON_Delete(deviceListEntry);
1386         return NULL;
1387     }
1388     cJSON_AddItemToObject(deviceListEntry, "ves-notifications-sent", vesNotificationsSent);
1389
1390     cJSON *netconfNotificationsSent = createSeverityCounters(netconf_counter);
1391     if (netconfNotificationsSent == NULL)
1392     {
1393         printf("Could not create JSON object: netconfNotificationsSent\n");
1394         cJSON_Delete(deviceListEntry);
1395         return NULL;
1396     }
1397     cJSON_AddItemToObject(deviceListEntry, "netconf-notifications-sent", netconfNotificationsSent);
1398
1399     return deviceListEntry;
1400 }
1401
1402 static void modifySeverityCounters(cJSON **severityCounters, counterAlarms count)
1403 {
1404     cJSON *severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-normal");
1405     if (!cJSON_IsNumber(severity))
1406     {
1407         printf("Status JSON is not as expected: severity-normal is not an number");
1408         return;
1409     }
1410     //we set the value of the severity-normal object
1411     cJSON_SetNumberValue(severity, count.normal);
1412
1413     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-warning");
1414     if (!cJSON_IsNumber(severity))
1415     {
1416         printf("Status JSON is not as expected: severity-warning is not an number");
1417         return;
1418     }
1419     //we set the value of the severity-warning object
1420     cJSON_SetNumberValue(severity, count.warning);
1421
1422     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-minor");
1423     if (!cJSON_IsNumber(severity))
1424     {
1425         printf("Status JSON is not as expected: severity-minor is not an number");
1426         return;
1427     }
1428     //we set the value of the severity-minor object
1429     cJSON_SetNumberValue(severity, count.minor);
1430
1431     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-major");
1432     if (!cJSON_IsNumber(severity))
1433     {
1434         printf("Status JSON is not as expected: severity-major is not an number");
1435         return;
1436     }
1437     //we set the value of the severity-major object
1438         cJSON_SetNumberValue(severity, count.major);
1439
1440     severity= cJSON_GetObjectItemCaseSensitive(*severityCounters, "severity-critical");
1441     if (!cJSON_IsNumber(severity))
1442     {
1443         printf("Status JSON is not as expected: severity-critical is not an number");
1444         return;
1445     }
1446     //we set the value of the severity-critical object
1447         cJSON_SetNumberValue(severity, count.critical);
1448
1449     return;
1450 }
1451
1452 static void modifyDeviceListEntry(cJSON **deviceListEntry, counterAlarms ves_counter, counterAlarms netconf_counter)
1453 {
1454     cJSON *vesNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "ves-notifications-sent");
1455     if (!cJSON_IsObject(vesNotificationsSent))
1456     {
1457         printf("Status JSON is not as expected: ves-notifications-sent is not a object");
1458         return;
1459     }
1460
1461     modifySeverityCounters(&vesNotificationsSent, ves_counter);
1462
1463     cJSON *netconfNotificationsSent= cJSON_GetObjectItemCaseSensitive(*deviceListEntry, "netconf-notifications-sent");
1464     if (!cJSON_IsObject(netconfNotificationsSent))
1465     {
1466         printf("Status JSON is not as expected: netconf-notifications-sent is not a object");
1467         return;
1468     }
1469
1470     modifySeverityCounters(&netconfNotificationsSent, netconf_counter);
1471 }
1472
1473 int writeStatusNotificationCounters(counterAlarms ves_counter, counterAlarms netconf_counter)
1474 {
1475         cJSON *jsonStatus = getDeviceListFromStatusFile();
1476
1477         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1478         if (!cJSON_IsArray(deviceList))
1479         {
1480                 printf("Status JSON is not as expected: device-list is not an object");
1481                 cJSON_Delete(jsonStatus);
1482                 return SR_ERR_OPERATION_FAILED;
1483         }
1484
1485     int array_size = cJSON_GetArraySize(deviceList);
1486
1487     int found = 0;
1488     for (int i=0; i<array_size; ++i)
1489     {
1490         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1491         char hostname[100];
1492         sprintf(hostname, "%s", getenv("HOSTNAME"));
1493
1494         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1495         if (!cJSON_IsString(deviceName))
1496         {
1497             printf("Status JSON is not as expected: device-name is not a string.");
1498             cJSON_Delete(jsonStatus);
1499             return SR_ERR_OPERATION_FAILED;
1500         }
1501         char *deviceNameString = cJSON_GetStringValue(deviceName);
1502
1503         if (strcmp(hostname, deviceNameString) == 0)
1504         {
1505             modifyDeviceListEntry(&deviceListEntry, ves_counter, netconf_counter);
1506             found = 1;
1507             break;
1508         }
1509     }
1510     if (found == 0)
1511     {
1512         cJSON* deviceListEntry = createDeviceListEntry(ves_counter, netconf_counter);
1513     
1514         cJSON_AddItemToArray(deviceList, deviceListEntry);  
1515     }
1516
1517         //writing the new JSON to the configuration file
1518         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1519         writeStatusFile(stringStatus);
1520
1521         cJSON_Delete(jsonStatus);
1522
1523         return SR_ERR_OK;
1524 }
1525
1526
1527 int removeDeviceEntryFromStatusFile(char *containerId)
1528 {
1529     cJSON *jsonStatus = getDeviceListFromStatusFile();
1530
1531         cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1532         if (!cJSON_IsArray(deviceList))
1533         {
1534                 printf("Status JSON is not as expected: device-list is not an object");
1535                 cJSON_Delete(jsonStatus);
1536                 return SR_ERR_OPERATION_FAILED;
1537         }
1538
1539     int array_size = cJSON_GetArraySize(deviceList);
1540     int found = array_size;
1541
1542     for (int i=0; i<array_size; ++i)
1543     {
1544         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1545         char hostname[100];
1546         sprintf(hostname, "%s", getenv("HOSTNAME"));
1547
1548         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1549         if (!cJSON_IsString(deviceName))
1550         {
1551             printf("Status JSON is not as expected: device-name is not a string.");
1552             cJSON_Delete(jsonStatus);
1553             return SR_ERR_OPERATION_FAILED;
1554         }
1555         char *deviceNameString = cJSON_GetStringValue(deviceName);
1556
1557         if (strcmp(containerId, deviceNameString) == 0)
1558         {
1559             found = i;
1560             break;
1561         }
1562     }
1563
1564     if (found < array_size)
1565     {
1566         cJSON_DeleteItemFromArray(deviceList, found);
1567     }
1568     else
1569     {
1570         printf("Could not find status file entry for device with id=\"%s\"", containerId);
1571     }
1572
1573         //writing the new JSON to the configuration file
1574         char *stringStatus = cJSON_PrintUnformatted(jsonStatus);
1575         writeStatusFile(stringStatus);
1576
1577         cJSON_Delete(jsonStatus);
1578
1579         return SR_ERR_OK;
1580 }
1581
1582 int compute_notifications_count(counterAlarms *ves_counter, counterAlarms *netconf_counter)
1583 {
1584     ves_counter->normal = ves_counter->warning = \
1585             ves_counter->minor = ves_counter->major = \
1586             ves_counter->critical = 0;
1587     netconf_counter->normal = netconf_counter->warning = \
1588             netconf_counter->minor = netconf_counter->major = \
1589             netconf_counter->critical = 0;
1590
1591     cJSON *jsonStatus = getDeviceListFromStatusFile();
1592
1593     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1594         if (!cJSON_IsArray(deviceList))
1595         {
1596                 printf("Status JSON is not as expected: device-list is not an object");
1597                 cJSON_Delete(jsonStatus);
1598                 return SR_ERR_OPERATION_FAILED;
1599         }
1600
1601     int array_size = cJSON_GetArraySize(deviceList);
1602
1603     for (int i=0; i<array_size; ++i)
1604     {
1605         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1606
1607         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1608         if (!cJSON_IsObject(vesNotifications))
1609         {
1610             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1611             cJSON_Delete(jsonStatus);
1612             return SR_ERR_OPERATION_FAILED;
1613         }
1614
1615         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1616         if (!cJSON_IsNumber(severity))
1617         {
1618             printf("Status JSON is not as expected: severity-normal is not a string.");
1619             cJSON_Delete(jsonStatus);
1620             return SR_ERR_OPERATION_FAILED;
1621         }
1622         int counter = (int)(severity->valuedouble);
1623         ves_counter->normal += counter;
1624
1625         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1626         if (!cJSON_IsNumber(severity))
1627         {
1628             printf("Status JSON is not as expected: severity-warning is not a string.");
1629             cJSON_Delete(jsonStatus);
1630             return SR_ERR_OPERATION_FAILED;
1631         }
1632         counter = (int)(severity->valuedouble);
1633         ves_counter->warning += counter;
1634
1635         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
1636         if (!cJSON_IsNumber(severity))
1637         {
1638             printf("Status JSON is not as expected: severity-minor is not a string.");
1639             cJSON_Delete(jsonStatus);
1640             return SR_ERR_OPERATION_FAILED;
1641         }
1642         counter = (int)(severity->valuedouble);
1643         ves_counter->minor += counter;
1644
1645         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
1646         if (!cJSON_IsNumber(severity))
1647         {
1648             printf("Status JSON is not as expected: severity-major is not a string.");
1649             cJSON_Delete(jsonStatus);
1650             return SR_ERR_OPERATION_FAILED;
1651         }
1652         counter = (int)(severity->valuedouble);
1653         ves_counter->major += counter;
1654
1655         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
1656         if (!cJSON_IsNumber(severity))
1657         {
1658             printf("Status JSON is not as expected: severity-critical is not a string.");
1659             cJSON_Delete(jsonStatus);
1660             return SR_ERR_OPERATION_FAILED;
1661         }
1662         counter = (int)(severity->valuedouble);
1663         ves_counter->critical += counter;
1664
1665         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
1666         if (!cJSON_IsObject(netconfNotifications))
1667         {
1668             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
1669             cJSON_Delete(jsonStatus);
1670             return SR_ERR_OPERATION_FAILED;
1671         }
1672
1673         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
1674         if (!cJSON_IsNumber(severity))
1675         {
1676             printf("Status JSON is not as expected: severity-normal is not a string.");
1677             cJSON_Delete(jsonStatus);
1678             return SR_ERR_OPERATION_FAILED;
1679         }
1680         
1681         counter = (int)(severity->valuedouble);
1682         netconf_counter->normal += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1683
1684         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
1685         if (!cJSON_IsNumber(severity))
1686         {
1687             printf("Status JSON is not as expected: severity-warning is not a string.");
1688             cJSON_Delete(jsonStatus);
1689             return SR_ERR_OPERATION_FAILED;
1690         }
1691         counter = (int)(severity->valuedouble);
1692         netconf_counter->warning += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1693
1694         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
1695         if (!cJSON_IsNumber(severity))
1696         {
1697             printf("Status JSON is not as expected: severity-minor is not a string.");
1698             cJSON_Delete(jsonStatus);
1699             return SR_ERR_OPERATION_FAILED;
1700         }
1701         counter = (int)(severity->valuedouble);
1702         netconf_counter->minor += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1703
1704         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
1705         if (!cJSON_IsNumber(severity))
1706         {
1707             printf("Status JSON is not as expected: severity-major is not a string.");
1708             cJSON_Delete(jsonStatus);
1709             return SR_ERR_OPERATION_FAILED;
1710         }
1711         counter = (int)(severity->valuedouble);
1712         netconf_counter->major += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1713
1714         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
1715         if (!cJSON_IsNumber(severity))
1716         {
1717             printf("Status JSON is not as expected: severity-critical is not a string.");
1718             cJSON_Delete(jsonStatus);
1719             return SR_ERR_OPERATION_FAILED;
1720         }
1721         counter = (int)(severity->valuedouble);
1722         netconf_counter->critical += (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1723     }
1724
1725     cJSON_Delete(jsonStatus);
1726
1727     return SR_ERR_OK;
1728 }
1729
1730 int getDeviceCounters(char *containerId, counterAlarms *ves_counter, counterAlarms *netconf_counter)
1731 {
1732     cJSON *jsonStatus = getDeviceListFromStatusFile();
1733
1734     cJSON *deviceList = cJSON_GetObjectItemCaseSensitive(jsonStatus, "device-list");
1735         if (!cJSON_IsArray(deviceList))
1736         {
1737                 printf("Status JSON is not as expected: device-list is not an object");
1738                 cJSON_Delete(jsonStatus);
1739                 return SR_ERR_OPERATION_FAILED;
1740         }
1741
1742     int array_size = cJSON_GetArraySize(deviceList);
1743
1744     for (int i=0; i<array_size; ++i)
1745     {
1746         cJSON *deviceListEntry = cJSON_GetArrayItem(deviceList, i);
1747
1748         cJSON *deviceName = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "device-name");
1749         if (!cJSON_IsString(deviceName))
1750         {
1751             printf("Status JSON is not as expected: device-name is not a string.");
1752             cJSON_Delete(jsonStatus);
1753             return SR_ERR_OPERATION_FAILED;
1754         }
1755         char *deviceNameString = cJSON_GetStringValue(deviceName);
1756
1757         if (strcmp(deviceNameString, containerId) != 0)
1758         {
1759             continue;
1760         }
1761
1762         cJSON *vesNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "ves-notifications-sent");
1763         if (!cJSON_IsObject(vesNotifications))
1764         {
1765             printf("Status JSON is not as expected: ves-notifications-sent is not an object.");
1766             cJSON_Delete(jsonStatus);
1767             return SR_ERR_OPERATION_FAILED;
1768         }
1769
1770         cJSON *severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-normal");
1771         if (!cJSON_IsNumber(severity))
1772         {
1773             printf("Status JSON is not as expected: severity-normal is not a string.");
1774             cJSON_Delete(jsonStatus);
1775             return SR_ERR_OPERATION_FAILED;
1776         }
1777         int counter = (int)(severity->valuedouble);
1778         ves_counter->normal = counter;
1779
1780         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-warning");
1781         if (!cJSON_IsNumber(severity))
1782         {
1783             printf("Status JSON is not as expected: severity-warning is not a string.");
1784             cJSON_Delete(jsonStatus);
1785             return SR_ERR_OPERATION_FAILED;
1786         }
1787         counter = (int)(severity->valuedouble);
1788         ves_counter->warning = counter;
1789
1790         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-minor");
1791         if (!cJSON_IsNumber(severity))
1792         {
1793             printf("Status JSON is not as expected: severity-minor is not a string.");
1794             cJSON_Delete(jsonStatus);
1795             return SR_ERR_OPERATION_FAILED;
1796         }
1797         counter = (int)(severity->valuedouble);
1798         ves_counter->minor = counter;
1799
1800         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-major");
1801         if (!cJSON_IsNumber(severity))
1802         {
1803             printf("Status JSON is not as expected: severity-major is not a string.");
1804             cJSON_Delete(jsonStatus);
1805             return SR_ERR_OPERATION_FAILED;
1806         }
1807         counter = (int)(severity->valuedouble);
1808         ves_counter->major = counter;
1809
1810         severity = cJSON_GetObjectItemCaseSensitive(vesNotifications, "severity-critical");
1811         if (!cJSON_IsNumber(severity))
1812         {
1813             printf("Status JSON is not as expected: severity-critical is not a string.");
1814             cJSON_Delete(jsonStatus);
1815             return SR_ERR_OPERATION_FAILED;
1816         }
1817         counter = (int)(severity->valuedouble);
1818         ves_counter->critical = counter;
1819
1820         cJSON *netconfNotifications = cJSON_GetObjectItemCaseSensitive(deviceListEntry, "netconf-notifications-sent");
1821         if (!cJSON_IsObject(netconfNotifications))
1822         {
1823             printf("Status JSON is not as expected: netconf-notifications-sent is not an object.");
1824             cJSON_Delete(jsonStatus);
1825             return SR_ERR_OPERATION_FAILED;
1826         }
1827
1828         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-normal");
1829         if (!cJSON_IsNumber(severity))
1830         {
1831             printf("Status JSON is not as expected: severity-normal is not a string.");
1832             cJSON_Delete(jsonStatus);
1833             return SR_ERR_OPERATION_FAILED;
1834         }
1835         
1836         counter = (int)(severity->valuedouble);
1837         netconf_counter->normal = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1838
1839         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-warning");
1840         if (!cJSON_IsNumber(severity))
1841         {
1842             printf("Status JSON is not as expected: severity-warning is not a string.");
1843             cJSON_Delete(jsonStatus);
1844             return SR_ERR_OPERATION_FAILED;
1845         }
1846         counter = (int)(severity->valuedouble);
1847         netconf_counter->warning = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1848
1849         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-minor");
1850         if (!cJSON_IsNumber(severity))
1851         {
1852             printf("Status JSON is not as expected: severity-minor is not a string.");
1853             cJSON_Delete(jsonStatus);
1854             return SR_ERR_OPERATION_FAILED;
1855         }
1856         counter = (int)(severity->valuedouble);
1857         netconf_counter->minor = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1858
1859         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-major");
1860         if (!cJSON_IsNumber(severity))
1861         {
1862             printf("Status JSON is not as expected: severity-major is not a string.");
1863             cJSON_Delete(jsonStatus);
1864             return SR_ERR_OPERATION_FAILED;
1865         }
1866         counter = (int)(severity->valuedouble);
1867         netconf_counter->major = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1868
1869         severity = cJSON_GetObjectItemCaseSensitive(netconfNotifications, "severity-critical");
1870         if (!cJSON_IsNumber(severity))
1871         {
1872             printf("Status JSON is not as expected: severity-critical is not a string.");
1873             cJSON_Delete(jsonStatus);
1874             return SR_ERR_OPERATION_FAILED;
1875         }
1876         counter = (int)(severity->valuedouble);
1877         netconf_counter->critical = (counter * NETCONF_CONNECTIONS_PER_DEVICE);
1878     }
1879
1880     cJSON_Delete(jsonStatus);
1881
1882     return SR_ERR_OK;
1883 }