Events: use tpool only if thread module is patched

At the moment, we use eventlet.tpool when waiting for events
even if the 'thread' module is not monkey patched, which causes
locking issues.

This patch changes this, checking if the 'thread' module is monkey
patched, otherwise calling the method waiting for events directly.

Related-Bug: #1568824

Change-Id: Ib752bfa2acc9f6b47996f6e949aadf20903c849b
This commit is contained in:
Lucian Petrut
2016-04-19 15:17:59 +03:00
committed by Claudiu Belu
parent 304fec7154
commit 356b6cca37
6 changed files with 42 additions and 17 deletions

View File

@@ -297,7 +297,8 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
[self._clusterutils._LIVE_MIGRATION_TYPE])
@mock.patch.object(clusterutils, 'tpool')
def test_monitor_vm_failover_no_vm(self, mock_tpool):
@mock.patch.object(clusterutils, 'patcher')
def test_monitor_vm_failover_no_vm(self, mock_patcher, mock_tpool):
self._clusterutils._watcher = mock.MagicMock()
fake_prev = mock.MagicMock(OwnerNode=self._FAKE_PREV_HOST)
fake_wmi_object = mock.MagicMock(OwnerNode=self._FAKE_HOST,
@@ -314,7 +315,8 @@ class ClusterUtilsTestCase(test_base.OsWinBaseTestCase):
fake_callback.assert_not_called()
@mock.patch.object(clusterutils, 'tpool')
def test_monitor_vm_failover(self, mock_tpool):
@mock.patch.object(clusterutils, 'patcher')
def test_monitor_vm_failover(self, mock_patcher, mock_tpool):
self._clusterutils._watcher = mock.MagicMock()
fake_prev = mock.MagicMock(OwnerNode=self._FAKE_PREV_HOST)
fake_wmi_object = mock.MagicMock(OwnerNode=self._FAKE_HOST,

View File

@@ -943,8 +943,9 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase):
@mock.patch('time.sleep')
@mock.patch.object(vmutils, 'tpool')
def test_vm_power_state_change_event_handler(self, mock_tpool,
mock_sleep):
@mock.patch.object(vmutils, 'patcher')
def test_vm_power_state_change_event_handler(self, mock_patcher,
mock_tpool, mock_sleep):
self._mock_wmi.x_wmi_timed_out = exceptions.HyperVException
enabled_state = constants.HYPERV_VM_STATE_ENABLED

View File

@@ -143,11 +143,12 @@ class NetworkUtilsTestCase(test_base.OsWinBaseTestCase):
mock.sentinel.switch_port_name)
self.assertEqual(mock.sentinel.mac_address, actual_mac_address)
@mock.patch.object(networkutils, 'patcher')
@mock.patch.object(networkutils.tpool, 'execute')
@mock.patch.object(networkutils, 'wmi', create=True)
@mock.patch.object(networkutils.NetworkUtils, '_get_event_wql_query')
def test_get_vnic_event_listener(self, mock_get_event_query, mock_wmi,
mock_execute):
mock_execute, mock_patcher):
mock_wmi.x_wmi_timed_out = ValueError
event = mock.MagicMock()
port_class = self.netutils._conn.Msvm_SyntheticEthernetPortSettingData

View File

@@ -23,6 +23,7 @@ import sys
if sys.platform == 'win32':
import wmi
from eventlet import patcher
from eventlet import tpool
from oslo_log import log as logging
@@ -211,8 +212,12 @@ class ClusterUtils(baseutils.BaseUtils):
new_host = None
try:
# wait for new event for _WMI_EVENT_TIMEOUT_MS miliseconds.
wmi_object = tpool.execute(self._watcher,
self._WMI_EVENT_TIMEOUT_MS)
if patcher.is_monkey_patched('thread'):
wmi_object = tpool.execute(self._watcher,
self._WMI_EVENT_TIMEOUT_MS)
else:
wmi_object = self._watcher(self._WMI_EVENT_TIMEOUT_MS)
old_host = wmi_object.previous.OwnerNode
new_host = wmi_object.OwnerNode
# wmi_object.Name field is of the form:

View File

@@ -20,6 +20,7 @@ Based on the "root/virtualization/v2" namespace available starting with
Hyper-V Server / Windows Server 2012.
"""
import functools
import sys
import time
import uuid
@@ -27,6 +28,7 @@ import uuid
if sys.platform == 'win32':
import wmi
from eventlet import patcher
from eventlet import tpool
from oslo_config import cfg
from oslo_log import log as logging
@@ -818,16 +820,22 @@ class VMUtils(baseutils.BaseUtilsVirt):
fields=[field])
def _handle_events(callback):
if patcher.is_monkey_patched('thread'):
# Retrieve one by one all the events that occurred in
# the checked interval.
#
# We use eventlet.tpool for retrieving the events in
# order to avoid issues caused by greenthread/thread
# communication. Note that PyMI must use the unpatched
# threading module.
listen = functools.partial(tpool.execute, listener,
event_timeout)
else:
listen = functools.partial(listener, event_timeout)
while True:
try:
# Retrieve one by one all the events that occurred in
# the checked interval.
#
# We use eventlet.tpool for retrieving the events in
# order to avoid issues caused by greenthread/thread
# communication. Note that PyMI must use the unpatched
# threading module.
event = tpool.execute(listener, event_timeout)
event = listen()
vm_name = event.ElementName
vm_state = event.EnabledState

View File

@@ -18,9 +18,11 @@ Utility class for network related operations.
Based on the "root/virtualization/v2" namespace available starting with
Hyper-V Server / Windows Server 2012.
"""
import functools
import re
from eventlet import greenthread
from eventlet import patcher
from eventlet import tpool
import sys
@@ -216,12 +218,18 @@ class NetworkUtils(baseutils.BaseUtilsVirt):
query)
def _poll_events(callback):
if patcher.is_monkey_patched('thread'):
listen = functools.partial(tpool.execute, listener,
self._VNIC_LISTENER_TIMEOUT_MS)
else:
listen = functools.partial(listener,
self._VNIC_LISTENER_TIMEOUT_MS)
while True:
# Retrieve one by one all the events that occurred in
# the checked interval.
try:
event = tpool.execute(listener,
self._VNIC_LISTENER_TIMEOUT_MS)
event = listen()
callback(event.ElementName)
except wmi.x_wmi_timed_out:
# no new event published.