Commit f0b37366 authored by Tomáš Peterka's avatar Tomáš Peterka

[recipe.wrapper] Add init(-command) and cpu-exclusive into buildout parameters.

-  intial command being run before actual `command` is specified by "init"
-  wrapper can demand exclusive CPU core by "reserve-cpu"
-  "command-line" has alias "command"
-  "wrapper-path" has alias "destination" to be consistent with other recipes
parent 066a340c
...@@ -131,7 +131,7 @@ class GenericBaseRecipe(object): ...@@ -131,7 +131,7 @@ class GenericBaseRecipe(object):
def createWrapper(self, name, command, parameters, comments=[], def createWrapper(self, name, command, parameters, comments=[],
parameters_extra=False, environment=None, parameters_extra=False, environment=None,
pidfile=None pidfile=None, init_command=None, reserve_cpu=False
): ):
""" """
Creates a shell script for process replacement. Creates a shell script for process replacement.
...@@ -139,6 +139,9 @@ class GenericBaseRecipe(object): ...@@ -139,6 +139,9 @@ class GenericBaseRecipe(object):
Takes care of #! line limitation when the wrapped command is a script. Takes care of #! line limitation when the wrapped command is a script.
if pidfile parameter is specified, then it will make the wrapper a singleton, if pidfile parameter is specified, then it will make the wrapper a singleton,
accepting to run only if no other instance is running. accepting to run only if no other instance is running.
:param init_command: str, arbitrary command being run before the actual `command`
:param reserve_cpu: bool, try to reserve one core for the `command`
""" """
lines = [ '#!/bin/sh' ] lines = [ '#!/bin/sh' ]
...@@ -163,6 +166,18 @@ class GenericBaseRecipe(object): ...@@ -163,6 +166,18 @@ class GenericBaseRecipe(object):
fi fi
echo $$ > $pidfile""" % shlex.quote(pidfile))) echo $$ > $pidfile""" % shlex.quote(pidfile)))
if reserve_cpu:
# if the CGROUPS cpuset is available (and prepared by slap format)
# request an exclusive CPU core for this process
lines.append(dedent("""
# put own PID into waiting list for exclusive CPU-core access
echo $$ >> ~/.slapos-cpu-exclusive
"""))
if init_command is not None:
lines.append("")
lines.append(init_command)
lines.append(dedent(''' lines.append(dedent('''
# If the wrapped command uses a shebang, execute the referenced # If the wrapped command uses a shebang, execute the referenced
# executable passing the script path as first argument. # executable passing the script path as first argument.
......
...@@ -31,9 +31,28 @@ import os ...@@ -31,9 +31,28 @@ import os
from slapos.recipe.librecipe import GenericBaseRecipe from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
"""Recipe to create a script from given command and options.
:param str init: shell command to execute before actuall command
:param str command: shell command which launches the intended process
:param str cleanup: shell command executed at the end or in case of SIGTERM/INT/KILL
:param bool safe: controls whether the parameters will be escaped (default false implies escaping)
:param lines wait-for-files: list of files to wait for
:param str pidfile: path to pidfile ensure exclusivity for the process
:param bool remove-pidfile: if pidfile is removed upon exit
:param bool parameters-extra: whether wrapper parameters are passed onto command
"""
def install(self): def install(self):
command_line = shlex.split(self.options['command-line']) command_line = shlex.split(self.options.get('command-line') or self.options.get('command'))
wrapper_path = self.options['wrapper-path'] assert command_line, "Specify either 'command-line' or 'command'"
# be more consistent with the naming across recipies - use "destination" too
wrapper_path = self.options.get('wrapper-path') or self.options.get('destination')
assert wrapper_path, "Specify either 'wrapper-path' or 'destination'"
# optionals bellow
init = self.options.get('init')
reserve_cpu = self.options.get('reserve-cpu', False)
wait_files = self.options.get('wait-for-files') wait_files = self.options.get('wait-for-files')
environment = self.options.get('environment') environment = self.options.get('environment')
parameters_extra = self.options.get('parameters-extra') parameters_extra = self.options.get('parameters-extra')
...@@ -47,6 +66,8 @@ class Recipe(GenericBaseRecipe): ...@@ -47,6 +66,8 @@ class Recipe(GenericBaseRecipe):
parameters=command_line[1:], parameters=command_line[1:],
parameters_extra=parameters_extra, parameters_extra=parameters_extra,
pidfile=pidfile, pidfile=pidfile,
init_command=init,
reserve_cpu=reserve_cpu
)] )]
# More complex needs: create a Python script as wrapper # More complex needs: create a Python script as wrapper
...@@ -76,5 +97,7 @@ class Recipe(GenericBaseRecipe): ...@@ -76,5 +97,7 @@ class Recipe(GenericBaseRecipe):
parameters=[], parameters=[],
parameters_extra=parameters_extra, parameters_extra=parameters_extra,
pidfile=pidfile, pidfile=pidfile,
init_command=init,
reserve_cpu=reserve_cpu
)] )]
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