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