diff --git a/ChangeLog.d/feature/ZBXNEXT-6401 b/ChangeLog.d/feature/ZBXNEXT-6401
new file mode 100644
index 00000000000..bc2475154d2
--- /dev/null
+++ b/ChangeLog.d/feature/ZBXNEXT-6401
@@ -0,0 +1 @@
+.......PS. [ZBXNEXT-6401] added new vmware keys vmware.datastore.perfcounter and vmware.hv.diskinfo.get (MVekslers)
diff --git a/include/common.h b/include/common.h
index 917a7bbefc3..2d2610c5569 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1315,6 +1315,7 @@ zbx_uint64_t	iprange_volume(const zbx_iprange_t *iprange);
 char	*zbx_age2str(int age);
 char	*zbx_date2str(time_t date, const char *tz);
 char	*zbx_time2str(time_t time, const char *tz);
+int	zbx_iso8601_utc(const char *str, time_t *time);
 
 #define ZBX_NULL2STR(str)	(NULL != str ? str : "(null)")
 #define ZBX_NULL2EMPTY_STR(str)	(NULL != (str) ? (str) : "")
diff --git a/include/zbxxml.h b/include/zbxxml.h
index 378973b919a..8a7217239ba 100644
--- a/include/zbxxml.h
+++ b/include/zbxxml.h
@@ -50,6 +50,7 @@ int	zbx_xml_node_read_values(xmlDoc *xdoc, xmlNode *node, const char *xpath, zbx
 int	zbx_xml_try_read_value(const char *data, size_t len, const char *xpath, xmlDoc **xdoc, char **value,
 		char **error);
 int	zbx_xml_doc_read_num(xmlDoc *xdoc, const char *xpath, int *num);
+int	zbx_xml_node_read_num(xmlDoc *xdoc, xmlNode *node, const char *xpath, int *num);
 char	*zbx_xml_node_read_value(xmlDoc *xdoc, xmlNode *node, const char *xpath);
 char	*zbx_xml_doc_read_value(xmlDoc *xdoc, const char *xpath);
 xmlNode	*zbx_xml_node_get(xmlDoc *xdoc, xmlNode *node, const char *xpath);
diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c
index c3064662055..6526be2c8d6 100644
--- a/src/libs/zbxcommon/str.c
+++ b/src/libs/zbxcommon/str.c
@@ -5915,3 +5915,141 @@ void	zbx_rtrim_utf8(char *str, const char *charlist)
 
 	*last = '\0';
 }
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: convert string from iso8601 timezone info to offset in seconds    *
+ *                                                                            *
+ * Parameters: zone    - [IN] iso8601 timezone string                         *
+ *             offset  - [OUT] offset value                                   *
+ *                                                                            *
+ * Return value: SUCCEED   - the operation has completed successfully         *
+ *               FAIL      - the operation has failed                         *
+ *                                                                            *
+ ******************************************************************************/
+static int zbx_iso8601_timezone(const char *zone, long int *offset)
+{
+	int		m, h, sign = 0;
+	char		c;
+	const char	*ptr = zone;
+
+	if ('.' == *zone)	/* skip milliseconds */
+	{
+		for (ptr++; 0 != isdigit(*ptr); ptr++)
+			;
+	}
+
+	for (; ' ' == *ptr; ptr++)
+		;
+
+	*offset = 0;
+	c = *ptr;
+
+	if ('\0' == c || 'Z' == c || 'z' == c)
+		return SUCCEED;
+	else if ('-' == c)
+		sign = -1;
+	else if ('+' == c)
+		sign = +1;
+	else
+		return FAIL;
+
+	ptr++;
+
+	if (ZBX_CONST_STRLEN("00:00") > strlen(ptr) || ':' != ptr[2])
+		return FAIL;
+
+	if (0 == isdigit(*ptr) || 23 < (h = atoi(ptr)))
+		return FAIL;
+
+	if (0 == isdigit(ptr[3]) || 59 < (m = atoi(&ptr[3])))
+		return FAIL;
+
+	*offset = sign * (m + h * 60) * 60;
+
+	return SUCCEED;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: parse string from iso8601 datetime (xml base) to UTC              *
+ *          without millisecond, supported formats:                           *
+ *              yyyy-mm-ddThh:mm:ss                                          *
+ *              yyyy-mm-ddThh:mm:ssZ                                          *
+ *              yyyy-mm-ddThh:mm:ss+hh:mm                                     *
+ *              yyyy-mm-ddThh:mm:ss-hh:mm                                     *
+ *              yyyy-mm-ddThh:mm:ss +hh:mm                                    *
+ *              yyyy-mm-ddThh:mm:ss -hh:mm                                    *
+ *              yyyy-mm-ddThh:mm:ss.ccc                                       *
+ *              yyyy-mm-ddThh:mm:ss.cccZ                                      *
+ *              yyyy-mm-ddThh:mm:ss.ccc+hh:mm                                 *
+ *              yyyy-mm-ddThh:mm:ss.ccc-hh:mm                                 *
+ *              yyyy-mm-ddThh:mm:ss.ccc +hh:mm                                *
+ *              yyyy-mm-ddThh:mm:ss.ccc -hh:mm                                *
+ *              yyyy-mm-dd hh:mm:ss                                          *
+ *              yyyy-mm-dd hh:mm:ssZ                                          *
+ *              yyyy-mm-dd hh:mm:ss+hh:mm                                     *
+ *              yyyy-mm-dd hh:mm:ss-hh:mm                                     *
+ *              yyyy-mm-dd hh:mm:ss +hh:mm                                    *
+ *              yyyy-mm-dd hh:mm:ss -hh:mm                                    *
+ *              yyyy-mm-dd hh:mm:ss.ccc                                       *
+ *              yyyy-mm-dd hh:mm:ss.cccZ                                      *
+ *              yyyy-mm-dd hh:mm:ss.ccc+hh:mm                                 *
+ *              yyyy-mm-dd hh:mm:ss.ccc-hh:mm                                 *
+ *              yyyy-mm-dd hh:mm:ss.ccc +hh:mm                                *
+ *              yyyy-mm-dd hh:mm:ss.ccc -hh:mm                                *
+ *                                                                            *
+ * Parameters: str  - [IN] iso8601 datetime string                            *
+ *             time - [OUT] parsed tm value                                   *
+ *                                                                            *
+ * Return value: SUCCEED   - the operation has completed successfully         *
+ *               FAIL      - the operation has failed                         *
+ *                                                                            *
+ ******************************************************************************/
+int	zbx_iso8601_utc(const char *str, time_t *time)
+{
+	struct tm	tm;
+
+	if ( 0 == isdigit(*str) || ZBX_CONST_STRLEN("1234-12-12T12:12:12") > strlen(str) ||
+			('T' != str[10] && ' ' != str[10]) ||
+			'-' != str[4] || '-' != str[7] || ':' != str[13] || ':' != str[16])
+	{
+		return FAIL;
+	}
+
+	memset(&tm, 0 , sizeof (struct tm));
+	tm.tm_year = atoi(str);
+
+	if (0 == isdigit(str[5]) || 12 < (tm.tm_mon = atoi(&str[5])))
+		return FAIL;
+
+	if (0 == isdigit(str[8]) || 31 < (tm.tm_mday = atoi(&str[8])))
+		return FAIL;
+
+	if (0 == isdigit(str[11]) || 23 < (tm.tm_hour = atoi(&str[11])))
+		return FAIL;
+
+	if (0 == isdigit(str[14]) || 59 < (tm.tm_min = atoi(&str[14])))
+		return FAIL;
+
+	if (0 == isdigit(str[17]) || 59 < (tm.tm_sec = atoi(&str[17])))
+		return FAIL;
+
+	tm.tm_isdst = 0;
+
+#ifdef HAVE_TM_TM_GMTOFF
+	if (FAIL == zbx_iso8601_timezone(&str[19], &tm.tm_gmtoff))
+		return FAIL;
+#endif
+	if (NULL != time)
+	{
+		int	t;
+
+		if(FAIL == zbx_utc_time(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, &t))
+			return FAIL;
+
+		*time = t - tm.tm_gmtoff;
+	}
+
+	return SUCCEED;
+}
diff --git a/src/libs/zbxxml/xml.c b/src/libs/zbxxml/xml.c
index 8230b21acaa..d76ec040d11 100644
--- a/src/libs/zbxxml/xml.c
+++ b/src/libs/zbxxml/xml.c
@@ -1260,6 +1260,24 @@ out:
  *                                                                            *
  ******************************************************************************/
 int	zbx_xml_doc_read_num(xmlDoc *xdoc, const char *xpath, int *num)
+{
+	return zbx_xml_node_read_num(xdoc, NULL, xpath, num);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: retrieves numeric xpath value                                     *
+ *                                                                            *
+ * Parameters: xdoc  - [IN] xml document                                      *
+ *             node  - [IN] the XML node                                     *
+ *             xpath - [IN] xpath                                             *
+ *             num   - [OUT] numeric value                                    *
+ *                                                                            *
+ * Return value: SUCCEED - the count was retrieved successfully               *
+ *               FAIL    - otherwise                                          *
+ *                                                                            *
+ ******************************************************************************/
+int	zbx_xml_node_read_num(xmlDoc *xdoc, xmlNode *node, const char *xpath, int *num)
 {
 	int		ret = FAIL;
 	xmlXPathContext	*xpathCtx;
@@ -1267,6 +1285,9 @@ int	zbx_xml_doc_read_num(xmlDoc *xdoc, const char *xpath, int *num)
 
 	xpathCtx = xmlXPathNewContext(xdoc);
 
+	if (NULL != node)
+		xpathCtx->node = node;
+
 	if (NULL == (xpathObj = xmlXPathEvalExpression((const xmlChar *)xpath, xpathCtx)))
 		goto out;
 
diff --git a/src/zabbix_server/poller/checks_simple.c b/src/zabbix_server/poller/checks_simple.c
index bbee69de02a..634e7b4ba3a 100644
--- a/src/zabbix_server/poller/checks_simple.c
+++ b/src/zabbix_server/poller/checks_simple.c
@@ -56,6 +56,7 @@ static zbx_vmcheck_t	vmchecks[] =
 	{"datastore.discovery", VMCHECK_FUNC(check_vcenter_datastore_discovery)},
 	{"datastore.tags.get", VMCHECK_FUNC(check_vcenter_datastore_tags_get)},
 	{"datastore.read", VMCHECK_FUNC(check_vcenter_datastore_read)},
+	{"datastore.perfcounter", VMCHECK_FUNC(check_vcenter_datastore_perfcounter)},
 	{"datastore.property", VMCHECK_FUNC(check_vcenter_datastore_property)},
 	{"datastore.size", VMCHECK_FUNC(check_vcenter_datastore_size)},
 	{"datastore.write", VMCHECK_FUNC(check_vcenter_datastore_write)},
@@ -76,6 +77,7 @@ static zbx_vmcheck_t	vmchecks[] =
 	{"hv.datastore.list", VMCHECK_FUNC(check_vcenter_hv_datastore_list)},
 	{"hv.datastore.multipath", VMCHECK_FUNC(check_vcenter_hv_datastore_multipath)},
 	{"hv.discovery", VMCHECK_FUNC(check_vcenter_hv_discovery)},
+	{"hv.diskinfo.get", VMCHECK_FUNC(check_vcenter_hv_diskinfo_get)},
 	{"hv.fullname", VMCHECK_FUNC(check_vcenter_hv_fullname)},
 	{"hv.hw.cpu.num", VMCHECK_FUNC(check_vcenter_hv_hw_cpu_num)},
 	{"hv.hw.cpu.freq", VMCHECK_FUNC(check_vcenter_hv_hw_cpu_freq)},
diff --git a/src/zabbix_server/poller/checks_simple_vmware.c b/src/zabbix_server/poller/checks_simple_vmware.c
index 4df656395d4..cab488b5e8e 100644
--- a/src/zabbix_server/poller/checks_simple_vmware.c
+++ b/src/zabbix_server/poller/checks_simple_vmware.c
@@ -301,6 +301,18 @@ static int	vmware_service_get_counter_value_by_id(zbx_vmware_service_t *service,
 
 	perfcounter = (zbx_vmware_perf_counter_t *)entity->counters.values[i];
 
+	if (0 != (perfcounter->state & ZBX_VMWARE_COUNTER_NOTSUPPORTED))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Performance counter not supported or data not ready."));
+		goto out;
+	}
+
+	if (0 != (ZBX_VMWARE_COUNTER_CUSTOM & perfcounter->state) &&
+			0 != (ZBX_VMWARE_COUNTER_READY & perfcounter->state))
+	{
+		perfcounter->last_used = time(NULL);
+	}
+
 	if (0 == (perfcounter->state & ZBX_VMWARE_COUNTER_READY))
 	{
 		ret = SYSINFO_RET_OK;
@@ -644,18 +656,20 @@ static int	custquery_read_result(zbx_vmware_cust_query_t *custom_query, AGENT_RE
 	}
 
 	if (0 != (custom_query->state & ZBX_VMWARE_CQ_READY))
+	{
 		SET_STR_RESULT(result, zbx_strdup(NULL, ZBX_NULL2EMPTY_STR(custom_query->value)));
 
-	if (0 != (custom_query->state & ZBX_VMWARE_CQ_PAUSED))
-		custom_query->state &= (unsigned char)~ZBX_VMWARE_CQ_PAUSED;
+		if (0 != (custom_query->state & ZBX_VMWARE_CQ_PAUSED))
+			custom_query->state &= (unsigned char)~ZBX_VMWARE_CQ_PAUSED;
 
-	if (NULL != custom_query->value && '\0' != *custom_query->value &&
-			0 != (custom_query->state & ZBX_VMWARE_CQ_SEPARATE))
-	{
-		custom_query->state &= (unsigned char)~ZBX_VMWARE_CQ_SEPARATE;
-	}
+		if (NULL != custom_query->value && '\0' != *custom_query->value &&
+				0 != (custom_query->state & ZBX_VMWARE_CQ_SEPARATE))
+		{
+			custom_query->state &= (unsigned char)~ZBX_VMWARE_CQ_SEPARATE;
+		}
 
-	custom_query->last_pooled = time(NULL);
+		custom_query->last_pooled = time(NULL);
+	}
 
 	return SYSINFO_RET_OK;
 }
@@ -789,6 +803,12 @@ int	check_vcenter_cluster_discovery(AGENT_REQUEST *request, const char *username
 		zbx_json_close(&json_data);
 		zbx_json_addarray(&json_data, "tags");
 		vmware_tags_id_json(&service->data_tags, ZBX_VMWARE_SOAP_CLUSTER, cluster->id, &json_data, NULL);
+		zbx_json_close(&json_data);
+		zbx_json_addarray(&json_data, "datastore_uuid");
+
+		for (j = 0; j < cluster->dss_uuid.values_num; j++)
+			zbx_json_addstring(&json_data, NULL, cluster->dss_uuid.values[j], ZBX_JSON_TYPE_STRING);
+
 		zbx_json_close(&json_data);
 		zbx_json_close(&json_data);
 	}
@@ -1406,7 +1426,7 @@ int	check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, con
 		AGENT_RESULT *result)
 {
 	struct zbx_json		json_data;
-	const char		*url, *name;
+	const char		*url;
 	zbx_vmware_service_t	*service;
 	int			ret = SYSINFO_RET_FAIL;
 	zbx_vmware_hv_t		*hv;
@@ -1433,6 +1453,7 @@ int	check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, con
 	while (NULL != (hv = (zbx_vmware_hv_t *)zbx_hashset_iter_next(&iter)))
 	{
 		int			i;
+		const char		*name;
 		zbx_vmware_cluster_t	*cluster = NULL;
 
 		if (NULL == (name = hv->props[ZBX_VMWARE_HVPROP_NAME]))
@@ -1495,6 +1516,98 @@ out:
 	return ret;
 }
 
+int	check_vcenter_hv_diskinfo_get(AGENT_REQUEST *request, const char *username, const char *password,
+		AGENT_RESULT *result)
+{
+	struct zbx_json		json_data;
+	const char		*url, *uuid;
+	zbx_vmware_service_t	*service;
+	int			i, ret = SYSINFO_RET_FAIL;
+	zbx_vmware_hv_t		*hv;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+	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;
+	}
+
+	zbx_json_initarray(&json_data, ZBX_JSON_STAT_BUF_LEN);
+
+	for (i = 0; i < hv->diskinfo.values_num; i++)
+	{
+		zbx_vmware_diskinfo_t	*di = hv->diskinfo.values[i];
+
+		zbx_json_addobject(&json_data, NULL);
+		zbx_json_addstring(&json_data, "instance", di->diskname,
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "hv_uuid", hv->uuid, ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "datastore_uuid", ZBX_NULL2EMPTY_STR(di->ds_uuid),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addraw(&json_data, "operational_state", ZBX_NULL2EMPTY_STR(di->operational_state));
+		zbx_json_addstring(&json_data, "lun_type", ZBX_NULL2EMPTY_STR(di->lun_type),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addint64(&json_data, "queue_depth", di->queue_depth);
+		zbx_json_addstring(&json_data, "model", ZBX_NULL2EMPTY_STR(di->model),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "vendor", ZBX_NULL2EMPTY_STR(di->vendor),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "revision", ZBX_NULL2EMPTY_STR(di->revision),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "serial_number", ZBX_NULL2EMPTY_STR(di->serial_number),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addobject(&json_data, "vsan");
+
+		if (NULL != di->vsan)
+		{
+			zbx_json_addstring(&json_data, "ssd", ZBX_NULL2EMPTY_STR(di->vsan->ssd),
+					ZBX_JSON_TYPE_STRING);
+			zbx_json_addstring(&json_data, "local_disk", ZBX_NULL2EMPTY_STR(di->vsan->local_disk),
+					ZBX_JSON_TYPE_STRING);
+			zbx_json_adduint64(&json_data, "block", di->vsan->block);
+			zbx_json_adduint64(&json_data, "block_size", di->vsan->block_size);
+		}
+
+		zbx_json_close(&json_data);
+		zbx_json_close(&json_data);
+	}
+
+	zbx_json_close(&json_data);
+
+	SET_STR_RESULT(result, zbx_strdup(NULL, json_data.buffer));
+
+	zbx_json_free(&json_data);
+
+	ret = SYSINFO_RET_OK;
+unlock:
+	zbx_vmware_unlock();
+out:
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_sysinfo_ret_string(ret));
+
+	return ret;
+}
+
 int	check_vcenter_hv_fullname(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result)
 {
@@ -2309,17 +2422,41 @@ int	check_vcenter_hv_datastore_discovery(AGENT_REQUEST *request, const char *use
 	for (i = 0; i < hv->dsnames.values_num; i++)
 	{
 		zbx_vmware_dsname_t	*dsname = hv->dsnames.values[i];
+		zbx_vmware_datastore_t	*datastore;
 		int			j, total = 0;
 
+		if (NULL == (datastore = ds_get(&service->data->datastores, dsname->uuid)))
+		{
+			zbx_json_free(&json_data);
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown datastore uuid."));
+			goto unlock;
+		}
+
 		for (j = 0; j < dsname->hvdisks.values_num; j++)
 			total += dsname->hvdisks.values[j].multipath_total;
 
 		zbx_json_addobject(&json_data, NULL);
 		zbx_json_addstring(&json_data, "{#DATASTORE}", dsname->name, ZBX_JSON_TYPE_STRING);
 		zbx_json_addstring(&json_data, "{#DATASTORE.UUID}", dsname->uuid, ZBX_JSON_TYPE_STRING);
+		zbx_json_addstring(&json_data, "{#DATASTORE.TYPE}", ZBX_NULL2EMPTY_STR(datastore->type),
+				ZBX_JSON_TYPE_STRING);
 		zbx_json_adduint64(&json_data, "{#MULTIPATH.COUNT}", (unsigned int)total);
 		zbx_json_adduint64(&json_data, "{#MULTIPATH.PARTITION.COUNT}",
 				(unsigned int)dsname->hvdisks.values_num);
+		zbx_json_addarray(&json_data, "datastore_extent");
+
+		for (j = 0; j < datastore->diskextents.values_num; j++)
+		{
+			zbx_vmware_diskextent_t	*ext = datastore->diskextents.values[j];
+
+			zbx_json_addobject(&json_data, NULL);
+			zbx_json_adduint64(&json_data, "partitionid", ext->partitionid);
+			zbx_json_addstring(&json_data, "instance", ext->diskname,
+					ZBX_JSON_TYPE_STRING);
+			zbx_json_close(&json_data);
+		}
+
+		zbx_json_close(&json_data);
 		zbx_json_addarray(&json_data, "tags");
 		vmware_tags_uuid_json(&service->data_tags, dsname->uuid, &json_data, NULL);
 		zbx_json_close(&json_data);
@@ -2967,15 +3104,15 @@ int	check_vcenter_cl_perfcounter(AGENT_REQUEST *request, const char *username, c
 	}
 
 	/* FAIL is returned if counter already exists */
-	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, "ClusterComputeResource", cluster->id,
-			counterid, "*"))
+	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_CLUSTER, cluster->id,
+			counterid, ZBX_VMWARE_PERF_QUERY_ALL))
 	{
 		ret = SYSINFO_RET_OK;
 		goto unlock;
 	}
 
 	/* the performance counter is already being monitored, try to get the results from statistics */
-	ret = vmware_service_get_counter_value_by_id(service, "ClusterComputeResource", cluster->id, counterid,
+	ret = vmware_service_get_counter_value_by_id(service, ZBX_VMWARE_SOAP_CLUSTER, cluster->id, counterid,
 			instance, 1, unit, result);
 unlock:
 	zbx_vmware_unlock();
@@ -3028,14 +3165,15 @@ int	check_vcenter_hv_perfcounter(AGENT_REQUEST *request, const char *username, c
 	}
 
 	/* FAIL is returned if counter already exists */
-	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, "HostSystem", hv->id, counterid, "*"))
+	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_HV, hv->id, counterid,
+			ZBX_VMWARE_PERF_QUERY_ALL))
 	{
 		ret = SYSINFO_RET_OK;
 		goto unlock;
 	}
 
 	/* the performance counter is already being monitored, try to get the results from statistics */
-	ret = vmware_service_get_counter_value_by_id(service, "HostSystem", hv->id, counterid, instance, 1, unit,
+	ret = vmware_service_get_counter_value_by_id(service, ZBX_VMWARE_SOAP_HV, hv->id, counterid, instance, 1, unit,
 			result);
 unlock:
 	zbx_vmware_unlock();
@@ -3276,6 +3414,67 @@ out:
 	return ret;
 }
 
+int	check_vcenter_datastore_perfcounter(AGENT_REQUEST *request, const char *username, const char *password,
+		AGENT_RESULT *result)
+{
+	const char		*instance, *url, *uuid, *path;
+	zbx_vmware_service_t	*service;
+	zbx_vmware_datastore_t	*ds;
+	zbx_uint64_t		counterid;
+	int			unit, ret = SYSINFO_RET_FAIL;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
+
+	if (3 > request->nparam || request->nparam > 4)
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
+		goto out;
+	}
+
+	url = get_rparam(request, 0);
+	uuid = get_rparam(request, 1);
+	path = get_rparam(request, 2);
+	instance = get_rparam(request, 3);
+
+	if (NULL == instance)
+		instance = "";
+
+	zbx_vmware_lock();
+
+	if (NULL == (service = get_vmware_service(url, username, password, result, &ret)))
+		goto unlock;
+
+	if (NULL == (ds = ds_get(&service->data->datastores, uuid)))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unknown datastore uuid."));
+		goto unlock;
+	}
+
+	if (FAIL == zbx_vmware_service_get_counterid(service, path, &counterid, &unit))
+	{
+		SET_MSG_RESULT(result, zbx_strdup(NULL, "Performance counter is not available."));
+		goto unlock;
+	}
+
+	/* FAIL is returned if counter already exists */
+	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_DS, ds->id, counterid,
+			ZBX_VMWARE_PERF_QUERY_ALL))
+	{
+		ret = SYSINFO_RET_OK;
+		goto unlock;
+	}
+
+	/* the performance counter is already being monitored, try to get the results from statistics */
+	ret = vmware_service_get_counter_value_by_id(service, ZBX_VMWARE_SOAP_DS, ds->id, counterid, instance, 1, unit,
+			result);
+unlock:
+	zbx_vmware_unlock();
+out:
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_sysinfo_ret_string(ret));
+
+	return ret;
+}
+
 int	check_vcenter_datastore_property(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result)
 {
@@ -3407,18 +3606,23 @@ int	check_vcenter_datastore_discovery(AGENT_REQUEST *request, const char *userna
 	for (i = 0; i < service->data->datastores.values_num; i++)
 	{
 		zbx_vmware_datastore_t	*datastore = service->data->datastores.values[i];
+
 		zbx_json_addobject(&json_data, NULL);
 		zbx_json_addstring(&json_data, "{#DATASTORE}", datastore->name, ZBX_JSON_TYPE_STRING);
 		zbx_json_addstring(&json_data, "{#DATASTORE.UUID}", datastore->uuid, ZBX_JSON_TYPE_STRING);
-		zbx_json_addobject(&json_data, "{#DATASTORE.EXTENT}");
+		zbx_json_addstring(&json_data, "{#DATASTORE.TYPE}", ZBX_NULL2EMPTY_STR(datastore->type),
+				ZBX_JSON_TYPE_STRING);
+		zbx_json_addarray(&json_data, "datastore_extent");
 
 		for (j = 0; j < datastore->diskextents.values_num; j++)
 		{
-			char			buffer[MAX_ID_LEN];
-			zbx_vmware_diskextent_t	*extent = datastore->diskextents.values[j];
+			zbx_vmware_diskextent_t	*ext = datastore->diskextents.values[j];
 
-			zbx_snprintf(buffer, sizeof(buffer), ZBX_FS_UI64, extent->partitionid);
-			zbx_json_addstring(&json_data, extent->diskname, buffer, ZBX_JSON_TYPE_INT);
+			zbx_json_addobject(&json_data, NULL);
+			zbx_json_adduint64(&json_data, "partitionid", ext->partitionid);
+			zbx_json_addstring(&json_data, "instance", ext->diskname,
+					ZBX_JSON_TYPE_STRING);
+			zbx_json_close(&json_data);
 		}
 
 		zbx_json_close(&json_data);
@@ -4106,7 +4310,7 @@ int	check_vcenter_vm_discovery(AGENT_REQUEST *request, const char *username, con
 			else
 				zbx_json_addstring(&json_data, "{#VM.RPOOL.PATH}", "", ZBX_JSON_TYPE_STRING);
 
-			zbx_json_addarray(&json_data, "vm.customattribute");
+			zbx_json_addarray(&json_data, "vm_customattribute");
 
 			for (j = 0; j < vm->custom_attrs.values_num; j++)
 			{
@@ -5019,14 +5223,15 @@ int	check_vcenter_vm_perfcounter(AGENT_REQUEST *request, const char *username, c
 	}
 
 	/* FAIL is returned if counter already exists */
-	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, "VirtualMachine", vm->id, counterid, "*"))
+	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_VM, vm->id, counterid,
+			ZBX_VMWARE_PERF_QUERY_ALL))
 	{
 		ret = SYSINFO_RET_OK;
 		goto unlock;
 	}
 
 	/* the performance counter is already being monitored, try to get the results from statistics */
-	ret = vmware_service_get_counter_value_by_id(service, "VirtualMachine", vm->id, counterid, instance, 1, unit,
+	ret = vmware_service_get_counter_value_by_id(service, ZBX_VMWARE_SOAP_VM, vm->id, counterid, instance, 1, unit,
 			result);
 unlock:
 	zbx_vmware_unlock();
@@ -5618,7 +5823,8 @@ static int	check_vcenter_rp_common(const char *url, const char *username, const
 	}
 
 	/* FAIL is returned if counter already exists */
-	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_RESOURCEPOOL, rpid, counterid, ""))
+	if (SUCCEED == zbx_vmware_service_add_perf_counter(service, ZBX_VMWARE_SOAP_RESOURCEPOOL, rpid, counterid,
+			ZBX_VMWARE_PERF_QUERY_TOTAL))
 	{
 		ret = SYSINFO_RET_OK;
 		goto unlock;
@@ -5888,4 +6094,20 @@ int	check_vcenter_alarms_get(AGENT_REQUEST *request, const char *username, const
 #undef	ALARMS_GET_START
 #undef	ALARMS_GET_END
 
+#undef	ZBX_VMWARE_DATASTORE_SIZE_TOTAL
+#undef	ZBX_VMWARE_DATASTORE_SIZE_FREE
+#undef	ZBX_VMWARE_DATASTORE_SIZE_PFREE
+#undef	ZBX_VMWARE_DATASTORE_SIZE_UNCOMMITTED
+
+#undef	ZBX_DATASTORE_TOTAL
+#undef	ZBX_DATASTORE_COUNTER_CAPACITY
+#undef	ZBX_DATASTORE_COUNTER_USED
+#undef	ZBX_DATASTORE_COUNTER_PROVISIONED
+
+#undef	ZBX_DATASTORE_DIRECTION_READ
+#undef	ZBX_DATASTORE_DIRECTION_WRITE
+
+#undef	ZBX_IF_DIRECTION_IN
+#undef	ZBX_IF_DIRECTION_OUT
+
 #endif	/* defined(HAVE_LIBXML2) && defined(HAVE_LIBCURL) */
diff --git a/src/zabbix_server/poller/checks_simple_vmware.h b/src/zabbix_server/poller/checks_simple_vmware.h
index a9ba97c9f07..dcb55362960 100644
--- a/src/zabbix_server/poller/checks_simple_vmware.h
+++ b/src/zabbix_server/poller/checks_simple_vmware.h
@@ -52,6 +52,8 @@ int	check_vcenter_datastore_tags_get(AGENT_REQUEST *request, const char *usernam
 		AGENT_RESULT *result);
 int	check_vcenter_datastore_read(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result);
+int	check_vcenter_datastore_perfcounter(AGENT_REQUEST *request, const char *username, const char *password,
+		AGENT_RESULT *result);
 int	check_vcenter_datastore_property(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result);
 int	check_vcenter_datastore_size(AGENT_REQUEST *request, const char *username, const char *password,
@@ -100,6 +102,8 @@ int	check_vcenter_hv_datastore_multipath(AGENT_REQUEST *request, const char *use
 		AGENT_RESULT *result);
 int	check_vcenter_hv_discovery(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result);
+int	check_vcenter_hv_diskinfo_get(AGENT_REQUEST *request, const char *username, const char *password,
+		AGENT_RESULT *result);
 int	check_vcenter_hv_fullname(AGENT_REQUEST *request, const char *username, const char *password,
 		AGENT_RESULT *result);
 int	check_vcenter_hv_hw_cpu_num(AGENT_REQUEST *request, const char *username, const char *password,
diff --git a/src/zabbix_server/vmware/vmware.c b/src/zabbix_server/vmware/vmware.c
index 43dd9835e99..3379b506ac1 100644
--- a/src/zabbix_server/vmware/vmware.c
+++ b/src/zabbix_server/vmware/vmware.c
@@ -61,6 +61,8 @@ extern zbx_uint64_t	CONFIG_VMWARE_CACHE_SIZE;
 extern int		CONFIG_VMWARE_TIMEOUT;
 extern char		*CONFIG_SOURCE_IP;
 
+#define zbx_strscat(x, y)	zbx_strlcat(x, y, sizeof(x))
+
 #define VMWARE_VECTOR_CREATE(ref, type)	zbx_vector_##type##_create_ext(ref,  __vm_shmem_malloc_func, \
 		__vm_shmem_realloc_func, __vm_shmem_free_func)
 
@@ -99,6 +101,7 @@ ZBX_PTR_VECTOR_IMPL(vmware_custom_attr, zbx_vmware_custom_attr_t *)
 ZBX_PTR_VECTOR_IMPL(custquery_param, zbx_vmware_custquery_param_t)
 ZBX_PTR_VECTOR_IMPL(vmware_dvswitch, zbx_vmware_dvswitch_t *)
 ZBX_PTR_VECTOR_IMPL(vmware_alarm, zbx_vmware_alarm_t *)
+ZBX_PTR_VECTOR_IMPL(vmware_diskinfo, zbx_vmware_diskinfo_t *)
 
 /* VMware service object name mapping for vcenter and vsphere installations */
 typedef struct
@@ -148,8 +151,8 @@ typedef struct
 }
 zbx_vmware_cq_value_t;
 
-ZBX_PTR_VECTOR_DECL(cq_value, zbx_vmware_cq_value_t)
-ZBX_PTR_VECTOR_IMPL(cq_value, zbx_vmware_cq_value_t)
+ZBX_PTR_VECTOR_DECL(cq_value, zbx_vmware_cq_value_t *)
+ZBX_PTR_VECTOR_IMPL(cq_value, zbx_vmware_cq_value_t *)
 
 /* performance data for a performance collector entity */
 typedef struct
@@ -194,6 +197,7 @@ typedef struct
 	int	enabled;
 }
 zbx_vmware_alarm_details_t;
+
 ZBX_PTR_VECTOR_DECL(vmware_alarm_details, zbx_vmware_alarm_details_t *)
 ZBX_PTR_VECTOR_IMPL(vmware_alarm_details, zbx_vmware_alarm_details_t *)
 
@@ -204,6 +208,21 @@ typedef struct
 }
 zbx_vmware_alarms_data_t;
 
+/* VMware performance counters available per object (information cache) */
+ZBX_VECTOR_DECL(uint16, uint16_t)
+ZBX_VECTOR_IMPL(uint16, uint16_t)
+
+typedef struct
+{
+	char			*type;
+	char			*id;
+	zbx_vector_uint16_t	list;
+}
+zbx_vmware_perf_available_t;
+
+ZBX_PTR_VECTOR_DECL(perf_available, zbx_vmware_perf_available_t *)
+ZBX_PTR_VECTOR_IMPL(perf_available, zbx_vmware_perf_available_t *)
+
 #define ZBX_HOSTINFO_NODES_DATACENTER		0x01
 #define ZBX_HOSTINFO_NODES_COMPRES		0x02
 #define ZBX_HOSTINFO_NODES_HOST			0x04
@@ -249,8 +268,10 @@ static zbx_uint64_t	evt_req_chunk_size;
 
 #define ZBX_XPATH_FAULT_SLOW(max_len)									\
 	"concat(substring(" ZBX_XPATH_FAULT_FAST("faultstring")",1," ZBX_STR(max_len) "),"		\
-	"substring(local-name(" ZBX_XPATH_FAULT_FAST("detail") "/*[1]"					\
-	"),1," ZBX_STR(max_len) " * number(string-length(" ZBX_XPATH_FAULT_FAST("faultstring") ")=0)))"
+	"substring(concat(local-name(" ZBX_XPATH_FAULT_FAST("detail") "/*[1]),':',"			\
+	ZBX_XPATH_FAULT_FAST("detail")"//*[local-name()='name']),1,"					\
+	ZBX_STR(max_len) " * number(string-length(" ZBX_XPATH_FAULT_FAST("faultstring") ")=0)"		\
+	"* number(string-length(local-name(" ZBX_XPATH_FAULT_FAST("detail") "/*[1]) )>0)))"
 
 #define ZBX_XPATH_REFRESHRATE()										\
 	"/*/*/*/*/*[local-name()='refreshRate' and ../*[local-name()='currentSupported']='true']"
@@ -319,10 +340,6 @@ static zbx_uint64_t	evt_req_chunk_size;
 		"/*[local-name()='val']/*[local-name()='adapter']/*[local-name()='target']"		\
 		"/*[local-name()='lun']/*[local-name()='scsiLun']"
 
-#define ZBX_XPATH_HV_LUN()										\
-		"substring-before(substring-after(/*/*/*/*/*/*[local-name()='propSet']"			\
-		"[*[local-name()='val'][text()='%s']][1]/*[local-name()='name'],'\"'),'\"')"
-
 #define ZBX_XPATH_HV_MULTIPATH(state)									\
 		"count(/*/*/*/*/*/*[local-name()='propSet'][1]/*[local-name()='val']"			\
 		"/*[local-name()='lun'][*[local-name()='lun'][text()='%s']][1]"				\
@@ -369,9 +386,10 @@ static zbx_uint64_t	evt_req_chunk_size;
 
 typedef int	(*nodeprocfunc_t)(void *, char **);
 static int	vmware_service_get_vm_snapshot(void *xml_node, char **jstr);
-static void	vmware_service_cq_prop_value(const char *fn_parent, xmlDoc *xdoc, zbx_vmware_cq_value_t *cqv);
+static void	vmware_service_cq_prop_value(const char *fn_parent, xmlDoc *xdoc, zbx_vector_cq_value_t *cqvs);
 static char	*vmware_cq_prop_soap_request(const zbx_vector_cq_value_t *cq_values, const char *soap_type,
-		const char *clusterid, const size_t bsz, char *buff, zbx_vmware_cq_value_t **cq_prop);
+		const char *obj_id, zbx_vector_cq_value_t *cqvs);
+static int	vmware_diskinfo_diskname_compare(const void *d1, const void *d2);
 
 typedef struct
 {
@@ -410,7 +428,7 @@ static zbx_vmware_propmap_t	hv_propmap[] = {
 	ZBX_HVPROPMAP("runtime.connectionState"),		/* ZBX_VMWARE_HVPROP_CONNECTIONSTATE */
 	ZBX_HVPROPMAP_EXT("hardware.systemInfo.serialNumber", NULL, 67),/* ZBX_VMWARE_HVPROP_HW_SERIALNUMBER */
 	ZBX_HVPROPMAP_EXT("runtime.healthSystemRuntime.hardwareStatusInfo",
-			zbx_xmlnode_to_json, 0),		/* ZBX_VMWARE_HVPROP_HW_SENSOR */
+			zbx_xmlnode_to_json, 0)			/* ZBX_VMWARE_HVPROP_HW_SENSOR */
 };
 
 static zbx_vmware_propmap_t	vm_propmap[] = {
@@ -450,6 +468,9 @@ static zbx_vmware_propmap_t	vm_propmap[] = {
 #define ZBX_XPATH_OBJECTS_BY_TYPE(type)									\
 	"/*/*/*/*/*[local-name()='objects'][*[local-name()='obj'][@type='" type "']]"
 
+#define ZBX_XPATH_OBJS_BY_TYPE(type)									\
+	"/*/*/*/*/*[local-name()='objects']/*[local-name()='obj'][@type='" type "']"
+
 #define ZBX_XPATH_NAME_BY_TYPE(type)									\
 	ZBX_XPATH_PROP_OBJECT(type) "*[local-name()='propSet'][*[local-name()='name']]"			\
 	"/*[local-name()='val']"
@@ -674,9 +695,10 @@ int	zbx_str_uint64_pair_name_compare(const void *p1, const void *p2)
  * Parameters: cq_value - [IN] the custom query value data                    *
  *                                                                            *
  ******************************************************************************/
-static void	zbx_vmware_cq_value_free(zbx_vmware_cq_value_t cq_value)
+static void	zbx_vmware_cq_value_free(zbx_vmware_cq_value_t *cq_value)
 {
-	zbx_free(cq_value.response);
+	zbx_str_free(cq_value->response);
+	zbx_free(cq_value);
 }
 
 /******************************************************************************
@@ -857,6 +879,43 @@ static int	vmware_perf_entity_compare_func(const void *d1, const void *d2)
 	return ret;
 }
 
+/******************************************************************************
+ *                                                                            *
+ * performance counter availability list support functions                    *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_perf_available_compare(const void *d1, const void *d2)
+{
+	int	ret;
+
+	const zbx_vmware_perf_available_t	*e1 = *(const zbx_vmware_perf_available_t * const *)d1;
+	const zbx_vmware_perf_available_t	*e2 = *(const zbx_vmware_perf_available_t * const *)d2;
+
+	if (0 == (ret = strcmp(e1->type, e2->type)))
+		ret = strcmp(e1->id, e2->id);
+
+	return ret;
+}
+
+static void	vmware_perf_available_free(zbx_vmware_perf_available_t *value)
+{
+	zbx_free(value->type);
+	zbx_free(value->id);
+	zbx_vector_uint16_clear(&value->list);
+	zbx_vector_uint16_destroy(&value->list);
+	zbx_free(value);
+}
+
+static int	vmware_uint16_compare(const void *d1, const void *d2)
+{
+	const uint16_t	*i1 = (const uint16_t *)d1;
+	const uint16_t	*i2 = (const uint16_t *)d2;
+
+	ZBX_RETURN_IF_NOT_EQUAL(*i1, *i2);
+
+	return 0;
+}
+
 /******************************************************************************
  *                                                                            *
  * custom query hashset support functions                                     *
@@ -1047,6 +1106,7 @@ static void	vmware_perf_counter_shared_free(zbx_vmware_perf_counter_t *counter)
 {
 	vmware_vector_str_uint64_pair_shared_clean(&counter->values);
 	zbx_vector_str_uint64_pair_destroy(&counter->values);
+	vmware_shared_strfree(counter->query_instance);
 	__vm_shmem_free_func(counter);
 }
 
@@ -1098,7 +1158,10 @@ static void	vmware_entities_shared_clean_stats(zbx_hashset_t *entities)
 			vmware_vector_str_uint64_pair_shared_clean(&counter->values);
 
 			if (0 != (counter->state & ZBX_VMWARE_COUNTER_UPDATING))
-				counter->state = ZBX_VMWARE_COUNTER_READY;
+			{
+				counter->state = ZBX_VMWARE_COUNTER_READY |
+						(counter->state & ZBX_VMWARE_COUNTER_STATE_MASK);
+			}
 		}
 		vmware_shared_strfree(entity->error);
 		entity->error = NULL;
@@ -1115,7 +1178,6 @@ static void	vmware_entities_shared_clean_stats(zbx_hashset_t *entities)
 static void	vmware_diskextent_shared_free(zbx_vmware_diskextent_t *diskextent)
 {
 	vmware_shared_strfree(diskextent->diskname);
-
 	__vm_shmem_free_func(diskextent);
 }
 
@@ -1131,6 +1193,7 @@ static void	vmware_datastore_shared_free(zbx_vmware_datastore_t *datastore)
 	vmware_shared_strfree(datastore->name);
 	vmware_shared_strfree(datastore->id);
 	vmware_shared_strfree(datastore->uuid);
+	vmware_shared_strfree(datastore->type);
 
 	vmware_vector_str_uint64_pair_shared_clean(&datastore->hv_uuids_access);
 	zbx_vector_str_uint64_pair_destroy(&datastore->hv_uuids_access);
@@ -1353,6 +1416,34 @@ static void	vmware_alarm_shared_free(zbx_vmware_alarm_t *alarm)
 	__vm_shmem_free_func(alarm);
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Purpose: frees shared resources allocated to store disk info data          *
+ *                                                                            *
+ * Parameters: di - [IN] the disk info object                                 *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_diskinfo_shared_free(zbx_vmware_diskinfo_t *di)
+{
+	vmware_shared_strfree(di->diskname);
+	vmware_shared_strfree(di->ds_uuid);
+	vmware_shared_strfree(di->operational_state);
+	vmware_shared_strfree(di->lun_type);
+	vmware_shared_strfree(di->model);
+	vmware_shared_strfree(di->vendor);
+	vmware_shared_strfree(di->revision);
+	vmware_shared_strfree(di->serial_number);
+
+	if (NULL != di->vsan)
+	{
+		vmware_shared_strfree(di->vsan->ssd);
+		vmware_shared_strfree(di->vsan->local_disk);
+		__vm_shmem_free_func(di->vsan);
+	}
+
+	__vm_shmem_free_func(di);
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: frees shared resources allocated to store vmware hypervisor       *
@@ -1374,6 +1465,9 @@ static void	vmware_hv_shared_clean(zbx_vmware_hv_t *hv)
 	zbx_vector_str_clear_ext(&hv->alarm_ids, vmware_shared_strfree);
 	zbx_vector_str_destroy(&hv->alarm_ids);
 
+	zbx_vector_vmware_diskinfo_clear_ext(&hv->diskinfo, vmware_diskinfo_shared_free);
+	zbx_vector_vmware_diskinfo_destroy(&hv->diskinfo);
+
 	if (NULL != hv->uuid)
 		vmware_shared_strfree(hv->uuid);
 
@@ -1416,6 +1510,9 @@ static void	vmware_cluster_shared_free(zbx_vmware_cluster_t *cluster)
 	if (NULL != cluster->status)
 		vmware_shared_strfree(cluster->status);
 
+	zbx_vector_str_clear_ext(&cluster->dss_uuid, vmware_shared_strfree);
+	zbx_vector_str_destroy(&cluster->dss_uuid);
+
 	zbx_vector_str_clear_ext(&cluster->alarm_ids, vmware_shared_strfree);
 	zbx_vector_str_destroy(&cluster->alarm_ids);
 
@@ -1636,9 +1733,14 @@ static zbx_vmware_cluster_t	*vmware_cluster_shared_dup(const zbx_vmware_cluster_
 	cluster->id = vmware_shared_strdup(src->id);
 	cluster->name = vmware_shared_strdup(src->name);
 	cluster->status = vmware_shared_strdup(src->status);
+	VMWARE_VECTOR_CREATE(&cluster->dss_uuid, str);
+	zbx_vector_str_reserve(&cluster->dss_uuid, (size_t)src->dss_uuid.values_num);
 	VMWARE_VECTOR_CREATE(&cluster->alarm_ids, str);
 	zbx_vector_str_reserve(&cluster->alarm_ids, (size_t)src->alarm_ids.values_num);
 
+	for (i = 0; i < src->dss_uuid.values_num; i++)
+		zbx_vector_str_append(&cluster->dss_uuid, vmware_shared_strdup(src->dss_uuid.values[i]));
+
 	for (i = 0; i < src->alarm_ids.values_num; i++)
 		zbx_vector_str_append(&cluster->alarm_ids, vmware_shared_strdup(src->alarm_ids.values[i]));
 
@@ -1680,8 +1782,8 @@ static zbx_vmware_diskextent_t	*vmware_diskextent_shared_dup(const zbx_vmware_di
 	zbx_vmware_diskextent_t	*diskextent;
 
 	diskextent = (zbx_vmware_diskextent_t *)__vm_shmem_malloc_func(NULL, sizeof(zbx_vmware_diskextent_t));
-	diskextent->diskname = vmware_shared_strdup(src->diskname);
 	diskextent->partitionid = src->partitionid;
+	diskextent->diskname = vmware_shared_strdup(src->diskname);
 
 	return diskextent;
 }
@@ -1704,6 +1806,7 @@ static zbx_vmware_datastore_t	*vmware_datastore_shared_dup(const zbx_vmware_data
 	datastore->uuid = vmware_shared_strdup(src->uuid);
 	datastore->name = vmware_shared_strdup(src->name);
 	datastore->id = vmware_shared_strdup(src->id);
+	datastore->type = vmware_shared_strdup(src->type);
 	VMWARE_VECTOR_CREATE(&datastore->hv_uuids_access, str_uint64_pair);
 	zbx_vector_str_uint64_pair_reserve(&datastore->hv_uuids_access, (size_t)src->hv_uuids_access.values_num);
 	VMWARE_VECTOR_CREATE(&datastore->diskextents, vmware_diskextent);
@@ -1974,6 +2077,45 @@ static zbx_vmware_dsname_t	*vmware_dsname_shared_dup(const zbx_vmware_dsname_t *
 	return dsname;
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Purpose: copies vmware hypervisor disks object into shared memory          *
+ *                                                                            *
+ * Parameters: src   - [IN] the vmware disk info object                       *
+ *                                                                            *
+ * Return value: a duplicated vmware disk info object                         *
+ *                                                                            *
+ ******************************************************************************/
+static zbx_vmware_diskinfo_t	*vmware_diskinfo_shared_dup(const zbx_vmware_diskinfo_t *src)
+{
+	zbx_vmware_diskinfo_t	*di;
+
+	di = (zbx_vmware_diskinfo_t *)__vm_shmem_malloc_func(NULL, sizeof(zbx_vmware_diskinfo_t));
+
+	di->diskname = vmware_shared_strdup(src->diskname);
+	di->ds_uuid = vmware_shared_strdup(src->ds_uuid);
+	di->operational_state = vmware_shared_strdup(src->operational_state);
+	di->lun_type = vmware_shared_strdup(src->lun_type);
+	di->queue_depth = src->queue_depth;
+	di->model = vmware_shared_strdup(src->model);
+	di->vendor = vmware_shared_strdup(src->vendor);
+	di->revision = vmware_shared_strdup(src->revision);
+	di->serial_number = vmware_shared_strdup(src->serial_number);
+
+	if (NULL != src->vsan)
+	{
+		di->vsan = (zbx_vmware_vsandiskinfo_t *)__vm_shmem_malloc_func(NULL, sizeof(zbx_vmware_vsandiskinfo_t));
+		di->vsan->ssd = vmware_shared_strdup(src->vsan->ssd);
+		di->vsan->local_disk = vmware_shared_strdup(src->vsan->local_disk);
+		di->vsan->block = src->vsan->block;
+		di->vsan->block_size = src->vsan->block_size;
+	}
+	else
+		di->vsan = NULL;
+
+	return di;
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: copies vmware physical NIC object into shared memory              *
@@ -2039,10 +2181,12 @@ static	void	vmware_hv_shared_copy(zbx_vmware_hv_t *dst, const zbx_vmware_hv_t *s
 	VMWARE_VECTOR_CREATE(&dst->vms, ptr);
 	VMWARE_VECTOR_CREATE(&dst->pnics, vmware_pnic);
 	VMWARE_VECTOR_CREATE(&dst->alarm_ids, str);
+	VMWARE_VECTOR_CREATE(&dst->diskinfo, vmware_diskinfo);
 	zbx_vector_vmware_dsname_reserve(&dst->dsnames, (size_t)src->dsnames.values_num);
 	zbx_vector_ptr_reserve(&dst->vms, (size_t)src->vms.values_num);
 	zbx_vector_vmware_pnic_reserve(&dst->pnics, (size_t)src->pnics.values_num);
 	zbx_vector_str_reserve(&dst->alarm_ids, (size_t)src->alarm_ids.values_num);
+	zbx_vector_vmware_diskinfo_reserve(&dst->diskinfo, (size_t)src->diskinfo.values_num);
 
 	dst->uuid = vmware_shared_strdup(src->uuid);
 	dst->id = vmware_shared_strdup(src->id);
@@ -2065,6 +2209,9 @@ static	void	vmware_hv_shared_copy(zbx_vmware_hv_t *dst, const zbx_vmware_hv_t *s
 
 	for (i = 0; i < src->alarm_ids.values_num; i++)
 		zbx_vector_str_append(&dst->alarm_ids, vmware_shared_strdup(src->alarm_ids.values[i]));
+
+	for (i = 0; i < src->diskinfo.values_num; i++)
+		zbx_vector_vmware_diskinfo_append(&dst->diskinfo, vmware_diskinfo_shared_dup(src->diskinfo.values[i]));
 }
 
 /******************************************************************************
@@ -2204,6 +2351,7 @@ static void	vmware_datastore_free(zbx_vmware_datastore_t *datastore)
 	zbx_free(datastore->name);
 	zbx_free(datastore->uuid);
 	zbx_free(datastore->id);
+	zbx_free(datastore->type);
 	zbx_free(datastore);
 }
 
@@ -2358,6 +2506,34 @@ static void	vmware_dsname_free(zbx_vmware_dsname_t *dsname)
 	zbx_free(dsname);
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Purpose: frees resources allocated to store disk info data                 *
+ *                                                                            *
+ * Parameters: di - [IN] the disk info                                        *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_diskinfo_free(zbx_vmware_diskinfo_t *di)
+{
+	zbx_free(di->diskname);
+	zbx_free(di->ds_uuid);
+	zbx_free(di->operational_state);
+	zbx_free(di->lun_type);
+	zbx_free(di->model);
+	zbx_free(di->vendor);
+	zbx_free(di->revision);
+	zbx_free(di->serial_number);
+
+	if (NULL != di->vsan)
+	{
+		zbx_free(di->vsan->ssd);
+		zbx_free(di->vsan->local_disk);
+		zbx_free(di->vsan);
+	}
+
+	zbx_free(di);
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: frees resources allocated to physical NIC data                    *
@@ -2428,6 +2604,9 @@ static void	vmware_hv_clean(zbx_vmware_hv_t *hv)
 	zbx_vector_str_clear_ext(&hv->alarm_ids, zbx_str_free);
 	zbx_vector_str_destroy(&hv->alarm_ids);
 
+	zbx_vector_vmware_diskinfo_clear_ext(&hv->diskinfo, vmware_diskinfo_free);
+	zbx_vector_vmware_diskinfo_destroy(&hv->diskinfo);
+
 	zbx_free(hv->uuid);
 	zbx_free(hv->id);
 	zbx_free(hv->clusterid);
@@ -2450,6 +2629,8 @@ static void	vmware_cluster_free(zbx_vmware_cluster_t *cluster)
 	zbx_free(cluster->name);
 	zbx_free(cluster->id);
 	zbx_free(cluster->status);
+	zbx_vector_str_clear_ext(&cluster->dss_uuid, zbx_str_free);
+	zbx_vector_str_destroy(&cluster->dss_uuid);
 	zbx_vector_str_clear_ext(&cluster->alarm_ids, zbx_str_free);
 	zbx_vector_str_destroy(&cluster->alarm_ids);
 	zbx_free(cluster);
@@ -3460,31 +3641,27 @@ static int	vmware_service_get_vm_data(zbx_vmware_service_t *service, CURL *easyh
 		"</ns0:RetrievePropertiesEx>"						\
 		ZBX_POST_VSPHERE_FOOTER
 
-	char	tmp[MAX_STRING_LEN + ZBX_VMWARE_VMPROPS_NUM * 100], props[MAX_STRING_LEN], *vmid_esc;
-	int	i, ret = FAIL;
+	char	*tmp, props[ZBX_VMWARE_VMPROPS_NUM * 150], *vmid_esc;
+	int	i, ret;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() vmid:'%s'", __func__, vmid);
 	props[0] = '\0';
 
 	for (i = 0; i < props_num; i++)
 	{
-		zbx_strlcat(props, "<ns0:pathSet>", sizeof(props));
-		zbx_strlcat(props, propmap[i].name, sizeof(props));
-		zbx_strlcat(props, "</ns0:pathSet>", sizeof(props));
+		zbx_strscat(props, "<ns0:pathSet>");
+		zbx_strscat(props, propmap[i].name);
+		zbx_strscat(props, "</ns0:pathSet>");
 	}
 
 	vmid_esc = zbx_xml_escape_dyn(vmid);
-
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_VM_STATUS_EX,
+	tmp = zbx_dsprintf(NULL, ZBX_POST_VMWARE_VM_STATUS_EX,
 			vmware_service_objects[service->type].property_collector, props, cq_prop, vmid_esc);
 
 	zbx_free(vmid_esc);
+	ret = zbx_soap_post(__func__, easyhandle, tmp, xdoc, NULL, error);
+	zbx_str_free(tmp);
 
-	if (SUCCEED != zbx_soap_post(__func__, easyhandle, tmp, xdoc, NULL, error))
-		goto out;
-
-	ret = SUCCEED;
-out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
 
 	return ret;
@@ -3618,6 +3795,7 @@ static void	vmware_vm_snapshot_disksize(xmlDoc *xdoc, const char *key, xmlNode *
  *             uniquesize - [IN/OUT] total uniquesize of all snapshots        *
  *             count      - [IN/OUT] total number of all snapshots            *
  *             latestdate - [OUT] the date of last snapshot                   *
+ *             oldestdate - [OUT] the date of oldest snapshot                 *
  *             json_data  - [OUT] json with info about snapshot               *
  *                                                                            *
  * Return value: SUCCEED - the operation has completed successfully           *
@@ -3626,7 +3804,7 @@ static void	vmware_vm_snapshot_disksize(xmlDoc *xdoc, const char *key, xmlNode *
  ******************************************************************************/
 static int	vmware_vm_snapshot_collect(xmlDoc *xdoc, xmlNode *snap_node, xmlNode *layout_node,
 		zbx_vector_uint64_t *disks_used, zbx_uint64_t *size, zbx_uint64_t *uniquesize, zbx_uint64_t *count,
-		char **latestdate, struct zbx_json *json_data)
+		char **latestdate, char **oldestdate, struct zbx_json *json_data)
 {
 	int			i, ret = FAIL;
 	char			*value, xpath[MAX_STRING_LEN], *name, *desc, *crtime;
@@ -3701,10 +3879,13 @@ static int	vmware_vm_snapshot_collect(xmlDoc *xdoc, xmlNode *snap_node, xmlNode
 	zbx_json_adduint64(json_data, "uniquesize", snap_usize);
 	zbx_json_close(json_data);
 
+	if (NULL != oldestdate)
+		*oldestdate = zbx_strdup(NULL, crtime);
+
 	if (NULL != (next_node = zbx_xml_node_get(xdoc, snap_node, ZBX_XNN("childSnapshotList"))))
 	{
 		ret = vmware_vm_snapshot_collect(xdoc, next_node, layout_node, disks_used, size, uniquesize, count,
-				latestdate, json_data);
+				latestdate, NULL, json_data);
 	}
 	else
 	{
@@ -3742,9 +3923,10 @@ static int	vmware_service_get_vm_snapshot(void *xml_node, char **jstr)
 	xmlDoc			*xdoc = node->doc;
 	struct zbx_json		json_data;
 	int			ret = FAIL;
-	char			*latestdate = NULL;
+	char			*latestdate = NULL, *oldestdate = NULL;
 	zbx_uint64_t		count, size, uniquesize;
 	zbx_vector_uint64_t	disks_used;
+	time_t			xml_time, now = time(NULL), latest_age = 0, oldest_age = 0;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
@@ -3770,14 +3952,23 @@ static int	vmware_service_get_vm_snapshot(void *xml_node, char **jstr)
 	uniquesize = 0;
 
 	if (FAIL == (ret = vmware_vm_snapshot_collect(xdoc, root_node, layout_node, &disks_used, &size, &uniquesize,
-			&count, &latestdate, &json_data)))
+			&count, &latestdate, &oldestdate, &json_data)))
 	{
 		goto out;
 	}
 
+	if (SUCCEED == zbx_iso8601_utc(ZBX_NULL2EMPTY_STR(latestdate), &xml_time))
+		latest_age = now - xml_time;
+
+	if (SUCCEED == zbx_iso8601_utc(ZBX_NULL2EMPTY_STR(oldestdate), &xml_time))
+		oldest_age = now - xml_time;
+
 	zbx_json_close(&json_data);
 	zbx_json_adduint64(&json_data, "count", count);
 	zbx_json_addstring(&json_data, "latestdate", ZBX_NULL2EMPTY_STR(latestdate), ZBX_JSON_TYPE_STRING);
+	zbx_json_addint64(&json_data, "latestage", latest_age);
+	zbx_json_addstring(&json_data, "oldestdate", ZBX_NULL2EMPTY_STR(oldestdate), ZBX_JSON_TYPE_STRING);
+	zbx_json_addint64(&json_data, "oldestage", oldest_age);
 	zbx_json_adduint64(&json_data, "size", size);
 	zbx_json_adduint64(&json_data, "uniquesize", uniquesize);
 	zbx_json_close(&json_data);
@@ -4103,11 +4294,11 @@ static zbx_vmware_vm_t	*vmware_service_create_vm(zbx_vmware_service_t *service,
 		zbx_vmware_alarms_data_t *alarms_data, char **error)
 {
 	zbx_vmware_vm_t		*vm;
-	char			*value, buff[MAX_STRING_LEN];
+	char			*value, *cq_prop;
 	xmlDoc			*details = NULL;
-	zbx_vmware_cq_value_t	*cqv;
+	zbx_vector_cq_value_t	cqvs;
 	const char		*uuid_xpath[3] = {NULL, ZBX_XPATH_VM_UUID(), ZBX_XPATH_VM_INSTANCE_UUID()};
-	int			ret = FAIL;
+	int			ret;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() vmid:'%s'", __func__, id);
 
@@ -4117,16 +4308,20 @@ static zbx_vmware_vm_t	*vmware_service_create_vm(zbx_vmware_service_t *service,
 	zbx_vector_ptr_create(&vm->devs);
 	zbx_vector_ptr_create(&vm->file_systems);
 	zbx_vector_vmware_custom_attr_create(&vm->custom_attrs);
+	zbx_vector_cq_value_create(&cqvs);
+	cq_prop = vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_VM, id, &cqvs);
+	ret = vmware_service_get_vm_data(service, easyhandle, id, vm_propmap, ZBX_VMWARE_VMPROPS_NUM, cq_prop,
+			&details, error);
+	zbx_str_free(cq_prop);
 
-	if (SUCCEED != vmware_service_get_vm_data(service, easyhandle, id, vm_propmap, ZBX_VMWARE_VMPROPS_NUM,
-			vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_VM, id, sizeof(buff), buff, &cqv),
-			&details, error))
-	{
+	if (FAIL == ret)
 		goto out;
-	}
 
 	if (NULL == (value = zbx_xml_doc_read_value(details, uuid_xpath[service->type])))
+	{
+		ret = FAIL;
 		goto out;
+	}
 
 	vm->uuid = value;
 	vm->id = zbx_strdup(NULL, id);
@@ -4177,13 +4372,14 @@ static zbx_vmware_vm_t	*vmware_service_create_vm(zbx_vmware_service_t *service,
 	vmware_vm_get_file_systems(vm, details);
 	vmware_vm_get_custom_attrs(vm, details);
 
-	if (NULL != cqv)
-		vmware_service_cq_prop_value(__func__, details, cqv);
+	if (0 != cqvs.values_num)
+		vmware_service_cq_prop_value(__func__, details, &cqvs);
 
 	zbx_vector_str_create(&vm->alarm_ids);
 	ret = vmware_service_get_alarms_data(__func__, service, easyhandle, details, NULL, &vm->alarm_ids, alarms_data,
 			error);
 out:
+	zbx_vector_cq_value_destroy(&cqvs);
 	zbx_xml_free_doc(details);
 
 	if (SUCCEED != ret)
@@ -4249,8 +4445,6 @@ static int	vmware_service_get_diskextents_list(xmlDoc *doc, zbx_vector_vmware_di
 	xmlXPathContext		*xpathCtx;
 	xmlXPathObject		*xpathObj;
 	xmlNodeSetPtr		nodeset;
-	char			*name, *partition;
-	zbx_vmware_diskextent_t	*diskextent;
 	int			i, ret = FAIL;
 
 	if (NULL == doc)
@@ -4268,19 +4462,23 @@ static int	vmware_service_get_diskextents_list(xmlDoc *doc, zbx_vector_vmware_di
 
 	for (i = 0; i < nodeset->nodeNr; i++)
 	{
-		if (NULL == (name = zbx_xml_node_read_value(doc, nodeset->nodeTab[i], ZBX_XPATH_NN("diskName"))))
+		char			*value;
+		zbx_vmware_diskextent_t	*diskextent;
+		xmlNode			*xn = nodeset->nodeTab[i];
+
+		if (NULL == (value = zbx_xml_node_read_value(doc, xn, ZBX_XPATH_NN("diskName"))))
 		{
 			zabbix_log(LOG_LEVEL_DEBUG, "%s(): Cannot get diskName.", __func__);
 			continue;
 		}
 
 		diskextent = (zbx_vmware_diskextent_t *)zbx_malloc(NULL, sizeof(zbx_vmware_diskextent_t));
-		diskextent->diskname = name;
+		diskextent->diskname = value;
 
-		if (NULL != (partition = zbx_xml_node_read_value(doc, nodeset->nodeTab[i], ZBX_XPATH_NN("partition"))))
+		if (NULL != (value = zbx_xml_node_read_value(doc, xn, ZBX_XPATH_NN("partition"))))
 		{
-			diskextent->partitionid = (unsigned int) atoi(partition);
-			zbx_free(partition);
+			diskextent->partitionid = (unsigned int) atoi(value);
+			zbx_free(value);
 		}
 		else
 			diskextent->partitionid = 0;
@@ -4288,7 +4486,7 @@ static int	vmware_service_get_diskextents_list(xmlDoc *doc, zbx_vector_vmware_di
 		zbx_vector_vmware_diskextent_append(diskextents, diskextent);
 	}
 
-	zbx_vector_vmware_diskextent_sort(diskextents, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
+	zbx_vector_vmware_diskextent_sort(diskextents, ZBX_DEFAULT_STR_PTR_COMPARE_FUNC);
 
 	ret = SUCCEED;
 out:
@@ -4335,15 +4533,16 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 		"</ns0:RetrievePropertiesEx>"							\
 		ZBX_POST_VSPHERE_FOOTER
 
-	char			tmp[MAX_STRING_LEN], buff[MAX_STRING_LEN], *uuid = NULL, *name = NULL, *path, *id_esc,
-				*value, *error = NULL;
+	char			*tmp, *cq_prop, *uuid = NULL, *name = NULL, *path, *id_esc, *value, *error = NULL;
+	int			ret;
 	zbx_vmware_datastore_t	*datastore = NULL;
 	zbx_uint64_t		capacity = ZBX_MAX_UINT64, free_space = ZBX_MAX_UINT64, uncommitted = ZBX_MAX_UINT64;
 	xmlDoc			*doc = NULL;
-	zbx_vmware_cq_value_t	*cqv;
+	zbx_vector_cq_value_t	cqvs;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() datastore:'%s'", __func__, id);
 
+	zbx_vector_cq_value_create(&cqvs);
 	id_esc = zbx_xml_escape_dyn(id);
 
 	if (ZBX_VMWARE_TYPE_VSPHERE == service->type && NULL != service->version &&
@@ -4354,14 +4553,16 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 		goto out;
 	}
 
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_DATASTORE_GET,
-			vmware_service_objects[service->type].property_collector,
-			vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_DS, id, sizeof(buff), buff, &cqv),
-			id_esc);
 
-	zbx_free(id_esc);
+	cq_prop = vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_DS, id, &cqvs);
+	tmp = zbx_dsprintf(NULL, ZBX_POST_DATASTORE_GET, vmware_service_objects[service->type].property_collector,
+			cq_prop, id_esc);
+	zbx_str_free(id_esc);
+	zbx_str_free(cq_prop);
+	ret = zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, &error);
+	zbx_str_free(tmp);
 
-	if (SUCCEED != zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, &error))
+	if (FAIL == ret)
 		goto out;
 
 	name = zbx_xml_doc_read_value(doc, ZBX_XPATH_DATASTORE_SUMMARY("name"));
@@ -4378,7 +4579,7 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 			if ('/' == path[len - 1])
 				path[len - 1] = '\0';
 
-			for (ptr = path + len - 2; ptr > path && *ptr != '/'; ptr--)
+			for (ptr = path + len - 2; ptr > path && *ptr != '/' && *ptr != ':'; ptr--)
 				;
 
 			uuid = zbx_strdup(NULL, ptr + 1);
@@ -4417,6 +4618,7 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 	datastore->name = (NULL != name) ? name : zbx_strdup(NULL, id);
 	datastore->uuid = uuid;
 	datastore->id = zbx_strdup(NULL, id);
+	datastore->type = zbx_xml_doc_read_value(doc, ZBX_XPATH_DATASTORE_SUMMARY("type"));
 	datastore->capacity = capacity;
 	datastore->free_space = free_space;
 	datastore->uncommitted = uncommitted;
@@ -4425,8 +4627,8 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 	zbx_vector_vmware_diskextent_create(&datastore->diskextents);
 	vmware_service_get_diskextents_list(doc, &datastore->diskextents);
 
-	if (NULL != cqv)
-		vmware_service_cq_prop_value(__func__, doc, cqv);
+	if (0 != cqvs.values_num)
+		vmware_service_cq_prop_value(__func__, doc, &cqvs);
 
 	if (FAIL == vmware_service_get_alarms_data(__func__, service, easyhandle, doc, NULL, &datastore->alarm_ids,
 			alarms_data, &error))
@@ -4436,6 +4638,7 @@ static zbx_vmware_datastore_t	*vmware_service_create_datastore(const zbx_vmware_
 	}
 out:
 	zbx_xml_free_doc(doc);
+	zbx_vector_cq_value_destroy(&cqvs);
 
 	if (NULL != error)
 	{
@@ -4496,7 +4699,7 @@ static int	vmware_service_get_hv_data(const zbx_vmware_service_t *service, CURL
 		"</ns0:RetrievePropertiesEx>"									\
 		ZBX_POST_VSPHERE_FOOTER
 
-	char	tmp[MAX_STRING_LEN + ZBX_VMWARE_HVPROPS_NUM * 100], props[MAX_STRING_LEN], *hvid_esc;
+	char	*tmp, props[ZBX_VMWARE_HVPROPS_NUM * 150], *hvid_esc;
 	int	i, ret = FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() guesthvid:'%s'", __func__, hvid);
@@ -4510,25 +4713,20 @@ static int	vmware_service_get_hv_data(const zbx_vmware_service_t *service, CURL
 		if (0 != propmap[i].vc_min && propmap[i].vc_min > service->major_version * 10 + service->minor_version)
 			continue;
 
-		zbx_strlcat(props, "<ns0:pathSet>", sizeof(props));
-		zbx_strlcat(props, propmap[i].name, sizeof(props));
-		zbx_strlcat(props, "</ns0:pathSet>", sizeof(props));
+		zbx_strscat(props, "<ns0:pathSet>");
+		zbx_strscat(props, propmap[i].name);
+		zbx_strscat(props, "</ns0:pathSet>");
 	}
 
 	hvid_esc = zbx_xml_escape_dyn(hvid);
-
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_HV_DETAILS, vmware_service_objects[service->type].property_collector,
+	tmp = zbx_dsprintf(NULL, ZBX_POST_HV_DETAILS, vmware_service_objects[service->type].property_collector,
 			props, cq_prop, hvid_esc);
-
 	zbx_free(hvid_esc);
-
 	zabbix_log(LOG_LEVEL_TRACE, "%s() SOAP request: %s", __func__, tmp);
 
-	if (SUCCEED != zbx_soap_post(__func__, easyhandle, tmp, xdoc, NULL, error))
-		goto out;
+	ret = zbx_soap_post(__func__, easyhandle, tmp, xdoc, NULL, error);
+	zbx_str_free(tmp);
 
-	ret = SUCCEED;
-out:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
 
 	return ret;
@@ -4759,126 +4957,524 @@ static int	vmware_service_hv_get_multipath_data(const zbx_vmware_service_t *serv
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_ds_uuid_compare                                           *
+ * Purpose: find DS by canonical disk name (perf counter instance)            *
  *                                                                            *
- * Purpose: sorting function to sort Datastore vector by uuid                 *
+ * Parameters: dss      - [IN] all known Datastores                           *
+ *             diskname - [IN] canonical disk name                            *
+ *                                                                            *
+ * Return value: uuid of Datastore or NULL                                    *
  *                                                                            *
  ******************************************************************************/
-int	vmware_ds_uuid_compare(const void *d1, const void *d2)
+static char	*vmware_datastores_diskname_search(const zbx_vector_vmware_datastore_t *dss, char *diskname)
 {
-	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
-	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+	zbx_vmware_diskextent_t	dx_cmp = {.diskname = diskname};
+	int			i;
 
-	return strcmp(ds1->uuid, ds2->uuid);
+	for (i = 0; i< dss->values_num; i++)
+	{
+		zbx_vmware_datastore_t	*ds = dss->values[i];
+
+		if (FAIL == zbx_vector_vmware_diskextent_bsearch(&ds->diskextents, &dx_cmp,
+				ZBX_DEFAULT_STR_PTR_COMPARE_FUNC))
+		{
+			continue;
+		}
+
+		return zbx_strdup(NULL, ds->uuid);
+	}
+
+	return NULL;
 }
 
 /******************************************************************************
  *                                                                            *
- * Function: vmware_ds_name_compare                                           *
+ * Purpose: parse the vmware hypervisor internal disks details info           *
  *                                                                            *
- * Purpose: sorting function to sort Datastore vector by name                 *
+ * Parameters: xdoc       - [IN] a reference to xml document with disks info  *
+ *             dss        - [IN] all known Datastores                         *
+ *             disks_info - [OUT]                                             *
+ *                                                                            *
+ * Return value: count of updated disk objects                                *
  *                                                                            *
  ******************************************************************************/
-int	vmware_ds_name_compare(const void *d1, const void *d2)
+static int	vmware_service_hv_disks_parse_info(xmlDoc *xdoc, const zbx_vector_vmware_datastore_t *dss,
+		zbx_vector_ptr_pair_t *disks_info)
 {
-	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
-	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+#	define SCSILUN_PROP_NUM		8
+#	define ZBX_XPATH_PSET		"/*/*/*/*/*/*[local-name()='propSet']"
+#	define ZBX_XPATH_LUN		"substring-before(substring-after(*[local-name()='name'],'\"'),'\"')"
+#	define ZBX_XPATH_LUN_PR_NAME	"substring-after(*[local-name()='name'],'\"].')"
 
-	return strcmp(ds1->name, ds2->name);
-}
 
-/******************************************************************************
- *                                                                            *
- * Purpose: sorting function to sort Datastore vector by id                   *
- *                                                                            *
- ******************************************************************************/
-static int	vmware_ds_id_compare(const void *d1, const void *d2)
-{
-	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
-	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+	xmlXPathContext	*xpathCtx;
+	xmlXPathObject	*xpathObj;
+	xmlNodeSetPtr	nodeset;
+	char		*lun_key = NULL, *name = NULL;
+	int 		i, created = 0, j = FAIL;
 
-	return strcmp(ds1->id, ds2->id);
-}
 
-/******************************************************************************
- *                                                                            *
- * Purpose: sorting function to sort Datacenter vector by id                  *
- *                                                                            *
- ******************************************************************************/
-int	vmware_dc_id_compare(const void *d1, const void *d2)
-{
-	const zbx_vmware_datacenter_t	*dc1 = *(const zbx_vmware_datacenter_t * const *)d1;
-	const zbx_vmware_datacenter_t	*dc2 = *(const zbx_vmware_datacenter_t * const *)d2;
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
-	return strcmp(dc1->id, dc2->id);
-}
+	xpathCtx = xmlXPathNewContext(xdoc);
 
-/******************************************************************************
- *                                                                            *
- * Purpose: sorting function to sort custom attributes vector by name         *
- *                                                                            *
- ******************************************************************************/
-int	vmware_custom_attr_compare_name(const void *a1, const void *a2)
-{
-	const zbx_vmware_custom_attr_t	*attr1 = *(const zbx_vmware_custom_attr_t * const *)a1;
-	const zbx_vmware_custom_attr_t	*attr2 = *(const zbx_vmware_custom_attr_t * const *)a2;
+	if (NULL == (xpathObj = xmlXPathEvalExpression((const xmlChar *)ZBX_XPATH_PSET, xpathCtx)))
+		goto clean;
 
-	return strcmp(attr1->name, attr2->name);
-}
+	if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+		goto clean;
 
-/******************************************************************************
- *                                                                            *
- * Purpose: sorting function to sort DVSwitch vector by uuid                  *
- *                                                                            *
- ******************************************************************************/
-int	vmware_dvs_uuid_compare(const void *d1, const void *d2)
-{
-	const zbx_vmware_dvswitch_t	*dvs1 = *(const zbx_vmware_dvswitch_t * const *)d1;
-	const zbx_vmware_dvswitch_t	*dvs2 = *(const zbx_vmware_dvswitch_t * const *)d2;
+	nodeset = xpathObj->nodesetval;
+	zbx_vector_ptr_pair_reserve(disks_info, (size_t)(nodeset->nodeNr / SCSILUN_PROP_NUM + disks_info->values_num));
 
-	return strcmp(dvs1->uuid, dvs2->uuid);
-}
+	for (i = 0; i < nodeset->nodeNr; i++)
+	{
+		zbx_vmware_diskinfo_t	*di;
+		xmlNode			*node = nodeset->nodeTab[i];
+		zbx_ptr_pair_t		pr;
 
+		zbx_str_free(lun_key);
+		zbx_str_free(name);
 
-/******************************************************************************
- *                                                                            *
- * Purpose: sorting function to sort DVSwitch vector by uuid                  *
- *                                                                            *
- ******************************************************************************/
-static int	vmware_cq_instance_id_compare(const void *d1, const void *d2)
-{
-	int	ret;
+		if (NULL == (lun_key = zbx_xml_node_read_value(xdoc, node, ZBX_XPATH_LUN)))
+			continue;
 
-	const zbx_vmware_cq_value_t	*prop1 = (const zbx_vmware_cq_value_t *)d1;
-	const zbx_vmware_cq_value_t	*prop2 = (const zbx_vmware_cq_value_t *)d2;
+		if (NULL == (name = zbx_xml_node_read_value(xdoc, node, ZBX_XPATH_LUN_PR_NAME)))
+			continue;
 
-	if (0 == (ret = strcmp(prop1->instance->soap_type, prop2->instance->soap_type)))
-		ret = strcmp(prop1->instance->id, prop2->instance->id);
+		pr.first = lun_key;
 
-	return ret;
+		if ((FAIL == j || 0 != strcmp(disks_info->values[j].first, lun_key)) &&
+				FAIL == (j = zbx_vector_ptr_pair_search(disks_info, pr,
+				ZBX_DEFAULT_STR_COMPARE_FUNC)))
+		{
+			lun_key = NULL;
+			pr.second = zbx_malloc(NULL, sizeof(zbx_vmware_diskinfo_t));
+			memset(pr.second, 0, sizeof(zbx_vmware_diskinfo_t));
+			zbx_vector_ptr_pair_append(disks_info, pr);
+			j = disks_info->values_num - 1;
+			created++;
+		}
+
+		di = (zbx_vmware_diskinfo_t *)disks_info->values[j].second;
+
+		if (0 == strcmp(name, "canonicalName"))
+		{
+			di->diskname = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+			di->ds_uuid = vmware_datastores_diskname_search(dss, di->diskname);
+		}
+		else if (0 == strcmp(name, "operationalState"))
+		{
+			zbx_vector_str_t	values;
+			int			k;
+
+			zbx_vector_str_create(&values);
+			zbx_xml_node_read_values(xdoc, node, ZBX_XNN("val") "/*", &values);
+			di->operational_state = zbx_strdcat(di->operational_state, "[");
+
+			for (k = 0; k < values.values_num; k++)
+				di->operational_state = zbx_strdcatf(di->operational_state, "\"%s\",", values.values[k]);
+
+			if (0 != values.values_num)
+				di->operational_state[strlen(di->operational_state) - 1] = '\0';
+
+			di->operational_state = zbx_strdcat(di->operational_state, "]");
+			zbx_vector_str_clear_ext(&values, zbx_str_free);
+			zbx_vector_str_destroy(&values);
+		}
+		else if (0 == strcmp(name, "lunType"))
+		{
+			di->lun_type = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+		}
+		else if (0 == strcmp(name, "queueDepth"))
+		{
+			zbx_xml_node_read_num(xdoc, node, "number(" ZBX_XNN("val") ")", &di->queue_depth);
+		}
+		else if (0 == strcmp(name, "model"))
+		{
+			di->model = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+			zbx_lrtrim(di->model, " ");
+		}
+		else if (0 == strcmp(name, "vendor"))
+		{
+			di->vendor = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+			zbx_lrtrim(di->vendor, " ");
+		}
+		else if (0 == strcmp(name, "revision"))
+		{
+			di->revision = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+			zbx_lrtrim(di->revision, " ");
+		}
+		else if (0 == strcmp(name, "serialNumber"))
+		{
+			di->serial_number = zbx_xml_node_read_value(xdoc, node, ZBX_XNN("val"));
+			zbx_lrtrim(di->serial_number, " ");
+		}
+	}
+
+	zbx_str_free(lun_key);
+	zbx_str_free(name);
+clean:
+	xmlXPathFreeObject(xpathObj);
+	xmlXPathFreeContext(xpathCtx);
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() created:%d", __func__, created);
+
+	return created;
+
+#	undef SCSILUN_PROP_NUM
+#	undef ZBX_XPATH_LUN_PR_NAME
+#	undef ZBX_XPATH_PSET
 }
 
 /******************************************************************************
  *                                                                            *
- * Purpose: populate array of values from an xml data                         *
+ * Purpose: parse the vmware hypervisor vsan disks details info               *
  *                                                                            *
- * Parameters: xdoc    - [IN] XML document                                    *
- *             ds_node - [IN] xml node with datastore info                    *
- *             ds_id   - [IN] datastore id (for logging)                      *
+ * Parameters: xdoc       - [IN] - a reference to xml document with disks info*
+ *             vsan_uuid  - [IN] - uuid of vsan DS                            *
+ *             disks_info - [IN/OUT] - collected the hv internal disks        *
  *                                                                            *
- * Return: bitmap value of HV access mode to DS                               *
+ * Return value: count of updated vsan disk objects                           *
  *                                                                            *
  ******************************************************************************/
-static zbx_uint64_t	vmware_hv_get_ds_access(xmlDoc *xdoc, xmlNode *ds_node, const char *ds_id)
+static int	vmware_service_hv_vsan_parse_info(xmlDoc *xdoc, const char *vsan_uuid,
+		zbx_vector_ptr_pair_t *disks_info)
 {
+	xmlXPathContext	*xpathCtx;
+	xmlXPathObject	*xpathObj;
+	xmlNodeSetPtr	nodeset;
+	int		i, updated_vsan = 0, j = FAIL;
 
-	zbx_uint64_t	mi_access = ZBX_VMWARE_DS_NONE;
-	char		*value;
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
-	zabbix_log(LOG_LEVEL_DEBUG, "In %s() for DS:%s", __func__, ds_id);
+	xpathCtx = xmlXPathNewContext(xdoc);
 
-	if (NULL != (value = zbx_xml_node_read_value(xdoc, ds_node, ZBX_XPATH_PROP_SUFFIX("mounted"))))
-	{
+	if (NULL == (xpathObj = xmlXPathEvalExpression((const xmlChar *)"//*[" ZBX_XNN("canonicalName") "]", xpathCtx)))
+		goto clean;
+
+	if (0 != xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
+		goto clean;
+
+	nodeset = xpathObj->nodesetval;
+
+	for (i = 0; i < nodeset->nodeNr; i++)
+	{
+		zbx_vmware_diskinfo_t	*di, di_cmp;
+		xmlNode			*mapinfo_node = nodeset->nodeTab[i];
+		zbx_ptr_pair_t		pr = {.first = NULL, .second = &di_cmp};
+
+		if (NULL == (di_cmp.diskname = zbx_xml_node_read_value(xdoc, mapinfo_node, ZBX_XNN("canonicalName"))) ||
+				FAIL == (j = zbx_vector_ptr_pair_bsearch(disks_info, pr,
+				vmware_diskinfo_diskname_compare)))
+		{
+			zabbix_log(LOG_LEVEL_DEBUG, "%s() skipped internal disk: %s", __func__,
+					ZBX_NULL2EMPTY_STR(di_cmp.diskname));
+			zbx_str_free(di_cmp.diskname);
+			continue;
+		}
+
+		zbx_str_free(di_cmp.diskname);
+		di = (zbx_vmware_diskinfo_t *)disks_info->values[j].second;
+		di->vsan = zbx_malloc(NULL, sizeof(zbx_vmware_vsandiskinfo_t));
+		memset(di->vsan, 0, sizeof(zbx_vmware_vsandiskinfo_t));
+		di->vsan->ssd = zbx_xml_node_read_value(xdoc, mapinfo_node, ZBX_XNN("ssd"));
+		di->vsan->local_disk = zbx_xml_node_read_value(xdoc, mapinfo_node, ZBX_XNN("localDisk"));
+		zbx_xml_node_read_num(xdoc, mapinfo_node,
+				"number(." ZBX_XPATH_LN2("capacity", "block") ")", (int *)&di->vsan->block);
+		zbx_xml_node_read_num(xdoc, mapinfo_node,
+				"number(." ZBX_XPATH_LN2("capacity", "blockSize") ")", (int *)&di->vsan->block_size);
+
+		if (NULL == di->ds_uuid)
+			di->ds_uuid = zbx_strdup(di->ds_uuid, vsan_uuid);
+
+		updated_vsan++;
+	}
+clean:
+	xmlXPathFreeObject(xpathObj);
+	xmlXPathFreeContext(xpathCtx);
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() vsan disks updated:%d", __func__, updated_vsan);
+
+	return updated_vsan;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: gets the vmware hypervisor internal disks details info            *
+ *                                                                            *
+ * Parameters: service      - [IN] the vmware service                         *
+ *             easyhandle   - [IN] the CURL handle                            *
+ *             hv_data      - [IN] the hv data with scsi topology info        *
+ *             hvid         - [IN] the vmware hypervisor id                   *
+ *             dss          - [IN] all known Datastores                       *
+ *             vsan_uuid    - [IN] uuid of vsan Datastore                    *
+ *             disks_info   - [OUT]
+ *             error        - [OUT] the error message in the case of failure  *
+ *                                                                            *
+ * Return value: SUCCEED - the operation has completed successfully           *
+ *               FAIL    - the operation has failed                           *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_service_hv_disks_get_info(const zbx_vmware_service_t *service, CURL *easyhandle,
+		xmlDoc *hv_data, const char *hvid, const zbx_vector_vmware_datastore_t *dss, const char *vsan_uuid,
+		zbx_vector_ptr_pair_t *disks_info, char **error)
+{
+#	define ZBX_POST_HV_DISK_INFO									\
+		ZBX_POST_VSPHERE_HEADER									\
+		"<ns0:RetrievePropertiesEx>"								\
+			"<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>"				\
+			"<ns0:specSet>"									\
+				"<ns0:propSet>"								\
+					"<ns0:type>HostSystem</ns0:type>"				\
+					"%s"								\
+				"</ns0:propSet>"							\
+				"<ns0:objectSet>"							\
+					"<ns0:obj type=\"HostSystem\">%s</ns0:obj>"			\
+					"<ns0:skip>false</ns0:skip>"					\
+				"</ns0:objectSet>"							\
+			"</ns0:specSet>"								\
+			"<ns0:options/>"								\
+		"</ns0:RetrievePropertiesEx>"								\
+		ZBX_POST_VSPHERE_FOOTER
+
+#	define ZBX_POST_SCSI_INFO									\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].canonicalName</ns0:pathSet>"		\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].operationalState</ns0:pathSet>"	\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].lunType</ns0:pathSet>"		\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].queueDepth</ns0:pathSet>"		\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].model</ns0:pathSet>"			\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].vendor</ns0:pathSet>"		\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].revision</ns0:pathSet>"		\
+		"<ns0:pathSet>config.storageDevice.scsiLun[\"%s\"].serialNumber</ns0:pathSet>"
+
+	zbx_vector_str_t		scsi_luns;
+	xmlDoc				*doc = NULL, *doc_dinfo = NULL;
+	zbx_property_collection_iter	*iter = NULL;
+	char				*tmp = NULL, *hvid_esc, *scsi_req = NULL, *err = NULL;
+	int				i, total, updated = 0, updated_vsan = 0, ret = SUCCEED;
+	const char			*pcollecter = vmware_service_objects[service->type].property_collector;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() hvid:'%s'", __func__, hvid);
+
+	zbx_vector_str_create(&scsi_luns);
+	zbx_xml_read_values(hv_data, ZBX_XPATH_HV_SCSI_TOPOLOGY, &scsi_luns);
+	total = scsi_luns.values_num;
+	zabbix_log(LOG_LEVEL_DEBUG, "%s() count of scsiLun:%d", __func__, total);
+
+	if (0 == total)
+		goto out;
+
+	for (i = 0; i < scsi_luns.values_num; i++)
+	{
+		scsi_req = zbx_strdcatf(scsi_req , ZBX_POST_SCSI_INFO, scsi_luns.values[i], scsi_luns.values[i],
+				scsi_luns.values[i], scsi_luns.values[i], scsi_luns.values[i], scsi_luns.values[i],
+				scsi_luns.values[i], scsi_luns.values[i]);
+	}
+
+	zbx_vector_str_clear_ext(&scsi_luns, zbx_str_free);
+	hvid_esc = zbx_xml_escape_dyn(hvid);
+	tmp = zbx_dsprintf(NULL, ZBX_POST_HV_DISK_INFO, pcollecter, scsi_req, hvid_esc);
+	zbx_free(hvid_esc);
+	zbx_free(scsi_req);
+
+	if (SUCCEED != (ret = zbx_property_collection_init(easyhandle, tmp, pcollecter, &iter, &doc, error)))
+		goto out;
+
+	updated += vmware_service_hv_disks_parse_info(doc, dss, disks_info);
+
+	while (NULL != iter->token)
+	{
+		zbx_xml_free_doc(doc);
+		doc = NULL;
+
+		if (SUCCEED != (ret = zbx_property_collection_next(iter, &doc, error)))
+			goto out;
+
+		updated += vmware_service_hv_disks_parse_info(doc, dss, disks_info);
+	}
+
+	if (NULL == vsan_uuid)
+		goto out;
+
+	zbx_property_collection_free(iter);
+	iter = NULL;
+	zbx_vector_ptr_pair_sort(disks_info, vmware_diskinfo_diskname_compare);
+	hvid_esc = zbx_xml_escape_dyn(hvid);
+	tmp = zbx_dsprintf(NULL, ZBX_POST_HV_DISK_INFO, pcollecter ,
+			"<ns0:pathSet>config.vsanHostConfig.storageInfo.diskMapping</ns0:pathSet>", hvid_esc);
+	zbx_free(hvid_esc);
+
+	if (SUCCEED != (ret = zbx_property_collection_init(easyhandle, tmp, pcollecter, &iter, &doc_dinfo, &err)))
+	{
+		zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot get vsan disk_info:%s", __func__, err);
+		zbx_str_free(err);
+		goto out;
+	}
+
+	updated_vsan += vmware_service_hv_vsan_parse_info(doc_dinfo, vsan_uuid, disks_info);
+
+	while (NULL != iter->token)
+	{
+		zbx_xml_free_doc(doc_dinfo);
+		doc_dinfo = NULL;
+
+		if (SUCCEED != (ret = zbx_property_collection_next(iter, &doc_dinfo, error)))
+			goto out;
+
+		updated_vsan += vmware_service_hv_vsan_parse_info(doc_dinfo, vsan_uuid, disks_info);
+	}
+out:
+	zbx_free(tmp);
+	zbx_xml_free_doc(doc);
+	zbx_xml_free_doc(doc_dinfo);
+	zbx_vector_str_destroy(&scsi_luns);
+	zbx_property_collection_free(iter);
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s for %d(vsan:%d) / %d", __func__, zbx_result_string(ret), updated,
+			updated_vsan, total);
+
+	return ret;
+
+#	undef	ZBX_POST_SCSI_INFO
+#	undef	ZBX_POST_HV_DISK_INFO
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: vmware_ds_uuid_compare                                           *
+ *                                                                            *
+ * Purpose: sorting function to sort Datastore vector by uuid                 *
+ *                                                                            *
+ ******************************************************************************/
+int	vmware_ds_uuid_compare(const void *d1, const void *d2)
+{
+	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
+	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+
+	return strcmp(ds1->uuid, ds2->uuid);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: vmware_ds_name_compare                                           *
+ *                                                                            *
+ * Purpose: sorting function to sort Datastore vector by name                 *
+ *                                                                            *
+ ******************************************************************************/
+int	vmware_ds_name_compare(const void *d1, const void *d2)
+{
+	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
+	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+
+	return strcmp(ds1->name, ds2->name);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort Datastore vector by id                   *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_ds_id_compare(const void *d1, const void *d2)
+{
+	const zbx_vmware_datastore_t	*ds1 = *(const zbx_vmware_datastore_t * const *)d1;
+	const zbx_vmware_datastore_t	*ds2 = *(const zbx_vmware_datastore_t * const *)d2;
+
+	return strcmp(ds1->id, ds2->id);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort Datacenter vector by id                  *
+ *                                                                            *
+ ******************************************************************************/
+int	vmware_dc_id_compare(const void *d1, const void *d2)
+{
+	const zbx_vmware_datacenter_t	*dc1 = *(const zbx_vmware_datacenter_t * const *)d1;
+	const zbx_vmware_datacenter_t	*dc2 = *(const zbx_vmware_datacenter_t * const *)d2;
+
+	return strcmp(dc1->id, dc2->id);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort custom attributes vector by name         *
+ *                                                                            *
+ ******************************************************************************/
+int	vmware_custom_attr_compare_name(const void *a1, const void *a2)
+{
+	const zbx_vmware_custom_attr_t	*attr1 = *(const zbx_vmware_custom_attr_t * const *)a1;
+	const zbx_vmware_custom_attr_t	*attr2 = *(const zbx_vmware_custom_attr_t * const *)a2;
+
+	return strcmp(attr1->name, attr2->name);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort DVSwitch vector by uuid                  *
+ *                                                                            *
+ ******************************************************************************/
+int	vmware_dvs_uuid_compare(const void *d1, const void *d2)
+{
+	const zbx_vmware_dvswitch_t	*dvs1 = *(const zbx_vmware_dvswitch_t * const *)d1;
+	const zbx_vmware_dvswitch_t	*dvs2 = *(const zbx_vmware_dvswitch_t * const *)d2;
+
+	return strcmp(dvs1->uuid, dvs2->uuid);
+}
+
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort DVSwitch vector by uuid                  *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_cq_instance_id_compare(const void *d1, const void *d2)
+{
+	int	ret;
+
+	const zbx_vmware_cq_value_t	*prop1 = *(const zbx_vmware_cq_value_t * const *)d1;
+	const zbx_vmware_cq_value_t	*prop2 = *(const zbx_vmware_cq_value_t * const *)d2;
+
+	if (0 == (ret = strcmp(prop1->instance->soap_type, prop2->instance->soap_type)))
+		ret = strcmp(prop1->instance->id, prop2->instance->id);
+
+	return ret;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: sorting function to sort diskinfo vector by diskname              *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_diskinfo_diskname_compare(const void *d1, const void *d2)
+{
+	const zbx_ptr_pair_t		*p1 = (const zbx_ptr_pair_t *)d1;
+	const zbx_ptr_pair_t		*p2 = (const zbx_ptr_pair_t *)d2;
+	const zbx_vmware_diskinfo_t	*di1 = (const zbx_vmware_diskinfo_t *)p1->second;
+	const zbx_vmware_diskinfo_t	*di2 = (const zbx_vmware_diskinfo_t *)p2->second;
+
+	return strcmp(di1->diskname, di2->diskname);
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: populate array of values from an xml data                         *
+ *                                                                            *
+ * Parameters: xdoc    - [IN] XML document                                    *
+ *             ds_node - [IN] xml node with datastore info                    *
+ *             ds_id   - [IN] datastore id (for logging)                      *
+ *                                                                            *
+ * Return: bitmap value of HV access mode to DS                               *
+ *                                                                            *
+ ******************************************************************************/
+static zbx_uint64_t	vmware_hv_get_ds_access(xmlDoc *xdoc, xmlNode *ds_node, const char *ds_id)
+{
+
+	zbx_uint64_t	mi_access = ZBX_VMWARE_DS_NONE;
+	char		*value;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() for DS:%s", __func__, ds_id);
+
+	if (NULL != (value = zbx_xml_node_read_value(xdoc, ds_node, ZBX_XPATH_PROP_SUFFIX("mounted"))))
+	{
 		if (0 == strcmp(value, "true"))
 			mi_access |= ZBX_VMWARE_DS_MOUNTED;
 
@@ -5252,6 +5848,7 @@ static int	vmware_hv_ds_access_update(zbx_vmware_service_t *service, CURL *easyh
 		ZBX_POST_VSPHERE_FOOTER
 
 	char				*hvid_esc, tmp[MAX_STRING_LEN];
+	const char			*pcollector = vmware_service_objects[service->type].property_collector;
 	int				ret = FAIL, updated = 0;
 	xmlDoc				*doc = NULL;
 	zbx_property_collection_iter	*iter = NULL;
@@ -5260,11 +5857,10 @@ static int	vmware_hv_ds_access_update(zbx_vmware_service_t *service, CURL *easyh
 			dss->values_num);
 
 	hvid_esc = zbx_xml_escape_dyn(hv_id);
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_HV_DS_ACCESS, vmware_service_objects[service->type].property_collector,
-			hvid_esc, hvid_esc, hvid_esc, hvid_esc);
+	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_HV_DS_ACCESS, pcollector, hvid_esc, hvid_esc, hvid_esc, hvid_esc);
 	zbx_free(hvid_esc);
 
-	if (SUCCEED != zbx_property_collection_init(easyhandle, tmp, "propertyCollector", &iter, &doc, error))
+	if (SUCCEED != zbx_property_collection_init(easyhandle, tmp, pcollector, &iter, &doc, error))
 		goto out;
 
 	updated += vmware_hv_ds_access_parse(doc, hv_dss, hv_uuid, hv_id, dss);
@@ -5372,6 +5968,41 @@ clean:
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() found:%d", __func__, i);
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Function: vmware_hv_vsan_uuid                                              *
+ *                                                                            *
+ * Purpose: search for Datastore uuid with type equal to 'vsan'               *
+ *                                                                            *
+ * Parameters: dss    - [IN] the vector with all Datastores                   *
+ *             hv_dss - [IN] the vector with all Datastores attechad to HV    *
+ *                                                                            *
+ * Return value: pointer to vsan DS uuid or NULL                              *
+ *                                                                            *
+ ******************************************************************************/
+static const char	*vmware_hv_vsan_uuid(zbx_vector_vmware_datastore_t *dss, zbx_vector_str_t *hv_dss)
+{
+	int	i;
+
+	for (i = 0; i < hv_dss->values_num; i++)
+	{
+		int			j;
+		zbx_vmware_datastore_t	*ds, ds_cmp;
+
+		ds_cmp.id = hv_dss->values[i];
+
+		if (FAIL == (j = zbx_vector_vmware_datastore_bsearch(dss, &ds_cmp, vmware_ds_id_compare)))
+			continue;
+
+		ds = dss->values[j];
+
+		if ('v' == *ds->type && 0 == strcmp("vsan", ds->type))	/* only one vsan can be attached to HV */
+			return ds->uuid;
+	}
+
+	return NULL;
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: sorting function to sort Resource pool names vector by name       *
@@ -5410,30 +6041,36 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 		zbx_vector_cq_value_t *cq_values, zbx_vmware_alarms_data_t *alarms_data, zbx_vmware_hv_t *hv,
 		char **error)
 {
-	char				*value, buff[MAX_STRING_LEN];
+	char				*value, *cq_prop;
+	int				i, j, ret;
 	xmlDoc				*details = NULL, *multipath_data = NULL;
 	zbx_vector_str_t		datastores, vms;
-	zbx_vmware_cq_value_t		*cqv;
-	int				i, j, ret = FAIL;
+	zbx_vector_cq_value_t		cqvs;
+	zbx_vector_ptr_pair_t		disks_info;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() hvid:'%s'", __func__, id);
 
 	memset(hv, 0, sizeof(zbx_vmware_hv_t));
 
 	zbx_vector_vmware_dsname_create(&hv->dsnames);
+	zbx_vector_vmware_diskinfo_create(&hv->diskinfo);
 	zbx_vector_ptr_create(&hv->vms);
 
 	zbx_vector_str_create(&datastores);
 	zbx_vector_str_create(&vms);
+	zbx_vector_ptr_pair_create(&disks_info);
+	zbx_vector_cq_value_create(&cqvs);
 
 	zbx_vector_vmware_pnic_create(&hv->pnics);
+	cq_prop = vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_HV, id, &cqvs);
+	ret = vmware_service_get_hv_data(service, easyhandle, id, hv_propmap, ZBX_VMWARE_HVPROPS_NUM, cq_prop,
+			&details, error);
+	zbx_str_free(cq_prop);
 
-	if (SUCCEED != vmware_service_get_hv_data(service, easyhandle, id, hv_propmap, ZBX_VMWARE_HVPROPS_NUM,
-			vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_HV, id, sizeof(buff), buff, &cqv),
-			&details, error))
-	{
+	if (FAIL == ret)
 		goto out;
-	}
+
+	ret = FAIL;
 
 	if (NULL == (hv->props = xml_read_props(details, hv_propmap, ZBX_VMWARE_HVPROPS_NUM)))
 		goto out;
@@ -5446,16 +6083,21 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 
 	vmware_service_get_hv_pnics_data(details, &hv->pnics);
 	zbx_vector_str_create(&hv->alarm_ids);
-	vmware_service_get_alarms_data(__func__, service, easyhandle, details, NULL, &hv->alarm_ids, alarms_data,
-			error);
+
+	if (FAIL == vmware_service_get_alarms_data(__func__, service, easyhandle, details, NULL, &hv->alarm_ids,
+			alarms_data, error))
+	{
+		zabbix_log(LOG_LEVEL_WARNING, "Cannot get hv %s alarms: %s.", hv->id, *error);
+		zbx_str_free(*error);
+	}
 
 	if (NULL != (value = zbx_xml_doc_read_value(details, "//*[@type='" ZBX_VMWARE_SOAP_CLUSTER "']")))
 		hv->clusterid = value;
 
 	hv->ip = vmware_hv_ip_search(details);
 
-	if (NULL != cqv)
-		vmware_service_cq_prop_value(__func__, details, cqv);
+	if (0 != cqvs.values_num)
+		vmware_service_cq_prop_value(__func__, details, &cqvs);
 
 	if (SUCCEED != vmware_hv_get_parent_data(service, easyhandle, hv, error))
 		goto out;
@@ -5469,6 +6111,12 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 	if (SUCCEED != vmware_service_hv_get_multipath_data(service, easyhandle, details, id, &multipath_data, error))
 		goto out;
 
+	if (SUCCEED != vmware_service_hv_disks_get_info(service, easyhandle, details, id, dss,
+			vmware_hv_vsan_uuid(dss, &datastores), &disks_info, error))
+	{
+		goto out;
+	}
+
 	if (SUCCEED != vmware_hv_ds_access_update(service, easyhandle, hv->uuid, hv->id, &datastores, dss, error))
 		goto out;
 
@@ -5498,17 +6146,23 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 		{
 			zbx_vmware_diskextent_t	*diskextent = ds->diskextents.values[j];
 			zbx_vmware_hvdisk_t	hvdisk;
-			char			tmp[MAX_STRING_LEN], *lun;
+			zbx_vmware_diskinfo_t	di;
+			zbx_ptr_pair_t		pair_cmp = {.second = &di};
+			const char		*lun;
+			char			tmp[MAX_STRING_LEN];
+			int			k;
 
-			zbx_snprintf(tmp, sizeof(tmp), ZBX_XPATH_HV_LUN(), diskextent->diskname);
+			di.diskname = diskextent->diskname;
 
-			if (NULL == (lun = zbx_xml_doc_read_value(multipath_data, tmp)))
+			if (FAIL == (k = zbx_vector_ptr_pair_bsearch(&disks_info, pair_cmp,
+					vmware_diskinfo_diskname_compare)))
 			{
 				zabbix_log(LOG_LEVEL_DEBUG, "%s(): not found diskextent: %s",
 						__func__, diskextent->diskname);
 				continue;
 			}
 
+			lun = (const char*)disks_info.values[k].first;
 			zbx_snprintf(tmp, sizeof(tmp), ZBX_XPATH_HV_MULTIPATH_PATHS(), lun);
 
 			if (SUCCEED != zbx_xml_doc_read_num(multipath_data, tmp, &hvdisk.multipath_total) ||
@@ -5516,7 +6170,6 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 			{
 				zabbix_log(LOG_LEVEL_DEBUG, "%s(): for diskextent: %s and lun: %s"
 						" multipath data is not found", __func__, diskextent->diskname, lun);
-				zbx_free(lun);
 				continue;
 			}
 
@@ -5527,7 +6180,6 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 
 			hvdisk.partitionid = diskextent->partitionid;
 			zbx_vector_vmware_hvdisk_append(&dsname->hvdisks, hvdisk);
-			zbx_free(lun);
 		}
 
 		zbx_vector_vmware_hvdisk_sort(&dsname->hvdisks, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
@@ -5552,7 +6204,14 @@ static int	vmware_service_init_hv(zbx_vmware_service_t *service, CURL *easyhandl
 			zabbix_log(LOG_LEVEL_DEBUG, "Unable initialize vm %s: %s.", vms.values[i], *error);
 			zbx_free(*error);
 		}
+	}
+
+	zbx_vector_vmware_diskinfo_reserve(&hv->diskinfo, (size_t)disks_info.values_num);
 
+	for (i = 0; i < disks_info.values_num; i++)
+	{
+		zbx_vector_vmware_diskinfo_append(&hv->diskinfo, disks_info.values[i].second);
+		disks_info.values[i].second = NULL;
 	}
 
 	ret = SUCCEED;
@@ -5565,6 +6224,17 @@ out:
 
 	zbx_vector_str_clear_ext(&datastores, zbx_str_free);
 	zbx_vector_str_destroy(&datastores);
+	zbx_vector_cq_value_destroy(&cqvs);
+
+	for (i = 0; i < disks_info.values_num; i++)
+	{
+		zbx_str_free(disks_info.values[i].first);
+
+		if (NULL != disks_info.values[i].second)
+			vmware_diskinfo_free((zbx_vmware_diskinfo_t *)disks_info.values[i].second);
+	}
+
+	zbx_vector_ptr_pair_destroy(&disks_info);
 
 	if (SUCCEED != ret)
 		vmware_hv_clean(hv);
@@ -5641,7 +6311,8 @@ static int	vmware_service_get_datacenters_list(const zbx_vmware_service_t *servi
 				nodeset->nodeTab[i], ZBX_XPATH_PROP_NAME_NODE("triggeredAlarmState")),
 				&datacenter->alarm_ids, alarms_data, &error))
 		{
-			zabbix_log(LOG_LEVEL_DEBUG, "%s(): Cannot get datacenter alarms: %s.", __func__, error);
+			zabbix_log(LOG_LEVEL_DEBUG, "%s(): Cannot get datacenter %s alarms: %s.", __func__,
+					datacenter->id, error);
 			zbx_str_free(error);
 		}
 
@@ -5916,6 +6587,7 @@ static int	vmware_service_get_hv_ds_dc_dvs_list(const zbx_vmware_service_t *serv
 		ZBX_XPATH_PROP_NAME_NODE("triggeredAlarmState")
 
 	char				tmp[MAX_STRING_LEN * 2];
+	const char			*pcollector = vmware_service_objects[service->type].property_collector;
 	int				ret = FAIL;
 	xmlDoc				*doc = NULL;
 	xmlNode				*vc_alarms;
@@ -5923,21 +6595,18 @@ static int	vmware_service_get_hv_ds_dc_dvs_list(const zbx_vmware_service_t *serv
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VCENTER_HV_DS_LIST,
-			vmware_service_objects[service->type].property_collector,
+	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VCENTER_HV_DS_LIST, pcollector,
 			vmware_service_objects[service->type].root_folder);
 
-	if (SUCCEED != zbx_property_collection_init(easyhandle, tmp, "propertyCollector", &iter, &doc, error))
-	{
+	if (SUCCEED != zbx_property_collection_init(easyhandle, tmp, pcollector, &iter, &doc, error))
 		goto out;
-	}
 
 	if (ZBX_VMWARE_TYPE_VCENTER == service->type)
-		zbx_xml_read_values(doc, "//*[@type='HostSystem']", hvs);
+		zbx_xml_read_values(doc, ZBX_XPATH_OBJS_BY_TYPE(ZBX_VMWARE_SOAP_HV) , hvs);
 	else
 		zbx_vector_str_append(hvs, zbx_strdup(NULL, "ha-host"));
 
-	zbx_xml_read_values(doc, "//*[@type='Datastore']", dss);
+	zbx_xml_read_values(doc, ZBX_XPATH_OBJS_BY_TYPE(ZBX_VMWARE_SOAP_DS), dss);
 	vmware_service_get_datacenters_list(service, easyhandle, doc, alarms_data, datacenters);
 	vmware_service_get_dvswitch_list(doc, dvswitches);
 	zbx_snprintf(tmp, sizeof(tmp), ZBX_XPATH_GET_ROOT_ALARMS(ZBX_VMWARE_SOAP_FOLDER, "%s"),
@@ -5958,9 +6627,9 @@ static int	vmware_service_get_hv_ds_dc_dvs_list(const zbx_vmware_service_t *serv
 			goto out;
 
 		if (ZBX_VMWARE_TYPE_VCENTER == service->type)
-			zbx_xml_read_values(doc, "//*[@type='HostSystem']", hvs);
+			zbx_xml_read_values(doc, ZBX_XPATH_OBJS_BY_TYPE(ZBX_VMWARE_SOAP_HV), hvs);
 
-		zbx_xml_read_values(doc, "//*[@type='Datastore']", dss);
+		zbx_xml_read_values(doc, ZBX_XPATH_OBJS_BY_TYPE(ZBX_VMWARE_SOAP_DS), dss);
 		vmware_service_get_datacenters_list(service, easyhandle, doc, alarms_data, datacenters);
 		vmware_service_get_dvswitch_list(doc, dvswitches);
 
@@ -6246,7 +6915,8 @@ static int	vmware_service_put_event_data(zbx_vector_ptr_t *events, zbx_id_xmlnod
 {
 	zbx_vmware_event_t		*event = NULL;
 	char				*message, *time_str, *ip;
-	int				timestamp = 0, nodes_det = 0;
+	int				nodes_det = 0;
+	time_t				timestamp = 0;
 	unsigned int			i;
 	zbx_uint64_t			sz;
 	static event_hostinfo_node_t	host_nodes[] =
@@ -6314,21 +6984,11 @@ static int	vmware_service_put_event_data(zbx_vector_ptr_t *events, zbx_id_xmlnod
 	}
 	else
 	{
-		int	year, mon, mday, hour, min, sec, t;
-
-		/* 2013-06-04T14:19:23.406298Z */
-		if (6 != sscanf(time_str, "%d-%d-%dT%d:%d:%d.%*s", &year, &mon, &mday, &hour, &min, &sec))
-		{
-			zabbix_log(LOG_LEVEL_TRACE, "unexpected format of createdTime '%s' for event"
-					" key '" ZBX_FS_UI64 "'", time_str, xml_event.id);
-		}
-		else if (SUCCEED != zbx_utc_time(year, mon, mday, hour, min, sec, &t))
+		if (FAIL == zbx_iso8601_utc(time_str, &timestamp))	/* 2013-06-04T14:19:23.406298Z */
 		{
-			zabbix_log(LOG_LEVEL_TRACE, "cannot convert createdTime '%s' for event key '"
+			zabbix_log(LOG_LEVEL_TRACE, "unexpected format of createdTime '%s' for event key '"
 					ZBX_FS_UI64 "'", time_str, xml_event.id);
 		}
-		else
-			timestamp = t;
 
 		zbx_free(time_str);
 	}
@@ -6881,16 +7541,19 @@ out:
  *                                                                            *
  * Parameters: easyhandle   - [IN] the CURL handle                            *
  *             clusterid    - [IN] the cluster id                             *
+ *             datastores   - [IN] all available Datastores                   *
  *             cq_values    - [IN/OUT] the vector with custom query entries   *
  *             status       - [OUT] a pointer to the output variable          *
+ *             dss          - [OUT] a list of DS available for cluster        *
  *             error        - [OUT] the error message in the case of failure  *
  *                                                                            *
  * Return value: SUCCEED - the operation has completed successfully           *
  *               FAIL    - the operation has failed                           *
  *                                                                            *
  ******************************************************************************/
-static int	vmware_service_get_cluster_status(CURL *easyhandle, const char *clusterid,
-		zbx_vector_cq_value_t *cq_values, char **status, char **error)
+static int	vmware_service_get_cluster_state(CURL *easyhandle, const char *clusterid,
+		const zbx_vector_vmware_datastore_t *datastores, zbx_vector_cq_value_t *cq_values, char **status,
+		zbx_vector_str_t *dss, char **error)
 {
 #	define ZBX_POST_VMWARE_CLUSTER_STATUS 								\
 		ZBX_POST_VSPHERE_HEADER									\
@@ -6901,6 +7564,7 @@ static int	vmware_service_get_cluster_status(CURL *easyhandle, const char *clust
 					"<ns0:type>ClusterComputeResource</ns0:type>"			\
 					"<ns0:all>false</ns0:all>"					\
 					"<ns0:pathSet>summary.overallStatus</ns0:pathSet>"		\
+					"<ns0:pathSet>datastore</ns0:pathSet>"				\
 					"%s"								\
 				"</ns0:propSet>"							\
 				"<ns0:objectSet>"							\
@@ -6911,32 +7575,56 @@ static int	vmware_service_get_cluster_status(CURL *easyhandle, const char *clust
 		"</ns0:RetrievePropertiesEx>"								\
 		ZBX_POST_VSPHERE_FOOTER
 
-	char			tmp[MAX_STRING_LEN], *clusterid_esc, buff[MAX_STRING_LEN];
-	int			ret = FAIL;
+	char			*tmp, *clusterid_esc, *cq_prop;
+	int			i, ret = FAIL;
 	xmlDoc			*doc = NULL;
-	zbx_vmware_cq_value_t	*cqv;
-
+	zbx_vector_cq_value_t	cqvs;
+	zbx_vector_str_t	ids;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() clusterid:'%s'", __func__, clusterid);
 
+	zbx_vector_str_create(&ids);
+	zbx_vector_cq_value_create(&cqvs);
 	clusterid_esc = zbx_xml_escape_dyn(clusterid);
+	cq_prop = vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_CLUSTER, clusterid, &cqvs);
 
-	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_CLUSTER_STATUS,
-			vmware_cq_prop_soap_request(cq_values, ZBX_VMWARE_SOAP_CLUSTER, clusterid, sizeof(buff), buff,
-			&cqv), clusterid_esc);
+	tmp = zbx_dsprintf(NULL, ZBX_POST_VMWARE_CLUSTER_STATUS, cq_prop, clusterid_esc);
 
-	zbx_free(clusterid_esc);
+	zbx_str_free(cq_prop);
+	zbx_str_free(clusterid_esc);
+	ret = zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, error);
+	zbx_str_free(tmp);
 
-	if (SUCCEED != zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, error))
+	if (FAIL == ret)
 		goto out;
 
 	*status = zbx_xml_doc_read_value(doc, ZBX_XPATH_PROP_NAME("summary.overallStatus"));
 
-	if (NULL != cqv)
-		vmware_service_cq_prop_value(__func__, doc, cqv);
+	if (0 != cqvs.values_num)
+		vmware_service_cq_prop_value(__func__, doc, &cqvs);
 
-	ret = SUCCEED;
+	zbx_xml_read_values(doc, ZBX_XPATH_PROP_NAME("datastore") "/*", &ids);
+
+	for (i = 0; i < ids.values_num; i++)
+	{
+		int			j;
+		zbx_vmware_datastore_t	ds_cmp;
+
+		ds_cmp.id = ids.values[i];
+
+		if (FAIL == (j = zbx_vector_vmware_datastore_bsearch(datastores, &ds_cmp, vmware_ds_id_compare)))
+		{
+			zabbix_log(LOG_LEVEL_DEBUG, "%s(): Datastore \"%s\" not found on cluster \"%s\".", __func__,
+					ds_cmp.id, clusterid);
+			continue;
+		}
+
+		zbx_vector_str_append(dss, zbx_strdup(NULL, datastores->values[j]->uuid));
+	}
 out:
+	zbx_vector_cq_value_destroy(&cqvs);
+	zbx_vector_str_clear_ext(&ids, zbx_str_free);
+	zbx_vector_str_destroy(&ids);
 	zbx_xml_free_doc(doc);
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
 
@@ -6951,6 +7639,7 @@ out:
  *                                                                            *
  * Parameters: service       - [IN] the vmware service                        *
  *             easyhandle    - [IN] the CURL handle                           *
+ *             datastores    - [IN] all available Datastores                  *
  *             cq_values     - [IN/OUT] the vector with custom query entries  *
  *             clusters      - [OUT] a pointer to the resulting clusters      *
  *                              vector                                        *
@@ -6964,38 +7653,39 @@ out:
  *                                                                            *
  ******************************************************************************/
 static int	vmware_service_get_clusters_and_resourcepools(zbx_vmware_service_t *service, CURL *easyhandle,
-		zbx_vector_cq_value_t *cq_values, zbx_vector_ptr_t *clusters,
-		zbx_vector_vmware_resourcepool_t *resourcepools, zbx_vmware_alarms_data_t *alarms_data, char **error)
+		const zbx_vector_vmware_datastore_t *datastores, zbx_vector_cq_value_t *cq_values,
+		zbx_vector_ptr_t *clusters, zbx_vector_vmware_resourcepool_t *resourcepools,
+		zbx_vmware_alarms_data_t *alarms_data, char **error)
 {
 	char			xpath[MAX_STRING_LEN];
 	int			i, ret = FAIL;
 	xmlDoc			*cluster_data = NULL;
-	zbx_vector_str_t	ids, rpools_all, rpools_uniq;
+	zbx_vector_str_t	ids, rpools_all, rpools_uniq, dss;
 	zbx_vmware_cluster_t	*cluster;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
 	zbx_vector_str_create(&ids);
+	zbx_vector_str_create(&dss);
 
 	if (SUCCEED != vmware_service_get_cluster_data(easyhandle, &cluster_data, error))
 		goto out;
 
-	zbx_xml_read_values(cluster_data, "/*/*/*/*/*[local-name()='objects']/*[local-name()='obj']"
-			"[@type='" ZBX_VMWARE_SOAP_CLUSTER "']", &ids);
+	zbx_xml_read_values(cluster_data, ZBX_XPATH_OBJS_BY_TYPE(ZBX_VMWARE_SOAP_CLUSTER), &ids);
 	zbx_vector_ptr_reserve(clusters, (size_t)(ids.values_num + clusters->values_alloc));
 
 	for (i = 0; i < ids.values_num; i++)
 	{
 		char	*status, *name;
 
-		zbx_snprintf(xpath, sizeof(xpath), "/*/*/*/*/*[local-name()='objects'][*[local-name()='obj']"
-				"[@type='" ZBX_VMWARE_SOAP_CLUSTER "'][.='%s']]/" ZBX_XPATH_PROP_NAME_NODE("name"),
-				ids.values[i]);
+		zbx_snprintf(xpath, sizeof(xpath), ZBX_XPATH_PROP_OBJECT_ID(ZBX_VMWARE_SOAP_CLUSTER, "[text()='%s']")
+				"/" ZBX_XPATH_PROP_NAME_NODE("name"), ids.values[i]);
 
 		if (NULL == (name = zbx_xml_doc_read_value(cluster_data, xpath)))
 			continue;
 
-		if (SUCCEED != vmware_service_get_cluster_status(easyhandle, ids.values[i], cq_values, &status, error))
+		if (SUCCEED != vmware_service_get_cluster_state(easyhandle, ids.values[i], datastores, cq_values,
+				&status, &dss, error))
 		{
 			zbx_free(name);
 			goto out;
@@ -7005,6 +7695,9 @@ static int	vmware_service_get_clusters_and_resourcepools(zbx_vmware_service_t *s
 		cluster->id = zbx_strdup(NULL, ids.values[i]);
 		cluster->name = name;
 		cluster->status = status;
+		zbx_vector_str_create(&cluster->dss_uuid);
+		zbx_vector_str_append_array(&cluster->dss_uuid, dss.values, dss.values_num);
+		zbx_vector_str_clear(&dss);
 		zbx_vector_str_create(&cluster->alarm_ids);
 
 		if (FAIL == vmware_service_get_alarms_data(__func__, service, easyhandle, cluster_data, NULL,
@@ -7057,6 +7750,7 @@ out:
 	zbx_xml_free_doc(cluster_data);
 	zbx_vector_str_clear_ext(&ids, zbx_str_free);
 	zbx_vector_str_destroy(&ids);
+	zbx_vector_str_destroy(&dss);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s found cl:%d rp:%d", __func__, zbx_result_string(ret),
 			clusters->values_num, resourcepools->values_num);
@@ -7168,15 +7862,18 @@ out:
  * Parameters: counters  - [IN/OUT] the vector the created performance        *
  *                                  counter object should be added to         *
  *             counterid - [IN] the performance counter id                    *
+ *             state     - [IN] the performance counter first state           *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_counters_add_new(zbx_vector_ptr_t *counters, zbx_uint64_t counterid)
+static void	vmware_counters_add_new(zbx_vector_ptr_t *counters, zbx_uint64_t counterid, unsigned char state)
 {
 	zbx_vmware_perf_counter_t	*counter;
 
 	counter = (zbx_vmware_perf_counter_t *)__vm_shmem_malloc_func(NULL, sizeof(zbx_vmware_perf_counter_t));
 	counter->counterid = counterid;
-	counter->state = ZBX_VMWARE_COUNTER_NEW;
+	counter->state = state;
+	counter->last_used = 0;
+	counter->query_instance = NULL;
 
 	zbx_vector_str_uint64_pair_create_ext(&counter->values, __vm_shmem_malloc_func, __vm_shmem_realloc_func,
 			__vm_shmem_free_func);
@@ -7204,7 +7901,7 @@ static int	vmware_service_initialize(zbx_vmware_service_t *service, CURL *easyha
 {
 #	define UNPARSED_SERVICE_MAJOR_VERSION_DELIM	"."
 
-	char			*version_without_major, *version = NULL, *fullname = NULL;
+	char			*subversion, *version = NULL, *fullname = NULL;
 	zbx_vector_ptr_t	counters;
 	int			ret = FAIL;
 
@@ -7263,14 +7960,23 @@ static int	vmware_service_initialize(zbx_vmware_service_t *service, CURL *easyha
 
 	/* version should have the "x.y.z" format, but there is also an "x.y Un" format in nature */
 	/* according to https://www.vmware.com/support/policies/version.html */
-	if (NULL == (version_without_major = strstr(version, UNPARSED_SERVICE_MAJOR_VERSION_DELIM)))
+	if (NULL == (subversion = strstr(version, UNPARSED_SERVICE_MAJOR_VERSION_DELIM)))
 	{
 		*error = zbx_dsprintf(*error, "Invalid version: %s.", version);
 		goto unlock;
 	}
 
 	service->minor_version = (unsigned short)atoi(
-			strlen(UNPARSED_SERVICE_MAJOR_VERSION_DELIM) + version_without_major);
+			ZBX_CONST_STRLEN(UNPARSED_SERVICE_MAJOR_VERSION_DELIM) + subversion);
+
+	if (NULL != (subversion = strstr(ZBX_CONST_STRLEN(UNPARSED_SERVICE_MAJOR_VERSION_DELIM) + subversion,
+			UNPARSED_SERVICE_MAJOR_VERSION_DELIM)))
+	{
+		service->patch_version = (unsigned short)atoi(
+				ZBX_CONST_STRLEN(UNPARSED_SERVICE_MAJOR_VERSION_DELIM) + subversion);
+	}
+	else
+		service->patch_version = 0;
 
 	ret = SUCCEED;
 unlock:
@@ -7303,7 +8009,7 @@ out:
  *                                                                            *
  ******************************************************************************/
 static void	vmware_service_add_perf_entity(zbx_vmware_service_t *service, const char *type, const char *id,
-		const char **counters, const char *instance, int now)
+		const char **counters, const char *instance, time_t now)
 {
 	zbx_vmware_perf_entity_t	entity, *pentity;
 	zbx_uint64_t			counterid;
@@ -7324,7 +8030,7 @@ static void	vmware_service_add_perf_entity(zbx_vmware_service_t *service, const
 		for (i = 0; NULL != counters[i]; i++)
 		{
 			if (SUCCEED == zbx_vmware_service_get_counterid(service, counters[i], &counterid, NULL))
-				vmware_counters_add_new(&pentity->counters, counterid);
+				vmware_counters_add_new(&pentity->counters, counterid, ZBX_VMWARE_COUNTER_NEW);
 			else
 				zabbix_log(LOG_LEVEL_DEBUG, "cannot find performance counter %s", counters[i]);
 		}
@@ -7398,14 +8104,14 @@ static void	vmware_service_update_perf_entities(zbx_vmware_service_t *service)
 	zbx_hashset_iter_reset(&service->data->hvs, &iter);
 	while (NULL != (hv = (zbx_vmware_hv_t *)zbx_hashset_iter_next(&iter)))
 	{
-		vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_HV, hv->id, hv_perfcounters, "*",
-				service->lastcheck);
+		vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_HV, hv->id, hv_perfcounters,
+				ZBX_VMWARE_PERF_QUERY_ALL, service->lastcheck);
 
 		for (i = 0; i < hv->vms.values_num; i++)
 		{
 			vm = (zbx_vmware_vm_t *)hv->vms.values[i];
-			vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_VM, vm->id, vm_perfcounters, "*",
-					service->lastcheck);
+			vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_VM, vm->id, vm_perfcounters,
+					ZBX_VMWARE_PERF_QUERY_ALL, service->lastcheck);
 			zabbix_log(LOG_LEVEL_TRACE, "%s() for type: VirtualMachine hv id: %s hv uuid: %s linked vm id:"
 					" %s vm uuid: %s", __func__, hv->id, hv->uuid, vm->id, vm->uuid);
 		}
@@ -7416,8 +8122,8 @@ static void	vmware_service_update_perf_entities(zbx_vmware_service_t *service)
 		for (i = 0; i < service->data->datastores.values_num; i++)
 		{
 			zbx_vmware_datastore_t	*ds = service->data->datastores.values[i];
-			vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_DS, ds->id, ds_perfcounters, "",
-					service->lastcheck);
+			vmware_service_add_perf_entity(service, ZBX_VMWARE_SOAP_DS, ds->id, ds_perfcounters,
+					ZBX_VMWARE_PERF_QUERY_TOTAL, service->lastcheck);
 			zabbix_log(LOG_LEVEL_TRACE, "%s() for type: Datastore id: %s name: %s uuid: %s", __func__,
 					ds->id, ds->name, ds->uuid);
 		}
@@ -7440,18 +8146,18 @@ static void	vmware_service_copy_cust_query_response(zbx_vector_cq_value_t *cq_va
 
 	for (i = 0; i < cq_values->values_num; i++)
 	{
-		if (ZBX_VMWARE_CQV_ERROR == cq_values->values[i].status)
+		if (ZBX_VMWARE_CQV_ERROR == cq_values->values[i]->status)
 		{
-			vmware_shared_strfree(cq_values->values[i].instance->error);
-			cq_values->values[i].instance->error = vmware_shared_strdup(cq_values->values[i].response);
-			cq_values->values[i].instance->state = ZBX_VMWARE_CQ_ERROR | ZBX_VMWARE_CQ_SEPARATE;
+			vmware_shared_strfree(cq_values->values[i]->instance->error);
+			cq_values->values[i]->instance->error = vmware_shared_strdup(cq_values->values[i]->response);
+			cq_values->values[i]->instance->state = ZBX_VMWARE_CQ_ERROR | ZBX_VMWARE_CQ_SEPARATE;
 		}
-		else if (ZBX_VMWARE_CQV_VALUE == cq_values->values[i].status)
+		else if (ZBX_VMWARE_CQV_VALUE == cq_values->values[i]->status)
 		{
-			vmware_shared_strfree(cq_values->values[i].instance->value);
-			cq_values->values[i].instance->value = vmware_shared_strdup(cq_values->values[i].response);
-			cq_values->values[i].instance->state = (unsigned char)(ZBX_VMWARE_CQ_READY |
-					(cq_values->values[i].instance->state & ZBX_VMWARE_CQ_SEPARATE));
+			vmware_shared_strfree(cq_values->values[i]->instance->value);
+			cq_values->values[i]->instance->value = vmware_shared_strdup(cq_values->values[i]->response);
+			cq_values->values[i]->instance->state = (unsigned char)(ZBX_VMWARE_CQ_READY |
+					(cq_values->values[i]->instance->state & ZBX_VMWARE_CQ_SEPARATE));
 		}
 	}
 }
@@ -7473,16 +8179,18 @@ static void	vmware_service_cust_query_prep(zbx_hashset_t *cust_queries, const zb
 	zbx_vmware_cust_query_t	*instance;
 	time_t			now = time(NULL);
 
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() cust_queries:%d", __func__, cust_queries->num_data);
+
 	zbx_hashset_iter_reset(cust_queries, &iter);
 
 	while (NULL != (instance = (zbx_vmware_cust_query_t *)zbx_hashset_iter_next(&iter)))
 	{
-		zbx_vmware_cq_value_t	cqv = {NULL, ZBX_VMWARE_CQV_EMPTY, NULL};
+		zbx_vmware_cq_value_t	*cqv;
 
 		if (instance->query_type != type)
 			continue;
 
-		if (ZBX_VMWARE_CQ_NEW != instance->state && now - instance->last_pooled > SEC_PER_DAY)
+		if (0 == (instance->state & ZBX_VMWARE_CQ_NEW) && now - instance->last_pooled > SEC_PER_DAY)
 		{
 			vmware_shared_cust_query_clean(instance);
 			zbx_hashset_iter_remove(&iter);
@@ -7492,16 +8200,21 @@ static void	vmware_service_cust_query_prep(zbx_hashset_t *cust_queries, const zb
 		if (0 != (instance->state & ZBX_VMWARE_CQ_PAUSED))
 			continue;
 
-		if (ZBX_VMWARE_CQ_NEW != instance->state &&
+		if (0 == (instance->state & ZBX_VMWARE_CQ_NEW) &&
 				now - instance->last_pooled > 2 * ZBX_VMWARE_CACHE_UPDATE_PERIOD)
 		{
 			instance->state |= ZBX_VMWARE_CQ_PAUSED;
 			continue;
 		}
 
-		cqv.instance = instance;
+		cqv = (zbx_vmware_cq_value_t *)zbx_malloc(NULL, sizeof(zbx_vmware_cq_value_t));
+		cqv->status = ZBX_VMWARE_CQV_EMPTY;
+		cqv->instance = instance;
+		cqv->response = NULL;
 		zbx_vector_cq_value_append(cq_values, cqv);
 	}
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() cq_values:%d", __func__, cq_values->values_num);
 }
 
 /******************************************************************************
@@ -7532,7 +8245,7 @@ static void	vmware_service_dvswitch_load(CURL *easyhandle, zbx_vector_cq_value_t
 
 	for (i = 0; i < cq_values->values_num; i++)
 	{
-		zbx_vmware_cq_value_t	*cqv = &cq_values->values[i];
+		zbx_vmware_cq_value_t	*cqv = cq_values->values[i];
 		xmlNode			*node;
 
 		criteria[0] = '\0';
@@ -7598,36 +8311,47 @@ static void	vmware_service_dvswitch_load(CURL *easyhandle, zbx_vector_cq_value_t
  *                                                                            *
  * Parameters: fn_parent - [IN] parent function name                          *
  *             xdoc      - [IN] the xml document                              *
- *             cqv       - [IN/OUT] the custom query entry                    *
+ *             cqvs      - [IN/OUT] the custom query entries                  *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_service_cq_prop_value(const char *fn_parent, xmlDoc *xdoc, zbx_vmware_cq_value_t *cqv)
+static void	vmware_service_cq_prop_value(const char *fn_parent, xmlDoc *xdoc, zbx_vector_cq_value_t *cqvs)
 {
-	char	xpath[MAX_STRING_LEN];
-	xmlNode	*node;
-
-	zbx_snprintf(xpath, sizeof(xpath), ZBX_XPATH_PROP_NAME("%s"), cqv->instance->key);
+	int	i;
 
-	if (NULL == (node = zbx_xml_doc_get(xdoc, xpath)))
-	{
-		cqv->response = NULL;
-		cqv->status = ZBX_VMWARE_CQV_VALUE;
-	}
-	else if (NULL != node->xmlChildrenNode && XML_TEXT_NODE == node->xmlChildrenNode->type)
-	{
-		cqv->response = zbx_xml_node_read_value(xdoc, node, ".");
-		cqv->status = ZBX_VMWARE_CQV_VALUE;
-	}
-	else
+	for (i = 0; i < cqvs->values_num; i++)
 	{
-		cqv->response = zbx_strdup(NULL, "only scalar values can be returned.");
-		cqv->status = ZBX_VMWARE_CQV_ERROR;
-	}
+		char			xpath[MAX_STRING_LEN];
+		xmlNode			*node;
+		zbx_vmware_cq_value_t	*cqv = cqvs->values[i];
+
+		zbx_snprintf(xpath, sizeof(xpath), ZBX_XPATH_PROP_NAME("%s"), cqv->instance->key);
+
+		if (NULL == (node = zbx_xml_doc_get(xdoc, xpath)))
+		{
+			cqv->response = NULL;
+			cqv->status = ZBX_VMWARE_CQV_VALUE;
+		}
+		else if ('\0' != *cqv->instance->mode && 0 == strcmp(cqv->instance->mode, "json"))
+		{
+			zbx_xmlnode_to_json(node, &cqv->response);
+			cqv->status = ZBX_VMWARE_CQV_VALUE;
+		}
+		else if (NULL != node->xmlChildrenNode && XML_TEXT_NODE == node->xmlChildrenNode->type)
+		{
+			cqv->response = zbx_xml_node_read_value(xdoc, node, ".");
+			cqv->status = ZBX_VMWARE_CQV_VALUE;
+		}
+		else
+		{
+			cqv->response = zbx_strdup(NULL, "only scalar values can be returned.");
+			cqv->status = ZBX_VMWARE_CQV_ERROR;
+		}
 
-	zabbix_log(LOG_LEVEL_DEBUG, "%s() %s id:%s key:%s response length:%d node type:%d", fn_parent,
-			ZBX_VMWARE_CQV_ERROR == cqv->status ? "FAIL" : "SUCCEED", cqv->instance->id,
-			cqv->instance->key, NULL == cqv->response ? -1 : (int)strlen(cqv->response),
-			NULL != node && NULL != node->xmlChildrenNode ? (int)node->xmlChildrenNode->type : -1);
+		zabbix_log(LOG_LEVEL_DEBUG, "%s() %s id:%s key:%s response length:%d node type:%d", fn_parent,
+				ZBX_VMWARE_CQV_ERROR == cqv->status ? "FAIL" : "SUCCEED", cqv->instance->id,
+				cqv->instance->key, NULL == cqv->response ? -1 : (int)strlen(cqv->response),
+				NULL != node && NULL != node->xmlChildrenNode ? (int)node->xmlChildrenNode->type : -1);
+	}
 }
 
 /******************************************************************************
@@ -7635,16 +8359,17 @@ static void	vmware_service_cq_prop_value(const char *fn_parent, xmlDoc *xdoc, zb
  * Purpose: load vmware object property info from VC                          *
  *                                                                            *
  * Parameters: easyhandle - [IN] the CURL handle                              *
+ *             collector  - [IN] the name of vmware property collector        *
  *             cq_values  - [IN/OUT] the vector with custom query entries     *
  *                                     and responses                          *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_service_props_load(CURL *easyhandle, zbx_vector_cq_value_t *cq_values)
+static void	vmware_service_props_load(CURL *easyhandle, const char *collector, zbx_vector_cq_value_t *cq_values)
 {
 #	define ZBX_POST_OBJ_PROP									\
 		ZBX_POST_VSPHERE_HEADER									\
 		"<ns0:RetrievePropertiesEx>"								\
-			"<ns0:_this type=\"PropertyCollector\">propertyCollector</ns0:_this>"		\
+			"<ns0:_this type=\"PropertyCollector\">%s</ns0:_this>"		\
 			"<ns0:specSet>"									\
 				"<ns0:propSet>"								\
 					"<ns0:type>%s</ns0:type>"					\
@@ -7659,22 +8384,26 @@ static void	vmware_service_props_load(CURL *easyhandle, zbx_vector_cq_value_t *c
 		"</ns0:RetrievePropertiesEx>"								\
 		ZBX_POST_VSPHERE_FOOTER
 
-	int	i, total = 0, count = 0;
-	xmlDoc	*doc = NULL;
+	int			i, total = 0, count = 0;
+	xmlDoc			*doc = NULL;
+	zbx_vector_cq_value_t	cq_resp;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() props total:%d", __func__, cq_values->values_num);
 
+	zbx_vector_cq_value_create(&cq_resp);
+	zbx_vector_cq_value_append(&cq_resp, NULL);
+
 	for (i = 0; i < cq_values->values_num; i++)
 	{
 		char			*error = NULL, tmp[MAX_STRING_LEN];
-		zbx_vmware_cq_value_t	*cqv = &cq_values->values[i];
+		zbx_vmware_cq_value_t	*cqv = cq_values->values[i];
 
 		if (0 == (cqv->instance->state & ZBX_VMWARE_CQ_SEPARATE))
 			continue;
 
 		zbx_xml_free_doc(doc);
-		zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_OBJ_PROP, cqv->instance->soap_type, cqv->instance->key,
-				cqv->instance->soap_type, cqv->instance->id);
+		zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_OBJ_PROP, collector, cqv->instance->soap_type,
+				cqv->instance->key, cqv->instance->soap_type, cqv->instance->id);
 		total++;
 
 		if (SUCCEED != zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, &error))
@@ -7685,12 +8414,14 @@ static void	vmware_service_props_load(CURL *easyhandle, zbx_vector_cq_value_t *c
 			continue;
 		}
 
-		vmware_service_cq_prop_value(__func__, doc, cqv);
+		cq_resp.values[0] = cqv;
+		vmware_service_cq_prop_value(__func__, doc, &cq_resp);
 		count++;
 	}
 
 	zbx_xml_free_doc(doc);
 
+	zbx_vector_cq_value_destroy(&cq_resp);
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() count: %d / %d", __func__, count, total);
 
 #	undef ZBX_POST_OBJ_PROP
@@ -7702,37 +8433,81 @@ static void	vmware_service_props_load(CURL *easyhandle, zbx_vector_cq_value_t *c
  *                                                                            *
  * Parameters: cq_values - [IN] the vector with custom query entries          *
  *             soap_type - [IN] soap type of hv, vm etc                       *
- *             clusterid - [IN] cluster id                                    *
- *             bsz       - [IN] buffer size                                   *
- *             buff      - [IN/OUT] - buffer for soap query                   *
- *             cq_prop   - [OUT] - custom query entry                         *
+ *             obj_id    - [IN] vmware instance id (hv, vm etc)               *
+ *             cqvs      - [OUT] - custom query entry                         *
  *                                                                            *
  * Return value: pointer to string with soap sub query                        *
  *                                                                            *
  ******************************************************************************/
 static char	*vmware_cq_prop_soap_request(const zbx_vector_cq_value_t *cq_values, const char *soap_type,
-		const char *clusterid, const size_t bsz, char *buff, zbx_vmware_cq_value_t **cq_prop)
+		const char *obj_id, zbx_vector_cq_value_t *cqvs)
 {
-	int			i;
-	zbx_vmware_cust_query_t	instance = {.soap_type = (char *)soap_type, .id = (char *)clusterid};
-	zbx_vmware_cq_value_t	*cq, cmp = {.instance = &instance};
-
-	*buff = '\0';
-	*cq_prop = NULL;
+	int	i;
+	char	*buff = zbx_strdup(NULL, "");
 
-	if (FAIL == (i = zbx_vector_cq_value_bsearch(cq_values, cmp, vmware_cq_instance_id_compare)))
-		return buff;
+	for (i = 0; i < cq_values->values_num; i++)
+	{
+		zbx_vmware_cq_value_t	*cq = cq_values->values[i];
+		char			tmp[MAX_STRING_LEN / 4];
 
-	cq = &cq_values->values[i];
+		if (0 != cqvs->values_num && 0 != strcmp(cq->instance->id, obj_id))
+			break;
 
-	if (0 != (cq->instance->state & ZBX_VMWARE_CQ_SEPARATE))
-		return buff;
+		if (0 != (cq->instance->state & ZBX_VMWARE_CQ_SEPARATE) || 0 != strcmp(cq->instance->id, obj_id) ||
+				0 != strcmp(cq->instance->soap_type, soap_type))
+		{
+			continue;
+		}
 
-	zbx_snprintf(buff, bsz, "<ns0:pathSet>%s</ns0:pathSet>", cq->instance->key);
-	*cq_prop = cq;
+		zbx_snprintf(tmp, sizeof(tmp), "<ns0:pathSet>%s</ns0:pathSet>", cq->instance->key);
+		buff = zbx_strdcat(buff, tmp);
+		zbx_vector_cq_value_append(cqvs, cq);
+	}
 
 	return buff;
 }
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: set CURL headers for soap request                                 *
+ *                                                                            *
+ * Parameters: easyhandle - [IN] prepared cURL connection handle              *
+ *             vc_version - [IN] major version of vc                          *
+ *             headers    - [IN/OUT] the CURL headers                         *
+ *             error      - [OUT] the error message in the case of failure    *
+ *                                                                            *
+ * Return value: SUCCEED - the headers were set successfully                  *
+ *               FAIL    - otherwise                                          *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_curl_set_header(CURL *easyhandle, int vc_version, struct curl_slist **headers, char **error)
+{
+	char		soapver[MAX_STRING_LEN / 32];
+	CURLoption	opt;
+	CURLcode	err;
+
+	if (0 != vc_version && 6 > vc_version)
+		return SUCCEED;
+	else if (6 > vc_version)
+		zbx_strlcpy(soapver, ZBX_XML_HEADER1_V4, sizeof(soapver));
+	else
+		zbx_strlcpy(soapver, ZBX_XML_HEADER1_V6, sizeof(soapver));
+
+	curl_slist_free_all(*headers);
+	*headers = NULL;
+	*headers = curl_slist_append(*headers, soapver);
+	*headers = curl_slist_append(*headers, ZBX_XML_HEADER2);
+	*headers = curl_slist_append(*headers, ZBX_XML_HEADER3);
+
+	if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPHEADER, *headers)))
+	{
+		*error = zbx_dsprintf(*error, "Cannot set cURL option %d: %s.", (int)opt, curl_easy_strerror(err));
+		return FAIL;
+	}
+
+	return SUCCEED;
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: updates object with a new data from vmware service                *
@@ -7743,8 +8518,6 @@ static char	*vmware_cq_prop_soap_request(const zbx_vector_cq_value_t *cq_values,
 int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 {
 	CURL			*easyhandle = NULL;
-	CURLoption		opt;
-	CURLcode		err;
 	struct curl_slist	*headers = NULL;
 	zbx_vmware_data_t	*data;
 	zbx_vector_str_t	hvs, dss;
@@ -7755,7 +8528,7 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 	ZBX_HTTPPAGE		page;	/* 347K/87K */
 	unsigned char		evt_pause = 0, evt_skip_old;
 	zbx_uint64_t		evt_last_key, events_sz = 0;
-	char			msg[MAX_STRING_LEN / 8], soapver[MAX_STRING_LEN / 32];
+	char			msg[MAX_STRING_LEN / 8];
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __func__, service->username, service->url);
 
@@ -7789,11 +8562,6 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 
 	zbx_vector_cq_value_sort(&prop_query_values, vmware_cq_instance_id_compare);
 
-	if (6 > service->major_version)
-		zbx_strlcpy(soapver, ZBX_XML_HEADER1_V4, sizeof(soapver));
-	else
-		zbx_strlcpy(soapver, ZBX_XML_HEADER1_V6, sizeof(soapver));
-
 	if (NULL == (easyhandle = curl_easy_init()))
 	{
 		zabbix_log(LOG_LEVEL_WARNING, "Cannot initialize cURL library");
@@ -7802,15 +8570,9 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 
 	page.alloc = ZBX_INIT_UPD_XML_SIZE;
 	page.data = (char *)zbx_malloc(NULL, page.alloc);
-	headers = curl_slist_append(headers, soapver);
-	headers = curl_slist_append(headers, ZBX_XML_HEADER2);
-	headers = curl_slist_append(headers, ZBX_XML_HEADER3);
 
-	if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPHEADER, headers)))
-	{
-		zabbix_log(LOG_LEVEL_WARNING, "Cannot set cURL option %d: %s.", (int)opt, curl_easy_strerror(err));
+	if (SUCCEED != vmware_curl_set_header(easyhandle, service->major_version, &headers, &data->error))
 		goto clean;
-	}
 
 	if (SUCCEED != vmware_service_authenticate(service, easyhandle, &page, &data->error))
 		goto clean;
@@ -7818,6 +8580,10 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 	if (SUCCEED != vmware_service_initialize(service, easyhandle, &data->error))
 		goto clean;
 
+	/* update headers after VC version detection */
+	if (SUCCEED != vmware_curl_set_header(easyhandle, service->major_version, &headers, &data->error))
+		goto clean;
+
 	if (NULL != service->data && 0 != service->data->events.values_num && 0 == evt_skip_old &&
 			((const zbx_vmware_event_t *)service->data->events.values[0])->key > evt_last_key)
 	{
@@ -7830,13 +8596,6 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 		goto clean;
 	}
 
-	if (ZBX_VMWARE_TYPE_VCENTER == service->type &&
-			SUCCEED != vmware_service_get_clusters_and_resourcepools(service, easyhandle,
-			&prop_query_values, &data->clusters, &data->resourcepools, &alarms_data, &data->error))
-	{
-		goto clean;
-	}
-
 	zbx_vector_vmware_datastore_reserve(&data->datastores, (size_t)(dss.values_num + data->datastores.values_alloc));
 
 	for (i = 0; i < dss.values_num; i++)
@@ -7852,6 +8611,13 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 
 	zbx_vector_vmware_datastore_sort(&data->datastores, vmware_ds_id_compare);
 
+	if (ZBX_VMWARE_TYPE_VCENTER == service->type &&
+			SUCCEED != vmware_service_get_clusters_and_resourcepools(service, easyhandle, &data->datastores,
+			&prop_query_values, &data->clusters, &data->resourcepools, &alarms_data, &data->error))
+	{
+		goto clean;
+	}
+
 	if (SUCCEED != zbx_hashset_reserve(&data->hvs, hvs.values_num))
 	{
 		THIS_SHOULD_NEVER_HAPPEN;
@@ -7893,7 +8659,8 @@ int	zbx_vmware_service_update(zbx_vmware_service_t *service)
 	zbx_vector_vmware_datastore_sort(&data->datastores, vmware_ds_uuid_compare);
 
 	vmware_service_dvswitch_load(easyhandle, &dvs_query_values);
-	vmware_service_props_load(easyhandle, &prop_query_values);
+	vmware_service_props_load(easyhandle, vmware_service_objects[service->type].property_collector,
+			&prop_query_values);
 	zbx_vector_vmware_alarm_sort(&data->alarms, ZBX_DEFAULT_STR_PTR_COMPARE_FUNC);
 
 	if (0 == service->eventlog.req_sz && 0 == evt_pause)
@@ -8189,7 +8956,7 @@ static void	vmware_service_parse_perf_data(zbx_vector_ptr_t *perfdata, xmlDoc *x
 
 	for (i = 0; i < nodeset->nodeNr; i++)
 	{
-		zbx_vmware_perf_data_t 	*data;
+		zbx_vmware_perf_data_t	*data;
 		int			ret = FAIL;
 
 		data = (zbx_vmware_perf_data_t *)zbx_malloc(NULL, sizeof(zbx_vmware_perf_data_t));
@@ -8352,7 +9119,7 @@ static void	vmware_service_retrieve_perf_counters(zbx_vmware_service_t *service,
 				char	st_str[ZBX_XML_DATETIME];
 
 				/* add startTime for entity performance counter request for decrease XML data load */
-				st_raw = zbx_time() - SEC_PER_HOUR;
+				st_raw = time(NULL) - SEC_PER_HOUR;
 				gmtime_r(&st_raw, &st);
 				strftime(st_str, sizeof(st_str), "%Y-%m-%dT%TZ", &st);
 				zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset, "<ns0:startTime>%s</ns0:startTime>",
@@ -8367,10 +9134,17 @@ static void	vmware_service_retrieve_perf_counters(zbx_vmware_service_t *service,
 
 				counter = (zbx_vmware_perf_counter_t *)entity->counters.values[j];
 
+				if (0 != (counter->state & ZBX_VMWARE_COUNTER_CUSTOM) &&
+						0 == (counter->state & ZBX_VMWARE_COUNTER_ACCEPTABLE))
+				{
+					continue;
+				}
+
 				zbx_snprintf_alloc(&tmp, &tmp_alloc, &tmp_offset,
 						"<ns0:metricId><ns0:counterId>" ZBX_FS_UI64
 						"</ns0:counterId><ns0:instance>%s</ns0:instance></ns0:metricId>",
-						counter->counterid, entity->query_instance);
+						counter->counterid, NULL == counter->query_instance ?
+						entity->query_instance : counter->query_instance);
 
 				counter->state |= ZBX_VMWARE_COUNTER_UPDATING;
 
@@ -8428,6 +9202,213 @@ static void	vmware_service_retrieve_perf_counters(zbx_vmware_service_t *service,
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Purpose: remove unused performance counters                                *
+ *                                                                            *
+ * Parameters: counters - [IN] the list of perf counters                      *
+ *                                                                            *
+ * Return value: SUCCEED - the performance entity is empty (can be deleted)   *
+ *               FAIL    - otherwise                                          *
+ *                                                                            *
+ ******************************************************************************/
+static int	vmware_perf_counters_expired_remove(zbx_vector_ptr_t *counters)
+{
+	int	i;
+	time_t	now = time(NULL);
+
+	for (i = counters->values_num - 1; i >= 0 ; i--)
+	{
+		zbx_vmware_perf_counter_t	*counter = (zbx_vmware_perf_counter_t *)counters->values[i];
+
+		if (0 == (counter->state & ZBX_VMWARE_COUNTER_CUSTOM))
+			continue;
+
+		if (0 == counter->last_used ||
+				(0 != (counter->state & ZBX_VMWARE_COUNTER_NOTSUPPORTED) &&
+				now - SEC_PER_HOUR * 2 < counter->last_used) ||
+				(0 == (counter->state & ZBX_VMWARE_COUNTER_NOTSUPPORTED) &&
+				now - SEC_PER_DAY < counter->last_used))
+		{
+			continue;
+		}
+
+		vmware_perf_counter_shared_free(counter);
+		zbx_vector_ptr_remove(counters, i);
+	}
+
+	return 0 == counters->values_num ? SUCCEED : FAIL;
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: update cache with lists of available perf counter for entity      *
+ *                                                                            *
+ * Parameters: service        - [IN] the vmware service                       *
+ *             easyhandle     - [IN] prepared cURL connection handle          *
+ *             type           - [IN] vmware object type (vm, hv etc)          *
+ *             id             - [IN] vmware object id (vm, hv etc)            *
+ *             refresh        - [IN] vmware refresh interval for perf counter *
+ *             begin_time     - [IN] vmware begin time for perf counters list *
+ *             perf_available - [IN/OUT] list of available counter per object *
+ *             perf           - [IN/OUT] the list of perf entities            *
+ *             error          - [OUT] the error message in the case of failure*
+ *                                                                            *
+ * Return value: SUCCEED - the operation has completed successfully           *
+ *               FAIL    - the operation has failed                           *
+ ******************************************************************************/
+static int	vmware_perf_available_update(zbx_vmware_service_t *service, CURL *easyhandle, const char *type,
+		const char *id, const int refresh, const char *begin_time, zbx_vector_perf_available_t *perf_available,
+		zbx_vmware_perf_available_t **perf, char **error)
+{
+#	define ZBX_POST_VMWARE_GET_AVAIL_PERF							\
+		ZBX_POST_VSPHERE_HEADER								\
+		"<ns0:QueryAvailablePerfMetric>"						\
+			"<ns0:_this type=\"PerformanceManager\">%s</ns0:_this>"			\
+			"<ns0:entity type=\"%s\">%s</ns0:entity>"				\
+			"<ns0:beginTime>%s</ns0:beginTime>"					\
+			"%s"									\
+		"</ns0:QueryAvailablePerfMetric>"						\
+		ZBX_POST_VSPHERE_FOOTER
+
+	int			i, ret;
+	char			tmp[MAX_STRING_LEN], interval[MAX_STRING_LEN / 32];
+	xmlDoc			*doc = NULL;
+	zbx_vector_str_t	counters;
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s begin_time:%s interval:%d", __func__, type, id,
+			begin_time, refresh);
+
+	zbx_vector_str_create(&counters);
+
+	if (ZBX_VMWARE_PERF_INTERVAL_NONE == refresh)
+		*interval = '\0';
+	else
+		zbx_snprintf(interval, sizeof(interval), "<ns0:intervalId>%d</ns0:intervalId>", refresh);
+
+	zbx_snprintf(tmp, sizeof(tmp), ZBX_POST_VMWARE_GET_AVAIL_PERF,
+			vmware_service_objects[service->type].performance_manager, type, id, begin_time, interval);
+
+	if (SUCCEED != (ret = zbx_soap_post(__func__, easyhandle, tmp, &doc, NULL, error)))
+		goto out;
+
+	if (FAIL == zbx_xml_read_values(doc, "/" ZBX_XPATH_LN2("returnval", "counterId"), &counters))
+	{
+		zabbix_log(LOG_LEVEL_DEBUG, "%s() empty list for type:%s id:%s interval:%d begin time:%s", __func__,
+				type, id, refresh, begin_time);
+	}
+
+	*perf = (zbx_vmware_perf_available_t *)zbx_malloc(NULL, sizeof(zbx_vmware_perf_available_t));
+	(*perf)->type = zbx_strdup(NULL, type);
+	(*perf)->id = zbx_strdup(NULL, id);
+	zbx_vector_uint16_create(&(*perf)->list);
+
+	for (i = 0; i < counters.values_num; i++)
+	{
+		zbx_vector_uint16_append(&(*perf)->list, (uint16_t)atoi(counters.values[i]));
+	}
+
+	zbx_vector_uint16_sort(&(*perf)->list, vmware_uint16_compare);
+	zbx_vector_uint16_uniq(&(*perf)->list, vmware_uint16_compare);
+	zbx_vector_perf_available_append(perf_available, *perf);
+	zbx_vector_perf_available_sort(perf_available, vmware_perf_available_compare);
+out:
+	zbx_vector_str_clear_ext(&counters, zbx_str_free);
+	zbx_vector_str_destroy(&counters);
+	zbx_xml_free_doc(doc);
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+
+	return ret;
+
+#	undef ZBX_POST_VMWARE_GET_AVAIL_PERF
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: setting flag ZBX_VMWARE_COUNTER_ACCEPTABLE for new perf counters  *
+ *                                                                            *
+ * Parameters: service        - [IN] the vmware service                       *
+ *             easyhandle     - [IN] prepared cURL connection handle          *
+ *             perf_available - [IN/OUT] list of available counter per object *
+ *             entities       - [IN/OUT] the list of perf entities            *
+ *                                                                            *
+ ******************************************************************************/
+static void	vmware_perf_counters_availability_check(zbx_vmware_service_t *service, CURL *easyhandle,
+		zbx_vector_perf_available_t *perf_available, zbx_vector_ptr_t *entities)
+{
+	int	i;
+	char	begin_time[ZBX_XML_DATETIME];
+
+	zabbix_log(LOG_LEVEL_DEBUG, "In %s() entities:%d perf_available:%d", __func__,
+			entities->values_num, perf_available->values_num);
+
+	*begin_time = '\0';
+
+	for (i = 0; i < entities->values_num ; i++)
+	{
+		int				j;
+		zbx_vmware_perf_entity_t	*entity;
+
+		entity = (zbx_vmware_perf_entity_t *)entities->values[i];
+
+		for (j = 0; j < entity->counters.values_num; j++)
+		{
+			int				k;
+			char				*err = NULL;
+			zbx_vmware_perf_counter_t	*counter;
+			zbx_vmware_perf_available_t	*perf, perf_cmp = {.type = entity->type, .id = entity->id};
+
+			counter = (zbx_vmware_perf_counter_t *)entity->counters.values[j];
+
+			if (0 == (counter->state & ZBX_VMWARE_COUNTER_CUSTOM) ||
+					0 != (counter->state & ZBX_VMWARE_COUNTER_ACCEPTABLE))
+			{
+				continue;
+			}
+
+			if ('\0' == *begin_time)
+			{
+				time_t		st_raw;
+				struct	tm	st;
+
+				st_raw = time(NULL) - SEC_PER_HOUR;
+				gmtime_r(&st_raw, &st);
+				strftime(begin_time, sizeof(begin_time), "%Y-%m-%dT%TZ", &st);
+			}
+
+			if (FAIL != (k = zbx_vector_perf_available_bsearch(
+					perf_available, &perf_cmp, vmware_perf_available_compare)))
+			{
+				perf = perf_available->values[k];
+			}
+			else if (FAIL == vmware_perf_available_update(service, easyhandle, entity->type,
+					entity->id, entity->refresh, begin_time, perf_available, &perf, &err))
+			{
+				zabbix_log(LOG_LEVEL_WARNING, "%s() cache update error: %s", __func__, err);
+				zbx_str_free(err);
+				return;
+			}
+
+			if (FAIL == zbx_vector_uint16_bsearch(&perf->list, (uint16_t)counter->counterid,
+					vmware_uint16_compare))
+			{
+				counter->state |= ZBX_VMWARE_COUNTER_NOTSUPPORTED;
+			}
+			else
+			{
+				counter->state |= ZBX_VMWARE_COUNTER_ACCEPTABLE;
+			}
+
+			zabbix_log(LOG_LEVEL_DEBUG, "%s() type:%s id:%s counterid:" ZBX_FS_UI64 " state:%X %s",
+					__func__, entity->type, entity->id, counter->counterid, counter->state,
+					0 == (counter->state & ZBX_VMWARE_COUNTER_ACCEPTABLE) ?
+					"NOTSUPPORTED" : "ACCEPTABLE");
+		}
+	}
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: updates vmware statistics data                                    *
@@ -8449,6 +9430,7 @@ int	zbx_vmware_service_update_perf(zbx_vmware_service_t *service)
 	zbx_vmware_perf_entity_t	*entity;
 	zbx_hashset_iter_t		iter;
 	zbx_vector_ptr_t		perfdata;
+	zbx_vector_perf_available_t	perf_available;
 	static ZBX_HTTPPAGE		page;	/* 173K */
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() '%s'@'%s'", __func__, service->username, service->url);
@@ -8456,6 +9438,7 @@ int	zbx_vmware_service_update_perf(zbx_vmware_service_t *service)
 	zbx_vector_ptr_create(&entities);
 	zbx_vector_ptr_create(&hist_entities);
 	zbx_vector_ptr_create(&perfdata);
+	zbx_vector_perf_available_create(&perf_available);
 	page.alloc = 0;
 
 	if (NULL == (easyhandle = curl_easy_init()))
@@ -8487,7 +9470,8 @@ int	zbx_vmware_service_update_perf(zbx_vmware_service_t *service)
 	while (NULL != (entity = (zbx_vmware_perf_entity_t *)zbx_hashset_iter_next(&iter)))
 	{
 		/* remove old entities */
-		if (0 != entity->last_seen && entity->last_seen < service->lastcheck)
+		if ((0 != entity->last_seen && entity->last_seen < service->lastcheck) ||
+				SUCCEED == vmware_perf_counters_expired_remove(&entity->counters))
 		{
 			vmware_shared_perf_entity_clean(entity);
 			zbx_hashset_iter_remove(&iter);
@@ -8524,6 +9508,34 @@ int	zbx_vmware_service_update_perf(zbx_vmware_service_t *service)
 
 	zbx_vmware_lock();
 
+	/* checking the availability of custom performance counters */
+	zbx_hashset_iter_reset(&service->entities, &iter);
+	while (NULL != (entity = (zbx_vmware_perf_entity_t *)zbx_hashset_iter_next(&iter)))
+	{
+		for (i = 0; i < entity->counters.values_num; i++)
+		{
+			zbx_vmware_perf_counter_t	*counter;
+
+			counter = (zbx_vmware_perf_counter_t *)entity->counters.values[i];
+
+			if (0 == (counter->state & ZBX_VMWARE_COUNTER_CUSTOM) || 0 != (counter->state &
+					(ZBX_VMWARE_COUNTER_ACCEPTABLE | ZBX_VMWARE_COUNTER_NOTSUPPORTED)))
+			{
+				continue;
+			}
+
+			zbx_vector_ptr_append(&entities, entity);
+			break;
+		}
+	}
+
+	zbx_vmware_unlock();
+
+	vmware_perf_counters_availability_check(service, easyhandle, &perf_available, &entities);
+	zbx_vector_ptr_clear(&entities);
+
+	zbx_vmware_lock();
+
 	zbx_hashset_iter_reset(&service->entities, &iter);
 	while (NULL != (entity = (zbx_vmware_perf_entity_t *)zbx_hashset_iter_next(&iter)))
 	{
@@ -8534,6 +9546,30 @@ int	zbx_vmware_service_update_perf(zbx_vmware_service_t *service)
 			continue;
 		}
 
+		/* pre-check acceptable counters */
+		for (i = 0; i < entity->counters.values_num; i++)
+		{
+			zbx_vmware_perf_counter_t	*counter;
+
+			counter = (zbx_vmware_perf_counter_t *)entity->counters.values[i];
+
+			if (0 != (counter->state & ZBX_VMWARE_COUNTER_CUSTOM) &&
+					0 == (counter->state & ZBX_VMWARE_COUNTER_ACCEPTABLE))
+			{
+				continue;
+			}
+
+			break;
+		}
+
+		if (i == entity->counters.values_num)
+		{
+			zabbix_log(LOG_LEVEL_DEBUG, "skipping performance entity with type:%s id:%s: "
+					"unsupported counters", entity->type, entity->id);
+			continue;
+		}
+
+
 		if (ZBX_VMWARE_PERF_INTERVAL_NONE == entity->refresh)
 			zbx_vector_ptr_append(&hist_entities, entity);
 		else
@@ -8577,6 +9613,9 @@ out:
 
 	zbx_vmware_unlock();
 
+	zbx_vector_perf_available_clear_ext(&perf_available, vmware_perf_available_free);
+	zbx_vector_perf_available_destroy(&perf_available);
+
 	zbx_vector_ptr_clear_ext(&perfdata, (zbx_mem_free_func_t)vmware_free_perfdata);
 	zbx_vector_ptr_destroy(&perfdata);
 
@@ -8770,7 +9809,8 @@ int	zbx_vmware_service_add_perf_counter(zbx_vmware_service_t *service, const cha
 		zbx_uint64_t counterid, const char *instance)
 {
 	zbx_vmware_perf_entity_t	*pentity, entity;
-	int				ret = FAIL;
+	zbx_vmware_perf_counter_t	*counter;
+	int				i, ret = FAIL;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() type:%s id:%s counterid:" ZBX_FS_UI64, __func__, type, id,
 			counterid);
@@ -8789,15 +9829,23 @@ int	zbx_vmware_service_add_perf_counter(zbx_vmware_service_t *service, const cha
 				sizeof(zbx_vmware_perf_entity_t));
 	}
 
-	if (FAIL == zbx_vector_ptr_search(&pentity->counters, &counterid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC))
+	if (FAIL == (i = zbx_vector_ptr_search(&pentity->counters, &counterid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
 	{
-		vmware_counters_add_new(&pentity->counters, counterid);
+		vmware_counters_add_new(&pentity->counters, counterid,
+				ZBX_VMWARE_COUNTER_NEW | ZBX_VMWARE_COUNTER_CUSTOM);
+		counter = (zbx_vmware_perf_counter_t *)pentity->counters.values[pentity->counters.values_num - 1];
 		zbx_vector_ptr_sort(&pentity->counters, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
 
 		ret = SUCCEED;
 	}
+	else
+		counter = (zbx_vmware_perf_counter_t *)pentity->counters.values[i];
 
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
+	if (*ZBX_VMWARE_PERF_QUERY_ALL != *pentity->query_instance)
+		counter->query_instance = vmware_shared_strdup(instance);
+
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s counter state:%X", __func__, zbx_result_string(ret),
+			counter->state);
 
 	return ret;
 }
diff --git a/src/zabbix_server/vmware/vmware.h b/src/zabbix_server/vmware/vmware.h
index 8a7962c6c99..27be194146e 100644
--- a/src/zabbix_server/vmware/vmware.h
+++ b/src/zabbix_server/vmware/vmware.h
@@ -31,11 +31,6 @@
 
 #define ZBX_VMWARE_STATE_MASK		0x0FF
 
-/* the vmware performance counter state */
-#define ZBX_VMWARE_COUNTER_NEW		0x00
-#define ZBX_VMWARE_COUNTER_READY	0x01
-#define ZBX_VMWARE_COUNTER_UPDATING	0x10
-
 #define ZBX_VMWARE_EVENT_KEY_UNINITIALIZED	__UINT64_C(0xffffffffffffffff)
 
 typedef struct
@@ -48,6 +43,8 @@ zbx_str_uint64_pair_t;
 ZBX_PTR_VECTOR_DECL(str_uint64_pair, zbx_str_uint64_pair_t)
 int	zbx_str_uint64_pair_name_compare(const void *p1, const void *p2);
 
+#define UC(v)	((unsigned char)v)
+
 /* performance counter data */
 typedef struct
 {
@@ -59,8 +56,22 @@ typedef struct
 	/*    pair->value - value                   */
 	zbx_vector_str_uint64_pair_t	values;
 
-	/* the counter state, see ZBX_VMAWRE_COUNTER_* defines */
+#define ZBX_VMWARE_COUNTER_NEW		UC(0x00)
+#define ZBX_VMWARE_COUNTER_READY	UC(0x01)
+#define ZBX_VMWARE_COUNTER_UPDATING	UC(0x02)
+#define ZBX_VMWARE_COUNTER_CUSTOM	UC(0x10)
+#define ZBX_VMWARE_COUNTER_ACCEPTABLE	UC(0x20)
+#define ZBX_VMWARE_COUNTER_NOTSUPPORTED	UC(0x40)
+
+#define ZBX_VMWARE_COUNTER_STATE_MASK	0xF0
+	/* the vmware performance counter state */
 	unsigned char			state;
+
+	/* time of last attempt of poller to use data */
+	time_t				last_used;
+
+	/* alternate query instance (for the case when 'entity' query is TOTAL) */
+	char				*query_instance;
 }
 zbx_vmware_perf_counter_t;
 
@@ -73,15 +84,19 @@ typedef struct
 	/* entity id */
 	char			*id;
 
+#define ZBX_VMWARE_PERF_INTERVAL_UNKNOWN	0
+#define ZBX_VMWARE_PERF_INTERVAL_NONE		-1
 	/* the performance counter refresh rate */
 	int			refresh;
 
 	/* timestamp when the entity was queried last time */
-	int			last_seen;
+	time_t			last_seen;
 
 	/* the performance counters to monitor */
 	zbx_vector_ptr_t	counters;
 
+#define ZBX_VMWARE_PERF_QUERY_ALL		"*"
+#define ZBX_VMWARE_PERF_QUERY_TOTAL		""
 	/* the performance counter query instance name */
 	char			*query_instance;
 
@@ -92,8 +107,34 @@ zbx_vmware_perf_entity_t;
 
 typedef struct
 {
-	zbx_uint64_t	partitionid;
+	char		*ssd;
+	char		*local_disk;
+	unsigned int	block_size;
+	unsigned int	block;
+}
+zbx_vmware_vsandiskinfo_t;
+
+typedef struct
+{
+	char				*diskname;
+	char				*ds_uuid;
+	char				*operational_state;
+	char				*lun_type;
+	int				queue_depth;
+	char				*model;
+	char				*vendor;
+	char				*revision;
+	char				*serial_number;
+	zbx_vmware_vsandiskinfo_t	*vsan;
+}
+zbx_vmware_diskinfo_t;
+
+ZBX_PTR_VECTOR_DECL(vmware_diskinfo, zbx_vmware_diskinfo_t *)
+
+typedef struct
+{
 	char		*diskname;
+	zbx_uint64_t	partitionid;
 }
 zbx_vmware_diskextent_t;
 
@@ -113,6 +154,7 @@ typedef struct
 	char				*uuid;
 	char				*name;
 	char				*id;
+	char				*type;
 	zbx_uint64_t			capacity;
 	zbx_uint64_t			free_space;
 	zbx_uint64_t			uncommitted;
@@ -266,6 +308,7 @@ typedef struct
 	zbx_vector_ptr_t		vms;
 	zbx_vector_vmware_pnic_t	pnics;
 	zbx_vector_str_t		alarm_ids;
+	zbx_vector_vmware_diskinfo_t	diskinfo;
 }
 zbx_vmware_hv_t;
 
@@ -283,6 +326,7 @@ typedef struct
 	char			*id;
 	char			*name;
 	char			*status;
+	zbx_vector_str_t	dss_uuid;
 	zbx_vector_str_t	alarm_ids;
 }
 zbx_vmware_cluster_t;
@@ -381,11 +425,11 @@ typedef struct
 	/* the result of query */
 	char				*value;
 
-#define ZBX_VMWARE_CQ_NEW	0
-#define ZBX_VMWARE_CQ_READY	1
-#define ZBX_VMWARE_CQ_ERROR	2
-#define ZBX_VMWARE_CQ_PAUSED	4
-#define ZBX_VMWARE_CQ_SEPARATE	8
+#define ZBX_VMWARE_CQ_NEW		UC(0x01)
+#define ZBX_VMWARE_CQ_READY		UC(0x02)
+#define ZBX_VMWARE_CQ_ERROR		UC(0x04)
+#define ZBX_VMWARE_CQ_PAUSED		UC(0x08)
+#define ZBX_VMWARE_CQ_SEPARATE		UC(0x10)
 	/* the state of query */
 	unsigned char			state;
 
@@ -443,10 +487,10 @@ typedef struct
 	/* the service state - see ZBX_VMWARE_STATE_* defines */
 	int				state;
 
-	int				lastcheck;
+	time_t				lastcheck;
 
 	/* The last vmware service access time. If a service is not accessed for a day it is removed */
-	int				lastaccess;
+	time_t				lastaccess;
 
 	/* the vmware service instance version */
 	char				*version;
@@ -454,6 +498,7 @@ typedef struct
 	/* the vmware service instance version numeric */
 	unsigned short			major_version;
 	unsigned short			minor_version;
+	unsigned short			patch_version;
 
 	/* the vmware service instance fullname */
 	char				*fullname;
@@ -481,9 +526,6 @@ typedef struct
 }
 zbx_vmware_service_t;
 
-#define ZBX_VMWARE_PERF_INTERVAL_UNKNOWN	0
-#define ZBX_VMWARE_PERF_INTERVAL_NONE		-1
-
 /* the vmware collector data */
 typedef struct
 {
@@ -496,7 +538,7 @@ zbx_vmware_t;
 
 typedef struct
 {
-	int			nextcheck;
+	time_t			nextcheck;
 #define ZBX_VMWARE_UPDATE_CONF		1
 #define ZBX_VMWARE_UPDATE_PERFCOUNTERS	2
 #define ZBX_VMWARE_UPDATE_REST_TAGS	3
@@ -546,7 +588,7 @@ int	zbx_vmware_service_add_perf_counter(zbx_vmware_service_t *service, const cha
 zbx_vmware_perf_entity_t	*zbx_vmware_service_get_perf_entity(zbx_vmware_service_t *service, const char *type,
 		const char *id);
 
-zbx_vmware_cust_query_t *zbx_vmware_service_add_cust_query(zbx_vmware_service_t *service, const char *type,
+zbx_vmware_cust_query_t *zbx_vmware_service_add_cust_query(zbx_vmware_service_t *service, const char *soap_type,
 		const char *id, const char *key, zbx_vmware_custom_query_type_t query_type, const char *mode,
 		zbx_vector_custquery_param_t *query_params);
 zbx_vmware_cust_query_t	*zbx_vmware_service_get_cust_query(zbx_vmware_service_t *service, const char *type,
diff --git a/src/zabbix_server/vmware/vmware_manager.c b/src/zabbix_server/vmware/vmware_manager.c
index 0c93112a2ca..f4c9fd6a910 100644
--- a/src/zabbix_server/vmware/vmware_manager.c
+++ b/src/zabbix_server/vmware/vmware_manager.c
@@ -69,7 +69,7 @@ static const char	*vmware_job_type_string(zbx_vmware_job_t *job)
  * Return value: job for object or NULL                                       *
  *                                                                            *
  ******************************************************************************/
-static zbx_vmware_job_t	*vmware_job_get(zbx_vmware_t *vmw, int time_now)
+static zbx_vmware_job_t	*vmware_job_get(zbx_vmware_t *vmw, time_t time_now)
 {
 	zbx_binary_heap_elem_t	*elem;
 	zbx_vmware_job_t	*job = NULL;
@@ -151,7 +151,7 @@ out:
  *             time_now - [IN] the current time                               *
  *                                                                            *
  ******************************************************************************/
-static void	vmware_job_schedule(zbx_vmware_t *vmw, zbx_vmware_job_t *job, int time_now)
+static void	vmware_job_schedule(zbx_vmware_t *vmw, zbx_vmware_job_t *job, time_t time_now)
 {
 	zbx_binary_heap_elem_t	elem_new = {0, job};
 
@@ -236,7 +236,7 @@ ZBX_THREAD_ENTRY(vmware_thread, args)
 			}
 
 			services_updated += vmware_job_exec(job);
-			vmware_job_schedule(vmware, job, (int)time_now);
+			vmware_job_schedule(vmware, job, (time_t)time_now);
 		}
 
 		if (zbx_time() - time_now <= JOB_TIMEOUT)
diff --git a/src/zabbix_server/vmware/vmware_rest.c b/src/zabbix_server/vmware/vmware_rest.c
index 48d97daa742..bec34f87224 100644
--- a/src/zabbix_server/vmware/vmware_rest.c
+++ b/src/zabbix_server/vmware/vmware_rest.c
@@ -411,9 +411,14 @@ static int	vmware_service_rest_authenticate(const zbx_vmware_service_t *service,
 		goto out;
 	}
 
-	if ('"' != page->data[0] && FAIL == vmware_rest_response_open(page->data, NULL, error))
+	if (0 == page->offset)
 	{
-		*error = zbx_dsprintf(*error, "Authentication fail, %s.", *error);
+		*error = zbx_strdup(*error, "Cannot authenticate, received empty response.");
+		goto out;
+	}
+	else if ('"' != page->data[0] && FAIL == vmware_rest_response_open(page->data, NULL, error))
+	{
+		*error = zbx_dsprintf(*error, "Cannot authenticate, %s.", *error);
 		goto out;
 	}
 
@@ -508,6 +513,8 @@ static int	vmware_http_request(const char *fn_parent, CURL *easyhandle, const ch
 		*error = zbx_strdup(*error, curl_easy_strerror(err));
 		return FAIL;
 	}
+	else if (0 == page->offset)
+		*page->data = '\0';
 
 	if (NULL != fn_parent)
 		zabbix_log(LOG_LEVEL_TRACE, "%s() REST response: %s", fn_parent, page->data);
@@ -783,9 +790,9 @@ int	zbx_vmware_service_update_tags(zbx_vmware_service_t *service)
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() vc version:%s", __func__, service->version);
 
-	if (65 > service->major_version * 10 + service->minor_version)
+	if (702 > service->major_version * 100 + service->minor_version * 10 + service->patch_version)
 	{
-		error = zbx_strdup(error, "Tags are supported since vmware version 6.5.");
+		error = zbx_strdup(error, "Tags are supported since vmware version 7.0.2");
 		goto out;
 	}
 
diff --git a/tests/libs/zbxcommon/Makefile.am b/tests/libs/zbxcommon/Makefile.am
index 280a9d6cc7a..113b999e0f6 100644
--- a/tests/libs/zbxcommon/Makefile.am
+++ b/tests/libs/zbxcommon/Makefile.am
@@ -29,7 +29,8 @@ SERVER_tests = \
 	zbx_get_report_nextcheck \
 	zbx_ltrim_utf8 \
 	zbx_rtrim_utf8 \
-	zbx_get_week_number
+	zbx_get_week_number \
+	zbx_iso8601_utc
 endif
 
 noinst_PROGRAMS = $(SERVER_tests)
@@ -538,5 +539,20 @@ zbx_get_week_number_LDFLAGS = @SERVER_LDFLAGS@
 
 zbx_get_week_number_CFLAGS = $(COMMON_COMPILER_FLAGS)
 
+# zbx_iso8601_utc
+
+zbx_iso8601_utc_SOURCES = \
+	zbx_iso8601_utc.c \
+	$(COMMON_SRC_FILES)
+
+zbx_iso8601_utc_LDADD = \
+	$(COMMON_LIB_FILES)
+
+zbx_iso8601_utc_LDADD += @SERVER_LIBS@
+
+zbx_iso8601_utc_LDFLAGS = @SERVER_LDFLAGS@
+
+zbx_iso8601_utc_CFLAGS = $(COMMON_COMPILER_FLAGS)
+
 
 endif
diff --git a/tests/libs/zbxcommon/zbx_iso8601_utc.c b/tests/libs/zbxcommon/zbx_iso8601_utc.c
new file mode 100644
index 00000000000..6afd306aea3
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_iso8601_utc.c
@@ -0,0 +1,52 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2022 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "zbxmocktest.h"
+#include "zbxmockdata.h"
+#include "zbxmockassert.h"
+#include "zbxmockutil.h"
+#include <stdlib.h>
+
+void	zbx_mock_test_entry(void **state)
+{
+	const char	*param;
+	int		expected_ret, returned_ret;
+	time_t		ut;
+
+	ZBX_UNUSED(state);
+
+	param = zbx_mock_get_parameter_string("in.param");
+
+	expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return"));
+	returned_ret = zbx_iso8601_utc(param, &ut);
+
+	zbx_mock_assert_result_eq("zbx_iso8601_datetime()", expected_ret, returned_ret);
+
+	if (SUCCEED == returned_ret)
+	{
+		zbx_timespec_t	dt;
+		time_t		t_out;
+
+		if (ZBX_MOCK_SUCCESS != zbx_strtime_to_timespec(zbx_mock_get_parameter_string("out.datetime"), &dt))
+			fail_msg("Invalid date time format");
+
+		t_out = dt.sec;
+		zbx_mock_assert_time_eq("zbx_iso8601_datetime() incorrect parsing:", t_out, ut);
+	}
+}
diff --git a/tests/libs/zbxcommon/zbx_iso8601_utc.yaml b/tests/libs/zbxcommon/zbx_iso8601_utc.yaml
new file mode 100644
index 00000000000..3de01c960fa
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_iso8601_utc.yaml
@@ -0,0 +1,222 @@
+---
+test case: Invalid value ''
+in:
+  param: 
+out:
+  return: FAIL
+---
+test case: Invalid value 'xxx'
+in:
+  param: xxx
+out:
+  return: FAIL
+---
+test case: Invalid value '123'
+in:
+  param: 123
+out:
+  return: FAIL
+---
+test case: Invalid value '2022x09-12T14:46:15'
+in:
+  param: 2022x09-12T14:46:15
+out:
+  return: FAIL
+---
+test case: Invalid value '2022-09x12T14:46:15'
+in:
+  param: 2022-09x12T14:46:15
+out:
+  return: FAIL
+---
+test case: Invalid value '2022-09-12x14:46:15'
+in:
+  param: 2022-09-12x14:46:15
+out:
+  return: FAIL
+---
+test case: Invalid value '2022-09-12T14x46:15'
+in:
+  param: 2022-09-12T14x46:15
+out:
+  return: FAIL
+---
+test case: Invalid value '2022-09-12T14:46x15'
+in:
+  param: 2022-09-12T14:46x15
+out:
+  return: FAIL
+
+
+---
+test case: Valid yyyy-mm-ddThh:mm:ss
+in:
+  param: 2022-09-12T14:46:15
+out:
+  datetime: 2022-09-12 14:46:15
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ssZ
+in:
+  param: 2022-09-12T14:46:15Z
+out:
+  datetime: 2022-09-12 14:46:15Z
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss+hh:mm
+in:
+  param: 2022-09-12T14:46:15+04:00
+out:
+  datetime: 2022-09-12 14:46:15 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss-hh:mm
+in:
+  param: 2022-09-12T14:46:15-04:00
+out:
+  datetime: 2022-09-12 14:46:15 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss +hh:mm
+in:
+  param: 2022-09-12T14:46:15 +04:00
+out:
+  datetime: 2022-09-12 14:46:15 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss -hh:mm
+in:
+  param: 2022-09-12T14:46:15 -04:00
+out:
+  datetime: 2022-09-12 14:46:15 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.ccc
+in:
+  param: 2022-09-12T14:46:15.123
+out:
+  datetime: 2022-09-12 14:46:15.123
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.cccZ
+in:
+  param: 2022-09-12T14:46:15.123Z
+out:
+  datetime: 2022-09-12 14:46:15.123Z
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.ccc+hh:mm
+in:
+  param: 2022-09-12T14:46:15.123+04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.ccc-hh:mm
+in:
+  param: 2022-09-12T14:46:15.123-04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.ccc +hh:mm
+in:
+  param: 2022-09-12T14:46:15.123 +04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-ddThh:mm:ss.ccc -hh:mm
+in:
+  param: 2022-09-12T14:46:15.123 -04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 -04:00
+  return: SUCCEED
+
+
+
+---
+test case: Valid yyyy-mm-dd hh:mm:ss
+in:
+  param: 2022-09-12 14:46:15
+out:
+  datetime: 2022-09-12 14:46:15
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ssZ
+in:
+  param: 2022-09-12 14:46:15Z
+out:
+  datetime: 2022-09-12 14:46:15Z
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss+hh:mm
+in:
+  param: 2022-09-12 14:46:15+04:00
+out:
+  datetime: 2022-09-12 14:46:15 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss-hh:mm
+in:
+  param: 2022-09-12 14:46:15-04:00
+out:
+  datetime: 2022-09-12 14:46:15 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss +hh:mm
+in:
+  param: 2022-09-12 14:46:15 +04:00
+out:
+  datetime: 2022-09-12 14:46:15 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss -hh:mm
+in:
+  param: 2022-09-12 14:46:15 -04:00
+out:
+  datetime: 2022-09-12 14:46:15 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.ccc
+in:
+  param: 2022-09-12 14:46:15.123
+out:
+  datetime: 2022-09-12 14:46:15.123
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.cccZ
+in:
+  param: 2022-09-12 14:46:15.123Z
+out:
+  datetime: 2022-09-12 14:46:15.123Z
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.ccc+hh:mm
+in:
+  param: 2022-09-12 14:46:15.123+04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.ccc-hh:mm
+in:
+  param: 2022-09-12 14:46:15.123-04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 -04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.ccc +hh:mm
+in:
+  param: 2022-09-12 14:46:15.123 +04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 +04:00
+  return: SUCCEED
+---
+test case: Valid yyyy-mm-dd hh:mm:ss.ccc -hh:mm
+in:
+  param: 2022-09-12 14:46:15.123 -04:00
+out:
+  datetime: 2022-09-12 14:46:15.123 -04:00
+  return: SUCCEED
+
diff --git a/ui/include/classes/data/CItemData.php b/ui/include/classes/data/CItemData.php
index 561ce8d7040..0931ef7486b 100644
--- a/ui/include/classes/data/CItemData.php
+++ b/ui/include/classes/data/CItemData.php
@@ -240,6 +240,7 @@ final class CItemData {
 			'vmware.datastore.alarms.get[<url>,<uuid>]',
 			'vmware.datastore.discovery[<url>]',
 			'vmware.datastore.hv.list[<url>,<datastore>]',
+			'vmware.datastore.perfcounter[<url>,<uuid>,<path>,<instance>]',
 			'vmware.datastore.property[<url>,<uuid>,<prop>]',
 			'vmware.datastore.read[<url>,<datastore>,<mode>]',
 			'vmware.datastore.size[<url>,<datastore>,<mode>]',
@@ -266,6 +267,7 @@ final class CItemData {
 			'vmware.hv.datastore.size[<url>,<uuid>,<datastore>,<mode>]',
 			'vmware.hv.datastore.write[<url>,<uuid>,<datastore>,<mode>]',
 			'vmware.hv.discovery[<url>]',
+			'vmware.hv.diskinfo.get[<url>,<uuid>]',
 			'vmware.hv.fullname[<url>,<uuid>]',
 			'vmware.hv.hw.cpu.freq[<url>,<uuid>]',
 			'vmware.hv.hw.cpu.model[<url>,<uuid>]',
@@ -1314,6 +1316,10 @@ final class CItemData {
 				'description' => _('VMware datastore hypervisors list, <url> - VMware service URL, <datastore> - datastore name'),
 				'value_type' => ITEM_VALUE_TYPE_TEXT
 			],
+			'vmware.datastore.perfcounter[<url>,<uuid>,<path>,<instance>]' => [
+				'description' => _('VMware datastore performance counter, <url> - VMware service URL, <id> - VMware datastore uuid, <path> - performance counter path, <instance> - performance counter instance'),
+				'value_type' => ITEM_VALUE_TYPE_FLOAT
+			],
 			'vmware.datastore.property[<url>,<uuid>,<prop>]' => [
 				'description' => _('VMware datastore property, <url> - VMware service URL, <uuid> - datastore name, <prop> - property path'),
 				'value_type' => ITEM_VALUE_TYPE_TEXT
@@ -1418,6 +1424,10 @@ final class CItemData {
 				'description' => _('Discovery of VMware hypervisors, <url> - VMware service URL. Returns JSON'),
 				'value_type' => ITEM_VALUE_TYPE_TEXT
 			],
+			'vmware.hv.diskinfo.get[<url>,<uuid>]' => [
+				'description' => _('Info about internal disks of hypervisor required for vmware.datastore.perfcounter, <url> - VMware service URL, <uuid> - VMware hypervisor host name. Returns JSON'),
+				'value_type' => ITEM_VALUE_TYPE_TEXT
+			],
 			'vmware.hv.fullname[<url>,<uuid>]' => [
 				'description' => _('VMware hypervisor name, <url> - VMware service URL, <uuid> - VMware hypervisor host name'),
 				'value_type' => ITEM_VALUE_TYPE_STR
@@ -1492,7 +1502,7 @@ final class CItemData {
 			],
 			'vmware.hv.perfcounter[<url>,<uuid>,<path>,<instance>]' => [
 				'description' => _('VMware hypervisor performance counter, <url> - VMware service URL, <uuid> - VMware hypervisor host name, <path> - performance counter path, <instance> - performance counter instance'),
-				'value_type' => null
+				'value_type' => ITEM_VALUE_TYPE_FLOAT
 			],
 			'vmware.hv.power[<url>,<uuid>,<max>]' => [
 				'description' => _('Power usage , <url> - VMware service URL, <uuid> - VMware hypervisor host name, <max> - Maximum allowed power usage'),
@@ -1664,7 +1674,7 @@ final class CItemData {
 			],
 			'vmware.vm.perfcounter[<url>,<uuid>,<path>,<instance>]' => [
 				'description' => _('VMware virtual machine performance counter, <url> - VMware service URL, <uuid> - VMware virtual machine host name, <path> - performance counter path, <instance> - performance counter instance'),
-				'value_type' => null
+				'value_type' => ITEM_VALUE_TYPE_FLOAT
 			],
 			'vmware.vm.powerstate[<url>,<uuid>]' => [
 				'description' => _('VMware virtual machine power state, <url> - VMware service URL, <uuid> - VMware virtual machine host name'),
