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