Merge "processutils: add support for missing process limits"
This commit is contained in:
commit
6bae2be9ba
@ -26,8 +26,15 @@ USAGE_PROGRAM = ('%s -m oslo_concurrency.prlimit'
|
|||||||
RESOURCES = (
|
RESOURCES = (
|
||||||
# argparse argument => resource
|
# argparse argument => resource
|
||||||
('as', resource.RLIMIT_AS),
|
('as', resource.RLIMIT_AS),
|
||||||
|
('core', resource.RLIMIT_CORE),
|
||||||
|
('cpu', resource.RLIMIT_CPU),
|
||||||
|
('data', resource.RLIMIT_DATA),
|
||||||
|
('fsize', resource.RLIMIT_FSIZE),
|
||||||
|
('memlock', resource.RLIMIT_MEMLOCK),
|
||||||
('nofile', resource.RLIMIT_NOFILE),
|
('nofile', resource.RLIMIT_NOFILE),
|
||||||
|
('nproc', resource.RLIMIT_NPROC),
|
||||||
('rss', resource.RLIMIT_RSS),
|
('rss', resource.RLIMIT_RSS),
|
||||||
|
('stack', resource.RLIMIT_STACK),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -35,10 +42,24 @@ def parse_args():
|
|||||||
parser = argparse.ArgumentParser(description='prlimit', prog=USAGE_PROGRAM)
|
parser = argparse.ArgumentParser(description='prlimit', prog=USAGE_PROGRAM)
|
||||||
parser.add_argument('--as', type=int,
|
parser.add_argument('--as', type=int,
|
||||||
help='Address space limit in bytes')
|
help='Address space limit in bytes')
|
||||||
|
parser.add_argument('--core', type=int,
|
||||||
|
help='Core file size limit in bytes')
|
||||||
|
parser.add_argument('--cpu', type=int,
|
||||||
|
help='CPU time limit in seconds')
|
||||||
|
parser.add_argument('--data', type=int,
|
||||||
|
help='Data size limit in bytes')
|
||||||
|
parser.add_argument('--fsize', type=int,
|
||||||
|
help='File size limit in bytes')
|
||||||
|
parser.add_argument('--memlock', type=int,
|
||||||
|
help='Locked memory limit in bytes')
|
||||||
parser.add_argument('--nofile', type=int,
|
parser.add_argument('--nofile', type=int,
|
||||||
help='Maximum number of open files')
|
help='Maximum number of open files')
|
||||||
|
parser.add_argument('--nproc', type=int,
|
||||||
|
help='Maximum number of processes')
|
||||||
parser.add_argument('--rss', type=int,
|
parser.add_argument('--rss', type=int,
|
||||||
help='Maximum Resident Set Size (RSS) in bytes')
|
help='Maximum Resident Set Size (RSS) in bytes')
|
||||||
|
parser.add_argument('--stack', type=int,
|
||||||
|
help='Stack size limit in bytes')
|
||||||
parser.add_argument('program',
|
parser.add_argument('program',
|
||||||
help='Program (absolute path)')
|
help='Program (absolute path)')
|
||||||
parser.add_argument('program_args', metavar="arg", nargs='...',
|
parser.add_argument('program_args', metavar="arg", nargs='...',
|
||||||
|
@ -134,16 +134,36 @@ class ProcessLimits(object):
|
|||||||
Attributes:
|
Attributes:
|
||||||
|
|
||||||
* address_space: Address space limit in bytes
|
* address_space: Address space limit in bytes
|
||||||
* number_files: Maximum number of open files.
|
* core_file_size: Core file size limit in bytes
|
||||||
|
* cpu_time: CPU time limit in seconds
|
||||||
|
* data_size: Data size limit in bytes
|
||||||
|
* file_size: File size limit in bytes
|
||||||
|
* memory_locked: Locked memory limit in bytes
|
||||||
|
* number_files: Maximum number of open files
|
||||||
|
* number_processes: Maximum number of processes
|
||||||
* resident_set_size: Maximum Resident Set Size (RSS) in bytes
|
* resident_set_size: Maximum Resident Set Size (RSS) in bytes
|
||||||
|
* stack_size: Stack size limit in bytes
|
||||||
|
|
||||||
This object can be used for the *prlimit* parameter of :func:`execute`.
|
This object can be used for the *prlimit* parameter of :func:`execute`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_LIMITS = {
|
||||||
|
"address_space": "--as",
|
||||||
|
"core_file_size": "--core",
|
||||||
|
"cpu_time": "--cpu",
|
||||||
|
"data_size": "--data",
|
||||||
|
"file_size": "--fsize",
|
||||||
|
"memory_locked": "--memlock",
|
||||||
|
"number_files": "--nofile",
|
||||||
|
"number_processes": "--nproc",
|
||||||
|
"resident_set_size": "--rss",
|
||||||
|
"stack_size": "--stack",
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.address_space = kw.pop('address_space', None)
|
for limit in self._LIMITS.keys():
|
||||||
self.number_files = kw.pop('number_files', None)
|
setattr(self, limit, kw.pop(limit, None))
|
||||||
self.resident_set_size = kw.pop('resident_set_size', None)
|
|
||||||
if kw:
|
if kw:
|
||||||
raise ValueError("invalid limits: %s"
|
raise ValueError("invalid limits: %s"
|
||||||
% ', '.join(sorted(kw.keys())))
|
% ', '.join(sorted(kw.keys())))
|
||||||
@ -151,12 +171,10 @@ class ProcessLimits(object):
|
|||||||
def prlimit_args(self):
|
def prlimit_args(self):
|
||||||
"""Create a list of arguments for the prlimit command line."""
|
"""Create a list of arguments for the prlimit command line."""
|
||||||
args = []
|
args = []
|
||||||
if self.address_space:
|
for limit in self._LIMITS.keys():
|
||||||
args.append('--as=%s' % self.address_space)
|
val = getattr(self, limit)
|
||||||
if self.number_files:
|
if val is not None:
|
||||||
args.append('--nofile=%s' % self.number_files)
|
args.append("%s=%s" % (self._LIMITS[limit], val))
|
||||||
if self.resident_set_size:
|
|
||||||
args.append('--rss=%s' % self.resident_set_size)
|
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
@ -752,7 +752,7 @@ class PrlimitTestCase(test_base.BaseTestCase):
|
|||||||
# Create a new soft limit for a resource, lower than the current
|
# Create a new soft limit for a resource, lower than the current
|
||||||
# soft limit.
|
# soft limit.
|
||||||
soft_limit, hard_limit = resource.getrlimit(res)
|
soft_limit, hard_limit = resource.getrlimit(res)
|
||||||
if soft_limit < 0:
|
if soft_limit <= 0:
|
||||||
soft_limit = default_limit
|
soft_limit = default_limit
|
||||||
else:
|
else:
|
||||||
soft_limit -= substract
|
soft_limit -= substract
|
||||||
@ -790,6 +790,31 @@ class PrlimitTestCase(test_base.BaseTestCase):
|
|||||||
prlimit = self.limit_address_space()
|
prlimit = self.limit_address_space()
|
||||||
self.check_limit(prlimit, 'RLIMIT_AS', prlimit.address_space)
|
self.check_limit(prlimit, 'RLIMIT_AS', prlimit.address_space)
|
||||||
|
|
||||||
|
def test_core_size(self):
|
||||||
|
size = self.soft_limit(resource.RLIMIT_CORE, 1, 1024)
|
||||||
|
prlimit = processutils.ProcessLimits(core_file_size=size)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_CORE', prlimit.core_file_size)
|
||||||
|
|
||||||
|
def test_cpu_time(self):
|
||||||
|
time = self.soft_limit(resource.RLIMIT_CPU, 1, 1024)
|
||||||
|
prlimit = processutils.ProcessLimits(cpu_time=time)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_CPU', prlimit.cpu_time)
|
||||||
|
|
||||||
|
def test_data_size(self):
|
||||||
|
max_memory = self.memory_limit(resource.RLIMIT_DATA)
|
||||||
|
prlimit = processutils.ProcessLimits(data_size=max_memory)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_DATA', max_memory)
|
||||||
|
|
||||||
|
def test_file_size(self):
|
||||||
|
size = self.soft_limit(resource.RLIMIT_FSIZE, 1, 1024)
|
||||||
|
prlimit = processutils.ProcessLimits(file_size=size)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_FSIZE', prlimit.file_size)
|
||||||
|
|
||||||
|
def test_memory_locked(self):
|
||||||
|
max_memory = self.memory_limit(resource.RLIMIT_MEMLOCK)
|
||||||
|
prlimit = processutils.ProcessLimits(memory_locked=max_memory)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_MEMLOCK', max_memory)
|
||||||
|
|
||||||
def test_resident_set_size(self):
|
def test_resident_set_size(self):
|
||||||
max_memory = self.memory_limit(resource.RLIMIT_RSS)
|
max_memory = self.memory_limit(resource.RLIMIT_RSS)
|
||||||
prlimit = processutils.ProcessLimits(resident_set_size=max_memory)
|
prlimit = processutils.ProcessLimits(resident_set_size=max_memory)
|
||||||
@ -800,6 +825,16 @@ class PrlimitTestCase(test_base.BaseTestCase):
|
|||||||
prlimit = processutils.ProcessLimits(number_files=nfiles)
|
prlimit = processutils.ProcessLimits(number_files=nfiles)
|
||||||
self.check_limit(prlimit, 'RLIMIT_NOFILE', nfiles)
|
self.check_limit(prlimit, 'RLIMIT_NOFILE', nfiles)
|
||||||
|
|
||||||
|
def test_number_processes(self):
|
||||||
|
nprocs = self.soft_limit(resource.RLIMIT_NPROC, 1, 65535)
|
||||||
|
prlimit = processutils.ProcessLimits(number_processes=nprocs)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_NPROC', nprocs)
|
||||||
|
|
||||||
|
def test_stack_size(self):
|
||||||
|
max_memory = self.memory_limit(resource.RLIMIT_STACK)
|
||||||
|
prlimit = processutils.ProcessLimits(stack_size=max_memory)
|
||||||
|
self.check_limit(prlimit, 'RLIMIT_STACK', max_memory)
|
||||||
|
|
||||||
def test_unsupported_prlimit(self):
|
def test_unsupported_prlimit(self):
|
||||||
self.assertRaises(ValueError, processutils.ProcessLimits, xxx=33)
|
self.assertRaises(ValueError, processutils.ProcessLimits, xxx=33)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user