Merge pull request #146 from kenchiang/onlp-snmp

Add CpuAllPercentUtilization and CpuAllPercentIdle.
This commit is contained in:
Jeffrey Townsend
2016-12-20 10:23:19 -08:00
committed by GitHub
8 changed files with 162 additions and 4 deletions

View File

@@ -34,7 +34,7 @@ CpuAllPercentUtilization OBJECT-TYPE
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The average CPU utilization (in percent). Provided by mpstat."
"The average CPU utilization in percent, multiplied by 100 and rounded to the nearest integer. Provided by mpstat."
::= { Basic 1 }
CpuAllPercentIdle OBJECT-TYPE
@@ -42,7 +42,7 @@ CpuAllPercentIdle OBJECT-TYPE
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"The average CPU idle time (in percent). Provided by mpstat."
"The average CPU idle time in percent, multiplied by 100 and rounded to the nearest integer. Provided by mpstat."
::= { Basic 2 }
END

View File

@@ -16,6 +16,7 @@ packages:
files:
builds/$BUILD_DIR/${TOOLCHAIN}/bin/onlp-snmpd: /usr/bin/onlp-snmpd
${ONL}/packages/base/any/onlp-snmpd/bin/onl-snmpwalk : /usr/bin/onl-snmpwalk
${ONL}/packages/base/any/onlp-snmpd/bin/onl-snmp-mpstat : /usr/bin/onl-snmp-mpstat
init: ${ONL}/packages/base/any/onlp-snmpd/onlp-snmpd.init

View File

@@ -0,0 +1,33 @@
#!/usr/bin/python
# call mpstat and generate json output containing stats for all cpus
"""
sample output from "mpstat 1 1":
# mpstat 1 1
Linux 3.8.13-OpenNetworkLinux-e500mc-1.5 (as6700-3) 2016-12-15 _ppc_(4 CPU)
04:59:31 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
04:59:32 PM all 5.17 0.00 2.07 0.00 0.00 0.00 0.00 0.00 92.76
Average: all 5.17 0.00 2.07 0.00 0.00 0.00 0.00 0.00 92.76
"""
import subprocess
import json
stats = {}
# 1 second interval, 1 count
out = subprocess.check_output(['mpstat','1','1'])
for line in out.split('\n'):
if "%idle" in line:
# extract keys from header line, skipping over time and AM/PM
keys = line.split()[2:]
if "Average" in line:
vals = line.split()[1:]
stats[vals[0]] = { k:int(round(100*float(v))) \
for (k,v) in zip(keys[1:],vals[1:]) }
print json.dumps(stats)

View File

@@ -3,7 +3,7 @@ include $(ONL)/make/any.mk
MODULE := onlp-snmpd
include $(BUILDER)/standardinit.mk
DEPENDMODULES := onlp_snmp AIM OS snmp_subagent IOF onlplib
DEPENDMODULES := onlp_snmp AIM OS snmp_subagent IOF onlplib cjson cjson_util
DEPENDMODULE_HEADERS := onlp
include $(BUILDER)/dependmodules.mk

View File

@@ -56,6 +56,9 @@ cdefs: &cdefs
- ONLP_SNMP_CONFIG_AS_SUBAGENT:
doc: "Configure as an snmp_subagent client."
default: 0
- ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS:
doc: "Resource object update period in seconds."
default: 5
definitions:
cdefs:

View File

@@ -191,6 +191,16 @@
#define ONLP_SNMP_CONFIG_AS_SUBAGENT 0
#endif
/**
* ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS
*
* Resource object update period in seconds. */
#ifndef ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS
#define ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS 5
#endif
/**

View File

@@ -94,6 +94,11 @@ onlp_snmp_config_settings_t onlp_snmp_config_settings[] =
{ __onlp_snmp_config_STRINGIFY_NAME(ONLP_SNMP_CONFIG_AS_SUBAGENT), __onlp_snmp_config_STRINGIFY_VALUE(ONLP_SNMP_CONFIG_AS_SUBAGENT) },
#else
{ ONLP_SNMP_CONFIG_AS_SUBAGENT(__onlp_snmp_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS
{ __onlp_snmp_config_STRINGIFY_NAME(ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS), __onlp_snmp_config_STRINGIFY_VALUE(ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS) },
#else
{ ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS(__onlp_snmp_config_STRINGIFY_NAME), "__undefined__" },
#endif
{ NULL, NULL }
};

View File

@@ -25,6 +25,9 @@
#include <onlp_snmp/onlp_snmp_config.h>
#include "onlp_snmp_log.h"
#include <AIM/aim_time.h>
#include <cjson/cJSON.h>
#include <cjson_util/cjson_util.h>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
@@ -54,7 +57,7 @@ platform_string_register(int index, const char* desc, char* value)
netsnmp_register_watched_scalar( reg, winfo );
}
void
static void
platform_int_register(int index, char* desc, int value)
{
oid tree[] = { 1, 3, 6, 1, 4, 1, 42623, 1, 1, 1, 1, 1};
@@ -69,6 +72,106 @@ platform_int_register(int index, char* desc, int value)
v, NULL);
}
static void
resource_int_register(int index, const char* desc,
Netsnmp_Node_Handler *handler)
{
oid tree[] = { 1, 3, 6, 1, 4, 1, 42623, 1, 3, 1, 1 };
tree[10] = index;
netsnmp_handler_registration *reg =
netsnmp_create_handler_registration(desc, handler,
tree, OID_LENGTH(tree),
HANDLER_CAN_RONLY);
if (netsnmp_register_scalar(reg) != MIB_REGISTERED_OK) {
AIM_LOG_ERROR("registering handler for %s failed", desc);
}
}
/* resource objects */
typedef struct {
uint32_t utilization_percent;
uint32_t idle_percent;
} resources_t;
static resources_t resources;
static uint64_t resource_update_time;
void resource_update(void)
{
uint64_t now = aim_time_monotonic();
if (now - resource_update_time >
(ONLP_SNMP_CONFIG_RESOURCE_UPDATE_SECONDS * 1000 * 1000)) {
resource_update_time = now;
AIM_LOG_INFO("update resource objects");
/* invoke mpstat collection script for json output */
FILE *fp = popen("/usr/bin/onl-snmp-mpstat", "r");
if (fp == NULL) {
AIM_LOG_ERROR("failed invoking onl-snmp-mpstat");
return;
}
/* parse json output */
char line[1024];
while (fgets(line, sizeof(line), fp) != NULL) {
cJSON *root = cJSON_Parse(line);
int result;
int rv = cjson_util_lookup_int(root, &result, "all.%%idle");
if (rv == 0) {
/* save it */
resources.idle_percent = result;
resources.utilization_percent = 100*100 - result;
}
cJSON_Delete(root);
}
}
}
static int
utilization_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
if (MODE_GET == reqinfo->mode) {
resource_update();
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
(u_char *) &resources.utilization_percent,
sizeof(resources.utilization_percent));
} else {
netsnmp_assert("bad mode in RO handler");
}
if (handler->next && handler->next->access_method) {
return netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
}
return SNMP_ERR_NOERROR;
}
static int
idle_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
if (MODE_GET == reqinfo->mode) {
resource_update();
snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE,
(u_char *) &resources.idle_percent,
sizeof(resources.idle_percent));
} else {
netsnmp_assert("bad mode in RO handler");
}
if (handler->next && handler->next->access_method) {
return netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
}
return SNMP_ERR_NOERROR;
}
void
onlp_snmp_platform_init(void)
@@ -110,5 +213,8 @@ onlp_snmp_platform_init(void)
REGISTER_STR(14, service_tag);
REGISTER_STR(15, onie_version);
}
resource_int_register(1, "CpuAllPercentUtilization", utilization_handler);
resource_int_register(2, "CpuAllPercentIdle", idle_handler);
}