From: Garret Heaton Date: Sun, 18 Oct 2009 21:06:22 +0000 (-0700) Subject: Replace dashes with underscores in python modules X-Git-Tag: collectd-4.7.5~18 X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=2499ec300378f4c89ade915f8fae834d8ca3a25b;p=collectd.git Replace dashes with underscores in python modules It's not possible to import python modules with dashes in the name. See http://bit.ly/2t7fcy for more information. --- diff --git a/contrib/collectd-network.py b/contrib/collectd-network.py deleted file mode 100644 index 445b1838..00000000 --- a/contrib/collectd-network.py +++ /dev/null @@ -1,318 +0,0 @@ -#! /usr/bin/env python -# -*- coding: utf-8 -*- -# vim: fileencoding=utf-8 -# -# Copyright © 2009 Adrian Perez -# -# Distributed under terms of the GPLv2 license. - -""" -Collectd network protocol implementation. -""" - -import socket -import struct - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - -from datetime import datetime -from copy import deepcopy - - -DEFAULT_PORT = 25826 -"""Default port""" - -DEFAULT_IPv4_GROUP = "239.192.74.66" -"""Default IPv4 multicast group""" - -DEFAULT_IPv6_GROUP = "ff18::efc0:4a42" -"""Default IPv6 multicast group""" - - - -# Message kinds -TYPE_HOST = 0x0000 -TYPE_TIME = 0x0001 -TYPE_PLUGIN = 0x0002 -TYPE_PLUGIN_INSTANCE = 0x0003 -TYPE_TYPE = 0x0004 -TYPE_TYPE_INSTANCE = 0x0005 -TYPE_VALUES = 0x0006 -TYPE_INTERVAL = 0x0007 - -# For notifications -TYPE_MESSAGE = 0x0100 -TYPE_SEVERITY = 0x0101 - -# DS kinds -DS_TYPE_COUNTER = 0 -DS_TYPE_GAUGE = 1 - - -header = struct.Struct("!2H") -number = struct.Struct("!Q") -short = struct.Struct("!H") -double = struct.Struct(" blen - off: - raise ValueError("Packet longer than amount of data in buffer") - - if ptype not in _decoders: - raise ValueError("Message type %i not recognized" % ptype) - - yield ptype, _decoders[ptype](ptype, plen, buf[off:]) - off += plen - - - - - -class Data(object): - time = 0 - host = None - plugin = None - plugininstance = None - type = None - typeinstance = None - - def __init__(self, **kw): - [setattr(self, k, v) for k, v in kw.iteritems()] - - @property - def datetime(self): - return datetime.fromtimestamp(self.time) - - @property - def source(self): - buf = StringIO() - if self.host: - buf.write(self.host) - if self.plugin: - buf.write("/") - buf.write(self.plugin) - if self.plugininstance: - buf.write("/") - buf.write(self.plugininstance) - if self.type: - buf.write("/") - buf.write(self.type) - if self.typeinstance: - buf.write("/") - buf.write(self.typeinstance) - return buf.getvalue() - - def __str__(self): - return "[%i] %s" % (self.time, self.source) - - - -class Notification(Data): - FAILURE = 1 - WARNING = 2 - OKAY = 4 - - SEVERITY = { - FAILURE: "FAILURE", - WARNING: "WARNING", - OKAY : "OKAY", - } - - __severity = 0 - message = "" - - def __set_severity(self, value): - if value in (self.FAILURE, self.WARNING, self.OKAY): - self.__severity = value - - severity = property(lambda self: self.__severity, __set_severity) - - @property - def severitystring(self): - return self.SEVERITY.get(self.severity, "UNKNOWN") - - def __str__(self): - return "%s [%s] %s" % ( - super(Notification, self).__str__(), - self.severitystring, - self.message) - - - -class Values(Data, list): - def __str__(self): - return "%s %s" % (Data.__str__(self), list.__str__(self)) - - - -def interpret_opcodes(iterable): - vl = Values() - nt = Notification() - - for kind, data in iterable: - if kind == TYPE_TIME: - vl.time = nt.time = data - elif kind == TYPE_INTERVAL: - vl.interval = data - elif kind == TYPE_HOST: - vl.host = nt.host = data - elif kind == TYPE_PLUGIN: - vl.plugin = nt.plugin = data - elif kind == TYPE_PLUGIN_INSTANCE: - vl.plugininstance = nt.plugininstance = data - elif kind == TYPE_TYPE: - vl.type = nt.type = data - elif kind == TYPE_TYPE_INSTANCE: - vl.typeinstance = nt.typeinstance = data - elif kind == TYPE_SEVERITY: - nt.severity = data - elif kind == TYPE_MESSAGE: - nt.message = data - yield deepcopy(nt) - elif kind == TYPE_VALUES: - vl[:] = data - yield deepcopy(vl) - - - -class Reader(object): - """Network reader for collectd data. - - Listens on the network in a given address, which can be a multicast - group address, and handles reading data when it arrives. - """ - addr = None - host = None - port = DEFAULT_PORT - - BUFFER_SIZE = 1024 - - - def __init__(self, host=None, port=DEFAULT_PORT, multicast=False): - if host is None: - multicast = True - host = DEFAULT_IPv4_GROUP - - self.host, self.port = host, port - self.ipv6 = ":" in self.host - - family, socktype, proto, canonname, sockaddr = socket.getaddrinfo( - None if multicast else self.host, self.port, - socket.AF_INET6 if self.ipv6 else socket.AF_UNSPEC, - socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)[0] - - self._sock = socket.socket(family, socktype, proto) - self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self._sock.bind(sockaddr) - - if multicast: - if hasattr(socket, "SO_REUSEPORT"): - self._sock.setsockopt( - socket.SOL_SOCKET, - socket.SO_REUSEPORT, 1) - - val = None - if family == socket.AF_INET: - assert "." in self.host - val = struct.pack("4sl", - socket.inet_aton(self.host), socket.INADDR_ANY) - elif family == socket.AF_INET6: - raise NotImplementedError("IPv6 support not ready yet") - else: - raise ValueError("Unsupported network address family") - - self._sock.setsockopt( - socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP, - socket.IP_ADD_MEMBERSHIP, val) - self._sock.setsockopt( - socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP, - socket.IP_MULTICAST_LOOP, 0) - - - def receive(self): - """Receives a single raw collect network packet. - """ - return self._sock.recv(self.BUFFER_SIZE) - - - def decode(self, buf=None): - """Decodes a given buffer or the next received packet. - """ - if buf is None: - buf = self.receive() - return decode_network_packet(buf) - - - def interpret(self, iterable=None): - """Interprets a sequence - """ - if iterable is None: - iterable = self.decode() - if isinstance(iterable, basestring): - iterable = self.decode(iterable) - return interpret_opcodes(iterable) - - diff --git a/contrib/collectd-unixsock.py b/contrib/collectd-unixsock.py deleted file mode 100644 index 2d7430d2..00000000 --- a/contrib/collectd-unixsock.py +++ /dev/null @@ -1,111 +0,0 @@ -#-*- coding: ISO-8859-1 -*- -# collect.py: the python collectd-unixsock module. -# -# Requires collectd to be configured with the unixsock plugin, like so: -# -# LoadPlugin unixsock -# -# SocketFile "/var/run/collectd-unixsock" -# SocketPerms "0775" -# -# -# Copyright (C) 2008 Clay Loveless -# -# This software is provided 'as-is', without any express or implied -# warranty. In no event will the author be held liable for any damages -# arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, -# including commercial applications, and to alter it and redistribute it -# freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not -# claim that you wrote the original software. If you use this software -# in a product, an acknowledgment in the product documentation would be -# appreciated but is not required. -# 2. Altered source versions must be plainly marked as such, and must not be -# misrepresented as being the original software. -# 3. This notice may not be removed or altered from any source distribution. - -import socket, string - -class Collect(object): - - def __init__(self, path='/var/run/collectd-unixsock'): - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self._path = path - self._sock.connect(self._path) - - def list(self): - numvalues = self._cmd('LISTVAL') - lines = [] - if numvalues: - lines = self._readlines(numvalues) - return lines - - def get(self, val, flush=True): - numvalues = self._cmd('GETVAL "' + val + '"') - lines = [] - if numvalues: - lines = self._readlines(numvalues) - if flush: - self._cmd('FLUSH identifier="' + val + '"') - return lines - - def _cmd(self, c): - self._sock.send(c + "\n") - stat = string.split(self._readline()) - status = int(stat[0]) - if status: - return status - return False - - ''' - _readline and _readlines methods borrowed from the _fileobject class - in sockets.py, tweaked a little bit for use in the collectd context. - ''' - def _readline(self): - data = '' - buf = [] - recv = self._sock.recv - while data != "\n": - data = recv(1) - if not data: - break - if data != "\n": - buf.append(data) - return ''.join(buf) - - def _readlines(self, sizehint=0): - total = 0 - list = [] - while True: - line = self._readline() - if not line: - break - list.append(line) - total = len(list) - if sizehint and total >= sizehint: - break - return list - - def __del__(self): - self._sock.close() - - - -if __name__ == '__main__': - - ''' - Example usage: - Collect values from socket and dump to STDOUT. - ''' - - c = Collect('/var/run/collectd-unixsock') - list = c.list() - - for val in list: - stamp, key = string.split(val) - glines = c.get(key) - print stamp + ' ' + key + ' ' + ', '.join(glines) - diff --git a/contrib/collectd_network.py b/contrib/collectd_network.py new file mode 100644 index 00000000..445b1838 --- /dev/null +++ b/contrib/collectd_network.py @@ -0,0 +1,318 @@ +#! /usr/bin/env python +# -*- coding: utf-8 -*- +# vim: fileencoding=utf-8 +# +# Copyright © 2009 Adrian Perez +# +# Distributed under terms of the GPLv2 license. + +""" +Collectd network protocol implementation. +""" + +import socket +import struct + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +from datetime import datetime +from copy import deepcopy + + +DEFAULT_PORT = 25826 +"""Default port""" + +DEFAULT_IPv4_GROUP = "239.192.74.66" +"""Default IPv4 multicast group""" + +DEFAULT_IPv6_GROUP = "ff18::efc0:4a42" +"""Default IPv6 multicast group""" + + + +# Message kinds +TYPE_HOST = 0x0000 +TYPE_TIME = 0x0001 +TYPE_PLUGIN = 0x0002 +TYPE_PLUGIN_INSTANCE = 0x0003 +TYPE_TYPE = 0x0004 +TYPE_TYPE_INSTANCE = 0x0005 +TYPE_VALUES = 0x0006 +TYPE_INTERVAL = 0x0007 + +# For notifications +TYPE_MESSAGE = 0x0100 +TYPE_SEVERITY = 0x0101 + +# DS kinds +DS_TYPE_COUNTER = 0 +DS_TYPE_GAUGE = 1 + + +header = struct.Struct("!2H") +number = struct.Struct("!Q") +short = struct.Struct("!H") +double = struct.Struct(" blen - off: + raise ValueError("Packet longer than amount of data in buffer") + + if ptype not in _decoders: + raise ValueError("Message type %i not recognized" % ptype) + + yield ptype, _decoders[ptype](ptype, plen, buf[off:]) + off += plen + + + + + +class Data(object): + time = 0 + host = None + plugin = None + plugininstance = None + type = None + typeinstance = None + + def __init__(self, **kw): + [setattr(self, k, v) for k, v in kw.iteritems()] + + @property + def datetime(self): + return datetime.fromtimestamp(self.time) + + @property + def source(self): + buf = StringIO() + if self.host: + buf.write(self.host) + if self.plugin: + buf.write("/") + buf.write(self.plugin) + if self.plugininstance: + buf.write("/") + buf.write(self.plugininstance) + if self.type: + buf.write("/") + buf.write(self.type) + if self.typeinstance: + buf.write("/") + buf.write(self.typeinstance) + return buf.getvalue() + + def __str__(self): + return "[%i] %s" % (self.time, self.source) + + + +class Notification(Data): + FAILURE = 1 + WARNING = 2 + OKAY = 4 + + SEVERITY = { + FAILURE: "FAILURE", + WARNING: "WARNING", + OKAY : "OKAY", + } + + __severity = 0 + message = "" + + def __set_severity(self, value): + if value in (self.FAILURE, self.WARNING, self.OKAY): + self.__severity = value + + severity = property(lambda self: self.__severity, __set_severity) + + @property + def severitystring(self): + return self.SEVERITY.get(self.severity, "UNKNOWN") + + def __str__(self): + return "%s [%s] %s" % ( + super(Notification, self).__str__(), + self.severitystring, + self.message) + + + +class Values(Data, list): + def __str__(self): + return "%s %s" % (Data.__str__(self), list.__str__(self)) + + + +def interpret_opcodes(iterable): + vl = Values() + nt = Notification() + + for kind, data in iterable: + if kind == TYPE_TIME: + vl.time = nt.time = data + elif kind == TYPE_INTERVAL: + vl.interval = data + elif kind == TYPE_HOST: + vl.host = nt.host = data + elif kind == TYPE_PLUGIN: + vl.plugin = nt.plugin = data + elif kind == TYPE_PLUGIN_INSTANCE: + vl.plugininstance = nt.plugininstance = data + elif kind == TYPE_TYPE: + vl.type = nt.type = data + elif kind == TYPE_TYPE_INSTANCE: + vl.typeinstance = nt.typeinstance = data + elif kind == TYPE_SEVERITY: + nt.severity = data + elif kind == TYPE_MESSAGE: + nt.message = data + yield deepcopy(nt) + elif kind == TYPE_VALUES: + vl[:] = data + yield deepcopy(vl) + + + +class Reader(object): + """Network reader for collectd data. + + Listens on the network in a given address, which can be a multicast + group address, and handles reading data when it arrives. + """ + addr = None + host = None + port = DEFAULT_PORT + + BUFFER_SIZE = 1024 + + + def __init__(self, host=None, port=DEFAULT_PORT, multicast=False): + if host is None: + multicast = True + host = DEFAULT_IPv4_GROUP + + self.host, self.port = host, port + self.ipv6 = ":" in self.host + + family, socktype, proto, canonname, sockaddr = socket.getaddrinfo( + None if multicast else self.host, self.port, + socket.AF_INET6 if self.ipv6 else socket.AF_UNSPEC, + socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)[0] + + self._sock = socket.socket(family, socktype, proto) + self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self._sock.bind(sockaddr) + + if multicast: + if hasattr(socket, "SO_REUSEPORT"): + self._sock.setsockopt( + socket.SOL_SOCKET, + socket.SO_REUSEPORT, 1) + + val = None + if family == socket.AF_INET: + assert "." in self.host + val = struct.pack("4sl", + socket.inet_aton(self.host), socket.INADDR_ANY) + elif family == socket.AF_INET6: + raise NotImplementedError("IPv6 support not ready yet") + else: + raise ValueError("Unsupported network address family") + + self._sock.setsockopt( + socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP, + socket.IP_ADD_MEMBERSHIP, val) + self._sock.setsockopt( + socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP, + socket.IP_MULTICAST_LOOP, 0) + + + def receive(self): + """Receives a single raw collect network packet. + """ + return self._sock.recv(self.BUFFER_SIZE) + + + def decode(self, buf=None): + """Decodes a given buffer or the next received packet. + """ + if buf is None: + buf = self.receive() + return decode_network_packet(buf) + + + def interpret(self, iterable=None): + """Interprets a sequence + """ + if iterable is None: + iterable = self.decode() + if isinstance(iterable, basestring): + iterable = self.decode(iterable) + return interpret_opcodes(iterable) + + diff --git a/contrib/collectd_unixsock.py b/contrib/collectd_unixsock.py new file mode 100644 index 00000000..2d7430d2 --- /dev/null +++ b/contrib/collectd_unixsock.py @@ -0,0 +1,111 @@ +#-*- coding: ISO-8859-1 -*- +# collect.py: the python collectd-unixsock module. +# +# Requires collectd to be configured with the unixsock plugin, like so: +# +# LoadPlugin unixsock +# +# SocketFile "/var/run/collectd-unixsock" +# SocketPerms "0775" +# +# +# Copyright (C) 2008 Clay Loveless +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the author be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# 3. This notice may not be removed or altered from any source distribution. + +import socket, string + +class Collect(object): + + def __init__(self, path='/var/run/collectd-unixsock'): + self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self._path = path + self._sock.connect(self._path) + + def list(self): + numvalues = self._cmd('LISTVAL') + lines = [] + if numvalues: + lines = self._readlines(numvalues) + return lines + + def get(self, val, flush=True): + numvalues = self._cmd('GETVAL "' + val + '"') + lines = [] + if numvalues: + lines = self._readlines(numvalues) + if flush: + self._cmd('FLUSH identifier="' + val + '"') + return lines + + def _cmd(self, c): + self._sock.send(c + "\n") + stat = string.split(self._readline()) + status = int(stat[0]) + if status: + return status + return False + + ''' + _readline and _readlines methods borrowed from the _fileobject class + in sockets.py, tweaked a little bit for use in the collectd context. + ''' + def _readline(self): + data = '' + buf = [] + recv = self._sock.recv + while data != "\n": + data = recv(1) + if not data: + break + if data != "\n": + buf.append(data) + return ''.join(buf) + + def _readlines(self, sizehint=0): + total = 0 + list = [] + while True: + line = self._readline() + if not line: + break + list.append(line) + total = len(list) + if sizehint and total >= sizehint: + break + return list + + def __del__(self): + self._sock.close() + + + +if __name__ == '__main__': + + ''' + Example usage: + Collect values from socket and dump to STDOUT. + ''' + + c = Collect('/var/run/collectd-unixsock') + list = c.list() + + for val in list: + stamp, key = string.split(val) + glines = c.get(key) + print stamp + ' ' + key + ' ' + ', '.join(glines) +