blob: fce544cc3a7afa9773b2f8c85014e1a5bcdb01ff [file] [log] [blame]
Alex Stancu29ce3682019-11-02 10:38:59 +02001/*
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
30volatile int exit_application = 0;
31
32pthread_mutex_t lock;
33
34static CURL *curl;
35
36int _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
48int 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
112static 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
172static void
173sigint_handler(int signum)
174{
175 exit_application = 1;
176}
177
178static 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
238static 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
292int
293main(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
345cleanup:
346
347 rc = cleanup_curl();
348
349 return rc;
350}
351