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) (BYTES_PER_MB * 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;
218 /* memory (quality of service) */
219 uint32_t memShares = 0;
221 VMSessionId sessionId = 0;
223 /* attempt to retrieve info from the host */
224 VMSessionId tmpSession;
226 glError = GuestLib_UpdateInfo(glHandle);
227 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
228 ERROR ("vmware plugin: UpdateInfo failed: %s", GuestLib_GetErrorText(glError));
232 /* retrieve and check the session ID */
233 glError = GuestLib_GetSessionId(glHandle, &tmpSession);
234 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
235 ERROR ("vmware plugin: Failed to get session ID: %s", GuestLib_GetErrorText(glError));
239 if (tmpSession == 0) {
240 ERROR ("vmware plugin: Error: Got zero sessionId from GuestLib");
244 if (sessionId == 0) {
245 sessionId = tmpSession;
246 DEBUG ("vmware plugin: Initial session ID is %#"PRIx64, (uint64_t) sessionId);
247 } else if (tmpSession != sessionId) {
248 sessionId = tmpSession;
249 DEBUG ("vmware plugin: Session ID changed to %#"PRIx64, (uint64_t) sessionId);
253 glError = GuestLib_GetElapsedMs(glHandle, &elapsedMs);
254 if (glError != VMGUESTLIB_ERROR_SUCCESS)
255 WARNING ("vmware plugin: Failed to get elapsed ms: %s", GuestLib_GetErrorText(glError));
257 submit_vmw_counter ("total_time_in_ms", "elapsed", (derive_t) elapsedMs);
260 glError = GuestLib_GetCpuUsedMs(glHandle, &cpuUsedMs);
261 if (glError != VMGUESTLIB_ERROR_SUCCESS)
262 WARNING ("vmware plugin: Failed to get used ms: %s",
263 GuestLib_GetErrorText(glError));
265 submit_vmw_counter ("virt_vcpu", "used", (derive_t) cpuUsedMs);
268 glError = GuestLib_GetCpuStolenMs(glHandle, &cpuStolenMs);
269 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
270 DEBUG ("vmware plugin: Failed to get CPU stolen: %s\n", GuestLib_GetErrorText(glError));
271 if (glError == VMGUESTLIB_ERROR_UNSUPPORTED_VERSION) {
275 submit_vmw_counter ("virt_vcpu", "stolen", (derive_t) cpuStolenMs);
277 /* GetCpuReservationMHz */
278 glError = GuestLib_GetCpuReservationMHz(glHandle, &cpuReservationMHz);
279 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
280 DEBUG ("vmware plugin: Failed to get CPU reservation: %s\n", GuestLib_GetErrorText(glError));
282 submit_vmw_gauge ("vcpu", "reservation", (gauge_t) cpuReservationMHz);
285 glError = GuestLib_GetCpuLimitMHz(glHandle, &cpuLimitMHz);
286 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
287 DEBUG ("vmware plugin: Failed to get CPU limit: %s\n", GuestLib_GetErrorText(glError));
289 submit_vmw_gauge ("vcpu", "limit", (gauge_t) cpuLimitMHz);
292 glError = GuestLib_GetCpuShares(glHandle, &cpuShares);
293 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
294 DEBUG ("vmware plugin: Failed to get cpu shares: %s\n", GuestLib_GetErrorText(glError));
296 submit_vmw_gauge ("vcpu", "shares", (gauge_t) cpuShares);
298 /* GetHostProcessorSpeed */
299 glError = GuestLib_GetHostProcessorSpeed(glHandle, &hostMHz);
300 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
301 DEBUG ("vmware plugin: Failed to get host proc speed: %s\n", GuestLib_GetErrorText(glError));
303 submit_vmw_gauge ("cpufreq", "", 1.0e6 * (gauge_t) hostMHz);
305 #define VMW_QUERY_MEMORY(func, type) \
306 vmw_query_memory (glHandle, #func, GuestLib_ ## func, type)
308 VMW_QUERY_MEMORY (GetMemTargetSizeMB, "target");
309 VMW_QUERY_MEMORY (GetMemUsedMB, "used");
310 VMW_QUERY_MEMORY (GetMemMappedMB, "mapped");
311 VMW_QUERY_MEMORY (GetMemActiveMB, "active");
312 VMW_QUERY_MEMORY (GetMemOverheadMB, "overhead");
313 VMW_QUERY_MEMORY (GetMemSharedMB, "shared");
314 VMW_QUERY_MEMORY (GetMemSharedSavedMB, "shared_saved");
315 VMW_QUERY_MEMORY (GetMemBalloonedMB, "ballooned");
316 VMW_QUERY_MEMORY (GetMemSwappedMB, "swapped");
317 VMW_QUERY_MEMORY (GetMemReservationMB, "reservation");
318 VMW_QUERY_MEMORY (GetMemLimitMB, "limit");
320 #undef VMW_QUERY_MEMORY
323 glError = GuestLib_GetMemShares(glHandle, &memShares);
324 if (glError != VMGUESTLIB_ERROR_SUCCESS) {
325 DEBUG ("vmware plugin: Failed to get mem shares: %s\n", GuestLib_GetErrorText(glError));
328 submit_vmw_gauge ("memory", "shares", (gauge_t) memShares);
333 void module_register (void)
335 plugin_register_init ("vmware", vmware_init);
336 plugin_register_read ("vmware", vmware_read);