diff options
author | Claudiu Belu <cbelu@cloudbasesolutions.com> | 2018-02-22 18:06:10 +0200 |
---|---|---|
committer | Claudiu Belu <cbelu@cloudbasesolutions.com> | 2018-02-22 18:11:49 +0200 |
commit | e2a3542fe8d5f562b590192dc34ece5eafa51931 (patch) | |
tree | 223dd6ff6d91e0ad5a2c3301bacc6d0167408196 /ceilometer/compute | |
parent | 01670dfcb47a78b8ee04f27203f027a31395d854 (diff) | |
download | ceilometer-e2a3542fe8d5f562b590192dc34ece5eafa51931.tar.gz |
hyper-v: Converts all os-win exceptions
When os-win was first introduced, a decorator which converts all os-win
exceptions to virt inspector exceptions has been added to the
HyperVInspector.
However, the decorator works as intended for methods that return values,
and not for the ones that yield (they return a generator).
This patch makes sure that exceptions are converted properly for yielding
methods as well.
Closes-Bug #1751088
Change-Id: I7d09e1860c6940758f0d0965fedfe4dd285e0cae
Diffstat (limited to 'ceilometer/compute')
-rw-r--r-- | ceilometer/compute/virt/hyperv/inspector.py | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/ceilometer/compute/virt/hyperv/inspector.py b/ceilometer/compute/virt/hyperv/inspector.py index f1819f22..3d4fcb42 100644 --- a/ceilometer/compute/virt/hyperv/inspector.py +++ b/ceilometer/compute/virt/hyperv/inspector.py @@ -26,39 +26,45 @@ from ceilometer.compute.pollsters import util from ceilometer.compute.virt import inspector as virt_inspector -def convert_exceptions(function, exception_map): +def convert_exceptions(exception_map, yields=True): expected_exceptions = tuple(exception_map.keys()) - @functools.wraps(function) - def wrapper(*args, **kwargs): - try: - return function(*args, **kwargs) - except expected_exceptions as ex: - # exception might be a subclass of an expected exception. - for expected in expected_exceptions: - if isinstance(ex, expected): - raised_exception = exception_map[expected] - break - - exc_info = sys.exc_info() - # NOTE(claudiub): Python 3 raises the exception object given as - # the second argument in six.reraise. - # The original message will be maintained by passing the original - # exception. - exc = raised_exception(six.text_type(exc_info[1])) - six.reraise(raised_exception, exc, exc_info[2]) - return wrapper - - -def decorate_all_methods(decorator, *args, **kwargs): - def decorate(cls): - for attr in cls.__dict__: - class_member = getattr(cls, attr) - if callable(class_member): - setattr(cls, attr, decorator(class_member, *args, **kwargs)) - return cls - - return decorate + def _reraise_exception(exc): + # exception might be a subclass of an expected exception. + for expected in expected_exceptions: + if isinstance(exc, expected): + raised_exception = exception_map[expected] + break + + exc_info = sys.exc_info() + # NOTE(claudiub): Python 3 raises the exception object given as + # the second argument in six.reraise. + # The original message will be maintained by passing the + # original exception. + exc = raised_exception(six.text_type(exc_info[1])) + six.reraise(raised_exception, exc, exc_info[2]) + + def decorator(function): + if yields: + @functools.wraps(function) + def wrapper(*args, **kwargs): + try: + # NOTE(claudiub): We're consuming the function's yield in + # order to avoid yielding a generator. + for item in function(*args, **kwargs): + yield item + except expected_exceptions as ex: + _reraise_exception(ex) + else: + @functools.wraps(function) + def wrapper(*args, **kwargs): + try: + return function(*args, **kwargs) + except expected_exceptions as ex: + _reraise_exception(ex) + + return wrapper + return decorator exception_conversion_map = collections.OrderedDict([ @@ -69,12 +75,11 @@ exception_conversion_map = collections.OrderedDict([ (os_win_exc.OSWinException, virt_inspector.InspectorException), ]) -# NOTE(claudiub): the purpose of the decorator below is to prevent any +# NOTE(claudiub): the purpose of the decorators below is to prevent any # os_win exceptions (subclasses of OSWinException) to leak outside of the # HyperVInspector. -@decorate_all_methods(convert_exceptions, exception_conversion_map) class HyperVInspector(virt_inspector.Inspector): def __init__(self, conf): @@ -91,6 +96,7 @@ class HyperVInspector(virt_inspector.Inspector): return float(host_cpu_clock * host_cpu_count) + @convert_exceptions(exception_conversion_map, yields=False) def inspect_instance(self, instance, duration): instance_name = util.instance_name(instance) (cpu_clock_used, @@ -105,6 +111,7 @@ class HyperVInspector(virt_inspector.Inspector): cpu_time=cpu_time, memory_usage=memory_usage) + @convert_exceptions(exception_conversion_map) def inspect_vnics(self, instance, duration): instance_name = util.instance_name(instance) for vnic_metrics in self._utils.get_vnic_metrics(instance_name): @@ -122,6 +129,7 @@ class HyperVInspector(virt_inspector.Inspector): tx_drop=0, tx_errors=0) + @convert_exceptions(exception_conversion_map) def inspect_disks(self, instance, duration): instance_name = util.instance_name(instance) for disk_metrics in self._utils.get_disk_metrics(instance_name): @@ -134,6 +142,7 @@ class HyperVInspector(virt_inspector.Inspector): write_bytes=disk_metrics['write_mb'] * units.Mi, errors=0, wr_total_times=0, rd_total_times=0) + @convert_exceptions(exception_conversion_map) def inspect_disk_latency(self, instance, duration): instance_name = util.instance_name(instance) for disk_metrics in self._utils.get_disk_latency_metrics( @@ -142,6 +151,7 @@ class HyperVInspector(virt_inspector.Inspector): device=disk_metrics['instance_id'], disk_latency=disk_metrics['disk_latency'] / 1000) + @convert_exceptions(exception_conversion_map) def inspect_disk_iops(self, instance, duration): instance_name = util.instance_name(instance) for disk_metrics in self._utils.get_disk_iops_count(instance_name): |