mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
commit
8ec4fb2a73
5 changed files with 133 additions and 33 deletions
|
@ -48,7 +48,7 @@ import salt.ext.six as six
|
|||
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
|
||||
HAS_PSUTIL = False
|
||||
try:
|
||||
import psutil
|
||||
import salt.utils.psutil_compat as psutil
|
||||
HAS_PSUTIL = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -520,7 +520,7 @@ class SaltLoadModules(ioflo.base.deeding.Deed):
|
|||
)
|
||||
modules_max_memory = True
|
||||
old_mem_limit = resource.getrlimit(resource.RLIMIT_AS)
|
||||
rss, vms = psutil.Process(os.getpid()).get_memory_info()
|
||||
rss, vms = psutil.Process(os.getpid()).memory_info()
|
||||
mem_limit = rss + vms + self.opts.value['modules_max_memory']
|
||||
resource.setrlimit(resource.RLIMIT_AS, (mem_limit, mem_limit))
|
||||
elif self.opts.value.get('modules_max_memory', -1) > 0:
|
||||
|
|
|
@ -42,7 +42,7 @@ except ImportError:
|
|||
|
||||
HAS_PSUTIL = False
|
||||
try:
|
||||
import psutil
|
||||
import salt.utils.psutil_compat as psutil
|
||||
HAS_PSUTIL = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -924,7 +924,7 @@ class Minion(MinionBase):
|
|||
log.debug('modules_max_memory set, enforcing a maximum of {0}'.format(self.opts['modules_max_memory']))
|
||||
modules_max_memory = True
|
||||
old_mem_limit = resource.getrlimit(resource.RLIMIT_AS)
|
||||
rss, vms = psutil.Process(os.getpid()).get_memory_info()
|
||||
rss, vms = psutil.Process(os.getpid()).memory_info()
|
||||
mem_limit = rss + vms + self.opts['modules_max_memory']
|
||||
resource.setrlimit(resource.RLIMIT_AS, (mem_limit, mem_limit))
|
||||
elif self.opts.get('modules_max_memory', -1) > 0:
|
||||
|
|
|
@ -17,7 +17,7 @@ from salt.exceptions import SaltInvocationError, CommandExecutionError
|
|||
|
||||
# Import third party libs
|
||||
try:
|
||||
import psutil
|
||||
import salt.utils.psutil_compat as psutil
|
||||
|
||||
HAS_PSUTIL = True
|
||||
PSUTIL2 = psutil.version_info >= (2, 0)
|
||||
|
@ -126,10 +126,10 @@ def top(num_processes=5, interval=3):
|
|||
'''
|
||||
result = []
|
||||
start_usage = {}
|
||||
for pid in psutil.get_pid_list():
|
||||
for pid in psutil.pids():
|
||||
try:
|
||||
process = psutil.Process(pid)
|
||||
user, system = process.get_cpu_times()
|
||||
user, system = process.cpu_times()
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
start_usage[process] = user + system
|
||||
|
@ -137,7 +137,7 @@ def top(num_processes=5, interval=3):
|
|||
usage = set()
|
||||
for process, start in start_usage.items():
|
||||
try:
|
||||
user, system = process.get_cpu_times()
|
||||
user, system = process.cpu_times()
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
now = user + system
|
||||
|
@ -159,9 +159,9 @@ def top(num_processes=5, interval=3):
|
|||
'cpu': {},
|
||||
'mem': {},
|
||||
}
|
||||
for key, value in process.get_cpu_times()._asdict().items():
|
||||
for key, value in process.cpu_times()._asdict().items():
|
||||
info['cpu'][key] = value
|
||||
for key, value in process.get_memory_info()._asdict().items():
|
||||
for key, value in process.memory_info()._asdict().items():
|
||||
info['mem'][key] = value
|
||||
result.append(info)
|
||||
|
||||
|
@ -178,7 +178,7 @@ def get_pid_list():
|
|||
|
||||
salt '*' ps.get_pid_list
|
||||
'''
|
||||
return psutil.get_pid_list()
|
||||
return psutil.pids()
|
||||
|
||||
|
||||
def proc_info(pid, attrs=None):
|
||||
|
@ -538,7 +538,7 @@ def boot_time(time_format=None):
|
|||
except AttributeError:
|
||||
# get_boot_time() has been removed in newer psutil versions, and has
|
||||
# been replaced by boot_time() which provides the same information.
|
||||
b_time = int(psutil.get_boot_time())
|
||||
b_time = int(psutil.boot_time())
|
||||
if time_format:
|
||||
# Load epoch timestamp as a datetime.datetime object
|
||||
b_time = datetime.datetime.fromtimestamp(b_time)
|
||||
|
@ -562,9 +562,9 @@ def network_io_counters(interface=None):
|
|||
salt '*' ps.network_io_counters interface=eth0
|
||||
'''
|
||||
if not interface:
|
||||
return dict(psutil.network_io_counters()._asdict())
|
||||
return dict(psutil.net_io_counters()._asdict())
|
||||
else:
|
||||
stats = psutil.network_io_counters(pernic=True)
|
||||
stats = psutil.net_io_counters(pernic=True)
|
||||
if interface in stats:
|
||||
return dict(stats[interface]._asdict())
|
||||
else:
|
||||
|
@ -604,7 +604,7 @@ def get_users():
|
|||
salt '*' ps.get_users
|
||||
'''
|
||||
try:
|
||||
recs = psutil.get_users()
|
||||
recs = psutil.users()
|
||||
return [dict(x._asdict()) for x in recs]
|
||||
except AttributeError:
|
||||
# get_users is only present in psutil > v0.5.0
|
||||
|
|
100
salt/utils/psutil_compat.py
Normal file
100
salt/utils/psutil_compat.py
Normal file
|
@ -0,0 +1,100 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Version agnostic psutil hack to fully support both old (<2.0) and new (>=2.0)
|
||||
psutil versions.
|
||||
|
||||
The old <1.0 psutil API is dropped in psutil 3.0
|
||||
|
||||
Should be removed once support for psutil <2.0 is dropped. (eg RHEL 6)
|
||||
|
||||
Built off of http://grodola.blogspot.com/2014/01/psutil-20-porting.html
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# No exception handling, as we want ImportError if psutil doesn't exist
|
||||
import psutil
|
||||
|
||||
if psutil.version_info >= (2, 0):
|
||||
from psutil import * # pylint: disable=wildcard-import
|
||||
else:
|
||||
# Import hack to work around bugs in old psutil's
|
||||
# Psuedo "from psutil import *"
|
||||
_globals = globals()
|
||||
for attr in psutil.__all__:
|
||||
_temp = __import__('psutil', globals(), locals(), [attr], -1)
|
||||
try:
|
||||
_globals[attr] = getattr(_temp, attr)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Import functions not in __all__
|
||||
from psutil import disk_partitions # pylint: disable=unused-import
|
||||
from psutil import disk_usage # pylint: disable=unused-import
|
||||
|
||||
# Alias new module functions
|
||||
def boot_time():
|
||||
return psutil.BOOT_TIME
|
||||
|
||||
def cpu_count():
|
||||
return psutil.NUM_CPUS
|
||||
|
||||
# Alias renamed module functions
|
||||
pids = psutil.get_pid_list
|
||||
users = psutil.get_users
|
||||
|
||||
# Deprecated in 1.0.1, but not mentioned in blog post
|
||||
if psutil.version_info < (1, 0, 1):
|
||||
net_io_counters = psutil.network_io_counters()
|
||||
|
||||
class Process(psutil.Process): # pylint: disable=no-init
|
||||
# Reimplement overloaded getters/setters
|
||||
def cpu_affinity(self, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
return self.set_cpu_affinity(*args, **kwargs)
|
||||
else:
|
||||
return self.get_cpu_affinity()
|
||||
|
||||
def ionice(self, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
return self.set_ionice(*args, **kwargs)
|
||||
else:
|
||||
return self.get_ionice()
|
||||
|
||||
def nice(self, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
return self.set_nice(*args, **kwargs)
|
||||
else:
|
||||
return self.get_nice()
|
||||
|
||||
def rlimit(self, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
return self.set_rlimit(*args, **kwargs)
|
||||
else:
|
||||
return self.get_rlimit()
|
||||
|
||||
# Alias renamed Process functions
|
||||
_PROCESS_FUNCTION_MAP = {
|
||||
"children": "get_children",
|
||||
"connections": "get_connections",
|
||||
"cpu_percent": "get_cpu_percent",
|
||||
"cpu_times": "get_cpu_times",
|
||||
"io_counters": "get_io_counters",
|
||||
"memory_info": "get_memory_info",
|
||||
"memory_info_ex": "get_ext_memory_info",
|
||||
"memory_maps": "get_memory_maps",
|
||||
"memory_percent": "get_memory_percent",
|
||||
"num_ctx_switches": "get_num_ctx_switches",
|
||||
"num_fds": "get_num_fds",
|
||||
"num_threads": "get_num_threads",
|
||||
"open_files": "get_open_files",
|
||||
"threads": "get_threads",
|
||||
"cwd": "getcwd",
|
||||
|
||||
}
|
||||
|
||||
for new, old in _PROCESS_FUNCTION_MAP.iteritems():
|
||||
try:
|
||||
setattr(Process, new, psutil.Process.__dict__[old])
|
||||
except KeyError:
|
||||
pass
|
|
@ -16,7 +16,7 @@ HAS_PSUTIL = ps.__virtual__()
|
|||
HAS_PSUTIL_VERSION = False
|
||||
|
||||
if HAS_PSUTIL:
|
||||
import psutil
|
||||
import salt.utils.psutil_compat as psutil
|
||||
from collections import namedtuple
|
||||
|
||||
PSUTIL2 = psutil.version_info >= (2, 0)
|
||||
|
@ -51,7 +51,7 @@ else:
|
|||
STUB_USER) = [None for val in range(9)]
|
||||
|
||||
STUB_PID_LIST = [0, 1, 2, 3]
|
||||
MOCK_PROC = mocked_proc = MagicMock('psutil.Process')
|
||||
MOCK_PROC = mocked_proc = MagicMock('salt.utils.psutil_compat.Process')
|
||||
|
||||
try:
|
||||
import utmp # pylint: disable=W0611
|
||||
|
@ -79,59 +79,59 @@ class PsTestCase(TestCase):
|
|||
MOCK_PROC.name = 'test_mock_proc'
|
||||
MOCK_PROC.pid = 9999999999
|
||||
|
||||
@patch('psutil.get_pid_list', new=MagicMock(return_value=STUB_PID_LIST))
|
||||
@patch('salt.utils.psutil_compat.pids', new=MagicMock(return_value=STUB_PID_LIST))
|
||||
def test_get_pid_list(self):
|
||||
self.assertListEqual(STUB_PID_LIST, ps.get_pid_list())
|
||||
|
||||
@patch('psutil.Process')
|
||||
@patch('salt.utils.psutil_compat.Process')
|
||||
def test_kill_pid(self, send_signal_mock):
|
||||
ps.kill_pid(0, signal=999)
|
||||
self.assertEqual(send_signal_mock.call_args, call(0))
|
||||
|
||||
@patch('psutil.Process.send_signal')
|
||||
@patch('psutil.process_iter', new=MagicMock(return_value=[MOCK_PROC]))
|
||||
@patch('salt.utils.psutil_compat.Process.send_signal')
|
||||
@patch('salt.utils.psutil_compat.process_iter', new=MagicMock(return_value=[MOCK_PROC]))
|
||||
def test_pkill(self, send_signal_mock):
|
||||
mocked_proc.send_signal = MagicMock()
|
||||
test_signal = 1234
|
||||
ps.pkill(_get_proc_name(mocked_proc), signal=test_signal)
|
||||
self.assertEqual(mocked_proc.send_signal.call_args, call(test_signal))
|
||||
|
||||
@patch('psutil.process_iter', new=MagicMock(return_value=[MOCK_PROC]))
|
||||
@patch('salt.utils.psutil_compat.process_iter', new=MagicMock(return_value=[MOCK_PROC]))
|
||||
def test_pgrep(self):
|
||||
self.assertIn(_get_proc_pid(MOCK_PROC), ps.pgrep(_get_proc_name(MOCK_PROC)))
|
||||
|
||||
@patch('psutil.cpu_percent', new=MagicMock(return_value=1))
|
||||
@patch('salt.utils.psutil_compat.cpu_percent', new=MagicMock(return_value=1))
|
||||
def test_cpu_percent(self):
|
||||
self.assertEqual(ps.cpu_percent(), 1)
|
||||
|
||||
@patch('psutil.cpu_times', new=MagicMock(return_value=STUB_CPU_TIMES))
|
||||
@patch('salt.utils.psutil_compat.cpu_times', new=MagicMock(return_value=STUB_CPU_TIMES))
|
||||
def test_cpu_times(self):
|
||||
self.assertDictEqual({'idle': 4, 'nice': 2, 'system': 3, 'user': 1}, ps.cpu_times())
|
||||
|
||||
@skipIf(HAS_PSUTIL_VERSION is False, 'psutil 0.6.0 or greater is required for this test')
|
||||
@patch('psutil.virtual_memory', new=MagicMock(return_value=STUB_VIRT_MEM))
|
||||
@patch('salt.utils.psutil_compat.virtual_memory', new=MagicMock(return_value=STUB_VIRT_MEM))
|
||||
def test_virtual_memory(self):
|
||||
self.assertDictEqual({'used': 500, 'total': 1000, 'available': 500, 'percent': 50, 'free': 500},
|
||||
ps.virtual_memory())
|
||||
|
||||
@skipIf(HAS_PSUTIL_VERSION is False, 'psutil 0.6.0 or greater is required for this test')
|
||||
@patch('psutil.swap_memory', new=MagicMock(return_value=STUB_SWAP_MEM))
|
||||
@patch('salt.utils.psutil_compat.swap_memory', new=MagicMock(return_value=STUB_SWAP_MEM))
|
||||
def test_swap_memory(self):
|
||||
self.assertDictEqual({'used': 500, 'total': 1000, 'percent': 50, 'free': 500, 'sin': 0, 'sout': 0},
|
||||
ps.swap_memory())
|
||||
|
||||
@patch('psutil.disk_partitions', new=MagicMock(return_value=[STUB_DISK_PARTITION]))
|
||||
@patch('salt.utils.psutil_compat.disk_partitions', new=MagicMock(return_value=[STUB_DISK_PARTITION]))
|
||||
def test_disk_partitions(self):
|
||||
self.assertDictEqual(
|
||||
{'device': '/dev/disk0s2', 'mountpoint': '/', 'opts': 'rw,local,rootfs,dovolfs,journaled,multilabel',
|
||||
'fstype': 'hfs'},
|
||||
ps.disk_partitions()[0])
|
||||
|
||||
@patch('psutil.disk_usage', new=MagicMock(return_value=STUB_DISK_USAGE))
|
||||
@patch('salt.utils.psutil_compat.disk_usage', new=MagicMock(return_value=STUB_DISK_USAGE))
|
||||
def test_disk_usage(self):
|
||||
self.assertDictEqual({'used': 500, 'total': 1000, 'percent': 50, 'free': 500}, ps.disk_usage('DUMMY_PATH'))
|
||||
|
||||
@patch('psutil.disk_partitions', new=MagicMock(return_value=[STUB_DISK_PARTITION]))
|
||||
@patch('salt.utils.psutil_compat.disk_partitions', new=MagicMock(return_value=[STUB_DISK_PARTITION]))
|
||||
def test_disk_partition_usage(self):
|
||||
self.assertDictEqual(
|
||||
{'device': '/dev/disk0s2', 'mountpoint': '/', 'opts': 'rw,local,rootfs,dovolfs,journaled,multilabel',
|
||||
|
@ -149,26 +149,26 @@ class PsTestCase(TestCase):
|
|||
## Should only be tested in integration
|
||||
# def test_boot_time(self):
|
||||
# pass
|
||||
@patch('psutil.network_io_counters', new=MagicMock(return_value=STUB_NETWORK_IO))
|
||||
@patch('salt.utils.psutil_compat.net_io_counters', new=MagicMock(return_value=STUB_NETWORK_IO))
|
||||
def test_network_io_counters(self):
|
||||
self.assertDictEqual(
|
||||
{'packets_sent': 500, 'packets_recv': 600, 'bytes_recv': 2000, 'dropout': 4, 'bytes_sent': 1000,
|
||||
'errout': 2, 'errin': 1, 'dropin': 3}, ps.network_io_counters())
|
||||
|
||||
@patch('psutil.disk_io_counters', new=MagicMock(return_value=STUB_DISK_IO))
|
||||
@patch('salt.utils.psutil_compat.disk_io_counters', new=MagicMock(return_value=STUB_DISK_IO))
|
||||
def test_disk_io_counters(self):
|
||||
self.assertDictEqual(
|
||||
{'read_time': 2000, 'write_bytes': 600, 'read_bytes': 500, 'write_time': 3000, 'read_count': 1000,
|
||||
'write_count': 2000}, ps.disk_io_counters())
|
||||
|
||||
@patch('psutil.get_users', new=MagicMock(return_value=[STUB_USER]))
|
||||
@patch('salt.utils.psutil_compat.users', new=MagicMock(return_value=[STUB_USER]))
|
||||
def test_get_users(self):
|
||||
self.assertDictEqual({'terminal': 'ttys000', 'started': 0.0, 'host': 'localhost', 'name': 'bdobbs'},
|
||||
ps.get_users()[0])
|
||||
|
||||
## This is commented out pending discussion on https://github.com/saltstack/salt/commit/2e5c3162ef87cca8a2c7b12ade7c7e1b32028f0a
|
||||
# @skipIf(not HAS_UTMP, "The utmp module must be installed to run test_get_users_utmp()")
|
||||
# @patch('psutil.get_users', new=MagicMock(return_value=None)) # This will force the function to use utmp
|
||||
# @patch('salt.utils.psutil_compat.get_users', new=MagicMock(return_value=None)) # This will force the function to use utmp
|
||||
# def test_get_users_utmp(self):
|
||||
# pass
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue