Skip to content

Instantly share code, notes, and snippets.

@jrottenberg
Created April 2, 2013 20:47
Show Gist options
  • Save jrottenberg/5296025 to your computer and use it in GitHub Desktop.
Save jrottenberg/5296025 to your computer and use it in GitHub Desktop.
puppet stats to gmond, embedded version of gmetric lib
#!/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