Commit 28ea60be authored by Julien Muchembled's avatar Julien Muchembled

wrapper: new private-tmpfs option, private-dev-shm deprecated

parent 5118c476
from __future__ import print_function
import errno
import sys
import os
import signal
......@@ -50,7 +51,7 @@ def _libc():
return mount, unshare
def generic_exec(args, extra_environ=None, wait_list=None,
pidfile=None, reserve_cpu=False, private_dev_shm=None,
pidfile=None, reserve_cpu=False, private_tmpfs=(),
#shebang_workaround=False, # XXX: still needed ?
):
args = list(args)
......@@ -83,7 +84,7 @@ def generic_exec(args, extra_environ=None, wait_list=None,
if wait_list:
_wait_files_creation(wait_list)
if private_dev_shm:
if private_tmpfs:
mount, unshare = _libc()
CLONE_NEWNS = 0x00020000
CLONE_NEWUSER = 0x10000000
......@@ -93,7 +94,13 @@ def generic_exec(args, extra_environ=None, wait_list=None,
with open('/proc/self/setgroups', 'wb') as f: f.write('deny')
with open('/proc/self/uid_map', 'wb') as f: f.write('%s %s 1' % (uid, uid))
with open('/proc/self/gid_map', 'wb') as f: f.write('%s %s 1' % (gid, gid))
mount('tmpfs', '/dev/shm', 'tmpfs', 0, 'size=' + private_dev_shm)
for size, path in private_tmpfs:
try:
os.mkdir(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
mount('tmpfs', path, 'tmpfs', 0, 'size=' + size)
if extra_environ:
env = os.environ.copy()
......
......@@ -43,7 +43,8 @@ from six.moves.urllib.parse import urlunparse
import pkg_resources
import zc.buildout
from zc.buildout import easy_install, UserError
from zc.recipe.egg import Egg
from slapos.recipe.librecipe import shlex
......@@ -85,8 +86,7 @@ class GenericBaseRecipe(object):
def getWorkingSet(self):
"""If you want do override the default working set"""
egg = zc.recipe.egg.Egg(self.buildout, 'slapos.cookbook',
self.options.copy())
egg = Egg(self.buildout, 'slapos.cookbook', self.options.copy())
requirements, ws = egg.working_set()
return ws
......@@ -156,10 +156,20 @@ class GenericBaseRecipe(object):
args = itertools.chain(map(repr, args),
map('%s=%r'.__mod__, six.iteritems(kw)))
return zc.buildout.easy_install.scripts(
return easy_install.scripts(
[(filename, module, function)], self._ws, sys.executable,
path, arguments=', '.join(args))[0]
def parsePrivateTmpfs(self):
private_tmpfs = []
for line in (self.options.get('private-tmpfs') or '').splitlines():
if line:
x = line.split(None, 1)
if len(x) != 2:
raise UserError("failed to split %r into size and path" % line)
private_tmpfs.append(tuple(x))
return private_tmpfs
def createWrapper(self, path, args, env=None, **kw):
"""Create a wrapper script for process replacement"""
assert args
......
......@@ -38,7 +38,7 @@ class Recipe(GenericBaseRecipe):
:param lines hash-files: list of buildout-generated files to be checked by hash
:param lines hash-existing-files: list of existing files to be checked by hash
:param str pidfile: path to pidfile ensure exclusivity for the process
:param str private-dev-shm: size of private /dev/shm, using user namespaces
:param lines private-tmpfs: list of "<size> <path>" private tmpfs, using user namespaces
:param bool reserve-cpu: command will ask for an exclusive CPU core
"""
......@@ -72,13 +72,17 @@ class Recipe(GenericBaseRecipe):
raise UserError(
"hash-files must only list files that are generated by buildout:"
"\n " + "\n ".join(self._existing))
args = shlex.split(self.options['command-line'])
wait_files = self.options.get('wait-for-files')
pidfile = self.options.get('pidfile')
private_dev_shm = self.options.get('private-dev-shm')
options = self.options
args = shlex.split(options['command-line'])
wait_files = options.get('wait-for-files')
pidfile = options.get('pidfile')
private_tmpfs = self.parsePrivateTmpfs()
private_dev_shm = options.get('private-dev-shm') # BBB
if private_dev_shm:
private_tmpfs.append((private_dev_shm, '/dev/shm'))
environment = {}
for line in (self.options.get('environment') or '').splitlines():
for line in (options.get('environment') or '').splitlines():
line = line.strip()
if line:
k, v = line.split('=', 1)
......@@ -89,9 +93,9 @@ class Recipe(GenericBaseRecipe):
kw['wait_list'] = wait_files.split()
if pidfile:
kw['pidfile'] = pidfile
if private_dev_shm:
kw['private_dev_shm'] = private_dev_shm
if self.isTrueValue(self.options.get('reserve-cpu')):
if private_tmpfs:
kw['private_tmpfs'] = private_tmpfs
if self.isTrueValue(options.get('reserve-cpu')):
kw['reserve_cpu'] = True
return self.createWrapper(self.getWrapperPath(),
args, environment, **kw)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment