Revision 56359d19

b/snf-cyclades-gtools/collectd/README.collectd
1
README
2
=======
3
snf-cyclades-gtools installs a Python collectd plugin, which collects stats
4
about the Ganeti VMs running on the host.
5

  
6
The plugin is installed under /usr/lib/snf-cyclades-gtools/collectd/.
7

  
8
The necessary plugin configuration is performed by
9
/etc/collectd/ganeti-stats.conf.
10

  
11
To enable the plugin, add in your original collectd configuration file the
12
following line:
13
 
14
 Include /etc/collectd/ganeti-stats.conf
15

  
16
An example collectd configuration, which enables the plugin, is also installed
17
in /usr/shared/doc/snf-cyclades-gtools/examples/ganeti-stats-collectd.conf.
b/snf-cyclades-gtools/collectd/conf/ganeti-stats.conf
1
<LoadPlugin python>
2
	Globals true
3
</LoadPlugin>
4
<Plugin python>
5
	ModulePath "/usr/lib/snf-cyclades-gtools/collectd/"
6
	LogTraces true
7
	Interactive false
8
	Import "ganeti-stats"
9
</Plugin>
b/snf-cyclades-gtools/collectd/examples/ganeti-stats-collectd.conf
1
FQDNLookup true
2

  
3
LoadPlugin syslog
4
<Plugin syslog>
5
	LogLevel info
6
</Plugin>
7

  
8
LoadPlugin network
9
<Plugin network>
10
	<Server "host" "25826">
11
		SecurityLevel "Encrypt"
12
		Username "user"
13
		Password "pass"
14
	</Server>
15
	TimeToLive 128
16
	ReportStats false
17
	MaxPacketSize 65535
18
	CacheFlush 1800
19
</Plugin>
20

  
21
<LoadPlugin python>
22
	Globals true
23
</LoadPlugin>
24
<Plugin python>
25
	ModulePath "/usr/lib/snf-cyclades-gtools/collectd/"
26
	LogTraces true
27
	Interactive false
28
	Import "ganeti-stats"
29
</Plugin>
30

  
31
Include "/etc/collectd/filters.conf"
32
Include "/etc/collectd/thresholds.conf"
b/snf-cyclades-gtools/collectd/plugins/ganeti-stats.py
1
#!/usr/bin/env python
2

  
3
import os
4
import collectd
5

  
6
from hashlib import md5
7

  
8
from glob import glob
9

  
10

  
11
def read_int(file):
12
    f = open(file, "r")
13
    try:
14
        val = int(f.read())
15
    except ValueError:
16
        val = None
17
    finally:
18
        f.close()
19

  
20
    return val
21

  
22

  
23
def anonymize_hostname(hostname):
24
    #return md5(hostname).hexdigest()
25
    return hostname
26

  
27

  
28
def get_vcpus(pid):
29
    """Get a KVM instance vCPU count by looking at its fd's"""
30
    vcpus = 0
31
    for fd in glob("/proc/%d/fd/*" % pid):
32
        # XXX: sad but trueeeeeeeeeeee
33
        if os.readlink(fd) == "anon_inode:kvm-vcpu":
34
            vcpus += 1
35
    return vcpus
36

  
37

  
38
def netstats(data=None):
39
    for dir in glob("/var/run/ganeti/kvm-hypervisor/nic/*"):
40
        if not os.path.isdir(dir):
41
            continue
42

  
43
        hostname = os.path.basename(dir)
44

  
45
        for nic in glob(os.path.join(dir, "*")):
46
            idx = int(os.path.basename(nic))
47
            with open(nic) as nicfile:
48
                try:
49
                    iface = nicfile.readline().strip()
50
                except EnvironmentError:
51
                    continue
52

  
53
            if not os.path.isdir("/sys/class/net/%s" % iface):
54
                continue
55
            
56
            bytes_in = read_int("/sys/class/net/%s/statistics/rx_bytes" % iface)
57
            bytes_out = read_int("/sys/class/net/%s/statistics/tx_bytes" % iface)
58

  
59
            vl = collectd.Values(type="counter")
60
            vl.host = anonymize_hostname(hostname)
61
            vl.plugin = "interface"
62
            vl.type = "if_octets"
63
            vl.type_instance = "eth%d" % idx
64
            vl.dispatch(values=[bytes_out, bytes_in])
65

  
66

  
67
def cpustats(data=None):
68
    for file in glob("/var/run/ganeti/kvm-hypervisor/pid/*"):
69
        instance = os.path.basename(file)
70
        try:
71
            pid = int(open(file, "r").read())
72
            proc = open("/proc/%d/stat" % pid, "r")
73
            cputime = [int(proc.readline().split()[42])]
74
        except EnvironmentError:
75
            continue
76
        vcpus = get_vcpus(pid)
77
        proc.close()
78

  
79
        vl = collectd.Values(type="counter")
80
        vl.host = anonymize_hostname(instance)
81
        vl.plugin = "cpu"
82
        vl.type = "virt_cpu_total"
83
        total = sum(cputime) * 100 / (vcpus * os.sysconf("SC_CLK_TCK"))
84
        vl.dispatch(values=[total])
85

  
86
collectd.register_read(netstats)
87
collectd.register_read(cpustats)
88

  
89
# vim: set ts=4 sts=4 et sw=4 :

Also available in: Unified diff