Cleanup code and correct License
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / evel_library / evel.c
1 /*************************************************************************//**
2  *
3  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
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  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  ****************************************************************************/
17
18 /**************************************************************************//**
19  * @file
20  * Source module isolating the ECOMP Vendor Event Listener (EVEL) API.
21  *
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:
25  *
26  *  *   The API's encoding into JSON.
27  *  *   The API's transport over HTTP/HTTPS.
28  *
29  ****************************************************************************/
30
31 #include <string.h>
32 #include <assert.h>
33 #include <stdlib.h>
34 #include <sys/time.h>
35 #include <curl/curl.h>
36
37 #include "evel.h"
38 #include "evel_internal.h"
39 #include "evel_throttle.h"
40 #include "metadata.h"
41
42 /**************************************************************************//**
43  * The type of equipment represented by this VNF.
44  *****************************************************************************/
45 EVEL_SOURCE_TYPES event_source_type = EVEL_SOURCE_OTHER;
46
47 /**************************************************************************//**
48  * The Functional Role of the equipment represented by this VNF.
49  *****************************************************************************/
50 char *functional_role = NULL;
51
52 /**************************************************************************//**
53  * Library initialization.
54  *
55  * Initialize the EVEL library.
56  *
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.
61  *
62  * @sa  Matching Term function.
63  *
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
74  *                        logs.
75  *
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,
81                                int port,
82                                const char * const path,
83                                const char * const topic,
84                                int secure,
85                                const char * const username,
86                                const char * const password,
87                                EVEL_SOURCE_TYPES source_type,
88                                const char * const role,
89                                int verbosity
90                                )
91 {
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};
99   int offset;
100
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);
108
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);
116
117   if (path != NULL)
118   {
119     EVEL_INFO("API path is: %s", path);
120   }
121   else
122   {
123     EVEL_INFO("No API path");
124   }
125
126   if (topic != NULL)
127   {
128     EVEL_INFO("API topic is: %s", topic);
129   }
130   else
131   {
132     EVEL_INFO("No API topic");
133   }
134
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);
139
140   /***************************************************************************/
141   /* Initialize event throttling to the default state.                       */
142   /***************************************************************************/
143   evel_throttle_initialize();
144
145   /***************************************************************************/
146   /* Save values we will need during operation.                              */
147   /***************************************************************************/
148   event_source_type = source_type;
149   functional_role = strdup(role);
150
151   /***************************************************************************/
152   /* Ensure there are no trailing zeroes and unnecessary decimal points in   */
153   /* the version.                                                            */
154   /***************************************************************************/
155   offset = sprintf(version_string, "%d", EVEL_API_MAJOR_VERSION);
156
157   if (EVEL_API_MINOR_VERSION != 0)
158   {
159     sprintf(version_string + offset, ".%d", EVEL_API_MINOR_VERSION);
160   }
161
162   /***************************************************************************/
163   /* Build a common base of the API URLs.                                    */
164   /***************************************************************************/
165   strcpy(path_url, "/");
166   snprintf(base_api_url,
167            EVEL_MAX_URL_LEN,
168            "%s://%s:%d%s/eventListener/v%s",
169            secure ? "https" : "http",
170            fqdn,
171            port,
172            (((path != NULL) && (strlen(path) > 0)) ?
173             strncat(path_url, path, EVEL_MAX_URL_LEN) : ""),
174            version_string);
175
176   /***************************************************************************/
177   /* Build the URL to the event API.                                         */
178   /***************************************************************************/
179   strcpy(topic_url, "/");
180   snprintf(event_api_url,
181            EVEL_MAX_URL_LEN,
182            "%s%s",
183            base_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);
187
188   /***************************************************************************/
189   /* Build the URL to the throttling API.                                    */
190   /***************************************************************************/
191   snprintf(throt_api_url,
192            EVEL_MAX_URL_LEN,
193            "%s/clientThrottlingState",
194            base_api_url);
195   EVEL_INFO("Vendor Event Throttling API is located at: %s", throt_api_url);
196
197   /***************************************************************************/
198   /* Spin-up the event-handler, which gets cURL readied for use.             */
199   /***************************************************************************/
200   rc = event_handler_initialize(event_api_url,
201                                 throt_api_url,
202                                 username,
203                                 password,
204                                 verbosity);
205   if (rc != EVEL_SUCCESS)
206   {
207     log_error_state("Failed to initialize event handler (including cURL)");
208     goto exit_label;
209   }
210
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)
218   {
219     EVEL_INFO("Failed to load OpenStack metadata - assuming test environment");
220     rc = EVEL_SUCCESS;
221   }
222
223   /***************************************************************************/
224   /* Start the event handler thread.                                         */
225   /***************************************************************************/
226   rc = event_handler_run();
227   if (rc != EVEL_SUCCESS)
228   {
229     log_error_state("Failed to start event handler thread. "
230                     "Error code=%d", rc);
231     goto exit_label;
232   }
233
234 exit_label:
235   return(rc);
236 }
237
238 /**************************************************************************//**
239  * Clean up the EVEL library.
240  *
241  * @note that at present don't expect Init/Term cycling not to leak memory!
242  *
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)
248 {
249   int rc = EVEL_SUCCESS;
250
251   /***************************************************************************/
252   /* First terminate any pending transactions in the event-posting thread.   */
253   /***************************************************************************/
254   rc = event_handler_terminate();
255   if (rc != EVEL_SUCCESS)
256   {
257     log_error_state("Failed to terminate EVEL library cleanly!");
258   }
259
260   /***************************************************************************/
261   /* Shut down the Event Handler library in a tidy manner.                   */
262   /***************************************************************************/
263   curl_global_cleanup();
264
265   /***************************************************************************/
266   /* Clean up allocated memory.                                              */
267   /***************************************************************************/
268   free(functional_role);
269
270   /***************************************************************************/
271   /* Clean up event throttling.                                              */
272   /***************************************************************************/
273   evel_throttle_terminate();
274
275   EVEL_INFO("EVEL stopped");
276   return(rc);
277 }
278
279 /**************************************************************************//**
280  * Free an event.
281  *
282  * Free off the event supplied.  Will free all the contained allocated memory.
283  *
284  * @note  It is safe to free a NULL pointer.
285  *****************************************************************************/
286 void evel_free_event(void * event)
287 {
288   EVENT_HEADER * evt_ptr = event;
289   EVEL_ENTER();
290
291   if (event != NULL)
292   {
293     /*************************************************************************/
294     /* Work out what kind of event we're dealing with so we can cast it      */
295     /* appropriately.                                                        */
296     /*************************************************************************/
297     switch (evt_ptr->event_domain)
298     {
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));
303       free(evt_ptr);
304       break;
305
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));
310       free(evt_ptr);
311       break;
312
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));
317       free(evt_ptr);
318       break;
319
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));
324       free(evt_ptr);
325       break;
326
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));
331       free(evt_ptr);
332       break;
333
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));
338       free(evt_ptr);
339       break;
340
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));
345       free(evt_ptr);
346       break;
347
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));
352       free(evt_ptr);
353       break;
354
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));
359       free(evt_ptr);
360       break;
361
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));
366       free(evt_ptr);
367       break;
368
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));
373       free(evt_ptr);
374       break;
375
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));
380       free(evt_ptr);
381       break;
382
383     default:
384       EVEL_ERROR("Unexpected event domain (%d)", evt_ptr->event_domain);
385       assert(0);
386     }
387   }
388   EVEL_EXIT();
389 }