Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP5:GA
salt.18639
fix-for-bsc-1102248-psutil-is-broken-and-so-pro...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File fix-for-bsc-1102248-psutil-is-broken-and-so-process-.patch of Package salt.18639
From 5e47db73c2b1059eef3a95066fbb2dcf9551aeb3 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <vzhestkov@suse.com> Date: Tue, 13 Oct 2020 09:26:07 +0300 Subject: [PATCH] Fix for bsc#1102248 - psutil is broken and so Process is not working on Python 3 as it is implemented --- salt/modules/ps.py | 268 ++++++++++++++++++++++++++------------------- 1 file changed, 157 insertions(+), 111 deletions(-) diff --git a/salt/modules/ps.py b/salt/modules/ps.py index bb37873f48..9925e29968 100644 --- a/salt/modules/ps.py +++ b/salt/modules/ps.py @@ -1,31 +1,33 @@ # -*- coding: utf-8 -*- -''' +""" A salt interface to psutil, a system and process library. See http://code.google.com/p/psutil. :depends: - psutil Python module, version 0.3.0 or later - python-utmp package (optional) -''' +""" # Import python libs -from __future__ import absolute_import, unicode_literals, print_function -import time +from __future__ import absolute_import, print_function, unicode_literals + import datetime import re +import time # Import salt libs import salt.utils.data -from salt.exceptions import SaltInvocationError, CommandExecutionError # Import third party libs import salt.utils.decorators.path +from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.ext import six + # pylint: disable=import-error try: import salt.utils.psutil_compat as psutil HAS_PSUTIL = True - PSUTIL2 = getattr(psutil, 'version_info', ()) >= (2, 0) + PSUTIL2 = getattr(psutil, "version_info", ()) >= (2, 0) except ImportError: HAS_PSUTIL = False # pylint: enable=import-error @@ -33,7 +35,10 @@ except ImportError: def __virtual__(): if not HAS_PSUTIL: - return False, 'The ps module cannot be loaded: python module psutil not installed.' + return ( + False, + "The ps module cannot be loaded: python module psutil not installed.", + ) # Functions and attributes used in this execution module seem to have been # added as of psutil 0.3.0, from an inspection of the source code. Only @@ -44,15 +49,20 @@ def __virtual__(): # as of Dec. 2013 EPEL is on 0.6.1, Debian 7 is on 0.5.1, etc.). if psutil.version_info >= (0, 3, 0): return True - return (False, 'The ps execution module cannot be loaded: the psutil python module version {0} is less than 0.3.0'.format(psutil.version_info)) + return ( + False, + "The ps execution module cannot be loaded: the psutil python module version {0} is less than 0.3.0".format( + psutil.version_info + ), + ) def _get_proc_cmdline(proc): - ''' + """ Returns the cmdline of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ try: return salt.utils.data.decode(proc.cmdline() if PSUTIL2 else proc.cmdline) except (psutil.NoSuchProcess, psutil.AccessDenied): @@ -60,23 +70,25 @@ def _get_proc_cmdline(proc): def _get_proc_create_time(proc): - ''' + """ Returns the create_time of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ try: - return salt.utils.data.decode(proc.create_time() if PSUTIL2 else proc.create_time) + return salt.utils.data.decode( + proc.create_time() if PSUTIL2 else proc.create_time + ) except (psutil.NoSuchProcess, psutil.AccessDenied): return None def _get_proc_name(proc): - ''' + """ Returns the name of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ try: return salt.utils.data.decode(proc.name() if PSUTIL2 else proc.name) except (psutil.NoSuchProcess, psutil.AccessDenied): @@ -84,11 +96,11 @@ def _get_proc_name(proc): def _get_proc_status(proc): - ''' + """ Returns the status of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ try: return salt.utils.data.decode(proc.status() if PSUTIL2 else proc.status) except (psutil.NoSuchProcess, psutil.AccessDenied): @@ -96,11 +108,11 @@ def _get_proc_status(proc): def _get_proc_username(proc): - ''' + """ Returns the username of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ try: return salt.utils.data.decode(proc.username() if PSUTIL2 else proc.username) except (psutil.NoSuchProcess, psutil.AccessDenied, KeyError): @@ -108,16 +120,16 @@ def _get_proc_username(proc): def _get_proc_pid(proc): - ''' + """ Returns the pid of a Process instance. It's backward compatible with < 2.0 versions of psutil. - ''' + """ return proc.pid def top(num_processes=5, interval=3): - ''' + """ Return a list of top CPU consuming processes during the interval. num_processes = return the top N CPU consuming processes interval = the number of seconds to sample CPU usage over @@ -129,57 +141,63 @@ def top(num_processes=5, interval=3): salt '*' ps.top salt '*' ps.top 5 10 - ''' + """ result = [] start_usage = {} for pid in psutil.pids(): try: process = psutil.Process(pid) - user, system = process.cpu_times() - except ValueError: - user, system, _, _ = process.cpu_times() except psutil.NoSuchProcess: continue + else: + try: + user, system = process.cpu_times()[:2] + except psutil.ZombieProcess: + user = system = 0.0 start_usage[process] = user + system time.sleep(interval) usage = set() for process, start in six.iteritems(start_usage): try: - user, system = process.cpu_times() - except ValueError: - user, system, _, _ = process.cpu_times() + user, system = process.cpu_times()[:2] except psutil.NoSuchProcess: continue now = user + system diff = now - start usage.add((diff, process)) - for idx, (diff, process) in enumerate(reversed(sorted(usage))): - if num_processes and idx >= num_processes: - break - if len(_get_proc_cmdline(process)) == 0: - cmdline = _get_proc_name(process) - else: - cmdline = _get_proc_cmdline(process) - info = {'cmd': cmdline, - 'user': _get_proc_username(process), - 'status': _get_proc_status(process), - 'pid': _get_proc_pid(process), - 'create_time': _get_proc_create_time(process), - 'cpu': {}, - 'mem': {}, + for diff, process in sorted(usage, key=lambda x: x[0], reverse=True): + info = { + "cmd": _get_proc_cmdline(process) or _get_proc_name(process), + "user": _get_proc_username(process), + "status": _get_proc_status(process), + "pid": _get_proc_pid(process), + "create_time": _get_proc_create_time(process), + "cpu": {}, + "mem": {}, } - for key, value in six.iteritems(process.cpu_times()._asdict()): - info['cpu'][key] = value - for key, value in six.iteritems(process.memory_info()._asdict()): - info['mem'][key] = value + try: + for key, value in six.iteritems(process.cpu_times()._asdict()): + info["cpu"][key] = value + for key, value in six.iteritems(process.memory_info()._asdict()): + info["mem"][key] = value + except psutil.NoSuchProcess: + # Process ended since psutil.pids() was run earlier in this + # function. Ignore this process and do not include this process in + # the return data. + continue + result.append(info) + # Stop gathering process info since we've reached the desired number + if len(result) >= num_processes: + break + return result def get_pid_list(): - ''' + """ Return a list of process ids (PIDs) for all running processes. CLI Example: @@ -187,12 +205,12 @@ def get_pid_list(): .. code-block:: bash salt '*' ps.get_pid_list - ''' + """ return psutil.pids() def proc_info(pid, attrs=None): - ''' + """ Return a dictionary of information for a process id (PID). CLI Example: @@ -209,7 +227,7 @@ def proc_info(pid, attrs=None): Optional list of desired process attributes. The list of possible attributes can be found here: http://pythonhosted.org/psutil/#psutil.Process - ''' + """ try: proc = psutil.Process(pid) return proc.as_dict(attrs) @@ -218,7 +236,7 @@ def proc_info(pid, attrs=None): def kill_pid(pid, signal=15): - ''' + """ Kill a process by PID. .. code-block:: bash @@ -239,7 +257,7 @@ def kill_pid(pid, signal=15): .. code-block:: bash salt 'minion' ps.kill_pid 2000 signal=9 - ''' + """ try: psutil.Process(pid).send_signal(signal) return True @@ -248,7 +266,7 @@ def kill_pid(pid, signal=15): def pkill(pattern, user=None, signal=15, full=False): - ''' + """ Kill processes matching a pattern. .. code-block:: bash @@ -283,12 +301,15 @@ def pkill(pattern, user=None, signal=15, full=False): .. code-block:: bash salt '*' ps.pkill bash signal=9 user=tom - ''' + """ killed = [] for proc in psutil.process_iter(): - name_match = pattern in ' '.join(_get_proc_cmdline(proc)) if full \ + name_match = ( + pattern in " ".join(_get_proc_cmdline(proc)) + if full else pattern in _get_proc_name(proc) + ) user_match = True if user is None else user == _get_proc_username(proc) if name_match and user_match: try: @@ -299,11 +320,11 @@ def pkill(pattern, user=None, signal=15, full=False): if not killed: return None else: - return {'killed': killed} + return {"killed": killed} -def pgrep(pattern, user=None, full=False): - ''' +def pgrep(pattern, user=None, full=False, pattern_is_regex=False): + """ Return the pids for processes matching a pattern. If full is true, the full command line is searched for a match, @@ -323,6 +344,12 @@ def pgrep(pattern, user=None, full=False): A boolean value indicating whether only the name of the command or the full command line should be matched against the pattern. + pattern_is_regex + This flag enables ps.pgrep to mirror the regex search functionality + found in the pgrep command line utility. + + .. versionadded:: 3001 + **Examples:** Find all httpd processes on all 'www' minions: @@ -336,20 +363,34 @@ def pgrep(pattern, user=None, full=False): .. code-block:: bash salt '*' ps.pgrep bash user=tom - ''' + """ procs = [] + + if pattern_is_regex: + pattern = re.compile(str(pattern)) + for proc in psutil.process_iter(): - name_match = pattern in ' '.join(_get_proc_cmdline(proc)) if full \ - else pattern in _get_proc_name(proc) + if full: + process_line = " ".join(_get_proc_cmdline(proc)) + else: + process_line = _get_proc_name(proc) + + if pattern_is_regex: + name_match = re.search(pattern, process_line) + else: + name_match = pattern in process_line + user_match = True if user is None else user == _get_proc_username(proc) + if name_match and user_match: procs.append(_get_proc_pid(proc)) + return procs or None def cpu_percent(interval=0.1, per_cpu=False): - ''' + """ Return the percent of time the CPU is busy. interval @@ -363,7 +404,7 @@ def cpu_percent(interval=0.1, per_cpu=False): .. code-block:: bash salt '*' ps.cpu_percent - ''' + """ if per_cpu: result = list(psutil.cpu_percent(interval, True)) else: @@ -372,7 +413,7 @@ def cpu_percent(interval=0.1, per_cpu=False): def cpu_times(per_cpu=False): - ''' + """ Return the percent of time the CPU spends in each state, e.g. user, system, idle, nice, iowait, irq, softirq. @@ -385,7 +426,7 @@ def cpu_times(per_cpu=False): .. code-block:: bash salt '*' ps.cpu_times - ''' + """ if per_cpu: result = [dict(times._asdict()) for times in psutil.cpu_times(True)] else: @@ -394,7 +435,7 @@ def cpu_times(per_cpu=False): def virtual_memory(): - ''' + """ .. versionadded:: 2014.7.0 Return a dict that describes statistics about system memory usage. @@ -408,15 +449,15 @@ def virtual_memory(): .. code-block:: bash salt '*' ps.virtual_memory - ''' + """ if psutil.version_info < (0, 6, 0): - msg = 'virtual_memory is only available in psutil 0.6.0 or greater' + msg = "virtual_memory is only available in psutil 0.6.0 or greater" raise CommandExecutionError(msg) return dict(psutil.virtual_memory()._asdict()) def swap_memory(): - ''' + """ .. versionadded:: 2014.7.0 Return a dict that describes swap memory statistics. @@ -430,15 +471,15 @@ def swap_memory(): .. code-block:: bash salt '*' ps.swap_memory - ''' + """ if psutil.version_info < (0, 6, 0): - msg = 'swap_memory is only available in psutil 0.6.0 or greater' + msg = "swap_memory is only available in psutil 0.6.0 or greater" raise CommandExecutionError(msg) return dict(psutil.swap_memory()._asdict()) def disk_partitions(all=False): - ''' + """ Return a list of disk partitions and their device, mount point, and filesystem type. @@ -451,14 +492,13 @@ def disk_partitions(all=False): .. code-block:: bash salt '*' ps.disk_partitions - ''' - result = [dict(partition._asdict()) for partition in - psutil.disk_partitions(all)] + """ + result = [dict(partition._asdict()) for partition in psutil.disk_partitions(all)] return result def disk_usage(path): - ''' + """ Given a path, return a dict listing the total available space as well as the free space, and used space. @@ -467,12 +507,12 @@ def disk_usage(path): .. code-block:: bash salt '*' ps.disk_usage /home - ''' + """ return dict(psutil.disk_usage(path)._asdict()) def disk_partition_usage(all=False): - ''' + """ Return a list of disk partitions plus the mount point, filesystem and usage statistics. @@ -481,15 +521,15 @@ def disk_partition_usage(all=False): .. code-block:: bash salt '*' ps.disk_partition_usage - ''' + """ result = disk_partitions(all) for partition in result: - partition.update(disk_usage(partition['mountpoint'])) + partition.update(disk_usage(partition["mountpoint"])) return result def total_physical_memory(): - ''' + """ Return the total number of bytes of physical memory. CLI Example: @@ -497,9 +537,9 @@ def total_physical_memory(): .. code-block:: bash salt '*' ps.total_physical_memory - ''' + """ if psutil.version_info < (0, 6, 0): - msg = 'virtual_memory is only available in psutil 0.6.0 or greater' + msg = "virtual_memory is only available in psutil 0.6.0 or greater" raise CommandExecutionError(msg) try: return psutil.virtual_memory().total @@ -510,7 +550,7 @@ def total_physical_memory(): def num_cpus(): - ''' + """ Return the number of CPUs. CLI Example: @@ -518,7 +558,7 @@ def num_cpus(): .. code-block:: bash salt '*' ps.num_cpus - ''' + """ try: return psutil.cpu_count() except AttributeError: @@ -528,7 +568,7 @@ def num_cpus(): def boot_time(time_format=None): - ''' + """ Return the boot time in number of seconds since the epoch began. CLI Example: @@ -545,7 +585,7 @@ def boot_time(time_format=None): .. code-block:: bash salt '*' ps.boot_time - ''' + """ try: b_time = int(psutil.boot_time()) except AttributeError: @@ -558,12 +598,12 @@ def boot_time(time_format=None): try: return b_time.strftime(time_format) except TypeError as exc: - raise SaltInvocationError('Invalid format string: {0}'.format(exc)) + raise SaltInvocationError("Invalid format string: {0}".format(exc)) return b_time def network_io_counters(interface=None): - ''' + """ Return network I/O statistics. CLI Example: @@ -573,7 +613,7 @@ def network_io_counters(interface=None): salt '*' ps.network_io_counters salt '*' ps.network_io_counters interface=eth0 - ''' + """ if not interface: return dict(psutil.net_io_counters()._asdict()) else: @@ -585,7 +625,7 @@ def network_io_counters(interface=None): def disk_io_counters(device=None): - ''' + """ Return disk I/O statistics. CLI Example: @@ -595,7 +635,7 @@ def disk_io_counters(device=None): salt '*' ps.disk_io_counters salt '*' ps.disk_io_counters device=sda1 - ''' + """ if not device: return dict(psutil.disk_io_counters()._asdict()) else: @@ -607,7 +647,7 @@ def disk_io_counters(device=None): def get_users(): - ''' + """ Return logged-in users. CLI Example: @@ -615,7 +655,7 @@ def get_users(): .. code-block:: bash salt '*' ps.get_users - ''' + """ try: recs = psutil.users() return [dict(x._asdict()) for x in recs] @@ -634,14 +674,20 @@ def get_users(): started = rec[8] if isinstance(started, tuple): started = started[0] - result.append({'name': rec[4], 'terminal': rec[2], - 'started': started, 'host': rec[5]}) + result.append( + { + "name": rec[4], + "terminal": rec[2], + "started": started, + "host": rec[5], + } + ) except ImportError: return False def lsof(name): - ''' + """ Retrieve the lsof information of the given process name. CLI Example: @@ -649,17 +695,17 @@ def lsof(name): .. code-block:: bash salt '*' ps.lsof apache2 - ''' + """ sanitize_name = six.text_type(name) - lsof_infos = __salt__['cmd.run']("lsof -c " + sanitize_name) + lsof_infos = __salt__["cmd.run"]("lsof -c " + sanitize_name) ret = [] ret.extend([sanitize_name, lsof_infos]) return ret -@salt.utils.decorators.path.which('netstat') +@salt.utils.decorators.path.which("netstat") def netstat(name): - ''' + """ Retrieve the netstat information of the given process name. CLI Example: @@ -667,9 +713,9 @@ def netstat(name): .. code-block:: bash salt '*' ps.netstat apache2 - ''' + """ sanitize_name = six.text_type(name) - netstat_infos = __salt__['cmd.run']("netstat -nap") + netstat_infos = __salt__["cmd.run"]("netstat -nap") found_infos = [] ret = [] for info in netstat_infos.splitlines(): @@ -679,9 +725,9 @@ def netstat(name): return ret -@salt.utils.decorators.path.which('ss') +@salt.utils.decorators.path.which("ss") def ss(name): - ''' + """ Retrieve the ss information of the given process name. CLI Example: @@ -692,9 +738,9 @@ def ss(name): .. versionadded:: 2016.11.6 - ''' + """ sanitize_name = six.text_type(name) - ss_infos = __salt__['cmd.run']("ss -neap") + ss_infos = __salt__["cmd.run"]("ss -neap") found_infos = [] ret = [] for info in ss_infos.splitlines(): @@ -705,7 +751,7 @@ def ss(name): def psaux(name): - ''' + """ Retrieve information corresponding to a "ps aux" filtered with the given pattern. It could be just a name or a regular expression (using python search from "re" module). @@ -715,11 +761,11 @@ def psaux(name): .. code-block:: bash salt '*' ps.psaux www-data.+apache2 - ''' + """ sanitize_name = six.text_type(name) pattern = re.compile(sanitize_name) salt_exception_pattern = re.compile("salt.+ps.psaux.+") - ps_aux = __salt__['cmd.run']("ps aux") + ps_aux = __salt__["cmd.run"]("ps aux") found_infos = [] ret = [] nb_lines = 0 -- 2.29.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor