Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vSphere new implementation #5251

Merged
merged 23 commits into from
Feb 3, 2020
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use native type everywhere
  • Loading branch information
FlorianVeaux committed Jan 23, 2020
commit 7110cadb98673cdb44987fda0b09a486845b8674
3 changes: 1 addition & 2 deletions vsphere/datadog_checks/vsphere/api.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@
from pyVim import connect
from pyVmomi import vim, vmodl

from datadog_checks.base import ensure_unicode
from datadog_checks.vsphere.constants import ALL_RESOURCES, MAX_QUERY_METRICS_OPTION, UNLIMITED_HIST_METRICS_PER_QUERY

# Python 3 only
@@ -70,7 +69,7 @@ def smart_connect(self):
# Next line tries a simple API call to check the health of the connection.
conn.CurrentTime()
FlorianVeaux marked this conversation as resolved.
Show resolved Hide resolved
except Exception as e:
AlexandreYang marked this conversation as resolved.
Show resolved Hide resolved
err_msg = "Connection to {} failed: {}".format(ensure_unicode(self.config.hostname), e)
err_msg = "Connection to {} failed: {}".format(self.config.hostname, e)
raise APIConnectionError(err_msg)
FlorianVeaux marked this conversation as resolved.
Show resolved Hide resolved

self._conn = conn
10 changes: 5 additions & 5 deletions vsphere/datadog_checks/vsphere/config.py
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ def __init__(self, instance, log):
self.batch_collector_size = instance.get('batch_property_collector_size', DEFAULT_BATCH_COLLECTOR_SIZE)
self.should_collect_events = instance.get("collect_events", self.collection_type == 'realtime')
self.excluded_host_tags = instance.get("excluded_host_tags", [])
self.base_tags = instance.get("tags", []) + [u"vcenter_server:{}".format(self.hostname)]
self.base_tags = instance.get("tags", []) + ["vcenter_server:{}".format(self.hostname)]
self.refresh_infrastructure_cache_interval = instance.get(
'refresh_infrastructure_cache_interval', DEFAULT_REFRESH_INFRASTRUCTURE_CACHE_INTERVAL
)
@@ -111,7 +111,7 @@ def parse_resource_filters(self, all_resource_filters):

if resource_filter['resource'] not in allowed_resource_types:
self.log.warning(
u"Ignoring filter %r because resource %s is not collected when collection_type is %s.",
"Ignoring filter %r because resource %s is not collected when collection_type is %s.",
resource_filter,
resource_filter['resource'],
self.collection_type,
@@ -124,8 +124,8 @@ def parse_resource_filters(self, all_resource_filters):

if resource_filter['property'] not in allowed_prop_names:
self.log.warning(
u"Ignoring filter %r because property '%s' is not valid "
u"for resource type %s. Should be one of %r.",
"Ignoring filter %r because property '%s' is not valid "
"for resource type %s. Should be one of %r.",
resource_filter,
resource_filter['property'],
resource_filter['resource'],
@@ -136,7 +136,7 @@ def parse_resource_filters(self, all_resource_filters):
filter_key = (resource_filter['resource'], resource_filter['property'])
if filter_key in formatted_resource_filters:
self.log.warning(
u"Ignoring filter %r because you already have a filter for resource type %s and property %s.",
"Ignoring filter %r because you already have a filter for resource type %s and property %s.",
resource_filter,
resource_filter['resource'],
resource_filter['property'],
22 changes: 10 additions & 12 deletions vsphere/datadog_checks/vsphere/utils.py
Original file line number Diff line number Diff line change
@@ -3,15 +3,13 @@
# Licensed under Simplified BSD License (see LICENSE)
from pyVmomi import vim

from datadog_checks.base import ensure_unicode
from datadog_checks.vsphere.constants import MOR_TYPE_AS_STRING, SHORT_ROLLUP, REFERENCE_METRIC
from datadog_checks.base import to_string
from datadog_checks.vsphere.constants import MOR_TYPE_AS_STRING, REFERENCE_METRIC, SHORT_ROLLUP


def format_metric_name(counter):
return "{}.{}.{}".format(
ensure_unicode(counter.groupInfo.key),
ensure_unicode(counter.nameInfo.key),
ensure_unicode(SHORT_ROLLUP[str(counter.rollupType)]),
to_string(counter.groupInfo.key), to_string(counter.nameInfo.key), SHORT_ROLLUP[str(counter.rollupType)],
)


@@ -97,19 +95,19 @@ def get_parent_tags_recursively(mor, infrastructure_data):
if parent:
tags = []
parent_props = infrastructure_data.get(parent, {})
parent_name = ensure_unicode(parent_props.get('name', 'unknown'))
parent_name = to_string(parent_props.get('name', 'unknown'))
if isinstance(parent, vim.HostSystem):
tags.append(u'vsphere_host:{}'.format(parent_name))
tags.append('vsphere_host:{}'.format(parent_name))
elif isinstance(parent, vim.Folder):
tags.append(u'vsphere_folder:{}'.format(parent_name))
tags.append('vsphere_folder:{}'.format(parent_name))
elif isinstance(parent, vim.ComputeResource):
if isinstance(parent, vim.ClusterComputeResource):
tags.append(u'vsphere_cluster:{}'.format(parent_name))
tags.append(u'vsphere_compute:{}'.format(parent_name))
tags.append('vsphere_cluster:{}'.format(parent_name))
tags.append('vsphere_compute:{}'.format(parent_name))
elif isinstance(parent, vim.Datacenter):
tags.append(u'vsphere_datacenter:{}'.format(parent_name))
tags.append('vsphere_datacenter:{}'.format(parent_name))
elif isinstance(parent, vim.Datastore):
tags.append(u'vsphere_datastore:{}'.format(parent_name))
tags.append('vsphere_datastore:{}'.format(parent_name))

parent_tags = get_parent_tags_recursively(parent, infrastructure_data)
parent_tags.extend(tags)
22 changes: 11 additions & 11 deletions vsphere/datadog_checks/vsphere/vsphere.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
from pyVmomi import vim
from six import iteritems

from datadog_checks.base import AgentCheck, ensure_unicode, is_affirmative
from datadog_checks.base import AgentCheck, is_affirmative, to_string
from datadog_checks.base.checks.libs.timer import Timer
from datadog_checks.stubs import datadog_agent
from datadog_checks.vsphere.api import APIConnectionError, VSphereAPI
@@ -136,7 +136,7 @@ def refresh_infrastructure_cache(self):
# The resource does not match the specified patterns
continue

mor_name = ensure_unicode(properties.get("name", "unknown"))
mor_name = to_string(properties.get("name", "unknown"))
mor_type_str = MOR_TYPE_AS_STRING[type(mor)]
hostname = None
tags = []
@@ -146,15 +146,15 @@ def refresh_infrastructure_cache(self):
if power_state != vim.VirtualMachinePowerState.poweredOn:
# Skipping because the VM is not powered on
# TODO: Sometimes VM are "poweredOn" but "disconnected" and thus have no metrics
self.log.debug("Skipping VM %s in state %s", mor_name, ensure_unicode(power_state))
self.log.debug("Skipping VM %s in state %s", mor_name, to_string(power_state))
continue

# Hosts are not considered as parents of the VMs they run, we use the `runtime.host` property
# to get the name of the ESXi host
runtime_host = properties.get("runtime.host")
runtime_host_props = infrastructure_data.get(runtime_host, {})
runtime_hostname = ensure_unicode(runtime_host_props.get("name", "unknown"))
tags.append(u'vsphere_host:{}'.format(runtime_hostname))
runtime_hostname = to_string(runtime_host_props.get("name", "unknown"))
tags.append('vsphere_host:{}'.format(runtime_hostname))

if self.config.use_guest_hostname:
hostname = properties.get("guest.hostName", mor_name)
@@ -163,10 +163,10 @@ def refresh_infrastructure_cache(self):
elif isinstance(mor, vim.HostSystem):
hostname = mor_name
else:
tags.append(u'vsphere_{}:{}'.format(mor_type_str, mor_name))
tags.append('vsphere_{}:{}'.format(mor_type_str, mor_name))

tags.extend(get_parent_tags_recursively(mor, infrastructure_data))
tags.append(u'vsphere_type:{}'.format(mor_type_str))
tags.append('vsphere_type:{}'.format(mor_type_str))
mor_payload = {"tags": tags}
if hostname:
mor_payload['hostname'] = hostname
@@ -208,7 +208,7 @@ def submit_metrics_callback(self, task):
continue

if not result.value:
self.log.debug("Skipping metric %s because the value is empty", ensure_unicode(metric_name))
self.log.debug("Skipping metric %s because the value is empty", to_string(metric_name))
continue

# Get the most recent value that isn't negative
@@ -217,7 +217,7 @@ def submit_metrics_callback(self, task):
self.log.debug(
"Skipping metric %s because the value returned by vCenter"
" is negative (i.e. the metric is not yet available).",
ensure_unicode(metric_name),
to_string(metric_name),
)
continue
value = valid_values[-1]
@@ -237,7 +237,7 @@ def submit_metrics_callback(self, task):
hostname = None
else:
# Tags are (mostly) submitted as external host tags.
hostname = ensure_unicode(mor_props.get('hostname'))
hostname = to_string(mor_props.get('hostname'))
if self.config.excluded_host_tags:
tags.extend(
[t for t in mor_props['tags'] if t.split(":", 1)[0] in self.config.excluded_host_tags]
@@ -247,7 +247,7 @@ def submit_metrics_callback(self, task):

# vsphere "rates" should be submitted as gauges (rate is
# precomputed).
self.gauge(ensure_unicode(metric_name), value, hostname=hostname, tags=tags)
self.gauge(to_string(metric_name), value, hostname=hostname, tags=tags)

def query_metrics_wrapper(self, query_specs):
"""Just an instrumentation wrapper around the VSphereAPI.query_metrics method
4 changes: 3 additions & 1 deletion vsphere/tests/test_check.py
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
from tests.common import HERE
from tests.mocked_api import MockedAPI

from datadog_checks.base import to_string
from datadog_checks.vsphere import VSphereCheck
from datadog_checks.vsphere.config import VSphereConfig

@@ -62,6 +63,7 @@ def test_external_host_tags(aggregator, realtime_instance):
for ex, sub in zip(expected_tags, submitted_tags):
ex_host, sub_host = ex[0], sub[0]
ex_tags, sub_tags = ex[1]['vsphere'], sub[1]['vsphere']
ex_tags = [to_string(t) for t in ex_tags] # json library loads data in unicode, let's convert back to native
assert ex_host == sub_host
assert ex_tags == sub_tags

@@ -73,7 +75,7 @@ def test_external_host_tags(aggregator, realtime_instance):
for ex, sub in zip(expected_tags, submitted_tags):
ex_host, sub_host = ex[0], sub[0]
ex_tags, sub_tags = ex[1]['vsphere'], sub[1]['vsphere']
ex_tags = [t for t in ex_tags if 'vsphere_host:' not in t]
ex_tags = [to_string(t) for t in ex_tags if 'vsphere_host:' not in t]
assert ex_host == sub_host
assert ex_tags == sub_tags