Hello Steven,

I attached a patch again.
I am not prepared to link status callback but could you merge.
(I am still thinking but not have good idea.)

also, how about I use a "tsafe_off()" and "tsafe_on()"?
I could be wrong because I did not understand it.
Otherwise, I can not attach snmp service for trunk.


Thanks in advance.

yuki sato


Sato-san,

Really nice initial work.  I have few comments on the patch which are
nitpicky but which once resolved, can be merged.

first the high level issues:

configure --with-snmp should be --enable-snmp.

The configure.ac SUPPORT_SNMP variable should be enable_snmp

Running configure --enable-snmp should assume a "yes" value

Running configure without --enable-snmp should create a build without
snmp support.

"Features" should print out "snmp" in the configure output ie:

  Features                 = nss snmp

The package should error during the configure step if net-snmp-devel
package is not installed and snmp is enabled.  Currently it just doesn't
build snmp support without giving any warning.  This is likely confusing
to users.

I get the following after installing when running.

Mar 11 14:43:51 corosync [SERV  ] Service engine loaded: corosync
profile loading service
/usr/libexec/lcrso/service_snmp.lcrso: open
failed: /usr/libexec/lcrso/service_snmp.lcrso: undefined symbol:
snmp_send

I looked over the Makefile and the output looks correct on my f11 system
- not sure why its not working.

SNMPLIBS is way overloaded.  I manually compiled as follows:

gcc `net-snmp-config --libs` -shared -Wl,-soname=service_snmp.lcros
snmp.o -o service_snmp.lcrso

This gives the dependencies:
[r...@localhost services]# ldd service_snmp.lcrso
        linux-gate.so.1 =>  (0x00ef4000)
        libcrypto.so.8 => /usr/lib/libcrypto.so.8 (0x00afc000)
        libsensors.so.4 => /usr/lib/libsensors.so.4 (0x00a4e000)
        libnetsnmp.so.15 => /usr/lib/libnetsnmp.so.15 (0x007c6000)
        libc.so.6 => /lib/libc.so.6 (0x0053b000)
        libdl.so.2 => /lib/libdl.so.2 (0x0090a000)
        libz.so.1 => /lib/libz.so.1 (0x00297000)
        libm.so.6 => /lib/libm.so.6 (0x00110000)
        /lib/ld-linux.so.2 (0x003e9000)

SNMPLIBS in my makefile on the other hand has many other unneeded
dependencies:
SNMPLIBS = -lcrypto -lsensors -L/usr/lib -lnetsnmpagent -lnetsnmphelpers
-lnetsnmpmibs -lnetsnmp -lz -Wl,-E
-Wl,-rpath,/usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE
-L/usr/local/lib -L/usr/lib/perl5/5.10.0/i386-linux-thread-multi/CORE
-lperl -lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc

Also -rpath is not allowed in corosync.

when running I see:
Mar 11 14:57:10 corosync [SNMP  ] ringid:340    nodeid:1        famiry:2
ip:192.168.1.105.
Log SNMP messages at debug level

famiry is a typo - should be family

additional comments inline in the patch.

make distcheck fails.  That must work to be able to merge the patch,
since that is part of our release process.  There are two ways to solve
this - add the COROSYNC-MIB.txt to EXTRA_DIST in the conf dir, or
alternately (less preferred) add to top level Makefile.am

Really great work!  just a few issues to sort out and we should be good
for merge.

Regards
-steve
Index: include/corosync/corodefs.h
===================================================================
--- include/corosync/corodefs.h (revision 2739)
+++ include/corosync/corodefs.h (working copy)
@@ -57,7 +57,8 @@
        TMR_SERVICE = 14,
        VOTEQUORUM_SERVICE = 15,
        NTF_SERVICE = 16,
-       AMF_V2_SERVICE = 17
+       AMF_V2_SERVICE = 17,
+       SNMP_SERVICE = 18
 };
 
 #ifdef HAVE_SMALL_MEMORY_FOOTPRINT
Index: services/Makefile.am
===================================================================
--- services/Makefile.am        (revision 2739)
+++ services/Makefile.am        (working copy)
@@ -37,7 +37,7 @@
                          -I$(top_builddir)/include/corosync \
                          -I$(top_srcdir)/include/corosync
 
-SERVICE_LCRSO          = evs cfg cpg confdb pload
+SERVICE_LCRSO          = evs cfg cpg confdb pload @SNMP_LCRSO@
 
 QUORUM_LCRSO           = votequorum testquorum
 
@@ -56,6 +56,11 @@
 service_%.lcrso: %.o
        $(CC) $(CFLAGS) -L$(top_builddir)/exec -llogsys -bundle -bundle_loader 
$(top_builddir)/exec/corosync $^ -o $@
 
+if BUILD_SNMP
+service_snmp.lcrso: snmp.o
+       $(CC) $(CFLAGS) $(SNMPLIBS) -L$(top_builddir)/exec -llogsys -bundle 
-bundle_loader $(top_builddir)/exec/corosync $^ -o $@
+endif
+
 else
 
 if BUILD_SOLARIS
@@ -66,16 +71,27 @@
 service_%.lcrso: %.o
        $(LD) $(LDFLAGS) -G $^ -o $@
 
+if BUILD_SNMP
+service_snmp.lcrso: snmp.o
+       $(LD) $(LDFLAGS) $(SNMPLIBS) -G $^ -o $@
+endif
+
 else
 quorum_%.lcrso: %.o
        $(CC) $(CFLAGS) $(COVERAGE_LCRSO_EXTRA_LDFLAGS) -shared -Wl,-soname=$@ 
$^ -o $@
 
 service_%.lcrso: %.o
        $(CC) $(CFLAGS) $(COVERAGE_LCRSO_EXTRA_LDFLAGS) -shared -Wl,-soname=$@ 
$^ -o $@
+
+if BUILD_SNMP
+service_snmp.lcrso: snmp.o
+       $(CC) $(CFLAGS) $(COVERAGE_LCRSO_EXTRA_LDFLAGS) $(SNMPLIBS) -shared 
-Wl,-soname=$@ $^ -o $@
 endif
 
 endif
 
+endif
+
 %.o: %.c
        $(CC) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
 
Index: services/snmp.c
===================================================================
--- services/snmp.c     (revision 0)
+++ services/snmp.c     (revision 0)
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2009 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ *
+ * All rights reserved.
+ *
+ * Author: Yuki Sato ([email protected])
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the 
documentation
+ *      and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *      contributors may be used to endorse or promote products derived from 
this
+ *      software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/coroipc_types.h>
+#include <corosync/corodefs.h>
+#include <corosync/list.h>
+#include <corosync/mar_gen.h>
+#include <corosync/totem/totemip.h>
+#include <corosync/totem/totem.h>
+#include <corosync/totem/coropoll.h>
+#include <corosync/lcr/lcr_comp.h>
+#include <corosync/engine/logsys.h>
+#include <corosync/engine/coroapi.h>
+#include "../exec/tsafe.h"
+
+/*
+#include <corosync/ipc_cfg.h>
+*/
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/snmpv3_api.h>
+#include <net-snmp/agent/agent_trap.h>
+#include <net-snmp/library/mib.h>
+#include <net-snmp/library/snmp_api.h>
+#include <net-snmp/library/snmp_client.h>
+#include <net-snmp/library/snmp_debug.h>
+
+#define SNMP_OID_COROSYNC "1.3.6.1.4.1.35488"
+#define SNMP_OID_NOTICE_ROOT SNMP_OID_COROSYNC ".1"
+#define SNMP_OID_NOTICE_NODE_TABLE  SNMP_OID_NOTICE_ROOT ".1"
+#define SNMP_OID_NOTICE_NODE_ENTRY  SNMP_OID_NOTICE_NODE_TABLE ".1"
+#define SNMP_OID_NOTICE_NODE_INDEX  SNMP_OID_NOTICE_NODE_ENTRY ".1"
+#define SNMP_OID_NOTICE_NODE_ID     SNMP_OID_NOTICE_NODE_ENTRY ".2"
+#define SNMP_OID_NOTICE_NODE        SNMP_OID_NOTICE_NODE_ENTRY ".3"
+#define SNMP_OID_NOTICE_NODE_STATE  SNMP_OID_NOTICE_NODE_ENTRY ".4"
+#define SNMP_OID_NOTICE_IFACE_TABLE SNMP_OID_NOTICE_ROOT ".2"
+#define SNMP_OID_NOTICE_IFACE_ENTRY SNMP_OID_NOTICE_IFACE_TABLE ".1"
+#define SNMP_OID_NOTICE_IFACE_INDEX SNMP_OID_NOTICE_IFACE_ENTRY ".1"
+#define SNMP_OID_NOTICE_IFACE       SNMP_OID_NOTICE_IFACE_ENTRY ".2"
+#define SNMP_OID_NOTICE_IFACE_STATE SNMP_OID_NOTICE_IFACE_ENTRY ".3"
+
+#define SNMP_OID_TRAPS_ROOT  SNMP_OID_COROSYNC ".100"
+#define SNMP_OID_TRAPS_NODE  SNMP_OID_TRAPS_ROOT ".1"
+#define SNMP_OID_TRAPS_IFACE SNMP_OID_TRAPS_ROOT ".2"
+
+enum snmp_node_status {
+       SNMP_NODE_STATUS_UNKNOWN = 0,
+       SNMP_NODE_STATUS_JOINED = 1,
+       SNMP_NODE_STATUS_LEFT = 2
+};
+
+enum snmp_iface_status {
+       SNMP_IFACE_STATUS_UNKNOWN = 0,
+       SNMP_IFACE_STATUS_UP = 1,
+       SNMP_IFACE_STATUS_DOWN = 2
+};
+
+struct my_interface {
+       struct totem_ip_address address[INTERFACE_MAX];
+       char *my_iface_status[INTERFACE_MAX];
+       char **iface_status;
+       unsigned int iface_cnt;
+};
+
+struct snmpsvc_instance {
+       corosync_timer_handle_t timeout_timer_handle;
+       unsigned long long snmp_duration;
+};
+
+LOGSYS_DECLARE_SUBSYS ("SNMP");
+
+/*
+enum snmp_message_req_types {
+
+};
+*/
+
+static struct list_head trackers_list;
+
+static void snmp_confchg_fn (
+       enum totem_configuration_type configuration_type,
+       const unsigned int *member_list, size_t member_list_entries,
+       const unsigned int *left_list, size_t left_list_entries,
+       const unsigned int *joined_list, size_t joined_list_entries,
+       const struct memb_ring_id *ring_id);
+
+static int snmp_exec_init_fn (struct corosync_api_v1 *corosync_api_v1);
+static int snmp_exec_exit_fn (void);
+
+static struct corosync_api_v1 *api;
+
+static int snmp_lib_init_fn (void *conn);
+
+static int snmp_lib_exit_fn (void *conn);
+
+static char *snmp_manager;
+static int use_snmp;
+static struct my_interface my_interface;
+static struct snmpsvc_instance *snmpsvc_instance = NULL;
+
+static netsnmp_session *snmp_init (
+       const char *target);
+
+static void sendsnmp_nodetrap(
+       const char *target, 
+       unsigned int node_id,
+       unsigned int node_status,
+       const char *node);
+
+static void sendsnmp_ifacetrap(
+       const char *target, 
+       unsigned int node_id,
+       unsigned int iface_status,
+       const char *iface);
+
+/*
+ * Service Handler Definition
+ */
+/*
+static struct corosync_lib_handler snmp_lib_engine[] =
+{
+       {
+               .lib_handler_fn         = NULL,
+               .flow_control           = NULL
+       }
+};
+*/
+/*
+static struct corosync_exec_handler snmp_exec_engine[] =
+{
+       {
+               .exec_handler_fn        = NULL
+       }
+};
+*/
+/*
+ * Exports the interface for the service
+ */
+struct corosync_service_engine snmp_service_engine = {
+       .name                           = "corosync snmp service",
+       .id                             = SNMP_SERVICE,
+       .priority                       = 1,
+       .private_data_size              = 0, /*sizeof (struct snmp_info)*/
+       .flow_control                   = CS_LIB_FLOW_CONTROL_NOT_REQUIRED,
+       .allow_inquorate                = CS_LIB_ALLOW_INQUORATE,
+       .lib_init_fn                    = snmp_lib_init_fn,
+       .lib_exit_fn                    = snmp_lib_exit_fn,
+       .lib_engine                     = 0, /*snmp_lib_engine,*/
+       .lib_engine_count               = 0, /*sizeof (snmp_lib_engine) / 
sizeof (struct corosync_lib_handler),*/
+       .exec_init_fn                   = snmp_exec_init_fn,
+       .exec_exit_fn                   = snmp_exec_exit_fn,
+       .exec_engine                    = 0, /*snmp_exec_engine,*/
+       .exec_engine_count              = 0, /* sizeof 
(snmp_aisexec_handler_fns) / sizeof (coroync_exec_handler), */
+       .confchg_fn                     = snmp_confchg_fn,
+       .sync_mode                      = CS_SYNC_V1
+};
+
+/*
+ * Dynamic Loader definition
+ */
+static struct corosync_service_engine *snmp_get_service_engine_ver0 (void);
+
+static struct corosync_service_engine_iface_ver0 snmp_service_engine_iface = {
+       .corosync_get_service_engine_ver0       = snmp_get_service_engine_ver0
+};
+
+static struct lcr_iface corosync_snmp_ver0[1] = {
+       {
+               .name                   = "corosync_snmp",
+               .version                = 0,
+               .versions_replace       = 0,
+               .versions_replace_count = 0,
+               .dependencies           = 0,
+               .dependency_count       = 0,
+               .constructor            = NULL,
+               .destructor             = NULL,
+               .interfaces             = NULL
+       }
+};
+
+static struct lcr_comp snmp_comp_ver0 = {
+       .iface_count                    = 1,
+       .ifaces                         = corosync_snmp_ver0
+};
+
+static struct corosync_service_engine *snmp_get_service_engine_ver0 (void)
+{
+       return (&snmp_service_engine);
+}
+
+#ifdef COROSYNC_SOLARIS
+void corosync_lcr_component_register (void);
+
+void corosync_lcr_component_register (void) {
+#else
+__attribute__ ((constructor)) static void corosync_lcr_component_register 
(void) {
+#endif
+       lcr_interfaces_set (&corosync_snmp_ver0[0], &snmp_service_engine_iface);
+
+       lcr_component_register (&snmp_comp_ver0);
+}
+
+/* IMPL */
+
+static inline int objdb_get_string(
+       hdb_handle_t object_handle,
+       const char *key,
+       char **value)
+{
+       *value = NULL;
+       if (!api->object_key_get (object_handle, key, strlen(key), (void 
*)value, NULL)) {
+               if (*value) {
+                       return (0);
+               }
+       }
+       return (-1);
+}
+
+static inline void iface_get (
+       unsigned int nodeid,
+       struct my_interface *interface)
+{
+       int ret = api->totem_ifaces_get (
+                       nodeid,
+                       interface->address,
+                       &interface->iface_status,
+                       &interface->iface_cnt);
+
+       if (ret == -1) {
+               interface->iface_cnt = 0;
+       }
+}
+
+static inline void my_iface_init (void)
+{
+       int i;
+
+       memset (&my_interface, 0x00, sizeof (struct my_interface));
+       for (i = 0; i < INTERFACE_MAX; i++ ) {
+               my_interface.my_iface_status[i] = malloc (1024);
+               my_interface.my_iface_status[i][0] = '\0';
+       }
+}
+
+static inline void my_iface_update (
+       struct my_interface *interface)
+{
+       int i;
+
+       if (interface->iface_cnt > 0) {
+               memcpy (&my_interface.address, &interface->address, sizeof 
(struct totem_ip_address));
+               my_interface.iface_cnt = interface->iface_cnt;
+               for (i = 0; i < interface->iface_cnt; i++) {
+                       strcpy (my_interface.my_iface_status[i], 
interface->iface_status[i]);
+               }
+       }
+}
+
+static void timer_function_iface_check (void* data)
+{
+       int i;
+       enum snmp_iface_status status;
+       const char *iface = NULL;
+       struct my_interface interface;
+
+       struct snmpsvc_instance *instance = (struct snmpsvc_instance*)data;
+
+       iface_get (api->totem_nodeid_get(), &interface);
+
+       if (my_interface.iface_cnt != interface.iface_cnt) {
+               my_iface_update (&interface);
+       } else {
+               for (i = 0; i < my_interface.iface_cnt; i++) {
+                       if (strcmp( interface.iface_status[i],
+                                       my_interface.my_iface_status[i]) != 0 ) 
{
+                               if (strstr (interface.iface_status[i], 
"FAULTY") != NULL) {
+                                       status  = SNMP_IFACE_STATUS_DOWN;
+                                       iface   = totemip_print 
(&interface.address[i]);
+                               } else if (strstr (interface.iface_status[i], 
"active with no faults") != NULL &&
+                                          strstr 
(my_interface.my_iface_status[i], "FAULTY") != NULL) {
+                                       status = SNMP_IFACE_STATUS_UP;
+                                       iface   = totemip_print 
(&interface.address[i]);
+                               } else if (strstr (interface.iface_status[i], 
"active with no faults") != NULL) {
+                                       /* status changed */
+                                       my_iface_update (&interface);
+                               }
+                               break;
+                       }
+               }
+       }
+       if (iface != NULL) {
+               tsafe_off();
+               sendsnmp_ifacetrap (snmp_manager, api->totem_nodeid_get(), 
status, iface);
+               tsafe_on();
+               my_iface_update (&interface);
+       }
+
+       if (instance != NULL) {
+               api->timer_add_duration (
+                       instance->snmp_duration * 1000000000ULL,
+                       (void*)instance,
+                       timer_function_iface_check,
+                       &instance->timeout_timer_handle);
+       }
+}
+
+static netsnmp_session *snmp_init (const char *target)
+{
+       static netsnmp_session *session = NULL;
+#ifndef NETSNMPV54
+       char default_port[128];
+       snprintf (default_port, sizeof (default_port), "%s:162", target);
+#endif
+       if (session) {
+               return (session);
+       }
+
+       if (target == NULL) {
+               return NULL;
+       }
+
+       session = malloc (sizeof (netsnmp_session));
+       
+       snmp_sess_init (session);
+       session->version = SNMP_VERSION_2c;
+       session->callback = NULL;
+       session->callback_magic = NULL;
+
+       session = snmp_add(session,
+#ifdef NETSNMPV54
+                       netsnmp_transport_open_client ("snmptrap", target),
+#else
+                       netsnmp_tdomain_transport (default_port, 0, "udp"),
+#endif
+                       NULL, NULL);
+
+       if (session == NULL) {
+               log_printf (LOGSYS_LEVEL_ERROR, "Could not create snmp 
transport");
+       }
+       return (session);
+}
+
+static inline void add_field (
+       netsnmp_pdu *trap_pdu,
+       u_char asn_type,
+       const char *prefix,
+       void *value,
+       size_t value_size)
+{
+       oid     _oid[MAX_OID_LEN];
+       size_t  _oid_len = MAX_OID_LEN;
+       if (snmp_parse_oid (prefix, _oid, &_oid_len)) {
+               snmp_pdu_add_variable (trap_pdu, _oid, _oid_len, asn_type, 
(u_char *) value, value_size);
+       }
+}
+
+static void sendsnmp_nodetrap (
+       const char *target, 
+       unsigned int node_id,
+       enum snmp_node_status node_status,
+       const char *node)
+{
+       int ret;
+       char csysuptime[20];
+       static oid snmptrap_oid[]  = { 1,3,6,1,6,3,1,1,4,1,0 };
+       static oid sysuptime_oid[] = { 1,3,6,1,2,1,1,3,0 };
+       time_t now = time (NULL);
+
+       netsnmp_pdu *trap_pdu;
+       netsnmp_session *session = snmp_init (target);
+       if (session == NULL) {
+               log_printf (LOGSYS_LEVEL_NOTICE, "Failed to init SNMP 
session.\n");
+               return ;
+       }
+
+       trap_pdu = snmp_pdu_create (SNMP_MSG_TRAP2);
+       if (!trap_pdu) {
+               log_printf (LOGSYS_LEVEL_NOTICE, "Failed to create SNMP 
notification.\n");
+               return ;
+       }
+
+       /* send uptime */
+       sprintf (csysuptime, "%ld", now);
+       snmp_add_var (trap_pdu, sysuptime_oid, sizeof (sysuptime_oid) / sizeof 
(oid), 't', csysuptime);
+       snmp_add_var (trap_pdu, snmptrap_oid, sizeof (snmptrap_oid) / sizeof 
(oid), 'o', SNMP_OID_TRAPS_NODE);
+
+       /* Add extries to the trap */
+       add_field (trap_pdu,ASN_INTEGER, SNMP_OID_NOTICE_NODE_ID, 
(void*)&node_id, sizeof (node_id));
+       add_field (trap_pdu,ASN_OCTET_STR, SNMP_OID_NOTICE_NODE, (void*)node, 
strlen (node));
+       add_field (trap_pdu,ASN_INTEGER, SNMP_OID_NOTICE_NODE_STATE, 
(void*)&node_status, sizeof (node_status));
+
+       /* Send and cleanup */
+       ret = snmp_send (session, trap_pdu);
+       if (ret == 0) {
+               /* error */
+               log_printf (LOGSYS_LEVEL_ERROR, "Could not send SNMP trap");
+               snmp_free_pdu (trap_pdu);
+       }
+}
+
+static void sendsnmp_ifacetrap (
+       const char *target, 
+       unsigned int node_id,
+       enum snmp_iface_status iface_status,
+       const char *iface )
+{
+       int ret;
+       char csysuptime[20];
+       static oid snmptrap_oid[]       = { 1,3,6,1,6,3,1,1,4,1,0 };
+       static oid sysuptime_oid[]      = { 1,3,6,1,2,1,1,3,0 };
+       time_t now = time(NULL);
+
+       netsnmp_pdu *trap_pdu;
+       netsnmp_session *session = snmp_init (target);
+       if (session == NULL) {
+               log_printf (LOGSYS_LEVEL_NOTICE, "Failed to init SNMP 
session.\n");
+       }
+
+       trap_pdu = snmp_pdu_create (SNMP_MSG_TRAP2);
+       if (!trap_pdu) {
+               log_printf (LOGSYS_LEVEL_NOTICE, "Failed to create SNMP 
notification.\n");
+               return ;
+       }
+
+       /* send uptime */
+       sprintf (csysuptime, "%ld", now);
+       snmp_add_var (trap_pdu, sysuptime_oid, sizeof (sysuptime_oid) / sizeof 
(oid), 't', csysuptime);
+       
+       /* Indicate what the trap is by setting snmpTrapOid.0 */
+       snmp_add_var (trap_pdu, snmptrap_oid, sizeof (snmptrap_oid) / sizeof 
(oid), 'o', SNMP_OID_TRAPS_IFACE);
+
+       /* Add extries to the trap */
+       add_field (trap_pdu,ASN_INTEGER, SNMP_OID_NOTICE_NODE_ID, 
(void*)&node_id, sizeof (node_id));
+       add_field (trap_pdu,ASN_OCTET_STR, SNMP_OID_NOTICE_IFACE, (void*)iface, 
strlen (iface));
+       add_field (trap_pdu,ASN_INTEGER, SNMP_OID_NOTICE_IFACE_STATE, 
(void*)&iface_status, sizeof (iface_status));
+
+       /* Send and cleanup */
+       ret = snmp_send (session, trap_pdu);
+       if (ret == 0) {
+               /* error */
+               log_printf (LOGSYS_LEVEL_ERROR, "Could not send SNMP trap");
+               snmp_free_pdu(trap_pdu);
+       }
+}
+
+static int snmp_exec_init_fn (
+       struct corosync_api_v1 *corosync_api_v1)
+{
+       hdb_handle_t object_handle, snmp_find_handle;
+       struct my_interface interface;
+
+#ifdef COROSYNC_SOLARIS
+       logsys_subsys_init();
+#endif
+
+       api = corosync_api_v1;
+
+       list_init(&trackers_list);
+
+       use_snmp = 0;
+       snmp_manager = NULL;
+
+       /* corosync.conf read */
+       api->object_find_create (OBJECT_PARENT_HANDLE, "snmp", strlen ("snmp"), 
&object_handle);
+       if ((api->object_find_next (object_handle, &snmp_find_handle)) == -1) {
+               return (-1);
+       }
+
+       if (!objdb_get_string (snmp_find_handle, "manager", &snmp_manager)) {
+               use_snmp = 1;
+       }
+
+       if (use_snmp) {
+               /* node,iface init */
+               my_iface_init();
+               iface_get (api->totem_nodeid_get(), &interface);
+               my_iface_update (&interface);
+
+               snmpsvc_instance = malloc (sizeof (struct snmpsvc_instance) );
+               if (snmpsvc_instance == NULL) {
+                       use_snmp = 0;
+                       return (-1);
+               }
+               /* timer handle set*/
+               snmpsvc_instance->snmp_duration = 10ULL;
+               api->timer_add_duration (
+                       snmpsvc_instance->snmp_duration * 1000000000ULL,
+                       (void*)snmpsvc_instance,
+                       timer_function_iface_check,
+                       &snmpsvc_instance->timeout_timer_handle);
+       }
+
+       return (0);
+}
+
+static int snmp_exec_exit_fn (void)
+{
+       if (use_snmp) {
+               unsigned int nodeid;
+               const char *node;
+
+               api->timer_delete (snmpsvc_instance->timeout_timer_handle);
+
+               nodeid = api->totem_nodeid_get();
+               node = totemip_print (&my_interface.address[0]);
+               if (node != NULL) {
+                       tsafe_off();
+                       sendsnmp_nodetrap (snmp_manager, nodeid, 
SNMP_NODE_STATUS_LEFT, node);
+                       tsafe_on();
+               }
+       }
+       return (0);
+}
+
+static void snmp_confchg_fn (
+       enum totem_configuration_type configuration_type,
+       const unsigned int *member_list, size_t member_list_entries,
+       const unsigned int *left_list, size_t left_list_entries,
+       const unsigned int *joined_list, size_t joined_list_entries,
+       const struct memb_ring_id *ring_id)
+{
+
+       log_printf (LOGSYS_LEVEL_DEBUG, 
"ringid:%lld\tnodeid:%d\tfamily:%d\tip:%s.\n",
+               ring_id->seq, ring_id->rep.nodeid, ring_id->rep.family, 
api->totem_ip_print (&ring_id->rep));
+
+       if (use_snmp) {
+               int i;
+               unsigned int nodeid;
+               const char *node;
+               struct my_interface interface;
+               
+               timer_function_iface_check (NULL);
+               
+               if (left_list_entries > 0) {
+                       for (i = 0; i < left_list_entries; ++i) {
+                               nodeid = left_list[i];
+                               iface_get (nodeid, &interface);
+                               node = totemip_print (&interface.address[0]);
+                               if (node != NULL) {
+                                       tsafe_off();
+                                       sendsnmp_nodetrap (snmp_manager, 
nodeid, SNMP_NODE_STATUS_LEFT, node);
+                                       tsafe_on();
+                               }
+                       }
+               }
+
+               if (joined_list_entries > 0) {
+                       for (i = 0; i < joined_list_entries; ++i) {
+                               nodeid = joined_list[i];
+                               iface_get (nodeid, &interface);
+                               node = totemip_print (&interface.address[0]);
+                               if (node != NULL) {
+                                       tsafe_off();
+                                       sendsnmp_nodetrap (snmp_manager, 
nodeid, SNMP_NODE_STATUS_JOINED, node);
+                                       tsafe_on();
+                               }
+                       }
+               }
+       }
+}
+
+int snmp_lib_exit_fn (void *conn)
+{
+       return (0);
+}
+
+static int snmp_lib_init_fn (void *conn)
+{
+       return (0);
+}
+
Index: exec/service.c
===================================================================
--- exec/service.c      (revision 2739)
+++ exec/service.c      (working copy)
@@ -89,6 +89,12 @@
                .name                    = "corosync_quorum",
                .ver                     = 0,
        }
+#ifdef ENABLE_SNMP
+       ,{
+               .name                    = "corosync_snmp",
+               .ver                     = 0,
+       }
+#endif
 };
 
 /*
Index: conf/COROSYNC-MIB.txt
===================================================================
--- conf/COROSYNC-MIB.txt       (revision 0)
+++ conf/COROSYNC-MIB.txt       (revision 0)
@@ -0,0 +1,185 @@
+COROSYNC-MIB DEFINITIONS ::= BEGIN
+
+--
+-- MIB objects for the corosync
+--
+
+IMPORTS
+    MODULE-IDENTITY,NOTIFICATION-TYPE,
+    Integer32,enterprises                       FROM SNMPv2-SMI
+    TEXTUAL-CONVENTION                          FROM SNMPv2-TC
+    SnmpAdminString                             FROM SNMP-FRAMEWORK-MIB
+    netSnmp                                     FROM NET-SNMP-MIB
+    InetAddressType, InetAddress                FROM INET-ADDRESS-MIB
+;
+
+corosync MODULE-IDENTITY
+    LAST-UPDATED    "200911061318Z"
+    ORGANIZATION    "www.corosync.org"
+    CONTACT-INFO    "name:  Yuki Sato
+                     email: [email protected]"
+    DESCRIPTION     "MIB objects for the corosync"
+    REVISION        "200911061318Z"
+    DESCRIPTION     "First draft"
+    REVISION        "201003251209Z"
+    DESCRIPTION
+        "Private Enterprise Number has been assigned."
+        ::= { enterprises 35488 }
+
+--
+-- top level structure
+--
+corosyncNotice OBJECT IDENTIFIER ::= { corosync 1 }
+
+--
+--  corosync MIB entries
+--
+
+--
+-- Node Information
+--
+corosyncNoticeNodeStatusTable OBJECT-TYPE
+    SYNTAX      SEQUENCE OF corosyncNoticeNodeEntry
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The table contains information about the nodes in the corosync."
+::= { corosyncNotice 1 }
+
+corosyncNoticeNodeEntry OBJECT-TYPE
+    SYNTAX      corosyncNoticeNodeEntry
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The entry containing information about the iface."
+    INDEX   { corosyncNoticeNodeIndex }
+::= { corosyncNoticeNodeStatusTable 1 }
+
+corosyncNoticeNodeEntry ::= SEQUENCE {
+    corosyncNoticeNodeIndex     Integer32,
+    corosyncNoticeNodeid        Integer32,
+    corosyncNoticeNode          OCTET STRING,
+    corosyncNoticeNodeStatus    INTEGER
+}
+
+corosyncNoticeNodeIndex OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION "The unique integer of the node."
+::= { corosyncNoticeNodeEntry 1 }
+
+corosyncNoticeNodeid OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION "The id of the node."
+::= { corosyncNoticeNodeEntry 2 }
+
+corosyncNoticeNode OBJECT-TYPE
+    SYNTAX      OCTET STRING (SIZE(1..64))
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The iface of the node."
+::= { corosyncNoticeNodeEntry 3 }
+
+corosyncNoticeNodeStatus OBJECT-TYPE
+    SYNTAX      INTEGER {
+                unknown (0),
+                joined  (1),
+                left    (2)
+            }
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The status change of the node."
+::= { corosyncNoticeNodeEntry 4 }
+
+--
+-- Iface(s) Information
+--
+corosyncNoticeIfaceStatusTable OBJECT-TYPE
+    SYNTAX      SEQUENCE OF corosyncNoticeIfaceEntry
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The table describes the iface(s) that are used by the corosync."
+::= { corosyncNotice 2 }
+
+corosyncNoticeIfaceEntry OBJECT-TYPE
+    SYNTAX      corosyncNoticeIfaceEntry
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The entry containing information about the iface."
+    INDEX   { corosyncNoticeIfaceIndex }
+::= { corosyncNoticeIfaceStatusTable 1 }
+
+corosyncNoticeIfaceEntry ::= SEQUENCE {
+    corosyncNoticeIfaceIndex    INTEGER,
+    corosyncNoticeIface         OCTET STRING,
+    corosyncNoticeIfaceStatus   OCTET STRING
+}
+
+corosyncNoticeIfaceIndex OBJECT-TYPE
+    SYNTAX      Integer32
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The unique integer of the iface(s)."
+::= { corosyncNoticeIfaceEntry 1 }
+
+corosyncNoticeIface OBJECT-TYPE
+    SYNTAX      OCTET STRING (SIZE(1..64))
+    MAX-ACCESS  accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The iface(s) of the change happened node."
+::= { corosyncNoticeIfaceEntry 2 }
+
+corosyncNoticeIfaceStatus OBJECT-TYPE
+    SYNTAX      INTEGER {
+                unknown (0),
+                up      (1),
+                down    (2)
+            }
+    MAX-ACCESS accessible-for-notify
+    STATUS      current
+    DESCRIPTION
+        "The status change of the iface."
+::= { corosyncNoticeIfaceEntry 3 }
+
+--corosyncNoticeIfaceStatus OBJECT-TYPE
+--   SYNTAX     OCTET STRING (SIZE(1..1024))
+--   MAX-ACCESS accessible-for-notify
+--   STATUS     current
+--   DESCRIPTION
+--       "The iface(s) status of the change happened node."
+--::= { corosyncNoticeIfaceEntry 3 }
+
+--
+-- Trap Information
+--
+corosyncNoticeTrap OBJECT IDENTIFIER ::= { corosync 100 }
+
+corosyncNoticeNodeTrap NOTIFICATION-TYPE
+    OBJECTS
+        { corosyncNoticeNodeid corosyncNoticeNode corosyncNoticeNodeStatus }
+    STATUS      current
+    DESCRIPTION
+        "The node status change event just happened."
+::= { corosyncNoticeTrap 1 }
+
+corosyncNoticeIfaceTrap NOTIFICATION-TYPE
+    OBJECTS
+        { corosyncNoticeNodeid corosyncNoticeIface corosyncNoticeIfaceStatus }
+    STATUS  current
+    DESCRIPTION
+        "The iface status change event just happened."
+::= { corosyncNoticeTrap 2 }
+
+END
+
+
+
Index: conf/Makefile.am
===================================================================
--- conf/Makefile.am    (revision 0)
+++ conf/Makefile.am    (revision 0)
@@ -0,0 +1,38 @@
+# Copyright (c) 2009 Red Hat, Inc.
+#
+# Authors: Andrew Beekhof
+#         Steven Dake ([email protected])
+#
+# This software licensed under BSD license, the text of which follows:
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# - Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+# - Neither the name of the MontaVista Software, Inc. nor the names of its
+#   contributors may be used to endorse or promote products derived from this
+#   software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+# THE POSSIBILITY OF SUCH DAMAGE.
+
+EXTRA_DIST     = COROSYNC-MIB.txt
+
+MAINTAINERCLEANFILES    = Makefile.in
+
+mibdir = $(datadir)/snmp/mibs
+mib_DATA = COROSYNC-MIB.txt
+
Index: configure.ac
===================================================================
--- configure.ac        (revision 2739)
+++ configure.ac        (working copy)
@@ -131,7 +131,8 @@
                 cts/Makefile
                 cts/agents/Makefile
                 cts/CTSvars.py
-                tools/Makefile])
+                tools/Makefile
+                conf/Makefile])
 
 ### Local business
 
@@ -219,6 +220,9 @@
        [ enable_augeas="no" ])
 AM_CONDITIONAL(INSTALL_AUGEAS, test x$enable_augeas = xyes)
 
+AC_ARG_ENABLE([snmp],
+       [  --enable-snmp           : SNMP protocol support ],
+       [ default="no" ])
 
 AC_ARG_WITH([initddir],
        [  --with-initddir=DIR     : path to init script directory. ],
@@ -353,6 +357,61 @@
        PACKAGE_FEATURES="$PACKAGE_FEATURES augeas"
 fi
 
+if test "x${enable_snmp}" = xyes; then
+       SNMPCONFIG=""
+       AC_CHECK_HEADERS(net-snmp/net-snmp-config.h)
+
+       if test "x${ac_cv_header_net_snmp_net_snmp_config_h}" != "xyes"; then
+               enable_snmp=no
+       fi
+
+       if test $enable_snmp != no; then
+               AC_PATH_PROGS(SNMPCONFIG, net-snmp-config)
+               if test "X${SNMPCONFIG}" = "X"; then
+                       AC_MSG_RESULT(You need the net_snmp development package 
to continue.)
+                       enable_snmp=no
+               fi
+       fi
+
+       if test $enable_snmp != no; then
+               AC_MSG_CHECKING(for special snmp libraries)
+               SNMPLIBS=`$SNMPCONFIG --libs`
+               AC_MSG_RESULT($SNMPLIBS)
+       fi
+
+       if test $enable_snmp != no; then
+               savedLibs=$LIBS
+               LIBS="$LIBS $SNMPLIBS"
+               AC_CHECK_FUNCS(netsnmp_transport_open_client)
+               if test $ac_cv_func_netsnmp_transport_open_client != yes; then
+                       AC_CHECK_FUNCS(netsnmp_tdomain_transport)
+                       if test $ac_cv_func_netsnmp_tdomain_transport != yes; 
then
+                               enable_snmp=no
+                       fi
+               else
+                       AC_DEFINE_UNQUOTED([NETSNMPV54], $NETSNMP_NEW_SUPPORT, 
[have net-snmp5.4 over])
+               fi
+               LIBS=$savedLibs
+       fi
+
+       AC_MSG_CHECKING(for snmp)
+       AC_MSG_RESULT($enable_snmp)
+   if test $enable_snmp = no; then
+               enable_snmp=0
+               AC_MSG_ERROR(Unable to support SNMP)
+   else
+               enable_snmp=1
+               SNMP_LCRSO="snmp"
+               PACKAGE_FEATURES="$PACKAGE_FEATURES snmp"
+               AC_DEFINE_UNQUOTED([ENABLE_SNMP], $enable_snmp, [Build in 
support for sending SNMP traps])
+   fi
+else
+       enable_snmp=0
+fi
+AC_SUBST([SNMPLIBS])
+AC_SUBST([SNMP_LCRSO])
+AM_CONDITIONAL(BUILD_SNMP, test "${enable_snmp}" = "1")
+
 # extra warnings
 EXTRA_WARNINGS=""
 
Index: Makefile.am
===================================================================
--- Makefile.am (revision 2739)
+++ Makefile.am (working copy)
@@ -58,7 +58,7 @@
 endif
 
 SUBDIRS                        = include lcr lib exec services tools test cts 
pkgconfig \
-                         man init
+                         man init conf
 
 install-exec-local:
        $(INSTALL) -d $(DESTDIR)/${COROSYSCONFDIR}/service.d
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to