Initial commit of the O1 simulator framework.
[sim/o1-interface.git] / ntsimulator / src / ves-messages / heartbeat.c
1 /*
2  * heartbeat.c
3  *
4  *  Created on: Oct 24, 2019
5  *      Author: parallels
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <inttypes.h>
13 #include <limits.h>
14 #include <string.h>
15 #include <time.h>
16 #include <math.h>
17 #include <sys/time.h>
18
19 #include <pthread.h>
20
21 #include "heartbeat.h"
22 #include "sysrepo.h"
23 #include "sysrepo/values.h"
24
25 #include "utils.h"
26
27 #define LINE_BUFSIZE 128
28 #define SLEEP_BEFORE_PNF_AUTOREG 60
29
30 volatile int exit_application = 0;
31
32 pthread_mutex_t lock;
33
34 static  CURL *curl;
35
36 int _init_curl()
37 {
38         curl = curl_easy_init();
39
40         if (curl == NULL) {
41                 printf("cURL initialization error! Aborting call!\n");
42                 return SR_ERR_OPERATION_FAILED;
43         }
44
45         return SR_ERR_OK;
46 }
47
48 int cleanup_curl()
49 {
50         if (curl != NULL)
51         {
52                 curl_easy_cleanup(curl);
53         }
54
55         return SR_ERR_OK;
56 }
57
58 //static void prepare_ves_message_curl(void)
59 //{
60 //      curl_easy_reset(curl);
61 //      set_curl_common_info();
62 //
63 //      char *ves_ip = getVesIpFromConfigJson();
64 //      int ves_port = getVesPortFromConfigJson();
65 //
66 //      char url[100];
67 //      sprintf(url, "http://%s:%d/eventListener/v7", ves_ip, ves_port);
68 //      curl_easy_setopt(curl, CURLOPT_URL, url);
69 //
70 //      free(ves_ip);
71 //
72 ////    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
73 //
74 //      return;
75 //}
76 /*
77  * Heartbeat payload example
78  *
79  * {
80   "event": {
81     "commonEventHeader": {
82       "domain": "heartbeat",
83       "eventId": "parallels-Parallels-Virtual-Platform_2019-10-24T10:25:25.514Z",
84       "eventName": "heartbeat_Controller",
85       "eventType": "Controller",
86       "sequence": 0,
87       "priority": "Low",
88       "reportingEntityId": "",
89       "reportingEntityName": "parallels-Parallels-Virtual-Platform",
90       "sourceId": "",
91       "sourceName": "parallels-Parallels-Virtual-Platform",
92       "startEpochMicrosec": 1571912725514,
93       "lastEpochMicrosec": 1571912725514,
94       "nfNamingCode": "sdn controller",
95       "nfVendorName": "sdn",
96       "timeZoneOffset": "+00:00",
97       "version": "4.0.1",
98       "vesEventListenerVersion":"7.0.1"
99     },
100     "heartbeatFields": {
101       "heartbeatFieldsVersion": "3.0",
102       "heartbeatInterval": 20,
103       "additionalFields": {
104         "eventTime": "2019-10-24T10:25:25.514Z"
105       }
106     }
107   }
108 }
109 *
110 * */
111
112 static int send_heartbeat(int heartbeat_interval)
113 {
114         CURLcode res;
115         static int sequence_number = 0;
116
117         prepare_ves_message_curl(curl);
118
119         cJSON *postDataJson = cJSON_CreateObject();
120
121         cJSON *event = cJSON_CreateObject();
122         if (event == NULL)
123         {
124                 printf("Could not create JSON object: event\n");
125                 return 1;
126         }
127         cJSON_AddItemToObject(postDataJson, "event", event);
128
129         char hostname[100];
130         sprintf(hostname, "%s", getenv("HOSTNAME"));
131
132         cJSON *commonEventHeader = vesCreateCommonEventHeader("heartbeat", "Controller", hostname, sequence_number++);
133         if (commonEventHeader == NULL)
134         {
135                 printf("Could not create JSON object: commonEventHeader\n");
136                 return 1;
137         }
138         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
139
140         cJSON *heartbeatFields = vesCreateHeartbeatFields(heartbeat_interval);
141         if (heartbeatFields == NULL)
142         {
143                 printf("Could not create JSON object: heartbeatFields\n");
144                 return 1;
145         }
146         cJSON_AddItemToObject(event, "heartbeatFields", heartbeatFields);
147
148     char *post_data_string = NULL;
149
150         post_data_string = cJSON_PrintUnformatted(postDataJson);
151
152         printf("Post data JSON:\n%s\n", post_data_string);
153
154         if (postDataJson != NULL)
155         {
156                 cJSON_Delete(postDataJson);
157         }
158
159         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
160
161         res = curl_easy_perform(curl);
162
163         if (res != CURLE_OK)
164         {
165                 printf("Failed to send cURL...\n");
166                 return SR_ERR_OPERATION_FAILED;
167         }
168
169         return SR_ERR_OK;
170 }
171
172 static void
173 sigint_handler(int signum)
174 {
175     exit_application = 1;
176 }
177
178 static int send_pnf_registration_instance(char *hostname, int port, bool is_tls)
179 {
180         CURLcode res;
181         static int sequence_number = 0;
182
183         prepare_ves_message_curl(curl);
184
185         cJSON *postDataJson = cJSON_CreateObject();
186
187         cJSON *event = cJSON_CreateObject();
188         if (event == NULL)
189         {
190                 printf("Could not create JSON object: event\n");
191                 return 1;
192         }
193         cJSON_AddItemToObject(postDataJson, "event", event);
194
195         char source_name[100];
196         sprintf(source_name, "%s_%d", hostname, port);
197
198         cJSON *commonEventHeader = vesCreateCommonEventHeader("pnfRegistration", "EventType5G", source_name, sequence_number++);
199         if (commonEventHeader == NULL)
200         {
201                 printf("Could not create JSON object: commonEventHeader\n");
202                 return 1;
203         }
204         cJSON_AddItemToObject(event, "commonEventHeader", commonEventHeader);
205
206         cJSON *pnfRegistrationFields = vesCreatePnfRegistrationFields(port, is_tls);
207         if (pnfRegistrationFields == NULL)
208         {
209                 printf("Could not create JSON object: pnfRegistrationFields\n");
210                 return 1;
211         }
212         cJSON_AddItemToObject(event, "pnfRegistrationFields", pnfRegistrationFields);
213
214     char *post_data_string = NULL;
215
216         post_data_string = cJSON_PrintUnformatted(postDataJson);
217
218         printf("Post data JSON:\n%s\n", post_data_string);
219
220         if (postDataJson != NULL)
221         {
222                 cJSON_Delete(postDataJson);
223         }
224
225         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data_string);
226
227         res = curl_easy_perform(curl);
228
229         if (res != CURLE_OK)
230         {
231                 printf("Failed to send cURL...\n");
232                 return SR_ERR_OPERATION_FAILED;
233         }
234
235         return SR_ERR_OK;
236 }
237
238 static void pnf_registration(void)
239 {
240         // delay the PNF Registration VES message, until anything else is initialized
241         printf("delay the PNF Registration VES message, until anything else is initialized");
242         sleep(SLEEP_BEFORE_PNF_AUTOREG);
243
244         int is_reg = getVesRegistrationFromConfigJson();
245
246         if (!is_reg)
247         {
248                 //ves-registration object is set to False, we do not make an automatic PNF registration
249                 printf("ves-registration object is set to False, we do not make an automatic PNF registration");
250                 return;
251         }
252
253         int rc = SR_ERR_OK, netconf_port_base = 0;
254         char *netconf_base_string = getenv("NETCONF_BASE");
255         char *hostname_string = getenv("HOSTNAME");
256
257         if (netconf_base_string != NULL)
258         {
259                 rc = sscanf(netconf_base_string, "%d", &netconf_port_base);
260                 if (rc != 1)
261                 {
262                         printf("Could not find the NETCONF base port, aborting the PNF registration...\n");
263                         return;
264                 }
265         }
266
267         //TODO This is where we hardcoded: 7 devices will have SSH connections and 3 devices will have TLS connections
268         for (int port = 0; port < NETCONF_CONNECTIONS_PER_DEVICE - 3; ++port)
269         {
270                 pthread_mutex_lock(&lock);
271                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, FALSE);
272                 if (rc != SR_ERR_OK)
273                 {
274                         printf("Could not send PNF Registration SSH message...\n");
275                 }
276                 pthread_mutex_unlock(&lock);
277         }
278         for (int port = NETCONF_CONNECTIONS_PER_DEVICE - 3; port < NETCONF_CONNECTIONS_PER_DEVICE; ++port)
279         {
280                 pthread_mutex_lock(&lock);
281                 rc = send_pnf_registration_instance(hostname_string, netconf_port_base + port, TRUE);
282                 pthread_mutex_unlock(&lock);
283                 if (rc != SR_ERR_OK)
284                 {
285                         printf("Could not send PNF Registration TLS message...\n");
286                 }
287         }
288
289         return;
290 }
291
292 int
293 main(int argc, char **argv)
294 {
295     int rc = SR_ERR_OK;
296
297     int heartbeat_interval = 120; //seconds
298
299     setbuf(stdout, NULL);
300
301     if (pthread_mutex_init(&lock, NULL) != 0)
302         {
303                 printf("Mutex init failed...\n");
304                 goto cleanup;
305         }
306
307     pthread_t pnf_autoregistration_thread;
308         if(pthread_create(&pnf_autoregistration_thread, NULL, pnf_registration, NULL))
309         {
310                 fprintf(stderr, "Could not create thread for pnf auto registration\n");
311                 goto cleanup;
312         }
313
314     rc = _init_curl();
315     if (rc != SR_ERR_OK)
316     {
317         fprintf(stderr, "Could not initialize cURL: %s\n", sr_strerror(rc));
318         goto cleanup;
319     }
320
321     /* loop until ctrl-c is pressed / SIGINT is received */
322     signal(SIGINT, sigint_handler);
323     signal(SIGTERM, sigint_handler);
324     signal(SIGPIPE, SIG_IGN);
325
326     while (!exit_application)
327     {
328         heartbeat_interval = getVesHeartbeatPeriodFromConfigJson();
329
330         if (heartbeat_interval > 0)
331         {
332                 pthread_mutex_lock(&lock);
333                         send_heartbeat(heartbeat_interval);
334                         pthread_mutex_unlock(&lock);
335                         sleep(heartbeat_interval);
336         }
337         else
338         {
339                 sleep(1);
340         }
341     }
342
343     printf("Application exit requested, exiting.\n");
344
345 cleanup:
346
347     rc = cleanup_curl();
348
349     return rc;
350 }
351