From aa2f05870106d0402f4bd4c3f425c62ed11a2e7a Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Sat, 17 Oct 2020 09:07:08 +0000 Subject: [PATCH] Implement "get_process_count_by_name" natively Use Python native libraries instead of shell calls. Closes-Bug: #1900269 Change-Id: If6eafb7f5f26ab127ab5432ce85096d052a20b0c --- lower-constraints.txt | 2 +- neutron/agent/linux/utils.py | 9 ++------ .../functional/agent/linux/test_utils.py | 23 +++++++++++++++++++ requirements.txt | 2 +- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lower-constraints.txt b/lower-constraints.txt index 8a28fdadea6..6a817905984 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -89,7 +89,7 @@ pika-pool==0.1.3 pika==0.10.0 positional==1.2.1 prettytable==0.7.2 -psutil==3.2.2 +psutil==5.3.0 pycadf==1.1.0 pycparser==2.18 Pygments==2.2.0 diff --git a/neutron/agent/linux/utils.py b/neutron/agent/linux/utils.py index a748c171022..7b31b05f009 100644 --- a/neutron/agent/linux/utils.py +++ b/neutron/agent/linux/utils.py @@ -195,13 +195,8 @@ def find_parent_pid(pid): def get_process_count_by_name(name): """Find the process count by name.""" - try: - out = execute(['ps', '-C', name, '-o', 'comm='], - log_fail_as_error=False) - except exceptions.ProcessExecutionError: - with excutils.save_and_reraise_exception(reraise=False): - return 0 - return len(out.strip('\n').split('\n')) + return len([p for p in psutil.process_iter(['name']) if + p.info['name'] == name]) def find_fork_top_parent(pid): diff --git a/neutron/tests/functional/agent/linux/test_utils.py b/neutron/tests/functional/agent/linux/test_utils.py index 6931b792afd..dde8f225090 100644 --- a/neutron/tests/functional/agent/linux/test_utils.py +++ b/neutron/tests/functional/agent/linux/test_utils.py @@ -118,3 +118,26 @@ class TestFindParentPid(functional_base.BaseSudoTestCase): def test_non_root_process(self): self._test_process(run_as_root=False) + + +class TestGetProcessCountByName(functional_base.BaseSudoTestCase): + + def _stop_processes(self, processes): + for process in processes: + process.stop(kill_signal=signal.SIGKILL) + + def test_root_process(self): + cmd = ['sleep', '100'] + processes = [] + for _ in range(20): + process = async_process.AsyncProcess(cmd) + process.start() + processes.append(process) + for process in processes: + common_utils.wait_until_true(lambda: process._process.pid, + sleep=0.5, timeout=5) + self.addCleanup(self._stop_processes, processes) + number_of_sleep = utils.get_process_count_by_name('sleep') + # NOTE(ralonsoh): other tests can spawn sleep processes too, but at + # this point we know there are, at least, 20 "sleep" processes running. + self.assertLessEqual(20, number_of_sleep) diff --git a/requirements.txt b/requirements.txt index c55dba4fd8b..7ca25669d45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -46,7 +46,7 @@ osprofiler>=2.3.0 # Apache-2.0 os-ken >= 0.3.0 # Apache-2.0 ovs>=2.8.0 # Apache-2.0 ovsdbapp>=1.4.0 # Apache-2.0 -psutil>=3.2.2 # BSD +psutil>=5.3.0 # BSD pyroute2>=0.5.13;sys_platform!='win32' # Apache-2.0 (+ dual licensed GPL2) pyOpenSSL>=17.1.0 # Apache-2.0