1 /*************************************************************************//**
3 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
5 * Unless otherwise specified, all software contained herein is
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ****************************************************************************/
19 /**************************************************************************//**
21 * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
23 * This file implements the EVEL library which is intended to provide a
24 * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
25 * that VNFs can use it without worrying about details of:
27 * * The API's encoding into JSON.
28 * * The API's transport over HTTP/HTTPS.
30 ****************************************************************************/
36 #include <curl/curl.h>
39 #include "evel_internal.h"
40 #include "evel_throttle.h"
43 /**************************************************************************//**
44 * The type of equipment represented by this VNF.
45 *****************************************************************************/
46 EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
48 /**************************************************************************//**
49 * The Functional Role of the equipment represented by this VNF.
50 *****************************************************************************/
51 char *functional_role = NULL;
53 /**************************************************************************//**
54 * Library initialization.
56 * Initialize the EVEL library.
58 * @note This function initializes the cURL library. Applications making use
59 * of libcurl may need to pull the initialization out of here. Note
60 * also that this function is not threadsafe as a result - refer to
61 * libcurl's API documentation for relevant warnings.
63 * @sa Matching Term function.
65 * @param fqdn The API's FQDN or IP address.
66 * @param port The API's port.
67 * @param bakup_fqdn The API's Backup FQDN or IP address.
68 * @param bakup_port The API's Backup port.
69 * @param path The optional path (may be NULL).
70 * @param topic The optional topic part of the URL (may be NULL).
71 * @param ring buf size Ring buffer size
72 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
73 * @param activmode Whether to use ActivStandby(0) collectors or ActiveStandby(1)
74 * @param cert_file_path Path to client certificate file
75 * @param key_file_path Path to client key file
76 * @param ca_info Path to CA cert file
77 * @param ca_file_path Path to CA cert files
78 * @param verify_peer SSL verification of peer 0 or 1
79 * @param verify_host SSL verification of host 0 or 1
80 * @param username Username for Basic Authentication of requests.
81 * @param password Password for Basic Authentication of requests.
82 * @param bakup_username Username for Basic Authentication of Bakup FQDN.
83 * @param bakup_password Password for Basic Authentication of Bakup FQDN.
84 * @param source_ip The ip of node we represent.(NULL for default ip)
85 * @param bakup_source_ip The ip bakup fqdn interface.(NULL for default ip)
86 * @param source_type The kind of node we represent.
87 * @param role The role this node undertakes.
88 * @param verbosity 0 for normal operation, positive values for chattier
91 * @returns Status code
92 * @retval EVEL_SUCCESS On success
93 * @retval ::EVEL_ERR_CODES On failure.
94 *****************************************************************************/
95 EVEL_ERR_CODES evel_initialize(const char * const fqdn,
97 const char * const bakup_fqdn,
99 const char * const path,
100 const char * const topic,
104 const char * const cert_file_path,
105 const char * const key_file_path,
106 const char * const ca_info,
107 const char * const ca_file_path,
110 const char * const username,
111 const char * const password,
112 const char * const bakup_username,
113 const char * const bakup_password,
114 const char * const source_ip,
115 const char * const bakup_source_ip,
116 EVEL_SOURCE_TYPES source_type,
117 const char * const role,
121 EVEL_ERR_CODES rc = EVEL_SUCCESS;
122 char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
123 char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
124 char bakup_api_url[EVEL_MAX_URL_LEN + 1] = {0};
125 char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
126 char path_url[EVEL_MAX_URL_LEN + 1] = {0};
127 char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
128 char version_string[10] = {0};
130 char * bakup_coll = NULL;
132 /***************************************************************************/
133 /* Check assumptions. */
134 /***************************************************************************/
135 assert(fqdn != NULL);
136 assert(port > 0 && port <= 65535);
137 assert(source_type < EVEL_MAX_SOURCE_TYPES);
138 assert(role != NULL);
140 if( bakup_fqdn != NULL ) {
141 assert(bakup_port > 0 && bakup_port <= 65535);
144 /***************************************************************************/
145 /* Start logging so we can report on progress. */
146 /***************************************************************************/
147 if( verbosity >= EVEL_LOG_MIN && verbosity <= EVEL_LOG_MAX)
148 log_initialize(verbosity, "EVEL");
150 log_initialize(EVEL_LOG_MIN, "EVEL");
151 EVEL_INFO("EVEL started");
152 EVEL_INFO("API server is: %s", fqdn);
153 EVEL_INFO("API port is: %d", port);
157 EVEL_INFO("API path is: %s", path);
161 EVEL_INFO("No API path");
166 EVEL_INFO("API topic is: %s", topic);
170 EVEL_INFO("No API topic");
173 EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
175 assert( verify_peer >= 0 );
176 assert( verify_host >= 0 );
177 if (cert_file_path != NULL)
179 EVEL_INFO("Client cert is: %s", cert_file_path);
183 EVEL_INFO("No Client cert");
185 if (key_file_path != NULL)
187 EVEL_INFO("Key file is: %s", key_file_path);
191 EVEL_INFO("No Key file");
193 if (ca_file_path != NULL)
195 EVEL_INFO("Client CA certs path is: %s", ca_file_path);
199 EVEL_INFO("No CA certs path");
203 EVEL_INFO("Client CA cert file is: %s", ca_info);
207 EVEL_INFO("No CA cert file");
210 EVEL_INFO("Event Source Type is: %d", source_type);
211 EVEL_INFO("Functional Role is: %s", role);
212 EVEL_INFO("Log verbosity is: %d", verbosity);
214 /***************************************************************************/
215 /* Initialize event throttling to the default state. */
216 /***************************************************************************/
217 evel_throttle_initialize();
219 /***************************************************************************/
220 /* Save values we will need during operation. */
221 /***************************************************************************/
222 event_source_type = source_type;
223 functional_role = strdup(role);
225 /***************************************************************************/
226 /* Ensure there are no trailing zeroes and unnecessary decimal points in */
228 /***************************************************************************/
229 offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
231 if (EVEL_API_MINOR_VERSION != 0)
233 sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
236 /***************************************************************************/
237 /* Build a common base of the API URLs. */
238 /***************************************************************************/
239 strcpy(path_url, "/");
240 snprintf(base_api_url,
242 "%s://%s:%d%s/eventListener/v%s",
243 secure ? "https" : "http",
246 (((path != NULL) && (strlen(path) > 0)) ?
247 strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
250 /***************************************************************************/
251 /* Build the URL to the event API. */
252 /***************************************************************************/
253 strcpy(topic_url, "/");
254 snprintf(event_api_url,
258 (((topic != NULL) && (strlen(topic) > 0)) ?
259 strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
260 EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
262 /***************************************************************************/
263 /* Build a common base of the Backup API URLs. */
264 /***************************************************************************/
265 if( bakup_fqdn != NULL )
267 strcpy(path_url, "/");
268 snprintf(base_api_url,
270 "%s://%s:%d%s/eventListener/v%s",
271 secure ? "https" : "http",
274 (((path != NULL) && (strlen(path) > 0)) ?
275 strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
278 /***************************************************************************/
279 /* Build the URL to the event API. */
280 /***************************************************************************/
281 strcpy(topic_url, "/");
282 snprintf(bakup_api_url,
286 (((topic != NULL) && (strlen(topic) > 0)) ?
287 strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
288 EVEL_INFO("Vendor Backup Event Listener API is located at: %s", bakup_api_url);
289 bakup_coll = bakup_api_url;
292 /***************************************************************************/
293 /* Build the URL to the throttling API. */
294 /***************************************************************************/
295 snprintf(throt_api_url,
297 "%s/clientThrottlingState",
299 EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
301 /***************************************************************************/
302 /* Spin-up the event-handler, which gets cURL readied for use. */
303 /***************************************************************************/
304 rc = event_handler_initialize(event_api_url,
323 if (rc != EVEL_SUCCESS)
325 log_error_state("Failed to initialize event handler (including cURL)");
329 /***************************************************************************/
330 /* Extract the metadata from OpenStack. If we fail to extract it, we */
331 /* record that in the logs, but carry on, assuming we're in a test */
332 /* without a metadata service. */
333 /***************************************************************************/
334 rc = openstack_metadata(verbosity);
335 if (rc != EVEL_SUCCESS)
337 EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
341 /***************************************************************************/
342 /* Start the event handler thread. */
343 /***************************************************************************/
344 rc = event_handler_run();
345 if (rc != EVEL_SUCCESS)
347 log_error_state("Failed to start event handler thread. "
348 "Error code=%d", rc);
356 /**************************************************************************//**
357 * Clean up the EVEL library.
359 * @note that at present don't expect Init/Term cycling not to leak memory!
361 * @returns Status code
362 * @retval EVEL_SUCCESS On success
363 * @retval "One of ::EVEL_ERR_CODES" On failure.
364 *****************************************************************************/
365 EVEL_ERR_CODES evel_terminate(void)
367 int rc = EVEL_SUCCESS;
369 /***************************************************************************/
370 /* First terminate any pending transactions in the event-posting thread. */
371 /***************************************************************************/
372 rc = event_handler_terminate();
373 if (rc != EVEL_SUCCESS)
375 log_error_state("Failed to terminate EVEL library cleanly!");
378 /***************************************************************************/
379 /* Shut down the Event Handler library in a tidy manner. */
380 /***************************************************************************/
381 curl_global_cleanup();
383 /***************************************************************************/
384 /* Clean up allocated memory. */
385 /***************************************************************************/
386 free(functional_role);
388 /***************************************************************************/
389 /* Clean up event throttling. */
390 /***************************************************************************/
391 evel_throttle_terminate();
393 EVEL_INFO("EVEL stopped");
397 /**************************************************************************//**
400 * Free off the event supplied. Will free all the contained allocated memory.
402 * @note It is safe to free a NULL pointer.
403 *****************************************************************************/
404 void evel_free_event(void * event)
406 EVENT_HEADER * evt_ptr = event;
411 /*************************************************************************/
412 /* Work out what kind of event we're dealing with so we can cast it */
414 /*************************************************************************/
415 switch (evt_ptr->event_domain)
417 case EVEL_DOMAIN_INTERNAL:
418 EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
419 evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
420 memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
424 case EVEL_DOMAIN_HEARTBEAT:
425 EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
426 evel_free_header(evt_ptr);
427 memset(evt_ptr, 0, sizeof(EVENT_HEADER));
431 case EVEL_DOMAIN_FAULT:
432 EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
433 evel_free_fault((EVENT_FAULT *)evt_ptr);
434 memset(evt_ptr, 0, sizeof(EVENT_FAULT));
438 case EVEL_DOMAIN_MEASUREMENT:
439 EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
440 evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
441 memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
445 case EVEL_DOMAIN_MOBILE_FLOW:
446 EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
447 evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
448 memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
452 case EVEL_DOMAIN_REPORT:
453 EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
454 evel_free_report((EVENT_REPORT *)evt_ptr);
455 memset(evt_ptr, 0, sizeof(EVENT_REPORT));
459 case EVEL_DOMAIN_HEARTBEAT_FIELD:
460 EVEL_DEBUG("Event is a Heartbeat Field Event at %lp", evt_ptr);
461 evel_free_hrtbt_field((EVENT_HEARTBEAT_FIELD *)evt_ptr);
462 memset(evt_ptr, 0, sizeof(EVENT_HEARTBEAT_FIELD));
466 case EVEL_DOMAIN_SIPSIGNALING:
467 EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr);
468 evel_free_signaling((EVENT_SIGNALING *)evt_ptr);
469 memset(evt_ptr, 0, sizeof(EVENT_SIGNALING));
473 case EVEL_DOMAIN_STATE_CHANGE:
474 EVEL_DEBUG("Event is a State Change at %lp", evt_ptr);
475 evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr);
476 memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE));
480 case EVEL_DOMAIN_SYSLOG:
481 EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr);
482 evel_free_syslog((EVENT_SYSLOG *)evt_ptr);
483 memset(evt_ptr, 0, sizeof(EVENT_SYSLOG));
487 case EVEL_DOMAIN_OTHER:
488 EVEL_DEBUG("Event is an Other at %lp", evt_ptr);
489 evel_free_other((EVENT_OTHER *)evt_ptr);
490 memset(evt_ptr, 0, sizeof(EVENT_OTHER));
494 case EVEL_DOMAIN_VOICE_QUALITY:
495 EVEL_DEBUG("Event is an VoiceQuality at %lp", evt_ptr);
496 evel_free_voice_quality((EVENT_VOICE_QUALITY *)evt_ptr);
497 memset(evt_ptr, 0, sizeof(EVENT_VOICE_QUALITY));
501 case EVEL_DOMAIN_THRESHOLD_CROSS:
502 EVEL_DEBUG("Event is a Threshold crossing at %lp", evt_ptr);
503 evel_free_threshold_cross((EVENT_THRESHOLD_CROSS *)evt_ptr);
504 memset(evt_ptr, 0, sizeof(EVENT_THRESHOLD_CROSS));
508 case EVEL_DOMAIN_BATCH:
509 EVEL_DEBUG("Event is a Batch at %lp", evt_ptr);
510 evel_free_batch((EVENT_HEADER *)evt_ptr);
511 memset(evt_ptr, 0, sizeof(EVENT_HEADER));
516 EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);