Remove psutil dependency

The version of psutil that was being required is not hosted on
PyPi which caused some issues. This patch removes the psutil
dependency in favor of using the method that was proposed for
the havana backport of polling minimization.

Closes-bug: #1268711
Change-Id: I5a1672cfd195099d92578321153c42b8bfd09b7d
This commit is contained in:
Terry Wilson 2014-01-24 13:34:15 -06:00
parent b78eea6146
commit 9d3a07ed04
5 changed files with 60 additions and 18 deletions

View File

@ -18,7 +18,6 @@ import eventlet
import eventlet.event
import eventlet.queue
import eventlet.timeout
import psutil
from neutron.agent.linux import utils
from neutron.openstack.common import log as logging
@ -141,12 +140,18 @@ class AsyncProcess(object):
# die is to target the child process directly.
if self.root_helper:
try:
# This assumes that there are not multiple children in any
# level of the process tree under the parent process.
pid = psutil.Process(
self._process.pid).get_children(recursive=True)[-1].pid
except (psutil.NoSuchProcess, IndexError):
pid = None
pid = utils.find_child_pids(pid)[0]
except IndexError:
# Process is already dead
return None
while True:
try:
# We shouldn't have more than one child per process
# so keep getting the children of the first one
pid = utils.find_child_pids(pid)[0]
except IndexError:
# Last process in the tree, return it
break
return pid
def _kill_process(self, pid):

View File

@ -108,3 +108,18 @@ def replace_file(file_name, data):
tmp_file.close()
os.chmod(tmp_file.name, 0o644)
os.rename(tmp_file.name, file_name)
def find_child_pids(pid):
"""Retrieve a list of the pids of child processes of the given pid."""
try:
raw_pids = execute(['ps', '--ppid', pid, '-o', 'pid='])
except RuntimeError as e:
# Exception has already been logged by execute
no_children_found = 'Exit code: 1' in str(e)
if no_children_found:
return []
# Unexpected errors are the responsibility of the caller
raise
return [x.strip() for x in raw_pids.split('\n') if x.strip()]

View File

@ -14,8 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import collections
import eventlet.event
import eventlet.queue
import eventlet.timeout
@ -187,19 +185,20 @@ class TestAsyncProcess(base.BaseTestCase):
def _test__get_pid_to_kill(self, expected=_marker,
root_helper=None, pids=None):
def _find_child_pids(x):
if not pids:
return []
pids.pop(0)
return pids
if root_helper:
self.proc.root_helper = root_helper
xpid = collections.namedtuple('xpid', ['pid'])
xpids = [xpid(pid) for pid in pids or []]
with mock.patch.object(self.proc, '_process') as mock_process:
with mock.patch.object(mock_process, 'pid') as mock_pid:
with mock.patch('psutil.Process') as mock_ps_process:
instance = mock_ps_process.return_value
instance.get_children.return_value = xpids
with mock.patch.object(utils, 'find_child_pids',
side_effect=_find_child_pids):
actual = self.proc._get_pid_to_kill()
if expected is _marker:
expected = mock_pid
self.assertEqual(expected, actual)
@ -208,7 +207,8 @@ class TestAsyncProcess(base.BaseTestCase):
self._test__get_pid_to_kill()
def test__get_pid_to_kill_returns_child_pid_with_root_helper(self):
self._test__get_pid_to_kill(expected='1', pids=['1'], root_helper='a')
self._test__get_pid_to_kill(expected='2', pids=['1', '2'],
root_helper='a')
def test__get_pid_to_kill_returns_last_child_pid_with_root_Helper(self):
self._test__get_pid_to_kill(expected='3', pids=['1', '2', '3'],

View File

@ -17,6 +17,7 @@
import fixtures
import mock
import testtools
from neutron.agent.linux import utils
from neutron.tests import base
@ -106,3 +107,25 @@ class AgentUtilsReplaceFile(base.BaseTestCase):
ntf.assert_has_calls(expected)
chmod.assert_called_once_with('/baz', 0o644)
rename.assert_called_once_with('/baz', '/foo')
class TestFindChildPids(base.BaseTestCase):
def test_returns_empty_list_for_exit_code_1(self):
with mock.patch.object(utils, 'execute',
side_effect=RuntimeError('Exit code: 1')):
self.assertEqual(utils.find_child_pids(-1), [])
def test_returns_empty_list_for_no_output(self):
with mock.patch.object(utils, 'execute', return_value=''):
self.assertEqual(utils.find_child_pids(-1), [])
def test_returns_list_of_child_process_ids_for_good_ouput(self):
with mock.patch.object(utils, 'execute', return_value=' 123 \n 185\n'):
self.assertEqual(utils.find_child_pids(-1), ['123', '185'])
def test_raises_unknown_exception(self):
with testtools.ExpectedException(RuntimeError):
with mock.patch.object(utils, 'execute',
side_effect=RuntimeError()):
utils.find_child_pids(-1)

View File

@ -16,7 +16,6 @@ jsonrpclib
Jinja2
kombu>=2.4.8
netaddr>=0.7.6
psutil>=0.6.1,<1.0
python-neutronclient>=2.3.0,<3
SQLAlchemy>=0.7.8,<=0.7.99
WebOb>=1.2.3,<1.3