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 © 2017 AT&T Intellectual Property. All rights reserved.
17 * Licensed under the Apache License, Version 2.0 (the "License");
18 * you may not use this file except in compliance with the License.
19 * You may obtain a copy of the License at
20 * http://www.apache.org/licenses/LICENSE-2.0
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 *****************************************************************************/
33 #include <curl/curl.h>
36 #include "evel_internal.h"
37 #include "evel_throttle.h"
40 /**************************************************************************//**
41 * The type of equipment represented by this VNF.
42 *****************************************************************************/
43 EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
45 /**************************************************************************//**
46 * The Functional Role of the equipment represented by this VNF.
47 *****************************************************************************/
48 char *functional_role = NULL;
50 /**************************************************************************//**
51 * Library initialization.
53 * Initialize the EVEL library.
55 * @note This function initializes the cURL library. Applications making use
56 * of libcurl may need to pull the initialization out of here. Note
57 * also that this function is not threadsafe as a result - refer to
58 * libcurl's API documentation for relevant warnings.
60 * @sa Matching Term function.
62 * @param fqdn The API's FQDN or IP address.
63 * @param port The API's port.
64 * @param path The optional path (may be NULL).
65 * @param topic The optional topic part of the URL (may be NULL).
66 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
67 * @param username Username for Basic Authentication of requests.
68 * @param password Password for Basic Authentication of requests.
69 * @param source_type The kind of node we represent.
70 * @param role The role this node undertakes.
71 * @param verbosity 0 for normal operation, positive values for chattier
74 * @returns Status code
75 * @retval EVEL_SUCCESS On success
76 * @retval ::EVEL_ERR_CODES On failure.
77 *****************************************************************************/
78 EVEL_ERR_CODES evel_initialize(const char * const fqdn,
80 const char * const path,
81 const char * const topic,
83 const char * const username,
84 const char * const password,
85 EVEL_SOURCE_TYPES source_type,
86 const char * const role,
90 EVEL_ERR_CODES rc = EVEL_SUCCESS;
91 char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
92 char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
93 char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
94 char path_url[EVEL_MAX_URL_LEN + 1] = {0};
95 char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
96 char version_string[10] = {0};
99 /***************************************************************************/
100 /* Check assumptions. */
101 /***************************************************************************/
102 assert(fqdn != NULL);
103 assert(port > 0 && port <= 65535);
104 assert(source_type < EVEL_MAX_SOURCE_TYPES);
105 assert(role != NULL);
107 /***************************************************************************/
108 /* Start logging so we can report on progress. */
109 /***************************************************************************/
110 log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL");
111 EVEL_INFO("EVEL started");
112 EVEL_INFO("API server is: %s", fqdn);
113 EVEL_INFO("API port is: %d", port);
117 EVEL_INFO("API path is: %s", path);
121 EVEL_INFO("No API path");
126 EVEL_INFO("API topic is: %s", topic);
130 EVEL_INFO("No API topic");
133 EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
134 EVEL_INFO("Event Source Type is: %d", source_type);
135 EVEL_INFO("Functional Role is: %s", role);
136 EVEL_INFO("Log verbosity is: %d", verbosity);
138 /***************************************************************************/
139 /* Initialize event throttling to the default state. */
140 /***************************************************************************/
141 evel_throttle_initialize();
143 /***************************************************************************/
144 /* Save values we will need during operation. */
145 /***************************************************************************/
146 event_source_type = source_type;
147 functional_role = strdup(role);
149 /***************************************************************************/
150 /* Ensure there are no trailing zeroes and unnecessary decimal points in */
152 /***************************************************************************/
153 offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
155 if (EVEL_API_MINOR_VERSION != 0)
157 sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
160 /***************************************************************************/
161 /* Build a common base of the API URLs. */
162 /***************************************************************************/
163 strcpy(path_url, "/");
164 snprintf(base_api_url,
166 "%s://%s:%d%s/eventListener/v%s",
167 secure ? "https" : "http",
170 (((path != NULL) && (strlen(path) > 0)) ?
171 strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
174 /***************************************************************************/
175 /* Build the URL to the event API. */
176 /***************************************************************************/
177 strcpy(topic_url, "/");
178 snprintf(event_api_url,
182 (((topic != NULL) && (strlen(topic) > 0)) ?
183 strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
184 EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
186 /***************************************************************************/
187 /* Build the URL to the throttling API. */
188 /***************************************************************************/
189 snprintf(throt_api_url,
191 "%s/clientThrottlingState",
193 EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
195 /***************************************************************************/
196 /* Spin-up the event-handler, which gets cURL readied for use. */
197 /***************************************************************************/
198 rc = event_handler_initialize(event_api_url,
203 if (rc != EVEL_SUCCESS)
205 log_error_state("Failed to initialize event handler (including cURL)");
209 /***************************************************************************/
210 /* Extract the metadata from OpenStack. If we fail to extract it, we */
211 /* record that in the logs, but carry on, assuming we're in a test */
212 /* without a metadata service. */
213 /***************************************************************************/
214 rc = openstack_metadata(verbosity);
215 if (rc != EVEL_SUCCESS)
217 EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
221 /***************************************************************************/
222 /* Start the event handler thread. */
223 /***************************************************************************/
224 rc = event_handler_run();
225 if (rc != EVEL_SUCCESS)
227 log_error_state("Failed to start event handler thread. "
228 "Error code=%d", rc);
236 /**************************************************************************//**
237 * Clean up the EVEL library.
239 * @note that at present don't expect Init/Term cycling not to leak memory!
241 * @returns Status code
242 * @retval EVEL_SUCCESS On success
243 * @retval "One of ::EVEL_ERR_CODES" On failure.
244 *****************************************************************************/
245 EVEL_ERR_CODES evel_terminate(void)
247 int rc = EVEL_SUCCESS;
249 /***************************************************************************/
250 /* First terminate any pending transactions in the event-posting thread. */
251 /***************************************************************************/
252 rc = event_handler_terminate();
253 if (rc != EVEL_SUCCESS)
255 log_error_state("Failed to terminate EVEL library cleanly!");
258 /***************************************************************************/
259 /* Shut down the Event Handler library in a tidy manner. */
260 /***************************************************************************/
261 curl_global_cleanup();
263 /***************************************************************************/
264 /* Clean up allocated memory. */
265 /***************************************************************************/
266 free(functional_role);
268 /***************************************************************************/
269 /* Clean up event throttling. */
270 /***************************************************************************/
271 evel_throttle_terminate();
273 EVEL_INFO("EVEL stopped");
277 /**************************************************************************//**
280 * Free off the event supplied. Will free all the contained allocated memory.
282 * @note It is safe to free a NULL pointer.
283 *****************************************************************************/
284 void evel_free_event(void * event)
286 EVENT_HEADER * evt_ptr = event;
291 /*************************************************************************/
292 /* Work out what kind of event we're dealing with so we can cast it */
294 /*************************************************************************/
295 switch (evt_ptr->event_domain)
297 case EVEL_DOMAIN_INTERNAL:
298 EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
299 evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
300 memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
304 case EVEL_DOMAIN_HEARTBEAT:
305 EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
306 evel_free_header(evt_ptr);
307 memset(evt_ptr, 0, sizeof(EVENT_HEADER));
311 case EVEL_DOMAIN_FAULT:
312 EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
313 evel_free_fault((EVENT_FAULT *)evt_ptr);
314 memset(evt_ptr, 0, sizeof(EVENT_FAULT));
318 case EVEL_DOMAIN_MEASUREMENT:
319 EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
320 evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
321 memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
325 case EVEL_DOMAIN_MOBILE_FLOW:
326 EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
327 evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
328 memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
332 case EVEL_DOMAIN_REPORT:
333 EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
334 evel_free_report((EVENT_REPORT *)evt_ptr);
335 memset(evt_ptr, 0, sizeof(EVENT_REPORT));
339 case EVEL_DOMAIN_SERVICE:
340 EVEL_DEBUG("Event is a Service Event at %lp", evt_ptr);
341 evel_free_service((EVENT_SERVICE *)evt_ptr);
342 memset(evt_ptr, 0, sizeof(EVENT_SERVICE));
346 case EVEL_DOMAIN_SIGNALING:
347 EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr);
348 evel_free_signaling((EVENT_SIGNALING *)evt_ptr);
349 memset(evt_ptr, 0, sizeof(EVENT_SIGNALING));
353 case EVEL_DOMAIN_STATE_CHANGE:
354 EVEL_DEBUG("Event is a State Change at %lp", evt_ptr);
355 evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr);
356 memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE));
360 case EVEL_DOMAIN_SYSLOG:
361 EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr);
362 evel_free_syslog((EVENT_SYSLOG *)evt_ptr);
363 memset(evt_ptr, 0, sizeof(EVENT_SYSLOG));
367 case EVEL_DOMAIN_OTHER:
368 EVEL_DEBUG("Event is an Other at %lp", evt_ptr);
369 evel_free_other((EVENT_OTHER *)evt_ptr);
370 memset(evt_ptr, 0, sizeof(EVENT_OTHER));
375 EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);