Merge "Add new Link Monitor (lmond) daemon to Mtce"
This commit is contained in:
commit
6e7bbf6e35
@ -8,6 +8,7 @@ mtce-pmon
|
||||
mtce-rmon
|
||||
mtce-hwmon
|
||||
mtce-hostw
|
||||
mtce-lmon
|
||||
|
||||
# mtce-compute
|
||||
mtce-compute
|
||||
|
@ -27,6 +27,33 @@ static char rest_api_filename[MAX_FILENAME_LEN];
|
||||
static char rest_api_log_str [MAX_API_LOG_LEN];
|
||||
static libEvent nullEvent ;
|
||||
|
||||
#define HTTP_GET_STR "GET"
|
||||
#define HTTP_PUT_STR "PUT"
|
||||
#define HTTP_PATCH_STR "PATCH"
|
||||
#define HTTP_POST_STR "POST"
|
||||
#define HTTP_DELETE_STR "DELETE"
|
||||
#define HTTP_UNKNOWN_STR "UNKNOWN"
|
||||
|
||||
/* convert http event type to its string name */
|
||||
const char * getHttpCmdType_str ( evhttp_cmd_type type )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EVHTTP_REQ_GET: return(HTTP_GET_STR);
|
||||
case EVHTTP_REQ_PUT: return(HTTP_PUT_STR);
|
||||
case EVHTTP_REQ_PATCH: return(HTTP_PATCH_STR);
|
||||
case EVHTTP_REQ_POST: return(HTTP_POST_STR);
|
||||
case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
|
||||
case EVHTTP_REQ_HEAD:
|
||||
case EVHTTP_REQ_OPTIONS:
|
||||
case EVHTTP_REQ_TRACE:
|
||||
case EVHTTP_REQ_CONNECT:
|
||||
default:
|
||||
break ;
|
||||
}
|
||||
return(HTTP_UNKNOWN_STR);
|
||||
}
|
||||
|
||||
/* ***********************************************************************
|
||||
*
|
||||
* Name : httpUtil_event_init
|
||||
@ -1057,3 +1084,132 @@ void httpUtil_log_event ( libEvent * event_ptr )
|
||||
|
||||
send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), &rest_api_filename[0], &rest_api_log_str[0] );
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
*
|
||||
* Name : httpUtil_bind
|
||||
*
|
||||
* Description : Setup the HTTP server socket
|
||||
*
|
||||
*****************************************************************/
|
||||
int httpUtil_bind ( libEvent & event )
|
||||
{
|
||||
int one = 1;
|
||||
|
||||
event.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (event.fd < 0)
|
||||
{
|
||||
elog ("failed to create http server socket (%d:%m)\n", errno );
|
||||
return FAIL_SOCKET_CREATE ;
|
||||
}
|
||||
|
||||
/* make socket reusable */
|
||||
if ( 0 > setsockopt(event.fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int)))
|
||||
{
|
||||
elog ("failed to set http server socket to reusable (%d:%m)\n", errno );
|
||||
return FAIL_SOCKET_OPTION ;
|
||||
}
|
||||
|
||||
memset(&event.addr, 0, sizeof(struct sockaddr_in));
|
||||
event.addr.sin_family = AF_INET;
|
||||
|
||||
/* ERIK: INADDR_ANY; TODO: Refine this if we can */
|
||||
event.addr.sin_addr.s_addr = inet_addr(LOOPBACK_IP);
|
||||
// event.addr.sin_addr.s_addr = INADDR_ANY;
|
||||
event.addr.sin_port = htons(event.port);
|
||||
|
||||
/* bind port */
|
||||
if ( 0 > bind ( event.fd, (struct sockaddr*)&event.addr, sizeof(struct sockaddr_in)))
|
||||
{
|
||||
elog ("failed to bind to http server port %d (%d:%m)\n", event.port, errno );
|
||||
return FAIL_SOCKET_BIND ;
|
||||
}
|
||||
|
||||
/* Listen for events */
|
||||
if ( 0 > listen(event.fd, 10 ))
|
||||
{
|
||||
elog ("failed to listen to http server socket (%d:%m)\n", errno );
|
||||
return FAIL_SOCKET_LISTEN;
|
||||
}
|
||||
|
||||
/* make non-blocking */
|
||||
int flags = fcntl ( event.fd, F_GETFL, 0) ;
|
||||
if ( flags < 0 || fcntl(event.fd, F_SETFL, flags | O_NONBLOCK) < 0)
|
||||
{
|
||||
elog ("failed to set http server socket to non-blocking (%d:%m)\n", errno );
|
||||
return FAIL_SOCKET_OPTION;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/* Setup the http server */
|
||||
int httpUtil_setup ( libEvent & event,
|
||||
int supported_methods,
|
||||
void(*hdlr)(struct evhttp_request *, void *) )
|
||||
{
|
||||
int rc = PASS ;
|
||||
if ( ( rc = httpUtil_bind ( event )) != PASS )
|
||||
{
|
||||
return rc ;
|
||||
}
|
||||
else if (event.fd < 0)
|
||||
{
|
||||
wlog ("failed to get http server socket file descriptor\n");
|
||||
return RETRY ;
|
||||
}
|
||||
|
||||
event.base = event_base_new();
|
||||
if (event.base == NULL)
|
||||
{
|
||||
elog ("failed to get http server event base\n");
|
||||
return -1;
|
||||
}
|
||||
event.httpd = evhttp_new(event.base);
|
||||
if (event.httpd == NULL)
|
||||
{
|
||||
elog ("failed to get httpd server handle\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* api is a void return */
|
||||
evhttp_set_allowed_methods (event.httpd, supported_methods );
|
||||
|
||||
rc = evhttp_accept_socket(event.httpd, event.fd);
|
||||
if ( rc == -1)
|
||||
{
|
||||
elog ("failed to accept on http server socket\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* api is a void return */
|
||||
evhttp_set_gencb(event.httpd, hdlr, NULL);
|
||||
|
||||
ilog ("Listening On: 'http server' socket %s:%d\n",
|
||||
inet_ntoa(event.addr.sin_addr), event.port );
|
||||
return PASS ;
|
||||
}
|
||||
|
||||
void httpUtil_fini ( libEvent & event )
|
||||
{
|
||||
if ( event.fd )
|
||||
{
|
||||
if ( event.base )
|
||||
{
|
||||
event_base_free( event.base);
|
||||
}
|
||||
close ( event.fd );
|
||||
event.fd = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
void httpUtil_look ( libEvent & event )
|
||||
{
|
||||
/* Look for Events */
|
||||
if ( event.base )
|
||||
{
|
||||
// rc = event_base_loopexit( mtce_event.base, NULL ) ; // EVLOOP_NONBLOCK );
|
||||
event_base_loop(event.base, EVLOOP_NONBLOCK );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <evhttp.h> /* for ... http libevent client */
|
||||
#include <time.h>
|
||||
#include <list>
|
||||
#include <fcntl.h> /* for ... F_GETFL */
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -22,6 +23,7 @@ using namespace std;
|
||||
#define MTC_HTTP_BAD_REQUEST 400
|
||||
#define MTC_HTTP_UNAUTHORIZED 401
|
||||
#define MTC_HTTP_FORBIDDEN 403
|
||||
#define MTC_HTTP_METHOD_NOT_ALLOWED 405
|
||||
#define MTC_HTTP_CONFLICT 409
|
||||
#define MTC_HTTP_LENGTH_REQUIRED 411
|
||||
#define MTC_HTTP_NORESPONSE 444
|
||||
@ -194,6 +196,10 @@ struct libEvent
|
||||
struct evbuffer *buf ; /**< HTTP output buffer ptr */
|
||||
struct evbuffer_ptr evp ; /**< HTTP output buffer ptr */
|
||||
|
||||
int fd ;
|
||||
struct sockaddr_in addr ;
|
||||
struct evhttp *httpd ;
|
||||
|
||||
string log_prefix ; /**< log prefix for this event */
|
||||
|
||||
/** Service Specific Request Info */
|
||||
@ -339,5 +345,14 @@ void httpUtil_event_info ( libEvent & event );
|
||||
|
||||
const char * getHttpCmdType_str ( evhttp_cmd_type type );
|
||||
|
||||
/* HTTP Server setup utilities */
|
||||
int httpUtil_bind ( libEvent & event );
|
||||
|
||||
int httpUtil_setup ( libEvent & event,
|
||||
int supported_methods,
|
||||
void(*hdlr)(struct evhttp_request *, void *));
|
||||
/* Cleanup */
|
||||
void httpUtil_fini ( libEvent & event );
|
||||
void httpUtil_look ( libEvent & event );
|
||||
|
||||
#endif /* __INCLUDE_HTTPUTIL_H__ */
|
||||
|
@ -55,6 +55,7 @@ typedef struct
|
||||
int mtc_agent_port ; /**< mtcAgent receive port (from Client) */
|
||||
int mtc_client_port ; /**< mtcClient receive port (from Agent) */
|
||||
|
||||
char* uri_path ; /**< /mtce/lmon ... for link monitor */
|
||||
int keystone_port ; /**< Keystone REST API port number */
|
||||
char* keystone_prefix_path ; /**< Keystone REST API prefix path */
|
||||
char* keystone_auth_host ; /**< =auth_host=192.168.204.2 */
|
||||
@ -67,7 +68,6 @@ typedef struct
|
||||
char* keystone_user_domain; /**< = Default */
|
||||
char* keystone_project_domain; /**< = Default */
|
||||
char* keyring_directory ; /**< =/opt/platform/.keyring/<release> */
|
||||
|
||||
char* sysinv_mtc_inv_label ; /**< =/v1/hosts/ */
|
||||
int sysinv_api_port ; /**< =6385 */
|
||||
char* sysinv_api_bind_ip ; /**< =<local floating IP> */
|
||||
@ -114,8 +114,9 @@ typedef struct
|
||||
int event_port ; /**< daemon specific event tx port */
|
||||
int cmd_port ; /**< daemon specific command rx port */
|
||||
int sensor_port ; /**< sensor read value port */
|
||||
int sm_server_port ; /**< port mtce uses to receive data from SM */
|
||||
int sm_client_port ; /**< port mtce uses to send SM data */
|
||||
int sm_server_port ; /**< port mtce uses to receive data from SM */
|
||||
int sm_client_port ; /**< port mtce uses to send SM data */
|
||||
int lmon_query_port ;
|
||||
int start_delay ; /**< startup delay, added for pmon */
|
||||
int api_retries ; /**< api retries before failure */
|
||||
int hostwd_failure_threshold ; /**< allowed # of missed pmon/hostwd messages */
|
||||
|
@ -1489,33 +1489,6 @@ string get_event_str ( int event_code )
|
||||
}
|
||||
}
|
||||
|
||||
#define HTTP_GET_STR "GET"
|
||||
#define HTTP_PUT_STR "PUT"
|
||||
#define HTTP_PATCH_STR "PATCH"
|
||||
#define HTTP_POST_STR "POST"
|
||||
#define HTTP_DELETE_STR "DELETE"
|
||||
#define HTTP_UNKNOWN_STR "UNKNOWN"
|
||||
|
||||
/* Private: convert http event type to its string name */
|
||||
const char * getHttpCmdType_str ( evhttp_cmd_type type )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EVHTTP_REQ_GET: return(HTTP_GET_STR);
|
||||
case EVHTTP_REQ_PUT: return(HTTP_PUT_STR);
|
||||
case EVHTTP_REQ_PATCH: return(HTTP_PATCH_STR);
|
||||
case EVHTTP_REQ_POST: return(HTTP_POST_STR);
|
||||
case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
|
||||
case EVHTTP_REQ_HEAD:
|
||||
case EVHTTP_REQ_OPTIONS:
|
||||
case EVHTTP_REQ_TRACE:
|
||||
case EVHTTP_REQ_CONNECT:
|
||||
default:
|
||||
break ;
|
||||
}
|
||||
return(HTTP_UNKNOWN_STR);
|
||||
}
|
||||
|
||||
#define MAX_NUM_LEN 64
|
||||
string itos ( int val )
|
||||
{
|
||||
@ -1527,6 +1500,17 @@ string itos ( int val )
|
||||
return (temp);
|
||||
}
|
||||
|
||||
#define MAX_NUM_LEN 64
|
||||
string lltos (long long unsigned int val )
|
||||
{
|
||||
char int_str[MAX_NUM_LEN] ;
|
||||
string temp ;
|
||||
memset ( &int_str[0], 0, MAX_NUM_LEN );
|
||||
snprintf ( &int_str[0], MAX_NUM_LEN, "%llu" , val );
|
||||
temp = int_str ;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
string ftos ( float val, int resolution )
|
||||
{
|
||||
char float_str[MAX_NUM_LEN] ;
|
||||
|
@ -99,9 +99,9 @@ int get_link_state ( int ioctl_socket , const char * iface_ptr, bool * run
|
||||
int open_ioctl_socket ( void );
|
||||
|
||||
string get_event_str ( int event_code );
|
||||
const char * getHttpCmdType_str ( evhttp_cmd_type type );
|
||||
|
||||
string itos ( int val );
|
||||
string lltos (long long unsigned int val );
|
||||
string ftos ( float val, int resolution );
|
||||
unsigned short checksum(void *b, int len);
|
||||
|
||||
|
@ -34,6 +34,7 @@ void daemon_config_default ( daemon_config_type* config_ptr )
|
||||
config_ptr->mon_process_5 = strdup("none");
|
||||
config_ptr->mon_process_6 = strdup("none");
|
||||
config_ptr->mon_process_7 = strdup("none");
|
||||
config_ptr->uri_path = strdup("");
|
||||
config_ptr->keystone_prefix_path = strdup("");
|
||||
config_ptr->keystone_identity_uri = strdup("");
|
||||
config_ptr->keystone_auth_uri = strdup("");
|
||||
@ -295,6 +296,7 @@ void daemon_dump_cfg ( void )
|
||||
|
||||
/* mtcAgent & hwmond */
|
||||
if ( ptr->sysinv_api_port ) { ilog ("sysinv_api_port = %d\n", ptr->sysinv_api_port );}
|
||||
if ( ptr->uri_path ) { ilog ("uri_path = %s\n", ptr->uri_path );}
|
||||
if ( ptr->keystone_prefix_path ) { ilog ("keystone_prefix_path = %s\n", ptr->keystone_prefix_path );}
|
||||
if ( ptr->keystone_auth_host ) { ilog ("keystone_auth_host = %s\n", ptr->keystone_auth_host );}
|
||||
if ( ptr->keystone_identity_uri ) { ilog ("keystone_identity_uri = %s\n", ptr->keystone_identity_uri );}
|
||||
|
@ -1,3 +1,3 @@
|
||||
SRC_DIR="src"
|
||||
TIS_PATCH_VER=145
|
||||
TIS_PATCH_VER=146
|
||||
BUILD_IS_SLOW=5
|
||||
|
@ -178,7 +178,7 @@ Provides: librmonapi.so.1()(64bit)
|
||||
Titanium Cloud Host Maintenance Resource Monitor Service (rmond) adds
|
||||
threshold based monitoring with predictive severity level alarming for
|
||||
out of tolerance utilization of critical resourses such as memory, cpu
|
||||
file system, interface state, etc.
|
||||
file system, etc.
|
||||
|
||||
%package -n mtce-hwmon
|
||||
Summary: Titanuim Server Maintenance Hardware Monitor Package
|
||||
@ -266,6 +266,39 @@ of spec operating conditions that can reduce outage time through automated
|
||||
notification and recovery thereby improving overall platform availability
|
||||
for the customer.
|
||||
|
||||
%package -n mtce-lmon
|
||||
Summary: Titanuim Server Maintenance Link Monitor Package
|
||||
Group: base
|
||||
BuildRequires: cppcheck
|
||||
Requires: util-linux
|
||||
Requires: /bin/bash
|
||||
Requires: /bin/systemctl
|
||||
Requires: dpkg
|
||||
Requires: time
|
||||
Requires: libstdc++.so.6(CXXABI_1.3)(64bit)
|
||||
Requires: libfmcommon.so.1()(64bit)
|
||||
Requires: libc.so.6(GLIBC_2.7)(64bit)
|
||||
Requires: libc.so.6(GLIBC_2.2.5)(64bit)
|
||||
Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit)
|
||||
Requires: /bin/sh
|
||||
Requires: libc.so.6(GLIBC_2.3)(64bit)
|
||||
Requires: libc.so.6(GLIBC_2.14)(64bit)
|
||||
Requires: librt.so.1(GLIBC_2.3.3)(64bit)
|
||||
Requires: libgcc_s.so.1(GCC_3.0)(64bit)
|
||||
Requires: librt.so.1(GLIBC_2.2.5)(64bit)
|
||||
Requires: libm.so.6()(64bit)
|
||||
Requires: rtld(GNU_HASH)
|
||||
Requires: libstdc++.so.6()(64bit)
|
||||
Requires: libc.so.6(GLIBC_2.4)(64bit)
|
||||
Requires: libc.so.6()(64bit)
|
||||
Requires: libgcc_s.so.1()(64bit)
|
||||
Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit)
|
||||
Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)
|
||||
|
||||
%description -n mtce-lmon
|
||||
Titanium Cloud Maintenance Link Monitor service (lmond) provides
|
||||
netlink monitoring for provisioned oam, mgmt and infra interfaces.
|
||||
|
||||
%define local_dir /usr/local
|
||||
%define local_bindir %{local_dir}/bin
|
||||
%define local_sbindir %{local_dir}/sbin
|
||||
@ -321,6 +354,7 @@ install -m 644 -p -D %{_buildsubdir}/scripts/mtc.conf %{buildroot}%{_sysconfdir}
|
||||
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmond.conf %{buildroot}%{_sysconfdir}/mtc/fsmond.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmond.conf %{buildroot}%{_sysconfdir}/mtc/hwmond.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmond.conf %{buildroot}%{_sysconfdir}/mtc/pmond.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmond.conf %{buildroot}%{_sysconfdir}/mtc/lmond.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmond.conf %{buildroot}%{_sysconfdir}/mtc/rmond.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostwd.conf %{buildroot}%{_sysconfdir}/mtc/hostwd.conf
|
||||
|
||||
@ -335,6 +369,7 @@ install -m 755 -p -D %{_buildsubdir}/maintenance/mtcClient %{buildroot}/%{local_
|
||||
install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsAgent %{buildroot}/%{local_bindir}/hbsAgent
|
||||
install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsClient %{buildroot}/%{local_bindir}/hbsClient
|
||||
install -m 755 -p -D %{_buildsubdir}/pmon/pmond %{buildroot}/%{local_bindir}/pmond
|
||||
install -m 755 -p -D %{_buildsubdir}/lmon/lmond %{buildroot}/%{local_bindir}/lmond
|
||||
install -m 755 -p -D %{_buildsubdir}/hostw/hostwd %{buildroot}/%{local_bindir}/hostwd
|
||||
install -m 755 -p -D %{_buildsubdir}/rmon/rmond %{buildroot}/%{local_bindir}/rmond
|
||||
install -m 755 -p -D %{_buildsubdir}/fsmon/fsmond %{buildroot}/%{local_bindir}/fsmond
|
||||
@ -355,6 +390,7 @@ install -m 755 -p -D %{_buildsubdir}/hwmon/scripts/lsb/hwmon %{buildroot}%{_sysc
|
||||
install -m 755 -p -D %{_buildsubdir}/fsmon/scripts/fsmon %{buildroot}%{_sysconfdir}/init.d/fsmon
|
||||
install -m 755 -p -D %{_buildsubdir}/scripts/mtclog %{buildroot}%{_sysconfdir}/init.d/mtclog
|
||||
install -m 755 -p -D %{_buildsubdir}/pmon/scripts/pmon %{buildroot}%{_sysconfdir}/init.d/pmon
|
||||
install -m 755 -p -D %{_buildsubdir}/lmon/scripts/lmon %{buildroot}%{_sysconfdir}/init.d/lmon
|
||||
install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon %{buildroot}%{_sysconfdir}/init.d/rmon
|
||||
install -m 755 -p -D %{_buildsubdir}/hostw/scripts/hostw %{buildroot}%{_sysconfdir}/init.d/hostw
|
||||
install -m 755 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.init %{buildroot}%{_sysconfdir}/init.d/mtcalarm
|
||||
@ -377,6 +413,7 @@ install -m 644 -p -D %{_buildsubdir}/scripts/mtclog.service %{buildroot}%{_unitd
|
||||
install -m 644 -p -D %{_buildsubdir}/scripts/goenabled.service %{buildroot}%{_unitdir}/goenabled.service
|
||||
install -m 644 -p -D %{_buildsubdir}/scripts/runservices.service %{buildroot}%{_unitdir}/runservices.service
|
||||
install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.service %{buildroot}%{_unitdir}/mtcalarm.service
|
||||
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.service %{buildroot}%{_unitdir}/lmon.service
|
||||
|
||||
# go enabled stuff
|
||||
install -m 755 -d %{buildroot}%{local_etc_goenabledd}
|
||||
@ -407,18 +444,15 @@ install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.conf %{buildroot}%{local_
|
||||
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.conf %{buildroot}%{local_etc_pmond}/fsmon.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/scripts/mtclogd.conf %{buildroot}%{local_etc_pmond}/mtclogd.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.pmon.conf %{buildroot}%{local_etc_pmond}/mtcalarm.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.pmon.conf %{buildroot}%{local_etc_pmond}/lmon.conf
|
||||
|
||||
# resource monitor config files
|
||||
install -m 755 -d %{buildroot}%{local_etc_rmond}
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/rmonapi.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/rmonfiles.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/rmon_interfaces.d
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/remotelogging_resource.conf %{buildroot}%{local_etc_rmond}/remotelogging_resource.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/cinder_virtual_resource.conf %{buildroot}%{local_etc_rmond}/cinder_virtual_resource.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/nova_virtual_resource.conf %{buildroot}%{local_etc_rmond}/nova_virtual_resource.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/oam_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/management_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/infrastructure_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
|
||||
install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon_reload_on_cpe.sh %{buildroot}%{local_etc_goenabledd}/rmon_reload_on_cpe.sh
|
||||
|
||||
# log rotation
|
||||
@ -426,6 +460,7 @@ install -m 755 -d %{buildroot}%{_sysconfdir}/logrotate.d
|
||||
install -m 644 -p -D %{_buildsubdir}/scripts/mtce.logrotate %{buildroot}%{local_etc_logrotated}/mtce.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostw.logrotate %{buildroot}%{local_etc_logrotated}/hostw.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmon.logrotate %{buildroot}%{local_etc_logrotated}/pmon.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.logrotate %{buildroot}%{local_etc_logrotated}/lmon.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.logrotate %{buildroot}%{local_etc_logrotated}/rmon.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.logrotate %{buildroot}%{local_etc_logrotated}/fsmon.logrotate
|
||||
install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmon.logrotate %{buildroot}%{local_etc_logrotated}/hwmon.logrotate
|
||||
@ -466,6 +501,9 @@ install -m 755 -d %{buildroot}/var/run
|
||||
%post -n mtce-rmon
|
||||
/bin/systemctl enable rmon.service
|
||||
|
||||
%post -n mtce-lmon
|
||||
/bin/systemctl enable lmon.service
|
||||
|
||||
###############################
|
||||
# Maintenance RPM Files
|
||||
###############################
|
||||
@ -583,10 +621,6 @@ install -m 755 -d %{buildroot}/var/run
|
||||
%{local_etc_rmond}/cinder_virtual_resource.conf
|
||||
%{local_etc_rmond}/nova_virtual_resource.conf
|
||||
|
||||
%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
|
||||
%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
|
||||
%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
|
||||
|
||||
%{_libdir}/librmonapi.so.1.0
|
||||
%{_libdir}/librmonapi.so.1
|
||||
%{_libdir}/librmonapi.so
|
||||
@ -628,6 +662,21 @@ install -m 755 -d %{buildroot}/var/run
|
||||
%{_sysconfdir}/init.d/hostw
|
||||
%{local_bindir}/hostwd
|
||||
|
||||
###############################
|
||||
# Link Monitor RPM Files
|
||||
###############################
|
||||
%files -n mtce-lmon
|
||||
%defattr(-,root,root,-)
|
||||
|
||||
# Config files - Non-Modifiable
|
||||
%{_sysconfdir}/mtc/lmond.conf
|
||||
|
||||
%{_unitdir}/lmon.service
|
||||
%{local_etc_logrotated}/lmon.logrotate
|
||||
%{local_etc_pmond}/lmon.conf
|
||||
%{local_bindir}/lmond
|
||||
%{_sysconfdir}/init.d/lmon
|
||||
|
||||
###############################
|
||||
# Maintenance Software Development RPM
|
||||
###############################
|
||||
|
@ -16,6 +16,7 @@ build:
|
||||
(cd maintenance ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd hwmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd mtclog ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd lmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd pmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd fsmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
(cd rmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
|
||||
@ -30,6 +31,7 @@ clean:
|
||||
@( cd alarm ; make clean )
|
||||
@( cd mtclog ; make clean )
|
||||
@( cd hwmon ; make clean )
|
||||
@( cd lmon ; make clean )
|
||||
@( cd pmon ; make clean )
|
||||
@( cd fsmon ; make clean )
|
||||
@( cd heartbeat ; make clean )
|
||||
|
35
mtce/src/lmon/Makefile
Executable file
35
mtce/src/lmon/Makefile
Executable file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
SHELL = /bin/bash
|
||||
|
||||
SRCS = lmonInit.cpp lmonUtil.cpp lmonHdlr.cpp
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
LDLIBS = -lstdc++ -ldaemon -lcommon -ljson-c -lcrypto -lrt -levent
|
||||
LDPATH = -L../../../mtce-common/src/daemon -L../../../mtce-common/src/common
|
||||
INCLUDES = -I. -I/usr/include/mtce-daemon -I/usr/include/mtce-common
|
||||
CCFLAGS = -g -O2 -Wall -Wextra -Werror
|
||||
|
||||
STATIC_ANALYSIS_TOOL = cppcheck
|
||||
STATIC_ANALYSIS_TOOL_EXISTS = $(shell [[ -e `which $(STATIC_ANALYSIS_TOOL)` ]] && echo 1 || echo 0)
|
||||
|
||||
all: clean static_analysis build
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) $(INCLUDES) $(CCFLAGS) $(EXTRACCFLAGS) -c $< -o $@
|
||||
|
||||
static_analysis:
|
||||
ifeq ($(STATIC_ANALYSIS_TOOL_EXISTS), 1)
|
||||
$(STATIC_ANALYSIS_TOOL) --language=c++ --enable=warning -U__AREA__ *.cpp *.h
|
||||
else
|
||||
echo "Warning: '$(STATIC_ANALYSIS_TOOL)' static analysis tool not installed ; bypassing ..."
|
||||
endif
|
||||
|
||||
build: clean static_analysis $(OBJS)
|
||||
$(CXX) $(CCFLAGS) $(OBJS) $(LDPATH) $(LDLIBS) -o lmond
|
||||
|
||||
clean:
|
||||
@rm -v -f $(OBJ) lmond *.o *.a
|
119
mtce/src/lmon/lmon.h
Normal file
119
mtce/src/lmon/lmon.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include <net/if.h> /* for ... IF_NAMESIZE */
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "daemon_ini.h" /* for ... ini_parse */
|
||||
#include "daemon_common.h" /* for ... daemon common definitions and types */
|
||||
#include "nodeBase.h" /* for ... maintenance base definitions */
|
||||
#include "nodeTimers.h" /* for ... mtcTimer_init/start/stop utilities */
|
||||
#include "nodeUtil.h" /* for ... common utils like open_ioctl_socket */
|
||||
#include "httpUtil.h" /* for ... httputil_setup */
|
||||
#include "nlEvent.h" /* for ... open_netlink_socket */
|
||||
#include "fmAPI.h" /* for ... FMTimeT */
|
||||
|
||||
#ifdef __AREA__
|
||||
#undef __AREA__
|
||||
#endif
|
||||
#define __AREA__ "mon"
|
||||
|
||||
#define INTERFACES_DIR ((const char *)"/sys/class/net/")
|
||||
#define PLATFORM_DIR ((const char *)"/etc/platform/platform.conf")
|
||||
|
||||
#define INTERFACES_MAX (3) /* maximum number of interfaces to monitor */
|
||||
|
||||
enum interface_type { ethernet = 0, vlan = 1, bond = 2 };
|
||||
string iface_type ( interface_type type_enum );
|
||||
|
||||
/* daemon only supports the GET request */
|
||||
#define HTTP_SUPPORTED_METHODS (EVHTTP_REQ_GET)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ioctl_socket ;
|
||||
int netlink_socket ;
|
||||
libEvent http_event ;
|
||||
msgSock_type mtclogd ;
|
||||
int dos_log_throttle ;
|
||||
struct mtc_timer audit_timer ;
|
||||
|
||||
char my_hostname[MAX_HOST_NAME_SIZE+1];
|
||||
char my_address [MAX_CHARS_IN_IP_ADDR+1];
|
||||
|
||||
} lmon_ctrl_type ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char * name ; /* pointer to well known primary interface name */
|
||||
|
||||
/* primary interface names */
|
||||
#define MGMT_INTERFACE_NAME ((const char *)"mgmt")
|
||||
#define INFRA_INTERFACE_NAME ((const char *)"infra")
|
||||
#define OAM_INTERFACE_NAME ((const char *)"oam")
|
||||
|
||||
/* name labels used in platform.conf */
|
||||
#define MGMT_INTERFACE_FULLNAME ((const char *)"management_interface")
|
||||
#define INFRA_INTERFACE_FULLNAME ((const char *)"infrastructure_interface")
|
||||
#define OAM_INTERFACE_FULLNAME ((const char *)"oam_interface")
|
||||
|
||||
/* true if the interface is configured.
|
||||
* i.e. the name label shown above is found in platform.conf */
|
||||
bool used ;
|
||||
interface_type type_enum ;
|
||||
|
||||
/* true if the link is up ; false otherwise */
|
||||
bool interface_one_link_up ;
|
||||
bool interface_two_link_up ;
|
||||
|
||||
FMTimeT interface_one_event_time ;
|
||||
FMTimeT interface_two_event_time ;
|
||||
|
||||
/* Config Items */
|
||||
const char * severity ; /* MINOR, MAJOR or CRITICAL for each resource */
|
||||
unsigned int debounce ; /* Period to wait before clearing alarms */
|
||||
unsigned int num_tries ; /* Number of times a resource has to be in
|
||||
failed or cleared state before sending alarm */
|
||||
|
||||
/* Dynamic Data */
|
||||
char interface_one[IF_NAMESIZE] ; /* primary interface */
|
||||
char interface_two[IF_NAMESIZE] ; /* second interface if lagged */
|
||||
char bond[IF_NAMESIZE] ; /* bonded interface name */
|
||||
bool lagged ; /* Lagged interface=true or not=false */
|
||||
|
||||
// unsigned int debounce_cnt ; /* running monitor debounce count */
|
||||
// unsigned int minorlog_cnt ; /* track minor log count for thresholding */
|
||||
// unsigned int count ; /* track the number of times the condition has been occured */
|
||||
// bool failed ; /* track if the resource needs to be serviced by the resource handler */
|
||||
// int resource_value ; /* 1 if the interface is up and 0 if it is down */
|
||||
// int resource_value_lagged ; /* 1 if the interface is up and 0 if it is down for lagged interfaces */
|
||||
// int sev ; /* The severity of the failed resource */
|
||||
// rmonStage_enum stage ; /* The stage the resource is in within the resource handler fsm */
|
||||
// char alarm_id[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised */
|
||||
// char alarm_id_port[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised for the ports */
|
||||
// char errorMsg[ERR_SIZE];
|
||||
// rmon_api_socket_type msg;
|
||||
// bool link_up_and_running; /* whether the interface is up or down initially */
|
||||
|
||||
// bool alarm_raised;
|
||||
// int failed_send; /* The number of times the rmon api failed to send a message */
|
||||
|
||||
|
||||
} interface_ctrl_type ;
|
||||
|
||||
|
||||
/* lmonHdlr.cpp */
|
||||
void daemon_exit ( void );
|
||||
void lmon_learn_interfaces ( int ioctl_sock );
|
||||
|
||||
/* lmonUtils.cpp */
|
||||
FMTimeT lmon_fm_timestamp ( void );
|
||||
int lmon_interfaces_init ( interface_ctrl_type * ptr );
|
||||
int lmon_get_link_state ( int ioctl_socket,
|
||||
char iface[IF_NAMESIZE],
|
||||
bool & link_up );
|
769
mtce/src/lmon/lmonHdlr.cpp
Normal file
769
mtce/src/lmon/lmonHdlr.cpp
Normal file
@ -0,0 +1,769 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Starling-X Maintenance Link Monitor Service Header
|
||||
*/
|
||||
|
||||
#include "lmon.h"
|
||||
#include <linux/rtnetlink.h> /* for ... RTMGRP_LINK */
|
||||
#include "nodeMacro.h" /* for ... CREATE_REUSABLE_INET_UDP_TX_SOCKET */
|
||||
|
||||
#define HTTP_SERVER_NAME ((const char *)"link status query")
|
||||
|
||||
|
||||
static lmon_ctrl_type lmon_ctrl ;
|
||||
|
||||
static interface_ctrl_type interfaces[INTERFACES_MAX];
|
||||
|
||||
static const char * iface_list[INTERFACES_MAX] = { MGMT_INTERFACE_NAME,
|
||||
INFRA_INTERFACE_NAME,
|
||||
OAM_INTERFACE_NAME };
|
||||
|
||||
/* httpUtil needs a mtclog socket pointer */
|
||||
msgSock_type * get_mtclogd_sockPtr ( void )
|
||||
{
|
||||
return (&lmon_ctrl.mtclogd);
|
||||
}
|
||||
|
||||
/* dump state before exiting */
|
||||
void daemon_exit ( void )
|
||||
{
|
||||
daemon_files_fini ();
|
||||
daemon_dump_info ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/* daemon timer handler */
|
||||
void lmonTimer_handler ( int sig, siginfo_t *si, void *uc)
|
||||
{
|
||||
UNUSED(sig); UNUSED(uc);
|
||||
timer_t * tid_ptr = (void**)si->si_value.sival_ptr ;
|
||||
if ( !(*tid_ptr) )
|
||||
return ;
|
||||
else if (( *tid_ptr == lmon_ctrl.audit_timer.tid ) )
|
||||
lmon_ctrl.audit_timer.ring = true ;
|
||||
else
|
||||
mtcTimer_stop_tid_int_safe ( tid_ptr );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmonHdlr_http_handler
|
||||
*
|
||||
* Description: Handle HTTP Link Status Query requests.
|
||||
*
|
||||
* Method : GET
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#define DOS_LOG_THROTTLE_THLD (10000)
|
||||
void lmonHdlr_http_handler (struct evhttp_request *req, void *arg)
|
||||
{
|
||||
int http_status_code = HTTP_NOTFOUND ;
|
||||
|
||||
UNUSED(arg);
|
||||
|
||||
if ( ! req )
|
||||
return;
|
||||
|
||||
/* Get sender must be localhost */
|
||||
const char * host_ptr = evhttp_request_get_host (req);
|
||||
if (( host_ptr == NULL ) ||
|
||||
(( strncmp ( host_ptr , "localhost" , 10 ) != 0 ) &&
|
||||
( strncmp ( host_ptr , LOOPBACK_IP , 10 ) != 0 )))
|
||||
{
|
||||
wlog_throttled ( lmon_ctrl.dos_log_throttle,
|
||||
DOS_LOG_THROTTLE_THLD,
|
||||
"Message received from unknown host (%s)\n",
|
||||
host_ptr?host_ptr:"(null)" );
|
||||
return ;
|
||||
}
|
||||
|
||||
const char * uri_ptr = evhttp_request_get_uri (req);
|
||||
if ( uri_ptr == NULL )
|
||||
{
|
||||
wlog_throttled ( lmon_ctrl.dos_log_throttle,
|
||||
DOS_LOG_THROTTLE_THLD,
|
||||
"null uri");
|
||||
return ;
|
||||
}
|
||||
|
||||
string uri_path = daemon_get_cfg_ptr()->uri_path ;
|
||||
if (strncmp(uri_ptr, uri_path.data(), uri_path.length()))
|
||||
{
|
||||
wlog_throttled ( lmon_ctrl.dos_log_throttle,
|
||||
DOS_LOG_THROTTLE_THLD,
|
||||
"http request not for this service: %s",
|
||||
uri_ptr);
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Extract the operation */
|
||||
evhttp_cmd_type http_cmd = evhttp_request_get_command (req);
|
||||
jlog ("'%s' %s\n", uri_ptr, getHttpCmdType_str(http_cmd));
|
||||
switch ( http_cmd )
|
||||
{
|
||||
case EVHTTP_REQ_GET:
|
||||
{
|
||||
http_status_code = HTTP_OK ;
|
||||
break ;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ilog_throttled ( lmon_ctrl.dos_log_throttle,
|
||||
DOS_LOG_THROTTLE_THLD,
|
||||
"unsupported %s request (%d)",
|
||||
getHttpCmdType_str(http_cmd),
|
||||
http_cmd);
|
||||
|
||||
http_status_code = MTC_HTTP_METHOD_NOT_ALLOWED ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Link status query response format - success path
|
||||
*
|
||||
* Lagged case has an array of 2 links
|
||||
*
|
||||
|
||||
{ "status" : "pass",
|
||||
"link_info": [
|
||||
{ "network":"mgmt",
|
||||
"type":"vlan",
|
||||
"links": [
|
||||
{ "name":"enp0s8.1", "state":"Up/Down", "time":5674323454567 },
|
||||
{ "name":"enp0s8.2", "state":"Up/Down", "time":5674323454567 }]
|
||||
},
|
||||
{ "network":"infra",
|
||||
"type":"bond",
|
||||
"bond":"bond0",
|
||||
"links": [
|
||||
{ "name":"enp0s9f1", "state":"Up/Down", "time":5674323454567 },
|
||||
{ "name":"enp0s9f0", "state":"Up/Down", "time":5674323454567 }]
|
||||
},
|
||||
{ "network":"oam",
|
||||
"type":"ethernet",
|
||||
"links": [
|
||||
{ "name":"enp0s3", "state":"Up/Down", "time":5674323454567 }]
|
||||
}]
|
||||
}
|
||||
*
|
||||
*lmonHdlr.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
// #define WANT_TYPE_STR
|
||||
// #define WANT_BOND_STR
|
||||
|
||||
if (( http_status_code == HTTP_OK ) || ( http_status_code == MTC_HTTP_ACCEPTED ))
|
||||
{
|
||||
/* build response string */
|
||||
string response = "{ \"status\":\"pass\",\"link_info\":[" ;
|
||||
|
||||
/* loop over the interfaces and build a response string for each
|
||||
* of those that are used */
|
||||
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
|
||||
{
|
||||
if ((interfaces[i].used == true) && (interfaces[i].name[0] != '\0'))
|
||||
{
|
||||
if ( i > 0 )
|
||||
response.append (",");
|
||||
|
||||
response.append ("{\"network\":\"");
|
||||
response.append (interfaces[i].name);
|
||||
response.append ("\"");
|
||||
|
||||
#ifdef WANT_TYPE_STR
|
||||
string type_str = "ethernet" ;
|
||||
if ( interfaces[i].type_enum == bond )
|
||||
type_str = "bond" ;
|
||||
else if ( interfaces[i].type_enum == vlan )
|
||||
type_str = "vlan" ;
|
||||
response.append (",\"type\":\"" + type_str + "\"");
|
||||
#endif
|
||||
|
||||
#ifdef WANT_BOND_STR
|
||||
if ( interfaces[i].type_enum == bond )
|
||||
{
|
||||
response.append (",\"bond\":\"");
|
||||
response.append (interfaces[i].bond);
|
||||
response.append ("\"");
|
||||
}
|
||||
#endif
|
||||
|
||||
response.append (",\"links\":[");
|
||||
{
|
||||
response.append ("{\"name\":\"");
|
||||
response.append (interfaces[i].interface_one);
|
||||
response.append ("\",\"state\":\"");
|
||||
response.append (interfaces[i].interface_one_link_up?"Up":"Down");
|
||||
response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_one_event_time) + "\"}");
|
||||
}
|
||||
if (( interfaces[i].lagged ) &&
|
||||
( interfaces[i].interface_two[0] != '\0'))
|
||||
{
|
||||
response.append (",{\"name\":\"");
|
||||
response.append (interfaces[i].interface_two);
|
||||
response.append ("\",\"state\":\"");
|
||||
response.append (interfaces[i].interface_two_link_up?"Up":"Down");
|
||||
response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_two_event_time) + "\"}");
|
||||
}
|
||||
response.append ("]}");
|
||||
}
|
||||
}
|
||||
response.append ("]}");
|
||||
|
||||
struct evbuffer * resp_buf = evbuffer_new();
|
||||
jlog ("Resp: %s\n", response.c_str());
|
||||
evbuffer_add_printf (resp_buf, "%s\n", response.data());
|
||||
evhttp_send_reply (req, http_status_code, "OK", resp_buf );
|
||||
evbuffer_free ( resp_buf );
|
||||
}
|
||||
else if ( http_status_code == MTC_HTTP_METHOD_NOT_ALLOWED )
|
||||
{
|
||||
/* build response string */
|
||||
string response = "{" ;
|
||||
response.append (" \"status\" : \"fail ; method not allowed\"");
|
||||
response.append ("}");
|
||||
|
||||
struct evbuffer * resp_buf = evbuffer_new();
|
||||
jlog ("Event Response: %s\n", response.c_str());
|
||||
evbuffer_add_printf (resp_buf, "%s\n", response.data());
|
||||
|
||||
/* Add the 'Allow' header */
|
||||
int rc = evhttp_add_header( req->output_headers, "Allow", "GET" );
|
||||
if ( rc ) { ilog ("failed to add 'Allow' header (%d %d:%m", rc, errno);}
|
||||
evhttp_send_reply (req, http_status_code, "NOT ALLOWED", resp_buf );
|
||||
evbuffer_free ( resp_buf );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* build response string */
|
||||
string response = "{" ;
|
||||
response.append (" \"status\" : \"fail ; bad request\"");
|
||||
response.append ("}");
|
||||
elog ("HTTP Event error:%d ; cmd:%s uri:%s response:%s\n",
|
||||
http_status_code,
|
||||
getHttpCmdType_str(http_cmd),
|
||||
uri_ptr,
|
||||
response.c_str());
|
||||
evhttp_send_error (req, http_status_code, response.data() );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmon_socket_init
|
||||
*
|
||||
* Purpose : Initialize all the sockets for this process.
|
||||
*
|
||||
* Sockets include ...
|
||||
*
|
||||
* 1. local kernel ioctl socket ; link attribute query
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int lmon_socket_init ( lmon_ctrl_type * ctrl_ptr )
|
||||
{
|
||||
int rc = PASS ;
|
||||
if ( ctrl_ptr )
|
||||
{
|
||||
httpUtil_event_init ( &lmon_ctrl.http_event,
|
||||
&lmon_ctrl.my_hostname[0],
|
||||
HTTP_SERVER_NAME,
|
||||
lmon_ctrl.my_address,
|
||||
daemon_get_cfg_ptr()->lmon_query_port );
|
||||
|
||||
if (( ctrl_ptr->ioctl_socket = open_ioctl_socket()) <= 0 )
|
||||
{
|
||||
/* errno/strerror logged by open utility if failure is detected */
|
||||
elog ("failed to create ioctl socket\n");
|
||||
rc = FAIL_SOCKET_CREATE ;
|
||||
}
|
||||
|
||||
/* Note that address changes should not generate netlink events.
|
||||
* Therefore these options are not set
|
||||
* RTMGRP_IPV4_IFADDR
|
||||
* RTMGRP_IPV6_IFADDR
|
||||
*/
|
||||
else if (( ctrl_ptr->netlink_socket = open_netlink_socket ( RTMGRP_LINK )) <= 0 )
|
||||
{
|
||||
/* errno/strerr logged by open utility if failure is detected */
|
||||
elog ("failed to create netlink listener socket\n");
|
||||
rc = FAIL_SOCKET_CREATE ;
|
||||
}
|
||||
else if ( httpUtil_setup ( ctrl_ptr->http_event,
|
||||
HTTP_SUPPORTED_METHODS,
|
||||
&lmonHdlr_http_handler ) != PASS )
|
||||
{
|
||||
/* errno/strerr logged by open utility if failure is detected */
|
||||
elog ("failed to setup http server\n");
|
||||
rc = FAIL_SOCKET_CREATE ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctrl_ptr->mtclogd.port = daemon_get_cfg_ptr()->daemon_log_port ;
|
||||
CREATE_REUSABLE_INET_UDP_TX_SOCKET ( LOOPBACK_IP,
|
||||
ctrl_ptr->mtclogd.port,
|
||||
ctrl_ptr->mtclogd.sock,
|
||||
ctrl_ptr->mtclogd.addr,
|
||||
ctrl_ptr->mtclogd.port,
|
||||
ctrl_ptr->mtclogd.len,
|
||||
"mtc logger message",
|
||||
rc );
|
||||
if ( rc )
|
||||
{
|
||||
elog ("failed to setup mtce logger port %d\n", ctrl_ptr->mtclogd.port );
|
||||
rc = PASS ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = FAIL_NULL_POINTER ;
|
||||
}
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmon_learn_interfaces
|
||||
*
|
||||
* Purpose : realize the interfaces to monitor in terms of
|
||||
*
|
||||
* - interface type ; ethernet, bonded or vlan
|
||||
* - initial up/down state
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void lmon_learn_interfaces ( int ioctl_socket )
|
||||
{
|
||||
/* initialize interface monitoring */
|
||||
for ( int iface = 0 ; iface < INTERFACES_MAX ; iface++ )
|
||||
{
|
||||
interfaces[iface].name = iface_list[iface];
|
||||
lmon_interfaces_init ( &interfaces[iface] );
|
||||
|
||||
if ( interfaces[iface].used == false )
|
||||
continue ;
|
||||
|
||||
/* set the link state for all the primary physical interfaces */
|
||||
if ( lmon_get_link_state ( ioctl_socket,
|
||||
interfaces[iface].interface_one,
|
||||
interfaces[iface].interface_one_link_up ) )
|
||||
{
|
||||
interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
|
||||
interfaces[iface].interface_one_link_up = false ;
|
||||
wlog ("%s interface state query failed ; defaulting to Down\n",
|
||||
interfaces[iface].interface_one) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
|
||||
ilog ("%s is %s\n",
|
||||
interfaces[iface].interface_one,
|
||||
interfaces[iface].interface_one_link_up ?
|
||||
"Up" : "Down" );
|
||||
|
||||
if ( interfaces[iface].lagged == true )
|
||||
{
|
||||
/* set the link state for all the lagged physical interfaces */
|
||||
if ( lmon_get_link_state ( ioctl_socket,
|
||||
interfaces[iface].interface_two,
|
||||
interfaces[iface].interface_two_link_up ) )
|
||||
{
|
||||
interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
|
||||
interfaces[iface].interface_two_link_up = false ;
|
||||
wlog ("%s lag interface state query failed ; defaulting to Down\n",
|
||||
interfaces[iface].interface_two) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
|
||||
ilog ("%s is %s (lag)\n",
|
||||
interfaces[iface].interface_two,
|
||||
interfaces[iface].interface_two_link_up ?
|
||||
"Up" : "Down" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : service_interface_events
|
||||
*
|
||||
* Purpose : Service state changes for monitored link
|
||||
*
|
||||
* Description: netlink event driven state change handler.
|
||||
*
|
||||
*****************************************************************************/
|
||||
int service_interface_events ( void )
|
||||
{
|
||||
list<string> links_gone_down ;
|
||||
list<string> links_gone_up ;
|
||||
list<string>::iterator iter_ptr ;
|
||||
|
||||
links_gone_down.clear();
|
||||
links_gone_up.clear();
|
||||
|
||||
int events = get_netlink_events ( lmon_ctrl.netlink_socket,
|
||||
links_gone_down,
|
||||
links_gone_up );
|
||||
if ( events <= 0 )
|
||||
{
|
||||
dlog1 ("called but get_netlink_events reported no events");
|
||||
return RETRY ;
|
||||
}
|
||||
|
||||
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
|
||||
{
|
||||
if ( interfaces[i].used == true )
|
||||
{
|
||||
bool running = false ;
|
||||
|
||||
/* handle links that went down */
|
||||
if ( ! links_gone_down.empty() )
|
||||
{
|
||||
bool found = false ;
|
||||
dlog ("netlink Down events: %ld", links_gone_down.size());
|
||||
/* Look at the down list */
|
||||
for ( iter_ptr = links_gone_down.begin();
|
||||
iter_ptr != links_gone_down.end() ;
|
||||
iter_ptr++ )
|
||||
{
|
||||
if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
|
||||
|
||||
dlog ("%s is Down ; netlink event\n",
|
||||
interfaces[i].interface_one );
|
||||
|
||||
if ( get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
iter_ptr->c_str(),
|
||||
&running ) == PASS )
|
||||
{
|
||||
if ( interfaces[i].interface_one_link_up == true )
|
||||
{
|
||||
wlog ("%s is Down ; (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog ("%s is Down ; (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
interfaces[i].interface_one_link_up = running ? true:false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog ("%s is Down ; oper query failed\n",
|
||||
iter_ptr->c_str());
|
||||
interfaces[i].interface_one_link_up = false ;
|
||||
}
|
||||
}
|
||||
|
||||
else if (interfaces[i].lagged == true)
|
||||
{
|
||||
if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
|
||||
|
||||
dlog ("%s is Down\n", interfaces[i].interface_two);
|
||||
|
||||
if ( get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
iter_ptr->c_str(),
|
||||
&running ) == PASS )
|
||||
{
|
||||
if ( interfaces[i].interface_two_link_up == true )
|
||||
{
|
||||
wlog ("%s is Down (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog ("%s is Down (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
interfaces[i].interface_two_link_up = running ? true:false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog ("%s is Down ; oper query failed\n",
|
||||
iter_ptr->c_str() );
|
||||
interfaces[i].interface_two_link_up = false ;
|
||||
}
|
||||
}
|
||||
if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
wlog ("%s is Down (bond)\n", interfaces[i].bond);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! found )
|
||||
{
|
||||
dlog ("netlink Down event on unmonitored link:%s", iter_ptr->c_str());
|
||||
}
|
||||
}
|
||||
/* handle links that came up */
|
||||
if ( !links_gone_up.empty() )
|
||||
{
|
||||
bool found = false ;
|
||||
dlog ("netlink Up events: %ld", links_gone_up.size());
|
||||
/* Look at the down list */
|
||||
for ( iter_ptr = links_gone_up.begin();
|
||||
iter_ptr != links_gone_up.end() ;
|
||||
iter_ptr++ )
|
||||
{
|
||||
if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
|
||||
|
||||
dlog ("%s is Up\n", interfaces[i].interface_one );
|
||||
|
||||
if ( get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
iter_ptr->c_str(),
|
||||
&running ) == PASS )
|
||||
{
|
||||
if ( interfaces[i].interface_one_link_up == false )
|
||||
{
|
||||
ilog ("%s is Up (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog ("%s is Up (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
interfaces[i].interface_one_link_up = running ? true:false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
|
||||
interfaces[i].interface_one_link_up = false ;
|
||||
}
|
||||
}
|
||||
else if (interfaces[i].lagged == true)
|
||||
{
|
||||
if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
|
||||
dlog ("%s is Up\n", interfaces[i].interface_two );
|
||||
|
||||
if ( get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
iter_ptr->c_str(),
|
||||
&running ) == PASS )
|
||||
{
|
||||
if ( interfaces[i].interface_two_link_up == false )
|
||||
{
|
||||
ilog ("%s is Up (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
else
|
||||
{
|
||||
dlog ("%s is Up (%s)\n",
|
||||
iter_ptr->c_str(),
|
||||
running ? "Up" : "Down" );
|
||||
}
|
||||
interfaces[i].interface_two_link_up = running ? true:false;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
|
||||
interfaces[i].interface_two_link_up = false ;
|
||||
}
|
||||
}
|
||||
if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
|
||||
{
|
||||
found = true ;
|
||||
wlog ("%s is Up (bond)\n", interfaces[i].bond);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! found )
|
||||
{
|
||||
dlog ("netlink Up event on unmonitored link:%s", iter_ptr->c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (PASS);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Name : lmon_query_all_links
|
||||
*
|
||||
* Purpose : self correct for netlink event misses by running this
|
||||
* as a periodic audit at a 1 minute cadence.
|
||||
*
|
||||
**************************************************************************/
|
||||
void lmon_query_all_links( void )
|
||||
{
|
||||
dlog1 ("audit timer fired");
|
||||
|
||||
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
|
||||
{
|
||||
if ( interfaces[i].used )
|
||||
{
|
||||
bool link_up = false ;
|
||||
string log_msg = "link state mismatch detected by audit";
|
||||
if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
interfaces[i].interface_one,
|
||||
link_up) == PASS )
|
||||
{
|
||||
if ( link_up != interfaces[i].interface_one_link_up )
|
||||
{
|
||||
wlog ("%s %s ; is:%s was:%s ; corrected",
|
||||
interfaces[i].interface_one,
|
||||
log_msg.c_str(),
|
||||
link_up?"Up":"Down",
|
||||
interfaces[i].interface_one_link_up?"Up":"Down" );
|
||||
|
||||
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
|
||||
interfaces[i].interface_one_link_up = link_up ;
|
||||
}
|
||||
}
|
||||
if ( interfaces[i].lagged )
|
||||
{
|
||||
if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
|
||||
interfaces[i].interface_two,
|
||||
link_up) == PASS )
|
||||
{
|
||||
if ( link_up != interfaces[i].interface_two_link_up )
|
||||
{
|
||||
wlog ("%s %s ; is:%s was:%s ; corrected",
|
||||
interfaces[i].interface_two,
|
||||
log_msg.c_str(),
|
||||
link_up?"Up":"Down",
|
||||
interfaces[i].interface_two_link_up?"Up":"Down" );
|
||||
|
||||
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
|
||||
interfaces[i].interface_two_link_up = link_up ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : daemon_service_run
|
||||
*
|
||||
* Purpose : track interface profile link status.
|
||||
*
|
||||
* Assumptions: Event driven with self-correcting audit.
|
||||
*
|
||||
* General Behavior:
|
||||
*
|
||||
* Init:
|
||||
*
|
||||
* 1. learn interface/port model
|
||||
* 2. setup http server
|
||||
*
|
||||
* Select:
|
||||
*
|
||||
* 3. load initial link status for learned links
|
||||
* 4. listen for link status change events
|
||||
* 5. provide link status info to http GET Query requests.
|
||||
*
|
||||
* Audit:
|
||||
*
|
||||
* 6. run 1 minute periodic self correcting audit.
|
||||
*
|
||||
*/
|
||||
|
||||
void daemon_service_run ( void )
|
||||
{
|
||||
fd_set readfds;
|
||||
struct timeval waitd;
|
||||
std::list<int> socks;
|
||||
|
||||
lmon_ctrl.ioctl_socket = 0 ;
|
||||
lmon_ctrl.netlink_socket = 0 ;
|
||||
memset (&lmon_ctrl.mtclogd, 0, sizeof(lmon_ctrl.mtclogd));
|
||||
memset (&interfaces, 0, sizeof(interface_ctrl_type));
|
||||
|
||||
get_hostname (&lmon_ctrl.my_hostname[0], MAX_HOST_NAME_SIZE );
|
||||
mtcTimer_init ( lmon_ctrl.audit_timer, lmon_ctrl.my_hostname, "audit");
|
||||
|
||||
string my_address = lmon_ctrl.my_address ;
|
||||
get_iface_address ( daemon_mgmnt_iface().data(), my_address, true );
|
||||
|
||||
/* Setup the messaging sockets */
|
||||
if (( lmon_socket_init ( &lmon_ctrl )) != PASS )
|
||||
{
|
||||
elog ("socket initialization failed ; exiting ...\n");
|
||||
daemon_exit ();
|
||||
}
|
||||
else if ( 0 >= lmon_ctrl.netlink_socket )
|
||||
{
|
||||
elog ("failed to get ioctl socket descriptor (%d) ; exiting ...\n",
|
||||
lmon_ctrl.netlink_socket );
|
||||
daemon_exit ();
|
||||
}
|
||||
|
||||
lmon_learn_interfaces ( lmon_ctrl.ioctl_socket );
|
||||
|
||||
int audit_secs = daemon_get_cfg_ptr()->audit_period ;
|
||||
ilog ("started %d second link state self correcting audit", audit_secs );
|
||||
mtcTimer_start ( lmon_ctrl.audit_timer, lmonTimer_handler, audit_secs );
|
||||
|
||||
socks.clear();
|
||||
socks.push_front (lmon_ctrl.netlink_socket);
|
||||
socks.sort();
|
||||
|
||||
ilog ("waiting on netlink events ...");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Accomodate for hup reconfig */
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(lmon_ctrl.netlink_socket, &readfds);
|
||||
waitd.tv_sec = 0;
|
||||
waitd.tv_usec = SOCKET_WAIT ;
|
||||
|
||||
/* This is used as a delay up to select timeout ; SOCKET_WAIT */
|
||||
select( socks.back()+1, &readfds, NULL, NULL, &waitd);
|
||||
if (FD_ISSET(lmon_ctrl.netlink_socket, &readfds))
|
||||
{
|
||||
dlog ("netlink socket fired\n");
|
||||
service_interface_events ();
|
||||
}
|
||||
|
||||
if ( lmon_ctrl.audit_timer.ring == true )
|
||||
{
|
||||
lmon_ctrl.audit_timer.ring = false ;
|
||||
lmon_query_all_links();
|
||||
}
|
||||
|
||||
httpUtil_look ( lmon_ctrl.http_event );
|
||||
daemon_signal_hdlr();
|
||||
}
|
||||
daemon_exit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
145
mtce/src/lmon/lmonInit.cpp
Normal file
145
mtce/src/lmon/lmonInit.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Starling-X Maintenance Link Monitor Initialization
|
||||
*/
|
||||
|
||||
#include "lmon.h"
|
||||
|
||||
/** Daemon Configuration Structure - Allocation and get pointer
|
||||
* @see daemon_common.h for daemon_config_type struct format. */
|
||||
static daemon_config_type lmon_config ;
|
||||
daemon_config_type * daemon_get_cfg_ptr () { return &lmon_config ; }
|
||||
|
||||
/* read config label values */
|
||||
static int lmon_config_handler ( void * user,
|
||||
const char * section,
|
||||
const char * name,
|
||||
const char * value)
|
||||
{
|
||||
daemon_config_type* config_ptr = (daemon_config_type*)user;
|
||||
|
||||
if (MATCH("client", "audit_period"))
|
||||
{
|
||||
config_ptr->audit_period = atoi(value);
|
||||
ilog ("Audit Period: %d (secs)", config_ptr->audit_period );
|
||||
}
|
||||
else if (MATCH("client", "lmon_query_port"))
|
||||
{
|
||||
config_ptr->lmon_query_port = atoi(value);
|
||||
ilog ("Status Query: %d (port)", config_ptr->lmon_query_port );
|
||||
}
|
||||
else if (MATCH("client", "daemon_log_port"))
|
||||
{
|
||||
config_ptr->daemon_log_port = atoi(value);
|
||||
ilog ("Daemon Log : %d (port)", config_ptr->daemon_log_port );
|
||||
}
|
||||
else if (MATCH("client", "uri_path"))
|
||||
{
|
||||
config_ptr->uri_path = strdup(value);
|
||||
}
|
||||
|
||||
return (PASS);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : daemon_configure
|
||||
*
|
||||
* Purpose : Read process config file settings into the daemon configuration
|
||||
*
|
||||
* Configuration File */
|
||||
|
||||
#define CONFIG_FILE ((const char *)"/etc/mtc/lmond.conf")
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int daemon_configure ( void )
|
||||
{
|
||||
int rc = PASS ;
|
||||
|
||||
/* read config out of /etc/mtc/lmond.conf */
|
||||
if (ini_parse( CONFIG_FILE, lmon_config_handler, &lmon_config) < 0)
|
||||
{
|
||||
elog("Can't load '%s'\n", CONFIG_FILE );
|
||||
rc = FAIL_INI_CONFIG ;
|
||||
}
|
||||
else
|
||||
{
|
||||
get_debug_options ( CONFIG_FILE, &lmon_config );
|
||||
}
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : daemon_init
|
||||
*
|
||||
* Purpose : Daemon Initialization
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int daemon_init ( string iface, string nodetype_str )
|
||||
{
|
||||
int rc = PASS ;
|
||||
|
||||
UNUSED(iface);
|
||||
UNUSED(nodetype_str);
|
||||
|
||||
if ( daemon_files_init ( ) != PASS )
|
||||
{
|
||||
elog ("Pid, log or other files could not be opened\n");
|
||||
return ( FAIL_FILES_INIT ) ;
|
||||
}
|
||||
|
||||
/* Bind signal handlers */
|
||||
if ( daemon_signal_init () != PASS )
|
||||
{
|
||||
elog ("daemon_signal_init failed\n");
|
||||
return ( FAIL_SIGNAL_INIT );
|
||||
}
|
||||
|
||||
daemon_wait_for_file ( CONFIG_COMPLETE_FILE, 0);
|
||||
daemon_wait_for_file ( PLATFORM_DIR, 0);
|
||||
daemon_wait_for_file ( GOENABLED_MAIN_READY, 0);
|
||||
|
||||
/* Configure the daemon */
|
||||
if ( (rc = daemon_configure ( )) != PASS )
|
||||
{
|
||||
elog ("Daemon service configuration failed (rc:%i)\n", rc );
|
||||
rc = FAIL_DAEMON_CONFIG ;
|
||||
}
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
|
||||
void daemon_dump_info ( void )
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void daemon_sigchld_hdlr ( void )
|
||||
{
|
||||
; /* dlog("Received SIGCHLD ... no action\n"); */
|
||||
}
|
||||
|
||||
const char MY_DATA [100] = { "eieio\n" } ;
|
||||
const char * daemon_stream_info ( void )
|
||||
{
|
||||
return (&MY_DATA[0]);
|
||||
}
|
||||
|
||||
/** Teat Head Entry */
|
||||
int daemon_run_testhead ( void )
|
||||
{
|
||||
// ilog ("Empty test head.\n");
|
||||
return (PASS);
|
||||
}
|
415
mtce/src/lmon/lmonUtil.cpp
Normal file
415
mtce/src/lmon/lmonUtil.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Starling-X Maintenance Link Monitor Utility
|
||||
*/
|
||||
|
||||
#include "lmon.h"
|
||||
#include <fstream> /* for ... ifstream */
|
||||
#include <sstream> /* for ... stringstream */
|
||||
#include <net/if.h> /* for ... if_indextoname , IF_NAMESIZE */
|
||||
#include <sys/ioctl.h> /* for ... SIOCGIFFLAGS */
|
||||
#include "nlEvent.h" /* for ... get_netlink_events */
|
||||
|
||||
#ifdef __AREA__
|
||||
#undef __AREA__
|
||||
#endif
|
||||
#define __AREA__ "mon"
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : iface_type
|
||||
*
|
||||
* Purpose : convert interface type enum to representative string.
|
||||
*
|
||||
* Returns : 0:ethernet returns "ethernet"
|
||||
* 1:vlan returns "vlan"
|
||||
* 2:bond returns "bond"
|
||||
* ? returns "unknown" ... error case
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
string iface_type ( interface_type type_enum )
|
||||
{
|
||||
switch(type_enum)
|
||||
{
|
||||
case ethernet: return "ethernet";
|
||||
case vlan: return "vlan" ;
|
||||
case bond: return "bond" ;
|
||||
default: return "unknown" ;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : get_iflink_interface
|
||||
*
|
||||
* Purpose : Gets the ifname of the linked parent interface
|
||||
*
|
||||
* Returns : Returns a string containing the ifname.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
string get_iflink_interface (string & ifname )
|
||||
{
|
||||
string ret = "";
|
||||
|
||||
/* build the full file path */
|
||||
string iflink_file = INTERFACES_DIR + ifname + "/iflink";
|
||||
|
||||
/* declare a file stream based on the full file path */
|
||||
ifstream iflink_file_stream ( iflink_file.c_str() );
|
||||
|
||||
/* open the file stream */
|
||||
if (iflink_file_stream.is_open())
|
||||
{
|
||||
int iflink = -1;
|
||||
string iflink_line;
|
||||
char * dummy_ptr ;
|
||||
char iface_buffer [IF_NAMESIZE] = "";
|
||||
memset (&iface_buffer[0], 0, IF_NAMESIZE);
|
||||
while ( getline (iflink_file_stream, iflink_line) )
|
||||
{
|
||||
iflink = strtol(iflink_line.c_str(), &dummy_ptr, 10);
|
||||
}
|
||||
iflink_file_stream.close();
|
||||
|
||||
/*
|
||||
* load iface_buffer with the name of the network interface
|
||||
* corresponding to iflink.
|
||||
*/
|
||||
if_indextoname (iflink, iface_buffer);
|
||||
|
||||
if (iface_buffer[0] != '\0')
|
||||
{
|
||||
ret = iface_buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
slog ("no ifname from linked parent interface\n");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmon_fm_timestamp
|
||||
*
|
||||
* Purpose : Get a microsecond timestamp of the current time.
|
||||
*
|
||||
* Description: Used to record the time of link state changes.
|
||||
*
|
||||
* The value is included in link state query responses.
|
||||
*
|
||||
* Uses : FMTimeT from fmAPI.h
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FMTimeT lmon_fm_timestamp ( void )
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
return ( ts.tv_sec*1000000 + ts.tv_nsec/1000 );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmon_get_link_state
|
||||
*
|
||||
* Purpose : Query the link up/down state of the specified interface.
|
||||
*
|
||||
* Updates : Sets the callers boolean pointer to ...
|
||||
*
|
||||
* true if interface is up
|
||||
* false if interface is doewn
|
||||
*
|
||||
* Returns : PASS on query success.
|
||||
* FAIL_OPERATION if the query was not successful.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int get_link_state_throttle = 0 ;
|
||||
#define GET_LINK_STATE__LOG_THROTTLE (100)
|
||||
|
||||
int lmon_get_link_state ( int ioctl_socket,
|
||||
char iface[IF_NAMESIZE],
|
||||
bool & link_up )
|
||||
{
|
||||
int rc = FAIL_OPERATION ;
|
||||
|
||||
link_up = false ; /* default to link down */
|
||||
|
||||
if (iface[0] == '\0')
|
||||
{
|
||||
slog ("supplied interface name is invalid ; null\n");
|
||||
return ( rc ) ;
|
||||
}
|
||||
|
||||
/* Declare and load interface data for ioctl query */
|
||||
struct ifreq if_data;
|
||||
memset( &if_data, 0, sizeof(if_data) );
|
||||
snprintf( if_data.ifr_name, IF_NAMESIZE, "%s", iface );
|
||||
|
||||
/* read the interface up/down state */
|
||||
if( 0 <= ioctl( ioctl_socket, SIOCGIFFLAGS, &if_data ) )
|
||||
{
|
||||
if( if_data.ifr_flags & IFF_RUNNING )
|
||||
link_up = true;
|
||||
|
||||
/* reset log flood gate counter */
|
||||
get_link_state_throttle = 0 ;
|
||||
|
||||
rc = PASS ;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog_throttled (get_link_state_throttle,
|
||||
GET_LINK_STATE__LOG_THROTTLE,
|
||||
"failed to get %s (%s) interface state (%d:%s)\n",
|
||||
iface,
|
||||
if_data.ifr_name,
|
||||
errno,
|
||||
strerror(errno));
|
||||
}
|
||||
return ( rc );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Name : lmon_interfaces_init
|
||||
*
|
||||
* Purpose : Map an interface (mgmt, oam or infra) to a physical port.
|
||||
* See interface_type enum in lmon.h
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int lmon_interfaces_init ( interface_ctrl_type * ptr )
|
||||
{
|
||||
FILE * file_ptr;
|
||||
char line_buf[MAX_CHARS_ON_LINE];
|
||||
string str;
|
||||
string physical_interface = "";
|
||||
|
||||
/* iface enum to pltform.conf iface name */
|
||||
if ( strcmp(ptr->name, MGMT_INTERFACE_NAME) == 0 )
|
||||
str = MGMT_INTERFACE_FULLNAME;
|
||||
else if ( strcmp(ptr->name, INFRA_INTERFACE_NAME) == 0 )
|
||||
str = INFRA_INTERFACE_FULLNAME;
|
||||
else if ( strcmp(ptr->name, OAM_INTERFACE_NAME) == 0 )
|
||||
str = OAM_INTERFACE_FULLNAME;
|
||||
else
|
||||
{
|
||||
slog ("%s is an unsupported iface\n", ptr->name );
|
||||
return (FAIL_BAD_PARM);
|
||||
}
|
||||
|
||||
/* open platform.conf and find the line containing this interface name. */
|
||||
file_ptr = fopen (PLATFORM_DIR , "r");
|
||||
if (file_ptr)
|
||||
{
|
||||
ifstream fin( PLATFORM_DIR );
|
||||
string line;
|
||||
|
||||
while ( getline( fin, line ))
|
||||
{
|
||||
/* does this line contain it ? */
|
||||
if ( line.find(str) != string::npos )
|
||||
{
|
||||
stringstream ss( line );
|
||||
getline( ss, physical_interface, '=' ); // string before
|
||||
getline( ss, physical_interface, '=' ); // string after
|
||||
|
||||
plog ("%s is the %s primary network interface",
|
||||
physical_interface.c_str(),
|
||||
ptr->name);
|
||||
|
||||
/* determine the interface type */
|
||||
string uevent_interface_file =
|
||||
INTERFACES_DIR + physical_interface + "/uevent";
|
||||
ifstream finUevent( uevent_interface_file.data() );
|
||||
|
||||
if (!finUevent)
|
||||
{
|
||||
elog ("Cannot find '%s' ; unable to monitor '%s' interface\n",
|
||||
uevent_interface_file.c_str(), ptr->name );
|
||||
|
||||
ptr->used = false;
|
||||
fclose(file_ptr);
|
||||
return FAIL_OPERATION ;
|
||||
}
|
||||
else
|
||||
{
|
||||
string line;
|
||||
ptr->type_enum = ethernet;
|
||||
while( getline( finUevent, line ) )
|
||||
{
|
||||
if ( line.find ("DEVTYPE") == 0 )
|
||||
{
|
||||
if ( line.find ("=vlan") != string::npos )
|
||||
ptr->type_enum = vlan;
|
||||
else if ( line.find ("=bond") != string::npos )
|
||||
ptr->type_enum = bond;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (ptr->type_enum)
|
||||
{
|
||||
case ethernet:
|
||||
{
|
||||
memcpy(ptr->interface_one,
|
||||
physical_interface.c_str(),
|
||||
physical_interface.size());
|
||||
|
||||
ilog("%s is a %s ethernet interface\n",
|
||||
ptr->interface_one, ptr->name );
|
||||
|
||||
break;
|
||||
}
|
||||
case bond:
|
||||
{
|
||||
memcpy(ptr->bond,
|
||||
physical_interface.c_str(),
|
||||
physical_interface.size());
|
||||
|
||||
ilog("%s is a bonded %s network interface\n",
|
||||
ptr->bond, ptr->name);
|
||||
|
||||
break;
|
||||
}
|
||||
case vlan:
|
||||
{
|
||||
/****************************************************
|
||||
*
|
||||
* If it is a VLAN interface, we need to determine its
|
||||
* parent interface, which may be a single ethernet
|
||||
* link or a bonded interface.
|
||||
*
|
||||
****************************************************/
|
||||
|
||||
string parent = get_iflink_interface(physical_interface);
|
||||
if (!parent.empty())
|
||||
{
|
||||
string physical_interface_save = physical_interface ;
|
||||
physical_interface = parent;
|
||||
|
||||
string uevent_parent_file =
|
||||
INTERFACES_DIR + parent + "/uevent";
|
||||
|
||||
ifstream finUevent2( uevent_parent_file.c_str() );
|
||||
|
||||
string line;
|
||||
bool bond_configured = false;
|
||||
while( getline( finUevent2, line ) )
|
||||
{
|
||||
// if this uevent does not have a DEVTYPE
|
||||
// then its a ethernet interface. If this
|
||||
// does have a DEVTYPE then check explicity
|
||||
// for bond. Since we don't allow vlan over
|
||||
// vlan, for all other DEVTYPEs, assume
|
||||
// this is a ethernet interface.
|
||||
if ( (line.find ("DEVTYPE") == 0) &&
|
||||
(line.find ("=bond") != string::npos) ) {
|
||||
|
||||
ilog("%s is a vlan off the %s network whose parent is %s\n",
|
||||
physical_interface_save.c_str(),
|
||||
ptr->name,
|
||||
parent.c_str());
|
||||
bond_configured = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bond_configured)
|
||||
{
|
||||
ilog("%s is a vlan off the %s network whose parent is %s\n",
|
||||
physical_interface.c_str(),
|
||||
ptr->name,
|
||||
parent.c_str());
|
||||
|
||||
memcpy(ptr->interface_one,
|
||||
parent.c_str(),
|
||||
parent.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ilog("%s is a vlan %s network\n",
|
||||
physical_interface.c_str(), ptr->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // end of switch
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(file_ptr);
|
||||
}
|
||||
|
||||
/* Lagged interface */
|
||||
if ((ptr->interface_one[0] == '\0') && (!physical_interface.empty()))
|
||||
{
|
||||
string lagged_interface_file =
|
||||
INTERFACES_DIR + physical_interface + "/bonding/slaves";
|
||||
|
||||
ifstream finTwo( lagged_interface_file.c_str() );
|
||||
if (!finTwo)
|
||||
{
|
||||
elog ("Cannot find bond interface file (%s) to "
|
||||
"resolve slave interfaces\n", lagged_interface_file.c_str());
|
||||
ptr->used = false ;
|
||||
return (FAIL_OPERATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
string line;
|
||||
while ( getline( finTwo, line ) )
|
||||
{
|
||||
strncpy(line_buf, line.c_str(), MAX_CHARS_ON_LINE);
|
||||
|
||||
// the slave interfaces are listed as enXYYY enXYYY...
|
||||
// starting with the primary. Read all other slaves
|
||||
// as interface_two
|
||||
sscanf(line_buf, "%19s %19s", ptr->interface_one, ptr->interface_two);
|
||||
|
||||
ilog("%s and %s are %s network aggregated interfaces\n",
|
||||
ptr->interface_one,
|
||||
ptr->interface_two,
|
||||
ptr->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ptr->interface_one[0] == '\0' )
|
||||
{
|
||||
ptr->used = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr->used = true;
|
||||
if ( ptr->interface_two[0] == '\0' )
|
||||
{
|
||||
/* this is not a lagged interface */
|
||||
ptr->lagged = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is a lagged interface */
|
||||
ptr->lagged = true;
|
||||
}
|
||||
}
|
||||
return (PASS);
|
||||
}
|
||||
|
||||
|
||||
|
83
mtce/src/lmon/scripts/lmon
Normal file
83
mtce/src/lmon/scripts/lmon
Normal file
@ -0,0 +1,83 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 2019 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# chkconfig: 2345 95 95
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: lmon
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: Link Monitor daemon
|
||||
### END INIT INFO
|
||||
|
||||
. /etc/init.d/functions
|
||||
|
||||
DAEMON_NAME="lmond"
|
||||
DAEMON="/usr/local/bin/${DAEMON_NAME}"
|
||||
IFACE=""
|
||||
|
||||
if [ ! -e "$DAEMON" ] ; then
|
||||
logger "$DAEMON is missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RETVAL=0
|
||||
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
|
||||
export PATH
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting $DAEMON_NAME: "
|
||||
# Prevent multiple starts
|
||||
if [ -n "`pidof ${DAEMON_NAME}`" ] ; then
|
||||
echo "OK"
|
||||
exit $RETVAL
|
||||
fi
|
||||
start-stop-daemon --start -b -x ${DAEMON} --
|
||||
RETVAL=$?
|
||||
if [ $RETVAL -eq 0 ] ; then
|
||||
echo "OK"
|
||||
else
|
||||
echo "FAIL"
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
echo -n "Stopping ${DAEMON_NAME}: "
|
||||
if [ -n "`pidof ${DAEMON_NAME}`" ] ; then
|
||||
killproc ${DAEMON_NAME}
|
||||
fi
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
status)
|
||||
pid=`pidof ${DAEMON_NAME}`
|
||||
RETVAL=$?
|
||||
if [ ${RETVAL} -eq 0 ] ; then
|
||||
echo "${DAEMON_NAME} is running"
|
||||
else
|
||||
echo "${DAEMON_NAME} is NOT running"
|
||||
fi
|
||||
;;
|
||||
|
||||
condrestart)
|
||||
[ -f /var/lock/subsys/${DAEMON_NAME} ] && $0 restart
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "usage: $0 { start | stop | status | restart | condrestart | status }"
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
16
mtce/src/lmon/scripts/lmon.logrotate
Normal file
16
mtce/src/lmon/scripts/lmon.logrotate
Normal file
@ -0,0 +1,16 @@
|
||||
#daily
|
||||
nodateext
|
||||
|
||||
/var/log/lmond.log
|
||||
{
|
||||
nodateext
|
||||
size 10M
|
||||
start 1
|
||||
missingok
|
||||
rotate 20
|
||||
compress
|
||||
sharedscripts
|
||||
postrotate
|
||||
systemctl reload syslog-ng > /dev/null 2>&1 || true
|
||||
endscript
|
||||
}
|
16
mtce/src/lmon/scripts/lmon.pmon.conf
Normal file
16
mtce/src/lmon/scripts/lmon.pmon.conf
Normal file
@ -0,0 +1,16 @@
|
||||
[process]
|
||||
process = lmond
|
||||
service = lmon
|
||||
pidfile = /var/run/lmond.pid
|
||||
style = lsb ; ocf or lsb
|
||||
severity = major ; minor, major, critical
|
||||
restarts = 3 ; restart retries before error assertion
|
||||
interval = 5 ; number of seconds to wait between restarts
|
||||
debounce = 20 ; number of seconds that a process needs to remain
|
||||
; running before degrade is removed and retry count
|
||||
; is cleared.
|
||||
startuptime = 5 ; Seconds to wait after process start before starting the debounce monitor
|
||||
mode = passive ; Monitoring mode: passive (default) or active
|
||||
; passive: process death monitoring (default: always)
|
||||
; active : heartbeat monitoring, i.e. request / response messaging
|
||||
; ignore : do not monitor or stop monitoring
|
17
mtce/src/lmon/scripts/lmon.service
Normal file
17
mtce/src/lmon/scripts/lmon.service
Normal file
@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
Description=Starling-X Maintenance Link Monitor
|
||||
|
||||
After=config.service
|
||||
After=syslog-ng.service
|
||||
Before=pmon.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/etc/rc.d/init.d/lmon start
|
||||
ExecStop=/etc/rc.d/init.d/lmon stop
|
||||
ExecReload=/etc/rc.d/init.d/lmon reload
|
||||
PIDFile=/var/run/lmond.pid
|
||||
KillMode=process
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
19
mtce/src/lmon/scripts/lmond.conf
Normal file
19
mtce/src/lmon/scripts/lmond.conf
Normal file
@ -0,0 +1,19 @@
|
||||
; Link Monitor Configuration File
|
||||
[client] ; Client configuration
|
||||
audit_period = 60 ; seconds between process audits
|
||||
lmon_query_port = 2122 ; port that responds to link query requests
|
||||
daemon_log_port = 2121 ; daemon logger port
|
||||
uri_path = /mtce/lmon ; maintenance service path http://<ip>:<port><uri_path>
|
||||
|
||||
[defaults]
|
||||
|
||||
[timeouts]
|
||||
|
||||
[features]
|
||||
|
||||
[debug] ; SIGHUP to reload
|
||||
debug_timer = 0 ; enable(1) or disable(0) timer logs (tlog)
|
||||
debug_json = 0 ; enable(1) or disable(0) message logs (jlog)
|
||||
debug_state = 0 ; enable(1) or disable(0) state change logs (clog)
|
||||
debug_level = 0 ; decimal mask 0..15 (8,4,2,1)
|
||||
debug_all = 0 ; set all debug labels to the specified value
|
@ -663,7 +663,7 @@ int rmon_hdlr_init ( rmon_ctrl_type * ctrl_ptr )
|
||||
|
||||
_thinmeta_config_load();
|
||||
_config_files_load ();
|
||||
_inter_config_load ();
|
||||
// _inter_config_load ();
|
||||
|
||||
/* init Thin Metadata Monitoring after config reload - including timers */
|
||||
thinmeta_init(thinmeta_resource_config, thinmetatimer, ctrl_ptr->thinmeta_resources);
|
||||
|
Loading…
Reference in New Issue
Block a user