1 /*************************************************************************//**
3 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
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 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 ****************************************************************************/
18 /**************************************************************************//**
20 * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
22 * This file implements the EVEL library which is intended to provide a
23 * simple wrapper around the complexity of AT&T's Vendor Event Listener API so
24 * that VNFs can use it without worrying about details of:
26 * * The API's encoding into JSON.
27 * * The API's transport over HTTP/HTTPS.
29 ****************************************************************************/
35 #include <curl/curl.h>
38 #include "evel_internal.h"
39 #include "evel_throttle.h"
42 /**************************************************************************//**
43 * The type of equipment represented by this VNF.
44 *****************************************************************************/
45 EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
47 /**************************************************************************//**
48 * The Functional Role of the equipment represented by this VNF.
49 *****************************************************************************/
50 char *functional_role = NULL;
52 /**************************************************************************//**
53 * Library initialization.
55 * Initialize the EVEL library.
57 * @note This function initializes the cURL library. Applications making use
58 * of libcurl may need to pull the initialization out of here. Note
59 * also that this function is not threadsafe as a result - refer to
60 * libcurl's API documentation for relevant warnings.
62 * @sa Matching Term function.
64 * @param fqdn The API's FQDN or IP address.
65 * @param port The API's port.
66 * @param path The optional path (may be NULL).
67 * @param topic The optional topic part of the URL (may be NULL).
68 * @param secure Whether to use HTTPS (0=HTTP, 1=HTTPS)
69 * @param username Username for Basic Authentication of requests.
70 * @param password Password for Basic Authentication of requests.
71 * @param source_type The kind of node we represent.
72 * @param role The role this node undertakes.
73 * @param verbosity 0 for normal operation, positive values for chattier
76 * @returns Status code
77 * @retval EVEL_SUCCESS On success
78 * @retval ::EVEL_ERR_CODES On failure.
79 *****************************************************************************/
80 EVEL_ERR_CODES evel_initialize(const char * const fqdn,
82 const char * const path,
83 const char * const topic,
85 const char * const username,
86 const char * const password,
87 EVEL_SOURCE_TYPES source_type,
88 const char * const role,
92 EVEL_ERR_CODES rc = EVEL_SUCCESS;
93 char base_api_url[EVEL_MAX_URL_LEN + 1] = {0};
94 char event_api_url[EVEL_MAX_URL_LEN + 1] = {0};
95 char throt_api_url[EVEL_MAX_URL_LEN + 1] = {0};
96 char path_url[EVEL_MAX_URL_LEN + 1] = {0};
97 char topic_url[EVEL_MAX_URL_LEN + 1] = {0};
98 char version_string[10] = {0};
101 /***************************************************************************/
102 /* Check assumptions. */
103 /***************************************************************************/
104 assert(fqdn != NULL);
105 assert(port > 0 && port <= 65535);
106 assert(source_type < EVEL_MAX_SOURCE_TYPES);
107 assert(role != NULL);
109 /***************************************************************************/
110 /* Start logging so we can report on progress. */
111 /***************************************************************************/
112 log_initialize(verbosity == 0 ? EVEL_LOG_INFO : EVEL_LOG_DEBUG, "EVEL");
113 EVEL_INFO("EVEL started");
114 EVEL_INFO("API server is: %s", fqdn);
115 EVEL_INFO("API port is: %d", port);
119 EVEL_INFO("API path is: %s", path);
123 EVEL_INFO("No API path");
128 EVEL_INFO("API topic is: %s", topic);
132 EVEL_INFO("No API topic");
135 EVEL_INFO("API transport is: %s", secure ? "HTTPS" : "HTTP");
136 EVEL_INFO("Event Source Type is: %d", source_type);
137 EVEL_INFO("Functional Role is: %s", role);
138 EVEL_INFO("Log verbosity is: %d", verbosity);
140 /***************************************************************************/
141 /* Initialize event throttling to the default state. */
142 /***************************************************************************/
143 evel_throttle_initialize();
145 /***************************************************************************/
146 /* Save values we will need during operation. */
147 /***************************************************************************/
148 event_source_type = source_type;
149 functional_role = strdup(role);
151 /***************************************************************************/
152 /* Ensure there are no trailing zeroes and unnecessary decimal points in */
154 /***************************************************************************/
155 offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
157 if (EVEL_API_MINOR_VERSION != 0)
159 sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
162 /***************************************************************************/
163 /* Build a common base of the API URLs. */
164 /***************************************************************************/
165 strcpy(path_url, "/");
166 snprintf(base_api_url,
168 "%s://%s:%d%s/eventListener/v%s",
169 secure ? "https" : "http",
172 (((path != NULL) && (strlen(path) > 0)) ?
173 strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
176 /***************************************************************************/
177 /* Build the URL to the event API. */
178 /***************************************************************************/
179 strcpy(topic_url, "/");
180 snprintf(event_api_url,
184 (((topic != NULL) && (strlen(topic) > 0)) ?
185 strncat(topic_url, topic, EVEL_MAX_URL_LEN) : ""));
186 EVEL_INFO("Vendor Event Listener API is located at: %s", event_api_url);
188 /***************************************************************************/
189 /* Build the URL to the throttling API. */
190 /***************************************************************************/
191 snprintf(throt_api_url,
193 "%s/clientThrottlingState",
195 EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
197 /***************************************************************************/
198 /* Spin-up the event-handler, which gets cURL readied for use. */
199 /***************************************************************************/
200 rc = event_handler_initialize(event_api_url,
205 if (rc != EVEL_SUCCESS)
207 log_error_state("Failed to initialize event handler (including cURL)");
211 /***************************************************************************/
212 /* Extract the metadata from OpenStack. If we fail to extract it, we */
213 /* record that in the logs, but carry on, assuming we're in a test */
214 /* without a metadata service. */
215 /***************************************************************************/
216 rc = openstack_metadata(verbosity);
217 if (rc != EVEL_SUCCESS)
219 EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
223 /***************************************************************************/
224 /* Start the event handler thread. */
225 /***************************************************************************/
226 rc = event_handler_run();
227 if (rc != EVEL_SUCCESS)
229 log_error_state("Failed to start event handler thread. "
230 "Error code=%d", rc);
238 /**************************************************************************//**
239 * Clean up the EVEL library.
241 * @note that at present don't expect Init/Term cycling not to leak memory!
243 * @returns Status code
244 * @retval EVEL_SUCCESS On success
245 * @retval "One of ::EVEL_ERR_CODES" On failure.
246 *****************************************************************************/
247 EVEL_ERR_CODES evel_terminate(void)
249 int rc = EVEL_SUCCESS;
251 /***************************************************************************/
252 /* First terminate any pending transactions in the event-posting thread. */
253 /***************************************************************************/
254 rc = event_handler_terminate();
255 if (rc != EVEL_SUCCESS)
257 log_error_state("Failed to terminate EVEL library cleanly!");
260 /***************************************************************************/
261 /* Shut down the Event Handler library in a tidy manner. */
262 /***************************************************************************/
263 curl_global_cleanup();
265 /***************************************************************************/
266 /* Clean up allocated memory. */
267 /***************************************************************************/
268 free(functional_role);
270 /***************************************************************************/
271 /* Clean up event throttling. */
272 /***************************************************************************/
273 evel_throttle_terminate();
275 EVEL_INFO("EVEL stopped");
279 /**************************************************************************//**
282 * Free off the event supplied. Will free all the contained allocated memory.
284 * @note It is safe to free a NULL pointer.
285 *****************************************************************************/
286 void evel_free_event(void * event)
288 EVENT_HEADER * evt_ptr = event;
293 /*************************************************************************/
294 /* Work out what kind of event we're dealing with so we can cast it */
296 /*************************************************************************/
297 switch (evt_ptr->event_domain)
299 case EVEL_DOMAIN_INTERNAL:
300 EVEL_DEBUG("Event is an Internal event at %lp", evt_ptr);
301 evel_free_internal_event((EVENT_INTERNAL *) evt_ptr);
302 memset(evt_ptr, 0, sizeof(EVENT_INTERNAL));
306 case EVEL_DOMAIN_HEARTBEAT:
307 EVEL_DEBUG("Event is a Heartbeat at %lp", evt_ptr);
308 evel_free_header(evt_ptr);
309 memset(evt_ptr, 0, sizeof(EVENT_HEADER));
313 case EVEL_DOMAIN_FAULT:
314 EVEL_DEBUG("Event is a Fault at %lp", evt_ptr);
315 evel_free_fault((EVENT_FAULT *)evt_ptr);
316 memset(evt_ptr, 0, sizeof(EVENT_FAULT));
320 case EVEL_DOMAIN_MEASUREMENT:
321 EVEL_DEBUG("Event is a Measurement at %lp", evt_ptr);
322 evel_free_measurement((EVENT_MEASUREMENT *)evt_ptr);
323 memset(evt_ptr, 0, sizeof(EVENT_MEASUREMENT));
327 case EVEL_DOMAIN_MOBILE_FLOW:
328 EVEL_DEBUG("Event is a Mobile Flow at %lp", evt_ptr);
329 evel_free_mobile_flow((EVENT_MOBILE_FLOW *)evt_ptr);
330 memset(evt_ptr, 0, sizeof(EVENT_MOBILE_FLOW));
334 case EVEL_DOMAIN_REPORT:
335 EVEL_DEBUG("Event is a Report at %lp", evt_ptr);
336 evel_free_report((EVENT_REPORT *)evt_ptr);
337 memset(evt_ptr, 0, sizeof(EVENT_REPORT));
341 case EVEL_DOMAIN_HEARTBEAT_FIELD:
342 EVEL_DEBUG("Event is a Heartbeat Field Event at %lp", evt_ptr);
343 evel_free_hrtbt_field((EVENT_HEARTBEAT_FIELD *)evt_ptr);
344 memset(evt_ptr, 0, sizeof(EVENT_HEARTBEAT_FIELD));
348 case EVEL_DOMAIN_SIPSIGNALING:
349 EVEL_DEBUG("Event is a Signaling at %lp", evt_ptr);
350 evel_free_signaling((EVENT_SIGNALING *)evt_ptr);
351 memset(evt_ptr, 0, sizeof(EVENT_SIGNALING));
355 case EVEL_DOMAIN_STATE_CHANGE:
356 EVEL_DEBUG("Event is a State Change at %lp", evt_ptr);
357 evel_free_state_change((EVENT_STATE_CHANGE *)evt_ptr);
358 memset(evt_ptr, 0, sizeof(EVENT_STATE_CHANGE));
362 case EVEL_DOMAIN_SYSLOG:
363 EVEL_DEBUG("Event is a Syslog at %lp", evt_ptr);
364 evel_free_syslog((EVENT_SYSLOG *)evt_ptr);
365 memset(evt_ptr, 0, sizeof(EVENT_SYSLOG));
369 case EVEL_DOMAIN_OTHER:
370 EVEL_DEBUG("Event is an Other at %lp", evt_ptr);
371 evel_free_other((EVENT_OTHER *)evt_ptr);
372 memset(evt_ptr, 0, sizeof(EVENT_OTHER));
376 case EVEL_DOMAIN_VOICE_QUALITY:
377 EVEL_DEBUG("Event is an VoiceQuality at %lp", evt_ptr);
378 evel_free_voice_quality((EVENT_VOICE_QUALITY *)evt_ptr);
379 memset(evt_ptr, 0, sizeof(EVENT_VOICE_QUALITY));
384 EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);