-
Notifications
You must be signed in to change notification settings - Fork 7
/
collectd_lxc.py
executable file
·173 lines (140 loc) · 7.87 KB
/
collectd_lxc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/env python2.7
import glob
import os
import re
import subprocess
from nsenter import Namespace
def configer(ObjConfiguration):
collectd.info('Configuring lxc collectd')
def initer():
collectd.info('initing lxc collectd')
def reader(input_data=None):
root_lxc_cgroup = glob.glob("/sys/fs/cgroup/*/lxc/*/")
unprivilege_lxc_cgroup = glob.glob("/sys/fs/cgroup/*/*/*/*/lxc/*/")
cgroup_lxc = root_lxc_cgroup + unprivilege_lxc_cgroup
metrics = dict()
#Get all stats by container group by user
for cgroup_lxc_metrics in cgroup_lxc:
m = re.search("/sys/fs/cgroup/(?P<type>[a-zA-Z_,]+)/(?:user/(?P<user_id>[0-9]+)\.user/[a-zA-Z0-9]+\.session/)?lxc/(?P<container_name>.*)/", cgroup_lxc_metrics)
user_id = int(m.group("user_id") or 0)
stat_type = m.group("type")
container_name = m.group("container_name")
if user_id not in metrics:
metrics[user_id] = dict()
if container_name not in metrics[user_id]:
metrics[user_id][container_name] = dict()
metrics[user_id][container_name][stat_type] = cgroup_lxc_metrics
# foreach user
for user_id in metrics:
# foreach container
for container_name in metrics[user_id]:
lxc_fullname = "{0}__{1}".format(user_id, container_name)
for metric in metrics[user_id][container_name]:
### Memory
if metric == "memory":
with open(os.path.join(metrics[user_id][container_name][metric], 'memory.stat'), 'r') as f:
lines = f.read().splitlines()
mem_rss = 0
mem_cache = 0
mem_swap = 0
for line in lines:
data = line.split()
if data[0] == "total_rss":
mem_rss = int(data[1])
elif data[0] == "total_cache":
mem_cache = int(data[1])
elif data[0] == "total_swap":
mem_swap = int(data[1])
values = collectd.Values(plugin_instance=lxc_fullname,
type="gauge", plugin="lxc_memory")
values.dispatch(type_instance="rss", values=[mem_rss])
values.dispatch(type_instance="cache", values=[mem_cache])
values.dispatch(type_instance="swap", values=[mem_swap])
### End Memory
### CPU
if metric == "cpuacct":
with open(os.path.join(metrics[user_id][container_name][metric], 'cpuacct.stat'), 'r') as f:
lines = f.read().splitlines()
cpu_user = 0
cpu_system = 0
for line in lines:
data = line.split()
if data[0] == "user":
cpu_user = int(data[1])
elif data[0] == "system":
cpu_system = int(data[1])
values = collectd.Values(plugin_instance=lxc_fullname,
type="gauge", plugin="lxc_cpu")
values.dispatch(type_instance="user", values=[cpu_user])
values.dispatch(type_instance="system", values=[cpu_system])
### End CPU
### DISK
if metric == "blkio":
with open(os.path.join(metrics[user_id][container_name][metric], 'blkio.throttle.io_service_bytes'), 'r') as f:
lines = f.read()
bytes_read = int(re.search("Read\s+(?P<read>[0-9]+)", lines).group("read"))
bytes_write = int(re.search("Write\s+(?P<write>[0-9]+)", lines).group("write"))
with open(os.path.join(metrics[user_id][container_name][metric], 'blkio.throttle.io_serviced'), 'r') as f:
lines = f.read()
ops_read = int(re.search("Read\s+(?P<read>[0-9]+)", lines).group("read"))
ops_write = int(re.search("Write\s+(?P<write>[0-9]+)", lines).group("write"))
values = collectd.Values(plugin_instance=lxc_fullname,
type="gauge", plugin="lxc_blkio")
values.dispatch(type_instance="bytes_read", values=[bytes_read])
values.dispatch(type_instance="bytes_write", values=[bytes_write])
values.dispatch(type_instance="ops_read", values=[ops_read])
values.dispatch(type_instance="ops_write", values=[ops_write])
### End DISK
### Network
if metric == "pids":
#PID lxc: cat /sys/fs/cgroup/devices/lxc/CONTAINER-NAME/tasks | head -n 1
with open(os.path.join(metrics[user_id][container_name][metric], 'tasks'), 'r') as f:
# The first line is PID of container
container_PID = f.readline().rstrip()
with Namespace(container_PID, 'net'):
# To read network metric in namespace, "open" method don't work with namespace
network_data = subprocess.check_output(['cat', '/proc/net/dev']).split("\n")
# HEAD OF /proc/net/dev :
# Inter-|Receive |Transmit
# face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
for line in network_data[2:]:
if line.strip() == "":
continue
interface = line.strip().split(':')[0]
rx_data = line.strip().split(':')[1].split()[0:7]
tx_data = line.strip().split(':')[1].split()[8:15]
rx_bytes = int(rx_data[0])
tx_bytes = int(tx_data[0])
rx_packets = int(rx_data[1])
tx_packets = int(tx_data[1])
rx_errors = int(rx_data[2])
tx_errors = int(tx_data[2])
values = collectd.Values(plugin_instance=lxc_fullname,
type="gauge", plugin="lxc_net")
values.dispatch(type_instance="tx_bytes_{0}".format(interface), values=[tx_bytes])
values.dispatch(type_instance="rx_bytes_{0}".format(interface), values=[rx_bytes])
values.dispatch(type_instance="tx_packets_{0}".format(interface), values=[tx_packets])
values.dispatch(type_instance="rx_packets_{0}".format(interface), values=[rx_packets])
values.dispatch(type_instance="tx_errors_{0}".format(interface), values=[tx_errors])
values.dispatch(type_instance="rx_errors_{0}".format(interface), values=[rx_errors])
### End Network
if __name__ == '__main__':
# Mimic Collectd Values object
class Values(object):
def __init__(self, **kwargs):
self.__dict__["_values"] = kwargs
def __setattr__(self, key, value):
self.__dict__["_values"][key] = value
def dispatch(self, **kwargs):
values = self._values.copy()
values.update(kwargs)
print(values)
import types
collectd = types.ModuleType("collectd")
collectd.Values = Values
reader()
else:
import collectd
collectd.register_config(configer)
collectd.register_init(initer)
collectd.register_read(reader)