Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / lxc / lxc_guests @ 137913e3

Historique | Voir | Annoter | Télécharger (10,5 ko)

1
#!/bin/sh
2
# -*- sh -*-
3

    
4
: << =cut
5

    
6
=head1 NAME
7

    
8
lxc_guests - collect statistics about containers virtualized via LXC
9

    
10
=head1 CONFIGURATION
11

    
12
  [lxc_guests]
13
    user root
14

    
15
    # The memory usage of containers are by default drawn as stacked area
16
    # charts.  Alternatively a non-stacked graph with lines can be configured.
17
    # Default: true
18
    #env.ram_display_stacked true
19

    
20
    # lxc container path, default below
21
    #env.lxcpath /var/lib/lxc
22

    
23
    # exclude the following containers
24
    # (default none excluded)
25
    #env.exclude container1 container2
26

    
27
    # path where tasks sysfs files are stored,
28
    # set this if the various attempts in the
29
    # code don't work
30
    # (default none)
31
    #env.cgrouppath /sys/fs/cgroup/cpuacct/lxc/
32

    
33
=head1 INTERPRETATION
34

    
35
This plugin needs root privilege.
36

    
37
This plugin has been tested with lxc 3 and
38
lx2 (on Debian buster and Debian jessie,
39
respectively).
40

    
41
If using lxc 2, make sure you do not have cruft
42
in your container config files, you can test
43
it with:
44
   lxc-cgroup -o /dev/stdout -l INFO -n 104 cpuacct.usage
45
-- with 104 a valid lxc instance), if you
46
get a warning, fix the config file.
47

    
48
For the logins graph, the "users" command is required in each
49
container.
50

    
51
Tested on Debian buster and Debian jessie.
52

    
53

    
54
=head1 AUTHOR
55

    
56
vajtsz vajtsz@gmail.com
57
mitty  mitty@mitty.jp
58
alphanet schaefer@alphanet.ch (many changes and multigraph)
59
Lars Kruse <devel@sumpfralle.de>
60

    
61
=head1 LICENSE
62

    
63
2-clause BSD License
64
or GPLv3 license or later, at your option
65

    
66
=head1 MAGIC MARKERS
67

    
68
 #%# family=auto
69
 #%# capabilities=autoconf
70

    
71
=cut
72

    
73
set -eu
74

    
75

    
76
. "$MUNIN_LIBDIR/plugins/plugin.sh"
77

    
78

    
79
lxcpath=${lxcpath:-/var/lib/lxc}
80
# containers to be ignored
81
exclude=${exclude:-}
82
ram_display_stacked=${ram_display_stacked:-true}
83
# try to guess the location, if empty
84
cgrouppath=${cgrouppath:-}
85

    
86

    
87
# --- FUNCTIONS
88

    
89
get_active_guests() {
90
   local excludes="$1"
91
   local guest_name
92
   for guest_name in $(lxc-ls)
93
   do
94
      # handle optional exclude list in $1
95
      if ! echo "$excludes" | grep -qwF "$guest_name"; then
96
         if lxc-info -n "$guest_name" --state 2>/dev/null | grep -qw RUNNING; then
97
            echo "$guest_name"
98
         fi
99
      fi
100
   done
101
}
102

    
103

    
104
get_lxc_cgroup_info() {
105
   local guest_name="$1"
106
   local field="$2"
107
   # lxc3 (lxc < 3: may output some warnings if there is cruft in your config dir)
108
   lxc-cgroup -o /dev/stdout -l INFO -n "$guest_name" "$field" | sed 's/^.*lxc_cgroup.c:main:[0-9][0-9]* - //' | grep -v set_config_idmaps
109
}
110

    
111

    
112
# find proper sysfs and count it
113
# Debian 6.0: /sys/fs/cgroup/<container>/tasks
114
# Ubuntu 12.04 with fstab: /sys/fs/cgroup/lxc/<container>/tasks
115
# Ubuntu 12.04 with cgroup-lite: /sys/fs/cgroup/cpuacct/lxc/<container>/tasks
116
# Ubuntu 12.04 with cgroup-bin: /sys/fs/cgroup/cpuacct/sysdefault/lxc/<container>/tasks
117
# Ubuntu 14.04 /sys/fs/cgroup/systemd/lxc/<container>/tasks
118
# and with cgmanager on jessie
119
lxc_count_processes () {
120
   local guest_name="$1"
121
   local SYSFS
122

    
123
   [ -z "$guest_name" ] && return 0
124

    
125
   if [ -n "$cgrouppath" ]; then
126
      SYSFS="$cgrouppath/$guest_name/tasks"
127
      if [ -e "$SYSFS" ]; then
128
         wc -l <"$SYSFS"
129
         return
130
      fi
131
   fi
132

    
133
   for SYSFS in \
134
      "/sys/fs/cgroup/$guest_name/tasks" \
135
      "/sys/fs/cgroup/lxc/$guest_name/tasks" \
136
      "/sys/fs/cgroup/cpuacct/lxc/$guest_name/tasks" \
137
      "/sys/fs/cgroup/systemd/lxc/$guest_name/tasks" \
138
      "/sys/fs/cgroup/cpuacct/sysdefault/lxc/$guest_name/tasks"
139
   do
140
      if [ -e "$SYSFS" ]; then
141
         wc -l <"$SYSFS"
142
         return
143
      fi
144
   done
145

    
146
   if [ -e /usr/bin/cgm ]; then
147
      cgm getvalue cpu "lxc/$guest_name" tasks 2>/dev/null | wc -l
148
   else
149
      get_lxc_cgroup_info "$guest_name" "tasks" | wc -l
150
   fi
151
}
152

    
153

    
154
# change the first character of a string to upper case
155
title_case() {
156
   local text="$1"
157
   printf "%s%s" "$(echo "$text" | cut -c 1 | tr "[:lower:]" "[:upper:]")" "$(echo "$text" | cut -c 2-)"
158
}
159

    
160

    
161
do_autoconf() {
162
   if [ ! -r /proc/net/dev ]; then
163
      echo "no (/proc/net/dev cannot be read)"
164
   elif [ ! -e "$lxcpath" ]; then
165
      echo "no ($lxcpath is not present)"
166
   elif [ -z "$(which lxc-ls)" ]; then
167
      echo "no ('lxc-ls' is not available in PATH)"
168
   else
169
      echo yes
170
   fi
171
}
172

    
173

    
174
do_config() {
175
   local active_guests guest_name draw_style
176
   active_guests=$(get_active_guests "$exclude")
177

    
178
   cat <<EOF
179
multigraph lxc_cpu
180
graph_title CPU Usage
181
graph_args -l 0 --base 1000
182
graph_vlabel USER_HZ
183
graph_category virtualization
184
EOF
185

    
186
   for guest_name in $active_guests
187
   do
188
      for cpu_usage in user system
189
      do
190
         cat <<EOF
191
$(clean_fieldname "cpu_${cpu_usage}_${guest_name}").label $guest_name: $(title_case "$cpu_usage")
192
$(clean_fieldname "cpu_${cpu_usage}_${guest_name}").type DERIVE
193
$(clean_fieldname "cpu_${cpu_usage}_${guest_name}").min 0
194
EOF
195
      done
196
   done
197

    
198
   cat <<EOF
199

    
200
multigraph lxc_cpu_time
201
graph_title CPU time
202
graph_args -l 0 --base 1000
203
graph_vlabel nanosec
204
graph_category virtualization
205
EOF
206

    
207
   for guest_name in $active_guests
208
   do
209
      cat <<EOF
210
$(clean_fieldname "cpu_time_${guest_name}").label $guest_name: CPU time
211
$(clean_fieldname "cpu_time_${guest_name}").type DERIVE
212
$(clean_fieldname "cpu_time_${guest_name}").min 0
213
EOF
214
   done
215

    
216
   cat <<EOF
217

    
218
multigraph lxc_logins
219
graph_title Logins
220
graph_category virtualization
221
EOF
222

    
223
   for guest_name in $active_guests
224
   do
225
      cat <<EOF
226
$(clean_fieldname "logins_${guest_name}").label $guest_name: logins
227
$(clean_fieldname "logins_${guest_name}").type GAUGE
228
EOF
229
   done
230

    
231
   cat <<EOF
232

    
233
multigraph lxc_net
234
graph_title Network traffic
235
graph_args --base 1000
236
graph_vlabel bits in (-) / out (+) per \${graph_period}
237
graph_category virtualization
238
graph_info This graph shows the traffic of active LXC containers.
239
EOF
240

    
241
   for guest_name in $active_guests
242
   do
243
      device=$(lxc-info -n "$guest_name" | grep Link | sed 's/Link:\ \+//g')
244
      if [ -z "$device" ]; then
245
         continue
246
      fi
247
      cat <<EOF
248
$(clean_fieldname "net_${guest_name}_down").label $guest_name
249
$(clean_fieldname "net_${guest_name}_down").type DERIVE
250
$(clean_fieldname "net_${guest_name}_down").graph no
251
$(clean_fieldname "net_${guest_name}_down").cdef $(clean_fieldname "net_${guest_name}_down"),8,*
252
$(clean_fieldname "net_${guest_name}_down").min 0
253
$(clean_fieldname "net_${guest_name}_up").label $guest_name
254
$(clean_fieldname "net_${guest_name}_up").type DERIVE
255
$(clean_fieldname "net_${guest_name}_up").negative $(clean_fieldname "net_${guest_name}_down")
256
$(clean_fieldname "net_${guest_name}_up").cdef $(clean_fieldname "net_${guest_name}_up"),8,*
257
$(clean_fieldname "net_${guest_name}_up").min 0
258
EOF
259
      if [ -r "/sys/class/net/$device/speed" ]; then
260
         megabit_per_second=$(cat "/sys/class/net/$device/speed")
261
         bps=$((megabit_per_second * 1000 * 1000))
262
         cat <<EOF
263
$(clean_fieldname "net_${guest_name}_down").max $bps
264
$(clean_fieldname "net_${guest_name}_up").max $bps
265
EOF
266
      fi
267
   done
268

    
269
   cat <<EOF
270

    
271
multigraph lxc_proc
272
graph_title Processes
273
graph_args -l 0 --base 1000
274
graph_vlabel Number of processes
275
graph_category virtualization
276
EOF
277
   for guest_name in $active_guests
278
   do
279
      cat <<EOF
280
$(clean_fieldname "lxc_proc_${guest_name}").label $guest_name: processes
281
$(clean_fieldname "lxc_proc_${guest_name}").type GAUGE
282
$(clean_fieldname "lxc_proc_${guest_name}").min 0
283
EOF
284
   done
285

    
286
   cat <<EOF
287

    
288
multigraph lxc_ram
289
graph_title Memory
290
graph_args -l 0 --base 1024
291
graph_vlabel byte
292
graph_category virtualization
293
EOF
294

    
295
   for guest_name in $active_guests
296
   do
297
      if [ "$ram_display_stacked" != "true" ]; then
298
         draw_style="LINE1"
299
      else
300
         draw_style="AREASTACK"
301
      fi
302

    
303
      cat <<EOF
304
$(clean_fieldname "mem_usage_${guest_name}").label ${guest_name}: Mem usage
305
$(clean_fieldname "mem_usage_${guest_name}").type GAUGE
306
$(clean_fieldname "mem_usage_${guest_name}").draw $draw_style
307
$(clean_fieldname "mem_cache_${guest_name}").label ${guest_name}: Cache
308
$(clean_fieldname "mem_cache_${guest_name}").type GAUGE
309
$(clean_fieldname "mem_active_${guest_name}").label ${guest_name}: Active
310
$(clean_fieldname "mem_active_${guest_name}").type GAUGE
311
$(clean_fieldname "mem_inactive_${guest_name}").label ${guest_name}: Inactive
312
$(clean_fieldname "mem_inactive_${guest_name}").type GAUGE
313
EOF
314
   done
315
}
316

    
317

    
318
do_fetch() {
319
   local active_guests cpu_usage device value_up value_down
320
   active_guests=$(get_active_guests "$exclude")
321

    
322
   echo "multigraph lxc_cpu"
323
   for guest_name in $active_guests
324
   do
325
      for cpu_usage in user system
326
      do
327
         echo "$(clean_fieldname "cpu_${cpu_usage}_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "cpuacct.stat" | grep "$cpu_usage" | awk '{ print $2; }')"
328
      done
329
   done
330

    
331
   echo "multigraph lxc_cpu_time"
332
   for guest_name in $active_guests
333
   do
334
      echo "$(clean_fieldname "cpu_time_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "cpuacct.usage")"
335
   done
336

    
337
   echo "multigraph lxc_logins"
338
   for guest_name in $active_guests
339
   do
340
      echo "$(clean_fieldname "logins_${guest_name}").value $(lxc-attach -n "$guest_name" users | wc -w)"
341
   done
342

    
343
   echo "multigraph lxc_net"
344
   for guest_name in $active_guests
345
   do
346
      device=$(lxc-info -n "$guest_name" | grep Link | sed 's/Link:\ \+//g')
347
      if [ -z "$device" ]; then
348
         value_up="U"
349
         value_down="U"
350
      else
351
         value_up=$(grep -E "^ *${device}:" /proc/net/dev | awk '{print $10;}')
352
         value_down=$(grep -E "^ *${device}:" /proc/net/dev | awk '{print $2;}')
353
      fi
354

    
355
      cat <<EOF
356
$(clean_fieldname "net_${guest_name}_up").value $value_up
357
$(clean_fieldname "net_${guest_name}_down").value $value_down
358
EOF
359
   done
360

    
361
   echo "multigraph lxc_proc"
362
   for guest_name in $active_guests
363
   do
364
      echo "$(clean_fieldname "lxc_proc_${guest_name}").value $(lxc_count_processes "$guest_name")"
365
   done
366

    
367
   echo "multigraph lxc_ram"
368
   for guest_name in $active_guests
369
   do
370
      cat <<EOF
371
$(clean_fieldname "mem_usage_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "memory.usage_in_bytes")
372
$(clean_fieldname "mem_cache_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "memory.stat" | grep total_cache | awk '{print $2;}')
373
$(clean_fieldname "mem_active_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "memory.stat" | grep total_active_anon | awk '{print $2;}')
374
$(clean_fieldname "mem_inactive_${guest_name}").value $(get_lxc_cgroup_info "$guest_name" "memory.stat" | grep total_inactive_anon | awk '{print $2;}')
375
EOF
376
   done
377
}
378

    
379

    
380
case "${1:-}" in
381
   autoconf)
382
      do_autoconf
383
      exit 0
384
      ;;
385
   config)
386
      do_config
387
      if [ "${MUNIN_CAP_DIRTYCONFIG:-0}" = 1 ]; then do_fetch; fi
388
      exit 0
389
      ;;
390
   "")
391
      do_fetch
392
      exit 0
393
      ;;
394
   *)
395
      echo >&2 "Invalid action requested (none of: autoconf / config / '')"
396
      exit 1
397
esac