[Linux-ha-dev] [PATCH] Proposal SNMP subagent extention (revised)
Dejan Muhamedagic
dejanmm at fastmail.fm
Tue Dec 4 16:00:00 MST 2007
Hi,
On Tue, Dec 04, 2007 at 07:53:06PM +0900, Keisuke MORI wrote:
> Hi,
>
> I'm posting the updated version of the SNMP hbagent extension for V2.
>
> This patch is reflecting the comments from Andrew and Dejan.
> Thank you very much about that!
>
> The differences from the previous patch are:
>
> 1) Add three new fields in the MIB object as below:
> LHAResourceIsManaged: the managed status of a resource.
> LHAResourceFailcount: the fail-count value of a resource.
> LHAResourceParent: the name of the parent resource if present.
>
> 2) Add a simple check in SNMPAgentSanityCheck.in
> for the functionality provided by this patch.
>
> 3) Revise the code implementation details as advised by Dejan.
>
> 4) Based on the more recent -dev: f153a9be0bdf
>
>
> I would appreciate if there're any further comments and suggestions,
> particularly about the MIB definition.
Thanks again for the patch. I'll take a look and get back to you.
Cheers,
Dejan
> It is just good enough for our usage, but I would like to know
> if someone still needs more information in the SNMP MIB object
> to be implemented.
>
> See README in the attachment for details how the current MIB looks like.
>
>
> Regards,
>
> Keisuke MORI
> NTT DATA Intellilink Corporation
Content-Description: README_hbagentv2.txt
> SNMP Subagent Extention for CRM Resources
>
> 1. Introduction
>
> The purpose of this patch is to extend the SNMP subagent to get and
> receive a trap about the CRM resource information provided by
> Heartbeat Version 2.
>
> This patch introduces two new SNMP MIB objects.
>
> 1) LHAResourceTable: resources' name, type, on which node they are
> running, and their status. On the other words, you can get the
> information which is provided with crm_mon through the SNMP interface.
>
> 2) LHAResourceStatusUpdate: when a resource's status changes, you are
> notified with this SNMP trap.
>
> 2. Added MIB
>
> The following is the added MIB at this patch.
>
> ---------------------------------------------------------------------------
> | OID | Object Name | Value type | Description |
> ---------------------------------------------------------------------------
> |4682.8 | | LHAResourceTable | table | |
> ---------------------------------------------------------------------------
> | |.1 | LHAResourceEntry | | |
> ---------------------------------------------------------------------------
> | |.1.1 | LHAResourceIndex | Integer32 | |
> ---------------------------------------------------------------------------
> | |.1.2 | LHAResourceName | DisplayString | |
> ---------------------------------------------------------------------------
> | |.1.3 | LHAResourceType | INTEGER | unknown(0) |
> | | | | | primitive(1) |
> | | | | | group(2) |
> | | | | | clone(3) |
> | | | | | masterSlave(4) |
> ---------------------------------------------------------------------------
> | |.1.4 | LHAResourceNode | DisplayString | |
> ---------------------------------------------------------------------------
> | |.1.5 | LHAResourceStatus | INTEGER | unknown(0) |
> | | | | | stopped(1) |
> | | | | | started(2) |
> | | | | | slave(3) |
> | | | | | master(4) |
> ---------------------------------------------------------------------------
> | |.1.6 | LHAResourceIsManaged | INTEGER | unmanaged(0) |
> | | | | | managed(1) |
> ---------------------------------------------------------------------------
> | |.1.7 | LHAResourceFailcount | Integer32 | |
> ---------------------------------------------------------------------------
> | |.1.8 | LHAResourceParent | DisplayString | |
> ---------------------------------------------------------------------------
>
>
> NOTE : "master" status means "promoted", and "slave" means "demoted".
> All master/slave resources start up as slave at first, and until
> they are demoted or promoted explicitly, heartbeat only knows
> they "started".
> So, LHAResourceStatus's value is according to the crm_mon output.
> NOTE : For the present, you can get the information only about *running*
> resources or the resources that their values of fail-count are
> larger than 1. Because it's difficult to decide which node
> a resource *stopped* on...
>
> 3. Added Trap
>
> The following is the added Trap at this patch.
>
> ---------------------------------------------------------------------------
> | OID | Object Name | Value type | Description |
> ---------------------------------------------------------------------------
> |4682.900.8 | LHAResourceStatusUpdate | | |
> | |------------------------------------------------------------
> | | LHAResourceName | DisplayString | |
> | |------------------------------------------------------------
> | | LHAResourceNode | DisplayString | |
> | |------------------------------------------------------------
> | | LHAResourceStatus | INTEGER | 0 : unknown |
> | | | | 1 : stopped |
> | | | | 2 : started |
> | | | | 3 : slave |
> | | | | 4 : master |
> ---------------------------------------------------------------------------
>
> NOTE : This trap is sent only when the resource operation succeeds.
> Concretely, the extended hbagent gets the cib information when it
> changes, and parse it. And if the rc_code of the operation (like
> CRMD_ACTION_START) is "0", then the hbagent sends a trap.
>
> 4. Demo Output
>
> [root at u5node1 ~]# snmpwalk -v 1 \
> -c public localhost LINUX-HA-MIB::LHAResourceTable
> LINUX-HA-MIB::LHAResourceName.1 = STRING: group0
> LINUX-HA-MIB::LHAResourceName.2 = STRING: prmIp
> LINUX-HA-MIB::LHAResourceName.3 = STRING: prmApPostgreSQLDB
> LINUX-HA-MIB::LHAResourceName.4 = STRING: clone0
> LINUX-HA-MIB::LHAResourceName.5 = STRING: clone0
> LINUX-HA-MIB::LHAResourceName.6 = STRING: clone0-dummy:0
> LINUX-HA-MIB::LHAResourceName.7 = STRING: clone0-dummy:1
> LINUX-HA-MIB::LHAResourceName.8 = STRING: ms-sf
> LINUX-HA-MIB::LHAResourceName.9 = STRING: ms-sf
> LINUX-HA-MIB::LHAResourceName.10 = STRING: master_slave_Stateful:0
> LINUX-HA-MIB::LHAResourceName.11 = STRING: master_slave_Stateful:1
> LINUX-HA-MIB::LHAResourceType.1 = INTEGER: group(2)
> LINUX-HA-MIB::LHAResourceType.2 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceType.3 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceType.4 = INTEGER: clone(3)
> LINUX-HA-MIB::LHAResourceType.5 = INTEGER: clone(3)
> LINUX-HA-MIB::LHAResourceType.6 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceType.7 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceType.8 = INTEGER: masterSlave(4)
> LINUX-HA-MIB::LHAResourceType.9 = INTEGER: masterSlave(4)
> LINUX-HA-MIB::LHAResourceType.10 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceType.11 = INTEGER: primitive(1)
> LINUX-HA-MIB::LHAResourceNode.1 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.2 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.3 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.4 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.5 = STRING: u5node2
> LINUX-HA-MIB::LHAResourceNode.6 = STRING: u5node2
> LINUX-HA-MIB::LHAResourceNode.7 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.8 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceNode.9 = STRING: u5node2
> LINUX-HA-MIB::LHAResourceNode.10 = STRING: u5node2
> LINUX-HA-MIB::LHAResourceNode.11 = STRING: u5node1
> LINUX-HA-MIB::LHAResourceStatus.1 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.2 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.3 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.4 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.5 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.6 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.7 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.8 = INTEGER: master(4)
> LINUX-HA-MIB::LHAResourceStatus.9 = INTEGER: master(4)
> LINUX-HA-MIB::LHAResourceStatus.10 = INTEGER: started(2)
> LINUX-HA-MIB::LHAResourceStatus.11 = INTEGER: master(4)
> LINUX-HA-MIB::LHAResourceIsManaged.1 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.2 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.3 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.4 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.5 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.6 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.7 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.8 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.9 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.10 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceIsManaged.11 = INTEGER: managed(1)
> LINUX-HA-MIB::LHAResourceFailCount.1 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.2 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.3 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.4 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.5 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.6 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.7 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.8 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.9 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.10 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceFailCount.11 = INTEGER: 0
> LINUX-HA-MIB::LHAResourceParent.1 = STRING:
> LINUX-HA-MIB::LHAResourceParent.2 = STRING: group0
> LINUX-HA-MIB::LHAResourceParent.3 = STRING: group0
> LINUX-HA-MIB::LHAResourceParent.4 = STRING:
> LINUX-HA-MIB::LHAResourceParent.5 = STRING:
> LINUX-HA-MIB::LHAResourceParent.6 = STRING: clone0
> LINUX-HA-MIB::LHAResourceParent.7 = STRING: clone0
> LINUX-HA-MIB::LHAResourceParent.8 = STRING:
> LINUX-HA-MIB::LHAResourceParent.9 = STRING:
> LINUX-HA-MIB::LHAResourceParent.10 = STRING: ms-sf
> LINUX-HA-MIB::LHAResourceParent.11 = STRING: ms-sf
>
> cf.) Then crm_mon's output is...
>
> ============
> Last updated: Mon Dec 3 17:39:27 2007
> Current DC: u5node2 (7e035df7-607d-42b4-a1e7-e8d9db108e6c)
> 2 Nodes configured.
> 3 Resources configured.
> ============
>
> Node: u5node1 (77b7c7b1-68ba-4542-9f10-b75de73e9ffd): online
> Node: u5node2 (7e035df7-607d-42b4-a1e7-e8d9db108e6c): online
>
> Resource Group: group0
> prmIp (heartbeat::ocf:IPaddr): Started u5node1
> prmApPostgreSQLDB (heartbeat::ocf:pgsql): Started u5node1
> Clone Set: clone0
> clone0-dummy:0 (heartbeat::ocf:Dummy): Started u5node2
> clone0-dummy:1 (heartbeat::ocf:Dummy): Started u5node1
> Master/Slave Set: ms-sf
> master_slave_Stateful:0 (heartbeat::ocf:Stateful): Started u5node2
> master_slave_Stateful:1 (heartbeat::ocf:Stateful): Master u5node1
>
>
> Sample SNMP traps
>
> Dec 3 17:38:31 manager_node snmptrapd[1343]: 2007-12-03 17:38:31 u5node2 [
> 192.168.70.129]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (22408) 0
> :03:44.08 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: master_slave_Stateful:0 LI
> NUX-HA-MIB::LHAResourceNode = STRING: u5node2 LINUX-HA-MIB::LHAResourceStat
> us = INTEGER: started(2)
> Dec 3 17:38:31 manager_node snmptrapd[1343]: 2007-12-03 17:38:31 u5node2 [
> 192.168.70.129]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (22420) 0
> :03:44.20 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: clone0-dummy:0 LINUX-HA-M
> IB::LHAResourceNode = STRING: u5node2 LINUX-HA-MIB::LHAResourceStatus = INT
> EGER: started(2)
> Dec 3 17:38:32 manager_node snmptrapd[1343]: 2007-12-03 17:38:32 u5node1 [
> 192.168.70.128]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (19126) 0
> :03:11.26 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: clone0-dummy:1 LINUX-HA-M
> IB::LHAResourceNode = STRING: u5node1 LINUX-HA-MIB::LHAResourceStatus = INT
> EGER: started(2)
> Dec 3 17:38:32 manager_node snmptrapd[1343]: 2007-12-03 17:38:32 u5node1 [
> 192.168.70.128]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (19129) 0
> :03:11.29 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: master_slave_Stateful:1 LI
> NUX-HA-MIB::LHAResourceNode = STRING: u5node1 LINUX-HA-MIB::LHAResourceStat
> us = INTEGER: started(2)
> Dec 3 17:38:34 manager_node snmptrapd[1343]: 2007-12-03 17:38:34 u5node1 [
> 192.168.70.128]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (19314) 0
> :03:13.14 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: master_slave_Stateful:1 LI
> NUX-HA-MIB::LHAResourceNode = STRING: u5node1 LINUX-HA-MIB::LHAResourceStat
> us = INTEGER: master(4)
> Dec 3 17:38:36 manager_node snmptrapd[1343]: 2007-12-03 17:38:36 u5node1 [
> 192.168.70.128]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (19516) 0
> :03:15.16 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: prmIp LINUX-HA-MIB::LHAR
> esourceNode = STRING: u5node1 LINUX-HA-MIB::LHAResourceStatus = INTEGER: st
> arted(2)
> Dec 3 17:38:42 manager_node snmptrapd[1343]: 2007-12-03 17:38:42 u5node1 [
> 192.168.70.128]: DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (20067) 0
> :03:20.67 SNMPv2-MIB::snmpTrapOID.0 = OID: LINUX-HA-MIB::LHAResourceStatu
> sUpdate LINUX-HA-MIB::LHAResourceName = STRING: prmApPostgreSQLDB LI
> NUX-HA-MIB::LHAResourceNode = STRING: u5node1 LINUX-HA-MIB::LHAResourceStat
> us = INTEGER: started(2)
>
> 5. Other changes
>
> This patch modifies the following too.
> 1) Make SNMP_CACHE_TIME_OUT variable.
> apply the value which is specified with -r option.
> 2) Fix some memory leaks.
> debug with valgrind.
> 3) Update SNMPAgentSanityCheck to keep up with the new functionality.
Content-Description: hbagent_v2resource.patch
> diff -urN org/snmp_subagent/LHAIFStatusTable.c mod/snmp_subagent/LHAIFStatusTable.c
> --- org/snmp_subagent/LHAIFStatusTable.c 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/LHAIFStatusTable.c 2007-11-21 10:19:55.000000000 +0900
> @@ -50,6 +50,7 @@
> #include "hbagent.h"
>
> static GPtrArray * gIFInfo = NULL;
> +extern const int snmp_cache_time_out;
>
> int LHAIFStatusTable_load(netsnmp_cache *cache, void *vmagic);
> void LHAIFStatusTable_free(netsnmp_cache *cache, void *vmagic);
> @@ -123,7 +124,7 @@
> * .... with a local cache
> */
> netsnmp_inject_handler(my_handler,
> - netsnmp_get_cache_handler(CACHE_TIME_OUT,
> + netsnmp_get_cache_handler(snmp_cache_time_out,
> LHAIFStatusTable_load,
> LHAIFStatusTable_free,
> LHAIFStatusTable_oid,
> diff -urN org/snmp_subagent/LHAMembershipTable.c mod/snmp_subagent/LHAMembershipTable.c
> --- org/snmp_subagent/LHAMembershipTable.c 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/LHAMembershipTable.c 2007-11-21 10:20:00.000000000 +0900
> @@ -50,6 +50,7 @@
> #include "hbagent.h"
>
> static GPtrArray * gMembershipInfo = NULL;
> +extern const int snmp_cache_time_out;
>
> int LHAMembershipTable_load(netsnmp_cache *cache, void *vmagic);
> void LHAMembershipTable_free(netsnmp_cache *cache, void *vmagic);
> @@ -112,7 +113,7 @@
> * .... with a local cache
> */
> netsnmp_inject_handler(my_handler,
> - netsnmp_get_cache_handler(CACHE_TIME_OUT,
> + netsnmp_get_cache_handler(snmp_cache_time_out,
> LHAMembershipTable_load,
> LHAMembershipTable_free,
> LHAMembershipTable_oid,
> diff -urN org/snmp_subagent/LHANodeTable.c mod/snmp_subagent/LHANodeTable.c
> --- org/snmp_subagent/LHANodeTable.c 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/LHANodeTable.c 2007-11-21 10:20:05.000000000 +0900
> @@ -50,6 +50,7 @@
> #include "hbagent.h"
>
> static GPtrArray * gNodeInfo = NULL;
> +extern const int snmp_cache_time_out;
>
> int LHANodeTable_load(netsnmp_cache *cache, void *vmagic);
> void LHANodeTable_free(netsnmp_cache *cache, void *vmagic);
> @@ -113,7 +114,7 @@
> * .... with a local cache
> */
> netsnmp_inject_handler(my_handler,
> - netsnmp_get_cache_handler(CACHE_TIME_OUT,
> + netsnmp_get_cache_handler(snmp_cache_time_out,
> LHANodeTable_load,
> LHANodeTable_free,
> LHANodeTable_oid,
> diff -urN org/snmp_subagent/LHAResourceGroupTable.c mod/snmp_subagent/LHAResourceGroupTable.c
> --- org/snmp_subagent/LHAResourceGroupTable.c 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceGroupTable.c 2007-11-21 10:20:17.000000000 +0900
> @@ -50,6 +50,7 @@
> #include "hbagent.h"
>
> static GPtrArray * gResourceGroupInfo = NULL;
> +extern const int snmp_cache_time_out;
>
> int LHAResourceGroupTable_load(netsnmp_cache *cache, void *vmagic);
> void LHAResourceGroupTable_free(netsnmp_cache *cache, void *vmagic);
> @@ -122,7 +123,7 @@
> * .... with a local cache
> */
> netsnmp_inject_handler(my_handler,
> - netsnmp_get_cache_handler(CACHE_TIME_OUT,
> + netsnmp_get_cache_handler(snmp_cache_time_out,
> LHAResourceGroupTable_load,
> LHAResourceGroupTable_free,
> LHAResourceGroupTable_oid,
> diff -urN org/snmp_subagent/LHAResourceStatusUpdate.c mod/snmp_subagent/LHAResourceStatusUpdate.c
> --- org/snmp_subagent/LHAResourceStatusUpdate.c 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceStatusUpdate.c 2007-11-20 10:07:36.000000000 +0900
> @@ -0,0 +1,85 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.notify.conf,v 5.2.2.1 2004/04/15 12:29:06 dts12 Exp $
> + */
> +#include <lha_internal.h>
> +
> +#include "hbagent.h"
> +#include "hbagentv2.h"
> +
> +#include <net-snmp/net-snmp-config.h>
> +#include <net-snmp/net-snmp-includes.h>
> +#include <net-snmp/agent/net-snmp-agent-includes.h>
> +#include "LHAResourceStatusUpdate.h"
> +
> +
> +
> +static oid snmptrap_oid[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
> +
> +int
> +send_LHAResourceStatusUpdate_trap(struct hb_rsinfov2 *resource)
> +{
> + netsnmp_variable_list *var_list = NULL;
> + oid LHAResourceStatusUpdate_oid[] =
> + { 1, 3, 6, 1, 4, 1, 4682, 900, 11 };
> + oid LHAResourceName_oid[] =
> + { 1, 3, 6, 1, 4, 1, 4682, 8, 1, 2, /* insert index here */ };
> + oid LHAResourceNode_oid[] =
> + { 1, 3, 6, 1, 4, 1, 4682, 8, 1, 4, /* insert index here */ };
> + oid LHAResourceStatus_oid[] =
> + { 1, 3, 6, 1, 4, 1, 4682, 8, 1, 5, /* insert index here */ };
> +
> +
> + /*
> + * Set the snmpTrapOid.0 value
> + */
> + snmp_varlist_add_variable(&var_list,
> + snmptrap_oid, OID_LENGTH(snmptrap_oid),
> + ASN_OBJECT_ID,
> + (u_char *)LHAResourceStatusUpdate_oid,
> + sizeof(LHAResourceStatusUpdate_oid));
> +
> + /*
> + * Add any objects from the trap definition
> + */
> + snmp_varlist_add_variable(&var_list,
> + LHAResourceName_oid,
> + OID_LENGTH(LHAResourceName_oid),
> + ASN_OCTET_STR,
> + /*
> + * Set an appropriate value for LHAResourceName
> + */
> + (u_char *)resource->resourceid,
> + strlen(resource->resourceid));
> + snmp_varlist_add_variable(&var_list,
> + LHAResourceNode_oid,
> + OID_LENGTH(LHAResourceNode_oid),
> + ASN_OCTET_STR,
> + /*
> + * Set an appropriate value for LHAResourceNode
> + */
> + (u_char *)resource->node,
> + strlen(resource->node));
> + snmp_varlist_add_variable(&var_list,
> + LHAResourceStatus_oid,
> + OID_LENGTH(LHAResourceStatus_oid),
> + ASN_INTEGER,
> + /*
> + * Set an appropriate value for LHAResourceStatus
> + */
> + (u_char *)&(resource->status),
> + sizeof(resource->status));
> +
> + /*
> + * Add any extra (optional) objects here
> + */
> +
> + /*
> + * Send the trap to the list of configured destinations
> + * and clean up
> + */
> + send_v2trap(var_list);
> + snmp_free_varbind(var_list);
> +
> + return SNMP_ERR_NOERROR;
> +}
> diff -urN org/snmp_subagent/LHAResourceStatusUpdate.h mod/snmp_subagent/LHAResourceStatusUpdate.h
> --- org/snmp_subagent/LHAResourceStatusUpdate.h 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceStatusUpdate.h 2007-11-20 10:07:36.000000000 +0900
> @@ -0,0 +1,14 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.notify.conf,v 5.2.2.1 2004/04/15 12:29:06 dts12 Exp $
> + */
> +#ifndef LHARESOURCESTATUSUPDATE_H
> +#define LHARESOURCESTATUSUPDATE_H
> +
> +
> +/*
> + * function declarations
> + */
> +int send_LHAResourceStatusUpdate_trap(struct hb_rsinfov2 *resource);
> +
> +#endif /* LHARESOURCESTATUSUPDATE_H */
> diff -urN org/snmp_subagent/LHAResourceTable.c mod/snmp_subagent/LHAResourceTable.c
> --- org/snmp_subagent/LHAResourceTable.c 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceTable.c 2007-11-26 18:25:05.000000000 +0900
> @@ -0,0 +1,343 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.iterate.conf,v 5.9 2003/06/04 00:14:41 hardaker Exp $
> + */
> +
> +#include <lha_internal.h>
> +
> +
> +#include <net-snmp/net-snmp-config.h>
> +#include <net-snmp/net-snmp-includes.h>
> +#include <net-snmp/agent/net-snmp-agent-includes.h>
> +#include "LHAResourceTable.h"
> +
> +#include "hbagent.h"
> +#include "hbagentv2.h"
> +#include "hb_api.h"
> +/*#include "heartbeat.h"*/
> +/*#include "clplumbing/cl_log.h"*/
> +
> +static GPtrArray * gResourceTableV2 = NULL;
> +extern const int snmp_cache_time_out;
> +
> +static int LHAResourceTable_load(netsnmp_cache *cache, void *vmagic);
> +static void LHAResourceTable_free(netsnmp_cache *cache, void *vmagic);
> +
> +/** Initialize the LHAResourceTable table by defining its contents and how it's structured */
> +void
> +initialize_table_LHAResourceTable(void)
> +{
> + static oid LHAResourceTable_oid[] = { 1, 3, 6, 1, 4, 1, 4682, 8 };
> + netsnmp_table_registration_info *table_info;
> + netsnmp_handler_registration *my_handler;
> + netsnmp_iterator_info *iinfo;
> +
> + /** create the table registration information structures */
> + table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
> + iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
> +
> + /** if your table is read only, it's easiest to change the
> + HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
> + my_handler = netsnmp_create_handler_registration("LHAResourceTable",
> + LHAResourceTable_handler,
> + LHAResourceTable_oid,
> + OID_LENGTH
> + (LHAResourceTable_oid),
> + HANDLER_CAN_RONLY);
> +
> + if (!my_handler || !table_info || !iinfo) {
> + snmp_log(LOG_ERR,
> + "malloc failed in initialize_table_LHAResourceTable");
> + SNMP_FREE(iinfo);
> + SNMP_FREE(table_info);
> + return; /* Serious error. */
> + }
> +
> + /***************************************************
> + * Setting up the table's definition
> + */
> + netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER, /* index: LHAResourceIndex */
> + 0);
> +
> + /** Define the minimum and maximum accessible columns. This
> + optimizes retrival. */
> + table_info->min_column = 2;
> + table_info->max_column = 8;
> +
> + /*
> + * iterator access routines
> + */
> + iinfo->get_first_data_point = LHAResourceTable_get_first_data_point;
> + iinfo->get_next_data_point = LHAResourceTable_get_next_data_point;
> +
> + /** you may wish to set these as well */
> +#ifdef MAYBE_USE_THESE
> + iinfo->make_data_context = LHAResourceTable_context_convert_function;
> + iinfo->free_data_context = LHAResourceTable_data_free;
> +
> + /** pick *only* one of these if you use them */
> + iinfo->free_loop_context = LHAResourceTable_loop_free;
> + iinfo->free_loop_context_at_end = LHAResourceTable_loop_free;
> +#endif
> +
> + /** tie the two structures together */
> + iinfo->table_reginfo = table_info;
> +
> + /***************************************************
> + * registering the table with the master agent
> + */
> + DEBUGMSGTL(("initialize_table_LHAResourceTable",
> + "Registering table LHAResourceTable as a table iterator\n"));
> + netsnmp_register_table_iterator(my_handler, iinfo);
> +
> + /*
> + * enable local cache
> + */
> + netsnmp_inject_handler(my_handler,
> + netsnmp_get_cache_handler(snmp_cache_time_out,
> + LHAResourceTable_load,
> + LHAResourceTable_free,
> + LHAResourceTable_oid,
> + OID_LENGTH
> + (LHAResourceTable_oid)));
> +
> +
> + snmp_log(LOG_INFO,
> + "LHAResourceTable initialization completed.\n");
> +}
> +
> +/** Initializes the LHAResourceTable module */
> +void
> +init_LHAResourceTable(void)
> +{
> +
> + /** here we initialize all the tables we're planning on supporting */
> + initialize_table_LHAResourceTable();
> +}
> +
> +/** returns the first data point within the LHAResourceTable table data.
> +
> + Set the my_loop_context variable to the first data point structure
> + of your choice (from which you can find the next one). This could
> + be anything from the first node in a linked list, to an integer
> + pointer containing the beginning of an array variable.
> +
> + Set the my_data_context variable to something to be returned to
> + you later (in your main LHAResourceTable_handler routine) that will provide
> + you with the data to return in a given row. This could be the
> + same pointer as what my_loop_context is set to, or something
> + different.
> +
> + The put_index_data variable contains a list of snmp variable
> + bindings, one for each index in your table. Set the values of
> + each appropriately according to the data matching the first row
> + and return the put_index_data variable at the end of the function.
> +*/
> +netsnmp_variable_list *
> +LHAResourceTable_get_first_data_point(void **my_loop_context,
> + void **my_data_context,
> + netsnmp_variable_list *
> + put_index_data,
> + netsnmp_iterator_info *mydata)
> +{
> + if (gResourceTableV2 && gResourceTableV2->len == 0) {
> + return NULL;
> + }
> +
> + *my_loop_context = NULL;
> + return LHAResourceTable_get_next_data_point(my_loop_context,
> + my_data_context,
> + put_index_data,
> + mydata);
> +}
> +
> +/** functionally the same as LHAResourceTable_get_first_data_point, but
> + my_loop_context has already been set to a previous value and should
> + be updated to the next in the list. For example, if it was a
> + linked list, you might want to cast it to your local data type and
> + then return my_loop_context->next. The my_data_context pointer
> + should be set to something you need later (in your main
> + LHAResourceTable_handler routine) and the indexes in put_index_data updated
> + again. */
> +netsnmp_variable_list *
> +LHAResourceTable_get_next_data_point(void **my_loop_context,
> + void **my_data_context,
> + netsnmp_variable_list *
> + put_index_data,
> + netsnmp_iterator_info *mydata)
> +{
> + static size_t i = 0;
> + netsnmp_variable_list *vptr;
> + struct hb_rsinfov2 *info;
> +
> + if (*my_loop_context != NULL) {
> + i = *((size_t *) *my_loop_context);
> + } else {
> + i = 0;
> + }
> +
> + if (!gResourceTableV2 || i >= gResourceTableV2->len) {
> + return NULL;
> + }
> +
> + vptr = put_index_data;
> + info = (struct hb_rsinfov2 *)g_ptr_array_index(gResourceTableV2, i);
> +
> + snmp_set_var_value(vptr, (u_char *)&info->index, sizeof(size_t));
> + vptr = vptr->next_variable;
> +
> + i++;
> + *my_loop_context = (void *)&i;
> + *my_data_context = (void *)info;
> +
> + return put_index_data;
> +}
> +
> +/** handles requests for the LHAResourceTable table, if anything else needs to be done */
> +int
> +LHAResourceTable_handler(netsnmp_mib_handler *handler,
> + netsnmp_handler_registration *reginfo,
> + netsnmp_agent_request_info *reqinfo,
> + netsnmp_request_info *requests)
> +{
> +
> + netsnmp_request_info *request;
> + netsnmp_table_request_info *table_info;
> + netsnmp_variable_list *var;
> +
> + struct hb_rsinfov2 *entry;
> +
> + for (request = requests; request; request = request->next) {
> + var = request->requestvb;
> + if (request->processed != 0)
> + continue;
> +
> + /** perform anything here that you need to do before each
> + request is processed. */
> +
> + /** the following extracts the my_data_context pointer set in
> + the loop functions above. You can then use the results to
> + help return data for the columns of the LHAResourceTable table in question */
> + entry =
> + (struct hb_rsinfov2 *)netsnmp_extract_iterator_context(request);
> + if (entry == NULL) {
> + if (reqinfo->mode == MODE_GET) {
> + netsnmp_set_request_error(reqinfo, request,
> + SNMP_NOSUCHINSTANCE);
> + continue;
> + }
> + /** XXX: no row existed, if you support creation and this is a
> + set, start dealing with it here, else continue */
> + }
> +
> + /** extracts the information about the table from the request */
> + table_info = netsnmp_extract_table_info(request);
> + /** table_info->colnum contains the column number requested */
> + /** table_info->indexes contains a linked list of snmp variable
> + bindings for the indexes of the table. Values in the list
> + have been set corresponding to the indexes of the
> + request */
> + if (table_info == NULL) {
> + continue;
> + }
> +
> + switch (reqinfo->mode) {
> + /** the table_iterator helper should change all GETNEXTs
> + into GETs for you automatically, so you don't have to
> + worry about the GETNEXT case. Only GETs and SETs need
> + to be dealt with here */
> + case MODE_GET:
> + switch (table_info->colnum) {
> + case COLUMN_LHARESOURCENAME:
> + snmp_set_var_typed_value(var, ASN_OCTET_STR,
> + (u_char *)entry->resourceid,
> + strlen(entry->resourceid) + 1
> + );
> + break;
> +
> + case COLUMN_LHARESOURCETYPE:
> + snmp_set_var_typed_value(var, ASN_INTEGER,
> + (u_char *)&entry->type,
> + sizeof(entry->type)
> + );
> + break;
> +
> + case COLUMN_LHARESOURCESTATUS:
> + snmp_set_var_typed_value(var, ASN_INTEGER,
> + (u_char *)&entry->status,
> + sizeof(entry->status)
> + );
> + break;
> +
> + case COLUMN_LHARESOURCENODE:
> + snmp_set_var_typed_value(var, ASN_OCTET_STR,
> + (u_char *)entry->node,
> + strlen(entry->node) + 1
> + );
> + break;
> +
> + case COLUMN_LHARESOURCEISMANAGED:
> + snmp_set_var_typed_value(var, ASN_INTEGER,
> + (u_char *)&entry->is_managed,
> + sizeof(entry->is_managed)
> + );
> + break;
> +
> + case COLUMN_LHARESOURCEFAILCOUNT:
> + snmp_set_var_typed_value(var, ASN_INTEGER,
> + (u_char *)&entry->failcount,
> + sizeof(entry->failcount)
> + );
> + break;
> +
> + case COLUMN_LHARESOURCEPARENT:
> + snmp_set_var_typed_value(var, ASN_OCTET_STR,
> + (u_char *)entry->parent,
> + strlen(entry->parent) + 1
> + );
> + break;
> +
> + default:
> + /** We shouldn't get here */
> + snmp_log(LOG_ERR,
> + "problem encountered in LHAResourceTable_handler: unknown column\n");
> + }
> + break;
> +
> + case MODE_SET_RESERVE1:
> + /** set handling... */
> +
> + default:
> + snmp_log(LOG_ERR,
> + "problem encountered in LHAResourceTable_handler: unsupported mode\n");
> + }
> + }
> + return SNMP_ERR_NOERROR;
> +}
> +
> +static int LHAResourceTable_load(netsnmp_cache *cache, void *vmagic)
> +{
> + LHAResourceTable_free(cache, vmagic);
> +
> + gResourceTableV2 = get_resource_table_v2();
> +
> + return 0;
> +}
> +
> +static void LHAResourceTable_free(netsnmp_cache *cache, void *vmagic)
> +{
> + /* do nothing. */
> + return;
> +}
> +
> +
> +
> +/**
> + * Emacs stuff:
> + * Local Variables:
> + * mode: C
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + *
> + */
> diff -urN org/snmp_subagent/LHAResourceTable.h mod/snmp_subagent/LHAResourceTable.h
> --- org/snmp_subagent/LHAResourceTable.h 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceTable.h 2007-11-20 10:07:36.000000000 +0900
> @@ -0,0 +1,28 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.iterate.conf,v 5.9 2003/06/04 00:14:41 hardaker Exp $
> + */
> +#ifndef LHARESOURCETABLE_H
> +#define LHARESOURCETABLE_H
> +
> +/*
> + * function declarations
> + */
> +void init_LHAResourceTable(void);
> +void initialize_table_LHAResourceTable(void);
> +Netsnmp_Node_Handler LHAResourceTable_handler;
> +
> +Netsnmp_First_Data_Point LHAResourceTable_get_first_data_point;
> +Netsnmp_Next_Data_Point LHAResourceTable_get_next_data_point;
> +
> +/*
> + * column number definitions for table LHAResourceTable
> + */
> +#include "LHAResourceTable_columns.h"
> +
> +/*
> + * enum definions
> + */
> +#include "LHAResourceTable_enums.h"
> +
> +#endif /* LHARESOURCETABLE_H */
> diff -urN org/snmp_subagent/LHAResourceTable_columns.h mod/snmp_subagent/LHAResourceTable_columns.h
> --- org/snmp_subagent/LHAResourceTable_columns.h 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceTable_columns.h 2007-11-26 18:01:20.000000000 +0900
> @@ -0,0 +1,19 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.column_defines.conf,v 5.1 2002/05/08 05:42:47 hardaker Exp $
> + */
> +#ifndef LHARESOURCETABLE_COLUMNS_H
> +#define LHARESOURCETABLE_COLUMNS_H
> +
> +/*
> + * column number definitions for table LHAResourceTable
> + */
> +#define COLUMN_LHARESOURCEINDEX 1
> +#define COLUMN_LHARESOURCENAME 2
> +#define COLUMN_LHARESOURCETYPE 3
> +#define COLUMN_LHARESOURCENODE 4
> +#define COLUMN_LHARESOURCESTATUS 5
> +#define COLUMN_LHARESOURCEISMANAGED 6
> +#define COLUMN_LHARESOURCEFAILCOUNT 7
> +#define COLUMN_LHARESOURCEPARENT 8
> +#endif /* LHARESOURCETABLE_COLUMNS_H */
> diff -urN org/snmp_subagent/LHAResourceTable_enums.h mod/snmp_subagent/LHAResourceTable_enums.h
> --- org/snmp_subagent/LHAResourceTable_enums.h 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/LHAResourceTable_enums.h 2007-11-27 18:32:49.000000000 +0900
> @@ -0,0 +1,32 @@
> +/*
> + * Note: this file originally auto-generated by mib2c using
> + * : mib2c.column_enums.conf,v 5.2 2003/02/22 04:09:25 hardaker Exp $
> + */
> +#ifndef LHARESOURCETABLE_ENUMS_H
> +#define LHARESOURCETABLE_ENUMS_H
> +
> +/*
> + * enums for column LHAResourceType
> + */
> +#define LHARESOURCETYPE_UNKNOWN 0
> +#define LHARESOURCETYPE_PRIMITIVE 1
> +#define LHARESOURCETYPE_GROUP 2
> +#define LHARESOURCETYPE_CLONE 3
> +#define LHARESOURCETYPE_MASTERSLAVE 4
> +
> +/*
> + * enums for column LHAResourceStatus
> + */
> +#define LHARESOURCESTATUS_UNKNOWN 0
> +#define LHARESOURCESTATUS_STOPPED 1
> +#define LHARESOURCESTATUS_STARTED 2
> +#define LHARESOURCESTATUS_SLAVE 3
> +#define LHARESOURCESTATUS_MASTER 4
> +
> +/*
> + * enums for column LHAResourceIsManaged
> + */
> +#define LHARESOURCEISMANAGED_UNMANAGED 0
> +#define LHARESOURCEISMANAGED_MANAGED 1
> +
> +#endif /* LHARESOURCETABLE_ENUMS_H */
> diff -urN org/snmp_subagent/LINUX-HA-MIB.mib mod/snmp_subagent/LINUX-HA-MIB.mib
> --- org/snmp_subagent/LINUX-HA-MIB.mib 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/LINUX-HA-MIB.mib 2007-12-03 16:58:46.000000000 +0900
> @@ -32,7 +32,7 @@
> FROM SNMPv2-CONF;
>
> LinuxHA MODULE-IDENTITY
> - LAST-UPDATED "200211040000Z" -- Nov. 4, 2002
> + LAST-UPDATED "200711260000Z" -- Nov. 26, 2007
> ORGANIZATION "High-Availability Linux Project"
> CONTACT-INFO
> "Alan Robertson
> @@ -64,7 +64,7 @@
> and memberships accessible through SNMP. Hopefully more
> things can be added as Linux-HA matures."
>
> - REVISION "200211040000Z" -- Nov. 4, 2002
> + REVISION "200711260000Z" -- Nov. 26, 2007
> DESCRIPTION
> "The original version of this MIB."
> ::= { enterprises 4682 }
> @@ -76,6 +76,7 @@
> -- LHAResourceGroupTable OBJECT IDENTIFIER ::= { LinuxHA 4 }
> -- LHAMembershipTable OBJECT IDENTIFIER ::= { LinuxHA 6 }
> -- LHAHeartbeatConfigInfo OBJECT IDENTIFIER ::= { LinuxHA 7 }
> +-- LHAResourceTable OBJECT IDENTIFIER ::= { LinuxHA 8 }
> -- LHATrapTable OBJECT IDENTIFIER ::= { LinuxHA 900 }
>
> LHAUUIDString ::= TEXTUAL-CONVENTION
> @@ -541,6 +542,128 @@
> "The other services that got respawned by heartbeat daemon."
> ::= { LHAHeartbeatConfigInfo 15 }
>
> +LHAResourceTable OBJECT-TYPE
> + SYNTAX SEQUENCE OF lhaResourceEntry
> + MAX-ACCESS not-accessible
> + STATUS current
> + DESCRIPTION
> + "A table containing information of all the resource for V2."
> + ::= { LinuxHA 8 }
> +
> +LHAResourceEntry OBJECT-TYPE
> + SYNTAX lhaResourceEntry
> + MAX-ACCESS not-accessible
> + STATUS current
> + DESCRIPTION
> + "An entry that describes the resource and its status for V2."
> + INDEX { LHAResourceIndex }
> + ::= { LHAResourceTable 1 }
> +
> +lhaResourceEntry ::= SEQUENCE {
> + LHAResourceIndex Integer32,
> + LHAResourceName DisplayString,
> + LHAResourceType INTEGER,
> + LHAResourceNode DisplayString,
> + LHAResourceStatus INTEGER,
> + LHAResourceIsManaged INTEGER,
> + LHAResourceFailCount Integer32,
> + LHAResourceParent DisplayString,
> +}
> +
> +LHAResourceIndex OBJECT-TYPE
> + SYNTAX Integer32 (0..65535)
> + MAX-ACCESS not-accessible
> + STATUS current
> + DESCRIPTION
> + "A unique integer that identifies this resource."
> + ::= { LHAResourceEntry 1 }
> +
> +LHAResourceName OBJECT-TYPE
> + SYNTAX DisplayString
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The name of this resource."
> + ::= { LHAResourceEntry 2 }
> +
> +LHAResourceType OBJECT-TYPE
> + SYNTAX INTEGER {
> + unknown (0),
> + primitive (1),
> + group (2),
> + clone (3),
> + masterSlave (4)
> + }
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The type of this resource.
> + 0 unknown type
> + 1 primitive resource.
> + 2 group resource.
> + 3 clone resource.
> + 4 master/slave resource.
> + "
> + ::= { LHAResourceEntry 3 }
> +
> +LHAResourceNode OBJECT-TYPE
> + SYNTAX DisplayString
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The node name that this resource resides on."
> + ::= { LHAResourceEntry 4 }
> +
> +LHAResourceStatus OBJECT-TYPE
> + SYNTAX INTEGER {
> + unknown (0),
> + stopped (1),
> + started (2),
> + slave (3),
> + master (4)
> + }
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The status of this resource.
> + 0 unknown status
> + 1 program is stopped.
> + 2 program is started.
> + 3 program is started in slave state.
> + 4 program is started in master state.
> + "
> + ::= { LHAResourceEntry 5 }
> +
> +LHAResourceIsManaged OBJECT-TYPE
> + SYNTAX INTEGER {
> + unmanaged (0),
> + managed (1)
> + }
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The status of this resource.
> + 0 resource is not managed.
> + 1 resource is managed.
> + "
> + ::= { LHAResourceEntry 6 }
> +
> +LHAResourceFailCount OBJECT-TYPE
> + SYNTAX Integer32 (0..65535)
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The value of this resource's fail-count."
> + ::= { LHAResourceEntry 7 }
> +
> +LHAResourceParent OBJECT-TYPE
> + SYNTAX DisplayString
> + MAX-ACCESS read-only
> + STATUS current
> + DESCRIPTION
> + "The name of this resource's parent resource."
> + ::= { LHAResourceEntry 8 }
> +
> LHATrapTable OBJECT IDENTIFIER ::= { LinuxHA 900 }
>
> LHANodeStatusUpdate NOTIFICATION-TYPE
> @@ -578,4 +701,11 @@
> "The heartbeat agent for this node is offline. "
> ::= { LHATrapTable 9 }
>
> +LHAResourceStatusUpdate NOTIFICATION-TYPE
> + OBJECTS { LHAResourceName LHAResourceNode LHAResourceStatus }
> + STATUS current
> + DESCRIPTION
> + "A resource status change event just happened."
> + ::= { LHATrapTable 11 }
> +
> END
> diff -urN org/snmp_subagent/Makefile.am mod/snmp_subagent/Makefile.am
> --- org/snmp_subagent/Makefile.am 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/Makefile.am 2007-11-20 10:07:36.000000000 +0900
> @@ -22,6 +22,8 @@
> hbagent_srces = snmp-config-resolve.h \
> hbagent.h \
> hbagent.c \
> + hbagentv2.h \
> + hbagentv2.c \
> LHANodeTable.h \
> LHANodeTable_columns.h \
> LHANodeTable_enums.h \
> @@ -41,7 +43,13 @@
> LHAResourceGroupTable_columns.h \
> LHAResourceGroupTable_enums.h \
> LHAResourceGroupTable.h \
> - LHAResourceGroupTable.c
> + LHAResourceGroupTable.c \
> + LHAResourceTable_columns.h \
> + LHAResourceTable_enums.h \
> + LHAResourceTable.h \
> + LHAResourceTable.c \
> + LHAResourceStatusUpdate.h \
> + LHAResourceStatusUpdate.c
>
> test_scrs = SNMPAgentSanityCheck
>
> @@ -69,8 +77,12 @@
> hbagent_LDADD = \
> $(top_builddir)/lib/clplumbing/libplumb.la \
> $(top_builddir)/lib/hbclient/libhbclient.la \
> + $(top_builddir)/lib/crm/common/libcrmcommon.la \
> + $(top_builddir)/lib/crm/cib/libcib.la \
> + $(top_builddir)/lib//crm/pengine/libpe_status.la \
> $(top_builddir)/membership/ccm/libccmclient.la \
> $(top_builddir)/membership/ccm/libclm.la \
> + $(CURSESLIBS) \
> $(GLIBLIB)
>
> hbagent_LDFLAGS = @SNMPAGENTLIB@
> diff -urN org/snmp_subagent/SNMPAgentSanityCheck.in mod/snmp_subagent/SNMPAgentSanityCheck.in
> --- org/snmp_subagent/SNMPAgentSanityCheck.in 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/SNMPAgentSanityCheck.in 2007-11-26 09:41:14.000000000 +0900
> @@ -59,7 +59,7 @@
>
> # start the linux-ha snmp subagent
> @libdir@/heartbeat/hbagent -d &
> -sleep 1
> +sleep 5
>
> # get the nodename for node0 and node1
> # node0 should be the value of the localhost
> @@ -96,11 +96,81 @@
>
> if test $ret2 = 0; then
> echo "BasicSanityCheck for SNMP Subagent passed."
> - exit 0
> +# exit 0
> else
> echo "BasicSanityCheck for SNMP Subagent failed."
> +# exit 1
> +fi
> +
> +#
> +# BasicSanityCheck for SNMP Subagent about CRM resources.
> +#
> +# NOTE: Heartbeat service for this test has to run without cib.xml.
> +
> +# add CRM resource.
> +RSC0NAME="prmDummy"
> +RSC0TYPE="primitive(1)"
> +RSC0NODE="$NODE0"
> +RSC0STATUS="started(2)"
> +cibadmin --cib_create -o resources \
> + -X '<primitive id="prmDummy" class="ocf" type="Dummy" provider="heartbeat"/>'
> +sleep 3
> +
> +# get resource's information with snmp subagent.
> +rsc0name=`snmpget -v2c localhost -c public LHAResourceName.1 \
> + | sed -ne 's/LINUX-HA-MIB::LHAResourceName.1 = STRING: //p'`
> +rsc0type=`snmpget -v2c localhost -c public LHAResourceType.1 \
> + | sed -ne 's/LINUX-HA-MIB::LHAResourceType.1 = INTEGER: //p'`
> +rsc0node=`snmpget -v2c localhost -c public LHAResourceNode.1 \
> + | sed -ne 's/LINUX-HA-MIB::LHAResourceNode.1 = STRING: //p'`
> +rsc0status=`snmpget -v2c localhost -c public LHAResourceStatus.1 \
> + | sed -ne 's/LINUX-HA-MIB::LHAResourceStatus.1 = INTEGER: //p'`
> +
> +# check for LHAResourceName
> +ret=0
> +echo "rsc0name = $rsc0name, RSC0NAME = $RSC0NAME"
> +if test "$rsc0name" != "$RSC0NAME"; then
> + echo "failed to get resource name." >&2
> + ret=1
> +fi
> +
> +# check for LHAResourceType
> +if test $ret = 0; then
> + echo "rsc0type = $rsc0type, RSC0TYPE = $RSC0TYPE"
> + if test "$rsc0type" != "$RSC0TYPE"; then
> + echo "failed to get resource type." >&2
> + ret=1
> + fi
> +fi
> +
> +# check for LHAResourceNode
> +if test $ret = 0; then
> + echo "rsc0node = $rsc0node, RSC0NODE = $RSC0NODE"
> + if test "$rsc0node" != "$RSC0NODE"; then
> + echo "failed to get resource node." >&2
> + ret=1
> + fi
> +fi
> +
> +# check for LHAResourceStatus
> +if test $ret = 0; then
> + echo "rsc0status = $rsc0status, RSC0STATUS = $RSC0STATUS"
> + if test "$rsc0status" != "$RSC0STATUS"; then
> + echo "failed to get resource status." >&2
> + ret=1
> + fi
> +fi
> +
> +# show the result.
> +if test $ret = 0; then
> + echo "BasicSanityCheck for SNMP Subagent about CRM resources passed."
> + exit 0
> +else
> + echo "BasicSanityCheck for SNMP Subagent about CRM resources failed."
> exit 1
> fi
> +
> +
> if
> [ -f $SNMPPIDFILE -a ! -z $SNMPPIDFILE ]
> then
> diff -urN org/snmp_subagent/hbagent.c mod/snmp_subagent/hbagent.c
> --- org/snmp_subagent/hbagent.c 2007-11-19 15:15:07.000000000 +0900
> +++ mod/snmp_subagent/hbagent.c 2007-11-21 10:16:35.000000000 +0900
> @@ -24,6 +24,7 @@
> #include <lha_internal.h>
>
> #include "hbagent.h"
> +#include "hbagentv2.h"
>
> #include "hb_api.h"
> #include "heartbeat.h"
> @@ -66,13 +67,12 @@
> #include <errno.h>
>
> #include "saf/ais.h"
> -
> -#define DEFAULT_TIME_OUT 5 /* default timeout value for snmp in sec. */
> -#define LHAAGENTID "lha-snmpagent"
> +#include "clplumbing/cl_uuid.h" /* UU_UNPARSE_SIZEOF */
>
> static unsigned long hbInitialized = 0;
> static ll_cluster_t * hb = NULL; /* heartbeat handle */
> -static char * myid = NULL; /* my node id */
> +char * myid = NULL; /* my node id */
> +char * myuuid = NULL; /* my node uuid */
> static SaClmHandleT clm = 0;
> static unsigned long clmInitialized = 0;
>
> @@ -82,6 +82,7 @@
> static GPtrArray * gResourceTable = NULL;
>
> static int keep_running;
> +int snmp_cache_time_out = CACHE_TIME_OUT;
>
> int init_heartbeat(void);
> int get_heartbeat_fd(void);
> @@ -559,6 +560,7 @@
> init_heartbeat(void)
> {
> char * parameter;
> + cl_uuid_t uuid;
> hb = NULL;
>
> cl_log_set_entity("lha-snmpagent");
> @@ -589,6 +591,18 @@
> return HA_FAIL;
> }
>
> + /*
> + * get uuid for trap message.
> + * see: hbagentv2_update_diff() in hbagentv2.c
> + */
> + if (hb->llc_ops->get_uuid_by_name(hb, myid, &uuid) == HA_FAIL) {
> + cl_log(LOG_ERR, "Cannot get mynodeid");
> + cl_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb));
> + return HA_FAIL;
> + }
> + myuuid = cl_malloc(UU_UNPARSE_SIZEOF);
> + cl_uuid_unparse(&uuid, myuuid);
> +
> if (hb->llc_ops->set_nstatus_callback(hb, NodeStatus, NULL) !=HA_OK){
> cl_log(LOG_ERR, "Cannot set node status callback");
> cl_log(LOG_ERR, "REASON: %s", hb->llc_ops->errmsg(hb));
> @@ -1307,6 +1321,7 @@
> struct timeval tv, *tvp;
> int flag, block = 0, numfds, hb_fd = 0, mem_fd = 0, debug = 0;
> int hb_already_dead = 0;
> + int cib_fd = 0;
>
> /* change this if you want to be a SNMP master agent */
> int agentx_subagent=1;
> @@ -1314,9 +1329,6 @@
> /* change this if you want to run in the background */
> int background = 0;
>
> - /* change this if you want to use syslog */
> - int syslog = 1;
> -
> /* LHAHeartbeatConfigInfo partial-mode */
> int hbconfig_refresh_timing = 0;
> int hbconfig_refresh_cnt;
> @@ -1335,6 +1347,7 @@
> hbconfig_refresh_timing = i / DEFAULT_TIME_OUT;
> else
> hbconfig_refresh_timing = DEFAULT_REFRESH_TIMING;
> + snmp_cache_time_out = i;
> break;
> case 'h':
> usage();
> @@ -1345,16 +1358,13 @@
> }
> }
>
> - if (debug)
> + if (debug) {
> cl_log_enable_stderr(TRUE);
> - else
> + snmp_enable_stderrlog();
> + } else {
> cl_log_enable_stderr(FALSE);
> -
> - /* print log errors to syslog or stderr */
> - if (syslog)
> snmp_enable_calllog();
> - else
> - snmp_enable_stderrlog();
> + }
>
> /* we're an agentx subagent? */
> if (agentx_subagent) {
> @@ -1364,7 +1374,7 @@
> }
>
> /* run in background, if requested */
> - if (background && netsnmp_daemonize(1, !syslog))
> + if (background && netsnmp_daemonize(1, debug))
> exit(1);
>
> /* initialize the agent library */
> @@ -1415,6 +1425,13 @@
> init_LHAMembershipTable();
> init_LHAHeartbeatConfigInfo();
>
> +
> + /* now implementing: hbagentv2 */
> + if ((ret = init_hbagentv2()) != HA_OK ||
> + (cib_fd = get_cib_fd()) <= 0) {
> + return -4;
> + }
> +
> /* LHA-agent will be used to read LHA-agent.conf files. */
> init_snmp("LHA-agent");
>
> @@ -1450,6 +1467,10 @@
> if (mem_fd > hb_fd)
> numfds = mem_fd + 1;
> }
> + FD_SET(cib_fd, &fdset);
> + if (numfds < (cib_fd + 1)) {
> + numfds = cib_fd + 1;
> + }
>
> tv.tv_sec = DEFAULT_TIME_OUT;
> tv.tv_usec = 0;
> @@ -1487,6 +1508,7 @@
> } else if (ret == 0) {
> /* timeout */
> ping_membership(&mem_fd);
> +
> /* LHAHeartbeatConfigInfo partial-mode */
> if (hbconfig_refresh_timing
> && ++hbconfig_refresh_cnt >= hbconfig_refresh_timing) {
> @@ -1513,6 +1535,12 @@
> cl_log(LOG_DEBUG, "unrecoverable membership error. quit now.");
> break;
> }
> + } else if (FD_ISSET(cib_fd, &fdset)) {
> + /* change cib info events */
> + if ((ret = handle_cib_msg()) == HA_FAIL) {
> + cl_log(LOG_DEBUG, "unrecoverable CIB error. quit now.");
> + break;
> + }
> } else {
>
> /* snmp request */
> @@ -1530,8 +1558,10 @@
> hbagent_trap(0, myid);
> snmp_shutdown("LHA-agent");
>
> - free_hbconfig();
> + free_hbagentv2();
> + free_hbconfig();
> cl_free(myid);
> + cl_free(myuuid);
> free_storage();
>
> if (!hb_already_dead && hb->llc_ops->signoff(hb, TRUE) != HA_OK) {
> @@ -1548,4 +1578,3 @@
> return 0;
> }
>
> -
> diff -urN org/snmp_subagent/hbagent.h mod/snmp_subagent/hbagent.h
> --- org/snmp_subagent/hbagent.h 2007-11-02 17:35:27.000000000 +0900
> +++ mod/snmp_subagent/hbagent.h 2007-12-03 16:48:19.000000000 +0900
> @@ -35,6 +35,8 @@
> #include <clplumbing/cl_uuid.h>
>
> #define CACHE_TIME_OUT 5
> +#define LHAAGENTID "lha-snmpagent"
> +#define DEFAULT_TIME_OUT 5 /* default timeout value for snmp in sec. */
>
> typedef enum lha_group {
> LHA_CLUSTERINFO,
> diff -urN org/snmp_subagent/hbagentv2.c mod/snmp_subagent/hbagentv2.c
> --- org/snmp_subagent/hbagentv2.c 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/hbagentv2.c 2007-12-03 17:08:03.000000000 +0900
> @@ -0,0 +1,657 @@
> +#include <lha_internal.h>
> +
> +#include "hbagent.h"
> +#include "hbagentv2.h"
> +
> +
> +#include "hb_api.h"
> +#include "heartbeat.h"
> +#include "clplumbing/cl_log.h"
> +#include "clplumbing/coredumps.h"
> +
> +#include "crm/crm.h"
> +#include "crm/cib.h"
> +#include "crm/pengine/status.h"
> +#include "crm/msg_xml.h"
> +#include "crm/transition.h"
> +
> +#include <net-snmp/net-snmp-config.h>
> +#include <net-snmp/net-snmp-includes.h>
> +#include <net-snmp/agent/net-snmp-agent-includes.h>
> +#include <sys/wait.h>
> +
> +#include <unistd.h>
> +
> +#include <errno.h>
> +
> +#include "LHAResourceTable.h"
> +#include "LHAResourceStatusUpdate.h"
> +
> +
> +/*
> + * Agent MIB value conversion macros from the internal value
> + */
> +/* ref. crm/pengine/complex.h:enum pe_obj_types */
> +#define PE_OBJ_TYPES2AGENTTYPE(variant) ((int)(variant) + 1)
> +/* ref. crm/pengine/common.h:enum rsc_role_e */
> +#define RSC_ROLE_E2AGENTSTATUS(role) ((int)(role)) /* the value is identical */
> +
> +/* need more than (RID_LEN + sizeof(CRMD_ACTION_xxx) + sizeof(rc_code) */
> +#define MAX_OP_STR_LEN 256
> +/* need more than sizeof(rc_code). ref. UNIFORM_RET_EXECRA in lrm/raexec.h */
> +#define MAX_RCCODE_STR_LEN 4
> +
> +static cib_t *cib_conn = NULL;
> +static GPtrArray * gResourceTableV2 = NULL;
> +static int err_occurs = 0; /* the flag which means an error occurs in callback func. */
> +extern const char *myid;
> +extern const char *myuuid;
> +
> +/* for debug */
> +void debugPrint(HA_Message *msg, int depth, FILE *fp);
> +
> +/**
> + * Initialize of resource table v2.
> + */
> +int
> +init_resource_table_v2(void)
> +{
> +
> + if (gResourceTableV2) {
> + free_resource_table_v2();
> + }
> +
> + return HA_OK;
> +}
> +
> +/**
> + * This is the main function to update resource table v2.
> + * Return the number of resources.
> + */
> +static int
> +update_resources_recursively(GListPtr reslist, int index)
> +{
> +
> + if (reslist == NULL) {
> + return index;
> + }
> + /*
> + * Set resource info to resource table v2 from data_set,
> + * and add it to Glib's array.
> + */
> + slist_iter(rsc, resource_t, reslist, lpc1,
> + {
> + cl_log(LOG_DEBUG, "resource %s processing.", rsc->id);
> + slist_iter(node, node_t, rsc->allowed_nodes, lpc2,
> + {
> + struct hb_rsinfov2 *rsinfo;
> + enum rsc_role_e rsstate;
> +
> + rsinfo = (struct hb_rsinfov2 *) cl_malloc(sizeof(struct hb_rsinfov2));
> + if (!rsinfo) {
> + cl_log(LOG_CRIT, "malloc resource info v2 failed.");
> + return HA_FAIL;
> + }
> +
> + rsinfo->resourceid = cl_strdup(rsc->id);
> + rsinfo->type = PE_OBJ_TYPES2AGENTTYPE(rsc->variant);
> +
> + /* using a temp var to suppress casting warning of the compiler */
> + rsstate = rsc->fns->state(rsc, TRUE);
> + if (pe_find_node_id(rsc->running_on, node->details->id) == NULL) {
> + /*
> + * if the resource is not running on current node,
> + * its status is "stopped(1)".
> + */
> + rsstate = RSC_ROLE_STOPPED;
> + }
> + rsinfo->status = RSC_ROLE_E2AGENTSTATUS(rsstate);
> + rsinfo->node = cl_strdup(node->details->uname);
> +
> + if (is_not_set(rsc->flags, pe_rsc_managed)) {
> + rsinfo->is_managed = LHARESOURCEISMANAGED_UNMANAGED;
> + } else {
> + rsinfo->is_managed = LHARESOURCEISMANAGED_MANAGED;
> + }
> +
> + /* get fail-count from <status> */
> + {
> + char *attr_name = NULL;
> + char *attr_value = NULL;
> + crm_data_t *tmp_xml = NULL;
> +
> + attr_name = crm_concat("fail-count", rsinfo->resourceid, '-');
> + attr_value = g_hash_table_lookup(node->details->attrs,
> + attr_name);
> + rsinfo->failcount = crm_parse_int(attr_value, "0");
> + crm_free(attr_name);
> + free_xml(tmp_xml);
> + }
> +
> + if (rsc->parent != NULL) {
> + rsinfo->parent = cl_strdup(rsc->parent->id);
> + } else {
> + rsinfo->parent = cl_strdup("");
> + }
> +
> + /*
> + * if the resource stops, and its fail-count is 0,
> + * don't list it up.
> + */
> + if (rsinfo->status != LHARESOURCESTATUS_STOPPED ||
> + rsinfo->failcount > 0) {
> + rsinfo->index = index++;
> + g_ptr_array_add(gResourceTableV2, (gpointer *)rsinfo);
> + } else {
> + cl_free(rsinfo->resourceid);
> + cl_free(rsinfo->node);
> + cl_free(rsinfo->parent);
> + cl_free(rsinfo);
> + }
> +
> + }); /* end slist_iter(node) */
> +
> + /* add resources recursively for group/clone/master */
> + index = update_resources_recursively(rsc->fns->children(rsc), index);
> +
> + }); /* end slist_iter(rsc) */
> +
> + return index;
> +}
> +
> +/**
> + * Send query to the CIB and update the information of resource table v2.
> + */
> +int
> +update_resource_table_v2(void)
> +{
> + crm_data_t *cib_object = NULL;
> + pe_working_set_t data_set;
> + int rc = cib_ok;
> + int options = cib_scope_local|cib_sync_call;
> + int index;
> +
> + if (!gResourceTableV2) {
> + cl_log(LOG_ERR, "resource table v2 is NULL.");
> + return HA_FAIL;
> + }
> + free_resource_table_v2();
> +
> + rc = cib_conn->cmds->query(cib_conn, NULL, &cib_object, options);
> + if (rc != cib_ok) {
> + cl_log(LOG_ERR, "CIB query failed: %s", cib_error2string(rc));
> + return HA_FAIL;
> + }
> + if (cib_object == NULL) {
> + cl_log(LOG_ERR, "CIB query failed: empty result.");
> + return HA_FAIL;
> + }
> +
> + cl_log(LOG_DEBUG, "CIB query done. Updating resource table v2.");
> +
> + set_working_set_defaults(&data_set);
> + data_set.input = cib_object;
> + /* parse cib xml info (cib_object). */
> + cluster_status(&data_set);
> +
> + index = update_resources_recursively(data_set.resources, 1);
> + if (index == HA_FAIL) {
> + cl_log(LOG_ERR, "Update resources failed.");
> +
> + data_set.input = NULL;
> + cleanup_calculations(&data_set);
> + free_xml(cib_object);
> + return HA_FAIL;
> + }
> +
> + cl_log(LOG_DEBUG, "Updated %d resources.", index-1);
> +
> +
> + data_set.input = NULL;
> + cleanup_calculations(&data_set);
> + free_xml(cib_object);
> + return HA_OK;
> +}
> +
> +/**
> + * Update resource table v2 and return it's pointer.
> + * To get latest information of resources.
> + * This function is called in LHAResourceTable_load(),
> + * only when snmp cache timeout occurs.
> + */
> +GPtrArray *
> +get_resource_table_v2(void)
> +{
> + update_resource_table_v2();
> + return gResourceTableV2;
> +}
> +
> +/**
> + * Free resource table v2.
> + */
> +void
> +free_resource_table_v2(void)
> +{
> + struct hb_rsinfov2 *resource;
> +
> + if (!gResourceTableV2) {
> + return;
> + }
> +
> + cl_log(LOG_DEBUG, "Freeing %d resources.", gResourceTableV2->len);
> + while (gResourceTableV2->len) {
> + resource = (struct hb_rsinfov2 *) g_ptr_array_remove_index_fast(gResourceTableV2, 0);
> + cl_free(resource->resourceid);
> + cl_free(resource->node);
> + cl_free(resource->parent);
> + cl_free(resource);
> + }
> +
> + return;
> +}
> +
> +/**
> + * This is the main function to send a trap to tell a resource's status is changed.
> + * This function is called when a change occurs on the cib information.
> + * First, it parses a received xml message, and if the msg tells that the status of
> + * a resource changes, it sends a trap to SNMP manager via Net-SNMP daemon.
> + * Note1: It sends a trap when the resouce [stopped|started|been Slave|been Master].
> + * And it sends a trap only when the execution of RA method is succeeded.
> + * Note2: If an error occurs in this function, set the variable "err_occurs" to tell
> + * that to the handler. (see: handle_cib_msg())
> + */
> +static void
> +hbagentv2_update_diff(const char *event, HA_Message *msg)
> +{
> +
> + /*implement parsing the diff and send a trap */
> + const char *op = NULL;
> + crm_data_t *diff = NULL;
> + const char *set_name = NULL;
> +
> + crm_data_t *change_set = NULL;
> + crm_data_t *lrm_rsc = NULL;
> + const char *node_id = NULL;
> + const char *rsc_id = NULL;
> + const char *rsc_op_id = NULL;
> + const char *rc_code = NULL;
> + const char *t_magic = NULL;
> + const char *operation = NULL;
> + char tmp_op_str[MAX_OP_STR_LEN];
> + char tmp_rc_str[MAX_RCCODE_STR_LEN];
> + char *tmp = tmp_op_str;
> +
> + /* Initialize err flag. */
> + err_occurs = 0;
> +
> + if (!msg) {
> + cl_log(LOG_ERR, "cib message is NULL.");
> + err_occurs = 1;
> + return;
> + }
> + op = cl_get_string(msg, F_CIB_OPERATION);
> + diff = get_message_xml(msg, F_CIB_UPDATE_RESULT);
> + if (!diff) {
> + cl_log(LOG_ERR, "update result is NULL.");
> + return;
> + }
> +
> + /* for debug */
> + /*
> + {
> + FILE * fp;
> + fp = fopen("/tmp/msgdiff.out", "a");
> + debugPrint(diff, 0, fp);
> + fclose(fp);
> + }
> + */
> +
> + /*
> + * start to get the following information from difference of cib xml.
> + * <lrm_rsc_op operation="xxx" rc_code="yyy">
> + */
> +
> + /* get the head pointer of <status> */
> + set_name = "diff-added"; /* we need the cib info only which have been updated. */
> + change_set = find_xml_node(diff, set_name, FALSE);
> + change_set = find_xml_node(change_set, XML_TAG_CIB, FALSE);
> + change_set = find_xml_node(change_set, XML_CIB_TAG_STATUS, FALSE);
> + if (!change_set) {
> + /* There is no information of <status> */
> + free_xml(diff);
> + return;
> + }
> +
> + xml_child_iter_filter(
> + change_set, node_state, XML_CIB_TAG_STATE,
> +
> + /* get the node id at which the resources changed */
> + node_id = crm_element_value(node_state, XML_ATTR_ID);
> + if (!node_id) {
> + /* There is no information of <node_status> */
> + free_xml(diff);
> + return;
> + }
> + if (STRNCMP_CONST(node_id, myuuid) != 0) {
> + /* This change is not at my node */
> + free_xml(diff);
> + return;
> + }
> +
> + /* get the head pointer of <lrm_resource> */
> + lrm_rsc = find_xml_node(node_state, XML_CIB_TAG_LRM, FALSE);
> + lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCES, FALSE);
> + if (!lrm_rsc) {
> + /* There is no information of <lrm_resources> */
> + free_xml(diff);
> + return;
> + }
> + lrm_rsc = find_xml_node(lrm_rsc, XML_LRM_TAG_RESOURCE, FALSE);
> + if (!lrm_rsc) {
> + /* There is no information of <lrm_resource> */
> + free_xml(diff);
> + return;
> + }
> +
> + /*
> + * now, get the head pointer of <lrm_rsc_op>,
> + * and parse it's resource id, operation, and rc_code.
> + */
> + xml_child_iter_filter(
> + lrm_rsc, lrm_rsc_op, XML_LRM_TAG_RSC_OP,
> +
> + rsc_id = crm_element_value(lrm_rsc, XML_ATTR_ID);
> + operation = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_TASK);
> + rc_code = crm_element_value(lrm_rsc_op, XML_LRM_ATTR_RC);
> + rsc_op_id = crm_element_value(lrm_rsc_op, XML_ATTR_ID);
> + t_magic = crm_element_value(lrm_rsc_op, XML_ATTR_TRANSITION_MAGIC);
> + ); /* end of xml_child_iter_filter(lrm_rsc) */
> + ); /* end of xml_child_iter_filter(change_set) */
> +
> +
> + /*
> + * Sometimes, the difference of cib infomation doesn't include operation and rc_code.
> + * Like when you move resources by hand (ex. crm_resource -M, or -F), or
> + * resources move according to <rule> and so on.
> + * In these cases, get them from other attributes' value.
> + */
> + /* get operation from lrm_rsc_op's id */
> + if (!operation) {
> + strcpy(tmp_op_str, rsc_op_id);
> + tmp = strrchr(tmp_op_str, '_');
> + *tmp = '\0';
> + operation = strrchr(tmp_op_str, '_') + 1;
> + }
> + /* get rc_code from transition magic number */
> + if (!rc_code) {
> + if (t_magic != NULL) {
> + int transition_num = -1;
> + int action_id = -1;
> + int status = -1;
> + int rc = -1;
> + char *uuid = NULL;
> +
> + if (!decode_transition_magic(
> + t_magic, &uuid, &transition_num, &action_id, &status, &rc)) {
> + cl_log(LOG_ERR, "decode_transition_magic() is failed.");
> + free_xml(diff);
> + return;
> + }
> + crm_free(uuid);
> + sprintf(tmp_rc_str, "%d\n", rc);
> + rc_code = tmp_rc_str;
> + }
> + }
> +
> + /* now, send a trap. */
> + if (operation != NULL && rc_code != NULL) {
> + if (atoi(rc_code) == EXECRA_OK) {
> + struct hb_rsinfov2 resource;
> +
> + resource.resourceid = cl_strdup(rsc_id);
> + resource.node = cl_strdup(myid);
> +
> + /* LHAResourceStatus is ... */
> + if (safe_str_eq(operation, CRMD_ACTION_STOP)) {
> + /* 1: Stopped */
> + resource.status = LHARESOURCESTATUS_STOPPED;
> + } else if (safe_str_eq(operation, CRMD_ACTION_START)) {
> + /* 2: Started */
> + resource.status = LHARESOURCESTATUS_STARTED;
> + } else if (safe_str_eq(operation, CRMD_ACTION_DEMOTE)) {
> + /* 3: Slave */
> + resource.status = LHARESOURCESTATUS_SLAVE;
> + } else if (safe_str_eq(operation, CRMD_ACTION_PROMOTE)) {
> + /* 4: Master */
> + resource.status = LHARESOURCESTATUS_MASTER;
> + } else {
> + /* other action. send no trap. */
> + cl_free(resource.resourceid);
> + cl_free(resource.node);
> + free_xml(diff);
> + return;
> + }
> +
> + send_LHAResourceStatusUpdate_trap(&resource);
> + cl_free(resource.resourceid);
> + cl_free(resource.node);
> + } else {
> + /* operation does not succeed. */
> + /* do nothing (for the present) */
> + }
> + }
> +
> + free_xml(diff);
> + return;
> +
> +}
> +
> +/**
> + * Initialization of connection to the CIB.
> + * Have a connection made newly. And set callback function, hbagentv2_update_diff(),
> + * that is called when cib infomation message changes.
> + */
> +static int
> +init_cib(void)
> +{
> + int rc;
> +
> +
> + cib_conn = cib_new();
> + if (cib_conn == NULL) {
> + cl_log(LOG_ERR, "CIB connection initialization failed.");
> + return HA_FAIL;
> + }
> + rc = cib_conn->cmds->signon(cib_conn, LHAAGENTID, cib_query);
> + if (rc != cib_ok) {
> + cl_log(LOG_ERR, "CIB connection signon failed.");
> + return HA_FAIL;
> + }
> +
> + rc = cib_conn->cmds->add_notify_callback(cib_conn, T_CIB_DIFF_NOTIFY,
> + hbagentv2_update_diff);
> + if (rc != cib_ok) {
> + cl_log(LOG_ERR, "CIB connection adding callback failed.");
> + return HA_FAIL;
> + }
> +
> + cl_log(LOG_INFO, "CIB connection initialization completed.");
> + return HA_OK;
> +}
> +
> +/**
> + * Sign off and clean the connection to the CIB.
> + */
> +static void
> +free_cib(void)
> +{
> + if (cib_conn) {
> + if (cib_conn->cmds->signoff(cib_conn) != cib_ok) {
> + cl_log(LOG_WARNING, "CIB connection signoff failed(ignored).");
> + }
> + cib_delete(cib_conn);
> + cib_conn = NULL;
> + }
> +
> + return;
> +}
> +
> +/**
> + * Returns a file discripter of the connection to the CIB.
> + * -1 : error occurs.
> + * else : cib conn's fd.
> + */
> +int
> +get_cib_fd(void)
> +{
> + int fd;
> + if (!cib_conn) {
> + cl_log(LOG_ERR, "CIB is not initialized.");
> + return -1;
> + }
> + if ((fd = cib_conn->cmds->inputfd(cib_conn)) < 0) {
> + cl_log(LOG_ERR, "Can not get CIB inputfd.");
> + return -1;
> + }
> + return fd;
> +}
> +
> +/**
> + * Handler of cib information message changes.
> + * Set this function in the select loop to send a trap.
> + */
> +int
> +handle_cib_msg(void)
> +{
> +
> + /* TODO: this prototype is not exported in any headers */
> + gboolean cib_native_dispatch(IPC_Channel *channel, gpointer user_data);
> +
> + if (cib_conn->cmds->msgready(cib_conn)) {
> + IPC_Channel * chan;
> +
> + /* get IPC Channel. */
> + chan = cib_conn->cmds->channel(cib_conn);
> + if (!chan) {
> + cl_log(LOG_ERR, "CIB connection's channel is NULL.");
> + return HA_FAIL;
> + }
> + /* check CIB connection. */
> + if (chan->ch_status == IPC_DISCONNECT) {
> + cl_log(LOG_ERR, "Lost connection to the CIB.");
> + return HA_FAIL;
> + }
> + /* call callback function. */
> + if (!cib_native_dispatch(NULL, cib_conn)) {
> + cl_log(LOG_ERR, "cib_native_dispatch() failed.");
> + return HA_FAIL;
> + }
> + /* check if an error occurs in callback function. */
> + if (err_occurs) {
> + return HA_FAIL;
> + }
> +
> + }
> + return HA_OK;
> +}
> +
> +/**
> + * Initialization of hbagentv2.
> + * hbagentv2 is agent which keeps watching on operation of resources.
> + * (see: LHAResourceTable and LHAResourceStatusUpdate)
> + */
> +int
> +init_hbagentv2(void)
> +{
> + int ret;
> +
> + gResourceTableV2 = g_ptr_array_new();
> + if (gResourceTableV2 == NULL) {
> + cl_log(LOG_ERR, "Storage allocation failure for hbagentv2.");
> + return HA_FAIL;
> + }
> +
> + ret = init_cib();
> + if (ret != HA_OK) {
> + cl_log(LOG_ERR, "init_cib() failed.");
> + return ret;
> + }
> + ret = init_resource_table_v2();
> + if (ret != HA_OK) {
> + cl_log(LOG_ERR, "resource table v2 initialization failure.");
> + }
> +
> + init_LHAResourceTable();
> +
> + cl_log(LOG_INFO, "hbagentv2 initialization completed.");
> +
> + return HA_OK;
> +}
> +
> +/**
> + * Free and clear resource table v2 and cib connection.
> + * Disposer which is called before stopping agent.
> + */
> +void
> +free_hbagentv2(void)
> +{
> + free_resource_table_v2();
> + g_ptr_array_free(gResourceTableV2, 1);
> + gResourceTableV2 = NULL;
> + free_cib();
> +}
> +
> +/*
> + * debug print for cib info.
> + */
> +void
> +debugPrint(HA_Message *msg, int depth, FILE *fp)
> +{
> + int i;
> +
> + if (msg == NULL) {
> + return;
> + }
> +
> + if (fp == NULL) {
> + fp = stdout;
> + }
> +
> + for (i = 0; i < msg->nfields; i++) {
> + int j;
> + for (j = 0; j < depth; j++) {
> + fprintf(fp, " ");
> + fflush(fp);
> + }
> + if (msg->types[i] == FT_STRING) {
> + fprintf(fp, "[%2d] %s = %s\n", i, msg->names[i], (char*)msg->values[i]);
> + fflush(fp);
> + }
> + else if (msg->types[i] == FT_STRUCT || msg->types[i] == FT_UNCOMPRESS) {
> + fprintf(fp, "[%2d] %s {\n", i, msg->names[i]);
> + fflush(fp);
> + debugPrint(msg->values[i], depth + 1, fp);
> +
> + for (j = 0; j < depth; j++) {
> + fprintf(fp, " ");
> + fflush(fp);
> + }
> + fprintf(fp, "}\n");
> + fflush(fp);
> + }
> + else {
> + fprintf(fp, "[%2d] %s is [%d] TYPE.\n", i, msg->names[i], msg->types[i]);
> + fflush(fp);
> + }
> + }
> +}
> +
> +/**
> + * Emacs stuff:
> + * Local Variables:
> + * mode: C
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + *
> + */
> diff -urN org/snmp_subagent/hbagentv2.h mod/snmp_subagent/hbagentv2.h
> --- org/snmp_subagent/hbagentv2.h 1970-01-01 09:00:00.000000000 +0900
> +++ mod/snmp_subagent/hbagentv2.h 2007-11-26 17:59:46.000000000 +0900
> @@ -0,0 +1,28 @@
> +#ifndef _HBAGENTV2_H
> +#define _HBAGENTV2_H
> +
> +
> +
> +struct hb_rsinfov2 {
> + size_t index;
> + char * resourceid;
> + uint32_t type;
> + uint32_t status;
> + char * node;
> + uint32_t is_managed;
> + uint32_t failcount;
> + char * parent;
> +};
> +
> +int init_hbagentv2(void);
> +void free_hbagentv2(void);
> +
> +int get_cib_fd(void);
> +int handle_cib_msg(void);
> +
> +int init_resource_table_v2(void);
> +int update_resource_table_v2(void);
> +GPtrArray *get_resource_table_v2(void);
> +void free_resource_table_v2(void);
> +
> +#endif /* _HBAGENTV2_H */
> _______________________________________________________
> Linux-HA-Dev: Linux-HA-Dev at lists.linux-ha.org
> http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
> Home Page: http://linux-ha.org/
More information about the Linux-HA-Dev
mailing list