c263f7afb1abb09f1308d91ee4c8ce085fdfea32
[ric-plt/xapp-frame-cpp.git] / 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 #include <iostream>
36
37 #include <rmr/RIC_message_types.h>
38
39 #include "msg_component.hpp"
40 #include "message.hpp"
41 #include "alarm.hpp"
42
43 #ifndef RIC_ALARM
44         // this _should_ come from the message types header, but if not ensure we have something
45         constexpr int ric_alarm_value = 110;
46         #define RIC_ALARM ric_alarm_value
47 #endif
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         return used;
151 }
152
153 // --------------- builders/operators  -------------------------------------
154
155 /*
156         Create a new message wrapper for an existing RMR msg buffer.
157
158         msg is a message which was allocaed by the framework and thus has the
159         mrc reference embedded.
160 */
161 xapp::Alarm::Alarm( std::shared_ptr<Message> msg ) :
162         msg( msg ),
163         endpoint( endpoint_addr() )
164 { /* empty body */ }
165
166 /*
167         Parameterised constructor (avoids calling setters after creation).
168 */
169 xapp::Alarm::Alarm( std::shared_ptr<Message> msg, int prob_id, const std::string& meid  ) :
170         msg( msg ),
171         endpoint( endpoint_addr() ),
172         me_id( meid ),
173         problem_id( prob_id )
174 { /* empty body */ }
175
176 xapp::Alarm::Alarm( std::shared_ptr<Message> msg, const std::string& meid  ) :
177         msg( msg ),
178         endpoint( endpoint_addr() ),
179         me_id( meid )
180 { /* empty body */ }
181
182
183
184 // ------------------ copy and move support ---------------------------------
185
186 /*
187         Copy builder.  Given a source object instance (soi), create a copy.
188         Creating a copy should be avoided as it can be SLOW!
189 */
190 xapp::Alarm::Alarm( const Alarm& soi ) :
191         msg(  soi.msg ),
192         endpoint(  soi.endpoint ),
193         whid(  soi.whid ),
194
195         me_id(  soi.me_id ),                            // user stuff
196         app_id(  soi.app_id ),
197         problem_id(  soi.problem_id ),
198         severity(  soi.severity ),
199         info(  soi.info ),
200         add_info(  soi.add_info )
201 { /* empty body */ }
202
203 /*
204         Assignment operator. Simiolar to the copycat, but "this" object exists and
205         may have data that needs to be released prior to making a copy of the soi.
206 */
207 Alarm& xapp::Alarm::operator=( const Alarm& soi ) {
208         if( this != &soi ) {                            // cannot do self assignment
209                 msg = soi.msg;
210                 endpoint = soi.endpoint;
211                 whid = soi.whid;
212                 me_id = soi.me_id;
213                 app_id = soi.app_id;
214                 problem_id = soi.problem_id;
215                 severity = soi.severity;
216                 info = soi.info;
217                 add_info = soi.add_info;
218         }
219
220         return *this;
221 }
222
223 /*
224         Move builder.  Given a source object instance (soi), move the information from
225         the soi ensuring that the destriction of the soi doesn't trash things from
226         under us.
227 */
228 xapp::Alarm::Alarm( Alarm&& soi )  :
229         msg(  soi.msg ),                                        // order must match .hpp else sonar complains
230         endpoint(  soi.endpoint ),
231         whid(  soi.whid ),
232         me_id(  soi.me_id ),
233         app_id(  soi.app_id ),
234         problem_id(  soi.problem_id ),
235         severity(  soi.severity ),
236         info(  soi.info ),
237         add_info(  soi.add_info )
238 {
239
240         soi.msg = NULL;         // prevent closing of RMR stuff on soi destroy
241 }
242
243 /*
244         Move Assignment operator. Move the message data to the existing object
245         ensure the object reference is cleaned up, and ensuring that the source
246         object references are removed.
247 */
248 Alarm& xapp::Alarm::operator=( Alarm&& soi ) noexcept {
249         if( this != &soi ) {                            // cannot do self assignment
250                 // anything that needs to be freed/delted from soi, must be done here
251
252                 msg = soi.msg;                  // move pointers and values
253                 endpoint = soi.endpoint;
254                 whid = soi.whid;
255
256                 me_id = soi.me_id;
257                 app_id = soi.app_id;
258                 problem_id = soi.problem_id;
259                 severity = soi.severity;
260                 info = soi.info;
261                 add_info = soi.add_info;
262
263                 soi.msg = NULL;                 // prevent bad things when source is destroyed
264         }
265
266         return *this;
267 }
268
269 /*
270         Destroyer.
271 */
272 xapp::Alarm::~Alarm() {
273
274         msg = NULL;
275 }
276
277
278 // ---- setters -------------------------------------------------
279
280 void xapp::Alarm::Set_meid( const std::string& new_meid ) {
281         me_id = new_meid;
282 }
283
284 void xapp::Alarm::Set_severity( int new_sev ) {
285         switch( new_sev ) {
286                 case    Alarm::SEV_CRIT:
287                         severity = "CRITICAL";
288                         break;
289
290                 case    Alarm::SEV_MAJOR:
291                         severity = "MAJOR";
292                         break;
293
294                 case    Alarm::SEV_MINOR:
295                         severity = "MINOR";
296                         break;
297
298                 case    Alarm::SEV_WARN:
299                         severity = "WARNING";
300                         break;
301
302                 case    Alarm::SEV_CLEAR:
303                         severity = "CLEARED";
304                         break;
305
306                 default:
307                         severity = "DEFAULT";
308                         break;
309         }
310 }
311
312 void xapp::Alarm::Set_appid( const std::string& new_id ) {
313         app_id = new_id;
314 }
315
316 void xapp::Alarm::Set_problem( int new_id ) {
317         problem_id = new_id;
318 }
319
320 void xapp::Alarm::Set_info( const std::string& new_info ) {
321         info = new_info;
322 }
323
324 void xapp::Alarm::Set_additional( const std::string& new_info ) {
325         add_info = new_info;
326 }
327
328 void xapp::Alarm::Set_whid( int new_whid ) {
329         whid = new_whid;
330 }
331
332 void xapp::Alarm::Dump() const {
333         fprintf( stderr, "Alarm: prob id: %d\n", problem_id );
334         fprintf( stderr, "Alarm: meid: %s\n", me_id.c_str() );
335         fprintf( stderr, "Alarm: app: %s\n", app_id.c_str() );
336         fprintf( stderr, "Alarm: info: %s\n", info.c_str() );
337         fprintf( stderr, "Alarm: ainfo: %s\n", add_info.c_str() );
338 }
339
340 // ------------------- getters ------------------------------------
341
342 /*
343         Return the enpoint address string we have.
344 */
345 std::string xapp::Alarm::Get_endpoint( ) const {
346         return endpoint;
347 }
348
349 // ------- message sending ---------------------------------------
350
351 /*
352         Send a raise message with the alarm contents unchanged.
353 */
354 bool xapp::Alarm::Raise( ) {
355         int used;
356         used = build_alarm( ACT_RAISE, msg->Get_payload(), msg->Get_available_size() );
357         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
358 }
359
360 /*
361         Additional prototypes allow for avoiding some setter calls when raising alarms.
362         Severity is one of our SEV_* constants. Problem is the caller's assigned
363         problem ID. Info and addional_info are user supplied data that is just passed
364         through.
365 */
366 bool xapp::Alarm::Raise( int new_severity, int problem, const std::string& cinfo ) {
367         Set_severity( new_severity );
368         problem_id = problem;
369         info = cinfo;
370
371         Raise();
372 }
373
374 bool xapp::Alarm::Raise( int new_severity, int problem, const std::string& cinfo, const std::string& additional_info ) {
375         Set_severity( new_severity );
376         problem_id = problem;
377         info = cinfo;
378         this->add_info = additional_info;
379
380         Raise();
381 }
382
383 /*
384         Send a clear message with the contents of the alarm otherwise unchanged.
385 */
386 bool xapp::Alarm::Clear( ) {
387         int used;
388
389         used = build_alarm( ACT_CLEAR, msg->Get_payload(), msg->Get_available_size() );
390         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
391 }
392
393 /*
394         Additional prototypes allow for avoiding some setter calls when raising alarms.
395         Severity is one of our SEV_* constants. Problem is the caller's assigned
396         problem ID. Info and addional_info are user supplied data that is just passed
397         through.
398 */
399 bool xapp::Alarm::Clear( int new_severity, int problem, const std::string& cinfo ) {
400         Set_severity( new_severity );
401         problem_id = problem;
402         info = cinfo;
403
404         Clear();
405 }
406
407 bool xapp::Alarm::Clear( int new_severity, int problem, const std::string& cinfo, const std::string& additional_info ) {
408         Set_severity( new_severity );
409         problem_id = problem;
410         info = cinfo;
411         this->add_info = additional_info;
412
413         Clear();
414 }
415
416
417 /*
418         Send a clear-all message. The contents of the alarm are unaffected.
419 */
420 bool xapp::Alarm::Clear_all( ) {
421         int used;
422
423         used = build_alarm( ACT_CLEAR_ALL, msg->Get_payload(), msg->Get_available_size() );
424         msg->Wormhole_send( whid,  RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
425 }
426
427
428 /*
429         This is a convenience function which sends a clear message followed by a
430         raise message. Alarm contents are not adjusted.
431 */
432 bool xapp::Alarm::Raise_again( ) {
433         Clear();
434         Raise();
435 }
436
437
438
439 } // namespace