diff --git a/centos_iso_image.inc b/centos_iso_image.inc index d607d55b..018e0631 100644 --- a/centos_iso_image.inc +++ b/centos_iso_image.inc @@ -8,6 +8,7 @@ mtce-pmon mtce-rmon mtce-hwmon mtce-hostw +mtce-lmon # mtce-compute mtce-compute diff --git a/mtce-common/src/common/httpUtil.cpp b/mtce-common/src/common/httpUtil.cpp index 534125c1..d263971c 100644 --- a/mtce-common/src/common/httpUtil.cpp +++ b/mtce-common/src/common/httpUtil.cpp @@ -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 ); + } +} + diff --git a/mtce-common/src/common/httpUtil.h b/mtce-common/src/common/httpUtil.h index f108e2b3..d846d29c 100644 --- a/mtce-common/src/common/httpUtil.h +++ b/mtce-common/src/common/httpUtil.h @@ -12,6 +12,7 @@ #include /* for ... http libevent client */ #include #include +#include /* 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__ */ diff --git a/mtce-common/src/common/logMacros.h b/mtce-common/src/common/logMacros.h index 55a72496..f8720c97 100644 --- a/mtce-common/src/common/logMacros.h +++ b/mtce-common/src/common/logMacros.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/ */ - char* sysinv_mtc_inv_label ; /**< =/v1/hosts/ */ int sysinv_api_port ; /**< =6385 */ char* sysinv_api_bind_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 */ diff --git a/mtce-common/src/common/nodeUtil.cpp b/mtce-common/src/common/nodeUtil.cpp index 1b282e8c..9aa30dc9 100755 --- a/mtce-common/src/common/nodeUtil.cpp +++ b/mtce-common/src/common/nodeUtil.cpp @@ -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] ; diff --git a/mtce-common/src/common/nodeUtil.h b/mtce-common/src/common/nodeUtil.h index 2c46100f..712a7251 100755 --- a/mtce-common/src/common/nodeUtil.h +++ b/mtce-common/src/common/nodeUtil.h @@ -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); diff --git a/mtce-common/src/daemon/daemon_config.cpp b/mtce-common/src/daemon/daemon_config.cpp index e92c6771..e11212c1 100644 --- a/mtce-common/src/daemon/daemon_config.cpp +++ b/mtce-common/src/daemon/daemon_config.cpp @@ -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 );} diff --git a/mtce/centos/build_srpm.data b/mtce/centos/build_srpm.data index 8cf0e480..5b13b5ad 100644 --- a/mtce/centos/build_srpm.data +++ b/mtce/centos/build_srpm.data @@ -1,3 +1,3 @@ SRC_DIR="src" -TIS_PATCH_VER=145 +TIS_PATCH_VER=146 BUILD_IS_SLOW=5 diff --git a/mtce/centos/mtce.spec b/mtce/centos/mtce.spec index b86dd00e..bf79a421 100644 --- a/mtce/centos/mtce.spec +++ b/mtce/centos/mtce.spec @@ -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 ############################### diff --git a/mtce/src/Makefile b/mtce/src/Makefile index e4587181..68db5444 100755 --- a/mtce/src/Makefile +++ b/mtce/src/Makefile @@ -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 ) diff --git a/mtce/src/lmon/Makefile b/mtce/src/lmon/Makefile new file mode 100755 index 00000000..2681097d --- /dev/null +++ b/mtce/src/lmon/Makefile @@ -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 diff --git a/mtce/src/lmon/lmon.h b/mtce/src/lmon/lmon.h new file mode 100644 index 00000000..4721f0e8 --- /dev/null +++ b/mtce/src/lmon/lmon.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include /* 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 ); diff --git a/mtce/src/lmon/lmonHdlr.cpp b/mtce/src/lmon/lmonHdlr.cpp new file mode 100644 index 00000000..9dec02e7 --- /dev/null +++ b/mtce/src/lmon/lmonHdlr.cpp @@ -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 /* 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 links_gone_down ; + list links_gone_up ; + list::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 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(); +} + + + + diff --git a/mtce/src/lmon/lmonInit.cpp b/mtce/src/lmon/lmonInit.cpp new file mode 100644 index 00000000..cdb771b2 --- /dev/null +++ b/mtce/src/lmon/lmonInit.cpp @@ -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); +} diff --git a/mtce/src/lmon/lmonUtil.cpp b/mtce/src/lmon/lmonUtil.cpp new file mode 100644 index 00000000..ea3509c8 --- /dev/null +++ b/mtce/src/lmon/lmonUtil.cpp @@ -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 /* for ... ifstream */ +#include /* for ... stringstream */ +#include /* for ... if_indextoname , IF_NAMESIZE */ +#include /* 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); +} + + + diff --git a/mtce/src/lmon/scripts/lmon b/mtce/src/lmon/scripts/lmon new file mode 100644 index 00000000..e55dac51 --- /dev/null +++ b/mtce/src/lmon/scripts/lmon @@ -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 diff --git a/mtce/src/lmon/scripts/lmon.logrotate b/mtce/src/lmon/scripts/lmon.logrotate new file mode 100644 index 00000000..b59fa9ff --- /dev/null +++ b/mtce/src/lmon/scripts/lmon.logrotate @@ -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 +} diff --git a/mtce/src/lmon/scripts/lmon.pmon.conf b/mtce/src/lmon/scripts/lmon.pmon.conf new file mode 100644 index 00000000..a62e9b52 --- /dev/null +++ b/mtce/src/lmon/scripts/lmon.pmon.conf @@ -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 diff --git a/mtce/src/lmon/scripts/lmon.service b/mtce/src/lmon/scripts/lmon.service new file mode 100644 index 00000000..84b14d46 --- /dev/null +++ b/mtce/src/lmon/scripts/lmon.service @@ -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 diff --git a/mtce/src/lmon/scripts/lmond.conf b/mtce/src/lmon/scripts/lmond.conf new file mode 100644 index 00000000..a99609ac --- /dev/null +++ b/mtce/src/lmon/scripts/lmond.conf @@ -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://: + +[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 diff --git a/mtce/src/rmon/rmonHdlr.cpp b/mtce/src/rmon/rmonHdlr.cpp index e4ae793f..42669567 100644 --- a/mtce/src/rmon/rmonHdlr.cpp +++ b/mtce/src/rmon/rmonHdlr.cpp @@ -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);