2e49870f172404a41b9373d3157ed2e91c66887b
[demo.git] / vnfs / VES / code / evel_library / evel_event.c
1 /**************************************************************************//**
2  * @file
3  * Implementation of EVEL functions relating to Event Headers - since
4  * Heartbeats only contain the Event Header, the Heartbeat factory function is
5  * here too.
6  *
7  * License
8  * -------
9  *
10  * Copyright(c) <2016>, AT&T Intellectual Property.  All other rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright notice,
16  *    this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright notice,
18  *    this list of conditions and the following disclaimer in the documentation
19  *    and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:  This product includes
22  *    software developed by the AT&T.
23  * 4. Neither the name of AT&T nor the names of its contributors may be used to
24  *    endorse or promote products derived from this software without specific
25  *    prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
28  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
34  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *****************************************************************************/
38
39 #include <string.h>
40 #include <assert.h>
41 #include <stdlib.h>
42 #include <sys/time.h>
43
44 #include "evel.h"
45 #include "evel_internal.h"
46 #include "evel_throttle.h"
47 #include "metadata.h"
48
49 /**************************************************************************//**
50  * Unique sequence number for events from this VNF.
51  *****************************************************************************/
52 static int event_sequence = 1;
53
54 /**************************************************************************//**
55  * Set the next event_sequence to use.
56  *
57  * @param sequence      The next sequence number to use.
58  *****************************************************************************/
59 void evel_set_next_event_sequence(const int sequence)
60 {
61   EVEL_ENTER();
62
63   EVEL_INFO("Setting event sequence to %d, was %d ", sequence, event_sequence);
64   event_sequence = sequence;
65
66   EVEL_EXIT();
67 }
68
69 /**************************************************************************//**
70  * Create a new heartbeat event.
71  *
72  * @note that the heartbeat is just a "naked" commonEventHeader!
73  *
74  * @returns pointer to the newly manufactured ::EVENT_HEADER.  If the event is
75  *          not used it must be released using ::evel_free_event
76  * @retval  NULL  Failed to create the event.
77  *****************************************************************************/
78 EVENT_HEADER * evel_new_heartbeat()
79 {
80   EVENT_HEADER * heartbeat = NULL;
81   EVEL_ENTER();
82
83   /***************************************************************************/
84   /* Allocate the header.                                                    */
85   /***************************************************************************/
86   heartbeat = malloc(sizeof(EVENT_HEADER));
87   if (heartbeat == NULL)
88   {
89     log_error_state("Out of memory");
90     goto exit_label;
91   }
92   memset(heartbeat, 0, sizeof(EVENT_HEADER));
93
94   /***************************************************************************/
95   /* Initialize the header.  Get a new event sequence number.  Note that if  */
96   /* any memory allocation fails in here we will fail gracefully because     */
97   /* everything downstream can cope with NULLs.                              */
98   /***************************************************************************/
99   evel_init_header(heartbeat);
100   evel_force_option_string(&heartbeat->event_type, "Autonomous heartbeat");
101
102 exit_label:
103   EVEL_EXIT();
104   return heartbeat;
105 }
106
107 /**************************************************************************//**
108  * Initialize a newly created event header.
109  *
110  * @param header  Pointer to the header being initialized.
111  *****************************************************************************/
112 void evel_init_header(EVENT_HEADER * const header)
113 {
114   char scratchpad[EVEL_MAX_STRING_LEN + 1] = {0};
115   struct timeval tv;
116
117   EVEL_ENTER();
118
119   assert(header != NULL);
120
121   gettimeofday(&tv, NULL);
122
123   /***************************************************************************/
124   /* Initialize the header.  Get a new event sequence number.  Note that if  */
125   /* any memory allocation fails in here we will fail gracefully because     */
126   /* everything downstream can cope with NULLs.                              */
127   /***************************************************************************/
128   header->event_domain = EVEL_DOMAIN_HEARTBEAT;
129   snprintf(scratchpad, EVEL_MAX_STRING_LEN, "%d", event_sequence);
130   header->event_id = strdup(scratchpad);
131   header->functional_role = strdup(functional_role);
132   header->last_epoch_microsec = tv.tv_usec + 1000000 * tv.tv_sec;
133   header->priority = EVEL_PRIORITY_NORMAL;
134   header->reporting_entity_name = strdup(openstack_vm_name());
135   header->source_name = strdup(openstack_vm_name());
136   header->sequence = event_sequence;
137   header->start_epoch_microsec = header->last_epoch_microsec;
138   header->major_version = EVEL_HEADER_MAJOR_VERSION;
139   header->minor_version = EVEL_HEADER_MINOR_VERSION;
140   event_sequence++;
141
142   /***************************************************************************/
143   /* Optional parameters.                                                    */
144   /***************************************************************************/
145   evel_init_option_string(&header->event_type);
146   evel_force_option_string(&header->reporting_entity_id, openstack_vm_uuid());
147   evel_force_option_string(&header->source_id, openstack_vm_uuid());
148
149   EVEL_EXIT();
150 }
151
152 /**************************************************************************//**
153  * Set the Event Type property of the event header.
154  *
155  * @note  The property is treated as immutable: it is only valid to call
156  *        the setter once.  However, we don't assert if the caller tries to
157  *        overwrite, just ignoring the update instead.
158  *
159  * @param header        Pointer to the ::EVENT_HEADER.
160  * @param type          The Event Type to be set. ASCIIZ string. The caller
161  *                      does not need to preserve the value once the function
162  *                      returns.
163  *****************************************************************************/
164 void evel_header_type_set(EVENT_HEADER * const header,
165                           const char * const type)
166 {
167   EVEL_ENTER();
168
169   /***************************************************************************/
170   /* Check preconditions.                                                    */
171   /***************************************************************************/
172   assert(header != NULL);
173   assert(type != NULL);
174
175   evel_set_option_string(&header->event_type, type, "Event Type");
176
177   EVEL_EXIT();
178 }
179
180 /**************************************************************************//**
181  * Set the Start Epoch property of the event header.
182  *
183  * @note The Start Epoch defaults to the time of event creation.
184  *
185  * @param header        Pointer to the ::EVENT_HEADER.
186  * @param start_epoch_microsec
187  *                      The start epoch to set, in microseconds.
188  *****************************************************************************/
189 void evel_start_epoch_set(EVENT_HEADER * const header,
190                           const unsigned long long start_epoch_microsec)
191 {
192   EVEL_ENTER();
193
194   /***************************************************************************/
195   /* Check preconditions and assign the new value.                           */
196   /***************************************************************************/
197   assert(header != NULL);
198   header->start_epoch_microsec = start_epoch_microsec;
199
200   EVEL_EXIT();
201 }
202
203 /**************************************************************************//**
204  * Set the Last Epoch property of the event header.
205  *
206  * @note The Last Epoch defaults to the time of event creation.
207  *
208  * @param header        Pointer to the ::EVENT_HEADER.
209  * @param last_epoch_microsec
210  *                      The last epoch to set, in microseconds.
211  *****************************************************************************/
212 void evel_last_epoch_set(EVENT_HEADER * const header,
213                          const unsigned long long last_epoch_microsec)
214 {
215   EVEL_ENTER();
216
217   /***************************************************************************/
218   /* Check preconditions and assign the new value.                           */
219   /***************************************************************************/
220   assert(header != NULL);
221   header->last_epoch_microsec = last_epoch_microsec;
222
223   EVEL_EXIT();
224 }
225
226 /**************************************************************************//**
227  * Set the Reporting Entity Name property of the event header.
228  *
229  * @note The Reporting Entity Name defaults to the OpenStack VM Name.
230  *
231  * @param header        Pointer to the ::EVENT_HEADER.
232  * @param entity_name   The entity name to set.
233  *****************************************************************************/
234 void evel_reporting_entity_name_set(EVENT_HEADER * const header,
235                                     const char * const entity_name)
236 {
237   EVEL_ENTER();
238
239   /***************************************************************************/
240   /* Check preconditions and assign the new value.                           */
241   /***************************************************************************/
242   assert(header != NULL);
243   assert(entity_name != NULL);
244   assert(header->reporting_entity_name != NULL);
245
246   /***************************************************************************/
247   /* Free the previously allocated memory and replace it with a copy of the  */
248   /* provided one.                                                           */
249   /***************************************************************************/
250   free(header->reporting_entity_name);
251   header->reporting_entity_name = strdup(entity_name);
252
253   EVEL_EXIT();
254 }
255
256 /**************************************************************************//**
257  * Set the Reporting Entity Id property of the event header.
258  *
259  * @note The Reporting Entity Id defaults to the OpenStack VM UUID.
260  *
261  * @param header        Pointer to the ::EVENT_HEADER.
262  * @param entity_id     The entity id to set.
263  *****************************************************************************/
264 void evel_reporting_entity_id_set(EVENT_HEADER * const header,
265                                   const char * const entity_id)
266 {
267   EVEL_ENTER();
268
269   /***************************************************************************/
270   /* Check preconditions and assign the new value.                           */
271   /***************************************************************************/
272   assert(header != NULL);
273   assert(entity_id != NULL);
274
275   /***************************************************************************/
276   /* Free the previously allocated memory and replace it with a copy of the  */
277   /* provided one.  Note that evel_force_option_string strdups entity_id.    */
278   /***************************************************************************/
279   evel_free_option_string(&header->reporting_entity_id);
280   evel_force_option_string(&header->reporting_entity_id, entity_id);
281
282   EVEL_EXIT();
283 }
284
285 /**************************************************************************//**
286  * Encode the event as a JSON event object according to AT&T's schema.
287  *
288  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
289  * @param event         Pointer to the ::EVENT_HEADER to encode.
290  *****************************************************************************/
291 void evel_json_encode_header(EVEL_JSON_BUFFER * jbuf,
292                              EVENT_HEADER * event)
293 {
294   char * domain;
295   char * priority;
296
297   EVEL_ENTER();
298
299   /***************************************************************************/
300   /* Check preconditions.                                                    */
301   /***************************************************************************/
302   assert(jbuf != NULL);
303   assert(jbuf->json != NULL);
304   assert(jbuf->max_size > 0);
305   assert(event != NULL);
306
307   domain = evel_event_domain(event->event_domain);
308   priority = evel_event_priority(event->priority);
309   evel_json_open_named_object(jbuf, "commonEventHeader");
310
311   /***************************************************************************/
312   /* Mandatory fields.                                                       */
313   /***************************************************************************/
314   evel_enc_kv_string(jbuf, "domain", domain);
315   evel_enc_kv_string(jbuf, "eventId", event->event_id);
316   evel_enc_kv_string(jbuf, "functionalRole", event->functional_role);
317   evel_enc_kv_ull(jbuf, "lastEpochMicrosec", event->last_epoch_microsec);
318   evel_enc_kv_string(jbuf, "priority", priority);
319   evel_enc_kv_string(
320     jbuf, "reportingEntityName", event->reporting_entity_name);
321   evel_enc_kv_int(jbuf, "sequence", event->sequence);
322   evel_enc_kv_string(jbuf, "sourceName", event->source_name);
323   evel_enc_kv_ull(jbuf, "startEpochMicrosec", event->start_epoch_microsec);
324   evel_enc_version(
325     jbuf, "version", event->major_version, event->minor_version);
326
327   /***************************************************************************/
328   /* Optional fields.                                                        */
329   /***************************************************************************/
330   evel_enc_kv_opt_string(jbuf, "eventType", &event->event_type);
331   evel_enc_kv_opt_string(
332     jbuf, "reportingEntityId", &event->reporting_entity_id);
333   evel_enc_kv_opt_string(jbuf, "sourceId", &event->source_id);
334
335   evel_json_close_object(jbuf);
336
337   EVEL_EXIT();
338 }
339
340 /**************************************************************************//**
341  * Free an event header.
342  *
343  * Free off the event header supplied.  Will free all the contained allocated
344  * memory.
345  *
346  * @note It does not free the header itself, since that may be part of a
347  * larger structure.
348  *****************************************************************************/
349 void evel_free_header(EVENT_HEADER * const event)
350 {
351   EVEL_ENTER();
352
353   /***************************************************************************/
354   /* Check preconditions.  As an internal API we don't allow freeing NULL    */
355   /* events as we do on the public API.                                      */
356   /***************************************************************************/
357   assert(event != NULL);
358
359   /***************************************************************************/
360   /* Free all internal strings.                                              */
361   /***************************************************************************/
362   free(event->event_id);
363   evel_free_option_string(&event->event_type);
364   free(event->functional_role);
365   evel_free_option_string(&event->reporting_entity_id);
366   free(event->reporting_entity_name);
367   evel_free_option_string(&event->source_id);
368   free(event->source_name);
369
370   EVEL_EXIT();
371 }
372
373 /**************************************************************************//**
374  * Encode the event as a JSON event object according to AT&T's schema.
375  *
376  * @param json      Pointer to where to store the JSON encoded data.
377  * @param max_size  Size of storage available in json_body.
378  * @param event     Pointer to the ::EVENT_HEADER to encode.
379  * @returns Number of bytes actually written.
380  *****************************************************************************/
381 int evel_json_encode_event(char * json,
382                            int max_size,
383                            EVENT_HEADER * event)
384 {
385   EVEL_JSON_BUFFER json_buffer;
386   EVEL_JSON_BUFFER * jbuf = &json_buffer;
387   EVEL_THROTTLE_SPEC * throttle_spec;
388
389   EVEL_ENTER();
390
391   /***************************************************************************/
392   /* Get the latest throttle specification for the domain.                   */
393   /***************************************************************************/
394   throttle_spec = evel_get_throttle_spec(event->event_domain);
395
396   /***************************************************************************/
397   /* Initialize the JSON_BUFFER and open the top-level objects.              */
398   /***************************************************************************/
399   evel_json_buffer_init(jbuf, json, max_size, throttle_spec);
400   evel_json_open_object(jbuf);
401   evel_json_open_named_object(jbuf, "event");
402
403   switch (event->event_domain)
404   {
405     case EVEL_DOMAIN_HEARTBEAT:
406       evel_json_encode_header(jbuf, event);
407       break;
408
409     case EVEL_DOMAIN_FAULT:
410       evel_json_encode_fault(jbuf, (EVENT_FAULT *)event);
411       break;
412
413     case EVEL_DOMAIN_MEASUREMENT:
414       evel_json_encode_measurement(jbuf, (EVENT_MEASUREMENT *)event);
415       break;
416
417     case EVEL_DOMAIN_MOBILE_FLOW:
418       evel_json_encode_mobile_flow(jbuf, (EVENT_MOBILE_FLOW *)event);
419       break;
420
421     case EVEL_DOMAIN_REPORT:
422       evel_json_encode_report(jbuf, (EVENT_REPORT *)event);
423       break;
424
425     case EVEL_DOMAIN_SERVICE:
426       evel_json_encode_service(jbuf, (EVENT_SERVICE *)event);
427       break;
428
429     case EVEL_DOMAIN_SIGNALING:
430       evel_json_encode_signaling(jbuf, (EVENT_SIGNALING *)event);
431       break;
432
433     case EVEL_DOMAIN_STATE_CHANGE:
434       evel_json_encode_state_change(jbuf, (EVENT_STATE_CHANGE *)event);
435       break;
436
437     case EVEL_DOMAIN_SYSLOG:
438       evel_json_encode_syslog(jbuf, (EVENT_SYSLOG *)event);
439       break;
440
441     case EVEL_DOMAIN_OTHER:
442       evel_json_encode_other(jbuf, (EVENT_OTHER *)event);
443       break;
444
445     case EVEL_DOMAIN_INTERNAL:
446     default:
447       EVEL_ERROR("Unexpected domain %d", event->event_domain);
448       assert(0);
449   }
450
451   evel_json_close_object(jbuf);
452   evel_json_close_object(jbuf);
453
454   /***************************************************************************/
455   /* Sanity check.                                                           */
456   /***************************************************************************/
457   assert(jbuf->depth == 0);
458
459   EVEL_EXIT();
460
461   return jbuf->offset;
462 }
463
464 /**************************************************************************//**
465  * Initialize an event instance id.
466  *
467  * @param instance_id   Pointer to the event instance id being initialized.
468  * @param vendor_id     The vendor id to encode in the event instance id.
469  * @param event_id      The event id to encode in the event instance id.
470  *****************************************************************************/
471 void evel_init_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id,
472                                  const char * const vendor_id,
473                                  const char * const event_id)
474 {
475   EVEL_ENTER();
476
477   /***************************************************************************/
478   /* Check preconditions.                                                    */
479   /***************************************************************************/
480   assert(instance_id != NULL);
481   assert(vendor_id != NULL);
482   assert(event_id != NULL);
483
484   /***************************************************************************/
485   /* Store the mandatory parts.                                              */
486   /***************************************************************************/
487   instance_id->vendor_id = strdup(vendor_id);
488   instance_id->event_id = strdup(event_id);
489
490   /***************************************************************************/
491   /* Initialize the optional parts.                                          */
492   /***************************************************************************/
493   evel_init_option_string(&instance_id->product_id);
494   evel_init_option_string(&instance_id->subsystem_id);
495   evel_init_option_string(&instance_id->event_friendly_name);
496
497   EVEL_EXIT();
498 }
499
500 /**************************************************************************//**
501  * Free an event instance id.
502  *
503  * @param instance_id   Pointer to the event instance id being initialized.
504  *****************************************************************************/
505 void evel_free_event_instance_id(EVEL_EVENT_INSTANCE_ID * const instance_id)
506 {
507   EVEL_ENTER();
508
509   /***************************************************************************/
510   /* Check preconditions.                                                    */
511   /***************************************************************************/
512   assert(instance_id != NULL);
513   assert(instance_id->vendor_id != NULL);
514   assert(instance_id->event_id != NULL);
515
516   /***************************************************************************/
517   /* Free everything.                                                        */
518   /***************************************************************************/
519   free(instance_id->vendor_id);
520   free(instance_id->event_id);
521   evel_free_option_string(&instance_id->product_id);
522   evel_free_option_string(&instance_id->subsystem_id);
523   evel_free_option_string(&instance_id->event_friendly_name);
524
525   EVEL_EXIT();
526 }
527
528 /**************************************************************************//**
529  * Encode the instance id as a JSON object according to AT&T's schema.
530  *
531  * @param jbuf          Pointer to the ::EVEL_JSON_BUFFER to encode into.
532  * @param instance_id   Pointer to the ::EVEL_EVENT_INSTANCE_ID to encode.
533  *****************************************************************************/
534 void evel_json_encode_instance_id(EVEL_JSON_BUFFER * jbuf,
535                                   EVEL_EVENT_INSTANCE_ID * instance_id)
536 {
537   EVEL_ENTER();
538
539   /***************************************************************************/
540   /* Check preconditions.                                                    */
541   /***************************************************************************/
542   assert(jbuf != NULL);
543   assert(jbuf->json != NULL);
544   assert(jbuf->max_size > 0);
545   assert(instance_id != NULL);
546   assert(instance_id->vendor_id != NULL);
547   assert(instance_id->event_id != NULL);
548
549   evel_json_open_named_object(jbuf, "eventInstanceIdentifier");
550
551   /***************************************************************************/
552   /* Mandatory fields.                                                       */
553   /***************************************************************************/
554   evel_enc_kv_string(jbuf, "vendorId", instance_id->vendor_id);
555   evel_enc_kv_string(jbuf, "eventId", instance_id->event_id);
556
557   /***************************************************************************/
558   /* Optional fields.                                                        */
559   /***************************************************************************/
560   evel_enc_kv_opt_string(jbuf, "productId", &instance_id->product_id);
561   evel_enc_kv_opt_string(jbuf, "subsystemId", &instance_id->subsystem_id);
562   evel_enc_kv_opt_string(
563     jbuf, "eventFriendlyName", &instance_id->event_friendly_name);
564
565   evel_json_close_object(jbuf);
566
567   EVEL_EXIT();
568 }