blob: c263f7afb1abb09f1308d91ee4c8ce085fdfea32 [file] [log] [blame]
// vi: ts=4 sw=4 noet:
/*
==================================================================================
Copyright (c) 2020 Nokia
Copyright (c) 2020 AT&T Intellectual Property.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================================
*/
/*
Mnemonic: alarm.cpp
Abstract: This class provides an API to the alarm collector/reporter.
An object is insanced by the user xAPP allowing the xAPP
to send, clear, or resend the alarm as is necessary.
Date: 15 July 2020
Author: E. Scott Daniels
*/
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <iostream>
#include <rmr/RIC_message_types.h>
#include "msg_component.hpp"
#include "message.hpp"
#include "alarm.hpp"
#ifndef RIC_ALARM
// this _should_ come from the message types header, but if not ensure we have something
constexpr int ric_alarm_value = 110;
#define RIC_ALARM ric_alarm_value
#endif
extern const char* __progname; // runtime lib supplied since we don't get argv[0]
namespace xapp {
// ------ private ----------------------------------------------
/*
Suss out the alarm target from environment.
We expect two variables in the environment:
ALARM_MGR_SERVICE_NAME
ALARM_MGR_SERVICE_PORT
If name is not given, localhost is assumed. If port is not given
then we assume 4560 (the defacto RMR listen port).
*/
static std::string endpoint_addr( ) {
const char* et; // environment token
std::string addr = "localhost";
std::string port = "4560";
if( (et = getenv( "ALARM_MGR_SERVICE_NAME" )) != NULL ) {
addr = std::string( et );
}
if( (et = getenv( "ALARM_MGR_SERVICE_PORT" )) != NULL ) {
port = std::string( et );
}
return addr + ":" + port;
}
/*
Return the current time in milliseconds past the UNIX epoch.
*/
static long long now( void ) {
struct timespec ts;
long long now = 0;
clock_gettime( CLOCK_REALTIME, &ts );
now = (ts.tv_sec * 1000000) + (ts.tv_nsec/1000000); // convert nano to milli and bang onto seconds
return now;
}
/*
Build the alarm json message with the current data.
Returns the length of the payload inserted.
*/
int xapp::Alarm::build_alarm( int action_id, xapp::Msg_component payload, int payload_len ) {
std::string maction; // message action is a text string
int used;
if( app_id.compare( "" ) == 0 ) {
app_id = std::string( __progname ); // see comment for extern above
}
if( severity.compare( "" ) == 0 ) {
Set_severity( Alarm::SEV_WARN );
}
switch( action_id ) {
case Alarm::ACT_CLEAR:
maction = "CLEAR";
break;
case Alarm::ACT_CLEAR_ALL:
maction = "CLEARALL";
break;
default:
maction = "RAISE";
break;
}
used = snprintf( (char *) payload.get(), payload_len,
"{ "
"\"managedObjectId\": \"%s\", "
"\"applicationId\": \"%s\", "
"\"specificProblem\": %d, "
"\"perceivedSeverity\": \"%s\", "
"\"identifyingInfo\": \"%s\", "
"\"additionalInfo\": \"%s\", "
"\"AlarmAction\": \"%s\", "
"\"AlarmTime\": %lld"
" }",
me_id.c_str(),
app_id.c_str(),
problem_id,
severity.c_str(),
info.c_str(),
add_info.c_str(),
maction.c_str(),
now()
);
return used;
}
// --------------- builders/operators -------------------------------------
/*
Create a new message wrapper for an existing RMR msg buffer.
msg is a message which was allocaed by the framework and thus has the
mrc reference embedded.
*/
xapp::Alarm::Alarm( std::shared_ptr<Message> msg ) :
msg( msg ),
endpoint( endpoint_addr() )
{ /* empty body */ }
/*
Parameterised constructor (avoids calling setters after creation).
*/
xapp::Alarm::Alarm( std::shared_ptr<Message> msg, int prob_id, const std::string& meid ) :
msg( msg ),
endpoint( endpoint_addr() ),
me_id( meid ),
problem_id( prob_id )
{ /* empty body */ }
xapp::Alarm::Alarm( std::shared_ptr<Message> msg, const std::string& meid ) :
msg( msg ),
endpoint( endpoint_addr() ),
me_id( meid )
{ /* empty body */ }
// ------------------ copy and move support ---------------------------------
/*
Copy builder. Given a source object instance (soi), create a copy.
Creating a copy should be avoided as it can be SLOW!
*/
xapp::Alarm::Alarm( const Alarm& soi ) :
msg( soi.msg ),
endpoint( soi.endpoint ),
whid( soi.whid ),
me_id( soi.me_id ), // user stuff
app_id( soi.app_id ),
problem_id( soi.problem_id ),
severity( soi.severity ),
info( soi.info ),
add_info( soi.add_info )
{ /* empty body */ }
/*
Assignment operator. Simiolar to the copycat, but "this" object exists and
may have data that needs to be released prior to making a copy of the soi.
*/
Alarm& xapp::Alarm::operator=( const Alarm& soi ) {
if( this != &soi ) { // cannot do self assignment
msg = soi.msg;
endpoint = soi.endpoint;
whid = soi.whid;
me_id = soi.me_id;
app_id = soi.app_id;
problem_id = soi.problem_id;
severity = soi.severity;
info = soi.info;
add_info = soi.add_info;
}
return *this;
}
/*
Move builder. Given a source object instance (soi), move the information from
the soi ensuring that the destriction of the soi doesn't trash things from
under us.
*/
xapp::Alarm::Alarm( Alarm&& soi ) :
msg( soi.msg ), // order must match .hpp else sonar complains
endpoint( soi.endpoint ),
whid( soi.whid ),
me_id( soi.me_id ),
app_id( soi.app_id ),
problem_id( soi.problem_id ),
severity( soi.severity ),
info( soi.info ),
add_info( soi.add_info )
{
soi.msg = NULL; // prevent closing of RMR stuff on soi destroy
}
/*
Move Assignment operator. Move the message data to the existing object
ensure the object reference is cleaned up, and ensuring that the source
object references are removed.
*/
Alarm& xapp::Alarm::operator=( Alarm&& soi ) noexcept {
if( this != &soi ) { // cannot do self assignment
// anything that needs to be freed/delted from soi, must be done here
msg = soi.msg; // move pointers and values
endpoint = soi.endpoint;
whid = soi.whid;
me_id = soi.me_id;
app_id = soi.app_id;
problem_id = soi.problem_id;
severity = soi.severity;
info = soi.info;
add_info = soi.add_info;
soi.msg = NULL; // prevent bad things when source is destroyed
}
return *this;
}
/*
Destroyer.
*/
xapp::Alarm::~Alarm() {
msg = NULL;
}
// ---- setters -------------------------------------------------
void xapp::Alarm::Set_meid( const std::string& new_meid ) {
me_id = new_meid;
}
void xapp::Alarm::Set_severity( int new_sev ) {
switch( new_sev ) {
case Alarm::SEV_CRIT:
severity = "CRITICAL";
break;
case Alarm::SEV_MAJOR:
severity = "MAJOR";
break;
case Alarm::SEV_MINOR:
severity = "MINOR";
break;
case Alarm::SEV_WARN:
severity = "WARNING";
break;
case Alarm::SEV_CLEAR:
severity = "CLEARED";
break;
default:
severity = "DEFAULT";
break;
}
}
void xapp::Alarm::Set_appid( const std::string& new_id ) {
app_id = new_id;
}
void xapp::Alarm::Set_problem( int new_id ) {
problem_id = new_id;
}
void xapp::Alarm::Set_info( const std::string& new_info ) {
info = new_info;
}
void xapp::Alarm::Set_additional( const std::string& new_info ) {
add_info = new_info;
}
void xapp::Alarm::Set_whid( int new_whid ) {
whid = new_whid;
}
void xapp::Alarm::Dump() const {
fprintf( stderr, "Alarm: prob id: %d\n", problem_id );
fprintf( stderr, "Alarm: meid: %s\n", me_id.c_str() );
fprintf( stderr, "Alarm: app: %s\n", app_id.c_str() );
fprintf( stderr, "Alarm: info: %s\n", info.c_str() );
fprintf( stderr, "Alarm: ainfo: %s\n", add_info.c_str() );
}
// ------------------- getters ------------------------------------
/*
Return the enpoint address string we have.
*/
std::string xapp::Alarm::Get_endpoint( ) const {
return endpoint;
}
// ------- message sending ---------------------------------------
/*
Send a raise message with the alarm contents unchanged.
*/
bool xapp::Alarm::Raise( ) {
int used;
used = build_alarm( ACT_RAISE, msg->Get_payload(), msg->Get_available_size() );
msg->Wormhole_send( whid, RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
}
/*
Additional prototypes allow for avoiding some setter calls when raising alarms.
Severity is one of our SEV_* constants. Problem is the caller's assigned
problem ID. Info and addional_info are user supplied data that is just passed
through.
*/
bool xapp::Alarm::Raise( int new_severity, int problem, const std::string& cinfo ) {
Set_severity( new_severity );
problem_id = problem;
info = cinfo;
Raise();
}
bool xapp::Alarm::Raise( int new_severity, int problem, const std::string& cinfo, const std::string& additional_info ) {
Set_severity( new_severity );
problem_id = problem;
info = cinfo;
this->add_info = additional_info;
Raise();
}
/*
Send a clear message with the contents of the alarm otherwise unchanged.
*/
bool xapp::Alarm::Clear( ) {
int used;
used = build_alarm( ACT_CLEAR, msg->Get_payload(), msg->Get_available_size() );
msg->Wormhole_send( whid, RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
}
/*
Additional prototypes allow for avoiding some setter calls when raising alarms.
Severity is one of our SEV_* constants. Problem is the caller's assigned
problem ID. Info and addional_info are user supplied data that is just passed
through.
*/
bool xapp::Alarm::Clear( int new_severity, int problem, const std::string& cinfo ) {
Set_severity( new_severity );
problem_id = problem;
info = cinfo;
Clear();
}
bool xapp::Alarm::Clear( int new_severity, int problem, const std::string& cinfo, const std::string& additional_info ) {
Set_severity( new_severity );
problem_id = problem;
info = cinfo;
this->add_info = additional_info;
Clear();
}
/*
Send a clear-all message. The contents of the alarm are unaffected.
*/
bool xapp::Alarm::Clear_all( ) {
int used;
used = build_alarm( ACT_CLEAR_ALL, msg->Get_payload(), msg->Get_available_size() );
msg->Wormhole_send( whid, RIC_ALARM, xapp::Message::NO_SUBID, used + 1, NULL );
}
/*
This is a convenience function which sends a clear message followed by a
raise message. Alarm contents are not adjusted.
*/
bool xapp::Alarm::Raise_again( ) {
Clear();
Raise();
}
} // namespace