From 9785d90909bdd211048fea1ddd2bc069d0574658 Mon Sep 17 00:00:00 2001
From: Andris Zeila <wiper@sfix.nox>
Date: Sun, 24 Jan 2016 10:24:03 +0200
Subject: [PATCH 2/3] Add hypervisor properties

---
 src/zabbix_server/poller/checks_simple_vmware.c | 230 +++++++++++++-----------
 src/zabbix_server/vmware/vmware.c               | 190 ++++++++++++++++++--
 src/zabbix_server/vmware/vmware.h               |  22 ++-
 3 files changed, 322 insertions(+), 120 deletions(-)

diff --git a/src/zabbix_server/poller/checks_simple_vmware.c b/src/zabbix_server/poller/checks_simple_vmware.c
index cc7b5e3..a2d7206 100644
--- a/src/zabbix_server/poller/checks_simple_vmware.c
+++ b/src/zabbix_server/poller/checks_simple_vmware.c
@@ -407,87 +407,32 @@ out:
 	return ret;
 }
 
-#define ZBX_OPT_XPATH		0
-#define ZBX_OPT_VM_NUM		1
-#define ZBX_OPT_MEM_BALLOONED	2
-
-static int	hv_get_stat(zbx_vmware_hv_t *hv, int opt, const char *xpath, AGENT_RESULT *result)
-{
-	const char	*__function_name = "hv_get_stat";
-
-	char		*value;
-	zbx_uint64_t	value_uint64, value_uint64_sum;
-	int		i, ret = SYSINFO_RET_FAIL;
-
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
-
-	switch (opt)
-	{
-		case ZBX_OPT_XPATH:
-			zabbix_log(LOG_LEVEL_DEBUG, "%s() xpath:'%s'", __function_name, xpath);
-
-			if (NULL == (value = zbx_xml_read_value(hv->details, xpath)))
-				goto out;
-
-			SET_STR_RESULT(result, value);
-			break;
-		case ZBX_OPT_VM_NUM:
-			SET_UI64_RESULT(result, hv->vms.values_num);
-			break;
-		case ZBX_OPT_MEM_BALLOONED:
-			xpath = ZBX_XPATH_VM_QUICKSTATS("balloonedMemory");
-			value_uint64_sum = 0;
-
-			for (i = 0; i < hv->vms.values_num; i++)
-			{
-				zbx_vmware_vm_t	*vm = (zbx_vmware_vm_t *)hv->vms.values[i];
-
-				if (NULL == (value = zbx_xml_read_value(vm->details, xpath)))
-					continue;
-
-				if (SUCCEED == is_uint64(value, &value_uint64))
-					value_uint64_sum += value_uint64;
-
-				zbx_free(value);
-			}
-
-			SET_UI64_RESULT(result, value_uint64_sum);
-			break;
-	}
-
-	ret = SYSINFO_RET_OK;
-out:
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
-
-	return ret;
-}
-
 /******************************************************************************
  *                                                                            *
- * Function: get_vcenter_stat                                                 *
+ * Function: get_vcenter_hvprop                                               *
  *                                                                            *
- * Purpose: retrieves data from hypervisor details                            *
+ * Purpose: retrieves hypervisor property                                     *
  *                                                                            *
  * Parameters: request   - [IN] the original request. The first parameter is  *
  *                              vmware service URL and the second parameter   *
  *                              is hypervisor uuid.                           *
  *             username  - [IN] the vmware service user name                  *
  *             password  - [IN] the vmware service password                   *
- *             xpath     - [IN] the xpath describing data to retrieve         *
+ *             propid    - [IN] the property id                               *
  *             result    - [OUT] the request result                           *
  *                                                                            *
  ******************************************************************************/
-static int	get_vcenter_stat(AGENT_REQUEST *request, const char *username, const char *password,
-		int opt, const char *xpath, AGENT_RESULT *result)
+static int	get_vcenter_hvprop(AGENT_REQUEST *request, const char *username, const char *password, int propid,
+		AGENT_RESULT *result)
 {
-	const char		*__function_name = "get_vcenter_stat";
+	const char		*__function_name = "get_vcenter_hvprop";
 
 	zbx_vmware_service_t	*service;
-	const char		*uuid, *url;
+	const char		*uuid, *url, *value;
 	zbx_vmware_hv_t		*hv;
 	int			ret = SYSINFO_RET_FAIL;
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s() opt:%d", __function_name, opt);
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() propid:%d", __function_name, propid);
 
 	if (2 != request->nparam)
 	{
@@ -515,7 +460,14 @@ static int	get_vcenter_stat(AGENT_REQUEST *request, const char *username, const
 		goto unlock;
 	}
 
-	ret = hv_get_stat(hv, opt, xpath, result);
+	if (NULL == (value = hv->props[propid]))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "No property value found."));
+		goto unlock;
+	}
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, value));
+	ret = SYSINFO_RET_OK;
 unlock:
 	zbx_vmware_unlock();
 out:
@@ -524,6 +476,7 @@ out:
 	return ret;
 }
 
+
 int	check_vcenter_cluster_discovery(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result)
 {
@@ -917,9 +870,7 @@ int	check_vcenter_hv_cpu_usage(AGENT_REQUEST *request, const char *username, con
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_QUICKSTATS("overallCpuUsage"), result);
-
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE, result);
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * 1000000;
 
@@ -964,7 +915,7 @@ int	check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, con
 	{
 		zbx_vmware_cluster_t	*cluster = NULL;
 
-		if (NULL == (name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"))))
+		if (NULL == (name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
 			continue;
 
 		if (NULL != hv->clusterid)
@@ -977,8 +928,6 @@ int	check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, con
 		zbx_json_addstring(&json_data, "{#CLUSTER.NAME}",
 				NULL != cluster ? cluster->name : "", ZBX_JSON_TYPE_STRING);
 		zbx_json_close(&json_data);
-
-		zbx_free(name);
 	}
 
 	zbx_json_close(&json_data);
@@ -1005,8 +954,7 @@ int	check_vcenter_hv_fullname(AGENT_REQUEST *request, const char *username, cons
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_CONFIG_PRODUCT("fullName"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_FULL_NAME, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1022,8 +970,7 @@ int	check_vcenter_hv_hw_cpu_num(AGENT_REQUEST *request, const char *username, co
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("numCpuCores"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1039,8 +986,7 @@ int	check_vcenter_hv_hw_cpu_freq(AGENT_REQUEST *request, const char *username, c
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("cpuMhz"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_CPU_MHZ, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * 1000000;
@@ -1059,8 +1005,7 @@ int	check_vcenter_hv_hw_cpu_model(AGENT_REQUEST *request, const char *username,
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("cpuModel"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_CPU_MODEL, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1076,8 +1021,7 @@ int	check_vcenter_hv_hw_cpu_threads(AGENT_REQUEST *request, const char *username
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("numCpuThreads"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1093,7 +1037,7 @@ int	check_vcenter_hv_hw_memory(AGENT_REQUEST *request, const char *username, con
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("memorySize"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1109,8 +1053,7 @@ int	check_vcenter_hv_hw_model(AGENT_REQUEST *request, const char *username, cons
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("model"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_MODEL, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1126,8 +1069,7 @@ int	check_vcenter_hv_hw_uuid(AGENT_REQUEST *request, const char *username, const
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("uuid"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_UUID, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1143,8 +1085,7 @@ int	check_vcenter_hv_hw_vendor(AGENT_REQUEST *request, const char *username, con
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_HARDWARE("vendor"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_HW_VENDOR, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1156,15 +1097,63 @@ int	check_vcenter_hv_memory_size_ballooned(AGENT_REQUEST *request, const char *u
 {
 	const char	*__function_name = "check_vcenter_hv_memory_size_ballooned";
 
-	int		ret;
+	int			i, ret = SYSINFO_RET_FAIL;
+	zbx_vmware_service_t	*service;
+	const char		*uuid, *url;
+	zbx_vmware_hv_t		*hv;
+	zbx_uint64_t		value = 0;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_MEM_BALLOONED, NULL, result);
+	if (2 != request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+		goto out;
+	}
+
+	url = get_rparam(request, 0);
+	uuid = get_rparam(request, 1);
 
-	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
-		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
+	if ('\0' == *uuid)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		goto out;
+	}
+
+	zbx_vmware_lock();
+
+	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
+		goto unlock;
+
+	if (NULL == (hv = hv_get(&service->data->hvs, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown hypervisor uuid."));
+		goto unlock;
+	}
+
+	/* TODO: uncomment when vmprop implementation is done
+	for (i = 0; i < hv->vms.values_num; i++)
+	{
+		zbx_uint64_t	mem;
+		zbx_vmware_vm_t	*vm = (zbx_vmware_vm_t *)hv->vms.values[i];
+
+		if (NULL == vm->props[ZBX_VMWARE_VMPROP_MEMEORY_SIZE_BALLOONED])
+			continue;
 
+		if (SUCCEED != is_uint64(vm->props[ZBX_VMWARE_VMPROP_MEMEORY_SIZE_BALLOONED], &mem))
+			continue;
+
+		value += mem;
+	}
+	*/
+
+	value *= ZBX_MEBIBYTE;
+	SET_UI64_RESULT(result, value);
+
+	ret = SYSINFO_RET_OK;
+unlock:
+	zbx_vmware_unlock();
+out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
 	return ret;
@@ -1179,8 +1168,7 @@ int	check_vcenter_hv_memory_used(AGENT_REQUEST *request, const char *username, c
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_QUICKSTATS("overallMemoryUsage"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_MEMORY_USED, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_UI64_RESULT(result))
 		result->ui64 = result->ui64 * ZBX_MEBIBYTE;
@@ -1199,8 +1187,7 @@ int	check_vcenter_hv_status(AGENT_REQUEST *request, const char *username, const
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH,
-			ZBX_XPATH_HV_SENSOR_STATUS("VMware Rollup Health State"), result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_STATUS, result);
 
 	if (SYSINFO_RET_OK == ret && NULL != GET_STR_RESULT(result))
 	{
@@ -1232,8 +1219,7 @@ int	check_vcenter_hv_uptime(AGENT_REQUEST *request, const char *username, const
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_QUICKSTATS("uptime"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_UPTIME, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1249,8 +1235,7 @@ int	check_vcenter_hv_version(AGENT_REQUEST *request, const char *username, const
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_XPATH, ZBX_XPATH_HV_CONFIG_PRODUCT("version"),
-			result);
+	ret = get_vcenter_hvprop(request, username, password, ZBX_VMWARE_HVPROP_VERSION, result);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
@@ -1262,12 +1247,44 @@ int	check_vcenter_hv_vm_num(AGENT_REQUEST *request, const char *username, const
 {
 	const char	*__function_name = "check_vcenter_hv_vm_num";
 
-	int		ret;
+	int			ret = SYSINFO_RET_FAIL;
+	zbx_vmware_service_t	*service;
+	const char		*uuid, *url;
+	zbx_vmware_hv_t		*hv;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
 
-	ret = get_vcenter_stat(request, username, password, ZBX_OPT_VM_NUM, NULL, result);
+	if (2 != request->nparam)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+		goto out;
+	}
+
+	url = get_rparam(request, 0);
+	uuid = get_rparam(request, 1);
+
+	if ('\0' == *uuid)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
+		goto out;
+	}
+
+	zbx_vmware_lock();
 
+	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
+		goto unlock;
+
+	if (NULL == (hv = hv_get(&service->data->hvs, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown hypervisor uuid."));
+		goto unlock;
+	}
+
+	SET_UI64_RESULT(result, hv->vms.values_num);
+	ret = SYSINFO_RET_OK;
+unlock:
+	zbx_vmware_unlock();
+out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, sysinfo_ret_string(ret));
 
 	return ret;
@@ -1754,7 +1771,7 @@ int	check_vcenter_vm_discovery(AGENT_REQUEST *request, const char *username, con
 			if (NULL == (vm_name = zbx_xml_read_value(vm->details, ZBX_XPATH_VM_CONFIG("name"))))
 				continue;
 
-			if (NULL == (hv_name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"))))
+			if (NULL == (hv_name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
 			{
 				zbx_free(vm_name);
 				continue;
@@ -1769,7 +1786,6 @@ int	check_vcenter_vm_discovery(AGENT_REQUEST *request, const char *username, con
 					NULL != cluster ? cluster->name : "", ZBX_JSON_TYPE_STRING);
 			zbx_json_close(&json_data);
 
-			zbx_free(hv_name);
 			zbx_free(vm_name);
 		}
 	}
@@ -1828,9 +1844,13 @@ int	check_vcenter_vm_hv_name(AGENT_REQUEST *request, const char *username, const
 		goto unlock;
 	}
 
-	name = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_CONFIG("name"));
-	SET_STR_RESULT(result, name);
+	if (NULL == (name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "No hypervisor name found."));
+		goto unlock;
+	}
 
+	SET_STR_RESULT(result, zbx_strdup(NULL, name));
 	ret = SYSINFO_RET_OK;
 
 	SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown virtual machine uuid."));
diff --git a/src/zabbix_server/vmware/vmware.c b/src/zabbix_server/vmware/vmware.c
index 4a2750a..8b815b6 100644
--- a/src/zabbix_server/vmware/vmware.c
+++ b/src/zabbix_server/vmware/vmware.c
@@ -114,6 +114,32 @@ typedef struct
 }
 zbx_vmware_counter_t;
 
+/* the vm/hv object property mapping */
+typedef struct
+{
+	int		propid;
+	const char	*xpath;
+}
+zbx_vmware_propmap_t;
+
+static char	*hv_propmap[] = {
+	ZBX_XPATH_HV_QUICKSTATS("overallCpuUsage"),			/* ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE */
+	ZBX_XPATH_HV_CONFIG_PRODUCT("fullName"),			/* ZBX_VMWARE_HVPROP_FULL_NAME */
+	ZBX_XPATH_HV_HARDWARE("numCpuCores"),				/* ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES */
+	ZBX_XPATH_HV_HARDWARE("cpuMhz"),				/* ZBX_VMWARE_HVPROP_HW_CPU_MHZ */
+	ZBX_XPATH_HV_HARDWARE("cpuModel"),				/* ZBX_VMWARE_HVPROP_HW_CPU_MODEL */
+	ZBX_XPATH_HV_HARDWARE("numCpuThreads"), 			/* ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS */
+	ZBX_XPATH_HV_HARDWARE("memorySize"), 				/* ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE */
+	ZBX_XPATH_HV_HARDWARE("model"), 				/* ZBX_VMWARE_HVPROP_HW_MODEL */
+	ZBX_XPATH_HV_HARDWARE("uuid"), 					/* ZBX_VMWARE_HVPROP_HW_UUID */
+	ZBX_XPATH_HV_HARDWARE("vendor"), 				/* ZBX_VMWARE_HVPROP_HW_VENDOR */
+	ZBX_XPATH_HV_QUICKSTATS("overallMemoryUsage"),			/* ZBX_VMWARE_HVPROP_MEMORY_USED */
+	ZBX_XPATH_HV_SENSOR_STATUS("VMware Rollup Health State"),	/* ZBX_VMWARE_HVPROP_STATUS */
+	ZBX_XPATH_HV_QUICKSTATS("uptime"),				/* ZBX_VMWARE_HVPROP_UPTIME */
+	ZBX_XPATH_HV_CONFIG_PRODUCT("version"),				/* ZBX_VMWARE_HVPROP_VERSION */
+	ZBX_XPATH_HV_CONFIG("name")					/* ZBX_VMWARE_HVPROP_NAME */
+};
+
 /* hypervisor hashset support */
 zbx_hash_t	vmware_hv_hash(const void *data)
 {
@@ -256,6 +282,65 @@ static int	vmware_perf_entity_compare_func(const void *d1, const void *d2)
 
 /******************************************************************************
  *                                                                            *
+ * Function: xml_read_props                                                   *
+ *                                                                            *
+ * Purpose: reads the vmware object properties by their xpaths from xml data  *
+ *                                                                            *
+ * Parameters: xml       - [IN] the xml data                                  *
+ *             propmap   - [IN] the xpaths of the properties to read          *
+ *             props_num - [IN] the number of properties to read              *
+ *                                                                            *
+ * Return value: an array of property values                                  *
+ *                                                                            *
+ * Comments: The array with property values must be freed by the caller.      *
+ *                                                                            *
+ ******************************************************************************/
+static char	**xml_read_props(const char *xml, char **propmap, int props_num)
+{
+	xmlDoc		*doc;
+	xmlXPathContext	*xpathCtx;
+	xmlXPathObject	*xpathObj;
+	xmlNodeSetPtr	nodeset;
+	xmlChar		*val;
+	char		**props;
+	int		i;
+
+	if (NULL == (doc = xmlReadMemory(xml, strlen(xml), ZBX_VM_NONAME_XML, NULL, 0)))
+		return NULL;
+
+	props = (char **)zbx_malloc(NULL, sizeof(char *) * props_num);
+	memset(props, 0, sizeof(char *) * props_num);
+
+	for (i = 0; i < props_num; i++)
+	{
+		xpathCtx = xmlXPathNewContext(doc);
+
+		if (NULL != (xpathObj = xmlXPathEvalExpression((const xmlChar *)propmap[i], xpathCtx)))
+		{
+			if (0 == xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+			{
+				nodeset = xpathObj->nodesetval;
+
+				if (NULL != (val = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1)))
+				{
+					props[i] = zbx_strdup(NULL, (char *)val);
+					xmlFree(val);
+				}
+			}
+
+			xmlXPathFreeObject(xpathObj);
+		}
+
+		xmlXPathFreeContext(xpathCtx);
+	}
+
+	xmlFreeDoc(doc);
+
+	return props;
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_shared_strdup                                             *
  *                                                                            *
  * Purpose: duplicates the specified string into shared memory                *
@@ -401,6 +486,32 @@ static void	vmware_datastore_shared_free(zbx_vmware_datastore_t *datastore)
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_props_shared_free                                         *
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store properties list         *
+ *                                                                            *
+ * Parameters: props     - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_props_shared_free(char **props, int props_num)
+{
+	int	i;
+
+	if (NULL == props)
+		return;
+
+	for (i = 0; i < props_num; i++)
+	{
+		if (NULL != props[i])
+			__vm_mem_free_func(props[i]);
+	}
+
+	__vm_mem_free_func(props);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_dev_shared_free                                           *
  *                                                                            *
  * Purpose: frees shared resources allocated to store vm device data          *
@@ -468,11 +579,10 @@ static void	vmware_hv_shared_clean(zbx_vmware_hv_t *hv)
 	if (NULL != hv->id)
 		__vm_mem_free_func(hv->id);
 
-	if (NULL != hv->details)
-		__vm_mem_free_func(hv->details);
-
 	if (NULL != hv->clusterid)
 		__vm_mem_free_func(hv->clusterid);
+
+	vmware_props_shared_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
 }
 
 /******************************************************************************
@@ -683,6 +793,31 @@ static zbx_vmware_dev_t	*vmware_dev_shared_dup(const zbx_vmware_dev_t *src)
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_props_shared_dup                                          *
+ *                                                                            *
+ * Purpose: copies object properties list into shared memory                  *
+ *                                                                            *
+ * Parameters: src       - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ * Return value: a duplicated object properties list                          *
+ *                                                                            *
+ ******************************************************************************/
+static char	**vmware_props_shared_dup(char ** const src, int props_num)
+{
+	char	**props;
+	int	i;
+
+	props = __vm_mem_malloc_func(NULL, sizeof(char *) * props_num);
+
+	for (i = 0; i < props_num; i++)
+		props[i] = vmware_shared_strdup(src[i]);
+
+	return props;
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_vm_shared_dup                                             *
  *                                                                            *
  * Purpose: copies vmware virtual machine object into shared memory           *
@@ -731,9 +866,10 @@ static	void	vmware_hv_shared_copy(zbx_vmware_hv_t *dst, const zbx_vmware_hv_t *s
 
 	dst->uuid = vmware_shared_strdup(src->uuid);
 	dst->id = vmware_shared_strdup(src->id);
-	dst->details = vmware_shared_strdup(src->details);
 	dst->clusterid = vmware_shared_strdup(src->clusterid);
 
+	dst->props = vmware_props_shared_dup(src->props, ZBX_VMWARE_HVPROPS_NUM);
+
 	for (i = 0; i < src->datastores.values_num; i++)
 		zbx_vector_ptr_append(&dst->datastores, vmware_datastore_shared_dup(src->datastores.values[i]));
 
@@ -810,6 +946,29 @@ static void	vmware_datastore_free(zbx_vmware_datastore_t *datastore)
 
 /******************************************************************************
  *                                                                            *
+ * Function: vmware_props_free                                                *
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store properties list         *
+ *                                                                            *
+ * Parameters: props     - [IN] the properties list                           *
+ *             props_num - [IN] the number of properties in the list          *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_props_free(char **props, int props_num)
+{
+	int	i;
+
+	if (NULL == props)
+		return;
+
+	for (i = 0; i < props_num; i++)
+		zbx_free(props[i]);
+
+	zbx_free(props);
+}
+
+/******************************************************************************
+ *                                                                            *
  * Function: vmware_dev_free                                                  *
  *                                                                            *
  * Purpose: frees resources allocated to store vm device data                 *
@@ -863,8 +1022,9 @@ static void	vmware_hv_clean(zbx_vmware_hv_t *hv)
 
 	zbx_free(hv->uuid);
 	zbx_free(hv->id);
-	zbx_free(hv->details);
 	zbx_free(hv->clusterid);
+
+	vmware_props_free(hv->props, ZBX_VMWARE_HVPROPS_NUM);
 }
 
 /******************************************************************************
@@ -1834,7 +1994,7 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 		zbx_vmware_hv_t *hv, char **error)
 {
 	const char		*__function_name = "vmware_service_init_hv";
-	char			*value;
+	char			*value, *details;
 	zbx_vector_str_t	datastores, vms;
 	int			i, ret = FAIL;
 
@@ -1848,21 +2008,21 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 	zbx_vector_str_create(&datastores);
 	zbx_vector_str_create(&vms);
 
-	if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, &hv->details, error))
+	if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, &details, error))
 		goto out;
 
-	if (NULL == (value = zbx_xml_read_value(hv->details, ZBX_XPATH_HV_HARDWARE("uuid"))))
+	hv->props = xml_read_props(details, hv_propmap, ZBX_VMWARE_HVPROPS_NUM);
+
+	if (NULL == hv->props[ZBX_VMWARE_HVPROP_HW_UUID])
 		goto out;
 
-	hv->uuid = value;
+	hv->uuid = zbx_strdup(NULL, hv->props[ZBX_VMWARE_HVPROP_HW_UUID]);
 	hv->id = zbx_strdup(NULL, id);
 
-	if (NULL != (value = zbx_xml_read_value(hv->details, "//*[@type='ClusterComputeResource']")))
-	{
+	if (NULL != (value = zbx_xml_read_value(details, "//*[@type='ClusterComputeResource']")))
 		hv->clusterid = value;
-	}
 
-	zbx_xml_read_values(hv->details, ZBX_XPATH_HV_DATASTORES(), &datastores);
+	zbx_xml_read_values(details, ZBX_XPATH_HV_DATASTORES(), &datastores);
 
 	for (i = 0; i < datastores.values_num; i++)
 	{
@@ -1872,7 +2032,7 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 			zbx_vector_ptr_append(&hv->datastores, datastore);
 	}
 
-	zbx_xml_read_values(hv->details, ZBX_XPATH_HV_VMS(), &vms);
+	zbx_xml_read_values(details, ZBX_XPATH_HV_VMS(), &vms);
 
 	for (i = 0; i < vms.values_num; i++)
 	{
@@ -1884,6 +2044,8 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 
 	ret = SUCCEED;
 out:
+	zbx_free(details);
+
 	zbx_vector_str_clean(&vms);
 	zbx_vector_str_destroy(&vms);
 
diff --git a/src/zabbix_server/vmware/vmware.h b/src/zabbix_server/vmware/vmware.h
index c7733e6..cfac2c4 100644
--- a/src/zabbix_server/vmware/vmware.h
+++ b/src/zabbix_server/vmware/vmware.h
@@ -95,6 +95,7 @@ typedef struct
 	char			*uuid;
 	char			*id;
 	char			*details;
+	char			**props;
 	zbx_vector_ptr_t	devs;
 }
 zbx_vmware_vm_t;
@@ -104,8 +105,8 @@ typedef struct
 {
 	char			*uuid;
 	char			*id;
-	char			*details;
 	char			*clusterid;
+	char			**props;
 	zbx_vector_ptr_t	datastores;
 	zbx_vector_ptr_t	vms;
 }
@@ -275,6 +276,25 @@ char	*zbx_xml_read_value(const char *data, const char *xpath);
 char	*zbx_xml_read_node_value(xmlDoc *doc, xmlNode *node, const char *xpath);
 int	zbx_xml_read_values(const char *data, const char *xpath, zbx_vector_str_t *values);
 
+/* hypervisor properties */
+#define ZBX_VMWARE_HVPROP_OVERALL_CPU_USAGE		0
+#define ZBX_VMWARE_HVPROP_FULL_NAME			1
+#define ZBX_VMWARE_HVPROP_HW_NUM_CPU_CORES		2
+#define ZBX_VMWARE_HVPROP_HW_CPU_MHZ			3
+#define ZBX_VMWARE_HVPROP_HW_CPU_MODEL			4
+#define ZBX_VMWARE_HVPROP_HW_NUM_CPU_THREADS		5
+#define ZBX_VMWARE_HVPROP_HW_MEMORY_SIZE		6
+#define ZBX_VMWARE_HVPROP_HW_MODEL			7
+#define ZBX_VMWARE_HVPROP_HW_UUID			8
+#define ZBX_VMWARE_HVPROP_HW_VENDOR			9
+#define ZBX_VMWARE_HVPROP_MEMORY_USED			10
+#define ZBX_VMWARE_HVPROP_STATUS			11
+#define ZBX_VMWARE_HVPROP_UPTIME			12
+#define ZBX_VMWARE_HVPROP_VERSION			13
+#define ZBX_VMWARE_HVPROP_NAME				14
+
+#define ZBX_VMWARE_HVPROPS_NUM				15
+
 #endif	/* defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL) */
 
 #endif	/* ZABBIX_VMWARE_H */
-- 
2.1.4

