diff --git a/neutron/agent/windows/utils.py b/neutron/agent/windows/utils.py index f97d3e45ef2..515a122a005 100644 --- a/neutron/agent/windows/utils.py +++ b/neutron/agent/windows/utils.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ctypes import io import os @@ -38,6 +39,8 @@ LOG = logging.getLogger(__name__) subprocess = eventlet.patcher.original('subprocess') subprocess.threading = eventlet.patcher.original('threading') +ERROR_KEY_DELETED = 0x03FA + def create_process(cmd, run_as_root=False, addl_env=None, tpool_proxy=True): @@ -71,8 +74,16 @@ def _get_wmi_process(pid): if not pid: return None - conn = wmi.WMI() - processes = conn.Win32_Process(ProcessId=pid) + try: + conn = wmi.WMI() + processes = conn.Win32_Process(ProcessId=pid) + except wmi.x_wmi as exc: + hresult = exc.com_error.hresult + err_code = ctypes.c_uint(hresult).value & 0xFFFF + if err_code == ERROR_KEY_DELETED: + return None + raise + if processes: return processes[0] return None diff --git a/neutron/tests/unit/agent/windows/test_utils.py b/neutron/tests/unit/agent/windows/test_utils.py index 229f6fe1395..6c291e760d6 100644 --- a/neutron/tests/unit/agent/windows/test_utils.py +++ b/neutron/tests/unit/agent/windows/test_utils.py @@ -26,6 +26,13 @@ from neutron.agent.windows import utils from neutron.tests import base +class x_wmi(Exception): + def __init__(self, info='', com_error=None): + super(x_wmi, self).__init__(info) + self.info = info + self.com_error = com_error + + @ddt.ddt class WindowsUtilsTestCase(base.BaseTestCase): @mock.patch('os.environ', {mock.sentinel.key0: mock.sentinel.val0}) @@ -87,6 +94,25 @@ class WindowsUtilsTestCase(base.BaseTestCase): if pid: mock_conn.Win32_Process.assert_called_once_with(ProcessId=pid) + @ddt.data({}, + {"hresult": 0xff, + "expect_exc": True}) + @ddt.unpack + @mock.patch.object(utils, 'wmi', create=True) + def test_get_wmi_process_exc(self, mock_wmi, expect_exc=False, + hresult=0x800703FA): + mock_conn = mock_wmi.WMI.return_value + mock_wmi.x_wmi = x_wmi + com_error = mock.Mock(hresult=hresult) + exc = x_wmi(com_error=com_error) + mock_conn.Win32_Process.side_effect = exc + + if expect_exc: + self.assertRaises( + x_wmi, utils._get_wmi_process, mock.sentinel.pid) + else: + self.assertIsNone(utils._get_wmi_process(mock.sentinel.pid)) + @ddt.data(True, False) @mock.patch.object(utils, '_get_wmi_process') def test_kill_process(self, process_exists, mock_get_process):