Created
April 2, 2013 20:47
-
-
Save jrottenberg/5296025 to your computer and use it in GitHub Desktop.
puppet stats to gmond, embedded version of gmetric lib
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# This file is managed by puppet | |
import yaml | |
from xdrlib import Packer, Unpacker | |
import socket | |
import optparse | |
import logging | |
slope_str2int = {'zero':0, | |
'positive':1, | |
'negative':2, | |
'both':3, | |
'unspecified':4} | |
# could be autogenerated from previous but whatever | |
slope_int2str = {0: 'zero', | |
1: 'positive', | |
2: 'negative', | |
3: 'both', | |
4: 'unspecified'} | |
class Gmetric: | |
""" | |
Class to send gmetric/gmond 2.X packets | |
Thread safe | |
""" | |
type = ('', 'string', 'uint16', 'int16', 'uint32', 'int32', 'float', | |
'double', 'timestamp') | |
protocol = ('udp', 'multicast') | |
def __init__(self, host, port, protocol): | |
if protocol not in self.protocol: | |
raise ValueError("Protocol must be one of: " + str(self.protocol)) | |
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
if protocol == 'multicast': | |
self.socket.setsockopt(socket.IPPROTO_IP, | |
socket.IP_MULTICAST_TTL, 20) | |
self.hostport = (host, int(port)) | |
#self.socket.connect(self.hostport) | |
def send(self, NAME, VAL, TYPE='', UNITS='', SLOPE='both', | |
TMAX=60, DMAX=0, GROUP="", SPOOF=""): | |
if SLOPE not in slope_str2int: | |
raise ValueError("Slope must be one of: " + str(self.slope.keys())) | |
if TYPE not in self.type: | |
raise ValueError("Type must be one of: " + str(self.type)) | |
if len(NAME) == 0: | |
raise ValueError("Name must be non-empty") | |
( meta_msg, data_msg ) = gmetric_write(NAME, VAL, TYPE, UNITS, SLOPE, TMAX, DMAX, GROUP, SPOOF) | |
# print msg | |
self.socket.sendto(meta_msg, self.hostport) | |
self.socket.sendto(data_msg, self.hostport) | |
def gmetric_write(NAME, VAL, TYPE, UNITS, SLOPE, TMAX, DMAX, GROUP, SPOOF): | |
""" | |
Arguments are in all upper-case to match XML | |
""" | |
packer = Packer() | |
HOSTNAME="test" | |
if SPOOF == "": | |
SPOOFENABLED=0 | |
else : | |
SPOOFENABLED=1 | |
# Meta data about a metric | |
packer.pack_int(128) | |
if SPOOFENABLED == 1: | |
packer.pack_string(SPOOF) | |
else: | |
packer.pack_string(HOSTNAME) | |
packer.pack_string(NAME) | |
packer.pack_int(SPOOFENABLED) | |
packer.pack_string(TYPE) | |
packer.pack_string(NAME) | |
packer.pack_string(UNITS) | |
packer.pack_int(slope_str2int[SLOPE]) # map slope string to int | |
packer.pack_uint(int(TMAX)) | |
packer.pack_uint(int(DMAX)) | |
# Magic number. Indicates number of entries to follow. Put in 1 for GROUP | |
if GROUP == "": | |
packer.pack_int(0) | |
else: | |
packer.pack_int(1) | |
packer.pack_string("GROUP") | |
packer.pack_string(GROUP) | |
# Actual data sent in a separate packet | |
data = Packer() | |
data.pack_int(128+5) | |
if SPOOFENABLED == 1: | |
data.pack_string(SPOOF) | |
else: | |
data.pack_string(HOSTNAME) | |
data.pack_string(NAME) | |
data.pack_int(SPOOFENABLED) | |
data.pack_string("%s") | |
data.pack_string(str(VAL)) | |
return ( packer.get_buffer() , data.get_buffer() ) | |
def gmetric_read(msg): | |
unpacker = Unpacker(msg) | |
values = dict() | |
unpacker.unpack_int() | |
values['TYPE'] = unpacker.unpack_string() | |
values['NAME'] = unpacker.unpack_string() | |
values['VAL'] = unpacker.unpack_string() | |
values['UNITS'] = unpacker.unpack_string() | |
values['SLOPE'] = slope_int2str[unpacker.unpack_int()] | |
values['TMAX'] = unpacker.unpack_uint() | |
values['DMAX'] = unpacker.unpack_uint() | |
unpacker.done() | |
return values | |
def puppet_data_send(connexion, key, value): | |
connexion.send('puppet.' + key, value, 'float', '', 'both', 600, 0, 'puppet', '') | |
if __name__ == '__main__': | |
optp = optparse.OptionParser() | |
optp.add_option('-v', '--verbose', dest='verbose', action='count', | |
help="Increase verbosity (specify multiple times for more)") | |
# Parse the arguments (defaults to parsing sys.argv). | |
opts, args = optp.parse_args() | |
log_level = logging.WARNING # default | |
if opts.verbose == 1: | |
log_level = logging.INFO | |
elif opts.verbose >= 2: | |
log_level = logging.DEBUG | |
logging.basicConfig(level=log_level) | |
fqdn = socket.getfqdn() | |
gmetric_connexion = Gmetric(fqdn, 8649, 'udp') | |
puppet_report = '/var/lib/puppet/state/last_run_summary.yaml' | |
yaml_report = open(puppet_report, 'r') | |
puppet_data = yaml.load(yaml_report) | |
logging.debug(puppet_data) | |
for metric in puppet_data.iterkeys(): | |
if metric in 'version': continue | |
for key in puppet_data[metric].iterkeys(): | |
my_key = "%s.%s" % (metric, key) | |
my_val = puppet_data[metric][key] | |
logging.info("%s = %s" % (my_key, my_val)) | |
puppet_data_send(gmetric_connexion, my_key, my_val) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment