Add API allowing xAPPs to send alarm messages
[ric-plt/xapp-frame-cpp.git] / src / alarm / alarm.cpp
1 // vi: ts=4 sw=4 noet:
2 /*
3 ==================================================================================
4         Copyright (c) 2020 Nokia
5         Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22         Mnemonic:       alarm.cpp
23         Abstract:       This class provides an API to the alarm collector/reporter.
24                                 An object is insanced by the user xAPP allowing the xAPP
25                                 to send, clear, or resend the alarm as is necessary.
26
27
28         Date:           15 July 2020
29         Author:         E. Scott Daniels
30 */
31
32 #include <string.h>
33 #include <unistd.h>
34 #include <time.h>
35
36 #include <rmr/RIC_message_types.h>
37 #ifndef RIC_ALARM
38         #define RIC_ALARM 110
39 #endif
40
41 #include <iostream>
42
43 #include "msg_component.hpp"
44 #include "message.hpp"
45 #include "alarm.hpp"
46
47 extern char* __progname;                        // runtime lib supplied since we don't get argv[0]
48
49 namespace xapp {
50
51
52
53 // ------ private ----------------------------------------------
54
55 /*
56         Suss out the alarm target from environment.
57
58         We expect two variables in the environment:
59                 ALARM_MGR_SERVICE_NAME
60                 ALARM_MGR_SERVICE_PORT
61
62         If name is not given, localhost is assumed. If port is not given
63         then we assume 4560 (the defacto RMR listen port).
64 */
65 static std::string endpoint_addr( ) {
66         char*   et;                                                                     // environment token
67         std::string addr = "localhost";
68         std::string port = "4560";
69
70         if( (et = getenv( "ALARM_MGR_SERVICE_NAME" )) != NULL ) {
71                 addr = std::string( et );
72         }
73
74         if( (et = getenv( "ALARM_MGR_SERVICE_PORT" )) != NULL ) {
75                 port = std::string( et );
76         }
77
78         return addr + ":" + port;
79 }
80
81
82 /*
83         Return the current time in milliseconds past the UNIX epoch.
84 */
85 static long long now( void ) {
86         struct timespec ts;
87         long long       now = 0;
88
89         clock_gettime( CLOCK_REALTIME, &ts );
90         now = (ts.tv_sec * 1000000) + (ts.tv_nsec/1000000);     // convert nano to milli and bang onto seconds
91
92         return now;
93 }
94
95
96 /*
97         Build the alarm json message with the current data.
98         Returns the length of the payload inserted.
99 */
100 int xapp::Alarm::build_alarm( int action_id, xapp::Msg_component payload, int payload_len ) {
101         //char  wbuf[4096];
102         std::string action;
103         int used;
104
105         if( app_id.compare( "" ) == 0 ) {
106                 app_id = std::string( __progname );                             // see comment for extern above
107         }
108
109         if( severity.compare( "" ) == 0 ) {
110                 Set_severity( Alarm::SEV_WARN );
111         }
112
113         switch( action_id ) {
114                 case    Alarm::ACT_CLEAR:
115                         action = "CLEAR";
116                         break;
117
118                 case    Alarm::ACT_CLEAR_ALL:
119                         action = "CLEARALL";
120                         break;
121
122                 default:
123                         action = "RAISE";
124                         break;
125         }
126
127         //memset( wbuf, 0, sizeof( wbuf ) );
128         //snprintf( wbuf, sizeof( wbuf ),
129         used = snprintf( (char *) payload.get(), payload_len,
130                         "{  "
131                         "\"managedObjectId\": \"%s\", "
132                         "\"applicationId\": \"%s\", "
133                         "\"specificProblem\": %d, "
134                         "\"perceivedSeverity\": \"%s\", "
135                         "\"identifyingInfo\": \"%s\", "
136                         "\"additionalInfo\": \"%s\", "
137                         "\"AlarmAction\": \"%s\", "
138                         "\"AlarmTime\": %lld"
139                         " }",
140
141                         me_id.c_str(),
142                         app_id.c_str(),
143                         problem_id,
144                         severity.c_str(),
145                         info.c_str(),
146                         add_info.c_str(),
147                         action.c_str(),
148                         now()
149         );
150
151         //action = std::string( wbuf );
152         return used;
153 }
154
155 // --------------- builders/operators  -------------------------------------
156
157 /*
158         Create a new message wrapper for an existing RMR msg buffer.
159
160         msg is a message which was allocaed by the framework and thus has the
161         mrc reference embedded.
162 */
163 xapp::Alarm::Alarm( std::shared_ptr<Message> msg ) :
164         msg( msg ),
165         endpoint( endpoint_addr() ),
166         whid( -1 ),
167         app_id( "" ),
168         me_id( "" ),
169         problem_id( -1 ),
170         info( "" ),
171         add_info( "" ),
172         action( "" )
173 { /* empty body */ }
174
175 /*
176         Parameterised constructor (avoids calling setters after creation).
177 */
178 xapp::Alarm::Alarm( std::shared_ptr<Message> msg, int prob_id, std::string meid  ) :
179         msg( msg ),
180         endpoint( endpoint_addr() ),
181         whid( -1 ),
182         app_id( "" ),
183         me_id( meid ),
184         problem_id( prob_id ),
185         info( "" ),
186         add_info( "" ),
187         action( "" )
188 { /* empty body */ }
189
190 xapp::Alarm::Alarm( std::shared_ptr<Message> msg, std::string meid  ) :
191         msg( msg ),
192         endpoint( endpoint_addr() ),
193         whid( -1 ),
194         app_id( "" ),
195         me_id( meid ),
196         problem_id( -1 ),
197         info( "" ),
198         add_info( "" ),
199         action( "" )
200 { /* empty body */ }
201
202
203
204 // ------------------ copy and move support ---------------------------------
205
206 /*
207         Copy builder.  Given a source object instance (soi), create a copy.
208         Creating a copy should be avoided as it can be SLOW!
209 */
210 xapp::Alarm::Alarm( const Alarm& soi ) {
211         msg = soi.msg;
212         endpoint = soi.endpoint;
213         whid = soi.whid;
214
215         me_id = soi.me_id;                              // user stuff
216         app_id = soi.app_id;
217         problem_id = soi.problem_id;
218         severity = soi.severity;
219         info = soi.info;
220         add_info = soi.add_info;
221 }
222
223 /*
224         Assignment operator. Simiolar to the copycat, but "this" object exists and
225         may have data that needs to be released prior to making a copy of the soi.
226 */
227 Alarm& xapp::Alarm::operator=( const Alarm& soi ) {
228         if( this != &soi ) {                            // cannot do self assignment
229                 msg = soi.msg;
230                 endpoint = soi.endpoint;
231                 whid = soi.whid;
232
233                 me_id = soi.me_id;
234                 app_id = soi.app_id;
235                 problem_id = soi.problem_id;
236                 severity = soi.severity;
237                 info = soi.info;
238                 add_info = soi.add_info;
239         }
240
241         return *this;
242 }
243
244 /*
245         Move builder.  Given a source object instance (soi), move the information from
246         the soi ensuring that the destriction of the soi doesn't trash things from
247         under us.
248 */
249 xapp::Alarm::Alarm( Alarm&& soi ) {
250         msg = soi.msg;          // capture pointers and copy data before setting soruce things to nil
251         endpoint = soi.endpoint;
252         whid = soi.whid;
253
254         me_id = soi.me_id;
255         app_id = soi.app_id;
256         problem_id = soi.problem_id;
257         severity = soi.severity;
258         info = soi.info;
259         add_info = soi.add_info;
260
261         soi.msg = NULL;         // prevent closing of RMR stuff on soi destroy
262 }
263
264 /*
265         Move Assignment operator. Move the message data to the existing object
266         ensure the object reference is cleaned up, and ensuring that the source
267         object references are removed.
268 */
269 Alarm& xapp::Alarm::operator=( Alarm&& soi ) {
270         if( this != &soi ) {                            // cannot do self assignment
271                 // anything that needs to be freed/delted from soi, must be done here
272
273                 msg = soi.msg;                  // move pointers and values
274                 endpoint = soi.endpoint;
275                 whid = soi.whid;
276
277                 me_id = soi.me_id;
278                 app_id = soi.app_id;
279                 problem_id = soi.problem_id;
280                 severity = soi.severity;
281                 info = soi.info;
282                 add_info = soi.add_info;
283
284                 soi.msg = NULL;                 // prevent bad things when source is destroyed
285         }
286
287         return *this;
288 }
289
290 /*
291         Destroyer.
292 */
293 xapp::Alarm::~Alarm() {
294
295         msg = NULL;
296 }
297
298
299 // ---- setters -------------------------------------------------
300
301 void xapp::Alarm::Set_meid( std::string new_meid ) {
302         me_id = new_meid;
303 }
304
305 void xapp::Alarm::Set_severity( int new_sev ) {
306         switch( new_sev ) {
307                 case    Alarm::SEV_CRIT:
308                         severity = "CRITICAL";
309                         break;
310
311                 case    Alarm::SEV_MAJOR:
312                         severity = "MAJOR";
313                         break;
314
315                 case    Alarm::SEV_MINOR:
316                         severity = "MINOR";
317                         break;
318
319                 case    Alarm::SEV_WARN:
320                         severity = "WARNING";
321                         break;
322
323                 case    Alarm::SEV_CLEAR:
324                         severity = "CLEARED";
325                         break;
326
327                 default:
328                         severity = "DEFAULT";
329                         break;
330         }
331 }
332
333 void xapp::Alarm::Set_appid( std::string new_id ) {
334         app_id = new_id;
335 }
336
337 void xapp::Alarm::Set_problem( int new_id ) {
338         problem_id = new_id;
339 }
340
341 void xapp::Alarm::Set_info( std::string new_info ) {
342         info = new_info;
343 }
344
345 void xapp::Alarm::Set_additional( std::string new_info ) {
346         add_info = new_info;
347 }
348
349 void xapp::Alarm::Set_whid( int new_whid ) {
350         whid = new_whid;
351 }
352
353 void xapp::Alarm::Dump() {
354         fprintf( stderr, "Alarm: prob id: %d\n", problem_id );
355         fprintf( stderr, "Alarm: meid: %s\n", me_id.c_str() );
356         fprintf( stderr, "Alarm: app: %s\n", app_id.c_str() );
357         fprintf( stderr, "Alarm: info: %s\n", info.c_str() );
358         fprintf( stderr, "Alarm: ainfo: %s\n", add_info.c_str() );
359 }
360
361 // ------------------- getters ------------------------------------
362
363 /*
364         Return the enpoint address string we have.
365 */
366 std::string xapp::Alarm::Get_endpoint( ) {
367         return endpoint;
368 }
369
370 // ------- message sending ---------------------------------------
371
372 /*
373         Send a raise message with the alarm contents unchanged.
374 */
375 bool xapp::Alarm::Raise( ) {
376         int used;
377         used = build_alarm( ACT_RAISE, msg->Get_payload(), msg->Get_available_size() );
378         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
379 }
380
381 /*
382         Additional prototypes allow for avoiding some setter calls when raising alarms.
383         Severity is one of our SEV_* constants. Problem is the caller's assigned
384         problem ID. Info and addional_info are user supplied data that is just passed
385         through.
386 */
387 bool xapp::Alarm::Raise( int severity, int problem, std::string info ) {
388         this->severity = severity;
389         problem_id = problem;
390         this->info = info;
391
392         Raise();
393 }
394
395 bool xapp::Alarm::Raise( int severity, int problem, std::string info, std::string additional_info ) {
396         this->severity = severity;
397         problem_id = problem;
398         this->info = info;
399         this->add_info = additional_info;
400
401         Raise();
402 }
403
404 /*
405         Send a clear message with the contents of the alarm otherwise unchanged.
406 */
407 bool xapp::Alarm::Clear( ) {
408         int used;
409
410         used = build_alarm( ACT_CLEAR, msg->Get_payload(), msg->Get_available_size() );
411         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
412 }
413
414 /*
415         Additional prototypes allow for avoiding some setter calls when raising alarms.
416         Severity is one of our SEV_* constants. Problem is the caller's assigned
417         problem ID. Info and addional_info are user supplied data that is just passed
418         through.
419 */
420 bool xapp::Alarm::Clear( int severity, int problem, std::string info ) {
421         this->severity = severity;
422         problem_id = problem;
423         this->info = info;
424
425         Clear();
426 }
427
428 bool xapp::Alarm::Clear( int severity, int problem, std::string info, std::string additional_info ) {
429         this->severity = severity;
430         problem_id = problem;
431         this->info = info;
432         this->add_info = additional_info;
433
434         Clear();
435 }
436
437
438 /*
439         Send a clear-all message. The contents of the alarm are unaffected.
440 */
441 bool xapp::Alarm::Clear_all( ) {
442         int used;
443
444         used = build_alarm( ACT_CLEAR_ALL, msg->Get_payload(), msg->Get_available_size() );
445         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
446 }
447
448
449 /*
450         This is a convenience function which sends a clear message followed by a
451         raise message. Alarm contents are not adjusted.
452 */
453 bool xapp::Alarm::Raise_again( ) {
454         Clear();
455         Raise();
456 }
457
458
459
460 } // namespace