1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21
22 /* LIBXML2 is used */
23 #ifdef HAVE_LIBXML2
24 # include <libxml/parser.h>
25 # include <libxml/tree.h>
26 # include <libxml/xpath.h>
27 #endif
28
29 #include "ipc.h"
30 #include "memalloc.h"
31 #include "log.h"
32 #include "zbxalgo.h"
33 #include "daemon.h"
34 #include "zbxself.h"
35
36 #include "vmware.h"
37 #include "../../libs/zbxalgo/vectorimpl.h"
38
39 /*
40 * The VMware data (zbx_vmware_service_t structure) are stored in shared memory.
41 * This data can be accessed with zbx_vmware_get_service() function and is regularly
42 * updated by VMware collector processes.
43 *
44 * When a new service is requested by poller the zbx_vmware_get_service() function
45 * creates a new service object, marks it as new, but still returns NULL object.
46 *
47 * The collectors check the service object list for new services or services not updated
48 * during last CONFIG_VMWARE_FREQUENCY seconds. If such service is found it is marked
49 * as updating.
50 *
51 * The service object is updated by creating a new data object, initializing it
52 * with the latest data from VMware vCenter (or Hypervisor), destroying the old data
53 * object and replacing it with the new one.
54 *
55 * The collector must be locked only when accessing service object list and working with
56 * a service object. It is not locked for new data object creation during service update,
57 * which is the most time consuming task.
58 *
59 * As the data retrieved by VMware collector can be quite big (for example 1 Hypervisor
60 * with 500 Virtual Machines will result in approximately 20 MB of data), VMware collector
61 * updates performance data (which is only 10% of the structure data) separately
62 * with CONFIG_VMWARE_PERF_FREQUENCY period. The performance data is stored directly
63 * in VMware service object entities vector - so the structure data is not affected by
64 * performance data updates.
65 */
66
67 extern char *CONFIG_FILE;
68 extern int CONFIG_VMWARE_FREQUENCY;
69 extern int CONFIG_VMWARE_PERF_FREQUENCY;
70 extern zbx_uint64_t CONFIG_VMWARE_CACHE_SIZE;
71 extern int CONFIG_VMWARE_TIMEOUT;
72
73 extern unsigned char process_type, program_type;
74 extern int server_num, process_num;
75 extern char *CONFIG_SOURCE_IP;
76
77 #define VMWARE_VECTOR_CREATE(ref, type) zbx_vector_##type##_create_ext(ref, __vm_mem_malloc_func, \
78 __vm_mem_realloc_func, __vm_mem_free_func)
79
80 #define ZBX_VMWARE_CACHE_UPDATE_PERIOD CONFIG_VMWARE_FREQUENCY
81 #define ZBX_VMWARE_PERF_UPDATE_PERIOD CONFIG_VMWARE_PERF_FREQUENCY
82 #define ZBX_VMWARE_SERVICE_TTL SEC_PER_HOUR
83 #define ZBX_XML_DATETIME 26
84
85 static ZBX_MUTEX vmware_lock = ZBX_MUTEX_NULL;
86
87 static zbx_mem_info_t *vmware_mem = NULL;
88
89 ZBX_MEM_FUNC_IMPL(__vm, vmware_mem)
90
91 static zbx_vmware_t *vmware = NULL;
92
93 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
94
95 /* according to libxml2 changelog XML_PARSE_HUGE option was introduced in version 2.7.0 */
96 #if 20700 <= LIBXML_VERSION /* version 2.7.0 */
97 # define ZBX_XML_PARSE_OPTS XML_PARSE_HUGE
98 #else
99 # define ZBX_XML_PARSE_OPTS 0
100 #endif
101
102 #define ZBX_VMWARE_COUNTERS_INIT_SIZE 500
103
104 #define ZBX_VPXD_STATS_MAXQUERYMETRICS 64
105 #define ZBX_MAXQUERYMETRICS_UNLIMITED 1000
106
107 /* VMware service object name mapping for vcenter and vsphere installations */
108 typedef struct
109 {
110 const char *performance_manager;
111 const char *session_manager;
112 const char *event_manager;
113 const char *property_collector;
114 }
115 zbx_vmware_service_objects_t;
116
117 static zbx_vmware_service_objects_t vmware_service_objects[3] =
118 {
119 {NULL, NULL, NULL, NULL},
120 {"ha-perfmgr", "ha-sessionmgr", "ha-eventmgr", "ha-property-collector"},
121 {"PerfMgr", "SessionManager", "EventManager", "propertyCollector"}
122 };
123
124 /* mapping of performance counter group/key[rollup type] to its id (net/transmitted[average] -> <id>) */
125 typedef struct
126 {
127 char *path;
128 zbx_uint64_t id;
129 }
130 zbx_vmware_counter_t;
131
132 /* the vm/hv object property mapping */
133 typedef struct
134 {
135 int propid;
136 const char *xpath;
137 }
138 zbx_vmware_propmap_t;
139
140 /* performance counter value for a specific instance */
141 typedef struct
142 {
143 zbx_uint64_t counterid;
144 char *instance;
145 char *value;
146 }
147 zbx_vmware_perf_value_t;
148
149 /* performance data for a performance collector entity */
150 typedef struct
151 {
152 /* entity type: HostSystem, Datastore or VirtualMachine */
153 char *type;
154
155 /* entity id */
156 char *id;
157
158 /* the performance counter values (see zbx_vmware_perfvalue_t) */
159 zbx_vector_ptr_t values;
160
161 /* error information */
162 char *error;
163 }
164 zbx_vmware_perf_data_t;
165
166 typedef struct
167 {
168 zbx_uint64_t id;
169 xmlNode *xml_node;
170 }
171 zbx_id_xmlnode_t;
172
173 ZBX_VECTOR_DECL(id_xmlnode, zbx_id_xmlnode_t)
174 ZBX_VECTOR_IMPL(id_xmlnode, zbx_id_xmlnode_t)
175
176 static char *hv_propmap[] = {
177 ZBX_XPATH_HV_QUICKSTATS("overallCpuUsage"), /* ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE */
178 ZBX_XPATH_HV_CONFIG_PRODUCT("fullName"), /* ZBX_VMWARE_HVPROP_FULL_NAME */
179 ZBX_XPATH_HV_HARDWARE("numCpuCores"), /* ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES */
180 ZBX_XPATH_HV_HARDWARE("cpuMhz"), /* ZBX_VMWARE_HVPROP_HW_CPU_MHZ */
181 ZBX_XPATH_HV_HARDWARE("cpuModel"), /* ZBX_VMWARE_HVPROP_HW_CPU_MODEL */
182 ZBX_XPATH_HV_HARDWARE("numCpuThreads"), /* ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS */
183 ZBX_XPATH_HV_HARDWARE("memorySize"), /* ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE */
184 ZBX_XPATH_HV_HARDWARE("model"), /* ZBX_VMWARE_HVPROP_HW_MODEL */
185 ZBX_XPATH_HV_HARDWARE("uuid"), /* ZBX_VMWARE_HVPROP_HW_UUID */
186 ZBX_XPATH_HV_HARDWARE("vendor"), /* ZBX_VMWARE_HVPROP_HW_VENDOR */
187 ZBX_XPATH_HV_QUICKSTATS("overallMemoryUsage"), /* ZBX_VMWARE_HVPROP_MEMORY_USED */
188 ZBX_XPATH_HV_SENSOR_STATUS("VMware Rollup Health State"), /* ZBX_VMWARE_HVPROP_HEALTH_STATE */
189 ZBX_XPATH_HV_QUICKSTATS("uptime"), /* ZBX_VMWARE_HVPROP_UPTIME */
190 ZBX_XPATH_HV_CONFIG_PRODUCT("version"), /* ZBX_VMWARE_HVPROP_VERSION */
191 ZBX_XPATH_HV_CONFIG("name"), /* ZBX_VMWARE_HVPROP_NAME */
192 ZBX_XPATH_HV_STATUS() /* ZBX_VMWARE_HVPROP_STATUS */
193 };
194
195 static char *vm_propmap[] = {
196 ZBX_XPATH_VM_CONFIG("numCpu"), /* ZBX_VMWARE_VMPROP_CPU_NUM */
197 ZBX_XPATH_VM_QUICKSTATS("overallCpuUsage"), /* ZBX_VMWARE_VMPROP_CPU_USAGE */
198 ZBX_XPATH_VM_CONFIG("name"), /* ZBX_VMWARE_VMPROP_NAME */
199 ZBX_XPATH_VM_CONFIG("memorySizeMB"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE */
200 ZBX_XPATH_VM_QUICKSTATS("balloonedMemory"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_BALLOONED */
201 ZBX_XPATH_VM_QUICKSTATS("compressedMemory"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_COMPRESSED */
202 ZBX_XPATH_VM_QUICKSTATS("swappedMemory"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_SWAPPED */
203 ZBX_XPATH_VM_QUICKSTATS("guestMemoryUsage"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_GUEST */
204 ZBX_XPATH_VM_QUICKSTATS("hostMemoryUsage"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_USAGE_HOST */
205 ZBX_XPATH_VM_QUICKSTATS("privateMemory"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_PRIVATE */
206 ZBX_XPATH_VM_QUICKSTATS("sharedMemory"), /* ZBX_VMWARE_VMPROP_MEMORY_SIZE_SHARED */
207 ZBX_XPATH_VM_RUNTIME("powerState"), /* ZBX_VMWARE_VMPROP_POWER_STATE */
208 ZBX_XPATH_VM_STORAGE("committed"), /* ZBX_VMWARE_VMPROP_STORAGE_COMMITED */
209 ZBX_XPATH_VM_STORAGE("unshared"), /* ZBX_VMWARE_VMPROP_STORAGE_UNSHARED */
210 ZBX_XPATH_VM_STORAGE("uncommitted"), /* ZBX_VMWARE_VMPROP_STORAGE_UNCOMMITTED */
211 ZBX_XPATH_VM_QUICKSTATS("uptimeSeconds") /* ZBX_VMWARE_VMPROP_UPTIME */
212 };
213
214 /* hypervisor hashset support */
vmware_hv_hash(const void * data)215 zbx_hash_t vmware_hv_hash(const void *data)
216 {
217 zbx_vmware_hv_t *hv = (zbx_vmware_hv_t *)data;
218
219 return ZBX_DEFAULT_STRING_HASH_ALGO(hv->uuid, strlen(hv->uuid), ZBX_DEFAULT_HASH_SEED);
220 }
221
vmware_hv_compare(const void * d1,const void * d2)222 int vmware_hv_compare(const void *d1, const void *d2)
223 {
224 zbx_vmware_hv_t *hv1 = (zbx_vmware_hv_t *)d1;
225 zbx_vmware_hv_t *hv2 = (zbx_vmware_hv_t *)d2;
226
227 return strcmp(hv1->uuid, hv2->uuid);
228 }
229
230 /* virtual machine index support */
vmware_vm_hash(const void * data)231 zbx_hash_t vmware_vm_hash(const void *data)
232 {
233 zbx_vmware_vm_index_t *vmi = (zbx_vmware_vm_index_t *)data;
234
235 return ZBX_DEFAULT_STRING_HASH_ALGO(vmi->vm->uuid, strlen(vmi->vm->uuid), ZBX_DEFAULT_HASH_SEED);
236 }
237
vmware_vm_compare(const void * d1,const void * d2)238 int vmware_vm_compare(const void *d1, const void *d2)
239 {
240 zbx_vmware_vm_index_t *vmi1 = (zbx_vmware_vm_index_t *)d1;
241 zbx_vmware_vm_index_t *vmi2 = (zbx_vmware_vm_index_t *)d2;
242
243 return strcmp(vmi1->vm->uuid, vmi2->vm->uuid);
244 }
245
246 /* string pool support */
247
248 #define REFCOUNT_FIELD_SIZE sizeof(zbx_uint32_t)
249
vmware_strpool_hash_func(const void * data)250 static zbx_hash_t vmware_strpool_hash_func(const void *data)
251 {
252 return ZBX_DEFAULT_STRING_HASH_FUNC((char *)data + REFCOUNT_FIELD_SIZE);
253 }
254
vmware_strpool_compare_func(const void * d1,const void * d2)255 static int vmware_strpool_compare_func(const void *d1, const void *d2)
256 {
257 return strcmp((char *)d1 + REFCOUNT_FIELD_SIZE, (char *)d2 + REFCOUNT_FIELD_SIZE);
258 }
259
vmware_shared_strdup(const char * str)260 static char *vmware_shared_strdup(const char *str)
261 {
262 void *ptr;
263
264 if (NULL == str)
265 return NULL;
266
267 ptr = zbx_hashset_search(&vmware->strpool, str - REFCOUNT_FIELD_SIZE);
268
269 if (NULL == ptr)
270 {
271 ptr = zbx_hashset_insert_ext(&vmware->strpool, str - REFCOUNT_FIELD_SIZE,
272 REFCOUNT_FIELD_SIZE + strlen(str) + 1, REFCOUNT_FIELD_SIZE);
273
274 *(zbx_uint32_t *)ptr = 0;
275 }
276
277 (*(zbx_uint32_t *)ptr)++;
278
279 return (char *)ptr + REFCOUNT_FIELD_SIZE;
280 }
281
vmware_shared_strfree(char * str)282 static void vmware_shared_strfree(char *str)
283 {
284 if (NULL != str)
285 {
286 void *ptr = str - REFCOUNT_FIELD_SIZE;
287
288 if (0 == --(*(zbx_uint32_t *)ptr))
289 zbx_hashset_remove_direct(&vmware->strpool, ptr);
290 }
291 }
292
293 /*
294 * SOAP support
295 */
296 #define ZBX_XML_HEADER1 "Soapaction:urn:vim25/4.1"
297 #define ZBX_XML_HEADER2 "Content-Type:text/xml; charset=utf-8"
298
299 #define ZBX_POST_VSPHERE_HEADER \
300 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
301 "<SOAP-ENV:Envelope" \
302 " xmlns:ns0=\"urn:vim25\"" \
303 " xmlns:ns1=\"http://schemas.xmlsoap.org/soap/envelope/\"" \
304 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" \
305 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" \
306 "<SOAP-ENV:Header/>" \
307 "<ns1:Body>"
308 #define ZBX_POST_VSPHERE_FOOTER \
309 "</ns1:Body>" \
310 "</SOAP-ENV:Envelope>"
311
312 #define ZBX_XPATH_FAULTSTRING() \
313 "/*/*/*[local-name()='Fault']/*[local-name()='faultstring']"
314
315 #define ZBX_XPATH_REFRESHRATE() \
316 "/*/*/*/*/*[local-name()='refreshRate' and ../*[local-name()='currentSupported']='true']"
317
318 #define ZBX_XPATH_ISAGGREGATE() \
319 "/*/*/*/*/*[local-name()='entity'][../*[local-name()='summarySupported']='true' and " \
320 "../*[local-name()='currentSupported']='false']"
321
322 #define ZBX_XPATH_COUNTERINFO() \
323 "/*/*/*/*/*[local-name()='propSet']/*[local-name()='val']/*[local-name()='PerfCounterInfo']"
324
325 #define ZBX_XPATH_DATASTORE(property) \
326 "/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='" property "']]" \
327 "/*[local-name()='val']"
328
329 #define ZBX_XPATH_DATASTORE_MOUNT() \
330 "/*/*/*/*/*[local-name()='propSet']/*/*[local-name()='DatastoreHostMount']" \
331 "/*[local-name()='mountInfo']/*[local-name()='path']"
332
333 #define ZBX_XPATH_HV_DATASTORES() \
334 "/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='datastore']]" \
335 "/*[local-name()='val']/*[@type='Datastore']"
336
337 #define ZBX_XPATH_HV_VMS() \
338 "/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='vm']]" \
339 "/*[local-name()='val']/*[@type='VirtualMachine']"
340
341 #define ZBX_XPATH_DATASTORE_SUMMARY(property) \
342 "/*/*/*/*/*[local-name()='propSet'][*[local-name()='name'][text()='summary']]" \
343 "/*[local-name()='val']/*[local-name()='" property "']"
344
345 #define ZBX_XPATH_MAXQUERYMETRICS() \
346 "/*/*/*/*[*[local-name()='key']='config.vpxd.stats.maxQueryMetrics']/*[local-name()='value']"
347
348 typedef struct
349 {
350 char *data;
351 size_t alloc;
352 size_t offset;
353 }
354 ZBX_HTTPPAGE;
355
356 static ZBX_HTTPPAGE page;
357
358 static char *zbx_xml_read_node_value(xmlDoc *doc, xmlNode *node, const char *xpath);
359
curl_write_cb(void * ptr,size_t size,size_t nmemb,void * userdata)360 static size_t curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
361 {
362 size_t r_size = size * nmemb;
363
364 ZBX_UNUSED(userdata);
365
366 zbx_strncpy_alloc(&page.data, &page.alloc, &page.offset, ptr, r_size);
367
368 return r_size;
369 }
370
curl_header_cb(void * ptr,size_t size,size_t nmemb,void * userdata)371 static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
372 {
373 ZBX_UNUSED(ptr);
374 ZBX_UNUSED(userdata);
375
376 return size * nmemb;
377 }
378
379 /******************************************************************************
380 * *
381 * performance counter hashset support functions *
382 * *
383 ******************************************************************************/
vmware_counter_hash_func(const void * data)384 static zbx_hash_t vmware_counter_hash_func(const void *data)
385 {
386 zbx_vmware_counter_t *counter = (zbx_vmware_counter_t *)data;
387
388 return ZBX_DEFAULT_STRING_HASH_ALGO(counter->path, strlen(counter->path), ZBX_DEFAULT_HASH_SEED);
389 }
390
vmware_counter_compare_func(const void * d1,const void * d2)391 static int vmware_counter_compare_func(const void *d1, const void *d2)
392 {
393 zbx_vmware_counter_t *c1 = (zbx_vmware_counter_t *)d1;
394 zbx_vmware_counter_t *c2 = (zbx_vmware_counter_t *)d2;
395
396 return strcmp(c1->path, c2->path);
397 }
398
399 /******************************************************************************
400 * *
401 * performance entities hashset support functions *
402 * *
403 ******************************************************************************/
vmware_perf_entity_hash_func(const void * data)404 static zbx_hash_t vmware_perf_entity_hash_func(const void *data)
405 {
406 zbx_hash_t seed;
407
408 zbx_vmware_perf_entity_t *entity = (zbx_vmware_perf_entity_t *)data;
409
410 seed = ZBX_DEFAULT_STRING_HASH_ALGO(entity->type, strlen(entity->type), ZBX_DEFAULT_HASH_SEED);
411
412 return ZBX_DEFAULT_STRING_HASH_ALGO(entity->id, strlen(entity->id), seed);
413 }
414
vmware_perf_entity_compare_func(const void * d1,const void * d2)415 static int vmware_perf_entity_compare_func(const void *d1, const void *d2)
416 {
417 int ret;
418
419 zbx_vmware_perf_entity_t *e1 = (zbx_vmware_perf_entity_t *)d1;
420 zbx_vmware_perf_entity_t *e2 = (zbx_vmware_perf_entity_t *)d2;
421
422 if (0 == (ret = strcmp(e1->type, e2->type)))
423 ret = strcmp(e1->id, e2->id);
424
425 return ret;
426 }
427
428 /******************************************************************************
429 * *
430 * Function: vmware_free_perfvalue *
431 * *
432 * Purpose: frees perfvalue data structure *
433 * *
434 ******************************************************************************/
vmware_free_perfvalue(zbx_vmware_perf_value_t * value)435 static void vmware_free_perfvalue(zbx_vmware_perf_value_t *value)
436 {
437 zbx_free(value->instance);
438 zbx_free(value->value);
439 zbx_free(value);
440 }
441
442 /******************************************************************************
443 * *
444 * Function: vmware_free_perfdata *
445 * *
446 * Purpose: frees perfdata data structure *
447 * *
448 ******************************************************************************/
vmware_free_perfdata(zbx_vmware_perf_data_t * data)449 static void vmware_free_perfdata(zbx_vmware_perf_data_t *data)
450 {
451 zbx_free(data->id);
452 zbx_free(data->type);
453 zbx_free(data->error);
454 zbx_vector_ptr_clear_ext(&data->values, (zbx_mem_free_func_t)vmware_free_perfvalue);
455 zbx_vector_ptr_destroy(&data->values);
456
457 zbx_free(data);
458 }
459
460 /******************************************************************************
461 * *
462 * Function: xml_read_props *
463 * *
464 * Purpose: reads the vmware object properties by their xpaths from xml data *
465 * *
466 * Parameters: xml - [IN] the xml data *
467 * propmap - [IN] the xpaths of the properties to read *
468 * props_num - [IN] the number of properties to read *
469 * *
470 * Return value: an array of property values *
471 * *
472 * Comments: The array with property values must be freed by the caller. *
473 * *
474 ******************************************************************************/
xml_read_props(const char * xml,char ** propmap,int props_num)475 static char **xml_read_props(const char *xml, char **propmap, int props_num)
476 {
477 xmlDoc *doc;
478 xmlXPathContext *xpathCtx;
479 xmlXPathObject *xpathObj;
480 xmlNodeSetPtr nodeset;
481 xmlChar *val;
482 char **props;
483 int i;
484
485 if (NULL == (doc = xmlReadMemory(xml, strlen(xml), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
486 return NULL;
487
488 props = (char **)zbx_malloc(NULL, sizeof(char *) * props_num);
489 memset(props, 0, sizeof(char *) * props_num);
490
491 for (i = 0; i < props_num; i++)
492 {
493 xpathCtx = xmlXPathNewContext(doc);
494
495 if (NULL != (xpathObj = xmlXPathEvalExpression((const xmlChar *)propmap[i], xpathCtx)))
496 {
497 if (0 == xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
498 {
499 nodeset = xpathObj->nodesetval;
500
501 if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1)))
502 {
503 props[i] = zbx_strdup(NULL, (const char *)val);
504 xmlFree(val);
505 }
506 }
507
508 xmlXPathFreeObject(xpathObj);
509 }
510
511 xmlXPathFreeContext(xpathCtx);
512 }
513
514 xmlFreeDoc(doc);
515
516 return props;
517 }
518
519 /******************************************************************************
520 * *
521 * Function: vmware_counters_shared_copy *
522 * *
523 * Purpose: copies performance counter vector into shared memory hashset *
524 * *
525 * Parameters: dst - [IN] the destination hashset *
526 * src - [IN] the source vector *
527 * *
528 ******************************************************************************/
vmware_counters_shared_copy(zbx_hashset_t * dst,const zbx_vector_ptr_t * src)529 static void vmware_counters_shared_copy(zbx_hashset_t *dst, const zbx_vector_ptr_t *src)
530 {
531 int i;
532 zbx_vmware_counter_t *csrc, *cdst;
533
534 for (i = 0; i < src->values_num; i++)
535 {
536 csrc = src->values[i];
537
538 cdst = zbx_hashset_insert(dst, csrc, sizeof(zbx_vmware_counter_t));
539 cdst->path = vmware_shared_strdup(csrc->path);
540 }
541 }
542
543 /******************************************************************************
544 * *
545 * Function: vmware_vector_ptr_pair_shared_clean *
546 * *
547 * Purpose: frees shared resources allocated to store instance performance *
548 * counter values *
549 * *
550 * Parameters: pairs - [IN] vector of performance counter pairs *
551 * *
552 ******************************************************************************/
vmware_vector_ptr_pair_shared_clean(zbx_vector_ptr_pair_t * pairs)553 static void vmware_vector_ptr_pair_shared_clean(zbx_vector_ptr_pair_t *pairs)
554 {
555 int i;
556
557 for (i = 0; i < pairs->values_num; i++)
558 {
559 zbx_ptr_pair_t *pair = &pairs->values[i];
560
561 if (NULL != pair->first)
562 vmware_shared_strfree(pair->first);
563
564 vmware_shared_strfree(pair->second);
565 }
566
567 pairs->values_num = 0;
568 }
569
570 /******************************************************************************
571 * *
572 * Function: vmware_perf_counter_shared_free *
573 * *
574 * Purpose: frees shared resources allocated to store performance counter *
575 * data *
576 * *
577 * Parameters: counter - [IN] the performance counter data *
578 * *
579 ******************************************************************************/
vmware_perf_counter_shared_free(zbx_vmware_perf_counter_t * counter)580 static void vmware_perf_counter_shared_free(zbx_vmware_perf_counter_t *counter)
581 {
582 vmware_vector_ptr_pair_shared_clean(&counter->values);
583 zbx_vector_ptr_pair_destroy(&counter->values);
584 __vm_mem_free_func(counter);
585 }
586
587 /******************************************************************************
588 * *
589 * Function: vmware_entities_shared_clean_stats *
590 * *
591 * Purpose: removes statistics data from vmware entities *
592 * *
593 ******************************************************************************/
vmware_entities_shared_clean_stats(zbx_hashset_t * entities)594 static void vmware_entities_shared_clean_stats(zbx_hashset_t *entities)
595 {
596 int i;
597 zbx_vmware_perf_entity_t *entity;
598 zbx_vmware_perf_counter_t *counter;
599 zbx_hashset_iter_t iter;
600
601
602 zbx_hashset_iter_reset(entities, &iter);
603 while (NULL != (entity = zbx_hashset_iter_next(&iter)))
604 {
605 for (i = 0; i < entity->counters.values_num; i++)
606 {
607 counter = (zbx_vmware_perf_counter_t *)entity->counters.values[i];
608 vmware_vector_ptr_pair_shared_clean(&counter->values);
609
610 if (0 != (counter->state & ZBX_VMWARE_COUNTER_UPDATING))
611 counter->state = ZBX_VMWARE_COUNTER_READY;
612 }
613 vmware_shared_strfree(entity->error);
614 entity->error = NULL;
615 }
616 }
617
618 /******************************************************************************
619 * *
620 * Function: vmware_datastore_shared_free *
621 * *
622 * Purpose: frees shared resources allocated to store datastore data *
623 * *
624 * Parameters: datastore - [IN] the datastore *
625 * *
626 ******************************************************************************/
vmware_datastore_shared_free(zbx_vmware_datastore_t * datastore)627 static void vmware_datastore_shared_free(zbx_vmware_datastore_t *datastore)
628 {
629 vmware_shared_strfree(datastore->name);
630 vmware_shared_strfree(datastore->id);
631
632 if (NULL != datastore->uuid)
633 vmware_shared_strfree(datastore->uuid);
634
635 __vm_mem_free_func(datastore);
636 }
637
638 /******************************************************************************
639 * *
640 * Function: vmware_props_shared_free *
641 * *
642 * Purpose: frees shared resources allocated to store properties list *
643 * *
644 * Parameters: props - [IN] the properties list *
645 * props_num - [IN] the number of properties in the list *
646 * *
647 ******************************************************************************/
vmware_props_shared_free(char ** props,int props_num)648 static void vmware_props_shared_free(char **props, int props_num)
649 {
650 int i;
651
652 if (NULL == props)
653 return;
654
655 for (i = 0; i < props_num; i++)
656 {
657 if (NULL != props[i])
658 vmware_shared_strfree(props[i]);
659 }
660
661 __vm_mem_free_func(props);
662 }
663
664 /******************************************************************************
665 * *
666 * Function: vmware_dev_shared_free *
667 * *
668 * Purpose: frees shared resources allocated to store vm device data *
669 * *
670 * Parameters: dev - [IN] the vm device *
671 * *
672 ******************************************************************************/
vmware_dev_shared_free(zbx_vmware_dev_t * dev)673 static void vmware_dev_shared_free(zbx_vmware_dev_t *dev)
674 {
675 if (NULL != dev->instance)
676 vmware_shared_strfree(dev->instance);
677
678 if (NULL != dev->label)
679 vmware_shared_strfree(dev->label);
680
681 __vm_mem_free_func(dev);
682 }
683
684 /******************************************************************************
685 * *
686 * Function: vmware_fs_shared_free *
687 * *
688 * Purpose: frees shared resources allocated to store file system object *
689 * *
690 * Parameters: fs - [IN] the file system *
691 * *
692 ******************************************************************************/
vmware_fs_shared_free(zbx_vmware_fs_t * fs)693 static void vmware_fs_shared_free(zbx_vmware_fs_t *fs)
694 {
695 if (NULL != fs->path)
696 vmware_shared_strfree(fs->path);
697
698 __vm_mem_free_func(fs);
699 }
700
701 /******************************************************************************
702 * *
703 * Function: vmware_vm_shared_free *
704 * *
705 * Purpose: frees shared resources allocated to store virtual machine *
706 * *
707 * Parameters: vm - [IN] the virtual machine *
708 * *
709 ******************************************************************************/
vmware_vm_shared_free(zbx_vmware_vm_t * vm)710 static void vmware_vm_shared_free(zbx_vmware_vm_t *vm)
711 {
712 zbx_vector_ptr_clear_ext(&vm->devs, (zbx_clean_func_t)vmware_dev_shared_free);
713 zbx_vector_ptr_destroy(&vm->devs);
714
715 zbx_vector_ptr_clear_ext(&vm->file_systems, (zbx_mem_free_func_t)vmware_fs_shared_free);
716 zbx_vector_ptr_destroy(&vm->file_systems);
717
718 if (NULL != vm->uuid)
719 vmware_shared_strfree(vm->uuid);
720
721 if (NULL != vm->id)
722 vmware_shared_strfree(vm->id);
723
724 vmware_props_shared_free(vm->props, ZBX_VMWARE_VMPROPS_NUM);
725
726 __vm_mem_free_func(vm);
727 }
728
729 /******************************************************************************
730 * *
731 * Function: vmware_hv_shared_clean *
732 * *
733 * Purpose: frees shared resources allocated to store vmware hypervisor *
734 * *
735 * Parameters: hv - [IN] the vmware hypervisor *
736 * *
737 ******************************************************************************/
vmware_hv_shared_clean(zbx_vmware_hv_t * hv)738 static void vmware_hv_shared_clean(zbx_vmware_hv_t *hv)
739 {
740 zbx_vector_ptr_clear_ext(&hv->datastores, (zbx_clean_func_t)vmware_datastore_shared_free);
741 zbx_vector_ptr_destroy(&hv->datastores);
742
743 zbx_vector_ptr_clear_ext(&hv->vms, (zbx_clean_func_t)vmware_vm_shared_free);
744 zbx_vector_ptr_destroy(&hv->vms);
745
746 if (NULL != hv->uuid)
747 vmware_shared_strfree(hv->uuid);
748
749 if (NULL != hv->id)
750 vmware_shared_strfree(hv->id);
751
752 if (NULL != hv->clusterid)
753 vmware_shared_strfree(hv->clusterid);
754
755 vmware_props_shared_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
756 }
757
758 /******************************************************************************
759 * *
760 * Function: vmware_cluster_shared_free *
761 * *
762 * Purpose: frees shared resources allocated to store vmware cluster *
763 * *
764 * Parameters: cluster - [IN] the vmware cluster *
765 * *
766 ******************************************************************************/
vmware_cluster_shared_free(zbx_vmware_cluster_t * cluster)767 static void vmware_cluster_shared_free(zbx_vmware_cluster_t *cluster)
768 {
769 if (NULL != cluster->name)
770 vmware_shared_strfree(cluster->name);
771
772 if (NULL != cluster->id)
773 vmware_shared_strfree(cluster->id);
774
775 if (NULL != cluster->status)
776 vmware_shared_strfree(cluster->status);
777
778 __vm_mem_free_func(cluster);
779 }
780
781 /******************************************************************************
782 * *
783 * Function: vmware_event_shared_free *
784 * *
785 * Purpose: frees shared resources allocated to store vmware event *
786 * *
787 * Parameters: event - [IN] the vmware event *
788 * *
789 ******************************************************************************/
vmware_event_shared_free(zbx_vmware_event_t * event)790 static void vmware_event_shared_free(zbx_vmware_event_t *event)
791 {
792 if (NULL != event->message)
793 vmware_shared_strfree(event->message);
794
795 __vm_mem_free_func(event);
796 }
797
798 /******************************************************************************
799 * *
800 * Function: vmware_data_shared_free *
801 * *
802 * Purpose: frees shared resources allocated to store vmware service data *
803 * *
804 * Parameters: data - [IN] the vmware service data *
805 * *
806 ******************************************************************************/
vmware_data_shared_free(zbx_vmware_data_t * data)807 static void vmware_data_shared_free(zbx_vmware_data_t *data)
808 {
809 if (NULL != data)
810 {
811 zbx_hashset_iter_t iter;
812 zbx_vmware_hv_t *hv;
813
814 zbx_hashset_iter_reset(&data->hvs, &iter);
815 while (NULL != (hv = zbx_hashset_iter_next(&iter)))
816 vmware_hv_shared_clean(hv);
817
818 zbx_hashset_destroy(&data->hvs);
819 zbx_hashset_destroy(&data->vms_index);
820
821 zbx_vector_ptr_clear_ext(&data->clusters, (zbx_clean_func_t)vmware_cluster_shared_free);
822 zbx_vector_ptr_destroy(&data->clusters);
823
824 zbx_vector_ptr_clear_ext(&data->events, (zbx_clean_func_t)vmware_event_shared_free);
825 zbx_vector_ptr_destroy(&data->events);
826
827 if (NULL != data->error)
828 vmware_shared_strfree(data->error);
829
830 __vm_mem_free_func(data);
831 }
832 }
833
834 /******************************************************************************
835 * *
836 * Function: vmware_shared_perf_entity_clean *
837 * *
838 * Purpose: cleans resources allocated by vmware peformance entity in vmware *
839 * cache *
840 * *
841 * Parameters: entity - [IN] the entity to free *
842 * *
843 ******************************************************************************/
vmware_shared_perf_entity_clean(zbx_vmware_perf_entity_t * entity)844 static void vmware_shared_perf_entity_clean(zbx_vmware_perf_entity_t *entity)
845 {
846 zbx_vector_ptr_clear_ext(&entity->counters, (zbx_mem_free_func_t)vmware_perf_counter_shared_free);
847 zbx_vector_ptr_destroy(&entity->counters);
848
849 vmware_shared_strfree(entity->query_instance);
850 vmware_shared_strfree(entity->type);
851 vmware_shared_strfree(entity->id);
852 vmware_shared_strfree(entity->error);
853 }
854
855 /******************************************************************************
856 * *
857 * Function: vmware_counter_shared_clean *
858 * *
859 * Purpose: frees resources allocated by vmware performance counter *
860 * *
861 * Parameters: counter - [IN] the performance counter to free *
862 * *
863 ******************************************************************************/
vmware_counter_shared_clean(zbx_vmware_counter_t * counter)864 static void vmware_counter_shared_clean(zbx_vmware_counter_t *counter)
865 {
866 vmware_shared_strfree(counter->path);
867 }
868
869 /******************************************************************************
870 * *
871 * Function: vmware_service_shared_free *
872 * *
873 * Purpose: frees shared resources allocated to store vmware service *
874 * *
875 * Parameters: data - [IN] the vmware service data *
876 * *
877 ******************************************************************************/
vmware_service_shared_free(zbx_vmware_service_t * service)878 static void vmware_service_shared_free(zbx_vmware_service_t *service)
879 {
880 const char *__function_name = "vmware_service_shared_free";
881
882 zbx_hashset_iter_t iter;
883 zbx_vmware_counter_t *counter;
884 zbx_vmware_perf_entity_t *entity;
885
886 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, service->username, service->url);
887
888 vmware_shared_strfree(service->url);
889 vmware_shared_strfree(service->username);
890 vmware_shared_strfree(service->password);
891
892 if (NULL != service->contents)
893 vmware_shared_strfree(service->contents);
894
895 vmware_data_shared_free(service->data);
896
897 zbx_hashset_iter_reset(&service->entities, &iter);
898 while (NULL != (entity = zbx_hashset_iter_next(&iter)))
899 vmware_shared_perf_entity_clean(entity);
900
901 zbx_hashset_destroy(&service->entities);
902
903 zbx_hashset_iter_reset(&service->counters, &iter);
904 while (NULL != (counter = zbx_hashset_iter_next(&iter)))
905 vmware_counter_shared_clean(counter);
906
907 zbx_hashset_destroy(&service->counters);
908
909 __vm_mem_free_func(service);
910
911 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
912 }
913
914 /******************************************************************************
915 * *
916 * Function: vmware_cluster_shared_dup *
917 * *
918 * Purpose: copies vmware cluster object into shared memory *
919 * *
920 * Parameters: src - [IN] the vmware cluster object *
921 * *
922 * Return value: a copied vmware cluster object *
923 * *
924 ******************************************************************************/
vmware_cluster_shared_dup(const zbx_vmware_cluster_t * src)925 static zbx_vmware_cluster_t *vmware_cluster_shared_dup(const zbx_vmware_cluster_t *src)
926 {
927 zbx_vmware_cluster_t *cluster;
928
929 cluster = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_cluster_t));
930 cluster->id = vmware_shared_strdup(src->id);
931 cluster->name = vmware_shared_strdup(src->name);
932 cluster->status = vmware_shared_strdup(src->status);
933
934 return cluster;
935 }
936
937 /******************************************************************************
938 * *
939 * Function: vmware_event_shared_dup *
940 * *
941 * Purpose: copies vmware event object into shared memory *
942 * *
943 * Parameters: src - [IN] the vmware event object *
944 * *
945 * Return value: a copied vmware event object *
946 * *
947 ******************************************************************************/
vmware_event_shared_dup(const zbx_vmware_event_t * src)948 static zbx_vmware_event_t *vmware_event_shared_dup(const zbx_vmware_event_t *src)
949 {
950 zbx_vmware_event_t *event;
951
952 event = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_event_t));
953 event->key = src->key;
954 event->message = vmware_shared_strdup(src->message);
955 event->timestamp = src->timestamp;
956
957 return event;
958 }
959
960 /******************************************************************************
961 * *
962 * Function: vmware_datastore_shared_dup *
963 * *
964 * Purpose: copies vmware hypervisor datastore object into shared memory *
965 * *
966 * Parameters: src - [IN] the vmware datastore object *
967 * *
968 * Return value: a duplicated vmware datastore object *
969 * *
970 ******************************************************************************/
vmware_datastore_shared_dup(const zbx_vmware_datastore_t * src)971 static zbx_vmware_datastore_t *vmware_datastore_shared_dup(const zbx_vmware_datastore_t *src)
972 {
973 zbx_vmware_datastore_t *datastore;
974
975 datastore = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_datastore_t));
976 datastore->uuid = vmware_shared_strdup(src->uuid);
977 datastore->name = vmware_shared_strdup(src->name);
978 datastore->id = vmware_shared_strdup(src->id);
979
980 datastore->capacity = src->capacity;
981 datastore->free_space = src->free_space;
982 datastore->uncommitted = src->uncommitted;
983
984 return datastore;
985 }
986
987 /******************************************************************************
988 * *
989 * Function: vmware_dev_shared_dup *
990 * *
991 * Purpose: copies vmware virtual machine device object into shared memory *
992 * *
993 * Parameters: src - [IN] the vmware device object *
994 * *
995 * Return value: a duplicated vmware device object *
996 * *
997 ******************************************************************************/
vmware_dev_shared_dup(const zbx_vmware_dev_t * src)998 static zbx_vmware_dev_t *vmware_dev_shared_dup(const zbx_vmware_dev_t *src)
999 {
1000 zbx_vmware_dev_t *dev;
1001
1002 dev = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_dev_t));
1003 dev->type = src->type;
1004 dev->instance = vmware_shared_strdup(src->instance);
1005 dev->label = vmware_shared_strdup(src->label);
1006
1007 return dev;
1008 }
1009
1010 /******************************************************************************
1011 * *
1012 * Function: vmware_fs_shared_dup *
1013 * *
1014 * Purpose: copies vmware virtual machine file system object into shared *
1015 * memory *
1016 * *
1017 * Parameters: src - [IN] the vmware device object *
1018 * *
1019 * Return value: a duplicated vmware device object *
1020 * *
1021 ******************************************************************************/
vmware_fs_shared_dup(const zbx_vmware_fs_t * src)1022 static zbx_vmware_fs_t *vmware_fs_shared_dup(const zbx_vmware_fs_t *src)
1023 {
1024 zbx_vmware_fs_t *fs;
1025
1026 fs = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_fs_t));
1027 fs->path = vmware_shared_strdup(src->path);
1028 fs->capacity = src->capacity;
1029 fs->free_space = src->free_space;
1030
1031 return fs;
1032 }
1033
1034 /******************************************************************************
1035 * *
1036 * Function: vmware_props_shared_dup *
1037 * *
1038 * Purpose: copies object properties list into shared memory *
1039 * *
1040 * Parameters: src - [IN] the properties list *
1041 * props_num - [IN] the number of properties in the list *
1042 * *
1043 * Return value: a duplicated object properties list *
1044 * *
1045 ******************************************************************************/
vmware_props_shared_dup(char ** const src,int props_num)1046 static char **vmware_props_shared_dup(char ** const src, int props_num)
1047 {
1048 char **props;
1049 int i;
1050
1051 props = __vm_mem_malloc_func(NULL, sizeof(char *) * props_num);
1052
1053 for (i = 0; i < props_num; i++)
1054 props[i] = vmware_shared_strdup(src[i]);
1055
1056 return props;
1057 }
1058
1059 /******************************************************************************
1060 * *
1061 * Function: vmware_vm_shared_dup *
1062 * *
1063 * Purpose: copies vmware virtual machine object into shared memory *
1064 * *
1065 * Parameters: src - [IN] the vmware virtual machine object *
1066 * *
1067 * Return value: a duplicated vmware virtual machine object *
1068 * *
1069 ******************************************************************************/
vmware_vm_shared_dup(const zbx_vmware_vm_t * src)1070 static zbx_vmware_vm_t *vmware_vm_shared_dup(const zbx_vmware_vm_t *src)
1071 {
1072 zbx_vmware_vm_t *vm;
1073 int i;
1074
1075 vm = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_vm_t));
1076
1077 VMWARE_VECTOR_CREATE(&vm->devs, ptr);
1078 VMWARE_VECTOR_CREATE(&vm->file_systems, ptr);
1079
1080 vm->uuid = vmware_shared_strdup(src->uuid);
1081 vm->id = vmware_shared_strdup(src->id);
1082 vm->props = vmware_props_shared_dup(src->props, ZBX_VMWARE_VMPROPS_NUM);
1083
1084 for (i = 0; i < src->devs.values_num; i++)
1085 zbx_vector_ptr_append(&vm->devs, vmware_dev_shared_dup(src->devs.values[i]));
1086
1087 for (i = 0; i < src->file_systems.values_num; i++)
1088 zbx_vector_ptr_append(&vm->file_systems, vmware_fs_shared_dup(src->file_systems.values[i]));
1089
1090 return vm;
1091 }
1092
1093 /******************************************************************************
1094 * *
1095 * Function: vmware_hv_shared_copy *
1096 * *
1097 * Purpose: copies vmware hypervisor object into shared memory *
1098 * *
1099 * Parameters: src - [IN] the vmware hypervisor object *
1100 * *
1101 * Return value: a duplicated vmware hypervisor object *
1102 * *
1103 ******************************************************************************/
vmware_hv_shared_copy(zbx_vmware_hv_t * dst,const zbx_vmware_hv_t * src)1104 static void vmware_hv_shared_copy(zbx_vmware_hv_t *dst, const zbx_vmware_hv_t *src)
1105 {
1106 int i;
1107
1108 VMWARE_VECTOR_CREATE(&dst->datastores, ptr);
1109 VMWARE_VECTOR_CREATE(&dst->vms, ptr);
1110
1111 dst->uuid = vmware_shared_strdup(src->uuid);
1112 dst->id = vmware_shared_strdup(src->id);
1113 dst->clusterid = vmware_shared_strdup(src->clusterid);
1114
1115 dst->props = vmware_props_shared_dup(src->props, ZBX_VMWARE_HVPROPS_NUM);
1116
1117 for (i = 0; i < src->datastores.values_num; i++)
1118 zbx_vector_ptr_append(&dst->datastores, vmware_datastore_shared_dup(src->datastores.values[i]));
1119
1120 for (i = 0; i < src->vms.values_num; i++)
1121 zbx_vector_ptr_append(&dst->vms, vmware_vm_shared_dup(src->vms.values[i]));
1122 }
1123
1124 /******************************************************************************
1125 * *
1126 * Function: vmware_data_shared_dup *
1127 * *
1128 * Purpose: copies vmware data object into shared memory *
1129 * *
1130 * Parameters: src - [IN] the vmware data object *
1131 * *
1132 * Return value: a duplicated vmware data object *
1133 * *
1134 ******************************************************************************/
vmware_data_shared_dup(zbx_vmware_data_t * src)1135 static zbx_vmware_data_t *vmware_data_shared_dup(zbx_vmware_data_t *src)
1136 {
1137 zbx_vmware_data_t *data;
1138 int i;
1139 zbx_hashset_iter_t iter;
1140 zbx_vmware_hv_t *hv, hv_local;
1141
1142 data = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_data_t));
1143
1144 zbx_hashset_create_ext(&data->hvs, 1, vmware_hv_hash, vmware_hv_compare, NULL, __vm_mem_malloc_func,
1145 __vm_mem_realloc_func, __vm_mem_free_func);
1146 VMWARE_VECTOR_CREATE(&data->clusters, ptr);
1147 VMWARE_VECTOR_CREATE(&data->events, ptr);
1148
1149 zbx_hashset_create_ext(&data->vms_index, 100, vmware_vm_hash, vmware_vm_compare, NULL, __vm_mem_malloc_func,
1150 __vm_mem_realloc_func, __vm_mem_free_func);
1151
1152 data->error = vmware_shared_strdup(src->error);
1153
1154 for (i = 0; i < src->clusters.values_num; i++)
1155 zbx_vector_ptr_append(&data->clusters, vmware_cluster_shared_dup(src->clusters.values[i]));
1156
1157 for (i = 0; i < src->events.values_num; i++)
1158 zbx_vector_ptr_append(&data->events, vmware_event_shared_dup(src->events.values[i]));
1159
1160 zbx_hashset_iter_reset(&src->hvs, &iter);
1161 while (NULL != (hv = zbx_hashset_iter_next(&iter)))
1162 {
1163
1164 vmware_hv_shared_copy(&hv_local, hv);
1165 hv = zbx_hashset_insert(&data->hvs, &hv_local, sizeof(hv_local));
1166
1167 for (i = 0; i < hv->vms.values_num; i++)
1168 {
1169 zbx_vmware_vm_index_t vmi_local = {(zbx_vmware_vm_t *)hv->vms.values[i], hv};
1170
1171 zbx_hashset_insert(&data->vms_index, &vmi_local, sizeof(vmi_local));
1172 }
1173 }
1174
1175 data->max_query_metrics = src->max_query_metrics;
1176
1177 return data;
1178 }
1179
1180 /******************************************************************************
1181 * *
1182 * Function: vmware_datastore_free *
1183 * *
1184 * Purpose: frees resources allocated to store datastore data *
1185 * *
1186 * Parameters: datastore - [IN] the datastore *
1187 * *
1188 ******************************************************************************/
vmware_datastore_free(zbx_vmware_datastore_t * datastore)1189 static void vmware_datastore_free(zbx_vmware_datastore_t *datastore)
1190 {
1191 zbx_free(datastore->name);
1192 zbx_free(datastore->uuid);
1193 zbx_free(datastore->id);
1194 zbx_free(datastore);
1195 }
1196
1197 /******************************************************************************
1198 * *
1199 * Function: vmware_props_free *
1200 * *
1201 * Purpose: frees shared resources allocated to store properties list *
1202 * *
1203 * Parameters: props - [IN] the properties list *
1204 * props_num - [IN] the number of properties in the list *
1205 * *
1206 ******************************************************************************/
vmware_props_free(char ** props,int props_num)1207 static void vmware_props_free(char **props, int props_num)
1208 {
1209 int i;
1210
1211 if (NULL == props)
1212 return;
1213
1214 for (i = 0; i < props_num; i++)
1215 zbx_free(props[i]);
1216
1217 zbx_free(props);
1218 }
1219
1220 /******************************************************************************
1221 * *
1222 * Function: vmware_dev_free *
1223 * *
1224 * Purpose: frees resources allocated to store vm device object *
1225 * *
1226 * Parameters: dev - [IN] the vm device *
1227 * *
1228 ******************************************************************************/
vmware_dev_free(zbx_vmware_dev_t * dev)1229 static void vmware_dev_free(zbx_vmware_dev_t *dev)
1230 {
1231 zbx_free(dev->instance);
1232 zbx_free(dev->label);
1233 zbx_free(dev);
1234 }
1235
1236 /******************************************************************************
1237 * *
1238 * Function: vmware_fs_free *
1239 * *
1240 * Purpose: frees resources allocated to store vm file system object *
1241 * *
1242 * Parameters: fs - [IN] the file system *
1243 * *
1244 ******************************************************************************/
vmware_fs_free(zbx_vmware_fs_t * fs)1245 static void vmware_fs_free(zbx_vmware_fs_t *fs)
1246 {
1247 zbx_free(fs->path);
1248 zbx_free(fs);
1249 }
1250
1251 /******************************************************************************
1252 * *
1253 * Function: vmware_vm_free *
1254 * *
1255 * Purpose: frees resources allocated to store virtual machine *
1256 * *
1257 * Parameters: vm - [IN] the virtual machine *
1258 * *
1259 ******************************************************************************/
vmware_vm_free(zbx_vmware_vm_t * vm)1260 static void vmware_vm_free(zbx_vmware_vm_t *vm)
1261 {
1262 zbx_vector_ptr_clear_ext(&vm->devs, (zbx_clean_func_t)vmware_dev_free);
1263 zbx_vector_ptr_destroy(&vm->devs);
1264
1265 zbx_vector_ptr_clear_ext(&vm->file_systems, (zbx_mem_free_func_t)vmware_fs_free);
1266 zbx_vector_ptr_destroy(&vm->file_systems);
1267
1268 zbx_free(vm->uuid);
1269 zbx_free(vm->id);
1270 vmware_props_free(vm->props, ZBX_VMWARE_VMPROPS_NUM);
1271 zbx_free(vm);
1272 }
1273
1274 /******************************************************************************
1275 * *
1276 * Function: vmware_hv_clean *
1277 * *
1278 * Purpose: frees resources allocated to store vmware hypervisor *
1279 * *
1280 * Parameters: hv - [IN] the vmware hypervisor *
1281 * *
1282 ******************************************************************************/
vmware_hv_clean(zbx_vmware_hv_t * hv)1283 static void vmware_hv_clean(zbx_vmware_hv_t *hv)
1284 {
1285 zbx_vector_ptr_clear_ext(&hv->datastores, (zbx_clean_func_t)vmware_datastore_free);
1286 zbx_vector_ptr_destroy(&hv->datastores);
1287
1288 zbx_vector_ptr_clear_ext(&hv->vms, (zbx_clean_func_t)vmware_vm_free);
1289 zbx_vector_ptr_destroy(&hv->vms);
1290
1291 zbx_free(hv->uuid);
1292 zbx_free(hv->id);
1293 zbx_free(hv->clusterid);
1294
1295 vmware_props_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
1296 }
1297
1298 /******************************************************************************
1299 * *
1300 * Function: vmware_cluster_free *
1301 * *
1302 * Purpose: frees resources allocated to store vmware cluster *
1303 * *
1304 * Parameters: cluster - [IN] the vmware cluster *
1305 * *
1306 ******************************************************************************/
vmware_cluster_free(zbx_vmware_cluster_t * cluster)1307 static void vmware_cluster_free(zbx_vmware_cluster_t *cluster)
1308 {
1309 zbx_free(cluster->name);
1310 zbx_free(cluster->id);
1311 zbx_free(cluster->status);
1312 zbx_free(cluster);
1313 }
1314
1315 /******************************************************************************
1316 * *
1317 * Function: vmware_event_free *
1318 * *
1319 * Purpose: frees resources allocated to store vmware event *
1320 * *
1321 * Parameters: event - [IN] the vmware event *
1322 * *
1323 ******************************************************************************/
vmware_event_free(zbx_vmware_event_t * event)1324 static void vmware_event_free(zbx_vmware_event_t *event)
1325 {
1326 zbx_free(event->message);
1327 zbx_free(event);
1328 }
1329
1330 /******************************************************************************
1331 * *
1332 * Function: vmware_data_free *
1333 * *
1334 * Purpose: frees resources allocated to store vmware service data *
1335 * *
1336 * Parameters: data - [IN] the vmware service data *
1337 * *
1338 ******************************************************************************/
vmware_data_free(zbx_vmware_data_t * data)1339 static void vmware_data_free(zbx_vmware_data_t *data)
1340 {
1341 zbx_hashset_iter_t iter;
1342 zbx_vmware_hv_t *hv;
1343
1344 zbx_hashset_iter_reset(&data->hvs, &iter);
1345 while (NULL != (hv = zbx_hashset_iter_next(&iter)))
1346 vmware_hv_clean(hv);
1347
1348 zbx_hashset_destroy(&data->hvs);
1349
1350 zbx_vector_ptr_clear_ext(&data->clusters, (zbx_clean_func_t)vmware_cluster_free);
1351 zbx_vector_ptr_destroy(&data->clusters);
1352
1353 zbx_vector_ptr_clear_ext(&data->events, (zbx_clean_func_t)vmware_event_free);
1354 zbx_vector_ptr_destroy(&data->events);
1355
1356 zbx_free(data->error);
1357 zbx_free(data);
1358 }
1359
1360 /******************************************************************************
1361 * *
1362 * Function: vmware_counter_free *
1363 * *
1364 * Purpose: frees vmware performance counter and the resources allocated by *
1365 * it *
1366 * *
1367 * Parameters: counter - [IN] the performance counter to free *
1368 * *
1369 ******************************************************************************/
vmware_counter_free(zbx_vmware_counter_t * counter)1370 static void vmware_counter_free(zbx_vmware_counter_t *counter)
1371 {
1372 zbx_free(counter->path);
1373 zbx_free(counter);
1374 }
1375
1376 /******************************************************************************
1377 * *
1378 * Function: vmware_service_authenticate *
1379 * *
1380 * Purpose: authenticates vmware service *
1381 * *
1382 * Parameters: service - [IN] the vmware service *
1383 * easyhandle - [IN] the CURL handle *
1384 * error - [OUT] the error message in the case of failure *
1385 * *
1386 * Return value: SUCCEED - the authentication was completed successfully *
1387 * FAIL - the authentication process has failed *
1388 * *
1389 * Comments: If service type is unknown this function will attempt to *
1390 * determine the right service type by trying to login with vCenter *
1391 * and vSphere session managers. *
1392 * *
1393 ******************************************************************************/
vmware_service_authenticate(zbx_vmware_service_t * service,CURL * easyhandle,char ** error)1394 static int vmware_service_authenticate(zbx_vmware_service_t *service, CURL *easyhandle, char **error)
1395 {
1396 # define ZBX_POST_VMWARE_AUTH \
1397 ZBX_POST_VSPHERE_HEADER \
1398 "<ns0:Login xsi:type=\"ns0:LoginRequestType\">" \
1399 "<ns0:_this type=\"SessionManager\">%s</ns0:_this>" \
1400 "<ns0:userName>%s</ns0:userName>" \
1401 "<ns0:password>%s</ns0:password>" \
1402 "</ns0:Login>" \
1403 ZBX_POST_VSPHERE_FOOTER
1404
1405 const char *__function_name = "vmware_service_authenticate";
1406 char xml[MAX_STRING_LEN], *error_object = NULL, *username_esc = NULL, *password_esc = NULL;
1407 int err, opt, ret = FAIL;
1408
1409 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, service->username, service->url);
1410
1411 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_COOKIEFILE, "")) ||
1412 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_FOLLOWLOCATION, 1L)) ||
1413 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_WRITEFUNCTION, curl_write_cb)) ||
1414 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HEADERFUNCTION, curl_header_cb)) ||
1415 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYPEER, 0L)) ||
1416 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POST, 1L)) ||
1417 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_URL, service->url)) ||
1418 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_TIMEOUT,
1419 (long)CONFIG_VMWARE_TIMEOUT)) ||
1420 CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYHOST, 0L)))
1421 {
1422 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1423 goto out;
1424 }
1425
1426 if (NULL != CONFIG_SOURCE_IP)
1427 {
1428 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_INTERFACE, CONFIG_SOURCE_IP)))
1429 {
1430 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1431 goto out;
1432 }
1433 }
1434
1435 username_esc = xml_escape_dyn(service->username);
1436 password_esc = xml_escape_dyn(service->password);
1437
1438 if (ZBX_VMWARE_TYPE_UNKNOWN == service->type)
1439 {
1440 char *xml_value = NULL;
1441
1442 /* try to detect the service type first using vCenter service manager object */
1443 zbx_snprintf(xml, sizeof(xml), ZBX_POST_VMWARE_AUTH,
1444 vmware_service_objects[ZBX_VMWARE_TYPE_VCENTER].session_manager,
1445 username_esc, password_esc);
1446
1447 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, xml)))
1448 {
1449 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1450 goto out;
1451 }
1452
1453 page.offset = 0;
1454
1455 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1456 {
1457 *error = zbx_strdup(*error, curl_easy_strerror(err));
1458 goto out;
1459 }
1460
1461 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1462
1463 if (FAIL == zbx_xml_try_read_value(page.data, ZBX_XPATH_FAULTSTRING(), &xml_value, error))
1464 goto out;
1465
1466 if (NULL == xml_value)
1467 {
1468 /* Successfully authenticated with vcenter service manager. */
1469 /* Set the service type and return with success. */
1470 service->type = ZBX_VMWARE_TYPE_VCENTER;
1471 ret = SUCCEED;
1472 goto out;
1473 }
1474
1475 *error = zbx_strdup(*error, xml_value);
1476 zbx_free(xml_value);
1477
1478 /* If the wrong service manager was used, set the service type as vsphere and */
1479 /* try again with vsphere service manager. Otherwise return with failure. */
1480 if (NULL == (error_object = zbx_xml_read_value(page.data,
1481 ZBX_XPATH_LN3("detail", "NotAuthenticatedFault", "object"))))
1482 {
1483 goto out;
1484 }
1485
1486 if (0 != strcmp(error_object, vmware_service_objects[ZBX_VMWARE_TYPE_VCENTER].session_manager))
1487 goto out;
1488
1489 service->type = ZBX_VMWARE_TYPE_VSPHERE;
1490 zbx_free(*error);
1491 }
1492
1493 zbx_snprintf(xml, sizeof(xml), ZBX_POST_VMWARE_AUTH, vmware_service_objects[service->type].session_manager,
1494 username_esc, password_esc);
1495
1496 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, xml)))
1497 {
1498 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1499 goto out;
1500 }
1501
1502 page.offset = 0;
1503
1504 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1505 {
1506 *error = zbx_strdup(*error, curl_easy_strerror(err));
1507 goto out;
1508 }
1509
1510 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1511
1512 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1513 goto out;
1514
1515 ret = SUCCEED;
1516 out:
1517 zbx_free(error_object);
1518 zbx_free(username_esc);
1519 zbx_free(password_esc);
1520
1521 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1522
1523 return ret;
1524 }
1525
1526 /******************************************************************************
1527 * *
1528 * Function: vmware_service_logout *
1529 * *
1530 * Purpose: Close unused connection with vCenter *
1531 * *
1532 * Parameters: service - [IN] the vmware service *
1533 * easyhandle - [IN] the CURL handle *
1534 * error - [OUT] the error message in the case of failure *
1535 * *
1536 ******************************************************************************/
vmware_service_logout(zbx_vmware_service_t * service,CURL * easyhandle,char ** error)1537 static int vmware_service_logout(zbx_vmware_service_t *service, CURL *easyhandle, char **error)
1538 {
1539 # define ZBX_POST_VMWARE_LOGOUT \
1540 ZBX_POST_VSPHERE_HEADER \
1541 "<ns0:Logout>" \
1542 "<ns0:_this type=\"SessionManager\">%s</ns0:_this>" \
1543 "</ns0:Logout>" \
1544 ZBX_POST_VSPHERE_FOOTER
1545
1546 const char *__function_name = "vmware_service_logout";
1547 char tmp[MAX_STRING_LEN];
1548 int opt, err;
1549
1550 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_LOGOUT, vmware_service_objects[service->type].session_manager);
1551 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
1552 {
1553 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1554 return FAIL;
1555 }
1556
1557 page.offset = 0;
1558
1559 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1560 {
1561 *error = zbx_strdup(*error, curl_easy_strerror(err));
1562 return FAIL;
1563 }
1564
1565 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1566
1567 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1568 return FAIL;
1569
1570 return SUCCEED;
1571 }
1572
1573 typedef struct
1574 {
1575 const char *property_collector;
1576 CURL *easyhandle;
1577 char *error;
1578 char *token;
1579 }
1580 zbx_property_collection_iter;
1581
zbx_property_collection_init(CURL * easyhandle,const char * property_collection_query,const char * property_collector)1582 static zbx_property_collection_iter *zbx_property_collection_init(CURL *easyhandle,
1583 const char *property_collection_query, const char *property_collector)
1584 {
1585 # define ZBX_XPATH_RETRIEVE_PROPERTIES_TOKEN \
1586 "/*[local-name()='Envelope']/*[local-name()='Body']" \
1587 "/*[local-name()='RetrievePropertiesExResponse']" \
1588 "/*[local-name()='returnval']/*[local-name()='token']"
1589
1590 zbx_property_collection_iter *iter = NULL;
1591 int err, opt;
1592
1593 iter = zbx_malloc(iter, sizeof(zbx_property_collection_iter));
1594 iter->property_collector = property_collector;
1595 iter->easyhandle = easyhandle;
1596 iter->error = NULL;
1597 iter->token = NULL;
1598
1599 if (CURLE_OK == (err = curl_easy_setopt(iter->easyhandle, opt = CURLOPT_POSTFIELDS, property_collection_query)))
1600 {
1601 page.offset = 0;
1602
1603 if (CURLE_OK == (err = curl_easy_perform(iter->easyhandle)))
1604 {
1605 if (NULL == (iter->error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1606 iter->token = zbx_xml_read_value(page.data, ZBX_XPATH_RETRIEVE_PROPERTIES_TOKEN);
1607 }
1608 else
1609 iter->error = zbx_strdup(iter->error, curl_easy_strerror(err));
1610 }
1611 else
1612 iter->error = zbx_dsprintf(iter->error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1613
1614 return iter;
1615 }
1616
zbx_property_collection_chunk(zbx_property_collection_iter * iter,char ** error)1617 static const char *zbx_property_collection_chunk(zbx_property_collection_iter *iter, char **error)
1618 {
1619 const char *__function_name = "zbx_property_collection_chunk";
1620
1621 if (NULL == iter->error)
1622 {
1623 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1624 return (const char *)page.data;
1625 }
1626
1627 zbx_free(*error);
1628 *error = iter->error;
1629 iter->error = NULL;
1630 return NULL;
1631 }
1632
zbx_property_collection_next(zbx_property_collection_iter * iter)1633 static int zbx_property_collection_next(zbx_property_collection_iter *iter)
1634 {
1635 # define ZBX_POST_CONTINUE_RETRIEVE_PROPERTIES \
1636 ZBX_POST_VSPHERE_HEADER \
1637 "<ns0:ContinueRetrievePropertiesEx xsi:type=\"ns0:ContinueRetrievePropertiesExRequestType\">" \
1638 "<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>" \
1639 "<ns0:token>%s</ns0:token>" \
1640 "</ns0:ContinueRetrievePropertiesEx>" \
1641 ZBX_POST_VSPHERE_FOOTER
1642
1643 # define ZBX_XPATH_CONTINUE_RETRIEVE_PROPERTIES_TOKEN \
1644 "/*[local-name()='Envelope']/*[local-name()='Body']" \
1645 "/*[local-name()='ContinueRetrievePropertiesExResponse']" \
1646 "/*[local-name()='returnval']/*[local-name()='token']"
1647
1648 const char *__function_name = "zbx_property_collection_next";
1649 char *token_esc, post[MAX_STRING_LEN];
1650 int err, opt;
1651
1652 if (NULL == iter->token)
1653 return FAIL;
1654
1655 zabbix_log(LOG_LEVEL_DEBUG, "%s() continue retrieving properties with token: '%s'", __function_name,
1656 iter->token);
1657
1658 token_esc = xml_escape_dyn(iter->token);
1659 zbx_snprintf(post, sizeof(post), ZBX_POST_CONTINUE_RETRIEVE_PROPERTIES, iter->property_collector, token_esc);
1660 zbx_free(token_esc);
1661
1662 if (CURLE_OK == (err = curl_easy_setopt(iter->easyhandle, opt = CURLOPT_POSTFIELDS, post)))
1663 {
1664 page.offset = 0;
1665
1666 if (CURLE_OK == (err = curl_easy_perform(iter->easyhandle)))
1667 {
1668 zbx_free(iter->error);
1669
1670 if (NULL == (iter->error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1671 {
1672 zbx_free(iter->token);
1673 iter->token = zbx_xml_read_value(page.data, ZBX_XPATH_CONTINUE_RETRIEVE_PROPERTIES_TOKEN);
1674 }
1675 }
1676 else
1677 iter->error = zbx_strdup(iter->error, curl_easy_strerror(err));
1678 }
1679 else
1680 iter->error = zbx_dsprintf(iter->error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1681
1682 return SUCCEED;
1683 }
1684
zbx_property_collection_free(zbx_property_collection_iter * iter)1685 static void zbx_property_collection_free(zbx_property_collection_iter *iter)
1686 {
1687 zbx_free(iter->error);
1688 zbx_free(iter->token);
1689 zbx_free(iter);
1690 }
1691
1692 /******************************************************************************
1693 * *
1694 * Function: vmware_service_get_contents *
1695 * *
1696 * Purpose: retrieves vmware service instance contents *
1697 * *
1698 * Parameters: service - [IN] the vmware service *
1699 * easyhandle - [IN] the CURL handle *
1700 * error - [OUT] the error message in the case of failure *
1701 * *
1702 * Return value: SUCCEED - the contents were retrieved successfully *
1703 * FAIL - the content retrieval faield *
1704 * *
1705 ******************************************************************************/
vmware_service_get_contents(zbx_vmware_service_t * service,CURL * easyhandle,char ** contents,char ** error)1706 static int vmware_service_get_contents(zbx_vmware_service_t *service, CURL *easyhandle, char **contents,
1707 char **error)
1708 {
1709 # define ZBX_POST_VMWARE_CONTENTS \
1710 ZBX_POST_VSPHERE_HEADER \
1711 "<ns0:RetrieveServiceContent>" \
1712 "<ns0:_this type=\"ServiceInstance\">ServiceInstance</ns0:_this>" \
1713 "</ns0:RetrieveServiceContent>" \
1714 ZBX_POST_VSPHERE_FOOTER
1715
1716 const char *__function_name = "vmware_service_get_contents";
1717
1718 int err, opt, ret = FAIL;
1719
1720 ZBX_UNUSED(service);
1721
1722 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, ZBX_POST_VMWARE_CONTENTS)))
1723 {
1724 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1725 goto out;
1726 }
1727
1728 page.offset = 0;
1729
1730 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1731 {
1732 *error = zbx_strdup(*error, curl_easy_strerror(err));
1733 goto out;
1734 }
1735
1736 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1737
1738 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1739 goto out;
1740
1741 *contents = zbx_strdup(*contents, page.data);
1742
1743 ret = SUCCEED;
1744 out:
1745 return ret;
1746 }
1747
1748 /******************************************************************************
1749 * *
1750 * Function: vmware_service_get_perf_counter_refreshrate *
1751 * *
1752 * Purpose: get the performance counter refreshrate for the specified entity *
1753 * *
1754 * Parameters: service - [IN] the vmware service *
1755 * easyhandle - [IN] the CURL handle *
1756 * type - [IN] the entity type (HostSystem, Datastore or *
1757 * VirtualMachine) *
1758 * id - [IN] the entity id *
1759 * refresh_rate - [OUT] a pointer to variable to store the *
1760 * regresh rate *
1761 * error - [OUT] the error message in the case of failure *
1762 * *
1763 * Return value: SUCCEED - the authentication was completed successfully *
1764 * FAIL - the authentication process has failed *
1765 * *
1766 ******************************************************************************/
vmware_service_get_perf_counter_refreshrate(zbx_vmware_service_t * service,CURL * easyhandle,const char * type,const char * id,int * refresh_rate,char ** error)1767 static int vmware_service_get_perf_counter_refreshrate(zbx_vmware_service_t *service, CURL *easyhandle,
1768 const char *type, const char *id, int *refresh_rate, char **error)
1769 {
1770 # define ZBX_POST_VCENTER_PERF_COUNTERS_REFRESH_RATE \
1771 ZBX_POST_VSPHERE_HEADER \
1772 "<ns0:QueryPerfProviderSummary>" \
1773 "<ns0:_this type=\"PerformanceManager\">%s</ns0:_this>" \
1774 "<ns0:entity type=\"%s\">%s</ns0:entity>" \
1775 "</ns0:QueryPerfProviderSummary>" \
1776 ZBX_POST_VSPHERE_FOOTER
1777
1778 const char *__function_name = "vmware_service_get_perf_counter_refreshrate";
1779
1780 char tmp[MAX_STRING_LEN], *value = NULL, *id_esc;
1781 int err, opt, ret = FAIL;
1782
1783 zabbix_log(LOG_LEVEL_DEBUG, "In %s() type: %s id: %s", __function_name, type, id);
1784
1785 id_esc = xml_escape_dyn(id);
1786
1787 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VCENTER_PERF_COUNTERS_REFRESH_RATE,
1788 vmware_service_objects[service->type].performance_manager, type, id_esc);
1789
1790 zbx_free(id_esc);
1791
1792 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
1793 {
1794 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
1795 goto out;
1796 }
1797
1798 page.offset = 0;
1799
1800 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1801 {
1802 *error = zbx_strdup(*error, curl_easy_strerror(err));
1803 goto out;
1804 }
1805
1806 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
1807
1808 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1809 goto out;
1810
1811 if (NULL != (value = zbx_xml_read_value(page.data, ZBX_XPATH_ISAGGREGATE())))
1812 {
1813 zbx_free(value);
1814 *refresh_rate = ZBX_VMWARE_PERF_INTERVAL_NONE;
1815 ret = SUCCEED;
1816
1817 zabbix_log(LOG_LEVEL_DEBUG, "%s() refresh_rate: unused", __function_name);
1818 goto out;
1819 }
1820 else if (NULL == (value = zbx_xml_read_value(page.data, ZBX_XPATH_REFRESHRATE())))
1821 {
1822 *error = zbx_strdup(*error, "Cannot find refreshRate.");
1823 goto out;
1824 }
1825
1826 zabbix_log(LOG_LEVEL_DEBUG, "%s() refresh_rate:%s", __function_name, value);
1827
1828 if (SUCCEED != (ret = is_uint31(value, refresh_rate)))
1829 *error = zbx_dsprintf(*error, "Cannot convert refreshRate from %s.", value);
1830
1831 zbx_free(value);
1832 out:
1833 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1834
1835 return ret;
1836 }
1837
1838 /******************************************************************************
1839 * *
1840 * Function: vmware_service_get_perf_counters *
1841 * *
1842 * Purpose: get the performance counter ids *
1843 * *
1844 * Parameters: service - [IN] the vmware service *
1845 * easyhandle - [IN] the CURL handle *
1846 * error - [OUT] the error message in the case of failure *
1847 * *
1848 * Return value: SUCCEED - the operation has completed successfully *
1849 * FAIL - the operation has failed *
1850 * *
1851 ******************************************************************************/
vmware_service_get_perf_counters(zbx_vmware_service_t * service,CURL * easyhandle,zbx_vector_ptr_t * counters,char ** error)1852 static int vmware_service_get_perf_counters(zbx_vmware_service_t *service, CURL *easyhandle,
1853 zbx_vector_ptr_t *counters, char **error)
1854 {
1855 # define ZBX_POST_VMWARE_GET_PERFCOUNTER \
1856 ZBX_POST_VSPHERE_HEADER \
1857 "<ns0:RetrieveProperties>" \
1858 "<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>" \
1859 "<ns0:specSet>" \
1860 "<ns0:propSet>" \
1861 "<ns0:type>PerformanceManager</ns0:type>" \
1862 "<ns0:pathSet>perfCounter</ns0:pathSet>" \
1863 "</ns0:propSet>" \
1864 "<ns0:objectSet>" \
1865 "<ns0:obj type=\"PerformanceManager\">%s</ns0:obj>" \
1866 "</ns0:objectSet>" \
1867 "</ns0:specSet>" \
1868 "</ns0:RetrieveProperties>" \
1869 ZBX_POST_VSPHERE_FOOTER
1870
1871 const char *__function_name = "vmware_service_get_perf_counters";
1872 char tmp[MAX_STRING_LEN], *group = NULL, *key = NULL, *rollup = NULL,
1873 *counterid = NULL;
1874 xmlDoc *doc;
1875 xmlXPathContext *xpathCtx;
1876 xmlXPathObject *xpathObj;
1877 xmlNodeSetPtr nodeset;
1878 int opts, err, i, ret = FAIL;
1879
1880 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1881
1882 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_GET_PERFCOUNTER,
1883 vmware_service_objects[service->type].property_collector,
1884 vmware_service_objects[service->type].performance_manager);
1885
1886 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opts = CURLOPT_POSTFIELDS, tmp)))
1887 {
1888 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opts, curl_easy_strerror(err));
1889 goto out;
1890 }
1891
1892 page.offset = 0;
1893
1894 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
1895 {
1896 *error = zbx_strdup(*error, curl_easy_strerror(err));
1897 goto out;
1898 }
1899
1900 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
1901 goto out;
1902
1903 if (NULL == (doc = xmlReadMemory(page.data, page.offset, ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
1904 {
1905 *error = zbx_strdup(*error, "Cannot parse performance counter list.");
1906 goto out;
1907 }
1908
1909 xpathCtx = xmlXPathNewContext(doc);
1910
1911 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)ZBX_XPATH_COUNTERINFO(), xpathCtx)))
1912 {
1913 *error = zbx_strdup(*error, "Cannot make performance counter list parsing query.");
1914 goto clean;
1915 }
1916
1917 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
1918 {
1919 *error = zbx_strdup(*error, "Cannot find items in performance counter list.");
1920 goto clean;
1921 }
1922
1923 nodeset = xpathObj->nodesetval;
1924
1925 for (i = 0; i < nodeset->nodeNr; i++)
1926 {
1927 zbx_vmware_counter_t *counter;
1928
1929 group = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
1930 "*[local-name()='groupInfo']/*[local-name()='key']");
1931
1932 key = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
1933 "*[local-name()='nameInfo']/*[local-name()='key']");
1934
1935 rollup = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='rollupType']");
1936 counterid = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='key']");
1937
1938 if (NULL != group && NULL != key && NULL != rollup && NULL != counterid)
1939 {
1940 counter = zbx_malloc(NULL, sizeof(zbx_vmware_counter_t));
1941 counter->path = zbx_dsprintf(NULL, "%s/%s[%s]", group, key, rollup);
1942 ZBX_STR2UINT64(counter->id, counterid);
1943
1944 zbx_vector_ptr_append(counters, counter);
1945
1946 zabbix_log(LOG_LEVEL_DEBUG, "adding performance counter %s:" ZBX_FS_UI64, counter->path,
1947 counter->id);
1948 }
1949
1950 zbx_free(counterid);
1951 zbx_free(rollup);
1952 zbx_free(key);
1953 zbx_free(group);
1954 }
1955
1956 /* The counter data uses a lot of memory which is needed only once during initialization. */
1957 /* Reset the download buffer afterwards so the memory is not wasted. */
1958 zbx_free(page.data);
1959 page.alloc = 0;
1960 page.offset = 0;
1961
1962 ret = SUCCEED;
1963 clean:
1964 if (NULL != xpathObj)
1965 xmlXPathFreeObject(xpathObj);
1966
1967 xmlXPathFreeContext(xpathCtx);
1968 xmlFreeDoc(doc);
1969 out:
1970 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1971
1972 return ret;
1973 }
1974
1975 /******************************************************************************
1976 * *
1977 * Function: vmware_vm_get_nic_devices *
1978 * *
1979 * Purpose: gets virtual machine network interface devices *
1980 * *
1981 * Parameters: vm - [OUT] the virtual machine *
1982 * details - [IN] a xml string containing virtual machine data *
1983 * *
1984 * Comments: The network interface devices are taken from vm device list *
1985 * filtered by macAddress key. *
1986 * *
1987 ******************************************************************************/
vmware_vm_get_nic_devices(zbx_vmware_vm_t * vm,const char * details)1988 static void vmware_vm_get_nic_devices(zbx_vmware_vm_t *vm, const char *details)
1989 {
1990 const char *__function_name = "vmware_vm_get_nic_devices";
1991
1992 xmlDoc *doc;
1993 xmlXPathContext *xpathCtx;
1994 xmlXPathObject *xpathObj;
1995 xmlNodeSetPtr nodeset;
1996 int i, nics = 0;
1997
1998 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1999
2000 if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
2001 goto out;
2002
2003 xpathCtx = xmlXPathNewContext(doc);
2004
2005 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)ZBX_XPATH_VM_HARDWARE("device")
2006 "[*[local-name()='macAddress']]", xpathCtx)))
2007 {
2008 goto clean;
2009 }
2010
2011 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
2012 goto clean;
2013
2014 nodeset = xpathObj->nodesetval;
2015
2016 for (i = 0; i < nodeset->nodeNr; i++)
2017 {
2018 char *key;
2019 zbx_vmware_dev_t *dev;
2020
2021 if (NULL == (key = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='key']")))
2022 continue;
2023
2024 dev = zbx_malloc(NULL, sizeof(zbx_vmware_dev_t));
2025 dev->type = ZBX_VMWARE_DEV_TYPE_NIC;
2026 dev->instance = key;
2027 dev->label = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
2028 "*[local-name()='deviceInfo']/*[local-name()='label']");
2029
2030 zbx_vector_ptr_append(&vm->devs, dev);
2031 nics++;
2032 }
2033 clean:
2034 if (NULL != xpathObj)
2035 xmlXPathFreeObject(xpathObj);
2036
2037 xmlXPathFreeContext(xpathCtx);
2038 xmlFreeDoc(doc);
2039 out:
2040 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() found:%d", __function_name, nics);
2041 }
2042
2043 /******************************************************************************
2044 * *
2045 * Function: vmware_vm_get_disk_devices *
2046 * *
2047 * Purpose: gets virtual machine virtual disk devices *
2048 * *
2049 * Parameters: vm - [OUT] the virtual machine *
2050 * details - [IN] a xml string containing virtual machine data *
2051 * *
2052 ******************************************************************************/
vmware_vm_get_disk_devices(zbx_vmware_vm_t * vm,const char * details)2053 static void vmware_vm_get_disk_devices(zbx_vmware_vm_t *vm, const char *details)
2054 {
2055 const char *__function_name = "vmware_vm_get_disk_devices";
2056
2057 xmlDoc *doc;
2058 xmlXPathContext *xpathCtx;
2059 xmlXPathObject *xpathObj;
2060 xmlNodeSetPtr nodeset;
2061 int i, disks = 0;
2062 char *xpath = NULL;
2063
2064 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2065
2066 if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
2067 goto out;
2068
2069 xpathCtx = xmlXPathNewContext(doc);
2070
2071 /* select all hardware devices of VirtualDisk type */
2072 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)ZBX_XPATH_VM_HARDWARE("device")
2073 "[string(@*[local-name()='type'])='VirtualDisk']", xpathCtx)))
2074 {
2075 goto clean;
2076 }
2077
2078 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
2079 goto clean;
2080
2081 nodeset = xpathObj->nodesetval;
2082
2083 for (i = 0; i < nodeset->nodeNr; i++)
2084 {
2085 zbx_vmware_dev_t *dev;
2086 char *unitNumber = NULL, *controllerKey = NULL, *busNumber = NULL,
2087 *scsiCtlrUnitNumber = NULL;
2088 xmlXPathObject *xpathObjController = NULL;
2089
2090 do
2091 {
2092 if (NULL == (unitNumber = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
2093 "*[local-name()='unitNumber']")))
2094 {
2095 break;
2096 }
2097
2098 if (NULL == (controllerKey = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
2099 "*[local-name()='controllerKey']")))
2100 {
2101 break;
2102 }
2103
2104 /* find the controller (parent) device */
2105 xpath = zbx_dsprintf(xpath, ZBX_XPATH_VM_HARDWARE("device")
2106 "[*[local-name()='key']/text()='%s']", controllerKey);
2107
2108 if (NULL == (xpathObjController = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx)))
2109 break;
2110
2111 if (0 != xmlXPathNodeSetIsEmpty(xpathObjController->nodesetval))
2112 break;
2113
2114 if (NULL == (busNumber = zbx_xml_read_node_value(doc,
2115 xpathObjController->nodesetval->nodeTab[0], "*[local-name()='busNumber']")))
2116 {
2117 break;
2118 }
2119
2120 /* scsiCtlrUnitNumber property is simply used to determine controller type. */
2121 /* For IDE controllers it is not set. */
2122 scsiCtlrUnitNumber = zbx_xml_read_node_value(doc, xpathObjController->nodesetval->nodeTab[0],
2123 "*[local-name()='scsiCtlrUnitNumber']");
2124
2125 dev = zbx_malloc(NULL, sizeof(zbx_vmware_dev_t));
2126 dev->type = ZBX_VMWARE_DEV_TYPE_DISK;
2127
2128 /* the virtual disk instance has format <controller type><busNumber>:<unitNumber> */
2129 /* where controller type is either ide or scsi depending on the controller type */
2130 dev->instance = zbx_dsprintf(NULL, "%s%s:%s", (NULL == scsiCtlrUnitNumber ? "ide" : "scsi"),
2131 busNumber, unitNumber);
2132
2133 dev->label = zbx_xml_read_node_value(doc, nodeset->nodeTab[i],
2134 "*[local-name()='deviceInfo']/*[local-name()='label']");
2135
2136 zbx_vector_ptr_append(&vm->devs, dev);
2137
2138 disks++;
2139
2140 }
2141 while (0);
2142
2143 if (NULL != xpathObjController)
2144 xmlXPathFreeObject(xpathObjController);
2145
2146 zbx_free(scsiCtlrUnitNumber);
2147 zbx_free(busNumber);
2148 zbx_free(unitNumber);
2149 zbx_free(controllerKey);
2150
2151 }
2152 clean:
2153 zbx_free(xpath);
2154
2155 if (NULL != xpathObj)
2156 xmlXPathFreeObject(xpathObj);
2157
2158 xmlXPathFreeContext(xpathCtx);
2159 xmlFreeDoc(doc);
2160 out:
2161 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() found:%d", __function_name, disks);
2162 }
2163
2164 /******************************************************************************
2165 * *
2166 * Function: vmware_vm_get_file_systems *
2167 * *
2168 * Purpose: gets the parameters of virtual machine disks *
2169 * *
2170 * Parameters: vm - [OUT] the virtual machine *
2171 * details - [IN] a xml string containing virtual machine data *
2172 * *
2173 ******************************************************************************/
vmware_vm_get_file_systems(zbx_vmware_vm_t * vm,const char * details)2174 static void vmware_vm_get_file_systems(zbx_vmware_vm_t *vm, const char *details)
2175 {
2176 const char *__function_name = "vmware_vm_get_file_systems";
2177 xmlDoc *doc;
2178 xmlXPathContext *xpathCtx;
2179 xmlXPathObject *xpathObj;
2180 xmlNodeSetPtr nodeset;
2181 int i;
2182
2183 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2184
2185 if (NULL == (doc = xmlReadMemory(details, strlen(details), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
2186 goto out;
2187
2188 xpathCtx = xmlXPathNewContext(doc);
2189
2190 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)ZBX_XPATH_VM_GUESTDISKS(), xpathCtx)))
2191 goto clean;
2192
2193 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
2194 goto clean;
2195
2196 nodeset = xpathObj->nodesetval;
2197
2198 for (i = 0; i < nodeset->nodeNr; i++)
2199 {
2200 zbx_vmware_fs_t *fs;
2201 char *value;
2202
2203 if (NULL == (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='diskPath']")))
2204 continue;
2205
2206 fs = zbx_malloc(NULL, sizeof(zbx_vmware_fs_t));
2207 memset(fs, 0, sizeof(zbx_vmware_fs_t));
2208
2209 fs->path = value;
2210
2211 if (NULL != (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='capacity']")))
2212 {
2213 ZBX_STR2UINT64(fs->capacity, value);
2214 zbx_free(value);
2215 }
2216
2217 if (NULL != (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='freeSpace']")))
2218 {
2219 ZBX_STR2UINT64(fs->free_space, value);
2220 zbx_free(value);
2221 }
2222
2223 zbx_vector_ptr_append(&vm->file_systems, fs);
2224 }
2225 clean:
2226 if (NULL != xpathObj)
2227 xmlXPathFreeObject(xpathObj);
2228
2229 xmlXPathFreeContext(xpathCtx);
2230 xmlFreeDoc(doc);
2231 out:
2232 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() found:%d", __function_name, vm->file_systems.values_num);
2233 }
2234
2235 /******************************************************************************
2236 * *
2237 * Function: vmware_service_get_vm_data *
2238 * *
2239 * Purpose: gets the virtual machine data *
2240 * *
2241 * Parameters: service - [IN] the vmware service *
2242 * easyhandle - [IN] the CURL handle *
2243 * vmid - [IN] the virtual machine id *
2244 * data - [OUT] a reference to output variable *
2245 * error - [OUT] the error message in the case of failure *
2246 * *
2247 * Return value: SUCCEED - the operation has completed successfully *
2248 * FAIL - the operation has failed *
2249 * *
2250 ******************************************************************************/
vmware_service_get_vm_data(zbx_vmware_service_t * service,CURL * easyhandle,const char * vmid,char ** data,char ** error)2251 static int vmware_service_get_vm_data(zbx_vmware_service_t *service, CURL *easyhandle, const char *vmid,
2252 char **data, char **error)
2253 {
2254 # define ZBX_POST_VMWARE_VM_STATUS_EX \
2255 ZBX_POST_VSPHERE_HEADER \
2256 "<ns0:RetrievePropertiesEx>" \
2257 "<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>" \
2258 "<ns0:specSet>" \
2259 "<ns0:propSet>" \
2260 "<ns0:type>VirtualMachine</ns0:type>" \
2261 "<ns0:pathSet>config.hardware</ns0:pathSet>" \
2262 "<ns0:pathSet>config.uuid</ns0:pathSet>" \
2263 "<ns0:pathSet>config.instanceUuid</ns0:pathSet>"\
2264 "<ns0:pathSet>summary</ns0:pathSet>" \
2265 "<ns0:pathSet>guest.disk</ns0:pathSet>" \
2266 "</ns0:propSet>" \
2267 "<ns0:objectSet>" \
2268 "<ns0:obj type=\"VirtualMachine\">%s</ns0:obj>" \
2269 "</ns0:objectSet>" \
2270 "</ns0:specSet>" \
2271 "<ns0:options></ns0:options>" \
2272 "</ns0:RetrievePropertiesEx>" \
2273 ZBX_POST_VSPHERE_FOOTER
2274
2275 const char *__function_name = "vmware_service_get_vm_data";
2276
2277 char tmp[MAX_STRING_LEN], *vmid_esc;
2278 int err, opt, ret = FAIL;
2279
2280 zabbix_log(LOG_LEVEL_DEBUG, "In %s() vmid:'%s'", __function_name, vmid);
2281
2282 vmid_esc = xml_escape_dyn(vmid);
2283
2284 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_VM_STATUS_EX,
2285 vmware_service_objects[service->type].property_collector, vmid_esc);
2286
2287 zbx_free(vmid_esc);
2288
2289 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
2290 {
2291 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
2292 goto out;
2293 }
2294
2295 page.offset = 0;
2296
2297 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
2298 {
2299 *error = zbx_strdup(*error, curl_easy_strerror(err));
2300 goto out;
2301 }
2302
2303 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
2304
2305 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
2306 goto out;
2307
2308 *data = zbx_strdup(NULL, page.data);
2309
2310 ret = SUCCEED;
2311 out:
2312 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2313
2314 return ret;
2315 }
2316
2317 /******************************************************************************
2318 * *
2319 * Function: vmware_service_create_vm *
2320 * *
2321 * Purpose: create virtual machine object *
2322 * *
2323 * Parameters: service - [IN] the vmware service *
2324 * easyhandle - [IN] the CURL handle *
2325 * id - [IN] the virtual machine id *
2326 * error - [OUT] the error message in the case of failure *
2327 * *
2328 * Return value: The created virtual machine object or NULL if an error was *
2329 * detected. *
2330 * *
2331 ******************************************************************************/
vmware_service_create_vm(zbx_vmware_service_t * service,CURL * easyhandle,const char * id,char ** error)2332 static zbx_vmware_vm_t *vmware_service_create_vm(zbx_vmware_service_t *service, CURL *easyhandle,
2333 const char *id, char **error)
2334 {
2335 const char *__function_name = "vmware_service_create_vm";
2336
2337 zbx_vmware_vm_t *vm;
2338 char *value, *details = NULL;
2339 const char *uuid_xpath[3] = {NULL, ZBX_XPATH_VM_UUID(), ZBX_XPATH_VM_INSTANCE_UUID()};
2340 int ret = FAIL;
2341
2342 zabbix_log(LOG_LEVEL_DEBUG, "In %s() vmid:'%s'", __function_name, id);
2343
2344 vm = zbx_malloc(NULL, sizeof(zbx_vmware_vm_t));
2345 memset(vm, 0, sizeof(zbx_vmware_vm_t));
2346
2347 zbx_vector_ptr_create(&vm->devs);
2348 zbx_vector_ptr_create(&vm->file_systems);
2349
2350 if (SUCCEED != vmware_service_get_vm_data(service, easyhandle, id, &details, error))
2351 goto out;
2352
2353 if (NULL == (value = zbx_xml_read_value(details, uuid_xpath[service->type])))
2354 goto out;
2355
2356 vm->uuid = value;
2357 vm->id = zbx_strdup(NULL, id);
2358
2359 if (NULL == (vm->props = xml_read_props(details, vm_propmap, ZBX_VMWARE_VMPROPS_NUM)))
2360 goto out;
2361
2362 vmware_vm_get_nic_devices(vm, details);
2363 vmware_vm_get_disk_devices(vm, details);
2364 vmware_vm_get_file_systems(vm, details);
2365
2366 ret = SUCCEED;
2367 out:
2368 zbx_free(details);
2369
2370 if (SUCCEED != ret)
2371 {
2372 vmware_vm_free(vm);
2373 vm = NULL;
2374 }
2375
2376 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2377
2378 return vm;
2379 }
2380
2381 /******************************************************************************
2382 * *
2383 * Function: vmware_service_refresh_datastore_info *
2384 * *
2385 * Purpose: Refreshes all storage related information including free-space, *
2386 * capacity, and detailed usage of virtual machines. *
2387 * *
2388 * Parameters: easyhandle - [IN] the CURL handle *
2389 * id - [IN] the datastore id *
2390 * *
2391 * Comments: This is required for ESX/ESXi hosts version < 6.0 only *
2392 * *
2393 ******************************************************************************/
vmware_service_refresh_datastore_info(CURL * easyhandle,const char * id)2394 static int vmware_service_refresh_datastore_info(CURL *easyhandle, const char *id)
2395 {
2396 # define ZBX_POST_REFRESH_DATASTORE \
2397 ZBX_POST_VSPHERE_HEADER \
2398 "<ns0:RefreshDatastoreStorageInfo>" \
2399 "<ns0:_this type=\"HostSystem\">%s</ns0:_this>" \
2400 "</ns0:RefreshDatastoreStorageInfo>" \
2401 ZBX_POST_VSPHERE_FOOTER
2402
2403 const char *__function_name = "vmware_service_refresh_datastore_info";
2404 char tmp[MAX_STRING_LEN];
2405
2406 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_REFRESH_DATASTORE, id);
2407 if (CURLE_OK != curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, tmp))
2408 return FAIL;
2409
2410 page.offset = 0;
2411
2412 if (CURLE_OK != curl_easy_perform(easyhandle))
2413 return FAIL;
2414
2415 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
2416
2417 return SUCCEED;
2418 }
2419
2420 /******************************************************************************
2421 * *
2422 * Function: vmware_service_create_datastore *
2423 * *
2424 * Purpose: create vmware hypervisor datastore object *
2425 * *
2426 * Parameters: service - [IN] the vmware service *
2427 * easyhandle - [IN] the CURL handle *
2428 * id - [IN] the datastore id *
2429 * *
2430 * Return value: The created datastore object or NULL if an error was *
2431 * detected *
2432 * *
2433 ******************************************************************************/
vmware_service_create_datastore(const zbx_vmware_service_t * service,CURL * easyhandle,const char * id)2434 static zbx_vmware_datastore_t *vmware_service_create_datastore(const zbx_vmware_service_t *service, CURL *easyhandle,
2435 const char *id)
2436 {
2437 # define ZBX_POST_DATASTORE_GET \
2438 ZBX_POST_VSPHERE_HEADER \
2439 "<ns0:RetrieveProperties>" \
2440 "<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>" \
2441 "<ns0:specSet>" \
2442 "<ns0:propSet>" \
2443 "<ns0:type>Datastore</ns0:type>" \
2444 "<ns0:pathSet>summary</ns0:pathSet>" \
2445 "<ns0:pathSet>host</ns0:pathSet>" \
2446 "</ns0:propSet>" \
2447 "<ns0:objectSet>" \
2448 "<ns0:obj type=\"Datastore\">%s</ns0:obj>" \
2449 "</ns0:objectSet>" \
2450 "</ns0:specSet>" \
2451 "</ns0:RetrieveProperties>" \
2452 ZBX_POST_VSPHERE_FOOTER
2453
2454 const char *__function_name = "vmware_service_create_datastore";
2455 char tmp[MAX_STRING_LEN], *uuid = NULL, *name = NULL, *path, *id_esc, *value;
2456 zbx_vmware_datastore_t *datastore = NULL;
2457 zbx_uint64_t capacity = ZBX_MAX_UINT64, free_space = ZBX_MAX_UINT64, uncommitted = ZBX_MAX_UINT64;
2458
2459 zabbix_log(LOG_LEVEL_DEBUG, "In %s() datastore:'%s'", __function_name, id);
2460
2461 id_esc = xml_escape_dyn(id);
2462
2463 if (ZBX_VMWARE_TYPE_VSPHERE == service->type
2464 && SUCCEED != vmware_service_refresh_datastore_info(easyhandle, id_esc))
2465 {
2466 zbx_free(id_esc);
2467 goto out;
2468 }
2469
2470 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_DATASTORE_GET,
2471 vmware_service_objects[service->type].property_collector, id_esc);
2472
2473 zbx_free(id_esc);
2474
2475 if (CURLE_OK != curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, tmp))
2476 goto out;
2477
2478 page.offset = 0;
2479
2480 if (CURLE_OK != curl_easy_perform(easyhandle))
2481 goto out;
2482
2483 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
2484
2485 name = zbx_xml_read_value(page.data, ZBX_XPATH_DATASTORE_SUMMARY("name"));
2486
2487 if (NULL != (path = zbx_xml_read_value(page.data, ZBX_XPATH_DATASTORE_MOUNT())))
2488 {
2489 if ('\0' != *path)
2490 {
2491 size_t len;
2492 char *ptr;
2493
2494 len = strlen(path);
2495
2496 if ('/' == path[len - 1])
2497 path[len - 1] = '\0';
2498
2499 for (ptr = path + len - 2; ptr > path && *ptr != '/'; ptr--)
2500 ;
2501
2502 uuid = zbx_strdup(NULL, ptr + 1);
2503 }
2504 zbx_free(path);
2505 }
2506
2507 if (ZBX_VMWARE_TYPE_VSPHERE == service->type)
2508 {
2509 if (NULL != (value = zbx_xml_read_value(page.data, ZBX_XPATH_DATASTORE_SUMMARY("capacity"))))
2510 {
2511 is_uint64(value, &capacity);
2512 zbx_free(value);
2513 }
2514
2515 if (NULL != (value = zbx_xml_read_value(page.data, ZBX_XPATH_DATASTORE_SUMMARY("freeSpace"))))
2516 {
2517 is_uint64(value, &free_space);
2518 zbx_free(value);
2519 }
2520
2521 if (NULL != (value = zbx_xml_read_value(page.data, ZBX_XPATH_DATASTORE_SUMMARY("uncommitted"))))
2522 {
2523 is_uint64(value, &uncommitted);
2524 zbx_free(value);
2525 }
2526 }
2527
2528 datastore = zbx_malloc(NULL, sizeof(zbx_vmware_datastore_t));
2529 datastore->name = (NULL != name) ? name : zbx_strdup(NULL, id);
2530 datastore->uuid = uuid;
2531 datastore->id = zbx_strdup(NULL, id);
2532 datastore->capacity = capacity;
2533 datastore->free_space = free_space;
2534 datastore->uncommitted = uncommitted;
2535 out:
2536 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2537
2538 return datastore;
2539 }
2540
2541 /******************************************************************************
2542 * *
2543 * Function: vmware_service_get_hv_data *
2544 * *
2545 * Purpose: gets the vmware hypervisor data *
2546 * *
2547 * Parameters: service - [IN] the vmware service *
2548 * easyhandle - [IN] the CURL handle *
2549 * hvid - [IN] the vmware hypervisor id *
2550 * data - [OUT] a reference to output variable *
2551 * error - [OUT] the error message in the case of failure *
2552 * *
2553 * Return value: SUCCEED - the operation has completed successfully *
2554 * FAIL - the operation has failed *
2555 * *
2556 ******************************************************************************/
vmware_service_get_hv_data(const zbx_vmware_service_t * service,CURL * easyhandle,const char * hvid,char ** data,char ** error)2557 static int vmware_service_get_hv_data(const zbx_vmware_service_t *service, CURL *easyhandle, const char *hvid,
2558 char **data, char **error)
2559 {
2560 # define ZBX_POST_HV_DETAILS \
2561 ZBX_POST_VSPHERE_HEADER \
2562 "<ns0:RetrieveProperties>" \
2563 "<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>" \
2564 "<ns0:specSet>" \
2565 "<ns0:propSet>" \
2566 "<ns0:type>HostSystem</ns0:type>" \
2567 "<ns0:pathSet>name</ns0:pathSet>" \
2568 "<ns0:pathSet>overallStatus</ns0:pathSet>" \
2569 "<ns0:pathSet>vm</ns0:pathSet>" \
2570 "<ns0:pathSet>summary.quickStats</ns0:pathSet>" \
2571 "<ns0:pathSet>summary.config</ns0:pathSet>" \
2572 "<ns0:pathSet>summary.hardware</ns0:pathSet>" \
2573 "<ns0:pathSet>parent</ns0:pathSet>" \
2574 "<ns0:pathSet>datastore</ns0:pathSet>" \
2575 "<ns0:pathSet>runtime.healthSystemRuntime." \
2576 "systemHealthInfo</ns0:pathSet>" \
2577 "</ns0:propSet>" \
2578 "<ns0:objectSet>" \
2579 "<ns0:obj type=\"HostSystem\">%s</ns0:obj>" \
2580 "</ns0:objectSet>" \
2581 "</ns0:specSet>" \
2582 "</ns0:RetrieveProperties>" \
2583 ZBX_POST_VSPHERE_FOOTER
2584
2585 const char *__function_name = "vmware_service_get_hv_data";
2586
2587 char tmp[MAX_STRING_LEN], *hvid_esc;
2588 int err, opt, ret = FAIL;
2589
2590 zabbix_log(LOG_LEVEL_DEBUG, "In %s() guesthvid:'%s'", __function_name, hvid);
2591
2592 hvid_esc = xml_escape_dyn(hvid);
2593
2594 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_HV_DETAILS,
2595 vmware_service_objects[service->type].property_collector, hvid_esc);
2596
2597 zbx_free(hvid_esc);
2598
2599 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
2600 {
2601 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
2602 goto out;
2603 }
2604
2605 page.offset = 0;
2606
2607 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
2608 {
2609 *error = zbx_strdup(*error, curl_easy_strerror(err));
2610 goto out;
2611 }
2612
2613 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
2614
2615 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
2616 goto out;
2617
2618 *data = zbx_strdup(NULL, page.data);
2619
2620 ret = SUCCEED;
2621 out:
2622 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2623
2624 return ret;
2625 }
2626
2627 /******************************************************************************
2628 * *
2629 * Function: vmware_service_init_hv *
2630 * *
2631 * Purpose: initialize vmware hypervisor object *
2632 * *
2633 * Parameters: service - [IN] the vmware service *
2634 * easyhandle - [IN] the CURL handle *
2635 * id - [IN] the vmware hypervisor id *
2636 * hv - [OUT] the hypervisor object (must be allocated) *
2637 * error - [OUT] the error message in the case of failure *
2638 * *
2639 * Return value: SUCCEED - the hypervisor object was initialized successfully *
2640 * FAIL - otherwise *
2641 * *
2642 ******************************************************************************/
vmware_service_init_hv(zbx_vmware_service_t * service,CURL * easyhandle,const char * id,zbx_vmware_hv_t * hv,char ** error)2643 static int vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandle, const char *id,
2644 zbx_vmware_hv_t *hv, char **error)
2645 {
2646 const char *__function_name = "vmware_service_init_hv";
2647 char *value, *details = NULL;
2648 zbx_vector_str_t datastores, vms;
2649 int i, ret = FAIL;
2650
2651 zabbix_log(LOG_LEVEL_DEBUG, "In %s() hvid:'%s'", __function_name, id);
2652
2653 memset(hv, 0, sizeof(zbx_vmware_hv_t));
2654
2655 zbx_vector_ptr_create(&hv->datastores);
2656 zbx_vector_ptr_create(&hv->vms);
2657
2658 zbx_vector_str_create(&datastores);
2659 zbx_vector_str_create(&vms);
2660
2661 if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, &details, error))
2662 goto out;
2663
2664 if (NULL == (hv->props = xml_read_props(details, hv_propmap, ZBX_VMWARE_HVPROPS_NUM)))
2665 goto out;
2666
2667 if (NULL == hv->props[ZBX_VMWARE_HVPROP_HW_UUID])
2668 goto out;
2669
2670 hv->uuid = zbx_strdup(NULL, hv->props[ZBX_VMWARE_HVPROP_HW_UUID]);
2671 hv->id = zbx_strdup(NULL, id);
2672
2673 if (NULL != (value = zbx_xml_read_value(details, "//*[@type='ClusterComputeResource']")))
2674 hv->clusterid = value;
2675
2676 zbx_xml_read_values(details, ZBX_XPATH_HV_DATASTORES(), &datastores);
2677
2678 for (i = 0; i < datastores.values_num; i++)
2679 {
2680 zbx_vmware_datastore_t *datastore;
2681
2682 if (NULL != (datastore = vmware_service_create_datastore(service, easyhandle, datastores.values[i])))
2683 zbx_vector_ptr_append(&hv->datastores, datastore);
2684 }
2685
2686 zbx_xml_read_values(details, ZBX_XPATH_HV_VMS(), &vms);
2687
2688 for (i = 0; i < vms.values_num; i++)
2689 {
2690 zbx_vmware_vm_t *vm;
2691
2692 if (NULL != (vm = vmware_service_create_vm(service, easyhandle, vms.values[i], error)))
2693 zbx_vector_ptr_append(&hv->vms, vm);
2694 }
2695
2696 ret = SUCCEED;
2697 out:
2698 zbx_free(details);
2699
2700 zbx_vector_str_clear_ext(&vms, zbx_ptr_free);
2701 zbx_vector_str_destroy(&vms);
2702
2703 zbx_vector_str_clear_ext(&datastores, zbx_ptr_free);
2704 zbx_vector_str_destroy(&datastores);
2705
2706 if (SUCCEED != ret)
2707 vmware_hv_clean(hv);
2708
2709 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2710
2711 return ret;
2712 }
2713
2714 /******************************************************************************
2715 * *
2716 * Function: vmware_service_get_hv_list *
2717 * *
2718 * Purpose: retrieves a list of all vmware service hypervisor ids *
2719 * *
2720 * Parameters: service - [IN] the vmware service *
2721 * easyhandle - [IN] the CURL handle *
2722 * hvs - [OUT] list of vmware hypervisor ids *
2723 * error - [OUT] the error message in the case of failure *
2724 * *
2725 * Return value: SUCCEED - the operation has completed successfully *
2726 * FAIL - the operation has failed *
2727 * *
2728 ******************************************************************************/
vmware_service_get_hv_list(const zbx_vmware_service_t * service,CURL * easyhandle,zbx_vector_str_t * hvs,char ** error)2729 static int vmware_service_get_hv_list(const zbx_vmware_service_t *service, CURL *easyhandle,
2730 zbx_vector_str_t *hvs, char **error)
2731 {
2732 # define ZBX_POST_VCENTER_HV_LIST \
2733 ZBX_POST_VSPHERE_HEADER \
2734 "<ns0:RetrievePropertiesEx xsi:type=\"ns0:RetrievePropertiesExRequestType\">" \
2735 "<ns0:_this type=\"PropertyCollector\">propertyCollector</ns0:_this>" \
2736 "<ns0:specSet>" \
2737 "<ns0:propSet>" \
2738 "<ns0:type>HostSystem</ns0:type>" \
2739 "</ns0:propSet>" \
2740 "<ns0:objectSet>" \
2741 "<ns0:obj type=\"Folder\">group-d1</ns0:obj>" \
2742 "<ns0:skip>false</ns0:skip>" \
2743 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2744 "<ns0:name>visitFolders</ns0:name>" \
2745 "<ns0:type>Folder</ns0:type>" \
2746 "<ns0:path>childEntity</ns0:path>" \
2747 "<ns0:skip>false</ns0:skip>" \
2748 "<ns0:selectSet>" \
2749 "<ns0:name>visitFolders</ns0:name>" \
2750 "</ns0:selectSet>" \
2751 "<ns0:selectSet>" \
2752 "<ns0:name>dcToHf</ns0:name>" \
2753 "</ns0:selectSet>" \
2754 "<ns0:selectSet>" \
2755 "<ns0:name>dcToVmf</ns0:name>" \
2756 "</ns0:selectSet>" \
2757 "<ns0:selectSet>" \
2758 "<ns0:name>crToH</ns0:name>" \
2759 "</ns0:selectSet>" \
2760 "<ns0:selectSet>" \
2761 "<ns0:name>crToRp</ns0:name>" \
2762 "</ns0:selectSet>" \
2763 "<ns0:selectSet>" \
2764 "<ns0:name>dcToDs</ns0:name>" \
2765 "</ns0:selectSet>" \
2766 "<ns0:selectSet>" \
2767 "<ns0:name>hToVm</ns0:name>" \
2768 "</ns0:selectSet>" \
2769 "<ns0:selectSet>" \
2770 "<ns0:name>rpToVm</ns0:name>" \
2771 "</ns0:selectSet>" \
2772 "</ns0:selectSet>" \
2773 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2774 "<ns0:name>dcToVmf</ns0:name>" \
2775 "<ns0:type>Datacenter</ns0:type>" \
2776 "<ns0:path>vmFolder</ns0:path>" \
2777 "<ns0:skip>false</ns0:skip>" \
2778 "<ns0:selectSet>" \
2779 "<ns0:name>visitFolders</ns0:name>" \
2780 "</ns0:selectSet>" \
2781 "</ns0:selectSet>" \
2782 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2783 "<ns0:name>dcToDs</ns0:name>" \
2784 "<ns0:type>Datacenter</ns0:type>" \
2785 "<ns0:path>datastore</ns0:path>" \
2786 "<ns0:skip>false</ns0:skip>" \
2787 "<ns0:selectSet>" \
2788 "<ns0:name>visitFolders</ns0:name>" \
2789 "</ns0:selectSet>" \
2790 "</ns0:selectSet>" \
2791 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2792 "<ns0:name>dcToHf</ns0:name>" \
2793 "<ns0:type>Datacenter</ns0:type>" \
2794 "<ns0:path>hostFolder</ns0:path>" \
2795 "<ns0:skip>false</ns0:skip>" \
2796 "<ns0:selectSet>" \
2797 "<ns0:name>visitFolders</ns0:name>" \
2798 "</ns0:selectSet>" \
2799 "</ns0:selectSet>" \
2800 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2801 "<ns0:name>crToH</ns0:name>" \
2802 "<ns0:type>ComputeResource</ns0:type>" \
2803 "<ns0:path>host</ns0:path>" \
2804 "<ns0:skip>false</ns0:skip>" \
2805 "</ns0:selectSet>" \
2806 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2807 "<ns0:name>crToRp</ns0:name>" \
2808 "<ns0:type>ComputeResource</ns0:type>" \
2809 "<ns0:path>resourcePool</ns0:path>" \
2810 "<ns0:skip>false</ns0:skip>" \
2811 "<ns0:selectSet>" \
2812 "<ns0:name>rpToRp</ns0:name>" \
2813 "</ns0:selectSet>" \
2814 "<ns0:selectSet>" \
2815 "<ns0:name>rpToVm</ns0:name>" \
2816 "</ns0:selectSet>" \
2817 "</ns0:selectSet>" \
2818 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2819 "<ns0:name>rpToRp</ns0:name>" \
2820 "<ns0:type>ResourcePool</ns0:type>" \
2821 "<ns0:path>resourcePool</ns0:path>" \
2822 "<ns0:skip>false</ns0:skip>" \
2823 "<ns0:selectSet>" \
2824 "<ns0:name>rpToRp</ns0:name>" \
2825 "</ns0:selectSet>" \
2826 "<ns0:selectSet>" \
2827 "<ns0:name>rpToVm</ns0:name>" \
2828 "</ns0:selectSet>" \
2829 "</ns0:selectSet>" \
2830 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2831 "<ns0:name>hToVm</ns0:name>" \
2832 "<ns0:type>HostSystem</ns0:type>" \
2833 "<ns0:path>vm</ns0:path>" \
2834 "<ns0:skip>false</ns0:skip>" \
2835 "<ns0:selectSet>" \
2836 "<ns0:name>visitFolders</ns0:name>" \
2837 "</ns0:selectSet>" \
2838 "</ns0:selectSet>" \
2839 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
2840 "<ns0:name>rpToVm</ns0:name>" \
2841 "<ns0:type>ResourcePool</ns0:type>" \
2842 "<ns0:path>vm</ns0:path>" \
2843 "<ns0:skip>false</ns0:skip>" \
2844 "</ns0:selectSet>" \
2845 "</ns0:objectSet>" \
2846 "</ns0:specSet>" \
2847 "<ns0:options/>" \
2848 "</ns0:RetrievePropertiesEx>" \
2849 ZBX_POST_VSPHERE_FOOTER
2850
2851 const char *__function_name = "vmware_service_get_hv_list";
2852
2853 int ret = FAIL;
2854
2855 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2856
2857 if (ZBX_VMWARE_TYPE_VCENTER == service->type)
2858 {
2859 zbx_property_collection_iter *iter;
2860 const char *chunk;
2861
2862 iter = zbx_property_collection_init(easyhandle, ZBX_POST_VCENTER_HV_LIST, "propertyCollector");
2863
2864 do
2865 {
2866 if (NULL == (chunk = zbx_property_collection_chunk(iter, error)))
2867 {
2868 zbx_property_collection_free(iter);
2869 goto out;
2870 }
2871
2872 zbx_xml_read_values(chunk, "//*[@type='HostSystem']", hvs);
2873 }
2874 while (SUCCEED == zbx_property_collection_next(iter));
2875
2876 zbx_property_collection_free(iter);
2877 }
2878 else
2879 zbx_vector_str_append(hvs, zbx_strdup(NULL, "ha-host"));
2880
2881 ret = SUCCEED;
2882 out:
2883 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s found:%d", __function_name, zbx_result_string(ret), hvs->values_num);
2884
2885 return ret;
2886 }
2887
2888 /******************************************************************************
2889 * *
2890 * Function: vmware_service_get_event_session *
2891 * *
2892 * Purpose: retrieves event session name *
2893 * *
2894 * Parameters: service - [IN] the vmware service *
2895 * easyhandle - [IN] the CURL handle *
2896 * event_session - [OUT] a pointer to the output variable *
2897 * error - [OUT] the error message in the case of failure*
2898 * *
2899 * Return value: SUCCEED - the operation has completed successfully *
2900 * FAIL - the operation has failed *
2901 * *
2902 ******************************************************************************/
vmware_service_get_event_session(const zbx_vmware_service_t * service,CURL * easyhandle,char ** event_session,char ** error)2903 static int vmware_service_get_event_session(const zbx_vmware_service_t *service, CURL *easyhandle,
2904 char **event_session, char **error)
2905 {
2906 # define ZBX_POST_VMWARE_CREATE_EVENT_COLLECTOR \
2907 ZBX_POST_VSPHERE_HEADER \
2908 "<ns0:CreateCollectorForEvents>" \
2909 "<ns0:_this type=\"EventManager\">%s</ns0:_this>" \
2910 "<ns0:filter/>" \
2911 "</ns0:CreateCollectorForEvents>" \
2912 ZBX_POST_VSPHERE_FOOTER
2913
2914 const char *__function_name = "vmware_service_get_event_session";
2915
2916 char tmp[MAX_STRING_LEN];
2917 int err, opt, ret = FAIL;
2918
2919 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2920
2921 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_CREATE_EVENT_COLLECTOR,
2922 vmware_service_objects[service->type].event_manager);
2923
2924 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
2925 {
2926 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
2927 goto out;
2928 }
2929
2930 page.offset = 0;
2931
2932 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
2933 {
2934 *error = zbx_strdup(*error, curl_easy_strerror(err));
2935 goto out;
2936 }
2937
2938 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
2939
2940 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
2941 goto out;
2942
2943 if (NULL == (*event_session = zbx_xml_read_value(page.data, "/*/*/*/*[@type='EventHistoryCollector']")))
2944 {
2945 *error = zbx_strdup(*error, "Cannot get EventHistoryCollector session.");
2946 goto out;
2947 }
2948
2949 ret = SUCCEED;
2950 out:
2951 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s event_session:'%s'", __function_name, zbx_result_string(ret),
2952 ZBX_NULL2EMPTY_STR(*event_session));
2953
2954 return ret;
2955 }
2956
2957 /******************************************************************************
2958 * *
2959 * Function: vmware_service_reset_event_history_collector *
2960 * *
2961 * Purpose: resets "scrollable view" to the latest events *
2962 * *
2963 * Parameters: easyhandle - [IN] the CURL handle *
2964 * event_session - [IN] event session (EventHistoryCollector) *
2965 * identifier *
2966 * error - [OUT] the error message in the case of failure*
2967 * *
2968 * Return value: SUCCEED - the operation has completed successfully *
2969 * FAIL - the operation has failed *
2970 * *
2971 ******************************************************************************/
vmware_service_reset_event_history_collector(CURL * easyhandle,const char * event_session,char ** error)2972 static int vmware_service_reset_event_history_collector(CURL *easyhandle, const char *event_session, char **error)
2973 {
2974 # define ZBX_POST_VMWARE_RESET_EVENT_COLLECTOR \
2975 ZBX_POST_VSPHERE_HEADER \
2976 "<ns0:ResetCollector>" \
2977 "<ns0:_this type=\"EventHistoryCollector\">%s</ns0:_this>" \
2978 "</ns0:ResetCollector>" \
2979 ZBX_POST_VSPHERE_FOOTER
2980
2981 const char *__function_name = "vmware_service_reset_event_history_collector";
2982
2983 int err, opt, ret = FAIL;
2984 char tmp[MAX_STRING_LEN], *event_session_esc;
2985
2986 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2987
2988 event_session_esc = xml_escape_dyn(event_session);
2989
2990 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_RESET_EVENT_COLLECTOR, event_session_esc);
2991
2992 zbx_free(event_session_esc);
2993
2994 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
2995 {
2996 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
2997 goto out;
2998 }
2999
3000 page.offset = 0;
3001
3002 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3003 {
3004 *error = zbx_strdup(*error, curl_easy_strerror(err));
3005 goto out;
3006 }
3007
3008 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3009 goto out;
3010
3011 ret = SUCCEED;
3012 out:
3013 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3014
3015 return ret;
3016 }
3017
3018 /******************************************************************************
3019 * *
3020 * Function: vmware_service_read_previous_events *
3021 * *
3022 * Purpose: reads events from "scrollable view" and moves it back in time *
3023 * *
3024 * Parameters: easyhandle - [IN] the CURL handle *
3025 * event_session - [IN] event session (EventHistoryCollector) *
3026 * identifier *
3027 * soap_count - [IN] max count of events in response *
3028 * error - [OUT] the error message in the case of failure*
3029 * *
3030 * Return value: SUCCEED - the operation has completed successfully *
3031 * FAIL - the operation has failed *
3032 * *
3033 ******************************************************************************/
vmware_service_read_previous_events(CURL * easyhandle,const char * event_session,int soap_count,char ** error)3034 static int vmware_service_read_previous_events(CURL *easyhandle, const char *event_session, int soap_count,
3035 char **error)
3036 {
3037 # define ZBX_POST_VMWARE_READ_PREVIOUS_EVENTS \
3038 ZBX_POST_VSPHERE_HEADER \
3039 "<ns0:ReadPreviousEvents>" \
3040 "<ns0:_this type=\"EventHistoryCollector\">%s</ns0:_this>" \
3041 "<ns0:maxCount>%d</ns0:maxCount>" \
3042 "</ns0:ReadPreviousEvents>" \
3043 ZBX_POST_VSPHERE_FOOTER
3044
3045 const char *__function_name = "vmware_service_read_previous_events";
3046
3047 int err, opt, ret = FAIL;
3048 char tmp[MAX_STRING_LEN], *event_session_esc;
3049
3050 zabbix_log(LOG_LEVEL_DEBUG, "In %s() soap_count: %d", __function_name, soap_count);
3051
3052 page.offset = 0;
3053
3054 if (0 >= soap_count)
3055 {
3056 ret = SUCCEED;
3057 goto out;
3058 }
3059
3060 event_session_esc = xml_escape_dyn(event_session);
3061
3062 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_READ_PREVIOUS_EVENTS, event_session_esc, soap_count);
3063
3064 zbx_free(event_session_esc);
3065
3066 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
3067 {
3068 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
3069 goto out;
3070 }
3071
3072 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3073 {
3074 *error = zbx_strdup(*error, curl_easy_strerror(err));
3075 goto out;
3076 }
3077
3078 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3079 goto out;
3080
3081 zabbix_log(LOG_LEVEL_TRACE, "SOAP response: %s", page.data);
3082
3083 ret = SUCCEED;
3084 out:
3085 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3086
3087 return ret;
3088 }
3089
3090 /******************************************************************************
3091 * *
3092 * Function: vmware_service_destroy_event_session *
3093 * *
3094 * Purpose: destroys event session *
3095 * *
3096 * Parameters: easyhandle - [IN] the CURL handle *
3097 * event_session - [IN] event session (EventHistoryCollector) *
3098 * identifier *
3099 * error - [OUT] the error message in the case of failure*
3100 * *
3101 * Return value: SUCCEED - the operation has completed successfully *
3102 * FAIL - the operation has failed *
3103 * *
3104 ******************************************************************************/
vmware_service_destroy_event_session(CURL * easyhandle,const char * event_session,char ** error)3105 static int vmware_service_destroy_event_session(CURL *easyhandle, const char *event_session, char **error)
3106 {
3107 # define ZBX_POST_VMWARE_DESTROY_EVENT_COLLECTOR \
3108 ZBX_POST_VSPHERE_HEADER \
3109 "<ns0:DestroyCollector>" \
3110 "<ns0:_this type=\"EventHistoryCollector\">%s</ns0:_this>" \
3111 "</ns0:DestroyCollector>" \
3112 ZBX_POST_VSPHERE_FOOTER
3113
3114 const char *__function_name = "vmware_service_destroy_event_session";
3115
3116 int err, opt, ret = FAIL;
3117 char tmp[MAX_STRING_LEN], *event_session_esc;
3118
3119 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3120
3121 event_session_esc = xml_escape_dyn(event_session);
3122
3123 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_DESTROY_EVENT_COLLECTOR, event_session_esc);
3124
3125 zbx_free(event_session_esc);
3126
3127 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
3128 {
3129 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
3130 goto out;
3131 }
3132
3133 page.offset = 0;
3134
3135 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3136 {
3137 *error = zbx_strdup(*error, curl_easy_strerror(err));
3138 goto out;
3139 }
3140
3141 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3142 goto out;
3143
3144 ret = SUCCEED;
3145 out:
3146 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3147
3148 return ret;
3149 }
3150
3151 /******************************************************************************
3152 * *
3153 * Function: vmware_service_put_event_data *
3154 * *
3155 * Purpose: read event data by id from xml and put to array of events *
3156 * *
3157 * Parameters: events - [IN/OUT] the array of parsed events *
3158 * xml_event - [IN] the xml node and id of parsed event *
3159 * xdoc - [IN] xml document with eventlog records *
3160 * *
3161 * Return value: SUCCEED - the operation has completed successfully *
3162 * FAIL - the operation has failed *
3163 ******************************************************************************/
vmware_service_put_event_data(zbx_vector_ptr_t * events,zbx_id_xmlnode_t xml_event,xmlDoc * xdoc)3164 static int vmware_service_put_event_data(zbx_vector_ptr_t *events, zbx_id_xmlnode_t xml_event, xmlDoc *xdoc)
3165 {
3166 zbx_vmware_event_t *event = NULL;
3167 char *message, *time_str;
3168 int timestamp = 0;
3169
3170 if (NULL == (message = zbx_xml_read_node_value(xdoc, xml_event.xml_node, ZBX_XPATH_NN("fullFormattedMessage"))))
3171 {
3172 zabbix_log(LOG_LEVEL_TRACE, "skipping event key '" ZBX_FS_UI64 "', fullFormattedMessage"
3173 " is missing", xml_event.id);
3174 return FAIL;
3175 }
3176
3177 zbx_replace_invalid_utf8(message);
3178
3179 if (NULL == (time_str = zbx_xml_read_node_value(xdoc, xml_event.xml_node, ZBX_XPATH_NN("createdTime"))))
3180 {
3181 zabbix_log(LOG_LEVEL_TRACE, "createdTime is missing for event key '" ZBX_FS_UI64 "'", xml_event.id);
3182 }
3183 else
3184 {
3185 int year, mon, mday, hour, min, sec, t;
3186
3187 /* 2013-06-04T14:19:23.406298Z */
3188 if (6 != sscanf(time_str, "%d-%d-%dT%d:%d:%d.%*s", &year, &mon, &mday, &hour, &min, &sec))
3189 {
3190 zabbix_log(LOG_LEVEL_TRACE, "unexpected format of createdTime '%s' for event"
3191 " key '" ZBX_FS_UI64 "'", time_str, xml_event.id);
3192 }
3193 else if (SUCCEED != zbx_utc_time(year, mon, mday, hour, min, sec, &t))
3194 {
3195 zabbix_log(LOG_LEVEL_TRACE, "cannot convert createdTime '%s' for event key '"
3196 ZBX_FS_UI64 "'", time_str, xml_event.id);
3197 }
3198 else
3199 timestamp = t;
3200
3201 zbx_free(time_str);
3202 }
3203
3204 event = (zbx_vmware_event_t *)zbx_malloc(event, sizeof(zbx_vmware_event_t));
3205 event->key = xml_event.id;
3206 event->message = message;
3207 event->timestamp = timestamp;
3208 zbx_vector_ptr_append(events, event);
3209
3210 return SUCCEED;
3211 }
3212
3213 /******************************************************************************
3214 * *
3215 * Function: vmware_service_parse_event_data *
3216 * *
3217 * Purpose: parse multiple events data *
3218 * *
3219 * Parameters: events - [IN/OUT] the array of parsed events *
3220 * last_key - [IN] the key of last parsed event *
3221 * xml - [IN] xml string with eventlog records *
3222 * len - [IN] length of xml string *
3223 * *
3224 * Return value: The count of events successfully parsed *
3225 * *
3226 ******************************************************************************/
vmware_service_parse_event_data(zbx_vector_ptr_t * events,zbx_uint64_t last_key,const char * xml,size_t len)3227 int vmware_service_parse_event_data(zbx_vector_ptr_t *events, zbx_uint64_t last_key, const char *xml, size_t len)
3228 {
3229 const char *__function_name = "vmware_service_parse_event_data";
3230
3231 zbx_vector_id_xmlnode_t ids;
3232 int i, parsed_num = 0;
3233 char *value;
3234 xmlDoc *doc;
3235 xmlXPathContext *xpathCtx;
3236 xmlXPathObject *xpathObj;
3237 xmlNodeSetPtr nodeset;
3238
3239 zabbix_log(LOG_LEVEL_DEBUG, "In %s() last_key:" ZBX_FS_UI64, __function_name, last_key);
3240
3241 if (NULL == (doc = xmlReadMemory(xml, len, ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
3242 {
3243 zabbix_log(LOG_LEVEL_DEBUG, "Cannot parse evenlog list.");
3244 goto out;
3245 }
3246
3247 xpathCtx = xmlXPathNewContext(doc);
3248
3249 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)"/*/*/*"ZBX_XPATH_LN("returnval"), xpathCtx)))
3250 {
3251 zabbix_log(LOG_LEVEL_DEBUG, "Cannot make evenlog list parsing query.");
3252 goto clean;
3253 }
3254
3255 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
3256 {
3257 zabbix_log(LOG_LEVEL_DEBUG, "Cannot find items in evenlog list.");
3258 goto clean;
3259 }
3260
3261 nodeset = xpathObj->nodesetval;
3262 zbx_vector_id_xmlnode_create(&ids);
3263 zbx_vector_id_xmlnode_reserve(&ids, nodeset->nodeNr);
3264
3265 for (i = 0; i < nodeset->nodeNr; i++)
3266 {
3267 zbx_id_xmlnode_t xml_event;
3268 zbx_uint64_t key;
3269
3270 if (NULL == (value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], ZBX_XPATH_NN("key"))))
3271 {
3272 zabbix_log(LOG_LEVEL_TRACE, "skipping eventlog record without key, xml number '%d'", i);
3273 continue;
3274 }
3275
3276 if (SUCCEED != is_uint64(value, &key))
3277 {
3278 zabbix_log(LOG_LEVEL_TRACE, "skipping eventlog key '%s', not a number", value);
3279 zbx_free(value);
3280 continue;
3281 }
3282
3283 zbx_free(value);
3284
3285 if (key <= last_key)
3286 {
3287 zabbix_log(LOG_LEVEL_TRACE, "skipping event key '" ZBX_FS_UI64 "', has been processed", key);
3288 continue;
3289 }
3290
3291 xml_event.id = key;
3292 xml_event.xml_node = nodeset->nodeTab[i];
3293 zbx_vector_id_xmlnode_append(&ids, xml_event);
3294 }
3295
3296 if (0 != ids.values_num)
3297 {
3298 zbx_vector_id_xmlnode_sort(&ids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3299 zbx_vector_ptr_reserve(events, ids.values_num + events->values_alloc);
3300
3301 /* we are reading "scrollable views" in reverse chronological order, */
3302 /* so inside a "scrollable view" latest events should come first too */
3303 for (i = ids.values_num - 1; i >= 0; i--)
3304 {
3305 if (SUCCEED == vmware_service_put_event_data(events, ids.values[i], doc))
3306 parsed_num++;
3307 }
3308 }
3309
3310 zbx_vector_id_xmlnode_destroy(&ids);
3311 clean:
3312 if (NULL != xpathObj)
3313 xmlXPathFreeObject(xpathObj);
3314
3315 xmlXPathFreeContext(xpathCtx);
3316 xmlFreeDoc(doc);
3317 out:
3318 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() parsed:%d", __function_name, parsed_num);
3319
3320 return parsed_num;
3321 }
3322
3323 /******************************************************************************
3324 * *
3325 * Function: vmware_service_get_event_data *
3326 * *
3327 * Purpose: retrieves event data *
3328 * *
3329 * Parameters: service - [IN] the vmware service *
3330 * easyhandle - [IN] the CURL handle *
3331 * events - [OUT] a pointer to the output variable *
3332 * error - [OUT] the error message in the case of failure *
3333 * *
3334 * Return value: SUCCEED - the operation has completed successfully *
3335 * FAIL - the operation has failed *
3336 * *
3337 ******************************************************************************/
vmware_service_get_event_data(const zbx_vmware_service_t * service,CURL * easyhandle,zbx_vector_ptr_t * events,char ** error)3338 static int vmware_service_get_event_data(const zbx_vmware_service_t *service, CURL *easyhandle,
3339 zbx_vector_ptr_t *events, char **error)
3340 {
3341 const char *__function_name = "vmware_service_get_event_data";
3342
3343 char *event_session = NULL;
3344 int ret = FAIL, soap_count = 5; /* 10 - initial value of eventlog records number in one response */
3345 zbx_uint64_t eventlog_last_key;
3346
3347
3348 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3349
3350 if (SUCCEED != vmware_service_get_event_session(service, easyhandle, &event_session, error))
3351 goto out;
3352
3353 if (SUCCEED != vmware_service_reset_event_history_collector(easyhandle, event_session, error))
3354 goto end_session;
3355
3356 if (NULL != service->data && 0 != service->data->events.values_num &&
3357 ((const zbx_vmware_event_t *)service->data->events.values[0])->key > service->eventlog_last_key)
3358 {
3359 eventlog_last_key = ((const zbx_vmware_event_t *)service->data->events.values[0])->key;
3360 }
3361 else
3362 eventlog_last_key = service->eventlog_last_key;
3363
3364 do
3365 {
3366 if ((ZBX_MAXQUERYMETRICS_UNLIMITED / 2) >= soap_count)
3367 soap_count = soap_count * 2;
3368 else if (ZBX_MAXQUERYMETRICS_UNLIMITED != soap_count)
3369 soap_count = ZBX_MAXQUERYMETRICS_UNLIMITED;
3370
3371 if (0 != events->values_num &&
3372 (((const zbx_vmware_event_t *)events->values[events->values_num - 1])->key -
3373 eventlog_last_key -1) < (unsigned int)soap_count)
3374 {
3375 soap_count = ((const zbx_vmware_event_t *)events->values[events->values_num - 1])->key -
3376 eventlog_last_key - 1;
3377 }
3378
3379 if (SUCCEED != vmware_service_read_previous_events(easyhandle, event_session, soap_count, error))
3380 goto end_session;
3381 }
3382 while (0 < vmware_service_parse_event_data(events, eventlog_last_key, page.data, page.offset));
3383
3384 ret = SUCCEED;
3385 end_session:
3386 if (SUCCEED != vmware_service_destroy_event_session(easyhandle, event_session, error))
3387 ret = FAIL;
3388 out:
3389 zbx_free(event_session);
3390
3391 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3392
3393 return ret;
3394 }
3395
3396 /******************************************************************************
3397 * *
3398 * Function: vmware_service_get_clusters *
3399 * *
3400 * Purpose: retrieves a list of vmware service clusters *
3401 * *
3402 * Parameters: service - [IN] the vmware service *
3403 * easyhandle - [IN] the CURL handle *
3404 * clusters - [OUT] a pointer to the output variable *
3405 * error - [OUT] the error message in the case of failure *
3406 * *
3407 * Return value: SUCCEED - the operation has completed successfully *
3408 * FAIL - the operation has failed *
3409 * *
3410 ******************************************************************************/
vmware_service_get_clusters(const zbx_vmware_service_t * service,CURL * easyhandle,char ** clusters,char ** error)3411 static int vmware_service_get_clusters(const zbx_vmware_service_t *service, CURL *easyhandle, char **clusters,
3412 char **error)
3413 {
3414 # define ZBX_POST_VCENTER_CLUSTER \
3415 ZBX_POST_VSPHERE_HEADER \
3416 "<ns0:RetrievePropertiesEx xsi:type=\"ns0:RetrievePropertiesExRequestType\">" \
3417 "<ns0:_this type=\"PropertyCollector\">propertyCollector</ns0:_this>" \
3418 "<ns0:specSet>" \
3419 "<ns0:propSet>" \
3420 "<ns0:type>ClusterComputeResource</ns0:type>" \
3421 "<ns0:pathSet>name</ns0:pathSet>" \
3422 "</ns0:propSet>" \
3423 "<ns0:objectSet>" \
3424 "<ns0:obj type=\"Folder\">group-d1</ns0:obj>" \
3425 "<ns0:skip>false</ns0:skip>" \
3426 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3427 "<ns0:name>visitFolders</ns0:name>" \
3428 "<ns0:type>Folder</ns0:type>" \
3429 "<ns0:path>childEntity</ns0:path>" \
3430 "<ns0:skip>false</ns0:skip>" \
3431 "<ns0:selectSet>" \
3432 "<ns0:name>visitFolders</ns0:name>" \
3433 "</ns0:selectSet>" \
3434 "<ns0:selectSet>" \
3435 "<ns0:name>dcToHf</ns0:name>" \
3436 "</ns0:selectSet>" \
3437 "<ns0:selectSet>" \
3438 "<ns0:name>dcToVmf</ns0:name>" \
3439 "</ns0:selectSet>" \
3440 "<ns0:selectSet>" \
3441 "<ns0:name>crToH</ns0:name>" \
3442 "</ns0:selectSet>" \
3443 "<ns0:selectSet>" \
3444 "<ns0:name>crToRp</ns0:name>" \
3445 "</ns0:selectSet>" \
3446 "<ns0:selectSet>" \
3447 "<ns0:name>dcToDs</ns0:name>" \
3448 "</ns0:selectSet>" \
3449 "<ns0:selectSet>" \
3450 "<ns0:name>hToVm</ns0:name>" \
3451 "</ns0:selectSet>" \
3452 "<ns0:selectSet>" \
3453 "<ns0:name>rpToVm</ns0:name>" \
3454 "</ns0:selectSet>" \
3455 "</ns0:selectSet>" \
3456 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3457 "<ns0:name>dcToVmf</ns0:name>" \
3458 "<ns0:type>Datacenter</ns0:type>" \
3459 "<ns0:path>vmFolder</ns0:path>" \
3460 "<ns0:skip>false</ns0:skip>" \
3461 "<ns0:selectSet>" \
3462 "<ns0:name>visitFolders</ns0:name>" \
3463 "</ns0:selectSet>" \
3464 "</ns0:selectSet>" \
3465 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3466 "<ns0:name>dcToDs</ns0:name>" \
3467 "<ns0:type>Datacenter</ns0:type>" \
3468 "<ns0:path>datastore</ns0:path>" \
3469 "<ns0:skip>false</ns0:skip>" \
3470 "<ns0:selectSet>" \
3471 "<ns0:name>visitFolders</ns0:name>" \
3472 "</ns0:selectSet>" \
3473 "</ns0:selectSet>" \
3474 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3475 "<ns0:name>dcToHf</ns0:name>" \
3476 "<ns0:type>Datacenter</ns0:type>" \
3477 "<ns0:path>hostFolder</ns0:path>" \
3478 "<ns0:skip>false</ns0:skip>" \
3479 "<ns0:selectSet>" \
3480 "<ns0:name>visitFolders</ns0:name>" \
3481 "</ns0:selectSet>" \
3482 "</ns0:selectSet>" \
3483 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3484 "<ns0:name>crToH</ns0:name>" \
3485 "<ns0:type>ComputeResource</ns0:type>" \
3486 "<ns0:path>host</ns0:path>" \
3487 "<ns0:skip>false</ns0:skip>" \
3488 "</ns0:selectSet>" \
3489 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3490 "<ns0:name>crToRp</ns0:name>" \
3491 "<ns0:type>ComputeResource</ns0:type>" \
3492 "<ns0:path>resourcePool</ns0:path>" \
3493 "<ns0:skip>false</ns0:skip>" \
3494 "<ns0:selectSet>" \
3495 "<ns0:name>rpToRp</ns0:name>" \
3496 "</ns0:selectSet>" \
3497 "<ns0:selectSet>" \
3498 "<ns0:name>rpToVm</ns0:name>" \
3499 "</ns0:selectSet>" \
3500 "</ns0:selectSet>" \
3501 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3502 "<ns0:name>rpToRp</ns0:name>" \
3503 "<ns0:type>ResourcePool</ns0:type>" \
3504 "<ns0:path>resourcePool</ns0:path>" \
3505 "<ns0:skip>false</ns0:skip>" \
3506 "<ns0:selectSet>" \
3507 "<ns0:name>rpToRp</ns0:name>" \
3508 "</ns0:selectSet>" \
3509 "<ns0:selectSet>" \
3510 "<ns0:name>rpToVm</ns0:name>" \
3511 "</ns0:selectSet>" \
3512 "</ns0:selectSet>" \
3513 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3514 "<ns0:name>hToVm</ns0:name>" \
3515 "<ns0:type>HostSystem</ns0:type>" \
3516 "<ns0:path>vm</ns0:path>" \
3517 "<ns0:skip>false</ns0:skip>" \
3518 "<ns0:selectSet>" \
3519 "<ns0:name>visitFolders</ns0:name>" \
3520 "</ns0:selectSet>" \
3521 "</ns0:selectSet>" \
3522 "<ns0:selectSet xsi:type=\"ns0:TraversalSpec\">" \
3523 "<ns0:name>rpToVm</ns0:name>" \
3524 "<ns0:type>ResourcePool</ns0:type>" \
3525 "<ns0:path>vm</ns0:path>" \
3526 "<ns0:skip>false</ns0:skip>" \
3527 "</ns0:selectSet>" \
3528 "</ns0:objectSet>" \
3529 "</ns0:specSet>" \
3530 "<ns0:options/>" \
3531 "</ns0:RetrievePropertiesEx>" \
3532 ZBX_POST_VSPHERE_FOOTER
3533
3534 const char *__function_name = "vmware_service_get_clusters";
3535
3536 int err, o, ret = FAIL;
3537
3538 ZBX_UNUSED(service);
3539
3540 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3541
3542 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, o = CURLOPT_POSTFIELDS, ZBX_POST_VCENTER_CLUSTER)))
3543 {
3544 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", o, curl_easy_strerror(err));
3545 goto out;
3546 }
3547
3548 page.offset = 0;
3549
3550 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3551 {
3552 *error = zbx_strdup(*error, curl_easy_strerror(err));
3553 goto out;
3554 }
3555
3556 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
3557
3558 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3559 goto out;
3560
3561 *clusters = zbx_strdup(*clusters, page.data);
3562
3563 ret = SUCCEED;
3564 out:
3565 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3566
3567 return ret;
3568 }
3569
3570 /******************************************************************************
3571 * *
3572 * Function: vmware_service_get_cluster_status *
3573 * *
3574 * Purpose: retrieves status of the specified vmware cluster *
3575 * *
3576 * Parameters: service - [IN] the vmware service *
3577 * easyhandle - [IN] the CURL handle *
3578 * clusterid - [IN] the cluster id *
3579 * status - [OUT] a pointer to the output variable *
3580 * error - [OUT] the error message in the case of failure *
3581 * *
3582 * Return value: SUCCEED - the operation has completed successfully *
3583 * FAIL - the operation has failed *
3584 * *
3585 ******************************************************************************/
vmware_service_get_cluster_status(const zbx_vmware_service_t * service,CURL * easyhandle,const char * clusterid,char ** status,char ** error)3586 static int vmware_service_get_cluster_status(const zbx_vmware_service_t *service, CURL *easyhandle,
3587 const char *clusterid, char **status, char **error)
3588 {
3589 # define ZBX_POST_VMWARE_CLUSTER_STATUS \
3590 ZBX_POST_VSPHERE_HEADER \
3591 "<ns0:RetrievePropertiesEx>" \
3592 "<ns0:_this type=\"PropertyCollector\">propertyCollector</ns0:_this>" \
3593 "<ns0:specSet>" \
3594 "<ns0:propSet>" \
3595 "<ns0:type>ClusterComputeResource</ns0:type>" \
3596 "<ns0:all>false</ns0:all>" \
3597 "<ns0:pathSet>summary</ns0:pathSet>" \
3598 "</ns0:propSet>" \
3599 "<ns0:objectSet>" \
3600 "<ns0:obj type=\"ClusterComputeResource\">%s</ns0:obj>" \
3601 "</ns0:objectSet>" \
3602 "</ns0:specSet>" \
3603 "<ns0:options></ns0:options>" \
3604 "</ns0:RetrievePropertiesEx>" \
3605 ZBX_POST_VSPHERE_FOOTER
3606
3607 const char *__function_name = "vmware_service_get_cluster_status";
3608
3609 char tmp[MAX_STRING_LEN], *clusterid_esc;
3610 int err, o, ret = FAIL;
3611
3612 ZBX_UNUSED(service);
3613
3614 zabbix_log(LOG_LEVEL_DEBUG, "In %s() clusterid:'%s'", __function_name, clusterid);
3615
3616 clusterid_esc = xml_escape_dyn(clusterid);
3617
3618 zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_CLUSTER_STATUS, clusterid_esc);
3619
3620 zbx_free(clusterid_esc);
3621
3622 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, o = CURLOPT_POSTFIELDS, tmp)))
3623 {
3624 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", o, curl_easy_strerror(err));
3625 goto out;
3626 }
3627
3628 page.offset = 0;
3629
3630 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3631 {
3632 *error = zbx_strdup(*error, curl_easy_strerror(err));
3633 goto out;
3634 }
3635
3636 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
3637
3638 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3639 goto out;
3640
3641 *status = zbx_strdup(NULL, page.data);
3642
3643 ret = SUCCEED;
3644 out:
3645 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3646
3647 return ret;
3648 }
3649
3650 /******************************************************************************
3651 * *
3652 * Function: vmware_service_get_cluster_list *
3653 * *
3654 * Purpose: creates list of vmware cluster objects *
3655 * *
3656 * Parameters: service - [IN] the vmware service *
3657 * easyhandle - [IN] the CURL handle *
3658 * clusters - [OUT] a pointer to the resulting cluster vector *
3659 * error - [OUT] the error message in the case of failure *
3660 * *
3661 * Return value: SUCCEED - the operation has completed successfully *
3662 * FAIL - the operation has failed *
3663 * *
3664 ******************************************************************************/
vmware_service_get_cluster_list(const zbx_vmware_service_t * service,CURL * easyhandle,zbx_vector_ptr_t * clusters,char ** error)3665 static int vmware_service_get_cluster_list(const zbx_vmware_service_t *service, CURL *easyhandle,
3666 zbx_vector_ptr_t *clusters, char **error)
3667 {
3668 const char *__function_name = "vmware_service_get_cluster_list";
3669
3670 char *cluster_data = NULL, xpath[MAX_STRING_LEN], *name;
3671 zbx_vector_str_t ids;
3672 zbx_vmware_cluster_t *cluster;
3673 int i, ret = FAIL;
3674
3675 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3676
3677 zbx_vector_str_create(&ids);
3678
3679 if (SUCCEED != vmware_service_get_clusters(service, easyhandle, &cluster_data, error))
3680 goto out;
3681
3682 zbx_xml_read_values(cluster_data, "//*[@type='ClusterComputeResource']", &ids);
3683
3684 for (i = 0; i < ids.values_num; i++)
3685 {
3686 char *status;
3687
3688 zbx_snprintf(xpath, sizeof(xpath), "//*[@type='ClusterComputeResource'][.='%s']"
3689 "/.." ZBX_XPATH_LN2("propSet", "val"), ids.values[i]);
3690
3691 if (NULL == (name = zbx_xml_read_value(cluster_data, xpath)))
3692 continue;
3693
3694 if (SUCCEED != vmware_service_get_cluster_status(service, easyhandle, ids.values[i], &status, error))
3695 {
3696 zbx_free(name);
3697 goto out;
3698 }
3699
3700 cluster = zbx_malloc(NULL, sizeof(zbx_vmware_cluster_t));
3701 cluster->id = zbx_strdup(NULL, ids.values[i]);
3702 cluster->name = name;
3703 cluster->status = status;
3704
3705 zbx_vector_ptr_append(clusters, cluster);
3706 }
3707
3708 ret = SUCCEED;
3709 out:
3710 zbx_free(cluster_data);
3711 zbx_vector_str_clear_ext(&ids, zbx_ptr_free);
3712 zbx_vector_str_destroy(&ids);
3713
3714 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s found:%d", __function_name, zbx_result_string(ret),
3715 clusters->values_num);
3716
3717 return ret;
3718 }
3719
3720 /******************************************************************************
3721 * *
3722 * Function: vmware_service_get_maxquerymetrics *
3723 * *
3724 * Purpose: get vpxd.stats.maxquerymetrics parameter from vcenter only *
3725 * *
3726 * Parameters: easyhandle - [IN] the CURL handle *
3727 * max_qm - [OUT] max count of Datastore metrics in one *
3728 * request *
3729 * error - [OUT] the error message in the case of failure *
3730 * *
3731 * Return value: SUCCEED - the operation has completed successfully *
3732 * FAIL - the operation has failed *
3733 * *
3734 ******************************************************************************/
vmware_service_get_maxquerymetrics(CURL * easyhandle,int * max_qm,char ** error)3735 static int vmware_service_get_maxquerymetrics(CURL *easyhandle, int *max_qm, char **error)
3736 {
3737 # define ZBX_POST_MAXQUERYMETRICS \
3738 ZBX_POST_VSPHERE_HEADER \
3739 "<ns0:QueryOptions>" \
3740 "<ns0:_this type=\"OptionManager\">VpxSettings</ns0:_this>" \
3741 "<ns0:name>config.vpxd.stats.maxQueryMetrics</ns0:name>" \
3742 "</ns0:QueryOptions>" \
3743 ZBX_POST_VSPHERE_FOOTER
3744
3745 const char *__function_name = "vmware_service_get_maxquerymetrics";
3746
3747 CURLoption opt;
3748 CURLcode err;
3749 int ret = FAIL;
3750 char *val;
3751
3752 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3753
3754 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, ZBX_POST_MAXQUERYMETRICS)))
3755 {
3756 *error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
3757 goto out;
3758 }
3759
3760 page.offset = 0;
3761
3762 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
3763 {
3764 *error = zbx_strdup(*error, curl_easy_strerror(err));
3765 goto out;
3766 }
3767
3768 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
3769
3770 if (NULL != (*error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
3771 {
3772 zabbix_log(LOG_LEVEL_WARNING, "Error of query maxQueryMetrics: %s.", *error);
3773 zbx_free(*error);
3774 }
3775
3776 ret = SUCCEED;
3777
3778 if (NULL == (val = zbx_xml_read_value(page.data, ZBX_XPATH_MAXQUERYMETRICS())))
3779 {
3780 *max_qm = ZBX_VPXD_STATS_MAXQUERYMETRICS;
3781 zabbix_log(LOG_LEVEL_DEBUG, "maxQueryMetrics used default value %d", ZBX_VPXD_STATS_MAXQUERYMETRICS);
3782 goto out;
3783 }
3784
3785 /* vmware article 2107096 */
3786 /* Edit the config.vpxd.stats.maxQueryMetrics key in the advanced settings of vCenter Server */
3787 /* To disable the limit, set a value to -1 */
3788 /* Edit the web.xml file. To disable the limit, set a value 0 */
3789 if (-1 == atoi(val))
3790 {
3791 *max_qm = ZBX_MAXQUERYMETRICS_UNLIMITED;
3792 }
3793 else if (SUCCEED != is_uint31(val, max_qm))
3794 {
3795 zabbix_log(LOG_LEVEL_DEBUG, "Cannot convert maxQueryMetrics from %s.", val);
3796 *max_qm = ZBX_VPXD_STATS_MAXQUERYMETRICS;
3797 }
3798 else if (0 == *max_qm)
3799 {
3800 *max_qm = ZBX_MAXQUERYMETRICS_UNLIMITED;
3801 }
3802
3803 zbx_free(val);
3804 out:
3805 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
3806
3807 return ret;
3808 }
3809 /******************************************************************************
3810 * *
3811 * Function: vmware_counters_add_new *
3812 * *
3813 * Purpose: creates a new performance counter object in shared memory and *
3814 * adds to the specified vector *
3815 * *
3816 * Parameters: counters - [IN/OUT] the vector the created performance *
3817 * counter object should be added to *
3818 * counterid - [IN] the performance counter id *
3819 * *
3820 ******************************************************************************/
vmware_counters_add_new(zbx_vector_ptr_t * counters,zbx_uint64_t counterid)3821 static void vmware_counters_add_new(zbx_vector_ptr_t *counters, zbx_uint64_t counterid)
3822 {
3823 zbx_vmware_perf_counter_t *counter;
3824
3825 counter = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_perf_counter_t));
3826 counter->counterid = counterid;
3827 counter->state = ZBX_VMWARE_COUNTER_NEW;
3828
3829 zbx_vector_ptr_pair_create_ext(&counter->values, __vm_mem_malloc_func, __vm_mem_realloc_func,
3830 __vm_mem_free_func);
3831
3832 zbx_vector_ptr_append(counters, counter);
3833 }
3834
3835 /******************************************************************************
3836 * *
3837 * Function: vmware_service_initialize *
3838 * *
3839 * Purpose: initializes vmware service object *
3840 * *
3841 * Parameters: service - [IN] the vmware service *
3842 * easyhandle - [IN] the CURL handle *
3843 * error - [OUT] the error message in the case of failure *
3844 * *
3845 * Return value: SUCCEED - the operation has completed successfully *
3846 * FAIL - the operation has failed *
3847 * *
3848 * Comments: While the service object can't be accessed from other processes *
3849 * during initialization it's still processed outside vmware locks *
3850 * and therefore must not allocate/free shared memory. *
3851 * *
3852 ******************************************************************************/
vmware_service_initialize(zbx_vmware_service_t * service,CURL * easyhandle,char ** error)3853 static int vmware_service_initialize(zbx_vmware_service_t *service, CURL *easyhandle, char **error)
3854 {
3855 char *contents = NULL;
3856 zbx_vector_ptr_t counters;
3857 int ret = FAIL;
3858
3859 zbx_vector_ptr_create(&counters);
3860
3861 if (SUCCEED != vmware_service_get_perf_counters(service, easyhandle, &counters, error))
3862 goto out;
3863
3864 if (SUCCEED != vmware_service_get_contents(service, easyhandle, &contents, error))
3865 goto out;
3866
3867 zbx_vmware_lock();
3868
3869 service->contents = vmware_shared_strdup(contents);
3870 vmware_counters_shared_copy(&service->counters, &counters);
3871
3872 zbx_vmware_unlock();
3873
3874 ret = SUCCEED;
3875 out:
3876 zbx_free(contents);
3877
3878 zbx_vector_ptr_clear_ext(&counters, (zbx_mem_free_func_t)vmware_counter_free);
3879 zbx_vector_ptr_destroy(&counters);
3880
3881 return ret;
3882 }
3883
3884 /******************************************************************************
3885 * *
3886 * Function: vmware_service_add_perf_entity *
3887 * *
3888 * Purpose: adds entity to vmware service performance entity list *
3889 * *
3890 * Parameters: service - [IN] the vmware service *
3891 * type - [IN] the performance entity type (HostSystem, *
3892 * (Datastore, VirtualMachine...) *
3893 * id - [IN] the performance entity id *
3894 * counters - [IN] NULL terminated list of performance counters *
3895 * to be monitored for this entity *
3896 * instance - [IN] the performance counter instance name *
3897 * now - [IN] the current timestamp *
3898 * *
3899 * Comments: The performance counters are specified by their path: *
3900 * <group>/<key>[<rollup type>] *
3901 * *
3902 ******************************************************************************/
vmware_service_add_perf_entity(zbx_vmware_service_t * service,const char * type,const char * id,const char ** counters,const char * instance,int now)3903 static void vmware_service_add_perf_entity(zbx_vmware_service_t *service, const char *type, const char *id,
3904 const char **counters, const char *instance, int now)
3905 {
3906 const char *__function_name = "vmware_service_add_perf_entity";
3907
3908 zbx_vmware_perf_entity_t entity, *pentity;
3909 zbx_uint64_t counterid;
3910 int i;
3911
3912 zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s", __function_name, type, id);
3913
3914 if (NULL == (pentity = zbx_vmware_service_get_perf_entity(service, type, id)))
3915 {
3916 entity.type = vmware_shared_strdup(type);
3917 entity.id = vmware_shared_strdup(id);
3918
3919 pentity = zbx_hashset_insert(&service->entities, &entity, sizeof(zbx_vmware_perf_entity_t));
3920
3921 zbx_vector_ptr_create_ext(&pentity->counters, __vm_mem_malloc_func, __vm_mem_realloc_func,
3922 __vm_mem_free_func);
3923
3924 for (i = 0; NULL != counters[i]; i++)
3925 {
3926 if (SUCCEED == zbx_vmware_service_get_counterid(service, counters[i], &counterid))
3927 vmware_counters_add_new(&pentity->counters, counterid);
3928 else
3929 zabbix_log(LOG_LEVEL_DEBUG, "cannot find performance counter %s", counters[i]);
3930 }
3931
3932 zbx_vector_ptr_sort(&pentity->counters, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3933 pentity->refresh = ZBX_VMWARE_PERF_INTERVAL_UNKNOWN;
3934 pentity->query_instance = vmware_shared_strdup(instance);
3935 pentity->error = NULL;
3936 }
3937
3938 pentity->last_seen = now;
3939
3940 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() perfcounters:%d", __function_name, pentity->counters.values_num);
3941 }
3942
3943 /******************************************************************************
3944 * *
3945 * Function: vmware_service_update_perf_entities *
3946 * *
3947 * Purpose: adds new or remove old entities (hypervisors, virtual machines) *
3948 * from service performance entity list *
3949 * *
3950 * Parameters: service - [IN] the vmware service *
3951 * *
3952 ******************************************************************************/
vmware_service_update_perf_entities(zbx_vmware_service_t * service)3953 static void vmware_service_update_perf_entities(zbx_vmware_service_t *service)
3954 {
3955 const char *__function_name = "vmware_service_update_perf_entities";
3956
3957 int i;
3958 zbx_vmware_hv_t *hv;
3959 zbx_vmware_vm_t *vm;
3960 zbx_hashset_iter_t iter;
3961
3962 const char *hv_perfcounters[] = {
3963 "net/packetsRx[summation]", "net/packetsTx[summation]",
3964 "net/received[average]", "net/transmitted[average]",
3965 "datastore/totalReadLatency[average]",
3966 "datastore/totalWriteLatency[average]", NULL
3967 };
3968 const char *vm_perfcounters[] = {
3969 "virtualDisk/read[average]", "virtualDisk/write[average]",
3970 "virtualDisk/numberReadAveraged[average]",
3971 "virtualDisk/numberWriteAveraged[average]",
3972 "net/packetsRx[summation]", "net/packetsTx[summation]",
3973 "net/received[average]", "net/transmitted[average]",
3974 "cpu/ready[summation]", NULL
3975 };
3976
3977 const char *ds_perfcounters[] = {
3978 "disk/used[latest]", "disk/provisioned[latest]",
3979 "disk/capacity[latest]", NULL
3980 };
3981
3982 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3983
3984 /* update current performance entities */
3985 zbx_hashset_iter_reset(&service->data->hvs, &iter);
3986 while (NULL != (hv = zbx_hashset_iter_next(&iter)))
3987 {
3988 vmware_service_add_perf_entity(service, "HostSystem", hv->id, hv_perfcounters, "*", service->lastcheck);
3989
3990 for (i = 0; i < hv->vms.values_num; i++)
3991 {
3992 vm = hv->vms.values[i];
3993 vmware_service_add_perf_entity(service, "VirtualMachine", vm->id, vm_perfcounters, "*",
3994 service->lastcheck);
3995 zabbix_log(LOG_LEVEL_TRACE, "%s() for type: VirtualMachine hv id: %s hv uuid: %s linked vm id:"
3996 " %s vm uuid: %s", __function_name, hv->id, hv->uuid, vm->id, vm->uuid);
3997 }
3998
3999 if (ZBX_VMWARE_TYPE_VSPHERE == service->type)
4000 continue;
4001
4002 for (i = 0; i < hv->datastores.values_num; i++)
4003 {
4004 zbx_vmware_datastore_t *ds = hv->datastores.values[i];
4005 vmware_service_add_perf_entity(service, "Datastore", ds->id, ds_perfcounters, "",
4006 service->lastcheck);
4007 zabbix_log(LOG_LEVEL_TRACE, "%s() for type: Datastore hv id: %s hv uuid: %s linked ds id:"
4008 " %s ds name: %s ds uuid: %s", __function_name, hv->id, hv->uuid, ds->id,
4009 ds->name, ds->uuid);
4010 }
4011 }
4012
4013 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() entities:%d", __function_name, service->entities.num_data);
4014 }
4015
4016 /******************************************************************************
4017 * *
4018 * Function: vmware_service_update *
4019 * *
4020 * Purpose: updates object with a new data from vmware service *
4021 * *
4022 * Parameters: service - [IN] the vmware service *
4023 * *
4024 ******************************************************************************/
vmware_service_update(zbx_vmware_service_t * service)4025 static void vmware_service_update(zbx_vmware_service_t *service)
4026 {
4027 const char *__function_name = "vmware_service_update";
4028
4029 CURL *easyhandle = NULL;
4030 struct curl_slist *headers = NULL;
4031 zbx_vmware_data_t *data;
4032 zbx_vector_str_t hvs;
4033 zbx_vector_ptr_t events;
4034 int opt, err, i, ret = FAIL;
4035
4036 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, service->username, service->url);
4037
4038 data = zbx_malloc(NULL, sizeof(zbx_vmware_data_t));
4039 memset(data, 0, sizeof(zbx_vmware_data_t));
4040
4041 zbx_hashset_create(&data->hvs, 1, vmware_hv_hash, vmware_hv_compare);
4042 zbx_vector_ptr_create(&data->clusters);
4043 zbx_vector_ptr_create(&data->events);
4044
4045 zbx_vector_str_create(&hvs);
4046
4047 if (NULL == (easyhandle = curl_easy_init()))
4048 {
4049 zabbix_log(LOG_LEVEL_WARNING, "Cannot initialize cURL library");
4050 goto out;
4051 }
4052
4053 headers = curl_slist_append(headers, ZBX_XML_HEADER1);
4054 headers = curl_slist_append(headers, ZBX_XML_HEADER2);
4055
4056 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPHEADER, headers)))
4057 {
4058 zabbix_log(LOG_LEVEL_WARNING, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
4059 goto clean;
4060 }
4061
4062 if (SUCCEED != vmware_service_authenticate(service, easyhandle, &data->error))
4063 goto clean;
4064
4065 if (0 != (service->state & ZBX_VMWARE_STATE_NEW) &&
4066 SUCCEED != vmware_service_initialize(service, easyhandle, &data->error))
4067 {
4068 goto clean;
4069 }
4070
4071 if (SUCCEED != vmware_service_get_hv_list(service, easyhandle, &hvs, &data->error))
4072 goto clean;
4073
4074 for (i = 0; i < hvs.values_num; i++)
4075 {
4076 zbx_vmware_hv_t hv_local;
4077
4078 if (SUCCEED == vmware_service_init_hv(service, easyhandle, hvs.values[i], &hv_local, &data->error))
4079 zbx_hashset_insert(&data->hvs, &hv_local, sizeof(hv_local));
4080 }
4081
4082 /* skip collection of event data if we don't know where we stopped last time or item can't accept values */
4083 if (ZBX_VMWARE_EVENT_KEY_UNINITIALIZED != service->eventlog_last_key &&
4084 SUCCEED != vmware_service_get_event_data(service, easyhandle, &data->events, &data->error))
4085 {
4086 goto clean;
4087 }
4088
4089 if (ZBX_VMWARE_TYPE_VCENTER == service->type &&
4090 SUCCEED != vmware_service_get_cluster_list(service, easyhandle, &data->clusters, &data->error))
4091 {
4092 goto clean;
4093 }
4094
4095 if (ZBX_VMWARE_TYPE_VCENTER != service->type)
4096 data->max_query_metrics = ZBX_VPXD_STATS_MAXQUERYMETRICS;
4097 else if (SUCCEED != vmware_service_get_maxquerymetrics(easyhandle, &data->max_query_metrics, &data->error))
4098 goto clean;
4099
4100 if (SUCCEED != vmware_service_logout(service, easyhandle, &data->error))
4101 {
4102 zabbix_log(LOG_LEVEL_DEBUG, "Cannot close vmware connection: %s.", data->error);
4103 zbx_free(data->error);
4104 }
4105
4106 ret = SUCCEED;
4107 clean:
4108 curl_slist_free_all(headers);
4109 curl_easy_cleanup(easyhandle);
4110
4111 zbx_vector_str_clear_ext(&hvs, zbx_ptr_free);
4112 zbx_vector_str_destroy(&hvs);
4113 out:
4114 zbx_vector_ptr_create(&events);
4115 zbx_vmware_lock();
4116
4117 /* remove UPDATING flag and set READY or FAILED flag */
4118 service->state &= ~(ZBX_VMWARE_STATE_MASK | ZBX_VMWARE_STATE_UPDATING);
4119 service->state |= (SUCCEED == ret) ? ZBX_VMWARE_STATE_READY : ZBX_VMWARE_STATE_FAILED;
4120
4121 if (NULL != service->data && 0 != service->data->events.values_num &&
4122 ((const zbx_vmware_event_t *)service->data->events.values[0])->key > service->eventlog_last_key)
4123 {
4124 zbx_vector_ptr_append_array(&events, service->data->events.values, service->data->events.values_num);
4125 zbx_vector_ptr_clear(&service->data->events);
4126 }
4127
4128 vmware_data_shared_free(service->data);
4129 service->data = vmware_data_shared_dup(data);
4130
4131 if (0 != events.values_num)
4132 zbx_vector_ptr_append_array(&service->data->events, events.values, events.values_num);
4133
4134 service->lastcheck = time(NULL);
4135
4136 vmware_service_update_perf_entities(service);
4137
4138 zbx_vmware_unlock();
4139
4140 vmware_data_free(data);
4141 zbx_vector_ptr_destroy(&events);
4142
4143 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
4144 }
4145
4146 /******************************************************************************
4147 * *
4148 * Function: vmware_service_process_perf_entity_data *
4149 * *
4150 * Purpose: updates vmware performance statistics data *
4151 * *
4152 * Parameters: pervalues - [OUT] the performance counter values *
4153 * doc - [IN] the XML document containing performance *
4154 * counter values for all entities *
4155 * node - [IN] the XML node containing performance counter *
4156 * values for the specified entity *
4157 * *
4158 * Return value: SUCCEED - the performance entity data was parsed *
4159 * FAIL - the perofmance entity data did not contain valid *
4160 * values *
4161 * *
4162 ******************************************************************************/
vmware_service_process_perf_entity_data(zbx_vector_ptr_t * pervalues,xmlDoc * doc,xmlNode * node)4163 static int vmware_service_process_perf_entity_data(zbx_vector_ptr_t *pervalues, xmlDoc *doc, xmlNode *node)
4164 {
4165 const char *__function_name = "vmware_service_process_perf_entity_data";
4166
4167 xmlXPathContext *xpathCtx;
4168 xmlXPathObject *xpathObj;
4169 xmlNodeSetPtr nodeset;
4170 char *instance, *counter, *value;
4171 int i, values = 0, ret = FAIL;
4172 zbx_vmware_perf_value_t *perfvalue;
4173
4174 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4175
4176 xpathCtx = xmlXPathNewContext(doc);
4177 xpathCtx->node = node;
4178
4179 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)"*[local-name()='value']", xpathCtx)))
4180 goto out;
4181
4182 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
4183 goto out;
4184
4185 nodeset = xpathObj->nodesetval;
4186
4187 for (i = 0; i < nodeset->nodeNr; i++)
4188 {
4189 value = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='value'][last()]");
4190 instance = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='id']"
4191 "/*[local-name()='instance']");
4192 counter = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='id']"
4193 "/*[local-name()='counterId']");
4194
4195 if (NULL != value && NULL != counter)
4196 {
4197 perfvalue = zbx_malloc(NULL, sizeof(zbx_vmware_perf_value_t));
4198
4199 ZBX_STR2UINT64(perfvalue->counterid, counter);
4200 perfvalue->instance = (NULL != instance ? instance : zbx_strdup(NULL, ""));
4201 perfvalue->value = value;
4202
4203 zbx_vector_ptr_append(pervalues, perfvalue);
4204
4205 if (FAIL == ret && 0 != strcmp(value, "-1"))
4206 ret = SUCCEED;
4207
4208 instance = NULL;
4209 value = NULL;
4210 }
4211
4212 zbx_free(counter);
4213 zbx_free(instance);
4214 zbx_free(value);
4215 }
4216
4217 out:
4218 if (NULL != xpathObj)
4219 xmlXPathFreeObject(xpathObj);
4220
4221 xmlXPathFreeContext(xpathCtx);
4222
4223 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() values:%d", __function_name, values);
4224
4225 return ret;
4226 }
4227
4228 /******************************************************************************
4229 * *
4230 * Function: vmware_service_parse_perf_data *
4231 * *
4232 * Purpose: updates vmware performance statistics data *
4233 * *
4234 * Parameters: perfdata - [OUT] performance entity data *
4235 * data - [IN] the performance data *
4236 * *
4237 ******************************************************************************/
vmware_service_parse_perf_data(zbx_vector_ptr_t * perfdata,const char * xml)4238 static void vmware_service_parse_perf_data(zbx_vector_ptr_t *perfdata, const char *xml)
4239 {
4240 const char *__function_name = "vmware_service_parse_perf_data";
4241
4242 xmlDoc *doc;
4243 xmlXPathContext *xpathCtx;
4244 xmlXPathObject *xpathObj;
4245 xmlNodeSetPtr nodeset;
4246 int i;
4247
4248 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4249
4250 if (NULL == (doc = xmlReadMemory(xml, strlen(xml), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
4251 goto out;
4252
4253 xpathCtx = xmlXPathNewContext(doc);
4254
4255 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)"/*/*/*/*", xpathCtx)))
4256 goto clean;
4257
4258 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
4259 goto clean;
4260
4261 nodeset = xpathObj->nodesetval;
4262
4263 for (i = 0; i < nodeset->nodeNr; i++)
4264 {
4265 zbx_vmware_perf_data_t *data;
4266 int ret = FAIL;
4267
4268 data = zbx_malloc(NULL, sizeof(zbx_vmware_perf_data_t));
4269
4270 data->id = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']");
4271 data->type = zbx_xml_read_node_value(doc, nodeset->nodeTab[i], "*[local-name()='entity']/@type");
4272 data->error = NULL;
4273 zbx_vector_ptr_create(&data->values);
4274
4275 if (NULL != data->type && NULL != data->id)
4276 ret = vmware_service_process_perf_entity_data(&data->values, doc, nodeset->nodeTab[i]);
4277
4278 if (SUCCEED == ret)
4279 zbx_vector_ptr_append(perfdata, data);
4280 else
4281 vmware_free_perfdata(data);
4282 }
4283 clean:
4284 if (NULL != xpathObj)
4285 xmlXPathFreeObject(xpathObj);
4286
4287 xmlXPathFreeContext(xpathCtx);
4288 xmlFreeDoc(doc);
4289 out:
4290 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4291 }
4292
4293 /******************************************************************************
4294 * *
4295 * Function: vmware_perf_data_add_error *
4296 * *
4297 * Purpose: adds error for the specified perf entity *
4298 * *
4299 * Parameters: perfdata - [OUT] the collected performance counter data *
4300 * type - [IN] the performance entity type (HostSystem, *
4301 * (Datastore, VirtualMachine...) *
4302 * id - [IN] the performance entity id *
4303 * error - [IN] the error to add *
4304 * instance - [IN] the performance counter instance name *
4305 * now - [IN] the current timestamp *
4306 * *
4307 * Comments: The performance counters are specified by their path: *
4308 * <group>/<key>[<rollup type>] *
4309 * *
4310 ******************************************************************************/
vmware_perf_data_add_error(zbx_vector_ptr_t * perfdata,const char * type,const char * id,const char * error)4311 static void vmware_perf_data_add_error(zbx_vector_ptr_t *perfdata, const char *type, const char *id,
4312 const char *error)
4313 {
4314 zbx_vmware_perf_data_t *data;
4315
4316 data = zbx_malloc(NULL, sizeof(zbx_vmware_perf_data_t));
4317
4318 data->type = zbx_strdup(NULL, type);
4319 data->id = zbx_strdup(NULL, id);
4320 data->error = zbx_strdup(NULL, error);
4321 zbx_vector_ptr_create(&data->values);
4322
4323 zbx_vector_ptr_append(perfdata, data);
4324 }
4325
4326 /******************************************************************************
4327 * *
4328 * Function: vmware_service_parse_perf_data *
4329 * *
4330 * Purpose: updates vmware performance statistics data *
4331 * *
4332 * Parameters: service - [IN] the vmware service *
4333 * perfdata - [IN] the performance data *
4334 * *
4335 ******************************************************************************/
vmware_service_copy_perf_data(zbx_vmware_service_t * service,zbx_vector_ptr_t * perfdata)4336 static void vmware_service_copy_perf_data(zbx_vmware_service_t *service, zbx_vector_ptr_t *perfdata)
4337 {
4338 const char *__function_name = "vmware_service_copy_perf_data";
4339
4340 int i, j, index;
4341 zbx_vmware_perf_data_t *data;
4342 zbx_vmware_perf_value_t *value;
4343 zbx_vmware_perf_entity_t *entity;
4344 zbx_vmware_perf_counter_t *perfcounter;
4345 zbx_ptr_pair_t perfvalue;
4346
4347 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4348
4349 for (i = 0; i < perfdata->values_num; i++)
4350 {
4351 data = (zbx_vmware_perf_data_t *)perfdata->values[i];
4352
4353 if (NULL == (entity = zbx_vmware_service_get_perf_entity(service, data->type, data->id)))
4354 continue;
4355
4356 if (NULL != data->error)
4357 {
4358 entity->error = vmware_shared_strdup(data->error);
4359 continue;
4360 }
4361
4362 for (j = 0; j < data->values.values_num; j++)
4363 {
4364 value = (zbx_vmware_perf_value_t *)data->values.values[j];
4365
4366 if (FAIL == (index = zbx_vector_ptr_bsearch(&entity->counters, &value->counterid,
4367 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4368 {
4369 continue;
4370 }
4371
4372 perfcounter = (zbx_vmware_perf_counter_t *)entity->counters.values[index];
4373
4374 perfvalue.first = vmware_shared_strdup(value->instance);
4375 perfvalue.second = vmware_shared_strdup(value->value);
4376
4377 zbx_vector_ptr_pair_append_ptr(&perfcounter->values, &perfvalue);
4378 }
4379 }
4380
4381 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4382 }
4383
4384 /******************************************************************************
4385 * *
4386 * Function: vmware_service_retrieve_perf_counters *
4387 * *
4388 * Purpose: retrieves performance counter values from vmware service *
4389 * *
4390 * Parameters: service - [IN] the vmware service *
4391 * easyhandle - [IN] prepared cURL connection handle *
4392 * entities - [IN] the performance collector entities to *
4393 * retrieve counters for *
4394 * counters_max - [IN] the maximum number of counters per query. *
4395 * perfdata - [OUT] the performance counter values *
4396 * *
4397 ******************************************************************************/
vmware_service_retrieve_perf_counters(zbx_vmware_service_t * service,CURL * easyhandle,zbx_vector_ptr_t * entities,int counters_max,zbx_vector_ptr_t * perfdata)4398 static void vmware_service_retrieve_perf_counters(zbx_vmware_service_t *service, CURL *easyhandle,
4399 zbx_vector_ptr_t *entities, int counters_max, zbx_vector_ptr_t *perfdata)
4400 {
4401 const char *__function_name = "vmware_service_retrieve_perf_counters";
4402
4403 char *tmp = NULL, *error = NULL;
4404 size_t tmp_alloc = 0, tmp_offset;
4405 int i, j, err, opt, start_counter = 0;
4406 zbx_vmware_perf_entity_t *entity;
4407
4408 zabbix_log(LOG_LEVEL_DEBUG, "In %s() counters_max:%d", __function_name, counters_max);
4409
4410 while (0 != entities->values_num)
4411 {
4412 int counters_num = 0;
4413
4414 tmp_offset = 0;
4415 zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, ZBX_POST_VSPHERE_HEADER);
4416 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:QueryPerf>"
4417 "<ns0:_this type=\"PerformanceManager\">%s</ns0:_this>",
4418 vmware_service_objects[service->type].performance_manager);
4419
4420 zbx_vmware_lock();
4421
4422 for (i = entities->values_num - 1; 0 <= i && counters_num < counters_max;)
4423 {
4424 char *id_esc;
4425
4426 entity = (zbx_vmware_perf_entity_t *)entities->values[i];
4427
4428 id_esc = xml_escape_dyn(entity->id);
4429
4430 /* add entity performance counter request */
4431 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:querySpec>"
4432 "<ns0:entity type=\"%s\">%s</ns0:entity>", entity->type, id_esc);
4433
4434 zbx_free(id_esc);
4435
4436 if (ZBX_VMWARE_PERF_INTERVAL_NONE == entity->refresh)
4437 {
4438 time_t st_raw;
4439 struct tm st;
4440 char st_str[ZBX_XML_DATETIME];
4441
4442 /* add startTime for entity performance counter request for decrease XML data load */
4443 st_raw = zbx_time() - SEC_PER_HOUR;
4444 gmtime_r(&st_raw, &st);
4445 strftime(st_str, sizeof(st_str), "%Y-%m-%dT%TZ", &st);
4446 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:startTime>%s</ns0:startTime>",
4447 st_str);
4448 }
4449
4450 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:maxSample>1</ns0:maxSample>");
4451
4452 for (j = start_counter; j < entity->counters.values_num && counters_num < counters_max; j++)
4453 {
4454 zbx_vmware_perf_counter_t *counter;
4455
4456 counter = (zbx_vmware_perf_counter_t *)entity->counters.values[j];
4457
4458 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset,
4459 "<ns0:metricId><ns0:counterId>" ZBX_FS_UI64
4460 "</ns0:counterId><ns0:instance>%s</ns0:instance></ns0:metricId>",
4461 counter->counterid, entity->query_instance);
4462
4463 counter->state |= ZBX_VMWARE_COUNTER_UPDATING;
4464
4465 counters_num++;
4466 }
4467
4468 if (j == entity->counters.values_num)
4469 {
4470 start_counter = 0;
4471 i--;
4472 }
4473 else
4474 start_counter = j;
4475
4476
4477 if (ZBX_VMWARE_PERF_INTERVAL_NONE != entity->refresh)
4478 {
4479 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:intervalId>%d</ns0:intervalId>",
4480 entity->refresh);
4481 }
4482
4483 zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "</ns0:querySpec>");
4484 }
4485
4486 zbx_vmware_unlock();
4487
4488 zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, "</ns0:QueryPerf>");
4489 zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, ZBX_POST_VSPHERE_FOOTER);
4490
4491 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP request: %s", __function_name, tmp);
4492
4493 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, tmp)))
4494 {
4495 for (j = i + 1; j < entities->values_num; j++)
4496 {
4497 entity = (zbx_vmware_perf_entity_t *)entities->values[j];
4498 vmware_perf_data_add_error(perfdata, entity->type, entity->id, curl_easy_strerror(err));
4499 }
4500
4501 break;
4502 }
4503
4504 page.offset = 0;
4505
4506 if (CURLE_OK != (err = curl_easy_perform(easyhandle)))
4507 {
4508 for (j = i + 1; j < entities->values_num; j++)
4509 {
4510 entity = (zbx_vmware_perf_entity_t *)entities->values[j];
4511 vmware_perf_data_add_error(perfdata, entity->type, entity->id, curl_easy_strerror(err));
4512 }
4513
4514 break;
4515 }
4516
4517 zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP response: %s", __function_name, page.data);
4518
4519 if (NULL != (error = zbx_xml_read_value(page.data, ZBX_XPATH_FAULTSTRING())))
4520 {
4521 for (j = i + 1; j < entities->values_num; j++)
4522 {
4523 entity = (zbx_vmware_perf_entity_t *)entities->values[j];
4524 vmware_perf_data_add_error(perfdata, entity->type, entity->id, error);
4525 }
4526
4527 zbx_free(error);
4528 break;
4529 }
4530
4531 /* parse performance data into local memory */
4532 vmware_service_parse_perf_data(perfdata, page.data);
4533
4534 while (entities->values_num > i + 1)
4535 zbx_vector_ptr_remove_noorder(entities, entities->values_num - 1);
4536 }
4537
4538 zbx_free(tmp);
4539
4540 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4541 }
4542
4543 /******************************************************************************
4544 * *
4545 * Function: vmware_service_update_perf *
4546 * *
4547 * Purpose: updates vmware statistics data *
4548 * *
4549 * Parameters: service - [IN] the vmware service *
4550 * *
4551 ******************************************************************************/
vmware_service_update_perf(zbx_vmware_service_t * service)4552 static void vmware_service_update_perf(zbx_vmware_service_t *service)
4553 {
4554 const char *__function_name = "vmware_service_update_perf";
4555
4556 CURL *easyhandle = NULL;
4557 struct curl_slist *headers = NULL;
4558 int err, opt, i, ret = FAIL;
4559 char *error = NULL;
4560 zbx_vector_ptr_t entities, hist_entities;
4561 zbx_vmware_perf_entity_t *entity;
4562 zbx_hashset_iter_t iter;
4563 zbx_vector_ptr_t perfdata;
4564
4565 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, service->username, service->url);
4566
4567 zbx_vector_ptr_create(&entities);
4568 zbx_vector_ptr_create(&hist_entities);
4569 zbx_vector_ptr_create(&perfdata);
4570
4571 if (NULL == (easyhandle = curl_easy_init()))
4572 {
4573 error = zbx_strdup(error, "cannot initialize cURL library");
4574 goto out;
4575 }
4576
4577 headers = curl_slist_append(headers, ZBX_XML_HEADER1);
4578 headers = curl_slist_append(headers, ZBX_XML_HEADER2);
4579
4580 if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPHEADER, headers)))
4581 {
4582 error = zbx_dsprintf(error, "Cannot set cURL option %d: %s.", opt, curl_easy_strerror(err));
4583 goto clean;
4584 }
4585
4586 if (SUCCEED != vmware_service_authenticate(service, easyhandle, &error))
4587 goto clean;
4588
4589 /* update performance counter refresh rate for entities */
4590
4591 zbx_vmware_lock();
4592
4593 zbx_hashset_iter_reset(&service->entities, &iter);
4594 while (NULL != (entity = zbx_hashset_iter_next(&iter)))
4595 {
4596 /* remove old entities */
4597 if (0 != entity->last_seen && entity->last_seen < service->lastcheck)
4598 {
4599 vmware_shared_perf_entity_clean(entity);
4600 zbx_hashset_iter_remove(&iter);
4601 continue;
4602 }
4603
4604 if (ZBX_VMWARE_PERF_INTERVAL_UNKNOWN != entity->refresh)
4605 continue;
4606
4607 /* Entities are removed only during performance counter update and no two */
4608 /* performance counter updates for one service can happen simultaneously. */
4609 /* This means for refresh update we can safely use reference to entity */
4610 /* outside vmware lock. */
4611 zbx_vector_ptr_append(&entities, entity);
4612 }
4613
4614 zbx_vmware_unlock();
4615
4616 /* get refresh rates */
4617 for (i = 0; i < entities.values_num; i++)
4618 {
4619 entity = entities.values[i];
4620
4621 if (SUCCEED != vmware_service_get_perf_counter_refreshrate(service, easyhandle, entity->type,
4622 entity->id, &entity->refresh, &error))
4623 {
4624 zabbix_log(LOG_LEVEL_WARNING, "cannot get refresh rate for %s \"%s\": %s", entity->type,
4625 entity->id, error);
4626 zbx_free(error);
4627 }
4628 }
4629
4630 zbx_vector_ptr_clear(&entities);
4631
4632 zbx_vmware_lock();
4633
4634 zbx_hashset_iter_reset(&service->entities, &iter);
4635 while (NULL != (entity = zbx_hashset_iter_next(&iter)))
4636 {
4637 if (ZBX_VMWARE_PERF_INTERVAL_UNKNOWN == entity->refresh)
4638 {
4639 zabbix_log(LOG_LEVEL_DEBUG, "skipping performance entity with zero refresh rate "
4640 "type:%s id:%d", entity->type, entity->id);
4641 continue;
4642 }
4643
4644 if (ZBX_VMWARE_PERF_INTERVAL_NONE == entity->refresh)
4645 zbx_vector_ptr_append(&hist_entities, entity);
4646 else
4647 zbx_vector_ptr_append(&entities, entity);
4648 }
4649
4650 zbx_vmware_unlock();
4651
4652 vmware_service_retrieve_perf_counters(service, easyhandle, &entities, ZBX_MAXQUERYMETRICS_UNLIMITED, &perfdata);
4653 vmware_service_retrieve_perf_counters(service, easyhandle, &hist_entities, service->data->max_query_metrics,
4654 &perfdata);
4655
4656 if (SUCCEED != vmware_service_logout(service, easyhandle, &error))
4657 {
4658 zabbix_log(LOG_LEVEL_DEBUG, "Cannot close vmware connection: %s.", error);
4659 zbx_free(error);
4660 }
4661
4662 ret = SUCCEED;
4663 clean:
4664 curl_slist_free_all(headers);
4665 curl_easy_cleanup(easyhandle);
4666 out:
4667 zbx_vmware_lock();
4668
4669 if (FAIL == ret)
4670 {
4671 zbx_hashset_iter_reset(&service->entities, &iter);
4672 while (NULL != (entity = zbx_hashset_iter_next(&iter)))
4673 entity->error = vmware_shared_strdup(error);
4674
4675 zbx_free(error);
4676 }
4677 else
4678 {
4679 /* clean old performance data and copy the new data into shared memory */
4680 vmware_entities_shared_clean_stats(&service->entities);
4681 vmware_service_copy_perf_data(service, &perfdata);
4682 }
4683
4684 service->state &= ~(ZBX_VMWARE_STATE_UPDATING_PERF);
4685 service->lastperfcheck = time(NULL);
4686
4687 zbx_vmware_unlock();
4688
4689 zbx_vector_ptr_clear_ext(&perfdata, (zbx_mem_free_func_t)vmware_free_perfdata);
4690 zbx_vector_ptr_destroy(&perfdata);
4691
4692 zbx_vector_ptr_destroy(&hist_entities);
4693 zbx_vector_ptr_destroy(&entities);
4694
4695 zabbix_log(LOG_LEVEL_DEBUG, "End of %s(): processed " ZBX_FS_SIZE_T " bytes of data", __function_name,
4696 (zbx_fs_size_t)page.offset);
4697 }
4698
4699 /******************************************************************************
4700 * *
4701 * Function: vmware_service_remove *
4702 * *
4703 * Purpose: removes vmware service *
4704 * *
4705 * Parameters: service - [IN] the vmware service *
4706 * *
4707 ******************************************************************************/
vmware_service_remove(zbx_vmware_service_t * service)4708 static void vmware_service_remove(zbx_vmware_service_t *service)
4709 {
4710 const char *__function_name = "vmware_service_remove";
4711 int index;
4712
4713 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, service->username, service->url);
4714
4715 zbx_vmware_lock();
4716
4717 if (FAIL != (index = zbx_vector_ptr_search(&vmware->services, service, ZBX_DEFAULT_PTR_COMPARE_FUNC)))
4718 {
4719 zbx_vector_ptr_remove(&vmware->services, index);
4720 vmware_service_shared_free(service);
4721 }
4722
4723 zbx_vmware_unlock();
4724
4725 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4726 }
4727
4728 /*
4729 * Public API
4730 */
4731
4732 /******************************************************************************
4733 * *
4734 * Function: vmware_get_service *
4735 * *
4736 * Purpose: gets vmware service object *
4737 * *
4738 * Parameters: url - [IN] the vmware service URL *
4739 * username - [IN] the vmware service username *
4740 * password - [IN] the vmware service password *
4741 * *
4742 * Return value: the requested service object or NULL if the object is not *
4743 * yet ready. *
4744 * *
4745 * Comments: vmware lock must be locked with zbx_vmware_lock() function *
4746 * before calling this function. *
4747 * If the service list does not contain the requested service object*
4748 * then a new object is created, marked as new, added to the list *
4749 * and a NULL value is returned. *
4750 * If the object is in list, but is not yet updated also a NULL *
4751 * value is returned. *
4752 * *
4753 ******************************************************************************/
zbx_vmware_get_service(const char * url,const char * username,const char * password)4754 zbx_vmware_service_t *zbx_vmware_get_service(const char* url, const char* username, const char* password)
4755 {
4756 const char *__function_name = "zbx_vmware_get_service";
4757
4758 int i, now;
4759 zbx_vmware_service_t *service = NULL;
4760
4761 zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __function_name, username, url);
4762
4763 if (NULL == vmware)
4764 goto out;
4765
4766 now = time(NULL);
4767
4768 for (i = 0; i < vmware->services.values_num; i++)
4769 {
4770 service = vmware->services.values[i];
4771
4772 if (0 == strcmp(service->url, url) && 0 == strcmp(service->username, username) &&
4773 0 == strcmp(service->password, password))
4774 {
4775 service->lastaccess = now;
4776
4777 /* return NULL if the service is not ready yet */
4778 if (0 == (service->state & (ZBX_VMWARE_STATE_READY | ZBX_VMWARE_STATE_FAILED)))
4779 service = NULL;
4780
4781 goto out;
4782 }
4783 }
4784
4785 service = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_service_t));
4786 memset(service, 0, sizeof(zbx_vmware_service_t));
4787
4788 service->url = vmware_shared_strdup(url);
4789 service->username = vmware_shared_strdup(username);
4790 service->password = vmware_shared_strdup(password);
4791 service->type = ZBX_VMWARE_TYPE_UNKNOWN;
4792 service->state = ZBX_VMWARE_STATE_NEW;
4793 service->lastaccess = now;
4794 service->eventlog_last_key = ZBX_VMWARE_EVENT_KEY_UNINITIALIZED;
4795
4796 zbx_hashset_create_ext(&service->entities, 100, vmware_perf_entity_hash_func, vmware_perf_entity_compare_func,
4797 NULL, __vm_mem_malloc_func, __vm_mem_realloc_func, __vm_mem_free_func);
4798
4799 zbx_hashset_create_ext(&service->counters, ZBX_VMWARE_COUNTERS_INIT_SIZE, vmware_counter_hash_func,
4800 vmware_counter_compare_func, NULL, __vm_mem_malloc_func, __vm_mem_realloc_func,
4801 __vm_mem_free_func);
4802
4803 zbx_vector_ptr_append(&vmware->services, service);
4804
4805 /* new service does not have any data - return NULL */
4806 service = NULL;
4807 out:
4808 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name,
4809 zbx_result_string(NULL != service ? SUCCEED : FAIL));
4810
4811 return service;
4812 }
4813
4814
4815 /******************************************************************************
4816 * *
4817 * Function: zbx_vmware_service_get_counterid *
4818 * *
4819 * Purpose: gets vmware performance counter id by the path *
4820 * *
4821 * Parameters: service - [IN] the vmware service *
4822 * path - [IN] the path of counter to retrieve in format *
4823 * <group>/<key>[<rollup type>] *
4824 * counterid - [OUT] the counter id *
4825 * *
4826 * Return value: SUCCEED if the counter was found, FAIL otherwise *
4827 * *
4828 ******************************************************************************/
zbx_vmware_service_get_counterid(zbx_vmware_service_t * service,const char * path,zbx_uint64_t * counterid)4829 int zbx_vmware_service_get_counterid(zbx_vmware_service_t *service, const char *path,
4830 zbx_uint64_t *counterid)
4831 {
4832 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
4833 const char *__function_name = "zbx_vmware_service_get_counterid";
4834 zbx_vmware_counter_t *counter;
4835 int ret = FAIL;
4836
4837 zabbix_log(LOG_LEVEL_DEBUG, "In %s() path:%s", __function_name, path);
4838
4839 if (NULL == (counter = zbx_hashset_search(&service->counters, &path)))
4840 goto out;
4841
4842 *counterid = counter->id;
4843
4844 zabbix_log(LOG_LEVEL_DEBUG, "%s() counterid:" ZBX_FS_UI64, __function_name, *counterid);
4845
4846 ret = SUCCEED;
4847 out:
4848 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
4849
4850 return ret;
4851 #else
4852 return FAIL;
4853 #endif
4854 }
4855
4856 /******************************************************************************
4857 * *
4858 * Function: zbx_vmware_service_add_perf_counter *
4859 * *
4860 * Purpose: start monitoring performance counter of the specified entity *
4861 * *
4862 * Parameters: service - [IN] the vmware service *
4863 * type - [IN] the entity type *
4864 * id - [IN] the entity id *
4865 * counterid - [IN] the performance counter id *
4866 * instance - [IN] the performance counter instance name *
4867 * *
4868 * Return value: SUCCEED - the entity counter was added to monitoring list. *
4869 * FAIL - the performance counter of the specified entity *
4870 * is already being monitored. *
4871 * *
4872 ******************************************************************************/
zbx_vmware_service_add_perf_counter(zbx_vmware_service_t * service,const char * type,const char * id,zbx_uint64_t counterid,const char * instance)4873 int zbx_vmware_service_add_perf_counter(zbx_vmware_service_t *service, const char *type, const char *id,
4874 zbx_uint64_t counterid, const char *instance)
4875 {
4876 const char *__function_name = "zbx_vmware_service_add_perf_counter";
4877 zbx_vmware_perf_entity_t *pentity, entity;
4878 int ret = FAIL;
4879
4880 zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s counterid:" ZBX_FS_UI64, __function_name, type, id,
4881 counterid);
4882
4883 if (NULL == (pentity = zbx_vmware_service_get_perf_entity(service, type, id)))
4884 {
4885 entity.refresh = ZBX_VMWARE_PERF_INTERVAL_UNKNOWN;
4886 entity.last_seen = 0;
4887 entity.query_instance = vmware_shared_strdup(instance);
4888 entity.type = vmware_shared_strdup(type);
4889 entity.id = vmware_shared_strdup(id);
4890 entity.error = NULL;
4891 zbx_vector_ptr_create_ext(&entity.counters, __vm_mem_malloc_func, __vm_mem_realloc_func,
4892 __vm_mem_free_func);
4893
4894 pentity = zbx_hashset_insert(&service->entities, &entity, sizeof(zbx_vmware_perf_entity_t));
4895 }
4896
4897 if (FAIL == zbx_vector_ptr_search(&pentity->counters, &counterid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))
4898 {
4899 vmware_counters_add_new(&pentity->counters, counterid);
4900 zbx_vector_ptr_sort(&pentity->counters, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4901
4902 ret = SUCCEED;
4903 }
4904
4905 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
4906
4907 return ret;
4908 }
4909
4910 /******************************************************************************
4911 * *
4912 * Function: zbx_vmware_service_get_perf_entity *
4913 * *
4914 * Purpose: gets performance entity by type and id *
4915 * *
4916 * Parameters: service - [IN] the vmware service *
4917 * type - [IN] the performance entity type *
4918 * id - [IN] the performance entity id *
4919 * *
4920 * Return value: the performance entity or NULL if not found *
4921 * *
4922 ******************************************************************************/
zbx_vmware_service_get_perf_entity(zbx_vmware_service_t * service,const char * type,const char * id)4923 zbx_vmware_perf_entity_t *zbx_vmware_service_get_perf_entity(zbx_vmware_service_t *service, const char *type,
4924 const char *id)
4925 {
4926 const char *__function_name = "zbx_vmware_service_get_perf_entity";
4927
4928 zbx_vmware_perf_entity_t *pentity, entity = {(char *)type, (char *)id};
4929
4930 zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s", __function_name, type, id);
4931
4932 pentity = zbx_hashset_search(&service->entities, &entity);
4933
4934 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() entity:%p", __function_name, pentity);
4935
4936 return pentity;
4937 }
4938 #endif
4939
4940 /******************************************************************************
4941 * *
4942 * Function: zbx_vmware_init *
4943 * *
4944 * Purpose: initializes vmware collector service *
4945 * *
4946 * Comments: This function must be called before worker threads are forked. *
4947 * *
4948 ******************************************************************************/
zbx_vmware_init(void)4949 void zbx_vmware_init(void)
4950 {
4951 const char *__function_name = "zbx_vmware_init";
4952
4953 key_t shm_key;
4954 zbx_uint64_t size_reserved;
4955
4956 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4957
4958 zbx_mutex_create(&vmware_lock, ZBX_MUTEX_VMWARE);
4959
4960 if (-1 == (shm_key = zbx_ftok(CONFIG_FILE, ZBX_IPC_VMWARE_ID)))
4961 {
4962 zabbix_log(LOG_LEVEL_CRIT, "cannot create IPC key for vmware cache");
4963 exit(EXIT_FAILURE);
4964 }
4965
4966 size_reserved = zbx_mem_required_size(1, "vmware cache size", "VMwareCacheSize");
4967
4968 CONFIG_VMWARE_CACHE_SIZE -= size_reserved;
4969
4970 zbx_mem_create(&vmware_mem, shm_key, ZBX_NO_MUTEX, CONFIG_VMWARE_CACHE_SIZE, "vmware cache size",
4971 "VMwareCacheSize", 0);
4972
4973 vmware = __vm_mem_malloc_func(NULL, sizeof(zbx_vmware_t));
4974 memset(vmware, 0, sizeof(zbx_vmware_t));
4975
4976 VMWARE_VECTOR_CREATE(&vmware->services, ptr);
4977 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
4978 zbx_hashset_create_ext(&vmware->strpool, 100, vmware_strpool_hash_func, vmware_strpool_compare_func, NULL,
4979 __vm_mem_malloc_func, __vm_mem_realloc_func, __vm_mem_free_func);
4980 #endif
4981 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4982 }
4983
4984 /******************************************************************************
4985 * *
4986 * Function: zbx_vmware_destroy *
4987 * *
4988 * Purpose: destroys vmware collector service *
4989 * *
4990 ******************************************************************************/
zbx_vmware_destroy(void)4991 void zbx_vmware_destroy(void)
4992 {
4993 const char *__function_name = "zbx_vmware_destroy";
4994
4995 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4996 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
4997 zbx_hashset_destroy(&vmware->strpool);
4998 #endif
4999 zbx_mem_destroy(vmware_mem);
5000 zbx_mutex_destroy(&vmware_lock);
5001
5002 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5003 }
5004
5005 #define ZBX_VMWARE_TASK_NONE 0
5006 #define ZBX_VMWARE_TASK_IDLE 1
5007 #define ZBX_VMWARE_TASK_UPDATE 2
5008 #define ZBX_VMWARE_TASK_UPDATE_PERF 3
5009 #define ZBX_VMWARE_TASK_REMOVE 4
5010
5011 /******************************************************************************
5012 * *
5013 * Function: main_vmware_loop *
5014 * *
5015 * Purpose: the vmware collector main loop *
5016 * *
5017 ******************************************************************************/
ZBX_THREAD_ENTRY(vmware_thread,args)5018 ZBX_THREAD_ENTRY(vmware_thread, args)
5019 {
5020 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
5021 int i, now, task, next_update, updated_services = 0, removed_services = 0,
5022 old_updated_services = 0, old_removed_services = 0, sleeptime = -1;
5023 zbx_vmware_service_t *service = NULL;
5024 double sec, total_sec = 0.0, old_total_sec = 0.0;
5025 time_t last_stat_time;
5026
5027 process_type = ((zbx_thread_args_t *)args)->process_type;
5028 server_num = ((zbx_thread_args_t *)args)->server_num;
5029 process_num = ((zbx_thread_args_t *)args)->process_num;
5030
5031 zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
5032 server_num, get_process_type_string(process_type), process_num);
5033
5034 #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */
5035 /* once in STAT_INTERVAL seconds */
5036
5037 last_stat_time = time(NULL);
5038
5039 for (;;)
5040 {
5041 zbx_handle_log();
5042
5043 if (0 != sleeptime)
5044 {
5045 zbx_setproctitle("%s #%d [updated %d, removed %d VMware services in " ZBX_FS_DBL " sec, "
5046 "querying VMware services]", get_process_type_string(process_type), process_num,
5047 old_updated_services, old_removed_services, old_total_sec);
5048 }
5049
5050 sec = zbx_time();
5051
5052 do
5053 {
5054 task = ZBX_VMWARE_TASK_IDLE;
5055
5056 now = time(NULL);
5057 next_update = now + POLLER_DELAY;
5058
5059 zbx_vmware_lock();
5060
5061 /* find a task to be performed on a vmware service */
5062 for (i = 0; i < vmware->services.values_num; i++)
5063 {
5064 service = vmware->services.values[i];
5065
5066 /* check if the service isn't used and should be removed */
5067 if (0 == (service->state & ZBX_VMWARE_STATE_BUSY) &&
5068 now - service->lastaccess > ZBX_VMWARE_SERVICE_TTL)
5069 {
5070 service->state |= ZBX_VMWARE_STATE_REMOVING;
5071 task = ZBX_VMWARE_TASK_REMOVE;
5072 break;
5073 }
5074
5075 /* check if the performance statistics should be updated */
5076 if (0 != (service->state & ZBX_VMWARE_STATE_READY) &&
5077 0 == (service->state & ZBX_VMWARE_STATE_UPDATING_PERF) &&
5078 now - service->lastperfcheck >= ZBX_VMWARE_PERF_UPDATE_PERIOD)
5079 {
5080 service->state |= ZBX_VMWARE_STATE_UPDATING_PERF;
5081 task = ZBX_VMWARE_TASK_UPDATE_PERF;
5082 break;
5083 }
5084
5085 /* check if the service data should be updated */
5086 if (0 == (service->state & ZBX_VMWARE_STATE_UPDATING) &&
5087 now - service->lastcheck >= ZBX_VMWARE_CACHE_UPDATE_PERIOD)
5088 {
5089 service->state |= ZBX_VMWARE_STATE_UPDATING;
5090 task = ZBX_VMWARE_TASK_UPDATE;
5091 break;
5092 }
5093
5094 /* don't calculate nextcheck for services that are already updating something */
5095 if (0 != (service->state & ZBX_VMWARE_STATE_BUSY))
5096 continue;
5097
5098 /* calculate next service update time */
5099
5100 if (service->lastcheck + ZBX_VMWARE_CACHE_UPDATE_PERIOD < next_update)
5101 next_update = service->lastcheck + ZBX_VMWARE_CACHE_UPDATE_PERIOD;
5102
5103 if (0 != (service->state & ZBX_VMWARE_STATE_READY))
5104 {
5105 if (service->lastperfcheck + ZBX_VMWARE_PERF_UPDATE_PERIOD < next_update)
5106 next_update = service->lastperfcheck + ZBX_VMWARE_PERF_UPDATE_PERIOD;
5107 }
5108 }
5109
5110 zbx_vmware_unlock();
5111
5112 switch (task)
5113 {
5114 case ZBX_VMWARE_TASK_UPDATE:
5115 vmware_service_update(service);
5116 updated_services++;
5117 break;
5118 case ZBX_VMWARE_TASK_UPDATE_PERF:
5119 vmware_service_update_perf(service);
5120 updated_services++;
5121 break;
5122 case ZBX_VMWARE_TASK_REMOVE:
5123 vmware_service_remove(service);
5124 removed_services++;
5125 break;
5126 }
5127 }
5128 while (ZBX_VMWARE_TASK_IDLE != task);
5129
5130 total_sec += zbx_time() - sec;
5131 now = time(NULL);
5132
5133 sleeptime = 0 < next_update - now ? next_update - now : 0;
5134
5135 if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time)
5136 {
5137 if (0 == sleeptime)
5138 {
5139 zbx_setproctitle("%s #%d [updated %d, removed %d VMware services in " ZBX_FS_DBL " sec,"
5140 " querying VMware services]", get_process_type_string(process_type),
5141 process_num, updated_services, removed_services, total_sec);
5142 }
5143 else
5144 {
5145 zbx_setproctitle("%s #%d [updated %d, removed %d VMware services in " ZBX_FS_DBL " sec,"
5146 " idle %d sec]", get_process_type_string(process_type), process_num,
5147 updated_services, removed_services, total_sec, sleeptime);
5148 old_updated_services = updated_services;
5149 old_removed_services = removed_services;
5150 old_total_sec = total_sec;
5151 }
5152 updated_services = 0;
5153 removed_services = 0;
5154 total_sec = 0.0;
5155 last_stat_time = time(NULL);
5156 }
5157
5158 zbx_sleep_loop(sleeptime);
5159
5160 #if !defined(_WINDOWS) && defined(HAVE_RESOLV_H)
5161 zbx_update_resolver_conf(); /* handle /etc/resolv.conf update */
5162 #endif
5163 }
5164 #undef STAT_INTERVAL
5165 #else
5166 zbx_thread_exit(EXIT_SUCCESS);
5167 #endif
5168 }
5169
5170 /******************************************************************************
5171 * *
5172 * Function: zbx_vmware_lock *
5173 * *
5174 * Purpose: locks vmware collector *
5175 * *
5176 ******************************************************************************/
zbx_vmware_lock(void)5177 void zbx_vmware_lock(void)
5178 {
5179 zbx_mutex_lock(&vmware_lock);
5180 }
5181
5182 /******************************************************************************
5183 * *
5184 * Function: zbx_vmware_unlock *
5185 * *
5186 * Purpose: unlocks vmware collector *
5187 * *
5188 ******************************************************************************/
zbx_vmware_unlock(void)5189 void zbx_vmware_unlock(void)
5190 {
5191 zbx_mutex_unlock(&vmware_lock);
5192 }
5193
5194 /******************************************************************************
5195 * *
5196 * Function: zbx_vmware_get_statistics *
5197 * *
5198 * Purpose: gets vmware collector statistics *
5199 * *
5200 * Parameters: stats - [OUT] the vmware collector statistics *
5201 * *
5202 * Return value: SUCCEEED - the statistics were retrieved successfully *
5203 * FAIL - no vmware collectors are running *
5204 * *
5205 ******************************************************************************/
zbx_vmware_get_statistics(zbx_vmware_stats_t * stats)5206 int zbx_vmware_get_statistics(zbx_vmware_stats_t *stats)
5207 {
5208 if (NULL == vmware_mem)
5209 return FAIL;
5210
5211 zbx_vmware_lock();
5212
5213 stats->memory_total = vmware_mem->total_size;
5214 stats->memory_used = vmware_mem->total_size - vmware_mem->free_size;
5215
5216 zbx_vmware_unlock();
5217
5218 return SUCCEED;
5219 }
5220
5221 #if defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL)
5222
5223 /*
5224 * XML support
5225 */
5226 /******************************************************************************
5227 * *
5228 * Function: libxml_handle_error *
5229 * *
5230 * Purpose: libxml2 callback function for error handle *
5231 * *
5232 * Parameters: user_data - [IN/OUT] the user context *
5233 * err - [IN] the libxml2 error message *
5234 * *
5235 ******************************************************************************/
libxml_handle_error(void * user_data,xmlErrorPtr err)5236 static void libxml_handle_error(void *user_data, xmlErrorPtr err)
5237 {
5238 ZBX_UNUSED(user_data);
5239 ZBX_UNUSED(err);
5240 }
5241
5242 /******************************************************************************
5243 * *
5244 * Function: zbx_xml_try_read_value *
5245 * *
5246 * Purpose: retrieve a value from xml data and return status of operation *
5247 * *
5248 * Parameters: data - [IN] XML data *
5249 * xpath - [IN] XML XPath *
5250 * value - [OUT] selected xml node value *
5251 * error - [OUT] error of xml or xpath formats *
5252 * *
5253 * Return: SUCCEED - select xpath successfully, result stored in 'value' *
5254 * FAIL - failed select xpath expression *
5255 * *
5256 ******************************************************************************/
zbx_xml_try_read_value(const char * data,const char * xpath,char ** value,char ** error)5257 int zbx_xml_try_read_value(const char *data, const char *xpath, char **value, char **error)
5258 {
5259 xmlDoc *doc;
5260 xmlXPathContext *xpathCtx;
5261 xmlXPathObject *xpathObj;
5262 xmlNodeSetPtr nodeset;
5263 xmlChar *val;
5264 int ret = FAIL;
5265
5266 if (NULL == data)
5267 goto out;
5268
5269 xmlSetStructuredErrorFunc(NULL, &libxml_handle_error);
5270
5271 if (NULL == (doc = xmlReadMemory(data, strlen(data), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
5272 {
5273 if (NULL != error)
5274 *error = zbx_dsprintf(*error, "Received response has no valid XML data.");
5275
5276 xmlSetStructuredErrorFunc(NULL, NULL);
5277 goto out;
5278 }
5279
5280 xpathCtx = xmlXPathNewContext(doc);
5281
5282 if (NULL == (xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath, xpathCtx)))
5283 {
5284 if (NULL != error)
5285 *error = zbx_dsprintf(*error, "Invalid xpath expression: \"%s\".", xpath);
5286
5287 goto clean;
5288 }
5289
5290 ret = SUCCEED;
5291
5292 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
5293 goto clean;
5294
5295 nodeset = xpathObj->nodesetval;
5296
5297 if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1)))
5298 {
5299 *value = zbx_strdup(NULL, (const char *)val);
5300 xmlFree(val);
5301 }
5302 clean:
5303 if (NULL != xpathObj)
5304 xmlXPathFreeObject(xpathObj);
5305
5306 xmlSetStructuredErrorFunc(NULL, NULL);
5307 xmlXPathFreeContext(xpathCtx);
5308 xmlFreeDoc(doc);
5309 out:
5310 return ret;
5311 }
5312
5313 /******************************************************************************
5314 * *
5315 * Function: zbx_xml_read_value *
5316 * *
5317 * Purpose: retrieve a value from xml data *
5318 * *
5319 * Parameters: data - [IN] XML data *
5320 * xpath - [IN] XML XPath *
5321 * *
5322 * Return: The allocated value string or NULL if the xml data does not *
5323 * contain the value specified by xpath. *
5324 * *
5325 ******************************************************************************/
zbx_xml_read_value(const char * data,const char * xpath)5326 char *zbx_xml_read_value(const char *data, const char *xpath)
5327 {
5328 char *value = NULL;
5329
5330 zbx_xml_try_read_value(data, xpath, &value, NULL);
5331 return value;
5332 }
5333
5334 /******************************************************************************
5335 * *
5336 * Function: zbx_xml_read_node_value *
5337 * *
5338 * Purpose: retrieve a value from xml data relative to the specified node *
5339 * *
5340 * Parameters: doc - [IN] the XML document *
5341 * node - [IN] the XML node *
5342 * xpath - [IN] the XML XPath *
5343 * *
5344 * Return: The allocated value string or NULL if the xml data does not *
5345 * contain the value specified by xpath. *
5346 * *
5347 ******************************************************************************/
zbx_xml_read_node_value(xmlDoc * doc,xmlNode * node,const char * xpath)5348 static char *zbx_xml_read_node_value(xmlDoc *doc, xmlNode *node, const char *xpath)
5349 {
5350 xmlXPathContext *xpathCtx;
5351 xmlXPathObject *xpathObj;
5352 xmlNodeSetPtr nodeset;
5353 xmlChar *val;
5354 char *value = NULL;
5355
5356 xpathCtx = xmlXPathNewContext(doc);
5357
5358 xpathCtx->node = node;
5359
5360 if (NULL == (xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath, xpathCtx)))
5361 goto clean;
5362
5363 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
5364 goto clean;
5365
5366 nodeset = xpathObj->nodesetval;
5367
5368 if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1)))
5369 {
5370 value = zbx_strdup(NULL, (const char *)val);
5371 xmlFree(val);
5372 }
5373 clean:
5374 if (NULL != xpathObj)
5375 xmlXPathFreeObject(xpathObj);
5376
5377 xmlXPathFreeContext(xpathCtx);
5378
5379 return value;
5380 }
5381
5382 /******************************************************************************
5383 * *
5384 * Function: zbx_xml_read_values *
5385 * *
5386 * Purpose: populate array of values from a xml data *
5387 * *
5388 * Parameters: data - [IN] XML data *
5389 * xpath - [IN] XML XPath *
5390 * values - [OUT] list of requested values *
5391 * *
5392 * Return: Upon successful completion the function return SUCCEED. *
5393 * Otherwise, FAIL is returned. *
5394 * *
5395 ******************************************************************************/
zbx_xml_read_values(const char * data,const char * xpath,zbx_vector_str_t * values)5396 int zbx_xml_read_values(const char *data, const char *xpath, zbx_vector_str_t *values)
5397 {
5398 xmlDoc *doc;
5399 xmlXPathContext *xpathCtx;
5400 xmlXPathObject *xpathObj;
5401 xmlNodeSetPtr nodeset;
5402 xmlChar *val;
5403 int i, ret = FAIL;
5404
5405 if (NULL == data)
5406 goto out;
5407
5408 if (NULL == (doc = xmlReadMemory(data, strlen(data), ZBX_VM_NONAME_XML, NULL, ZBX_XML_PARSE_OPTS)))
5409 goto out;
5410
5411 xpathCtx = xmlXPathNewContext(doc);
5412
5413 if (NULL == (xpathObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCtx)))
5414 goto clean;
5415
5416 if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
5417 goto clean;
5418
5419 nodeset = xpathObj->nodesetval;
5420
5421 for (i = 0; i < nodeset->nodeNr; i++)
5422 {
5423 if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1)))
5424 {
5425 zbx_vector_str_append(values, zbx_strdup(NULL, (const char *)val));
5426 xmlFree(val);
5427 }
5428 }
5429
5430 ret = SUCCEED;
5431 clean:
5432 if (NULL != xpathObj)
5433 xmlXPathFreeObject(xpathObj);
5434
5435 xmlXPathFreeContext(xpathCtx);
5436 xmlFreeDoc(doc);
5437 out:
5438 return ret;
5439 }
5440
5441 #endif
5442