/*
  Copyright Red Hat, Inc. 2005

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; see the file COPYING.  If not, write to the
  Free Software Foundation, Inc.,  675 Mass Ave, Cambridge, 
  MA 02139, USA.
*/
/*
 * Author: Stanko Kupcevic <kupcevic@redhat.com>
 */
/*
 * Note: this file originally auto-generated by mib2c using
 *        : mib2c.scalar.conf,v 1.7 2003/04/08 14:57:04 dts12 Exp $
 */


#include "clusterMIB.h"
#include "clusterMonitorSnmp.h"


using namespace ClusterMonitoring;
using namespace std;


static unsigned int getStatusCode();
static string getStatusDescription(unsigned int code);


void
initialize_clusterMIB(void)
{
    static oid      rhcMIBVersion_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 1, 1 };
    
    static oid      rhcClusterName_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 1 };
    static oid      rhcClusterStatusCode_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 2 };
    static oid      rhcClusterStatusDesc_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 3 };
    static oid      rhcClusterVotesNeededForQuorum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 4 };
    static oid      rhcClusterVotes_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 5 };
    static oid      rhcClusterQuorate_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 6 };
    static oid      rhcClusterNodesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 7 };
    static oid      rhcClusterNodesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 8 };
    static oid      rhcClusterAvailNodesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 9 };
    static oid      rhcClusterAvailNodesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 10 };
    static oid      rhcClusterUnavailNodesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 11 };
    static oid      rhcClusterUnavailNodesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 12 };
    static oid      rhcClusterServicesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 13 };
    static oid      rhcClusterServicesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 14 };
    static oid      rhcClusterRunningServicesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 15 };
    static oid      rhcClusterRunningServicesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 16 };
    static oid      rhcClusterStoppedServicesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 17 };
    static oid      rhcClusterStoppedServicesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 18 };
    static oid      rhcClusterFailedServicesNum_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 19 };
    static oid      rhcClusterFailedServicesNames_oid[] =
        { 1, 3, 6, 1, 4, 1, 2312, 8, 2, 20 };
    
    DEBUGMSGTL(("libClusterMonitorSnmp", "Initializing\n"));
    
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcMIBVersion",
                             handle_rhcMIBVersion,
                             rhcMIBVersion_oid,
                             OID_LENGTH(rhcMIBVersion_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterFailedServicesNum",
                             handle_rhcClusterFailedServicesNum,
                             rhcClusterFailedServicesNum_oid,
                             OID_LENGTH(rhcClusterFailedServicesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterFailedServicesNames",
                             handle_rhcClusterFailedServicesNames,
                             rhcClusterFailedServicesNames_oid,
                             OID_LENGTH(rhcClusterFailedServicesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterStatusDesc",
                             handle_rhcClusterStatusDesc,
                             rhcClusterStatusDesc_oid,
                             OID_LENGTH(rhcClusterStatusDesc_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterVotes", handle_rhcClusterVotes,
                             rhcClusterVotes_oid,
                             OID_LENGTH(rhcClusterVotes_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterQuorate", handle_rhcClusterQuorate,
                             rhcClusterQuorate_oid,
                             OID_LENGTH(rhcClusterQuorate_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterStoppedServicesNum",
                             handle_rhcClusterStoppedServicesNum,
                             rhcClusterStoppedServicesNum_oid,
                             OID_LENGTH(rhcClusterStoppedServicesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterStoppedServicesNames",
                             handle_rhcClusterStoppedServicesNames,
                             rhcClusterStoppedServicesNames_oid,
                             OID_LENGTH(rhcClusterStoppedServicesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterAvailNodesNum",
                             handle_rhcClusterAvailNodesNum,
                             rhcClusterAvailNodesNum_oid,
                             OID_LENGTH(rhcClusterAvailNodesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterAvailNodesNames",
                             handle_rhcClusterAvailNodesNames,
                             rhcClusterAvailNodesNames_oid,
                             OID_LENGTH(rhcClusterAvailNodesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterServicesNum",
                             handle_rhcClusterServicesNum,
                             rhcClusterServicesNum_oid,
                             OID_LENGTH(rhcClusterServicesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterServicesNames",
                             handle_rhcClusterServicesNames,
                             rhcClusterServicesNames_oid,
                             OID_LENGTH(rhcClusterServicesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterName", handle_rhcClusterName,
                             rhcClusterName_oid,
                             OID_LENGTH(rhcClusterName_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterStatusCode",
                             handle_rhcClusterStatusCode,
                             rhcClusterStatusCode_oid,
                             OID_LENGTH(rhcClusterStatusCode_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterUnavailNodesNum",
                             handle_rhcClusterUnavailNodesNum,
                             rhcClusterUnavailNodesNum_oid,
                             OID_LENGTH(rhcClusterUnavailNodesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterUnavailNodesNames",
                             handle_rhcClusterUnavailNodesNames,
                             rhcClusterUnavailNodesNames_oid,
                             OID_LENGTH(rhcClusterUnavailNodesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterNodesNum",
                             handle_rhcClusterNodesNum,
                             rhcClusterNodesNum_oid,
                             OID_LENGTH(rhcClusterNodesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterNodesNames",
                             handle_rhcClusterNodesNames,
                             rhcClusterNodesNames_oid,
                             OID_LENGTH(rhcClusterNodesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterRunningServicesNum",
                             handle_rhcClusterRunningServicesNum,
                             rhcClusterRunningServicesNum_oid,
                             OID_LENGTH(rhcClusterRunningServicesNum_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterRunningServicesNames",
                             handle_rhcClusterRunningServicesNames,
                             rhcClusterRunningServicesNames_oid,
                             OID_LENGTH(rhcClusterRunningServicesNames_oid),
                             HANDLER_CAN_RONLY));
    netsnmp_register_scalar(netsnmp_create_handler_registration
                            ("rhcClusterVotesNeededForQuorum",
                             handle_rhcClusterVotesNeededForQuorum,
                             rhcClusterVotesNeededForQuorum_oid,
                             OID_LENGTH
                             (rhcClusterVotesNeededForQuorum_oid),
                             HANDLER_CAN_RONLY));
}


unsigned int 
getStatusCode(Cluster* cluster)
{
  unsigned int code = 1; // OK
  
  if (cluster->failedServices().size() != 0)
    // service failed
    code = (code & ~1) | 2;
  
  if (cluster->stoppedServices().size() != 0)
    // service not running
    code = (code & ~1) | 4;
  
  if (cluster->unclusteredNodes().size() != 0)
    // unavailable node
    code = (code & ~1) | 8;
  
  if (cluster->votes() < cluster->minQuorum())
    // not quorate
    code = (code & ~1) | 16;
  
  if (cluster->unclusteredNodes().size() == cluster->nodes().size())
    // cluster stopped
    code = (code & ~1) | 32;
  
  return code;
}

string
getStatusDescription(unsigned int code)
{
  if (code == 1)
    return "All services and nodes functional";
  if (code & 32)
    return "Cluster stopped (all services stopped)";
  if (code & 16)
    return "Not quorate (all services stopped)";
  
  string descr;
  if (code & 2) {
    string c = "Some services failed";
    if (descr.size() == 0)
      descr = c;
    else
      descr += ", " + c;
  }
  if (code & 4) {
    string c = "Some services not running";
    if (descr.size() == 0)
      descr = c;
    else
      descr += ", " + c;
  }
  if (code & 8) {
    string c = "Some nodes unavailable";
    if (descr.size() == 0)
      descr = c;
    else
      descr += ", " + c;
  }
  return descr;
}


int
handle_rhcMIBVersion(netsnmp_mib_handler *handler,
		     netsnmp_handler_registration *reginfo,
		     netsnmp_agent_request_info *reqinfo,
		     netsnmp_request_info *requests)
{
  try {
    
    unsigned int num = 1;  // MIB version 1
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
			       (u_char *)
			       &num,
			       sizeof(num));
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterFailedServicesNum(netsnmp_mib_handler *handler,
                                   netsnmp_handler_registration *reginfo,
                                   netsnmp_agent_request_info *reqinfo,
                                   netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->failedServices().size();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
			       (u_char *)
			       &num,
			       sizeof(num));
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterFailedServicesNames(netsnmp_mib_handler *handler,
				     netsnmp_handler_registration *reginfo,
				     netsnmp_agent_request_info *reqinfo,
				     netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Service> > l = cluster->failedServices();
    string str;
    for (list<counting_auto_ptr<Service> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterStatusDesc(netsnmp_mib_handler *handler,
			    netsnmp_handler_registration *reginfo,
			    netsnmp_agent_request_info *reqinfo,
			    netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int code = getStatusCode(cluster.get());
    string str = getStatusDescription(code);
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterVotes(netsnmp_mib_handler *handler,
                       netsnmp_handler_registration *reginfo,
                       netsnmp_agent_request_info *reqinfo,
                       netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->votes();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;
	
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterStoppedServicesNum(netsnmp_mib_handler *handler,
                                    netsnmp_handler_registration *reginfo,
                                    netsnmp_agent_request_info *reqinfo,
                                    netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->stoppedServices().size();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;
	
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterStoppedServicesNames(netsnmp_mib_handler *handler,
				      netsnmp_handler_registration *reginfo,
				      netsnmp_agent_request_info *reqinfo,
				      netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Service> > l = cluster->stoppedServices();
    string str;
    for (list<counting_auto_ptr<Service> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterAvailNodesNum(netsnmp_mib_handler *handler,
                               netsnmp_handler_registration *reginfo,
                               netsnmp_agent_request_info *reqinfo,
                               netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->clusteredNodes().size();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;
	
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterAvailNodesNames(netsnmp_mib_handler *handler,
				 netsnmp_handler_registration *reginfo,
				 netsnmp_agent_request_info *reqinfo,
				 netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Node> > l = cluster->clusteredNodes();
    string str;
    for (list<counting_auto_ptr<Node> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterServicesNum(netsnmp_mib_handler *handler,
                             netsnmp_handler_registration *reginfo,
                             netsnmp_agent_request_info *reqinfo,
                             netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->services().size();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterServicesNames(netsnmp_mib_handler *handler,
				 netsnmp_handler_registration *reginfo,
				 netsnmp_agent_request_info *reqinfo,
				 netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Service> > l = cluster->services();
    string str;
    for (list<counting_auto_ptr<Service> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterName(netsnmp_mib_handler *handler,
                      netsnmp_handler_registration *reginfo,
                      netsnmp_agent_request_info *reqinfo,
                      netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    string name = cluster->name();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
                                 (u_char *)
                                 name.c_str(),
                                 name.size());
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterStatusCode(netsnmp_mib_handler *handler,
                            netsnmp_handler_registration *reginfo,
                            netsnmp_agent_request_info *reqinfo,
                            netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int code = getStatusCode(cluster.get());
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &code,
                                 sizeof(code));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterUnavailNodesNum(netsnmp_mib_handler *handler,
                                 netsnmp_handler_registration *reginfo,
                                 netsnmp_agent_request_info *reqinfo,
                                 netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->unclusteredNodes().size();
      
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterUnavailNodesNames(netsnmp_mib_handler *handler,
				   netsnmp_handler_registration *reginfo,
				   netsnmp_agent_request_info *reqinfo,
				   netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Node> > l = cluster->unclusteredNodes();
    string str;
    for (list<counting_auto_ptr<Node> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterNodesNum(netsnmp_mib_handler *handler,
                          netsnmp_handler_registration *reginfo,
                          netsnmp_agent_request_info *reqinfo,
                          netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->nodes().size();
  
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterNodesNames(netsnmp_mib_handler *handler,
			    netsnmp_handler_registration *reginfo,
			    netsnmp_agent_request_info *reqinfo,
			    netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Node> > l = cluster->nodes();
    string str;
    for (list<counting_auto_ptr<Node> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterRunningServicesNum(netsnmp_mib_handler *handler,
                                    netsnmp_handler_registration *reginfo,
                                    netsnmp_agent_request_info *reqinfo,
                                    netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->runningServices().size();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterRunningServicesNames(netsnmp_mib_handler *handler,
				      netsnmp_handler_registration *reginfo,
				      netsnmp_agent_request_info *reqinfo,
				      netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    list<counting_auto_ptr<Service> > l = cluster->runningServices();
    string str;
    for (list<counting_auto_ptr<Service> >::iterator iter = l.begin();
	 iter != l.end();
	 iter++)
      if (str.empty())
	str = (*iter)->name();
      else 
	str += ", " + (*iter)->name();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */
    
    switch (reqinfo->mode) {
      
    case MODE_GET:
      snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
			       (u_char *)
			       str.c_str(),
			       str.size());
      break;
      
    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterVotesNeededForQuorum(netsnmp_mib_handler *handler,
                                      netsnmp_handler_registration
                                      *reginfo,
                                      netsnmp_agent_request_info *reqinfo,
                                      netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->minQuorum();
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}

int
handle_rhcClusterQuorate(netsnmp_mib_handler *handler,
			 netsnmp_handler_registration
			 *reginfo,
			 netsnmp_agent_request_info *reqinfo,
			 netsnmp_request_info *requests)
{
  try {
    counting_auto_ptr<Cluster> cluster = monitor.get_cluster();
    if(cluster.get() == NULL)
      return SNMP_ERR_NOERROR;
    
    unsigned int num = cluster->quorate() ? 1 : 0;
    
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */
    
    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
                                 (u_char *)
                                 &num,
                                 sizeof(num));
        break;

    default:
      /*
       * we should never get here, so this is a really bad error 
       */
      return SNMP_ERR_GENERR;
    }
  }
  catch( ... ) {
    return SNMP_ERR_GENERR;
  }
  return SNMP_ERR_NOERROR;
}
