Merge "Optimize pid property in AsyncProcess class"

This commit is contained in:
Jenkins 2017-04-16 03:09:50 +00:00 committed by Gerrit Code Review
commit d20c0edfc6
2 changed files with 31 additions and 6 deletions
neutron
agent/linux
tests/unit/agent/linux

View File

@ -78,6 +78,7 @@ class AsyncProcess(object):
raise ValueError(_('respawn_interval must be >= 0 if provided.'))
self.respawn_interval = respawn_interval
self._process = None
self._pid = None
self._is_running = False
self._kill_event = None
self._reset_queues()
@ -95,8 +96,8 @@ class AsyncProcess(object):
def is_active(self):
# If using sudo rootwrap as a root_helper, we have to wait until sudo
# spawns rootwrap and rootwrap spawns the process.
# spawns rootwrap and rootwrap spawns the process. self.pid will make
# sure to get the correct pid.
return utils.pid_invoked_with_cmdline(
self.pid, self.cmd_without_namespace)
@ -137,6 +138,7 @@ class AsyncProcess(object):
def _spawn(self):
"""Spawn a process and its watchers."""
self._is_running = True
self._pid = None
self._kill_event = eventlet.event.Event()
self._process, cmd = utils.create_process(self._cmd,
run_as_root=self.run_as_root)
@ -154,16 +156,19 @@ class AsyncProcess(object):
@property
def pid(self):
if self._process:
return utils.get_root_helper_child_pid(
self._process.pid,
self.cmd_without_namespace,
run_as_root=self.run_as_root)
if not self._pid:
self._pid = utils.get_root_helper_child_pid(
self._process.pid,
self.cmd_without_namespace,
run_as_root=self.run_as_root)
return self._pid
def _kill(self, kill_signal):
"""Kill the process and the associated watcher greenthreads."""
pid = self.pid
if pid:
self._is_running = False
self._pid = None
self._kill_process(pid, kill_signal)
# Halt the greenthreads if they weren't already.

View File

@ -56,6 +56,25 @@ class TestAsyncProcess(base.BaseTestCase):
])
self.assertEqual(len(proc._watchers), 2)
def test__pid_none(self):
pid = 1
self.proc._pid = None
with mock.patch.object(self.proc, '_process') as _process:
with mock.patch.object(utils,
'get_root_helper_child_pid') as func:
func.return_value = pid
self.assertEqual(self.proc.pid, pid)
func.assert_called_once_with(_process.pid, ['fake'],
run_as_root=False)
self.assertEqual(self.proc._pid, pid)
def test__pid_not_none(self):
self.proc._pid = 1
with mock.patch.object(self.proc, '_process'),\
mock.patch.object(utils, 'get_root_helper_child_pid') as func:
self.assertEqual(self.proc.pid, 1)
func.assert_not_called()
def test__handle_process_error_kills_with_respawn(self):
with mock.patch.object(self.proc, '_kill') as kill:
self.proc._handle_process_error()
@ -185,6 +204,7 @@ class TestAsyncProcess(base.BaseTestCase):
self.assertIsNone(self.proc._kill_event)
self.assertFalse(self.proc._is_running)
self.assertIsNone(self.proc._pid)
mock_kill_event.send.assert_called_once_with()
if pid: