Commit 0228d2dd authored by Pavel Vainerman's avatar Pavel Vainerman

(netdata-plugin): Вариант на основе запуска uniset2-admin

parent 527661d2
......@@ -52,6 +52,7 @@ static struct option longopts[] =
{ "oinfo", required_argument, 0, 'p' },
{ "verbose", no_argument, 0, 'v' },
{ "quiet", no_argument, 0, 'q' },
{ "csv", required_argument, 0, 'z' },
{ NULL, 0, 0, 0 }
};
......@@ -117,6 +118,7 @@ static void usage()
print_help(36, "-t|--getChangedTime id1@node1,id2@node2,id3,.. ", "Получить время последнего изменения.\n");
print_help(36, "-v|--verbose", "Подробный вывод логов.\n");
print_help(36, "-q|--quiet", "Выводит только результат.\n");
print_help(36, "-z|--csv", "Вывести результат (getValue) в виде val1,val2,val3...\n");
cout << endl;
}
......@@ -129,6 +131,7 @@ static void usage()
// --------------------------------------------------------------------------------------
static bool verb = false;
static bool quiet = false;
static bool csv = false;
int main(int argc, char** argv)
{
......@@ -141,7 +144,7 @@ int main(int argc, char** argv)
while(1)
{
opt = getopt_long(argc, argv, "hc:beosfur:l:i::x:g:w:y:p:vq", longopts, &optindex);
opt = getopt_long(argc, argv, "hc:beosfur:l:i::x:g:w:y:p:vqz:", longopts, &optindex);
if( opt == -1 )
break;
......@@ -190,7 +193,10 @@ int main(int argc, char** argv)
break;
case 'g': //--getValue
case 'z': //--csv
{
if( opt == 'z' )
csv = true;
// cout<<"(main):received option --getValue='"<<optarg<<"'"<<endl;
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
......@@ -666,9 +672,14 @@ int getValue( const string& args, UInterface& ui )
auto conf = ui.getConf();
auto sl = UniSetTypes::getSInfoList( args, conf );
if( csv )
quiet = true;
if( !quiet )
cout << "====== getValue ======" << endl;
size_t num = 0;
for( auto && it : sl )
{
try
......@@ -694,8 +705,19 @@ int getValue( const string& args, UInterface& ui )
if( !quiet )
cout << " value: " << ui.getValue(it.si.id, it.si.node) << endl;
else
cout << ui.getValue(it.si.id, it.si.node);
{
if( csv )
{
// т.к. может сработать исключение, а нам надо вывести ','
// до числа, то сперва получаем val
long val = ui.getValue(it.si.id, it.si.node);
if( csv && num++ > 0 )
cout << ",";
cout << val;
}
else
cout << ui.getValue(it.si.id, it.si.node);
}
break;
default:
......
......@@ -11,6 +11,7 @@ ln -s -f admin.sh omap
ln -s -f admin.sh msgmap
ln -s -f admin.sh setValue
ln -s -f admin.sh getValue
ln -s -f admin.sh csv
ln -s -f admin.sh getRawValue
ln -s -f admin.sh getChangedTime
ln -s -f admin.sh getCalibrate
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------------------------------------
# Description: uniset netdata python.d module
# Author: Pavel Vainerman (pv)
# ----------------------------------------------------------------------------------------------------------
# Вариант на основе запуска uniset2-admin --сsv id1,id2,id3...
# ----------------------------------------------------------------------------------------------------------
# В configure.xml проекта ождается секция <netdata> описывающая
# charts и параметры.
# <netdata>
# <!-- https://github.com/firehol/netdata/wiki/External-Plugins -->
# <!-- CHART type.id name title units [family [context [charttype [priority [update_every]]]]] -->
# <chart id='unet' name='Temperature' title="Temperature" units='°С' context='' charttype='area' priority='' update_every=''>
#
# <!-- Чтобы иметь возможность выводить на одном чарте, разные группы можно указывать много 'line' -->
#
# <!-- Параметры берутся из <sensors> в виду netdata_xxx (необязательные помечены []
# В качестве id - берётся name.
# В качестве name - берётся name, если не указан netdata_name=''
# -->
# <!-- DIMENSION id [name [algorithm [multiplier [divisor [hidden]]]]] -->
# <lines filter_field='ndata' filter_value='temp'/>
# </chart>
# </netdata>
#
# TODO: можно сделать вариант со специальным UniSetNetDataServer
# ----------------------------------------------------------------------------------------------------------
import os
import sys
import random
import uniset2
from uniset2 import UniXML
from uniset2 import UProxyObject
from uniset2 import UConnector
from subprocess import Popen, PIPE
sys.path.append("./python_modules")
from base import SimpleService
from base import ExecutableService
NAME = os.path.basename(__file__).replace(".chart.py", "")
......@@ -21,18 +43,14 @@ update_every = 5
priority = 90000
retries = 60
class Service(SimpleService):
sensors = []
uproxy = None
uconnector = None
smOK = False
class Service(ExecutableService):
def __init__(self, configuration=None, name=None):
super(self.__class__, self).__init__(configuration=configuration, name=name)
conf = self.configuration.pop
confile = None
try:
confile = conf('confile')
except KeyError:
......@@ -43,36 +61,31 @@ class Service(SimpleService):
self.error("uniset plugin: Not found confile '%s'"%confile)
raise RuntimeError
#self.name = self.get_conf_param('name', name)
self.sensors = []
self.confile = confile;
self.info("%s: read from %s"%(name,confile))
self.create_charts(confile)
self.init_uniset(confile)
# добавляем датчики в опрос..
for s in self.sensors:
self.uproxy.addToAsk(s[1])
def init_uniset(self, confile):
uniset_port = self.get_conf_param('port', '')
arglist= uniset2.Params_inst()
for i in range(0, len(sys.argv)):
if i >= uniset2.Params.max:
break;
arglist.add(sys.argv[i])
idlist = ''
num = 0
for nid,sid in self.sensors:
if num == 0:
idlist="%s"%str(sid)
num += 1
else:
idlist += ",%s"%str(sid)
port = self.get_conf_param('port', '')
if port != '':
p = '--uniset-port'
arglist.add_str(p)
arglist.add_str( str(port) )
uniset_command = self.get_conf_param('uniset_command',"/usr/bin/uniset2-admin --confile %s"%(self.confile))
uname = self.get_conf_param('uname', 'TestProc')
command = "%s --csv %s"%(uniset_command,idlist)
if uniset_port!=None and uniset_port!='':
command += " --uniset-port %s"%uniset_port
try:
self.uconnector = UConnector(arglist,confile)
self.uproxy = UProxyObject(uname)
except uniset2.UException, e:
self.error("uniset plugin: error: %s"% e.getError())
raise RuntimeError
self.configuration['command'] = command
self.command = command
self.info("Update command: %s"%command)
def get_conf_param(self, propname, defval):
try:
......@@ -86,7 +99,7 @@ class Service(SimpleService):
def find_section(self, xml, secname):
node = xml.findNode(xml.getDoc(), secname)[0]
if node == None:
self.error("not found '%s' section in %s" % (secname,xml.getFileName()))
self.error("not found section <%s> in confile '%s'" % (secname,xml.getFileName()))
raise RuntimeError
return node.children
......@@ -107,7 +120,7 @@ class Service(SimpleService):
# CHART type.id name title units [family [context [charttype [priority [update_every]]]]]
id = node.prop('id')
if id == '' or id == None:
self.error("IGNORE CHART.. Unknown id=''.")
self.error("IGNORE CHART.. Unknown id=''")
node = xml.nextNode(node)
continue
......@@ -214,62 +227,76 @@ class Service(SimpleService):
return True
def check(self):
def _get_data(self):
data = {}
self.info("**** uniset_activate_objects")
# ret = super(self.__class__, self).check()
try:
self.uconnector.activate_objects()
except uniset2.UException, e:
self.error("%s"% e.getError())
raise False
raw = self._get_raw_data()
return True
if raw == None or len(raw) == 0:
return {}
def _get_data(self):
raw = raw[-1].split(',')
data = {}
if len(raw) < len(self.sensors):
if len(raw) > 0:
self.debug("_get_data ERROR: len data=%d < len sensors=%d"%(len(raw),len(self.sensors)))
return {}
for netid,id in self.sensors:
data[netid] = self.uproxy.getValue(id)
i = 0
for id,sid in self.sensors:
data[id] = raw[i]
i += 1
if len(data) == 0:
return None
except (ValueError, AttributeError):
return {}
return data
def update(self, interval):
def _get_raw_data(self):
"""
Get raw data from executed command
:return: str
"""
try:
p = Popen(self.command, shell=True, stdout=PIPE, stderr=PIPE)
except Exception as e:
self.error("Executing command", self.command, "resulted in error:", str(e))
return None
if not self.uproxy.askIsOK() and not self.uproxy.reaskSensors():
return False
data = []
for line in p.stdout.readlines():
data.append(str(line.decode()))
prev_smOK = self.smOK
self.smOK = self.uproxy.smIsOK()
if len(data) == 0:
# self.error("No data collected.")
return None
if prev_smOK != self.smOK and self.smOK:
self.info("SM exist OK. Reask sensors..")
self.uproxy.reaskSensors()
return data
return super(self.__class__, self).update(interval)
def check(self):
# Считаем что у нас всегда, всё хорошо, даже если SM недоступна
return True
if __name__ == "__main__":
config = {}
config['confile'] = './test.xml'
config['port'] = 2809
config['uname'] = 'TestProc'
config['update_every'] = update_every
config['priority'] = priority
config['retries'] = retries
serv = Service(config,"test")
config2 = {}
config2['confile'] = './test.xml'
config2['port'] = 2809
config2['uname'] = 'TestProc1'
config2['update_every'] = update_every
config2['priority'] = priority
config2['retries'] = retries
serv2 = Service(config2,"test")
config = {}
config['confile'] = './test.xml'
config['port'] = 53817
config['uname'] = 'TestProc'
config['update_every'] = update_every
config['priority'] = priority
config['retries'] = retries
serv = Service(config,"test")
# config2 = {}
# config2['confile'] = './test.xml'
# config2['port'] = 52809
# config2['uname'] = 'TestProc1'
# config2['update_every'] = update_every
# config2['priority'] = priority
# config2['retries'] = retries
#
# serv2 = Service(config2,"test")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment