Cisco cbQoS integration
Subscribe

From OpenNMS

Revision as of 08:17, 14 June 2011 by Charlesghopkins (Talk | contribs)

Jump to: navigation, search


Problematics

OpenNMS SNMP grapher/collector is based on assumption, that counters and descriptions of particular probe should contains in the same indexes.

Let's take a look at the Cisco jitter probes:

.1.3.6.1.4.1.9.9.42.1.2.1.1.3.<index> - has describe the probe, while .1.3.6.1.4.1.9.9.42.1.5.2.1.<counter_id>.<index> - contain counters.

In the Cisco class based QoS things are much more complex. It has different groups of counters in one oid, and describe each group in different oid, using different indexes. Also it has reference to parent interface ids, deep down in that structures.

In fact, there is no way to configure OpenNMS to handle that structure and show you something, that make a sense. You still can collect that counters, but you never knows what it meant to be.

Solution

Even where OpenNMS can't do something, and does have not respective API, we can still extend the coding by ourselves :)

The way is:

  • to configure what we can (SNMP data collection and prefabricated graphs)
  • to add lacking functionality (as included JSP)
  • to create an interface where we need new functionality

Configuration

datacollection-config.xml

Include code that configures / extends the respective parts of your datacollection-config.xml

<resourceType name="cbQoSPolicyDescr" label="cbQoS Policy Config Description"
	resourceLabel="${index}">
<persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
<storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
</resourceType>


<resourceType name="cbQoSMonPolicy" label="cbQoS Policy Config"
	resourceLabel="${index}">
<persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
<storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
</resourceType>

<resourceType name="cbQoSCfgCM" label="cbQoS Classmaps Config"
	resourceLabel="${index}">
<persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
<storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
</resourceType>

<resourceType name="cbQoS" label="cbQoS Statistics"
	resourceLabel="${index}">
<persistenceSelectorStrategy class="org.opennms.netmgt.collectd.PersistAllSelectorStrategy"/>
<storageStrategy class="org.opennms.netmgt.dao.support.IndexStorageStrategy"/>
</resourceType>
<group name="cisco-cbqos-config-policy-descr" ifType="all">
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.6.1.1.1" instance="cbQoSPolicyDescr" alias="cbqosPolicyName" type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.6.1.1.2" instance="cbQoSPolicyDescr" alias="cbqosPolicyDescr" type="string" />
</group>
	
<group name="cisco-cbqos-config-policy" ifType="all">
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.1.1.1.2" instance="cbQoSMonPolicy" alias="cbqosIfType" type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.1.1.1.3" instance="cbQoSMonPolicy" alias="cbqosPolicyDirection" type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.1.1.1.4" instance="cbQoSMonPolicy" alias="cbqosIfId" type="string" />
</group>

<group name="cisco-cbqos-config-classmap" ifType="all">
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.7.1.1.1" instance="cbQoSCfgCM" alias="cbqosCMName" type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.7.1.1.2" instance="cbQoSCfgCM" alias="cbqosCMDesc" type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.7.1.1.3" instance="cbQoSCfgCM" alias="cbqosCMInfo" type="string" />
</group>

<group name="cisco-cbqos-stats" ifType="all">
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.5.1.1.2"   instance="cbQoS" alias="cbqosConfId"         type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.5.1.1.3"   instance="cbQoS" alias="cbqosObjectType"     type="string" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.5.1.1.4"   instance="cbQoS" alias="cbqosParentId"    type="string" />

<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.1"  instance="cbQoS" alias="cbqosCMPrePPktOf"    type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.3"  instance="cbQoS" alias="cbqosCMPrePPkt"      type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.4"  instance="cbQoS" alias="cbqosCMPrePByteOf"   type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.6"  instance="cbQoS" alias="cbqosCMPrePByte"     type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.7"  instance="cbQoS" alias="cbqosCMPrePBitR"     type="gauge" />

<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.8"  instance="cbQoS" alias="cbqosCMPostPByteOf"  type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.10" instance="cbQoS" alias="cbqosCMPostPByte"    type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.11" instance="cbQoS" alias="cbqosCMPostPBitR"    type="gauge" />

<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.12" instance="cbQoS" alias="cbqosCMDropPktOf"    type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.14" instance="cbQoS" alias="cbqosCMDropPkt"      type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.15" instance="cbQoS" alias="cbqosCMDropByteOf"   type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.17" instance="cbQoS" alias="cbqosCMDropByte"     type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.18" instance="cbQoS" alias="cbqosCMDropBitR"     type="gauge" />

<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.19" instance="cbQoS" alias="cbqosCMNBufDrPktOf"  type="counter" />
<mibObj oid=".1.3.6.1.4.1.9.9.166.1.15.1.1.21" instance="cbQoS" alias="cbqosCMNBufDrPkt"    type="counter" />
</group>
<includeGroup>cisco-cbqos-config-policy</includeGroup>
<includeGroup>cisco-cbqos-config-classmap</includeGroup>
<includeGroup>cisco-cbqos-stats</includeGroup>

snmp-graph.properties

Include code that configures / extends the respective parts of your snmp-graph.properties

cisco.cbQoS.class.pkt, cisco.cbQoS.class.pktof, cisco.cbQoS.class.byte, cisco.cbQoS.class.byteof, cisco.cbQoS.class.bit, \
report.cisco.cbQoS.class.pkt.name=cbQoS Packets
report.cisco.cbQoS.class.pkt.columns=cbqosCMPrePPkt,cbqosCMDropPkt,cbqosCMNBufDrPkt
report.cisco.cbQoS.class.pkt.type=cbQoS
report.cisco.cbQoS.class.pkt.command=--title="cbQoS Packets" \
--vertical-label packets/sec \
DEF:pre={rrd1}:cbqosCMPrePPkt:AVERAGE \
DEF:drop={rrd2}:cbqosCMDropPkt:AVERAGE \
DEF:nobuf={rrd3}:cbqosCMNBufDrPkt:AVERAGE \
AREA:pre#00dd00:"PrePolicy  " \
GPRINT:pre:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:pre:MIN:"Min  \\: %8.2lf %s" \
GPRINT:pre:MAX:"Max  \\: %8.2lf %s\\n"  \
LINE2:drop#ff0000:"Dropped     " \
GPRINT:drop:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:drop:MIN:"Min  \\: %8.2lf %s" \
GPRINT:drop:MAX:"Max  \\: %8.2lf %s\\n" \
LINE1:nobuf#440000:"NoBuff     " \
GPRINT:nobuf:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:nobuf:MIN:"Min  \\: %8.2lf %s" \
GPRINT:nobuf:MAX:"Max  \\: %8.2lf %s\\n"

report.cisco.cbQoS.class.pktof.name=cbQoS Packets Overflow
report.cisco.cbQoS.class.pktof.columns=cbqosCMPrePPktOf,cbqosCMDropPktOf,cbqosCMNBufDrPktOf
report.cisco.cbQoS.class.pktof.type=cbQoS
report.cisco.cbQoS.class.pktof.command=--title="cbQoS Packets Overflow" \
--vertical-label packets/sec \
DEF:pre={rrd1}:cbqosCMPrePPktOf:AVERAGE \
DEF:drop={rrd2}:cbqosCMDropPktOf:AVERAGE \
DEF:nobuf={rrd3}:cbqosCMNBufDrPktOf:AVERAGE \
AREA:pre#00dd00:"PrePolicy  " \
GPRINT:pre:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:pre:MIN:"Min  \\: %8.2lf %s" \
GPRINT:pre:MAX:"Max  \\: %8.2lf %s\\n"  \
LINE2:drop#ff0000:"Dropped     " \
GPRINT:drop:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:drop:MIN:"Min  \\: %8.2lf %s" \
GPRINT:drop:MAX:"Max  \\: %8.2lf %s\\n" \
LINE1:nobuf#440000:"NoBuff     " \
GPRINT:nobuf:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:nobuf:MIN:"Min  \\: %8.2lf %s" \
GPRINT:nobuf:MAX:"Max  \\: %8.2lf %s\\n"

report.cisco.cbQoS.class.byte.name=cbQoS Bytes
report.cisco.cbQoS.class.byte.columns=cbqosCMPrePByte,cbqosCMPostPByte,cbqosCMDropByte
report.cisco.cbQoS.class.byte.type=cbQoS
report.cisco.cbQoS.class.byte.command=--title="cbQoS Bytes" \
--vertical-label bytes/sec \
DEF:pre={rrd1}:cbqosCMPrePByte:AVERAGE \
DEF:post={rrd2}:cbqosCMPostPByte:AVERAGE \
DEF:drop={rrd3}:cbqosCMDropByte:AVERAGE \
AREA:pre#00dd00:"PrePolicy   " \
GPRINT:pre:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:pre:MIN:"Min  \\: %8.2lf %s" \
GPRINT:pre:MAX:"Max  \\: %8.2lf %s\\n" \
LINE1:post#0000ff:"PostPolicy  " \
GPRINT:post:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:post:MIN:"Min  \\: %8.2lf %s" \
GPRINT:post:MAX:"Max  \\: %8.2lf %s\\n" \
LINE2:drop#ff0000:"Dropped      " \
GPRINT:drop:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:drop:MIN:"Min  \\: %8.2lf %s" \
GPRINT:drop:MAX:"Max  \\: %8.2lf %s\\n"

report.cisco.cbQoS.class.byteof.name=cbQoS Bytes Overflow
report.cisco.cbQoS.class.byteof.columns=cbqosCMPrePByteOf,cbqosCMPostPByteOf,cbqosCMDropByteOf
report.cisco.cbQoS.class.byteof.type=cbQoS
report.cisco.cbQoS.class.byteof.command=--title="cbQoS Bytes Overflow" \
--vertical-label bytes/sec \
DEF:pre={rrd1}:cbqosCMPrePByteOf:AVERAGE \
DEF:post={rrd2}:cbqosCMPostPByteOf:AVERAGE \
DEF:drop={rrd3}:cbqosCMDropByteOf:AVERAGE \
AREA:pre#00dd00:"PrePolicy   " \
GPRINT:pre:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:pre:MIN:"Min  \\: %8.2lf %s" \
GPRINT:pre:MAX:"Max  \\: %8.2lf %s\\n" \
LINE1:post#0000ff:"PostPolicy  " \
GPRINT:post:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:post:MIN:"Min  \\: %8.2lf %s" \
GPRINT:post:MAX:"Max  \\: %8.2lf %s\\n" \
LINE2:drop#ff0000:"Dropped      " \
GPRINT:drop:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:drop:MIN:"Min  \\: %8.2lf %s" \
GPRINT:drop:MAX:"Max  \\: %8.2lf %s\\n"

report.cisco.cbQoS.class.bit.name=cbQoS BitRates
report.cisco.cbQoS.class.bit.columns=cbqosCMPrePBitR,cbqosCMPostPBitR,cbqosCMDropBitR
report.cisco.cbQoS.class.bit.type=cbQoS
report.cisco.cbQoS.class.bit.command=--title="cbQoS BitRates" \
--vertical-label="bitrate" \
DEF:pre={rrd1}:cbqosCMPrePBitR:AVERAGE \
DEF:post={rrd2}:cbqosCMPostPBitR:AVERAGE \
DEF:drop={rrd3}:cbqosCMDropBitR:AVERAGE \
AREA:pre#00dd00:"PrePolicy   " \
GPRINT:pre:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:pre:MIN:"Min  \\: %8.2lf %s" \
GPRINT:pre:MAX:"Max  \\: %8.2lf %s\\n" \
LINE1:post#0000ff:"PostPolicy  " \
GPRINT:post:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:post:MIN:"Min  \\: %8.2lf %s" \
GPRINT:post:MAX:"Max  \\: %8.2lf %s\\n" \
LINE2:drop#ff0000:"Dropped      " \
GPRINT:drop:AVERAGE:"Avg  \\: %8.2lf %s" \
GPRINT:drop:MIN:"Min  \\: %8.2lf %s" \
GPRINT:drop:MAX:"Max  \\: %8.2lf %s\\n"

Installation

Create the file <opennms>/[jetty-]webapps/opennms/includes/cbqos.jsp and fill it with the following code:

<%
  String nodeid = request.getParameter("node");
  String resourceLabel = request.getParameter("resource");

  if( nodeid == null ) {
    throw new MissingParameterException("node");
  }
  String selectlist = "";

  WebApplicationContext webAppContext = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
  ResourceService resourceService = (ResourceService)webAppContext.getBean("resourceService", ResourceService.class);
  RrdDao rrdDao = (RrdDao)webAppContext.getBean("rrdDao", RrdDao.class);
  File rrdDir = new File(resourceService.getRrdDirectory(), "snmp");
  PropertiesCache s_cache = new PropertiesCache();

    Map<String, String> resourceLables = new HashMap<String, String>();
    Map<Integer, Interface> ifaces = new HashMap<Integer, Interface>();
    Map<String, Map> cbqos_policy = new HashMap<String, Map>();
    Map<String, Map> cbqos_class = new HashMap<String, Map>();
    Map<String, Map> policy_props = new HashMap<String, Map>();
    Map<String, Map> class_props = new HashMap<String, Map>();
    Set<String> usable_ifaces = new HashSet<String>();

    OnmsResource node = resourceService.getResourceById(nodeid);
    String node_name = node.toString();
    Matcher mnode = Pattern.compile("node\\[(\\d+)\\]").matcher(node_name);
    boolean node_status = mnode.matches();
    String node_index = mnode.group(1);

    selectlist += "<h3>cbQoS Statistics</h3>";

    for (Interface iface : NetworkElementFactory.getActiveInterfacesOnNode(Integer.parseInt(node_index))) {
      ifaces.put(iface.getIfIndex(), iface);
    }

    List<OnmsResource> resourcesx = resourceService.findChildResources(node, "cbQoS");

    // Set [class_id = Set [class_resource_id, class_name, child_policy_id]]
    Map <String, Set <String[]>> classes = new HashMap<String, Set<String[]>>();

    // Set [policy_id = Set [class_id, object_type (1 == policy), policy_name ]]
    Map <String, Set <String[]>> policies = new HashMap<String, Set<String[]>>();

    // Set [interface_name = Set [policy_id, policy_direction, ]]
    Map <String, Set <String[]>> cbqos_ifaces = new HashMap<String, Set<String[]>>();

    for (OnmsResource resource : resourcesx) {
      Map <String, String> _attributes = resource.getStringPropertyAttributes();
      if (_attributes.get("cbqosObjectType").equals("2")) {
        Matcher _ids = Pattern.compile("node\\[\\d+\\]\\.cbQoS\\[(\\d+)\\.(\\d+)\\]").matcher(resource.toString());
        boolean _matches = _ids.matches();
        String _bush_id = _ids.group(1);
        String _id = _bush_id + "." + _ids.group(2);
        String _conf = _attributes.get("cbqosConfId");
        String _parent = _bush_id + "." + _attributes.get("cbqosParentId");

        File _CfgCM_file = new File(rrdDir, node_index +"/cbQoSCfgCM/" + _conf + "/strings.properties");
        String cbqos_classname = s_cache.getProperty(_CfgCM_file, "cbqosCMName");
        _CfgCM_file = null;

        Set <String[]> _res = new HashSet<String[]>();
        if (classes.containsKey(_parent)) {
          _res = classes.remove(_parent);
        }
        String[] _props = {resource.toString(), cbqos_classname, _id};
        _res.add(_props);
        classes.put(_parent, _res);
      }
    }
    for (String pid : classes.keySet()) {
      File _policy_file =  new File(rrdDir, node_index +"/cbQoS/" + pid + "/strings.properties");
      Map _policy_props = s_cache.getProperties(_policy_file);
      String _parent_suf = s_cache.getProperty(_policy_file, "cbqosParentId");
      String _parent_pref = pid.split("\\.")[0];
      String _parent = _parent_pref + "." + _parent_suf;
      String _policy_conf = s_cache.getProperty(_policy_file, "cbqosConfId");
      String _policy_type = s_cache.getProperty(_policy_file, "cbqosObjectType");

      if (_parent_suf.equals("0")) {
        File _policy_cfg_file = new File(rrdDir, node_index +"/cbQoSMonPolicy/" + _parent_pref + "/strings.properties");
        Map _policy_cfg_props = s_cache.getProperties(_policy_cfg_file);
        String _policy_cfg_iface = s_cache.getProperty(_policy_cfg_file, "cbqosIfId");
        String _policy_cfg_direction = s_cache.getProperty(_policy_cfg_file, "cbqosPolicyDirection");
        if (_policy_cfg_direction.equals("1")) {
          _policy_cfg_direction = "[in]";
        } else if (_policy_cfg_direction.equals("2")) {
          _policy_cfg_direction = "[out]";
        } else {
          _policy_cfg_direction = "[]";
        }

        String _iface_fullname = "";
        if (ifaces.containsKey(Integer.parseInt(_policy_cfg_iface))) {
          Interface _iface = ifaces.get(Integer.parseInt(_policy_cfg_iface));
          String _iface_name = _iface.getSnmpIfName();
          String _iface_addr = _iface.getIpAddress();
          if (_iface_name != null && _iface_name != "") {
            _iface_fullname += _iface_name + " ";
          }
          if (_iface_addr != "0.0.0.0") {
            _iface_fullname += "(" + _iface_addr + ")";
          }
        } else {
          _iface_fullname = "unknown iface " + _policy_cfg_iface;
        }
        Set <String[]> _res = new HashSet<String[]>();
        if (cbqos_ifaces.containsKey(_iface_fullname)) {
          _res = cbqos_ifaces.remove(_iface_fullname);
        }
        String[] _props = {_parent, _policy_cfg_direction, ""};
        _res.add(_props);
        cbqos_ifaces.put(_iface_fullname, _res);

      }

      File _policy_descr_file =  new File(rrdDir, node_index +"/cbQoSPolicyDescr/" + _policy_conf + "/strings.properties");
      String _policy_descr_name = s_cache.getProperty(_policy_descr_file, "cbqosPolicyName");

      Set <String[]> _res = new HashSet<String[]>();
      if (policies.containsKey(_parent)) {
        _res = policies.remove(_parent);
      }
      String[] _props = {pid, _policy_type, _policy_descr_name};
      _res.add(_props);
      policies.put(_parent, _res);
    }

    for (Map.Entry <String, Set <String[]>> entry : cbqos_ifaces.entrySet()) {
      String iface_id = entry.getKey();
      selectlist += "<div style=\"float: left; margin: 0 0 0 11px\"><div>" + iface_id + "</div>";
      selectlist += "<select multiple=\"\"  size=\"\" name=\"resourceId\">";
      for (String[] policy_prop : entry.getValue()) {
        for (String[] policy : policies.get(policy_prop[0])) {
          selectlist += "<optgroup label=\"" + policy[2] + "\">";
          if (classes.containsKey(policy[0])) {
            for (String[] cbclass : classes.get(policy[0])) {
              selectlist += "<option value=\"" + cbclass[0] + "\">" + cbclass[1] + "</option>";
              resourceLables.put(cbclass[0], iface_id + ": " + policy[2] + " > " + cbclass[1]);
              if (policies.containsKey(cbclass[2])) {
                for (String[] subpolicy : policies.get(cbclass[2])) {
                  selectlist += "<optgroup label=\"[" + policy[2] + " > " + cbclass[1] +
                  "]: " + subpolicy[2] + " \">";
                  if (classes.containsKey(subpolicy[0])) {
                    for (String[] subcbclass : classes.get(subpolicy[0])) {
                      selectlist += "<option value=\"" + subcbclass[0] + "\">[" + policy[2] +
                      " > " + cbclass[1] + "]: " + subcbclass[1] + " </option>";
                      resourceLables.put(subcbclass[0], iface_id + ": [" + policy[2] +
                      " > " + cbclass[1] + "]: " + subpolicy[2] + " > " + subcbclass[1]);
                    }
                  }
                  selectlist += "</optgroup>";
                }
              }
            }
          }
          selectlist += "</optgroup>";
        }
      }
      selectlist += "</select></div>";
    }
    selectlist += "<div style=\"clear: left\" />";

    if (resourceLabel == null ) {
      out.print(selectlist);
    } else {
      if (!resourceLables.containsKey(resourceLabel)) {
        out.print("cbQoS Statistics: unknown resource");
      } else {
        out.print(resourceLables.get(resourceLabel));
      }
    }
%>
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@page import="
  java.io.Reader,
  java.io.File,
  java.io.FileReader,
  java.io.FileInputStream,
  java.util.*,
  java.util.regex.*,
  java.net.*,
  org.opennms.web.*,
  org.opennms.web.element.*,
  org.opennms.web.acegisecurity.Authentication.*,
  org.opennms.web.svclayer.ResourceService,
  org.opennms.netmgt.dao.RrdDao,
  org.opennms.netmgt.dao.ResourceDao,
  org.opennms.core.utils.PropertiesCache,
  org.opennms.netmgt.model.OnmsNode,
  org.opennms.netmgt.model.OnmsResource,
  org.opennms.netmgt.model.OnmsResourceType,
  org.springframework.web.context.WebApplicationContext,
  org.springframework.web.context.support.WebApplicationContextUtils"%>

Patching

cd to the directory <opennms>/[jetty-]webapps/opennms/WEB-INF/jsp/graph

chooseresource.jsp

Make a patch:

--- chooseresource.orig 2010-07-07 14:40:57.000000000 -0500
+++ chooseresource.jsp  2010-07-07 14:48:38.000000000 -0500
@@ -205,40 +205,52 @@
 
       <p>
         Please choose one or more resources that you wish to query.
       </p>
 
       <form method="get" name="report" action="${model.endUrl}">
         <%=Util.makeHiddenTags(request, new String[] { "parentResourceId", "parentResourceType", "parentResource", "endUrl" })%>
   
         <c:set var="num" value="0"/>
         <c:forEach var="resourceType" items="${model.resourceTypes}">
+        <c:choose>
+        <c:when test="${resourceType.key.label == \"cbQoS Statistics\"}" >
+          <jsp:include page="/includes/cbqos.jsp" flush="false" >
+            <jsp:param name="node" value="${model.resource.id}" />
+          </jsp:include>
+
+        </c:when>
+        <c:otherwise>
+
           <h3 class="o-box">${resourceType.key.label}</h3>
 
           <c:choose>
             <c:when test="${fn:length(resourceType.value) < 10}">
               <c:set var="selectSize" value="${resource.count}"/>
             </c:when>
             
             <c:otherwise>
               <c:set var="selectSize" value="10"/>
             </c:otherwise>
           </c:choose>
         
           <select name="resourceId" id="resource-select-${num}" size="${selectSize}" multiple>
             <c:forEach var="resource" items="${resourceType.value}">
               <option value="${resource.id}">
                 ${resource.label}
               </option>
             </c:forEach>
           </select>
         
+        </c:otherwise>
+        </c:choose>
+
           <c:set var="num" value="${num + 1}"/>
         </c:forEach>
       
         <br/>
         <br/>
         <input type="submit" value="Submit" onclick="submitForm(document.report.resourceId, document.report, 'resource')" />
         <input type="button" value="Select All" onclick="selectAll('resourceId', true)" />
         <input type="button" value="Unselect All" onclick="selectAll('resourceId', false)" />
       </form>
       

results.jsp

Make a patch:

--- results.orig        2010-07-07 14:49:16.000000000 -0500
+++ results.jsp 2010-07-07 14:51:19.000000000 -0500
@@ -176,11 +176,21 @@
         <br />
         ${resultSet.resource.resourceType.label}:
         <c:choose>
-          <c:when test="${(!empty resultSet.resource.link) && loggedIn}">
-            <a href="<c:url value='${resultSet.resource.link}'/>">${resultSet.resource.label}</a>
+          <c:when test="${resultSet.resource.resourceType.label == 'cbQoS Statistics'}">
+            <jsp:include page="/includes/cbqos.jsp" flush="false" >
+              <jsp:param name="node" value="${resultSet.resource.parent.id}" />
+              <jsp:param name="resource" value="${resultSet.resource.id}" />
+            </jsp:include>
           </c:when>
           <c:otherwise>
-            ${resultSet.resource.label}
+            <c:choose>
+              <c:when test="${!empty resultSet.resource.link}">
+                <a href="<c:url value='${resultSet.resource.link}'/>">${resultSet.resource.label}</a>
+              </c:when>
+              <c:otherwise>
+                ${resultSet.resource.label}
+              </c:otherwise>
+            </c:choose>
           </c:otherwise>
         </c:choose>
       </c:if>

Enjoy

If you do things right, and I didn't mess up :) you should see something like this:

  • in graph/chooseresource.htm (Home / Reports / Resource Graphs / Results)

Cbqos demo chooseresource.png

  • in graph/results.htm (Home / Reports / Resource Graphs / Choose)

Cbqos demo results.png

Limits and bugs

This solution is limited to:

  • *nix filesystems (ready for windows, do you want to test it?)
  • it graphs only two levels of cbQoS classes tree, and ignore the others

Limits can be resolved, if there is some testers to make it works in mentioned environments.

Further integration (developers notes)

If there is someone, who considered of patching that functionality in to source three, i have a statement to publicize:

There is more things, along cbQoS, who needs much more complex handling, than OpenNMS default model can acquire. It would be nice to implement some sort of plugin model, that give the ability to include homemade JSP to the problematic places of the interface, without the needs of rehacking the code. And i can give you some different ideas howto implement that model, if you interested.

Contacts

You can mail me to oziabr.gmail.com