1 /**************************************************************************//**
3 * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
5 * This file implements the EVEL library which is intended to provide a
6 * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
7 * that VNFs can use it without worrying about details of:
9 * * The API's encoding into JSON.
10 * * The API's transport over HTTP/HTTPS.
15 * Copyright(c) <2016>, AT&T Intellectual Property. All other rights reserved.
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
20 * 1. Redistributions of source code must retain the above copyright notice,
21 * this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright notice,
23 * this list of conditions and the following disclaimer in the documentation
24 * and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 * must display the following acknowledgement: This product includes
27 * software developed by the AT&T.
28 * 4. Neither the name of AT&T nor the names of its contributors may be used to
29 * endorse or promote products derived from this software without specific
30 * prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
33 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
41 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 *****************************************************************************/
48 #include <curl/curl.h>
51 #include "evel_internal.h"
52 #include "evel_throttle.h"
55 /**************************************************************************//**
56 * The type of equipment represented by this VNF.
57 *****************************************************************************/
58 EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
60 /**************************************************************************//**
61 * The Functional Role of the equipment represented by this VNF.
62 *****************************************************************************/
63 char *functional_role = NULL;
65 /**************************************************************************//**
66 * Library initialization.
68 * Initialize the EVEL library.
70 * @note This function initializes the cURL library. Applications making use
71 * of libcurl may need to pull the initialization out of here. Note
72 * also that this function is not threadsafe as a result - refer to
73 * libcurl's API documentation for relevant warnings.
75 * @sa Matching Term function.
77 * @param fqdn The API's FQDN or IP address.
78 * @param port The API's port.
79 * @param path The optional path (may be NULL).
80 * @param topic The optional topic part of the URL (may be NULL).
81 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
82 * @param username Username for Basic Authentication of requests.
83 * @param password Password for Basic Authentication of requests.
84 * @param source_type The kind of node we represent.
85 * @param role The role this node undertakes.
86 * @param verbosity 0 for normal operation, positive values for chattier
89 * @returns Status code
90 * @retval EVEL_SUCCESS On success
91 * @retval ::EVEL_ERR_CODES On failure.
92 *****************************************************************************/
93 EVEL_ERR_CODES evel_initialize(const char * const fqdn,
95 const char * const path,
96 const char * const topic,
98 const char * const username,
99 const char * const password,
100 EVEL_SOURCE_TYPES source_type,
101 const char * const role,
105 EVEL_ERR_CODES rc = EVEL_SUCCESS;
106 char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
107 char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
108 char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
109 char path_url[EVEL_MAX_URL_LEN + 1] = {0};
110 char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
111 char version_string[10] = {0};
114 /***************************************************************************/
115 /* Check assumptions. */
116 /***************************************************************************/
117 assert(fqdn != NULL);
118 assert(port > 0 && port <= 65535);
119 assert(source_type < EVEL_MAX_SOURCE_TYPES);
120 assert(role != NULL);
122 /***************************************************************************/
123 /* Start logging so we can report on progress. */
124 /***************************************************************************/
125 log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL");
126 EVEL_INFO("EVEL started");
127 EVEL_INFO("API server is: %s", fqdn);
128 EVEL_INFO("API port is: %d", port);
132 EVEL_INFO("API path is: %s", path);
136 EVEL_INFO("No API path");
141 EVEL_INFO("API topic is: %s", topic);
145 EVEL_INFO("No API topic");
148 EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
149 EVEL_INFO("Event Source Type is: %d", source_type);
150 EVEL_INFO("Functional Role is: %s", role);
151 EVEL_INFO("Log verbosity is: %d", verbosity);
153 /***************************************************************************/
154 /* Initialize event throttling to the default state. */
155 /***************************************************************************/
156 evel_throttle_initialize();
158 /***************************************************************************/
159 /* Save values we will need during operation. */
160 /***************************************************************************/
161 event_source_type = source_type;
162 functional_role = strdup(role);
164 /***************************************************************************/
165 /* Ensure there are no trailing zeroes and unnecessary decimal points in */
167 /***************************************************************************/
168 offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
170 if (EVEL_API_MINOR_VERSION != 0)
172 sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
175 /***************************************************************************/
176 /* Build a common base of the API URLs. */
177 /***************************************************************************/
178 strcpy(path_url, "/");
179 snprintf(base_api_url,
181 "%s://%s:%d%s/eventListener/v%s",
182 secure ? "https" : "http",
185 (((path != NULL) && (strlen(path) > 0)) ?
186 strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
189 /***************************************************************************/
190 /* Build the URL to the event API. */
191 /***************************************************************************/
192 strcpy(topic_url, "/");
193 snprintf(event_api_url,
197 (((topic != NULL) && (strlen(topic) > 0)) ?
198 strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
199 EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
201 /***************************************************************************/
202 /* Build the URL to the throttling API. */
203 /***************************************************************************/
204 snprintf(throt_api_url,
206 "%s/clientThrottlingState",
208 EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
210 /***************************************************************************/
211 /* Spin-up the event-handler, which gets cURL readied for use. */
212 /***************************************************************************/
213 rc = event_handler_initialize(event_api_url,
218 if (rc != EVEL_SUCCESS)
220 log_error_state("Failed to initialize event handler (including cURL)");
224 /***************************************************************************/
225 /* Extract the metadata from OpenStack. If we fail to extract it, we */
226 /* record that in the logs, but carry on, assuming we're in a test */
227 /* without a metadata service. */
228 /***************************************************************************/
229 rc = openstack_metadata(verbosity);
230 if (rc != EVEL_SUCCESS)
232 EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
236 /***************************************************************************/
237 /* Start the event handler thread. */
238 /***************************************************************************/
239 rc = event_handler_run();
240 if (rc != EVEL_SUCCESS)
242 log_error_state("Failed to start event handler thread. "
243 "Error code=%d", rc);
251 /**************************************************************************//**
252 * Clean up the EVEL library.
254 * @note that at present don't expect Init/Term cycling not to leak memory!
256 * @returns Status code
257 * @retval EVEL_SUCCESS On success
258 * @retval "One of ::EVEL_ERR_CODES" On failure.
259 *****************************************************************************/
260 EVEL_ERR_CODES evel_terminate(void)
262 int rc = EVEL_SUCCESS;
264 /***************************************************************************/
265 /* First terminate any pending transactions in the event-posting thread. */
266 /***************************************************************************/
267 rc = event_handler_terminate();
268 if (rc != EVEL_SUCCESS)
270 log_error_state("Failed to terminate EVEL library cleanly!");
273 /***************************************************************************/
274 /* Shut down the Event Handler library in a tidy manner. */
275 /***************************************************************************/
276 curl_global_cleanup();
278 /***************************************************************************/
279 /* Clean up allocated memory. */
280 /***************************************************************************/
281 free(functional_role);
283 /***************************************************************************/
284 /* Clean up event throttling. */
285 /***************************************************************************/
286 evel_throttle_terminate();
288 EVEL_INFO("EVEL stopped");
292 /**************************************************************************//**
295 * Free off the event supplied. Will free all the contained allocated memory.
297 * @note It is safe to free a NULL pointer.
298 *****************************************************************************/
299 void evel_free_event(void * event)
301 EVENT_HEADER * evt_ptr = event;
306 /*************************************************************************/
307 /* Work out what kind of event we're dealing with so we can cast it */
309 /*************************************************************************/
310 switch (evt_ptr->event_domain)
312 case EVEL_DOMAIN_INTERNAL:
313 EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
314 evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
315 memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
319 case EVEL_DOMAIN_HEARTBEAT:
320 EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
321 evel_free_header(evt_ptr);
322 memset(evt_ptr, 0, sizeof(EVENT_HEADER));
326 case EVEL_DOMAIN_FAULT:
327 EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
328 evel_free_fault((EVENT_FAULT *)evt_ptr);
329 memset(evt_ptr, 0, sizeof(EVENT_FAULT));
333 case EVEL_DOMAIN_MEASUREMENT:
334 EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
335 evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
336 memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
340 case EVEL_DOMAIN_MOBILE_FLOW:
341 EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
342 evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
343 memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
347 case EVEL_DOMAIN_REPORT:
348 EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
349 evel_free_report((EVENT_REPORT *)evt_ptr);
350 memset(evt_ptr, 0, sizeof(EVENT_REPORT));
354 case EVEL_DOMAIN_SERVICE:
355 EVEL_DEBUG("Event is a Service Event at %lp", evt_ptr);
356 evel_free_service((EVENT_SERVICE *)evt_ptr);
357 memset(evt_ptr, 0, sizeof(EVENT_SERVICE));
361 case EVEL_DOMAIN_SIGNALING:
362 EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr);
363 evel_free_signaling((EVENT_SIGNALING *)evt_ptr);
364 memset(evt_ptr, 0, sizeof(EVENT_SIGNALING));
368 case EVEL_DOMAIN_STATE_CHANGE:
369 EVEL_DEBUG("Event is a State Change at %lp", evt_ptr);
370 evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr);
371 memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE));
375 case EVEL_DOMAIN_SYSLOG:
376 EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr);
377 evel_free_syslog((EVENT_SYSLOG *)evt_ptr);
378 memset(evt_ptr, 0, sizeof(EVENT_SYSLOG));
382 case EVEL_DOMAIN_OTHER:
383 EVEL_DEBUG("Event is an Other at %lp", evt_ptr);
384 evel_free_other((EVENT_OTHER *)evt_ptr);
385 memset(evt_ptr, 0, sizeof(EVENT_OTHER));
390 EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);