2 * collectd - src/vmware.c
3 * Copyright (C) 2010 Edward Muller
4 * Copyright (C) 2011 Keith Chambers
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; only version 2.1 of the License is
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 * Edward Muller <emuller at engineyard.com>
22 * Keith Chambers <chambers_keith at yahoo.com>
30 #include <vmGuestLib.h>
32 /* functions to dynamically load from the GuestLib library */
33 static char const * (*GuestLib_GetErrorText)(VMGuestLibError);
34 static VMGuestLibError (*GuestLib_OpenHandle)(VMGuestLibHandle*);
35 static VMGuestLibError (*GuestLib_CloseHandle)(VMGuestLibHandle);
36 static VMGuestLibError (*GuestLib_UpdateInfo)(VMGuestLibHandle handle);
37 static VMGuestLibError (*GuestLib_GetSessionId)(VMGuestLibHandle handle, VMSessionId *id);
38 static VMGuestLibError (*GuestLib_GetElapsedMs)(VMGuestLibHandle handle, uint64_t *elapsedMs);
39 static VMGuestLibError (*GuestLib_GetCpuUsedMs)(VMGuestLibHandle handle, uint64_t *cpuUsedMs);
40 static VMGuestLibError (*GuestLib_GetCpuStolenMs)(VMGuestLibHandle handle, uint64_t *cpuStolenMs);
41 static VMGuestLibError (*GuestLib_GetCpuReservationMHz)(VMGuestLibHandle handle, uint32_t *cpuReservationMHz);
42 static VMGuestLibError (*GuestLib_GetCpuLimitMHz)(VMGuestLibHandle handle, uint32_t *cpuLimitMHz);
43 static VMGuestLibError (*GuestLib_GetCpuShares)(VMGuestLibHandle handle, uint32_t *cpuShares);
44 static VMGuestLibError (*GuestLib_GetHostProcessorSpeed)(VMGuestLibHandle handle, uint32_t *mhz);
45 static VMGuestLibError (*GuestLib_GetMemUsedMB)(VMGuestLibHandle handle, uint32_t *memUsedMB);
46 static VMGuestLibError (*GuestLib_GetMemMappedMB)(VMGuestLibHandle handle, uint32_t *memMappedMB);
47 static VMGuestLibError (*GuestLib_GetMemActiveMB)(VMGuestLibHandle handle, uint32_t *memActiveMB);
48 static VMGuestLibError (*GuestLib_GetMemTargetSizeMB)(VMGuestLibHandle handle, uint64_t *memTargetSizeMB);
49 static VMGuestLibError (*GuestLib_GetMemOverheadMB)(VMGuestLibHandle handle, uint32_t *memOverheadMB);
50 static VMGuestLibError (*GuestLib_GetMemSharedMB)(VMGuestLibHandle handle, uint32_t *memSharedMB);
51 static VMGuestLibError (*GuestLib_GetMemSharedSavedMB)(VMGuestLibHandle handle, uint32_t *memSharedSavedMB);
52 static VMGuestLibError (*GuestLib_GetMemBalloonedMB)(VMGuestLibHandle handle, uint32_t *memBalloonedMB);
53 static VMGuestLibError (*GuestLib_GetMemSwappedMB)(VMGuestLibHandle handle, uint32_t *memSwappedMB);
54 static VMGuestLibError (*GuestLib_GetMemReservationMB)(VMGuestLibHandle handle, uint32_t *memReservationMB);
55 static VMGuestLibError (*GuestLib_GetMemLimitMB)(VMGuestLibHandle handle, uint32_t *memLimitMB);
56 static VMGuestLibError (*GuestLib_GetMemShares)(VMGuestLibHandle handle, uint32_t *memShares);
58 /* handle for use with shared library */
59 static VMGuestLibHandle glHandle;
61 /* used when converting megabytes to bytes for memory counters */
62 #define BYTES_PER_MB 1024*1024
64 /* macro to load a single GuestLib function from the shared library */
65 #define LOAD_ONE_FUNC(funcname) \
67 funcname = dlsym(dlHandle, "VM" #funcname); \
68 if ((dlErrStr = dlerror()) != NULL) { \
69 ERROR ("vmware plugin: Failed to load \"%s\": %s", \
70 #funcname, dlErrStr); \
76 static LoadFunctions(void)
78 void *dlHandle = NULL;
80 /* first try to load the shared library */
83 dlHandle = dlopen("libvmGuestLib.so", RTLD_NOW);
86 ERROR("vmware plugin: dlopen (\"libvmGuestLib.so\") failed: %s",
91 /* Load all the individual library functions */
92 LOAD_ONE_FUNC(GuestLib_GetErrorText);
93 LOAD_ONE_FUNC(GuestLib_OpenHandle);
94 LOAD_ONE_FUNC(GuestLib_CloseHandle);
95 LOAD_ONE_FUNC(GuestLib_UpdateInfo);
96 LOAD_ONE_FUNC(GuestLib_GetSessionId);
97 LOAD_ONE_FUNC(GuestLib_GetElapsedMs);
98 LOAD_ONE_FUNC(GuestLib_GetCpuStolenMs);
99 LOAD_ONE_FUNC(GuestLib_GetCpuUsedMs);
100 LOAD_ONE_FUNC(GuestLib_GetCpuReservationMHz);
101 LOAD_ONE_FUNC(GuestLib_GetCpuLimitMHz);
102 LOAD_ONE_FUNC(GuestLib_GetCpuShares);
103 LOAD_ONE_FUNC(GuestLib_GetHostProcessorSpeed);
104 LOAD_ONE_FUNC(GuestLib_GetMemReservationMB);
105 LOAD_ONE_FUNC(GuestLib_GetMemLimitMB);
106 LOAD_ONE_FUNC(GuestLib_GetMemShares);
107 LOAD_ONE_FUNC(GuestLib_GetMemMappedMB);
108 LOAD_ONE_FUNC(GuestLib_GetMemActiveMB);
109 LOAD_ONE_FUNC(GuestLib_GetMemOverheadMB);
110 LOAD_ONE_FUNC(GuestLib_GetMemBalloonedMB);
111 LOAD_ONE_FUNC(GuestLib_GetMemSwappedMB);
112 LOAD_ONE_FUNC(GuestLib_GetMemSharedMB);
113 LOAD_ONE_FUNC(GuestLib_GetMemSharedSavedMB);
114 LOAD_ONE_FUNC(GuestLib_GetMemUsedMB);
115 LOAD_ONE_FUNC(GuestLib_GetMemTargetSizeMB);
120 static int vmware_init (void)
122 VMGuestLibError glError;
124 if (!LoadFunctions()) {
125 ERROR ("vmware plugin: Unable to load GuestLib functions");
129 /* try to load the library */
130 glError = GuestLib_OpenHandle(&glHandle);
131 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
132 ERROR ("vmware plugin: OpenHandle failed: %s", GuestLib_GetErrorText(glError));
139 static void submit_vmw_counter (const char *type, const char *type_inst,
143 value_list_t vl = VALUE_LIST_INIT;
145 values[0].derive = value;
150 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
151 sstrncpy (vl.plugin, "vmware", sizeof (vl.plugin));
152 sstrncpy (vl.type, type, sizeof (vl.type));
153 sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
155 plugin_dispatch_values (&vl);
158 static void submit_vmw_gauge (const char *type, const char *type_inst,
162 value_list_t vl = VALUE_LIST_INIT;
164 values[0].gauge = value;
169 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
170 sstrncpy (vl.plugin, "vmware", sizeof (vl.plugin));
171 sstrncpy (vl.type, type, sizeof (vl.type));
172 sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
174 plugin_dispatch_values (&vl);
177 static int vmw_query_memory (VMGuestLibHandle handle, const char *function_name,
178 VMGuestLibError (*function) (VMGuestLibHandle handle, uint32_t *ret_data),
179 const char *type_instance)
182 VMGuestLibError status;
184 status = (*function) (handle, &value);
185 if (status != VMGUESTLIB_ERROR_SUCCESS) {
186 WARNING ("vmware plugin: %s failed: %s",
188 GuestLib_GetErrorText(glError));
192 /* The returned value is in megabytes, so multiply it by 2^20. It's not
193 * 10^6, because we're talking about memory. */
194 submit_vmw_gauge ("memory", type_instance,
195 (gauge_t) (1024 * 1024 * value));
197 } /* }}} int vmw_query_megabyte */
199 static int vmware_read (void)
201 VMGuestLibError glError;
203 /* total_time_in_ms */
204 uint64_t elapsedMs = 0;
207 uint64_t cpuUsedMs = 0;
208 uint64_t cpuStolenMs = 0;
210 /* vcpu (quality of service) */
211 uint32_t cpuReservationMHz = 0;
212 uint32_t cpuLimitMHz = 0;
213 uint32_t cpuShares = 0;
216 uint32_t hostMHz = 0;
219 uint64_t memTargetSizeMB = 0;
220 uint32_t memUsedMB = 0;
221 uint32_t memMappedMB = 0;
222 uint32_t memActiveMB = 0;
223 uint32_t memOverheadMB = 0;
224 uint32_t memSharedMB = 0;
225 uint32_t memSharedSavedMB = 0;
226 uint32_t memBalloonedMB = 0;
227 uint32_t memSwappedMB = 0;
229 /* memory (quality of service) */
230 uint32_t memReservationMB = 0;
231 uint32_t memLimitMB = 0;
232 uint32_t memShares = 0;
234 VMSessionId sessionId = 0;
236 /* attempt to retrieve info from the host */
237 VMSessionId tmpSession;
239 glError = GuestLib_UpdateInfo(glHandle);
240 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
241 ERROR ("vmware plugin: UpdateInfo failed: %s", GuestLib_GetErrorText(glError));
245 /* retrieve and check the session ID */
246 glError = GuestLib_GetSessionId(glHandle, &tmpSession);
247 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
248 ERROR ("vmware plugin: Failed to get session ID: %s", GuestLib_GetErrorText(glError));
252 if (tmpSession == 0) {
253 ERROR ("vmware plugin: Error: Got zero sessionId from GuestLib");
257 if (sessionId == 0) {
258 sessionId = tmpSession;
259 DEBUG ("vmware plugin: Initial session ID is %#"PRIx64, (uint64_t) sessionId);
260 } else if (tmpSession != sessionId) {
261 sessionId = tmpSession;
262 DEBUG ("vmware plugin: Session ID changed to %#"PRIx64, (uint64_t) sessionId);
266 glError = GuestLib_GetElapsedMs(glHandle, &elapsedMs);
267 if (glError != VMGUESTLIB_ERROR_SUCCESS)
268 WARNING ("vmware plugin: Failed to get elapsed ms: %s", GuestLib_GetErrorText(glError));
270 submit_vmw_counter ("total_time_in_ms", "elapsed", (derive_t) elapsedMs);
273 glError = GuestLib_GetCpuUsedMs(glHandle, &cpuUsedMs);
274 if (glError != VMGUESTLIB_ERROR_SUCCESS)
275 WARNING ("vmware plugin: Failed to get used ms: %s",
276 GuestLib_GetErrorText(glError));
278 submit_vmw_counter ("virt_vcpu", "used", (derive_t) cpuUsedMs);
281 glError = GuestLib_GetCpuStolenMs(glHandle, &cpuStolenMs);
282 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
283 DEBUG ("vmware plugin: Failed to get CPU stolen: %s\n", GuestLib_GetErrorText(glError));
284 if (glError == VMGUESTLIB_ERROR_UNSUPPORTED_VERSION) {
288 submit_vmw_counter ("virt_vcpu", "stolen", (derive_t) cpuStolenMs);
290 /* GetCpuReservationMHz */
291 glError = GuestLib_GetCpuReservationMHz(glHandle, &cpuReservationMHz);
292 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
293 DEBUG ("vmware plugin: Failed to get CPU reservation: %s\n", GuestLib_GetErrorText(glError));
295 submit_vmw_gauge ("vcpu", "reservation", (gauge_t) cpuReservationMHz);
298 glError = GuestLib_GetCpuLimitMHz(glHandle, &cpuLimitMHz);
299 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
300 DEBUG ("vmware plugin: Failed to get CPU limit: %s\n", GuestLib_GetErrorText(glError));
302 submit_vmw_gauge ("vcpu", "limit", (gauge_t) cpuLimitMHz);
305 glError = GuestLib_GetCpuShares(glHandle, &cpuShares);
306 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
307 DEBUG ("vmware plugin: Failed to get cpu shares: %s\n", GuestLib_GetErrorText(glError));
309 submit_vmw_gauge ("vcpu", "shares", (gauge_t) cpuShares);
311 /* GetHostProcessorSpeed */
312 glError = GuestLib_GetHostProcessorSpeed(glHandle, &hostMHz);
313 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
314 DEBUG ("vmware plugin: Failed to get host proc speed: %s\n", GuestLib_GetErrorText(glError));
316 submit_vmw_gauge ("cpufreq", "", 1.0e6 * (gauge_t) hostMHz);
318 #define VMW_QUERY_MEMORY(func, type) \
319 vmw_query_memory (glHandle, #func, GuestLib_ ## func, type)
321 VMW_QUERY_MEMORY (GetMemTargetSizeMB, "target");
322 VMW_QUERY_MEMORY (GetMemUsedMB, "used");
323 VMW_QUERY_MEMORY (GetMemMappedMB, "mapped");
324 VMW_QUERY_MEMORY (GetMemActiveMB, "active");
325 VMW_QUERY_MEMORY (GetMemOverheadMB, "overhead");
326 VMW_QUERY_MEMORY (GetMemSharedMB, "shared");
327 VMW_QUERY_MEMORY (GetMemSharedSavedMB, "shared_saved");
328 VMW_QUERY_MEMORY (GetMemBalloonedMB, "ballooned");
329 VMW_QUERY_MEMORY (GetMemSwappedMB, "swapped");
330 VMW_QUERY_MEMORY (GetMemReservationMB, "reservation");
331 VMW_QUERY_MEMORY (GetMemLimitMB, "limit");
333 #undef VMW_QUERY_MEMORY
335 /* GetMemTargetSizeMB */
336 glError = GuestLib_GetMemTargetSizeMB(glHandle, &memTargetSizeMB);
337 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
338 DEBUG ("vmware plugin: Failed to get target mem size: %s\n", GuestLib_GetErrorText(glError));
339 if (glError == VMGUESTLIB_ERROR_UNSUPPORTED_VERSION) {
343 submit_vmw_gauge ("memory", "target", BYTES_PER_MB * (gauge_t) memTargetSizeMB);
346 glError = GuestLib_GetMemUsedMB(glHandle, &memUsedMB);
347 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
348 DEBUG ("vmware plugin: Failed to get used mem: %s\n", GuestLib_GetErrorText(glError));
350 submit_vmw_gauge ("memory", "used", BYTES_PER_MB * (gauge_t) memUsedMB);
353 glError = GuestLib_GetMemMappedMB(glHandle, &memMappedMB);
354 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
355 DEBUG ("vmware plugin: Failed to get mapped mem: %s\n", GuestLib_GetErrorText(glError));
357 submit_vmw_gauge ("memory", "mapped", BYTES_PER_MB * (gauge_t) memMappedMB);
360 glError = GuestLib_GetMemActiveMB(glHandle, &memActiveMB);
361 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
362 DEBUG ("vmware plugin: Failed to get active mem: %s\n", GuestLib_GetErrorText(glError));
364 submit_vmw_gauge ("memory", "active", BYTES_PER_MB * (gauge_t) memActiveMB);
366 /* GetMemOverheadMB */
367 glError = GuestLib_GetMemOverheadMB(glHandle, &memOverheadMB);
368 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
369 DEBUG ("vmware plugin: Failed to get overhead mem: %s\n", GuestLib_GetErrorText(glError));
371 submit_vmw_gauge ("memory", "overhead", BYTES_PER_MB * (gauge_t) memOverheadMB);
374 glError = GuestLib_GetMemSharedMB(glHandle, &memSharedMB);
375 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
376 DEBUG ("vmware plugin: Failed to get shared mem: %s\n", GuestLib_GetErrorText(glError));
378 submit_vmw_gauge ("memory", "shared", BYTES_PER_MB * (gauge_t) memSharedMB);
380 /* GetMemSharedSavedMB */
381 glError = GuestLib_GetMemSharedSavedMB(glHandle, &memSharedSavedMB);
382 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
383 DEBUG ("vmware plugin: Failed to get shared saved mem: %s\n", GuestLib_GetErrorText(glError));
385 submit_vmw_gauge ("memory", "shared_saved", BYTES_PER_MB * (gauge_t) memSharedSavedMB);
387 /* GetMemBalloonedMB */
388 glError = GuestLib_GetMemBalloonedMB(glHandle, &memBalloonedMB);
389 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
390 DEBUG ("vmware plugin: Failed to get ballooned mem: %s\n", GuestLib_GetErrorText(glError));
392 submit_vmw_gauge ("memory", "ballooned", BYTES_PER_MB * (gauge_t) memBalloonedMB);
394 /* GetMemSwappedMB */
395 glError = GuestLib_GetMemSwappedMB(glHandle, &memSwappedMB);
396 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
397 DEBUG ("vmware plugin: Failed to get swapped mem: %s\n", GuestLib_GetErrorText(glError));
399 submit_vmw_gauge ("memory", "swapped", BYTES_PER_MB * (gauge_t) memSwappedMB);
401 /* GetMemReservationMB */
402 glError = GuestLib_GetMemReservationMB(glHandle, &memReservationMB);
403 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
404 DEBUG ("vmware plugin: Failed to get mem reservation: %s\n", GuestLib_GetErrorText(glError));
406 submit_vmw_gauge ("memory", "reservation", BYTES_PER_MB * (gauge_t) memReservationMB);
409 glError = GuestLib_GetMemLimitMB(glHandle, &memLimitMB);
410 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
411 DEBUG ("vmware plugin: Failed to get mem limit: %s\n", GuestLib_GetErrorText(glError));
413 submit_vmw_gauge ("memory", "limit", BYTES_PER_MB * (gauge_t) memLimitMB);
416 glError = GuestLib_GetMemShares(glHandle, &memShares);
417 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
418 DEBUG ("vmware plugin: Failed to get mem shares: %s\n", GuestLib_GetErrorText(glError));
421 submit_vmw_gauge ("memory", "shares", (gauge_t) memShares);
426 void module_register (void)
428 plugin_register_init ("vmware", vmware_init);
429 plugin_register_read ("vmware", vmware_read);