Commit 342b5393 authored by Aurélien Vermylen's avatar Aurélien Vermylen

Merge branch 'master' into clearroad

parents c44e2f89 503a278b
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
extends = extends =
../coreutils/buildout.cfg ../coreutils/buildout.cfg
../patch/buildout.cfg ../patch/buildout.cfg
../randomsleep/buildout.cfg
parts = dcron-output parts = dcron-output
...@@ -18,6 +19,7 @@ make-options = ...@@ -18,6 +19,7 @@ make-options =
post-make-hook = ${:_profile_base_location_}/dcron-hooks.py#860e914dff4108b47565965fe5ebc7b5:post_make_hook post-make-hook = ${:_profile_base_location_}/dcron-hooks.py#860e914dff4108b47565965fe5ebc7b5:post_make_hook
environment = environment =
PATH=${patch:location}/bin:%(PATH)s PATH=${patch:location}/bin:%(PATH)s
randomsleep_install = ${randomsleep:location}
[dcron-output] [dcron-output]
# Shared binary location to ease migration # Shared binary location to ease migration
......
...@@ -7,14 +7,15 @@ extends = ...@@ -7,14 +7,15 @@ extends =
../bzip2/buildout.cfg ../bzip2/buildout.cfg
../zlib/buildout.cfg ../zlib/buildout.cfg
../bzip2/buildout.cfg ../bzip2/buildout.cfg
../gperf/buildout.cfg
parts = parts =
fontconfig fontconfig
[fontconfig] [fontconfig]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://fontconfig.org/release/fontconfig-2.12.1.tar.bz2 url = http://fontconfig.org/release/fontconfig-2.12.6.tar.bz2
md5sum = b5af5a423ee3b5cfc34846838963c058 md5sum = 733f5e2371ca77b69707bd7b30cc2163
pkg_config_depends = ${freetype:pkg_config_depends}:${freetype:location}/lib/pkgconfig:${libxml2:location}/lib/pkgconfig pkg_config_depends = ${freetype:pkg_config_depends}:${freetype:location}/lib/pkgconfig:${libxml2:location}/lib/pkgconfig
# XXX-Cedric : should we use --with-add-fonts={somefont:location}/share,{someotherfont:location}/share? # XXX-Cedric : should we use --with-add-fonts={somefont:location}/share,{someotherfont:location}/share?
configure-options = configure-options =
...@@ -23,7 +24,7 @@ configure-options = ...@@ -23,7 +24,7 @@ configure-options =
--enable-libxml2 --enable-libxml2
--with-default-fonts=${fonts:location} --with-default-fonts=${fonts:location}
environment = environment =
PATH=${pkgconfig:location}/bin:%(PATH)s PATH=${pkgconfig:location}/bin:${gperf:location}/bin:%(PATH)s
PKG_CONFIG_PATH=${:pkg_config_depends} PKG_CONFIG_PATH=${:pkg_config_depends}
CPPFLAGS=-I${zlib:location}/include -I${bzip2:location}/include CPPFLAGS=-I${zlib:location}/include -I${bzip2:location}/include
LDFLAGS=-L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib -L${bzip2:location}/lib -Wl,-rpath=${bzip2:location}/lib LDFLAGS=-L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib -L${bzip2:location}/lib -Wl,-rpath=${bzip2:location}/lib
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Mostly required to support languages different than C or C++ # Mostly required to support languages different than C or C++
[buildout] [buildout]
extends = extends =
../gettext/buildout.cfg
../gmp/buildout.cfg ../gmp/buildout.cfg
../perl/buildout.cfg ../perl/buildout.cfg
../tar/buildout.cfg ../tar/buildout.cfg
...@@ -32,7 +33,7 @@ configure-options = ...@@ -32,7 +33,7 @@ configure-options =
--with-as=${binutils:location}/bin/as --with-as=${binutils:location}/bin/as
environment = environment =
LDFLAGS=-Wl,-rpath=${gmp:location}/lib -Wl,-rpath=${isl:location}/lib -Wl,-rpath=${mpc:location}/lib -Wl,-rpath=${mpfr:location}/lib LDFLAGS=-Wl,-rpath=${gmp:location}/lib -Wl,-rpath=${isl:location}/lib -Wl,-rpath=${mpc:location}/lib -Wl,-rpath=${mpfr:location}/lib
PATH=${binutils:location}/bin:${perl:location}/bin:${tar:location}/bin:%(PATH)s PATH=${binutils:location}/bin:${gettext:location}/bin:${perl:location}/bin:${tar:location}/bin:%(PATH)s
[gcc-minimal] [gcc-minimal]
<= gcc-common <= gcc-common
......
...@@ -34,8 +34,8 @@ make-targets= cd src && ./make.bash && cp -alf .. ${:location} ...@@ -34,8 +34,8 @@ make-targets= cd src && ./make.bash && cp -alf .. ${:location}
[golang18] [golang18]
<= golang-common <= golang-common
url = https://storage.googleapis.com/golang/go1.8.3.src.tar.gz url = https://dl.google.com/go/go1.8.7.src.tar.gz
md5sum = 64e9380e07bba907e26a00cf5fcbe77e md5sum = c61cfe9c85e7d42f903d3fe146d7cde6
# go1.8 needs go1.4 to bootstrap # go1.8 needs go1.4 to bootstrap
environment-extra = environment-extra =
...@@ -43,8 +43,8 @@ environment-extra = ...@@ -43,8 +43,8 @@ environment-extra =
[golang19] [golang19]
<= golang-common <= golang-common
url = https://storage.googleapis.com/golang/go1.9.2.src.tar.gz url = https://dl.google.com/go/go1.9.4.src.tar.gz
md5sum = 44105c865a1a810464df79233a05a568 md5sum = 6816441fd6680c63865cdd5cb8bc1960
# go1.9 needs go1.4 to bootstrap # go1.9 needs go1.4 to bootstrap
environment-extra = environment-extra =
...@@ -63,6 +63,11 @@ environment-extra = ...@@ -63,6 +63,11 @@ environment-extra =
# lab.nexedi.com/kirr/neo/go/... \ # lab.nexedi.com/kirr/neo/go/... \
# github.com/pkg/profile \ # github.com/pkg/profile \
# golang.org/x/perf/cmd/benchstat # golang.org/x/perf/cmd/benchstat
#
# it is possible to specify Go build flags used for compilation e.g. this way:
#
# [gowork]
# buildflags = -race
[gowork] [gowork]
directory = ${buildout:directory}/go.work directory = ${buildout:directory}/go.work
src = ${:directory}/src src = ${:directory}/src
...@@ -72,6 +77,9 @@ depends = ${gowork.goinstall:recipe} ...@@ -72,6 +77,9 @@ depends = ${gowork.goinstall:recipe}
# go version used for the workspace (possible to override in applications) # go version used for the workspace (possible to override in applications)
golang = ${golang19:location} golang = ${golang19:location}
# no special build flags by default
buildflags =
# everything is done by dependent parts # everything is done by dependent parts
recipe = plone.recipe.command recipe = plone.recipe.command
command = : command = :
...@@ -100,7 +108,7 @@ stop-on-error = true ...@@ -100,7 +108,7 @@ stop-on-error = true
# clients should put package list to install to gowork:install ("..." requests installing everything) # clients should put package list to install to gowork:install ("..." requests installing everything)
[gowork.goinstall] [gowork.goinstall]
recipe = plone.recipe.command recipe = plone.recipe.command
command = bash -c ". ${gowork:env.sh} && go install -v ${gowork:install}" command = bash -c ". ${gowork:env.sh} && go install ${gowork:buildflags} -v ${gowork:install}"
update-command = ${:command} update-command = ${:command}
stop-on-error = true stop-on-error = true
...@@ -115,7 +123,7 @@ git-executable = ${git:location}/bin/git ...@@ -115,7 +123,7 @@ git-executable = ${git:location}/bin/git
# 3) provide repository (which is not the same as importpath in general case) # 3) provide repository (which is not the same as importpath in general case)
# #
# the list of go packages for a go workspace state can be automatically # the list of go packages for a go workspace state can be automatically
# generated with the help of go-pkg-snapshot tool. # generated with the help of gowork-snapshot tool.
[go-git-package] [go-git-package]
<= git-repository <= git-repository
location = ${gowork:src}/${:go.importpath} location = ${gowork:src}/${:go.importpath}
...@@ -25,9 +25,16 @@ gogit_list() { ...@@ -25,9 +25,16 @@ gogit_list() {
# git_upstream_url <repo> - show current branch upstream URL # git_upstream_url <repo> - show current branch upstream URL
git_upstream_url() { git_upstream_url() {
repo=$1 repo=$1
head="`git -C $repo symbolic-ref --short HEAD`" # current branch - e.g. "t" head="`git -C $repo symbolic-ref -q --short HEAD`" # current branch - e.g. "master"
remote="`git -C $repo config --get branch.$head.remote`" # upstream name, e.g. "kirr" if [ -z $head ] ; then
url="`git -C $repo config --get remote.$remote.url`" # upstream URL remote="origin" # If we are in detached HEAD, assume the upstream name is origin
else
remote="`git -C $repo config --get branch.$head.remote`" # upstream name, e.g. "origin"
fi
url="`git -C $repo config --get remote.$remote.url`" # upstream URL
if [ -z $url ] ; then
echo "ERROR: Failed to guess upstream url from $repo" 1>&2
fi
echo "$url" echo "$url"
} }
...@@ -59,5 +66,5 @@ while read pkg url rev; do ...@@ -59,5 +66,5 @@ while read pkg url rev; do
echo "<= go-git-package" echo "<= go-git-package"
echo "go.importpath = $pkg" echo "go.importpath = $pkg"
echo "repository = $url" echo "repository = $url"
echo "revision = $rev" echo "revision = $rev"
done done
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
extends = extends =
../hdf5/buildout.cfg ../hdf5/buildout.cfg
../cython/buildout.cfg ../cython/buildout.cfg
../numpy/buildout.cfg
parts = parts =
h5py h5py
...@@ -12,7 +13,9 @@ CPPFLAGS = -I${hdf5:location}/include ...@@ -12,7 +13,9 @@ CPPFLAGS = -I${hdf5:location}/include
[h5py] [h5py]
recipe = zc.recipe.egg:custom recipe = zc.recipe.egg:custom
egg = h5py egg = h5py
setup-eggs = ${cython:egg} setup-eggs =
${cython:egg}
${numpy:egg}
include-dirs = include-dirs =
${hdf5:location}/include ${hdf5:location}/include
library-dirs = library-dirs =
......
...@@ -11,8 +11,8 @@ parts = ...@@ -11,8 +11,8 @@ parts =
[libxml2] [libxml2]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://xmlsoft.org/sources/libxml2-2.9.5.tar.gz url = http://xmlsoft.org/sources/libxml2-2.9.7.tar.gz
md5sum = 5ce0da9bdaa267b40c4ca36d35363b8b md5sum = 896608641a08b465098a40ddf51cefba
configure-options = configure-options =
--disable-static --disable-static
--without-python --without-python
......
...@@ -7,8 +7,8 @@ parts = ...@@ -7,8 +7,8 @@ parts =
libxslt libxslt
[libxslt] [libxslt]
url = ftp://xmlsoft.org/libxslt/libxslt-1.1.30.tar.gz url = ftp://xmlsoft.org/libxslt/libxslt-1.1.32.tar.gz
md5sum = 70becbbcb1dad55f14de0b84171b91d5 md5sum = 1fc72f98e98bf4443f1651165f3aa146
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
configure-options = configure-options =
--disable-static --disable-static
...@@ -20,5 +20,3 @@ configure-options = ...@@ -20,5 +20,3 @@ configure-options =
environment = environment =
CPPFLAGS=-I${zlib:location}/include CPPFLAGS=-I${zlib:location}/include
LDFLAGS=-L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib LDFLAGS=-L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib
LIBXML_CFLAGS=-I${libxml2:location}/include
LIBXML_LIBS=-L${libxml2:location}/lib -Wl,-rpath=${libxml2:location}/lib
...@@ -27,8 +27,8 @@ parts = ...@@ -27,8 +27,8 @@ parts =
[mariadb] [mariadb]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = https://downloads.mariadb.org/f/mariadb-${:version}/source/mariadb-${:version}.tar.gz/from/http%3A//fr.mirror.babylon.network/mariadb/?serve url = https://downloads.mariadb.org/f/mariadb-${:version}/source/mariadb-${:version}.tar.gz/from/http%3A//fr.mirror.babylon.network/mariadb/?serve
version = 10.1.29 version = 10.1.31
md5sum = 6d2cc6b0f8c5c7525e08aaddad8dca96 md5sum = 14ab0398c019eb531bc29f2c437ccb51
patch-options = -p0 patch-options = -p0
patches = patches =
${:_profile_base_location_}/mariadb_10.1.21_create_system_tables__no_test.patch#3c76aa9564a162f13aced7c0a3f783b3 ${:_profile_base_location_}/mariadb_10.1.21_create_system_tables__no_test.patch#3c76aa9564a162f13aced7c0a3f783b3
......
# Do not extend any file that touch buildout:parts. # Do not extend any file that touch buildout:parts.
[mariadb] [mariadb]
version = 10.2.11 version = 10.2.13
md5sum = 954088299fe5f11b4fda3b540558adbd md5sum = 20c61bd4059ba287e54cfb2862bae81d
stable-patches = stable-patches =
configure-options += configure-options +=
# force build of TokuDB due to a regression in 10.2.11
-DTOKUDB_OK=1
-DCMAKE_C_COMPILER=${gcc:location}/bin/gcc -DCMAKE_C_COMPILER=${gcc:location}/bin/gcc
-DCMAKE_CXX_COMPILER=${gcc:location}/bin/g++ -DCMAKE_CXX_COMPILER=${gcc:location}/bin/g++
extra_cflags = -I${zstd:location}/include extra_cflags = -I${zstd:location}/include
......
...@@ -18,6 +18,7 @@ patch-options = -p0 ...@@ -18,6 +18,7 @@ patch-options = -p0
patch-binary = ${patch:location}/bin/patch patch-binary = ${patch:location}/bin/patch
patches = patches =
http://nginx.org/download/patch.2017.ranges.txt#40bf9f37c881cb3b10cfefd84ca92f6a http://nginx.org/download/patch.2017.ranges.txt#40bf9f37c881cb3b10cfefd84ca92f6a
${:_profile_base_location_}/fix-gcc7-implicit-fallthrough-errors.patch
[nginx] [nginx]
<= nginx-common <= nginx-common
......
commit 8449f750e62cd229026e9df3bd023ec7e073a7d4
Author: Maxim Dounin <mdounin@mdounin.ru>
Date: Thu Apr 27 16:57:18 2017 +0300
Added missing "fall through" comments (ticket #1259).
Found by gcc7 (-Wimplicit-fallthrough).
diff --git src/core/ngx_murmurhash.c src/core/ngx_murmurhash.c
index c31e0e03..5ade658d 100644
--- src/core/ngx_murmurhash.c
+++ src/core/ngx_murmurhash.c
@@ -35,8 +35,10 @@ ngx_murmur_hash2(u_char *data, size_t len)
switch (len) {
case 3:
h ^= data[2] << 16;
+ /* fall through */
case 2:
h ^= data[1] << 8;
+ /* fall through */
case 1:
h ^= data[0];
h *= 0x5bd1e995;
diff --git src/http/ngx_http_parse.c src/http/ngx_http_parse.c
index 36220fdc..e8e51563 100644
--- src/http/ngx_http_parse.c
+++ src/http/ngx_http_parse.c
@@ -1396,6 +1396,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
goto done;
case '+':
r->plus_in_uri = 1;
+ /* fall through */
default:
state = sw_usual;
*u++ = ch;
@@ -1437,6 +1438,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
goto done;
case '+':
r->plus_in_uri = 1;
+ /* fall through */
default:
state = sw_usual;
*u++ = ch;
@@ -1484,6 +1486,7 @@ ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
goto done;
case '+':
r->plus_in_uri = 1;
+ /* fall through */
default:
state = sw_usual;
*u++ = ch;
diff --git src/os/unix/ngx_process.c src/os/unix/ngx_process.c
index dd50b5ca..993c032a 100644
--- src/os/unix/ngx_process.c
+++ src/os/unix/ngx_process.c
@@ -413,6 +413,7 @@ ngx_signal_handler(int signo, siginfo_t *siginfo, void *ucontext)
break;
}
ngx_debug_quit = 1;
+ /* fall through */
case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
ngx_quit = 1;
action = ", shutting down";
...@@ -32,8 +32,8 @@ setup-eggs = ...@@ -32,8 +32,8 @@ setup-eggs =
${matplotlib:egg} ${matplotlib:egg}
${pillow-python:egg} ${pillow-python:egg}
patches = patches =
${:_profile_base_location_}/ocropy.patch ${:_profile_base_location_}/ocropy.patch#dd7a02e1e63ed9df68e3a539b3e919eb
patch-options = -p0 patch-options = -p1
patch-binary = ${patch:location}/bin/patch patch-binary = ${patch:location}/bin/patch
environment = ocropy-env environment = ocropy-env
find-links = https://github.com/tmbdev/ocropy/tarball/4efbddca22bb2f0c639af0694e7a1386f2f097b5/ocropy-1.0.tar.gz find-links = https://github.com/tmbdev/ocropy/tarball/4efbddca22bb2f0c639af0694e7a1386f2f097b5/ocropy-1.0.tar.gz
......
diff --git ocrolib/__init__.py ocrolib/__init__.py From 1bb1546b12b0c08b1b32b293207de2d58d43ff1c Mon Sep 17 00:00:00 2001
From: Francois Le Corre <francois.lecorre@nexedi.com>
Date: Thu, 6 Apr 2017 11:32:27 +0200
Subject: [PATCH] WIP
- New OCROPY_MODEL_PATH environment variable to specify the position of models
- Import for the first time a module that compiles C code from python,
allowing us to have the static library built before runtime and
preventing us from using gcc through zope.
---
ocrolib/__init__.py | 3 ++-
ocrolib/common.py | 7 ++++---
ocrolib/native.py | 1 +
setup.py | 15 ++++++++++++---
4 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/ocrolib/__init__.py b/ocrolib/__init__.py
index 1e0d627..81e85fb 100644 index 1e0d627..81e85fb 100644
--- ocrolib/__init__.py --- a/ocrolib/__init__.py
+++ ocrolib/__init__.py +++ b/ocrolib/__init__.py
@@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
__all__ = [ __all__ = [
"binnednn","cairoextras","common","components","dbtables", "binnednn","cairoextras","common","components","dbtables",
...@@ -11,18 +27,18 @@ index 1e0d627..81e85fb 100644 ...@@ -11,18 +27,18 @@ index 1e0d627..81e85fb 100644
] ]
################################################################ ################################################################
@@ -9,5 +9,6 @@ __all__ = [ @@ -9,5 +9,6 @@
################################################################ ################################################################
import default import default
+from psegutils import * +from psegutils import *
from common import * from common import *
from default import traceback as trace from default import traceback as trace
diff --git ocrolib/common.py ocrolib/common.py diff --git a/ocrolib/common.py b/ocrolib/common.py
index 27c0f26..14f088f 100644 index 27c0f26..14f088f 100644
--- ocrolib/common.py --- a/ocrolib/common.py
+++ ocrolib/common.py +++ b/ocrolib/common.py
@@ -14,6 +14,7 @@ import unicodedata @@ -14,6 +14,7 @@
import inspect import inspect
import glob import glob
import cPickle import cPickle
...@@ -38,7 +54,7 @@ index 27c0f26..14f088f 100644 ...@@ -38,7 +54,7 @@ index 27c0f26..14f088f 100644
def load_object(fname,zip=0,nofind=0,verbose=0): def load_object(fname,zip=0,nofind=0,verbose=0):
"""Loads an object from disk. By default, this handles zipped files """Loads an object from disk. By default, this handles zipped files
and searches in the usual places for OCRopus. It also handles some and searches in the usual places for OCRopus. It also handles some
@@ -439,8 +441,7 @@ def load_object(fname,zip=0,nofind=0,verbose=0): @@ -439,8 +441,7 @@ class names that have changed."""
if zip==0 and fname.endswith(".gz"): if zip==0 and fname.endswith(".gz"):
zip = 1 zip = 1
if zip>0: if zip>0:
...@@ -57,10 +73,10 @@ index 27c0f26..14f088f 100644 ...@@ -57,10 +73,10 @@ index 27c0f26..14f088f 100644
possible_prefixes.append("/usr/local/share/ocropus") possible_prefixes.append("/usr/local/share/ocropus")
diff --git ocrolib/native.py ocrolib/native.py diff --git a/ocrolib/native.py b/ocrolib/native.py
index b7a207f..240450b 100644 index b7a207f..240450b 100644
--- ocrolib/native.py --- a/ocrolib/native.py
+++ ocrolib/native.py +++ b/ocrolib/native.py
@@ -44,6 +44,7 @@ class CompileError(Exception): @@ -44,6 +44,7 @@ class CompileError(Exception):
def compile_and_find(c_string,prefix=".pynative",opt="-g -O4",libs="-lm", def compile_and_find(c_string,prefix=".pynative",opt="-g -O4",libs="-lm",
...@@ -69,22 +85,22 @@ index b7a207f..240450b 100644 ...@@ -69,22 +85,22 @@ index b7a207f..240450b 100644
if not os.path.exists(prefix): if not os.path.exists(prefix):
os.mkdir(prefix) os.mkdir(prefix)
m = hashlib.md5() m = hashlib.md5()
diff --git setup.py setup.py diff --git a/setup.py b/setup.py
index 2ec5832..6697b12 100644 index 2ec5832..0ad4d85 100644
--- setup.py --- a/setup.py
+++ setup.py +++ b/setup.py
@@ -10,7 +10,9 @@ assert sys.version_info[0]==2 and sys.version_info[1]>=7,\ @@ -10,7 +10,9 @@
from distutils.core import setup #, Extension, Command from distutils.core import setup #, Extension, Command
#from distutils.command.install_data import install_data #from distutils.command.install_data import install_data
-if not os.path.exists("models/en-default.pyrnn.gz"): -if not os.path.exists("models/en-default.pyrnn.gz"):
+models = os.environ.get('OCROPY_MODEL_PATH', '').split(':') or \ +models = os.environ.get('OCROPY_MODEL_PATH')
+ [c for c in glob.glob("models/*pyrnn.gz")] +models = models.split(':') if models else glob.glob("models/*pyrnn.gz")
+if not models: +if not models:
print() print()
print("You should download the default model 'en-default.pyrnn.gz'") print("You should download the default model 'en-default.pyrnn.gz'")
print("and put it into ./models.") print("and put it into ./models.")
@@ -18,16 +20,23 @@ if not os.path.exists("models/en-default.pyrnn.gz"): @@ -18,16 +20,23 @@
print("Check https://github.com/tmbdev/ocropy for the location") print("Check https://github.com/tmbdev/ocropy for the location")
print("of model files.") print("of model files.")
print() print()
...@@ -110,3 +126,6 @@ index 2ec5832..6697b12 100644 ...@@ -110,3 +126,6 @@ index 2ec5832..6697b12 100644
+ data_files= [('share/ocropus', models), ("", ["LICENSE"])], + data_files= [('share/ocropus', models), ("", ["LICENSE"])],
scripts = scripts, scripts = scripts,
) )
--
2.14.1
From efa86aa5ad5b89ec329b3cde288cb119efb21c89 Mon Sep 17 00:00:00 2001
From: Kirill Smelkov <kirr@nexedi.com>
Date: Thu, 06 Jul 2017 21:15:31 +0200
Subject: [PATCH] asyncore: switch default to use poll instead of select
Recently we started to get the following errors on a Wendelin production
instance:
File ".../bin/runzope", line 211, in <module>
sys.exit(Zope2.Startup.run.run())
File ".../eggs/Zope2-2.13.24-py2.7.egg/Zope2/Startup/run.py", line 26, in run
starter.run()
File ".../eggs/Zope2-2.13.24-py2.7.egg/Zope2/Startup/__init__.py", line 111, in run
Lifetime.loop()
File ".../eggs/Zope2-2.13.24-py2.7.egg/Lifetime/__init__.py", line 43, in loop
lifetime_loop()
File ".../eggs/Zope2-2.13.24-py2.7.egg/Lifetime/__init__.py", line 53, in lifetime_loop
asyncore.poll(timeout, map)
File ".../parts/python2.7/lib/python2.7/asyncore.py", line 145, in poll
r, w, e = select.select(r, w, e, timeout)
ValueError: filedescriptor out of range in select()
Initially we thought the reason here is that number of file descriptors this
process uses goes beyond allowed limit (65K open files on that instance)
because wendelin.core uses 1 fd per an array view (opening
/dev/shm/ramh.XXXXX) but that turned out to be not strictly that case:
The reason here is that select() has limit for how many #fd it can
monitor at all. The limit is system-specific but on Linux it is usually
1024 - http://man7.org/linux/man-pages/man2/select.2.html#BUGS :
$ cat s.c
#include <sys/select.h>
#include <stdio.h>
int main() {
printf("%d\n", FD_SETSIZE);
return 0;
}
$ tcc -run s.c
1024
Also select() can monitor only file descriptors which are by itself
"< FD_SETSIZE", e.g. it cannot monitor fd=1025 even if there are only 10
opened file descriptors because 1025 is not < 1024.
As was said above in wendelin.core every array view uses 1 file
descriptor, so if we are using not so small amount of arrays, even
though #fd does not go beyond process-specific ulimit, because of
select() usage the total number of allowed opened file descriptors
becomes essentially 1024.
So let's switch from select() to poll() which does not have this 1024
#fd limit. Asyncore already support using poll() out of the box -
either via passing use_pull=True to asyncore.loop()
https://docs.python.org/2/library/asyncore.html#asyncore.loop
or by using asyncore.poll2() instead of asyncore.poll()
https://github.com/python/cpython/blob/2.7/Lib/asyncore.py#L170
https://github.com/python/cpython/blob/2.7/Lib/asyncore.py#L125
--------
One option would be to switch asyncore.poll() -> asyncore.poll2() for only 1
place in Zope - inside lifetime_loop(). There are however many such similar
places in Zope (e.g. in medusa) and in other software.
For this reason, for me, what makes sense to do is not to patch all such
places, but instead change via runtime-patching asyncore.poll to be
asyncore.poll2 - this way all software will automatically benefit from
poll() usage instead of select.
P.S.
What might also make sense to do in the future is to actually let
asyncore.poll to use epoll(), as both select() and poll() are doing all
fd registration on _every_ call, so when #fd grows this preparation
time grows too. For epoll() file descriptors are registered only once.
For this to work asyncore.socket_map has to be patched also, since there
are places in code which modify this fd registry directly (e.g. remove
fd from there etc)
Original patch & discussion: https://lab.nexedi.com/kirr/Zope/commit/c6addb05
---
Lib/asyncore.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Lib/asyncore.py b/Lib/asyncore.py
index 105982f..a3025a4 100644
--- a/Lib/asyncore.py
+++ b/Lib/asyncore.py
@@ -661,3 +661,12 @@ if os.name == 'posix':
self.socket = file_wrapper(fd)
self._fileno = self.socket.fileno()
self.add_channel()
+
+# monkeypatch to switch everyone's default to use poll instead of select
+# (select has 1024 fd limit)
+# TODO it is better to use epoll
+_poll_select = poll
+_poll_poll = poll2
+poll = _poll_poll
+
+#print >>sys.stderr, 'I(nxd): asyncore: using poll instead of select'
--
2.16.1.101.gde0f0111ea
...@@ -43,6 +43,7 @@ patches = ...@@ -43,6 +43,7 @@ patches =
${:_profile_base_location_}/fix_compiler_module_issue_20613.patch#94443a77f903e9de880a029967fa6aa7 ${:_profile_base_location_}/fix_compiler_module_issue_20613.patch#94443a77f903e9de880a029967fa6aa7
${:_profile_base_location_}/pytracemalloc_pep445.patch#46662cf0ccc7cb7cfb8289bbfd68b21a ${:_profile_base_location_}/pytracemalloc_pep445.patch#46662cf0ccc7cb7cfb8289bbfd68b21a
${:_profile_base_location_}/disabled_module_list.patch#71ad30d32bcdbc50c19cf48675b1246e ${:_profile_base_location_}/disabled_module_list.patch#71ad30d32bcdbc50c19cf48675b1246e
${:_profile_base_location_}/asyncore_poll_insteadof_select.patch#ab6991c0ee6e25aeb8951e71f280a2f1
url = url =
http://www.python.org/ftp/python/${:package_version}/Python-${:package_version}${:package_version_suffix}.tar.xz http://www.python.org/ftp/python/${:package_version}/Python-${:package_version}${:package_version_suffix}.tar.xz
configure-options = configure-options =
......
...@@ -19,12 +19,11 @@ extends = ...@@ -19,12 +19,11 @@ extends =
[kvm] [kvm]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
# qemu-kvm and qemu are now the same since 1.3. # qemu-kvm and qemu are now the same since 1.3.
url = http://wiki.qemu-project.org/download/qemu-2.8.0.tar.bz2 url = http://wiki.qemu-project.org/download/qemu-2.11.0.tar.bz2
md5sum = 17940dce063b6ce450a12e719a6c9c43 md5sum = 335994a755bc655e88a87aeb36bfc0b9
configure-options = configure-options =
--target-list="$(uname -m 2>/dev/null|sed 's,^i[456]86$,i386,')-softmmu" --target-list="$(uname -m 2>/dev/null|sed 's,^i[456]86$,i386,')-softmmu"
--enable-system --enable-system
--with-system-pixman
--disable-sdl --disable-sdl
--disable-xen --disable-xen
--disable-vnc-sasl --disable-vnc-sasl
...@@ -58,25 +57,26 @@ location = ${buildout:parts-directory}/${:_buildout_section_name_} ...@@ -58,25 +57,26 @@ location = ${buildout:parts-directory}/${:_buildout_section_name_}
<= debian-netinst-base <= debian-netinst-base
arch = amd64 arch = amd64
[debian-amd64-squeeze-netinst.iso]
<= debian-amd64-netinst-base
version = 6.0.10
md5sum = 7f82d341561035f65933da43f94d5b52
[debian-amd64-wheezy-netinst.iso] [debian-amd64-wheezy-netinst.iso]
<= debian-amd64-netinst-base <= debian-amd64-netinst-base
version = 7.11.0 version = 7.11.0
md5sum = 096c1c18b44c269808bd815d58c53c8f md5sum = 096c1c18b44c269808bd815d58c53c8f
[debian-amd64-jessie-netinst.iso]
<= debian-amd64-netinst-base
release = archive
version = 8.10.0
md5sum = 19dcfc381bd3e609c6056216d203f5bc
[debian-amd64-netinst.iso] [debian-amd64-netinst.iso]
# Download the installer of Debian 8 (Jessie) # Download the installer of Debian 9 (Stretch)
<= debian-amd64-netinst-base <= debian-amd64-netinst-base
release = release/current release = release/current
version = 8.6.0 version = 9.3.0
md5sum = e9f61bf327db6d8f7cee05a99f2353cc md5sum = db8ab7871bc2b7d456c4746e706fb5d3
[debian-amd64-testing-netinst.iso] [debian-amd64-testing-netinst.iso]
# Download the installer of Debian Stretch # Download the installer of Debian Buster
<= debian-amd64-netinst-base <= debian-amd64-netinst-base
release = stretch_di_alpha7 release = stretch_di_alpha7
version = stretch-DI-alpha7 version = stretch-DI-alpha7
......
[buildout]
extends =
../coreutils/buildout.cfg
../bash/buildout.cfg
[randomsleep]
recipe = slapos.recipe.build
location = ${buildout:parts-directory}/${:_buildout_section_name_}
bin_dir = ${buildout:bin-directory}
bash_script_code =
if [ "$#" -ne 1 ]; then
echo "usage: randomsleep maxseconds"
exit
fi
${coreutils:location}/bin/sleep $((RANDOM % $1)).$((RANDOM % 100))
wrapper_script_code =
#!${bash:location}/bin/bash
${bash:location}/bin/bash ${:location}/randomsleep.bash "$@"
script =
os.makedirs(self.options['location'])
bash_script_path = os.path.join(self.options['location'], 'randomsleep.bash')
with open(bash_script_path, 'w') as f:
f.write(self.options['bash_script_code'])
wrapper_script_path = os.path.join(self.options['bin_dir'], 'randomsleep')
with open(wrapper_script_path, 'w') as f:
f.write(self.options['wrapper_script_code'])
os.chmod(wrapper_script_path, 0750)
...@@ -7,8 +7,8 @@ parts = ...@@ -7,8 +7,8 @@ parts =
[rsync] [rsync]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://rsync.samba.org/ftp/rsync/src/rsync-3.1.1.tar.gz url = https://download.samba.org/pub/rsync/rsync-3.1.2.tar.gz
md5sum = 43bd6676f0b404326eee2d63be3cdcfe md5sum = 0f758d7e000c0f7f7d3792610fad70cb
make-options = make-options =
PREFIX=${buildout:parts-directory}/${:_buildout_section_name_} PREFIX=${buildout:parts-directory}/${:_buildout_section_name_}
environment = environment =
......
diff --git a/tensorboard/pip_package/build_pip_package.sh b/tensorboard/pip_package/build_pip_package.sh diff --git a/tensorboard/pip_package/build_pip_package.sh b/tensorboard/pip_package/build_pip_package.sh
index b386d59..f03b056 100755 index 88fb5a2..782dbc5 100755
--- a/tensorboard/pip_package/build_pip_package.sh --- a/tensorboard/pip_package/build_pip_package.sh
+++ b/tensorboard/pip_package/build_pip_package.sh +++ b/tensorboard/pip_package/build_pip_package.sh
@@ -26,6 +26,7 @@ function main() { @@ -26,6 +26,7 @@ function main() {
...@@ -10,14 +10,14 @@ index b386d59..f03b056 100755 ...@@ -10,14 +10,14 @@ index b386d59..f03b056 100755
echo $(date) : "=== Using tmpdir: ${TMPDIR}" echo $(date) : "=== Using tmpdir: ${TMPDIR}"
@@ -45,8 +46,8 @@ function main() { @@ -44,9 +45,7 @@ function main() {
pushd ${TMPDIR} >/dev/null
rm -f MANIFEST rm -f MANIFEST
echo $(date) : "=== Building wheel" echo $(date) : "=== Building python2 wheel in $PWD"
echo $(pwd) - python setup.py bdist_wheel --python-tag py2 >/dev/null
- python setup.py bdist_wheel >/dev/null - echo $(date) : "=== Building python3 wheel in $PWD"
- python3 setup.py bdist_wheel >/dev/null - python setup.py bdist_wheel --python-tag py3 >/dev/null
+ PYTHONPATH=${WORKDIR}/${RUNFILES} $PYTHON_BIN_PATH setup.py bdist_egg >/dev/null + PYTHONPATH=${WORKDIR}/${RUNFILES} $PYTHON_BIN_PATH setup.py bdist_egg >/dev/null
+ #python3 setup.py bdist_wheel >/dev/null
mkdir -p ${DEST} mkdir -p ${DEST}
cp dist/* ${DEST} cp dist/* ${DEST}
popd popd >/dev/null
...@@ -11,11 +11,11 @@ parts = ...@@ -11,11 +11,11 @@ parts =
recipe = plone.recipe.command recipe = plone.recipe.command
stop-on-error = true stop-on-error = true
repository = https://github.com/tensorflow/tensorboard repository = https://github.com/tensorflow/tensorboard
tag = 0.4 tag = 0.4.0
git-binary = ${git:location}/bin/git git-binary = ${git:location}/bin/git
patch-binary = ${patch:location}/bin/patch patch-binary = ${patch:location}/bin/patch
location = ${buildout:parts-directory}/${:_buildout_section_name_} location = ${buildout:parts-directory}/${:_buildout_section_name_}
command = export HOME=${:location}; (${:git-binary} clone --quiet -b ${:tag} ${:repository} ${:location}; cd ${buildout:parts-directory} ; ${:patch-binary} -p1 -d ${:_buildout_section_name_} < ${:_profile_base_location_}/0.4.patch ) || (rm -fr ${:location}; exit 1) command = export HOME=${:location}; (${:git-binary} clone --quiet -b ${:tag} ${:repository} ${:location}; cd ${buildout:parts-directory} ; ${:patch-binary} -p1 -d ${:_buildout_section_name_} < ${:_profile_base_location_}/0.4.0.patch ) || (rm -fr ${:location}; exit 1)
[tensorboard-build] [tensorboard-build]
recipe = slapos.recipe.build recipe = slapos.recipe.build
...@@ -61,7 +61,7 @@ numpy-python-command = ${buildout:bin-directory}/${numpy-egg:interpreter} ...@@ -61,7 +61,7 @@ numpy-python-command = ${buildout:bin-directory}/${numpy-egg:interpreter}
script = script =
os.makedirs(location) os.makedirs(location)
workdir = self.options['tensorboard-repository-path'] workdir = self.options['tensorboard-repository-path']
egg_name = 'tensorflow_tensorboard-0.4.0rc3-py2.7.egg' egg_name = 'tensorflow_tensorboard-0.4.0-py2.7.egg'
dist_dir = os.path.join(workdir, 'dist') dist_dir = os.path.join(workdir, 'dist')
dest_dir = os.path.join(self.buildout['buildout']['eggs-directory'], egg_name) dest_dir = os.path.join(self.buildout['buildout']['eggs-directory'], egg_name)
env = {'PATH':':'.join([self.options['bazel-bin'], env = {'PATH':':'.join([self.options['bazel-bin'],
......
...@@ -5,8 +5,8 @@ extends = ...@@ -5,8 +5,8 @@ extends =
[util-linux] [util-linux]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://www.kernel.org/pub/linux/utils/util-linux/v2.29/util-linux-2.29.tar.xz url = https://www.kernel.org/pub/linux/utils/util-linux/v2.31/util-linux-2.31.1.tar.xz
md5sum = 07b6845f48a421ad5844aa9d58edb837 md5sum = 7733b583dcb51518944d42aa62ef19ea
configure-options = configure-options =
--disable-static --disable-static
--enable-libuuid --enable-libuuid
...@@ -29,7 +29,7 @@ configure-options = ...@@ -29,7 +29,7 @@ configure-options =
--disable-rename --disable-rename
--disable-schedutils --disable-schedutils
--disable-setterm --disable-setterm
--disable-libsmartcols --enable-libsmartcols
--disable-switch_root --disable-switch_root
--disable-tinfo --disable-tinfo
--disable-tls --disable-tls
......
[buildout]
parts=
zbar
[zbar]
recipe = slapos.recipe.cmmi
url = https://jaist.dl.sourceforge.net/project/zbar/zbar/0.10/zbar-0.10.tar.bz2
md5sum = 0fd61eb590ac1bab62a77913c8b086a5
configure-options =
--disable-video
--without-imagemagick
--without-gtk
--without-xv
--without-qt
--without-python
--without-x
--without-jpg
environment =
CFLAGS=
[buildout]
extends =
../pillow/buildout.cfg
../zbar/buildout.cfg
parts =
zbarlight
[zbarlight]
recipe = zc.recipe.egg:custom
egg = zbarlight
include-dirs =
${zbar:location}/include
library-dirs =
${zbar:location}/lib
rpath =
${zbar:location}/lib
depend-eggs = ${pillow-python:egg}
...@@ -5,7 +5,7 @@ parts = ...@@ -5,7 +5,7 @@ parts =
[zstd] [zstd]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
location = ${buildout:parts-directory}/${:_buildout_section_name_} location = ${buildout:parts-directory}/${:_buildout_section_name_}
url = https://github.com/facebook/zstd/archive/v1.3.1.tar.gz url = https://github.com/facebook/zstd/archive/v1.3.3.tar.gz
md5sum = e849ceef2f090240f690c13fba6ca70b md5sum = 187f8df17a75a74f78a23ea4806ac65f
configure-command = : configure-command = :
make-options = PREFIX=${:location} make-options = PREFIX=${:location}
...@@ -72,7 +72,6 @@ setup(name=name, ...@@ -72,7 +72,6 @@ setup(name=name,
'zc.buildout': [ 'zc.buildout': [
'addresiliency = slapos.recipe.addresiliency:Recipe', 'addresiliency = slapos.recipe.addresiliency:Recipe',
'accords = slapos.recipe.accords:Recipe', 'accords = slapos.recipe.accords:Recipe',
'apache.zope.backend = slapos.recipe.apache_zope_backend:Recipe',
'apacheperl = slapos.recipe.apacheperl:Recipe', 'apacheperl = slapos.recipe.apacheperl:Recipe',
'apachephp = slapos.recipe.apachephp:Recipe', 'apachephp = slapos.recipe.apachephp:Recipe',
'apachephpconfigure = slapos.recipe.apachephpconfigure:Recipe', 'apachephpconfigure = slapos.recipe.apachephpconfigure:Recipe',
...@@ -118,14 +117,11 @@ setup(name=name, ...@@ -118,14 +117,11 @@ setup(name=name,
'generic.mysql.wrap_update_mysql = slapos.recipe.generic_mysql:WrapUpdateMySQL', 'generic.mysql.wrap_update_mysql = slapos.recipe.generic_mysql:WrapUpdateMySQL',
'generic.mysql.wrap_mysqld = slapos.recipe.generic_mysql:WrapMySQLd', 'generic.mysql.wrap_mysqld = slapos.recipe.generic_mysql:WrapMySQLd',
'generic.varnish = slapos.recipe.generic_varnish:Recipe', 'generic.varnish = slapos.recipe.generic_varnish:Recipe',
'generic.zope = slapos.recipe.generic_zope:Recipe',
'generic.zope.zeo.client = slapos.recipe.generic_zope_zeo_client:Recipe',
'gitinit = slapos.recipe.gitinit:Recipe', 'gitinit = slapos.recipe.gitinit:Recipe',
'haproxy = slapos.recipe.haproxy:Recipe', 'haproxy = slapos.recipe.haproxy:Recipe',
'ipv4toipv6 = slapos.recipe.6tunnel:FourToSix', 'ipv4toipv6 = slapos.recipe.6tunnel:FourToSix',
'ipv6toipv4 = slapos.recipe.6tunnel:SixToFour', 'ipv6toipv4 = slapos.recipe.6tunnel:SixToFour',
'jsondump = slapos.recipe.jsondump:Recipe', 'jsondump = slapos.recipe.jsondump:Recipe',
'kumofs = slapos.recipe.kumofs:Recipe',
'kvm.frontend = slapos.recipe.kvm_frontend:Recipe', 'kvm.frontend = slapos.recipe.kvm_frontend:Recipe',
'lamp = slapos.recipe.lamp:Request', 'lamp = slapos.recipe.lamp:Request',
'lamp.generic = slapos.recipe.lampgeneric:Recipe', 'lamp.generic = slapos.recipe.lampgeneric:Recipe',
...@@ -136,7 +132,6 @@ setup(name=name, ...@@ -136,7 +132,6 @@ setup(name=name,
'libcloudrequest = slapos.recipe.libcloudrequest:Recipe', 'libcloudrequest = slapos.recipe.libcloudrequest:Recipe',
'logrotate = slapos.recipe.logrotate:Recipe', 'logrotate = slapos.recipe.logrotate:Recipe',
'logrotate.d = slapos.recipe.logrotate:Part', 'logrotate.d = slapos.recipe.logrotate:Part',
'memcached = slapos.recipe.memcached:Recipe',
'mkdirectory = slapos.recipe.mkdirectory:Recipe', 'mkdirectory = slapos.recipe.mkdirectory:Recipe',
'mioga.instantiate = slapos.recipe.mioga.instantiate:Recipe', 'mioga.instantiate = slapos.recipe.mioga.instantiate:Recipe',
'mydumper = slapos.recipe.mydumper:Recipe', 'mydumper = slapos.recipe.mydumper:Recipe',
...@@ -196,7 +191,6 @@ setup(name=name, ...@@ -196,7 +191,6 @@ setup(name=name,
'urlparse = slapos.recipe._urlparse:Recipe', 'urlparse = slapos.recipe._urlparse:Recipe',
'uuid = slapos.recipe._uuid:Recipe', 'uuid = slapos.recipe._uuid:Recipe',
'userinfo = slapos.recipe.userinfo:Recipe', 'userinfo = slapos.recipe.userinfo:Recipe',
'waitfor = slapos.recipe.waitfor:Recipe',
'webchecker = slapos.recipe.web_checker:Recipe', 'webchecker = slapos.recipe.web_checker:Recipe',
'wrapper = slapos.recipe.wrapper:Recipe', 'wrapper = slapos.recipe.wrapper:Recipe',
'xvfb = slapos.recipe.xvfb:Recipe', 'xvfb = slapos.recipe.xvfb:Recipe',
......
...@@ -91,8 +91,8 @@ class Recipe(GenericSlapRecipe): ...@@ -91,8 +91,8 @@ class Recipe(GenericSlapRecipe):
# Generate wrapper # Generate wrapper
wrapper_location = self.createPythonScript(self.options['accords-wrapper'], wrapper_location = self.createPythonScript(self.options['accords-wrapper'],
'%s.accords.runAccords' % __name__, __name__ + '.accords.runAccords',
parameter_dict) (parameter_dict,))
path_list.append(wrapper_location) path_list.append(wrapper_location)
# Generate helper for debug # Generate helper for debug
......
...@@ -38,26 +38,18 @@ class Recipe(GenericSlapRecipe): ...@@ -38,26 +38,18 @@ class Recipe(GenericSlapRecipe):
""" """
def _install(self): def _install(self):
path_list = []
slap_connection = self.buildout['slap-connection'] slap_connection = self.buildout['slap-connection']
takeover_wrapper = self.createPythonScript( return self.createPythonScript(
name=self.options['wrapper-takeover'], self.options['wrapper-takeover'],
absolute_function='slapos.recipe.addresiliency.takeover.run', __name__ + '.takeover.takeover',
arguments={ kw={
'server_url': slap_connection['server-url'], 'server_url': slap_connection['server-url'],
'key_file': slap_connection.get('key-file'), 'key_file': slap_connection.get('key-file'),
'cert_file': slap_connection.get('cert-file'), 'cert_file': slap_connection.get('cert-file'),
'computer_id': slap_connection['computer-id'], 'computer_guid': slap_connection['computer-id'],
'partition_id': slap_connection['partition-id'], 'partition_id': slap_connection['partition-id'],
'software': slap_connection['software-release-url'], 'software_release': slap_connection['software-release-url'],
'namebase': self.parameter_dict['namebase'], 'namebase': self.parameter_dict['namebase'],
'takeover_triggered_file_path': self.options['takeover-triggered-file-path'], 'takeover_triggered_file_path': self.options['takeover-triggered-file-path'],
}) })
path_list.append(takeover_wrapper)
return path_list
...@@ -78,14 +78,3 @@ def takeover(server_url, key_file, cert_file, computer_guid, ...@@ -78,14 +78,3 @@ def takeover(server_url, key_file, cert_file, computer_guid,
# Create "lock" file preventing equeue to run import scripts # Create "lock" file preventing equeue to run import scripts
# XXX hardcoded # XXX hardcoded
open(takeover_triggered_file_path, 'w').write('') open(takeover_triggered_file_path, 'w').write('')
def run(args):
slapos.recipe.addresiliency.takeover.takeover(server_url = args.pop('server_url'),
key_file = args.pop('key_file'),
cert_file = args.pop('cert_file'),
computer_guid = args.pop('computer_id'),
partition_id = args.pop('partition_id'),
software_release = args.pop('software'),
namebase = args.pop('namebase'),
takeover_triggered_file_path = args.pop('takeover_triggered_file_path'))
##############################################################################
#
# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from slapos.recipe.librecipe import GenericBaseRecipe
import pkg_resources
class Recipe(GenericBaseRecipe):
def install(self):
try:
backend_list = self.options['backend-list']
except KeyError:
backend_list = [(self.options['port'], self.options['backend'])]
scheme = self.options['scheme']
if scheme == 'http':
required_path_list = []
ssl_enable = ssl_snippet = ''
elif scheme == 'https':
key = self.options['key-file']
certificate = self.options['cert-file']
required_path_list = [key, certificate]
ssl_snippet = self.substituteTemplate(self.getTemplateFilename('snippet.ssl.in'), {
'key': key,
'certificate': certificate,
'ssl_session_cache': self.options['ssl-session-cache'],
})
if 'ssl-authentication' in self.options and self.optionIsTrue(
'ssl-authentication'):
ssl_snippet += self.substituteTemplate(self.getTemplateFilename('snippet.ssl.ca.in'), {
'ca_certificate': self.options['ssl-authentication-certificate'],
'ca_crl': self.options['ssl-authentication-crl'],
})
ssl_enable = 'SSLEngine on'
else:
raise ValueError('Unsupported scheme %s' % scheme)
ip_list = self.options['ip']
if isinstance(ip_list, basestring):
ip_list = [ip_list]
backend_path = self.options.get('backend-path', '/')
vhost_template_name = self.getTemplateFilename('vhost.in')
apache_config_file = self.createFile(
self.options['configuration-file'],
self.substituteTemplate(
self.getTemplateFilename('apache.zope.conf.in'),
{
'path': '/',
'server_admin': 'admin@',
'pid_file': self.options['pid-file'],
'lock_file': self.options['lock-file'],
'error_log': self.options['error-log'],
'access_log': self.options['access-log'],
'access_control_string': self.options['access-control-string'],
'ssl_snippet': ssl_snippet,
'vhosts': ''.join(self.substituteTemplate(vhost_template_name, {
'ip': ip,
'port': port,
'backend': ('%s/%s' % (backend.rstrip('/'), backend_path.strip('/'))).rstrip('/'),
'ssl_enable': ssl_enable,
}) for (port, backend) in backend_list for ip in ip_list),
},
)
)
return [
apache_config_file,
self.createPythonScript(
self.options['wrapper'],
__name__ + '.apache.runApache',
[
{
'required_path_list': required_path_list,
'binary': self.options['apache-binary'],
'config': apache_config_file,
},
],
),
]
import os
import sys
import time
def runApache(args):
sleep = 60
conf = args[0]
while True:
ready = True
for f in conf.get('required_path_list', []):
if not os.path.exists(f):
print 'File %r does not exists, sleeping for %s' % (f, sleep)
ready = False
if ready:
break
time.sleep(sleep)
apache_wrapper_list = [conf['binary'], '-f', conf['config'], '-DFOREGROUND']
apache_wrapper_list.extend(sys.argv[1:])
sys.stdout.flush()
sys.stderr.flush()
os.execl(apache_wrapper_list[0], *apache_wrapper_list)
# Apache configuration file for Zope
# Automatically generated
# List of modules
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
# Basic server configuration
PidFile "%(pid_file)s"
ServerAdmin %(server_admin)s
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
# Apache 2.4's default value (60 seconds) can be a bit too short
TimeOut 300
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
%(ssl_snippet)s
# Log configuration
ErrorLog "%(error_log)s"
# Default apache log format with request time in microsecond at the end
LogFormat "%%h %%l %%u %%t \"%%r\" %%>s %%b \"%%{Referer}i\" \"%%{User-Agent}i\" %%D" combined
CustomLog "%(access_log)s" combined
# Directory protection
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
</Directory>
# Path protected
<Location %(path)s>
Order Deny,Allow
Deny from all
Allow from %(access_control_string)s
</Location>
# Magic of Zope related rewrite
RewriteEngine On
%(vhosts)s
SSLVerifyClient require
RequestHeader set REMOTE_USER %%{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile %(ca_certificate)s
SSLCARevocationPath %(ca_crl)s
SSLCertificateFile %(certificate)s
SSLCertificateKeyFile %(key)s
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
SSLSessionCache shmcb:%(ssl_session_cache)s(512000)
SSLProxyEngine On
Listen %(ip)s:%(port)s
<VirtualHost *:%(port)s>
%(ssl_enable)s
RewriteRule ^/(.*) %(backend)s/$1 [L,P]
</VirtualHost>
...@@ -57,10 +57,9 @@ class Recipe(GenericBaseRecipe): ...@@ -57,10 +57,9 @@ class Recipe(GenericBaseRecipe):
) )
path_list.append(httpd_conf) path_list.append(httpd_conf)
wrapper = self.createPythonScript(self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute', (self.options['httpd-binary'], '-f', self.options['httpd-conf'],
[self.options['httpd-binary'], '-f', self.options['httpd-conf'], '-DFOREGROUND'),
'-DFOREGROUND']
) )
path_list.append(wrapper) path_list.append(wrapper)
......
...@@ -92,14 +92,13 @@ class Recipe(GenericBaseRecipe): ...@@ -92,14 +92,13 @@ class Recipe(GenericBaseRecipe):
) )
path_list.append(httpd_conf) path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
command=self.options['httpd-binary'], (self.options['httpd-binary'],
parameters=[
'-f', '-f',
self.options['httpd-conf'], self.options['httpd-conf'],
'-DFOREGROUND' '-DFOREGROUND'
], ),
environment=self.environ) self.environ)
path_list.append(wrapper) path_list.append(wrapper)
secret_key_filename = os.path.join(self.buildout['buildout']['directory'], secret_key_filename = os.path.join(self.buildout['buildout']['directory'],
......
...@@ -118,7 +118,7 @@ class Recipe(GenericBaseRecipe): ...@@ -118,7 +118,7 @@ class Recipe(GenericBaseRecipe):
configureinstall_wrapper_path = self.createPythonScript( configureinstall_wrapper_path = self.createPythonScript(
self.options['configureinstall-location'], self.options['configureinstall-location'],
__name__ + '.runner.executeRunner', __name__ + '.runner.executeRunner',
[argument, delete, rename, chmod, data] (argument, delete, rename, chmod, data)
) )
#TODO finish to port this and remove upper one #TODO finish to port this and remove upper one
......
import subprocess import subprocess
def executeRunner(args): def executeRunner(arguments, delete, rename, chmod, data):
"""Start the instance configure. this may run a python script, move or/and rename """Start the instance configure. this may run a python script, move or/and rename
file or directory when dondition is filled. the condition may be when file exist or when an entry file or directory when dondition is filled. the condition may be when file exist or when an entry
exist into database. exist into database.
""" """
arguments, delete, rename, chmod, data = args if delete:
if delete != []:
print "Calling lampconfigure with 'delete' arguments" print "Calling lampconfigure with 'delete' arguments"
result = subprocess.Popen(arguments + delete) subprocess.call(arguments + delete)
result.wait() if rename:
if rename != []:
for parameters in rename: for parameters in rename:
print "Calling lampconfigure with 'rename' arguments" print "Calling lampconfigure with 'rename' arguments"
result = subprocess.Popen(arguments + parameters) subprocess.call(arguments + parameters)
result.wait() if chmod:
if chmod != []:
print "Calling lampconfigure with 'chmod' arguments" print "Calling lampconfigure with 'chmod' arguments"
result = subprocess.Popen(arguments + chmod) subprocess.call(arguments + chmod)
result.wait() if data:
if data != []:
print "Calling lampconfigure with 'run' arguments" print "Calling lampconfigure with 'run' arguments"
print arguments + data print arguments + data
result = subprocess.Popen(arguments + data) subprocess.call(arguments + data)
result.wait()
return
...@@ -49,13 +49,12 @@ class Recipe(GenericBaseRecipe): ...@@ -49,13 +49,12 @@ class Recipe(GenericBaseRecipe):
) )
path_list.append(httpd_conf) path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
command=self.options['httpd-binary'], (self.options['httpd-binary'],
parameters=[
'-f', '-f',
self.options['httpd-conf'], self.options['httpd-conf'],
'-DFOREGROUND', '-DFOREGROUND',
]) ))
path_list.append(wrapper) path_list.append(wrapper)
......
...@@ -124,12 +124,15 @@ class Recipe(GenericBaseRecipe): ...@@ -124,12 +124,15 @@ class Recipe(GenericBaseRecipe):
#Generate wrapper for php #Generate wrapper for php
wrapperphp = os.path.join(self.home, 'bin/php') wrapperphp = os.path.join(self.home, 'bin/php')
php_wrapper = self.createPythonScript(wrapperphp, php_wrapper = self.createWrapper(wrapperphp,
'slapos.recipe.librecipe.execute.executee', (self.phpbin, '-c', self.phpini),
([self.phpbin, '-c', self.phpini], os.environ)
) )
path_list.append(php_wrapper) path_list.append(php_wrapper)
mysql_dict = dict(db=self.database,
host=self.mysqlhost, port=self.mysqlport,
user=self.username, passwd=self.password)
#Generate python script for MySQL database test (starting) #Generate python script for MySQL database test (starting)
file_status = os.path.join(self.home, '.boinc_config') file_status = os.path.join(self.home, '.boinc_config')
if os.path.exists(file_status): if os.path.exists(file_status):
...@@ -137,11 +140,7 @@ class Recipe(GenericBaseRecipe): ...@@ -137,11 +140,7 @@ class Recipe(GenericBaseRecipe):
mysql_wrapper = self.createPythonScript( mysql_wrapper = self.createPythonScript(
os.path.join(self.wrapperdir, 'start_config'), os.path.join(self.wrapperdir, 'start_config'),
'%s.configure.checkMysql' % __name__, '%s.configure.checkMysql' % __name__,
dict(mysql_port=self.mysqlport, mysql_host=self.mysqlhost, (environment, mysql_dict, file_status)
mysql_user=self.username, mysql_password=self.password,
database=self.database,
file_status=file_status, environment=environment
)
) )
# Generate make project wrapper file # Generate make project wrapper file
...@@ -164,8 +163,7 @@ class Recipe(GenericBaseRecipe): ...@@ -164,8 +163,7 @@ class Recipe(GenericBaseRecipe):
install_wrapper = self.createPythonScript( install_wrapper = self.createPythonScript(
os.path.join(self.wrapperdir, 'make_project'), os.path.join(self.wrapperdir, 'make_project'),
'%s.configure.makeProject' % __name__, '%s.configure.makeProject' % __name__,
dict(launch_args=launch_args, request_file=request_make_boinc, (file_status, launch_args, request_make_boinc, environment)
make_sig=file_status, env=environment)
) )
path_list.append(install_wrapper) path_list.append(install_wrapper)
...@@ -197,7 +195,7 @@ class Recipe(GenericBaseRecipe): ...@@ -197,7 +195,7 @@ class Recipe(GenericBaseRecipe):
) )
start_service = self.createPythonScript( start_service = self.createPythonScript(
os.path.join(self.wrapperdir, 'config_project'), os.path.join(self.wrapperdir, 'config_project'),
'%s.configure.services' % __name__, parameter '%s.configure.services' % __name__, (parameter,)
) )
path_list.append(start_service) path_list.append(start_service)
...@@ -208,14 +206,12 @@ class Recipe(GenericBaseRecipe): ...@@ -208,14 +206,12 @@ class Recipe(GenericBaseRecipe):
os.unlink(start_boinc) os.unlink(start_boinc)
boinc_parameter = dict(service_status=service_status, boinc_parameter = dict(service_status=service_status,
installroot=self.installroot, drop_install=drop_install, installroot=self.installroot, drop_install=drop_install,
mysql_port=self.mysqlport, mysql_host=self.mysqlhost, mysql_dict=mysql_dict, environment=environment,
mysql_user=self.username, mysql_password=self.password,
database=self.database, environment=environment,
start_boinc=start_boinc) start_boinc=start_boinc)
start_wrapper = self.createPythonScript(os.path.join(self.wrapperdir, start_wrapper = self.createPythonScript(os.path.join(self.wrapperdir,
'start_boinc'), 'start_boinc'),
'%s.configure.restart_boinc' % __name__, '%s.configure.restart_boinc' % __name__,
boinc_parameter (boinc_parameter,)
) )
path_list.append(start_wrapper) path_list.append(start_wrapper)
...@@ -362,7 +358,7 @@ class App(GenericBaseRecipe): ...@@ -362,7 +358,7 @@ class App(GenericBaseRecipe):
) )
deploy_app = self.createPythonScript( deploy_app = self.createPythonScript(
os.path.join(wrapperdir, 'boinc_%s' % appname), os.path.join(wrapperdir, 'boinc_%s' % appname),
'%s.configure.deployApp' % __name__, parameter '%s.configure.deployApp' % __name__, (parameter,)
) )
path_list.append(deploy_app) path_list.append(deploy_app)
...@@ -404,17 +400,15 @@ class Client(GenericBaseRecipe): ...@@ -404,17 +400,15 @@ class Client(GenericBaseRecipe):
cc_cmd = '--read_cc_config' cc_cmd = '--read_cc_config'
cmd = self.createPythonScript(cmd_wrapper, cmd = self.createPythonScript(cmd_wrapper,
'%s.configure.runCmd' % __name__, '%s.configure.runCmd' % __name__,
dict(base_cmd=base_cmd, cc_cmd=cc_cmd, installdir=installdir, (base_cmd, cc_cmd, installdir, url, key)
project_url=url, key=key)
) )
path_list.append(cmd) path_list.append(cmd)
#Generate BOINC client wrapper #Generate BOINC client wrapper
boinc = self.createPythonScript(boinc_wrapper, boinc = self.createWrapper(boinc_wrapper,
'slapos.recipe.librecipe.execute.execute', (boincbin, '--allow_multiple_clients', '--gui_rpc_port',
[boincbin, '--allow_multiple_clients', '--gui_rpc_port',
str(self.options['rpc-port']), '--allow_remote_gui_rpc', str(self.options['rpc-port']), '--allow_remote_gui_rpc',
'--dir', installdir, '--redirectio', '--check_all_logins'] '--dir', installdir, '--redirectio', '--check_all_logins'),
) )
path_list.append(boinc) path_list.append(boinc)
......
...@@ -35,27 +35,21 @@ import filecmp ...@@ -35,27 +35,21 @@ import filecmp
from lock_file import LockFile from lock_file import LockFile
def checkMysql(args): def checkMysql(environment, connect_kw, file_status=None):
sys.path += args['environment']['PYTHONPATH'].split(':') sys.path += environment['PYTHONPATH'].split(':')
import MySQLdb import MySQLdb
#Sleep until mysql server becomes available #Sleep until mysql server becomes available
while True: while True:
try: try:
conn = MySQLdb.connect(host = args['mysql_host'], MySQLdb.connect(**connect_kw).close()
user = args['mysql_user'],
port = int(args['mysql_port']),
passwd = args['mysql_password'],
db = args['database'])
conn.close()
print "Successfully connect to MySQL database... "
if args.has_key('file_status'):
writeFile(args['file_status'], "starting")
break break
except Exception, ex: except Exception, ex:
print "The result is: \n" + ex.message print "The result is: \n" + ex.message
print "Could not connect to MySQL database... sleep for 2 secondes" print "Could not connect to MySQL database... sleep for 2 secondes"
time.sleep(2) time.sleep(2)
print "Successfully connect to MySQL database... "
if file_status:
writeFile(file_status, "starting")
def checkFile(file, stime): def checkFile(file, stime):
"""Loop until 'file' is created (exist)""" """Loop until 'file' is created (exist)"""
...@@ -70,18 +64,16 @@ def checkFile(file, stime): ...@@ -70,18 +64,16 @@ def checkFile(file, stime):
def restart_boinc(args): def restart_boinc(args):
"""Stop (if currently is running state) and start all Boinc service""" """Stop (if currently is running state) and start all Boinc service"""
environment = args['environment']
if args['drop_install']: if args['drop_install']:
checkFile(args['service_status'], 3) checkFile(args['service_status'], 3)
else: else:
checkMysql(args) checkMysql(environment, args['mysql_dict'], args.get('file_status'))
print "Restart Boinc..." print "Restart Boinc..."
env = os.environ env = os.environ.copy()
env['PATH'] = args['environment']['PATH'] env.update(environment)
env['PYTHONPATH'] = args['environment']['PYTHONPATH'] subprocess.call((os.path.join(args['installroot'], 'bin', 'stop'),), env=env)
binstart = os.path.join(args['installroot'], 'bin/start') subprocess.call((os.path.join(args['installroot'], 'bin', 'start'),), env=env)
binstop = os.path.join(args['installroot'], 'bin/stop')
os.system(binstop)
os.system(binstart)
writeFile(args['start_boinc'], "started") writeFile(args['start_boinc'], "started")
print "Done." print "Done."
...@@ -122,17 +114,16 @@ def startProcess(launch_args, env=None, cwd=None, stdout=subprocess.PIPE): ...@@ -122,17 +114,16 @@ def startProcess(launch_args, env=None, cwd=None, stdout=subprocess.PIPE):
return False return False
return True return True
def makeProject(args): def makeProject(make_sig, launch_args, request_file, extra_environ):
"""Run BOINC make_project script but once only""" """Run BOINC make_project script but once only"""
#Wait for DateBase initialization... #Wait for DateBase initialization...
checkFile(args['make_sig'], 3) checkFile(make_sig, 3)
print "Cheking if needed to run BOINC make_project..." print "Cheking if needed to run BOINC make_project..."
if os.path.exists(args['request_file']): if os.path.exists(request_file):
env = os.environ env = os.environ.copy()
env['PATH'] = args['env']['PATH'] env.update(extra_environ)
env['PYTHONPATH'] = args['env']['PYTHONPATH'] if startProcess(launch_args, env=env):
if startProcess(args['launch_args'], env=env): os.unlink(request_file)
os.unlink(args['request_file'])
print "Finished running BOINC make_projet...Ending" print "Finished running BOINC make_projet...Ending"
else: else:
print "No new request for make_project. Exiting..." print "No new request for make_project. Exiting..."
...@@ -155,9 +146,8 @@ def services(args): ...@@ -155,9 +146,8 @@ def services(args):
return return
print "execute script xadd..." print "execute script xadd..."
env = os.environ env = os.environ.copy()
env['PATH'] = args['environment']['PATH'] env.update(args['environment'])
env['PYTHONPATH'] = args['environment']['PYTHONPATH']
if not startProcess([os.path.join(args['installroot'], 'bin/xadd')], env): if not startProcess([os.path.join(args['installroot'], 'bin/xadd')], env):
return return
print "Update files and directories permissions..." print "Update files and directories permissions..."
...@@ -212,9 +202,8 @@ def deployManagement(args): ...@@ -212,9 +202,8 @@ def deployManagement(args):
newInstall = True newInstall = True
#Sleep until file .start_boinc exist (File indicate that BOINC has been started) #Sleep until file .start_boinc exist (File indicate that BOINC has been started)
checkFile(args['start_boinc'], 3) checkFile(args['start_boinc'], 3)
env = os.environ env = os.environ.copy()
env['PATH'] = args['environment']['PATH'] env.update(args['environment'])
env['PYTHONPATH'] = args['environment']['PYTHONPATH']
print "setup directories..." print "setup directories..."
numversion = args['version'].replace('.', '') numversion = args['version'].replace('.', '')
...@@ -263,7 +252,7 @@ def deployManagement(args): ...@@ -263,7 +252,7 @@ def deployManagement(args):
privateKeyFile = os.path.join(args['installroot'], 'keys/code_sign_private') privateKeyFile = os.path.join(args['installroot'], 'keys/code_sign_private')
output = open(binary + '.sig', 'w') output = open(binary + '.sig', 'w')
p_sign = subprocess.Popen([sign, binary, privateKeyFile], stdout=output, p_sign = subprocess.Popen([sign, binary, privateKeyFile], stdout=output,
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT, env=env)
result = p_sign.communicate()[0] result = p_sign.communicate()[0]
if p_sign.returncode is None or p_sign.returncode != 0: if p_sign.returncode is None or p_sign.returncode != 0:
print "Failed to execute bin/sign_executable.\nThe error was: %s" % result print "Failed to execute bin/sign_executable.\nThe error was: %s" % result
...@@ -290,10 +279,8 @@ def deployManagement(args): ...@@ -290,10 +279,8 @@ def deployManagement(args):
create_wu(args, env) create_wu(args, env)
print "Restart Boinc..." print "Restart Boinc..."
binstart = os.path.join(args['installroot'], 'bin/start') subprocess.call((os.path.join(args['installroot'], 'bin', 'stop'),), env=env)
binstop = os.path.join(args['installroot'], 'bin/stop') subprocess.call((os.path.join(args['installroot'], 'bin', 'start'),), env=env)
os.system(binstop)
os.system(binstart)
print "Boinc Application deployment is done... writing end signal file..." print "Boinc Application deployment is done... writing end signal file..."
writeFile(token, str(args['wu_number'])) writeFile(token, str(args['wu_number']))
...@@ -315,22 +302,21 @@ def create_wu(args, env): ...@@ -315,22 +302,21 @@ def create_wu(args, env):
startProcess(launch_args, env, args['installroot']) startProcess(launch_args, env, args['installroot'])
def runCmd(args): def runCmd(base_cmd, cc_cmd, installdir, url, key):
"""Wait for Boinc Client started and run boinc cmd""" """Wait for Boinc Client started and run boinc cmd"""
client_config = os.path.join(args['installdir'], 'client_state.xml') client_config = os.path.join(installdir, 'client_state.xml')
checkFile(client_config, 5) checkFile(client_config, 5)
time.sleep(10) time.sleep(10)
#Scan client state xml to find client ipv4 adress #Scan client state xml to find client ipv4 adress
host = re.search("<ip_addr>([\w\d\.:]+)</ip_addr>", host = re.search("<ip_addr>([\w\d\.:]+)</ip_addr>",
open(client_config, 'r').read()).group(1) open(client_config, 'r').read()).group(1)
args['base_cmd'][2] = host + ':' + args['base_cmd'][2] base_cmd[2] = host + ':' + base_cmd[2]
print "Run boinccmd with host at %s " % args['base_cmd'][2] print "Run boinccmd with host at %s " % base_cmd[2]
project_args = args['base_cmd'] + ['--project_attach', args['project_url'], project_args = base_cmd + ['--project_attach', url, key]
args['key']] startProcess(project_args, cwd=installdir)
startProcess(project_args, cwd=args['installdir']) if cc_cmd:
if args['cc_cmd'] != '':
#Load or reload cc_config file #Load or reload cc_config file
startProcess(args['base_cmd'] + [args['cc_cmd']], cwd=args['installdir']) startProcess(base_cmd + [cc_cmd], cwd=installdir)
def writeFile(file, content): def writeFile(file, content):
......
...@@ -62,8 +62,8 @@ class Recipe(GenericBaseRecipe): ...@@ -62,8 +62,8 @@ class Recipe(GenericBaseRecipe):
condor_wrapper_list=condor_wrapper_list, condor_wrapper_list=condor_wrapper_list,
boinc_wrapper_list=boinc_wrapper_list) boinc_wrapper_list=boinc_wrapper_list)
bonjourGrid_wrapper = self.createPythonScript(grid_wrapper, bonjourGrid_wrapper = self.createPythonScript(grid_wrapper,
'%s.configure.launchScript' % __name__, __name__ + '.configure.launchScript',
parameters (parameters,)
) )
path_list.append(bonjourGrid_wrapper) path_list.append(bonjourGrid_wrapper)
...@@ -73,16 +73,15 @@ class Recipe(GenericBaseRecipe): ...@@ -73,16 +73,15 @@ class Recipe(GenericBaseRecipe):
bg_wrapper = self.options['wrapper'].strip() bg_wrapper = self.options['wrapper'].strip()
log = self.options['log_file'].strip() log = self.options['log_file'].strip()
pid_file = self.options['pid_file'].strip() pid_file = self.options['pid_file'].strip()
wrapper = self.createPythonScript(bg_wrapper, wrapper = self.createWrapper(bg_wrapper,
'slapos.recipe.librecipe.execute.execute', (python, bonjourgrid_master, '--log_file', log,
([python, bonjourgrid_master, '--log_file', log,
'--pid_file', pid_file, '--pid_file', pid_file,
'--master_wrapper', grid_wrapper, '--master_wrapper', grid_wrapper,
'--directory', self.options['work_dir'].strip(), '--directory', self.options['work_dir'].strip(),
'--server', self.options['redis-url'].strip(), '--server', self.options['redis-url'].strip(),
'--port', self.options['redis-port'].strip(), '--port', self.options['redis-port'].strip(),
'--num_workers', self.options['nworkers'].strip(), '--num_workers', self.options['nworkers'].strip(),
]) ),
) )
path_list.append(wrapper) path_list.append(wrapper)
...@@ -113,9 +112,8 @@ class Client(GenericBaseRecipe): ...@@ -113,9 +112,8 @@ class Client(GenericBaseRecipe):
bg_wrapper = self.options['wrapper'].strip() bg_wrapper = self.options['wrapper'].strip()
log = self.options['log_file'].strip() log = self.options['log_file'].strip()
pid_file = self.options['pid_file'].strip() pid_file = self.options['pid_file'].strip()
wrapper = self.createPythonScript(bg_wrapper, wrapper = self.createWrapper(bg_wrapper,
'slapos.recipe.librecipe.execute.execute', (python, bonjourgrid_client, '--log_file', log,
([python, bonjourgrid_client, '--log_file', log,
'--pid_file', pid_file, '--pid_file', pid_file,
'--boinc_wrapper', boinc_script, '--boinc_wrapper', boinc_script,
'--condor_wrapper', condor_script, '--condor_wrapper', condor_script,
...@@ -123,7 +121,7 @@ class Client(GenericBaseRecipe): ...@@ -123,7 +121,7 @@ class Client(GenericBaseRecipe):
'--install_directory', self.options['install_dir'].strip(), '--install_directory', self.options['install_dir'].strip(),
'--server', self.options['redis-url'].strip(), '--server', self.options['redis-url'].strip(),
'--port', self.options['redis-port'].strip(), '--port', self.options['redis-port'].strip(),
]) ),
) )
path_list.append(wrapper) path_list.append(wrapper)
......
...@@ -40,13 +40,10 @@ class Recipe(GenericBaseRecipe): ...@@ -40,13 +40,10 @@ class Recipe(GenericBaseRecipe):
self.ca_private = self.options['ca-private'] self.ca_private = self.options['ca-private']
self.ca_certs = self.options['ca-certs'] self.ca_certs = self.options['ca-certs']
self.ca_newcerts = self.options['ca-newcerts'] self.ca_newcerts = self.options['ca-newcerts']
self.ca_crl = self.options['ca-crl']
self.ca_key_ext = '.key' self.ca_key_ext = '.key'
self.ca_crt_ext = '.crt' self.ca_crt_ext = '.crt'
def install(self): def install(self):
path_list = []
ca_country_code = self.options.get('country-code', 'XX') ca_country_code = self.options.get('country-code', 'XX')
ca_email = self.options.get('email', 'xx@example.com') ca_email = self.options.get('email', 'xx@example.com')
# XXX-BBB: State by mistake has been configured as string "('State',)" # XXX-BBB: State by mistake has been configured as string "('State',)"
...@@ -77,21 +74,15 @@ class Recipe(GenericBaseRecipe): ...@@ -77,21 +74,15 @@ class Recipe(GenericBaseRecipe):
self.createFile(openssl_configuration, self.substituteTemplate( self.createFile(openssl_configuration, self.substituteTemplate(
self.getTemplateFilename('openssl.cnf.ca.in'), config)) self.getTemplateFilename('openssl.cnf.ca.in'), config))
ca_wrapper = self.createPythonScript( return self.createPythonScript(
self.options['wrapper'], self.options['wrapper'],
'%s.certificate_authority.runCertificateAuthority' % __name__, __name__ + '.certificate_authority.runCertificateAuthority',
dict( (os.path.join(self.ca_private, 'cakey.pem'),
openssl_configuration=openssl_configuration, os.path.join(self.ca_dir, 'cacert.pem'),
openssl_binary=self.options['openssl-binary'], self.options['openssl-binary'],
certificate=os.path.join(self.ca_dir, 'cacert.pem'), openssl_configuration,
key=os.path.join(self.ca_private, 'cakey.pem'), self.request_directory)
crl=self.ca_crl,
request_dir=self.request_directory
)
) )
path_list.append(ca_wrapper)
return path_list
class Request(Recipe): class Request(Recipe):
...@@ -146,11 +137,10 @@ class Request(Recipe): ...@@ -146,11 +137,10 @@ class Request(Recipe):
path_list = [key_file, cert_file] path_list = [key_file, cert_file]
if request_needed: if request_needed:
wrapper = self.createPythonScript( wrapper = self.createWrapper(
self.options['wrapper'], self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute_wait', (self.options['executable'],),
[ [self.options['executable']], wait_list=(certificate, key),
[certificate, key] ],
) )
path_list.append(wrapper) path_list.append(wrapper)
......
...@@ -102,10 +102,8 @@ class CertificateAuthority: ...@@ -102,10 +102,8 @@ class CertificateAuthority:
'certificate_file')): 'certificate_file')):
print 'Created certificate %r' % parser.get('certificate', 'name') print 'Created certificate %r' % parser.get('certificate', 'name')
def runCertificateAuthority(ca_conf): def runCertificateAuthority(*args):
ca = CertificateAuthority(ca_conf['key'], ca_conf['certificate'], ca = CertificateAuthority(*args)
ca_conf['openssl_binary'], ca_conf['openssl_configuration'],
ca_conf['request_dir'])
while True: while True:
ca.checkAuthority() ca.checkAuthority()
ca.checkRequestDir() ca.checkRequestDir()
......
...@@ -42,8 +42,6 @@ class Recipe(GenericBaseRecipe): ...@@ -42,8 +42,6 @@ class Recipe(GenericBaseRecipe):
options['access-url'] = 'http://[%s]:%s' % (self.ip, self.port) options['access-url'] = 'http://[%s]:%s' % (self.ip, self.port)
def install(self): def install(self):
path_list = []
environment = { environment = {
'PATH': os.path.dirname(self.git) + ':' + os.environ['PATH'], 'PATH': os.path.dirname(self.git) + ':' + os.environ['PATH'],
} }
...@@ -51,10 +49,4 @@ class Recipe(GenericBaseRecipe): ...@@ -51,10 +49,4 @@ class Recipe(GenericBaseRecipe):
cloud9_args = [self.node_executable, self.cloud9, '-l', self.ip, '-p', cloud9_args = [self.node_executable, self.cloud9, '-l', self.ip, '-p',
self.port, '-w', self.workdir] self.port, '-w', self.workdir]
wrapper = self.createPythonScript(self.wrapper, return self.createWrapper(self.wrapper, cloud9_args, environment)
'slapos.recipe.librecipe.execute.executee',
(cloud9_args, environment)
)
path_list.append(wrapper)
return path_list
...@@ -178,12 +178,11 @@ class Recipe(GenericBaseRecipe): ...@@ -178,12 +178,11 @@ class Recipe(GenericBaseRecipe):
os.chmod(wrapper_location, 0744) os.chmod(wrapper_location, 0744)
#generate script for start condor #generate script for start condor
start_condor = os.path.join(self.wrapperdir, 'start_condor') wrapper = self.createPythonScript(
start_bin = os.path.join(self.wrapper_sbin, 'condor_master') os.path.join(self.wrapperdir, 'start_condor'),
condor_reconfig = os.path.join(self.wrapper_sbin, 'condor_reconfig') __name__ + '.configure.condorStart',
wrapper = self.createPythonScript(start_condor, (os.path.join(self.wrapper_sbin, 'condor_reconfig'),
'%s.configure.condorStart' % __name__, os.path.join(self.wrapper_sbin, 'condor_master'))
dict(start_bin=start_bin, condor_reconfig=condor_reconfig)
) )
path_list.append(wrapper) path_list.append(wrapper)
return path_list return path_list
...@@ -276,13 +275,11 @@ class AppSubmit(GenericBaseRecipe): ...@@ -276,13 +275,11 @@ class AppSubmit(GenericBaseRecipe):
os.unlink(destination) os.unlink(destination)
os.symlink(app_list[appname]['files'][file], destination) os.symlink(app_list[appname]['files'][file], destination)
#generate wrapper for submitting job #generate wrapper for submitting job
condor_submit = os.path.join(self.options['bin'].strip(), 'condor_submit')
parameter = dict(submit=condor_submit, sig_install=sig_install,
submit_file='submit',
appname=appname, appdir=appdir)
submit_job = self.createPythonScript( submit_job = self.createPythonScript(
os.path.join(self.options['wrapper-dir'].strip(), appname), os.path.join(self.options['wrapper-dir'].strip(), appname),
'%s.configure.submitJob' % __name__, parameter __name__ + '.configure.submitJob',
(os.path.join(self.options['bin'].strip(), 'condor_submit'),
'submit', appdir, appname, sig_install)
) )
path_list.append(submit_job) path_list.append(submit_job)
return path_list return path_list
\ No newline at end of file
...@@ -29,27 +29,25 @@ import os ...@@ -29,27 +29,25 @@ import os
import subprocess import subprocess
import time import time
def submitJob(args): def submitJob(submit, submit_file, appdir, appname, sig_install):
"""Run condor_submit (if needed) for job deployment""" """Run condor_submit (if needed) for job deployment"""
time.sleep(10) time.sleep(10)
print "Check if needed to submit %s job's" % args['appname'] print "Check if needed to submit %s job's" % appname
if not os.path.exists(args['sig_install']): if not os.path.exists(sig_install):
print "Nothing for install or update...Exited" print "Nothing for install or update...Exited"
return return
# '-a', "log = out.log", '-a', "error = error.log", # '-a', "log = out.log", '-a', "error = error.log",
launch_args = [args['submit'], '-verbose', args['submit_file']] launch_args = submit, '-verbose', submit_file
process = subprocess.Popen(launch_args, stdout=subprocess.PIPE, process = subprocess.Popen(launch_args, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, cwd=args['appdir']) stderr=subprocess.STDOUT, cwd=appdir)
result = process.communicate()[0] result = process.communicate()[0]
if process.returncode is None or process.returncode != 0: if process.returncode is None or process.returncode != 0:
print "Failed to execute condor_submit.\nThe error was: %s" % result print "Failed to execute condor_submit.\nThe error was: %s" % result
else: else:
os.unlink(args['sig_install']) os.unlink(sig_install)
def condorStart(args): def condorStart(condor_reconfig, start_bin):
"""Start Condor if deamons is currently stopped""" """Start Condor if deamons is currently stopped"""
result = os.system(args['condor_reconfig']) if subprocess.call(condor_reconfig):
if result != 0:
#process failled to reconfig condor that mean that condor deamons is not curently started #process failled to reconfig condor that mean that condor deamons is not curently started
os.system(args['start_bin']) subprocess.call(start_bin)
\ No newline at end of file
...@@ -98,26 +98,19 @@ class Recipe(GenericBaseRecipe): ...@@ -98,26 +98,19 @@ class Recipe(GenericBaseRecipe):
) )
path_list.append(config_file) path_list.append(config_file)
wrapper = self.createPythonScript(self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute', (self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'))
[self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'])
path_list.append(wrapper) path_list.append(wrapper)
promise = self.createPythonScript(self.options['promise'], promise = self.createPythonScript(self.options['promise'],
__name__ + '.promise', __name__ + '.promise',
dict(host=self.options['ip'], port=int(self.options['port_webdav']), (self.options['ip'], int(self.options['port_webdav']),
user=self.options['user'], password=self.options['password']) self.options['user'], self.options['password']))
)
path_list.append(promise) path_list.append(promise)
return path_list return path_list
def promise(args): def promise(host, port, user, password):
host = args['host']
port = args['port']
user = args['user']
password = args['password']
connection = httplib.HTTPSConnection(host, port) connection = httplib.HTTPSConnection(host, port)
auth = base64.b64encode('%s:%s' % (user, password)) auth = base64.b64encode('%s:%s' % (user, password))
connection.request('OPTIONS', '/', connection.request('OPTIONS', '/',
......
...@@ -35,15 +35,14 @@ class Recipe(GenericBaseRecipe): ...@@ -35,15 +35,14 @@ class Recipe(GenericBaseRecipe):
self.logger.info("Installing dcron...") self.logger.info("Installing dcron...")
options = self.options options = self.options
script = self.createWrapper(name=options['binary'], script = self.createWrapper(options['binary'],
command=options['dcrond-binary'].strip(), (options['dcrond-binary'].strip(),
parameters=[
'-s', options['cron-entries'], '-s', options['cron-entries'],
'-c', options['crontabs'], '-c', options['crontabs'],
'-t', options['cronstamps'], '-t', options['cronstamps'],
'-f', '-l', '5', '-f', '-l', '5',
'-M', options['catcher'] '-M', options['catcher']
]) ))
self.logger.debug('Main cron executable created at : %r', script) self.logger.debug('Main cron executable created at : %r', script)
......
...@@ -57,8 +57,6 @@ class KnownHostsFile(dict): ...@@ -57,8 +57,6 @@ class KnownHostsFile(dict):
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
def install(self): def install(self):
path_list = []
dropbear_cmd = [self.options['dropbear-binary']] dropbear_cmd = [self.options['dropbear-binary']]
# Don't fork into background # Don't fork into background
dropbear_cmd.append('-F') dropbear_cmd.append('-F')
...@@ -95,19 +93,12 @@ class Recipe(GenericBaseRecipe): ...@@ -95,19 +93,12 @@ class Recipe(GenericBaseRecipe):
if 'shell' in self.options: if 'shell' in self.options:
env['DROPBEAR_OVERRIDE_SHELL'] = self.options['shell'] env['DROPBEAR_OVERRIDE_SHELL'] = self.options['shell']
wrapper = self.createPythonScript( return self.createWrapper(self.options['wrapper'], dropbear_cmd, env)
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
(dropbear_cmd, env, )
)
path_list.append(wrapper)
return path_list
class Client(GenericBaseRecipe): class Client(GenericBaseRecipe):
def install(self): def install(self):
env = dict() env = {}
if 'home' in self.options: if 'home' in self.options:
env['HOME'] = self.options['home'] env['HOME'] = self.options['home']
...@@ -120,13 +111,7 @@ class Client(GenericBaseRecipe): ...@@ -120,13 +111,7 @@ class Client(GenericBaseRecipe):
if 'identity-file' in self.options: if 'identity-file' in self.options:
dropbear_cmd.extend(['-i', self.options['identity-file']]) dropbear_cmd.extend(['-i', self.options['identity-file']])
wrapper = self.createPythonScript( return self.createWrapper(self.options['wrapper'], dropbear_cmd, env)
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
(dropbear_cmd, env, )
)
return [wrapper]
class AddAuthorizedKey(GenericBaseRecipe): class AddAuthorizedKey(GenericBaseRecipe):
......
...@@ -46,7 +46,4 @@ class Recipe(GenericBaseRecipe): ...@@ -46,7 +46,4 @@ class Recipe(GenericBaseRecipe):
cmd.extend(options) cmd.extend(options)
cmd.extend([backup_directory, remote_url]) cmd.extend([backup_directory, remote_url])
wrapper = self.createPythonScript(self.options['wrapper'], return self.createWrapper(self.options['wrapper'], cmd)
'slapos.recipe.librecipe.execute.execute', cmd)
return [wrapper]
...@@ -30,23 +30,20 @@ class Recipe(GenericBaseRecipe): ...@@ -30,23 +30,20 @@ class Recipe(GenericBaseRecipe):
def install(self): def install(self):
parameters = [ args = [
self.options['equeue-binary'],
'--database', self.options['database'], '--database', self.options['database'],
'--logfile', self.options['log'], '--logfile', self.options['log'],
'--lockfile', self.options['lockfile'] '--lockfile', self.options['lockfile']
] ]
if 'takeover-triggered-file-path' in self.options: if 'takeover-triggered-file-path' in self.options:
parameters.extend(['--takeover-triggered-file-path', self.options['takeover-triggered-file-path']]) args += ('--takeover-triggered-file-path',
self.options['takeover-triggered-file-path'])
if 'loglevel' in self.options: if 'loglevel' in self.options:
parameters.extend(['--loglevel', self.options['loglevel']]) args += '--loglevel', self.options['loglevel']
parameters.append(self.options['socket']) args.append(self.options['socket'])
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['equeue-binary'],
parameters=parameters)
return [wrapper]
return self.createWrapper(self.options['wrapper'], args)
...@@ -67,7 +67,7 @@ class Recipe(GenericBaseRecipe): ...@@ -67,7 +67,7 @@ class Recipe(GenericBaseRecipe):
openssl_binary=self.options['openssl-binary'], openssl_binary=self.options['openssl-binary'],
test_ca_path=self.options['certificate-authority-path'], test_ca_path=self.options['certificate-authority-path'],
) )
common_list = [ common_list = (
'--conversion_server_url=' + cloudooo_url, '--conversion_server_url=' + cloudooo_url,
# BBB: We still have test suites that only accept the following 2 options. # BBB: We still have test suites that only accept the following 2 options.
'--conversion_server_hostname=%s' % cloudooo_parsed.hostname, '--conversion_server_hostname=%s' % cloudooo_parsed.hostname,
...@@ -76,19 +76,19 @@ class Recipe(GenericBaseRecipe): ...@@ -76,19 +76,19 @@ class Recipe(GenericBaseRecipe):
'--volatile_memcached_server_port=%s' % memcached_parsed.port, '--volatile_memcached_server_port=%s' % memcached_parsed.port,
'--persistent_memcached_server_hostname=%s' % kumofs_parsed.hostname, '--persistent_memcached_server_hostname=%s' % kumofs_parsed.hostname,
'--persistent_memcached_server_port=%s' % kumofs_parsed.port, '--persistent_memcached_server_port=%s' % kumofs_parsed.port,
] )
path_list.append(self.createPythonScript(self.options['run-unit-test'], path_list.append(self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest', [dict( __name__ + '.test.runUnitTest',
call_list=[self.options['run-unit-test-binary'], ((self.options['run-unit-test-binary'],
'--erp5_sql_connection_string', mysql_connection_string, '--erp5_sql_connection_string', mysql_connection_string,
'--extra_sql_connection_string_list', ','.join( '--extra_sql_connection_string_list', ','.join(
mysql_connection_string_list), mysql_connection_string_list),
] + common_list, **common_dict)])) ) + common_list, common_dict)))
path_list.append(self.createPythonScript(self.options['run-test-suite'], path_list.append(self.createPythonScript(self.options['run-test-suite'],
__name__ + '.test.runUnitTest', [dict( __name__ + '.test.runTestSuite',
call_list=[self.options['run-test-suite-binary'], ((self.options['run-test-suite-binary'],
'--db_list', ','.join(mysql_connection_string_list), '--db_list', ','.join(mysql_connection_string_list),
] + common_list, **common_dict)])) ) + common_list, common_dict)))
return path_list return path_list
...@@ -98,20 +98,18 @@ class CloudoooRecipe(GenericBaseRecipe): ...@@ -98,20 +98,18 @@ class CloudoooRecipe(GenericBaseRecipe):
common_dict = dict( common_dict = dict(
prepend_path=self.options['prepend-path'], prepend_path=self.options['prepend-path'],
) )
common_list = [ common_list = (
"--paster_path", self.options['ooo-paster'], "--paster_path", self.options['ooo-paster'],
self.options['configuration-file'] self.options['configuration-file']
] )
run_unit_test_path = self.createPythonScript(self.options['run-unit-test'], path_list.append(self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest', [dict( __name__ + '.test.runUnitTest',
call_list=[self.options['run-unit-test-binary'], ((self.options['run-unit-test-binary'],
] + common_list, **common_dict)]) ) + common_list, common_dict)))
path_list.append(run_unit_test_path)
path_list.append(self.createPythonScript(self.options['run-test-suite'], path_list.append(self.createPythonScript(self.options['run-test-suite'],
__name__ + '.test.runTestSuite', [dict( __name__ + '.test.runTestSuite',
call_list=[self.options['run-test-suite-binary'], ((self.options['run-test-suite-binary'],
], **common_dict)])) ), common_dict)))
return path_list return path_list
...@@ -121,32 +119,20 @@ class EggTestRecipe(GenericBaseRecipe): ...@@ -121,32 +119,20 @@ class EggTestRecipe(GenericBaseRecipe):
off a list of Python eggs. off a list of Python eggs.
""" """
def install(self): def install(self):
path_list = []
test_list = self.options['test-list'].strip().replace('\n', ',') test_list = self.options['test-list'].strip().replace('\n', ',')
common_dict = {}
environment_dict = {} common_dict = {}
if self.options.get('environment'): if self.options.get('environment'):
environment_part = self.buildout.get(self.options['environment']) environment_part = self.buildout.get(self.options['environment'])
if environment_part: if environment_part:
for key, value in environment_part.iteritems(): common_dict['environment'] = dict(environment_part)
environment_dict[key] = value
common_list = [ "--source_code_path_list", test_list]
argument_dict = dict(
call_list=[self.options['run-test-suite-binary'],] + common_list,
environment=environment_dict,
**common_dict
)
if 'prepend-path' in self.options: if 'prepend-path' in self.options:
argument_dict['prepend_path'] = self.options['prepend-path'] common_dict['prepend_path'] = self.options['prepend-path']
run_test_suite_script = self.createPythonScript( return self.createPythonScript(
self.options['run-test-suite'], __name__ + '.test.runTestSuite', self.options['run-test-suite'], __name__ + '.test.runTestSuite',
[argument_dict] ((self.options['run-test-suite-binary'],
"--source_code_path_list", test_list),
common_dict)
) )
path_list.append(run_test_suite_script)
return path_list
...@@ -26,15 +26,18 @@ ...@@ -26,15 +26,18 @@
############################################################################## ##############################################################################
import os import os
import sys import sys
def runTestSuite(args):
def runTestSuite(args, d):
env = os.environ.copy() env = os.environ.copy()
d = args[0]
if 'openssl_binary' in d: if 'openssl_binary' in d:
env['OPENSSL_BINARY'] = d['openssl_binary'] env['OPENSSL_BINARY'] = d['openssl_binary']
if 'test_ca_path' in d: if 'test_ca_path' in d:
env['TEST_CA_PATH'] = d['test_ca_path'] env['TEST_CA_PATH'] = d['test_ca_path']
if 'prepend_path' in d: if 'prepend_path' in d:
env['PATH'] = ':'.join([d['prepend_path']] + os.environ.get('PATH', '').split(':')) try:
env['PATH'] = d['prepend_path'] + ':' + env['PATH']
except KeyError:
env['PATH'] = d['prepend_path']
if 'instance_home' in d: if 'instance_home' in d:
env['INSTANCE_HOME'] = d['instance_home'] env['INSTANCE_HOME'] = d['instance_home']
env['REAL_INSTANCE_HOME'] = d['instance_home'] env['REAL_INSTANCE_HOME'] = d['instance_home']
...@@ -44,42 +47,15 @@ def runTestSuite(args): ...@@ -44,42 +47,15 @@ def runTestSuite(args):
env.update(d['environment']) env.update(d['environment'])
# Deal with Shebang size limitation # Deal with Shebang size limitation
executable_filepath = d['call_list'][0] executable_filepath = args[0]
file_object = open(executable_filepath, 'r') with open(executable_filepath, 'r') as f:
line = file_object.readline() line = f.readline()
file_object.close()
argument_list = []
if line[:2] == '#!':
executable_filepath = line[2:].strip()
argument_list.append(executable_filepath)
argument_list.extend(d['call_list'])
argument_list.extend(sys.argv[1:])
argument_list.append(env)
os.execle(executable_filepath, *argument_list)
def runUnitTest(args):
env = os.environ.copy()
d = args[0]
if 'openssl_binary' in d:
env['OPENSSL_BINARY'] = d['openssl_binary']
if 'test_ca_path' in d:
env['TEST_CA_PATH'] = d['test_ca_path']
if 'prepend_path' in d:
env['PATH'] = ':'.join([d['prepend_path']] + os.environ.get('PATH', '').split(':'))
if 'instance_home' in d:
env['INSTANCE_HOME'] = d['instance_home']
env['REAL_INSTANCE_HOME'] = d['instance_home']
# Deal with Shebang size limitation
executable_filepath = d['call_list'][0]
file_object = open(executable_filepath, 'r')
line = file_object.readline()
file_object.close()
argument_list = [] argument_list = []
if line[:2] == '#!': if line[:2] == '#!':
executable_filepath = line[2:].strip() executable_filepath = line[2:].strip()
argument_list.append(executable_filepath) argument_list.append(executable_filepath)
argument_list.extend(d['call_list']) argument_list += args
argument_list.extend(sys.argv[1:]) argument_list += sys.argv[1:]
argument_list.append(env) os.execve(executable_filepath, argument_list, env)
os.execle(executable_filepath, *argument_list)
runUnitTest = runTestSuite
...@@ -68,17 +68,14 @@ class Recipe(GenericBaseRecipe): ...@@ -68,17 +68,14 @@ class Recipe(GenericBaseRecipe):
) )
self.path_list.append(configuration_file) self.path_list.append(configuration_file)
self.path_list.append( self.path_list.append(
self.createPythonScript( self.createWrapper(self.options['wrapper'],
self.options['wrapper'], # Command
'slapos.recipe.librecipe.execute.executee', ( self.options['testnode'], '-l', self.options['log-file'],
[ # Executable configuration_file),
[ self.options['testnode'], '-l', self.options['log-file'],
configuration_file],
# Environment # Environment
{ {
'GIT_SSL_NO_VERIFY': '1', 'GIT_SSL_NO_VERIFY': '1',
} }
],
) )
) )
self.installApache() self.installApache()
...@@ -106,9 +103,8 @@ class Recipe(GenericBaseRecipe): ...@@ -106,9 +103,8 @@ class Recipe(GenericBaseRecipe):
apache_config) apache_config)
) )
self.path_list.append(config_file) self.path_list.append(config_file)
wrapper = self.createPythonScript(self.options['httpd-wrapper'], wrapper = self.createWrapper(self.options['httpd-wrapper'],
'slapos.recipe.librecipe.execute.execute', (self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'))
[self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'])
self.path_list.append(wrapper) self.path_list.append(wrapper)
# create empty html page to not allow listing of / # create empty html page to not allow listing of /
page = open(os.path.join(self.options['log-directory'], "index.html"), "w") page = open(os.path.join(self.options['log-directory'], "index.html"), "w")
......
...@@ -118,5 +118,5 @@ class Recipe(GenericBaseRecipe): ...@@ -118,5 +118,5 @@ class Recipe(GenericBaseRecipe):
path_list.append(config_file) path_list.append(config_file)
path_list.append(self.createPythonScript(self.options['wrapper'], path_list.append(self.createPythonScript(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute_with_signal_translation', 'slapos.recipe.librecipe.execute.execute_with_signal_translation',
[self.options['ooo-paster'].strip(), 'serve', config_file])) ((self.options['ooo-paster'].strip(), 'serve', config_file),)))
return path_list return path_list
...@@ -154,7 +154,7 @@ class Recipe(GenericBaseRecipe): ...@@ -154,7 +154,7 @@ class Recipe(GenericBaseRecipe):
)] )]
) )
path_list.append(mysqld) path_list.append(mysqld)
environment = dict(PATH='%s' % self.options['bin-directory']) environment = {'PATH': self.options['bin-directory']}
# TODO: move to a separate recipe (ack'ed by Cedric) # TODO: move to a separate recipe (ack'ed by Cedric)
if 'backup-script' in self.options: if 'backup-script' in self.options:
# backup configuration # backup configuration
...@@ -165,9 +165,13 @@ class Recipe(GenericBaseRecipe): ...@@ -165,9 +165,13 @@ class Recipe(GenericBaseRecipe):
'--defaults-file=%s' % mysql_conf_file, '--defaults-file=%s' % mysql_conf_file,
'--socket=%s' % socket.strip(), '--user=root', '--socket=%s' % socket.strip(), '--user=root',
'--ibbackup=%s'% self.options['xtrabackup-binary']] '--ibbackup=%s'% self.options['xtrabackup-binary']]
innobackupex_incremental = self.createPythonScript(self.options['innobackupex-incremental'], 'slapos.recipe.librecipe.execute.executee', [innobackupex_argument_list + ['--incremental'], environment]) innobackupex_incremental = self.createWrapper(
self.options['innobackupex-incremental'],
innobackupex_argument_list + ['--incremental'], environment)
path_list.append(innobackupex_incremental) path_list.append(innobackupex_incremental)
innobackupex_full = self.createPythonScript(self.options['innobackupex-full'], 'slapos.recipe.librecipe.execute.executee', [innobackupex_argument_list, environment]) innobackupex_full = self.createWrapper(
self.options['innobackupex-full'],
innobackupex_argument_list, environment)
path_list.append(innobackupex_full) path_list.append(innobackupex_full)
backup_controller = self.createPythonScript(self.options['backup-script'], __name__ + '.innobackupex.controller', [innobackupex_incremental, innobackupex_full, full_backup, incremental_backup]) backup_controller = self.createPythonScript(self.options['backup-script'], __name__ + '.innobackupex.controller', [innobackupex_incremental, innobackupex_full, full_backup, incremental_backup])
path_list.append(backup_controller) path_list.append(backup_controller)
...@@ -215,7 +219,9 @@ class Recipe(GenericBaseRecipe): ...@@ -215,7 +219,9 @@ class Recipe(GenericBaseRecipe):
'--defaults-file=%s' % mysql_conf_file, '--defaults-file=%s' % mysql_conf_file,
'--socket=%s' % socket.strip(), '--user=root', '--socket=%s' % socket.strip(), '--user=root',
] ]
pt_exe = self.createPythonScript(os.path.join(self.options['bin-directory'], pt_script_name), 'slapos.recipe.librecipe.execute.executee', [pt_argument_list, environment]) pt_exe = self.createWrapper(
os.path.join(self.options['bin-directory'], pt_script_name),
pt_argument_list, environment)
path_list.append(pt_exe) path_list.append(pt_exe)
return path_list return path_list
......
import os import os
import glob import glob
def controller(args): def controller(innobackupex_incremental, innobackupex_full,
full_backup, incremental_backup):
"""Creates full or incremental backup """Creates full or incremental backup
If no full backup is done, it is created If no full backup is done, it is created
...@@ -9,8 +10,6 @@ def controller(args): ...@@ -9,8 +10,6 @@ def controller(args):
base is the newest (according to date) full or incremental backup base is the newest (according to date) full or incremental backup
""" """
innobackupex_incremental, innobackupex_full, full_backup, incremental_backup \
= args
if len(os.listdir(full_backup)) == 0: if len(os.listdir(full_backup)) == 0:
print 'Doing full backup in %r' % full_backup print 'Doing full backup in %r' % full_backup
os.execv(innobackupex_full, [innobackupex_full, full_backup]) os.execv(innobackupex_full, [innobackupex_full, full_backup])
......
...@@ -5,9 +5,8 @@ import sys ...@@ -5,9 +5,8 @@ import sys
import pytz import pytz
def runMysql(args): def runMysql(conf):
sleep = 60 sleep = 60
conf = args[0]
mysqld_wrapper_list = [conf['mysqld_binary'], '--defaults-file=%s' % mysqld_wrapper_list = [conf['mysqld_binary'], '--defaults-file=%s' %
conf['configuration_file']] conf['configuration_file']]
# we trust mysql_install that if mysql directory is available mysql was # we trust mysql_install that if mysql directory is available mysql was
...@@ -54,8 +53,7 @@ def runMysql(args): ...@@ -54,8 +53,7 @@ def runMysql(args):
os.execl(mysqld_wrapper_list[0], *mysqld_wrapper_list) os.execl(mysqld_wrapper_list[0], *mysqld_wrapper_list)
def updateMysql(args): def updateMysql(conf):
conf = args[0]
sleep = 30 sleep = 30
is_succeed = False is_succeed = False
try: try:
......
##############################################################################
#
# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from slapos.recipe.librecipe import GenericBaseRecipe
import binascii
import hashlib
import os
import re
import zc.buildout
_isurl = re.compile('([a-zA-Z0-9+.-]+)://').match
# based on Zope2.utilities.mkzopeinstance.write_inituser
def Zope2InitUser(path, username, password):
# Set password only once
# Currently, rely on existence of a simple file:
# Create it the first time, then next time, detect this file and do no-op.
inituser_done_path = '%s_done' % path
if os.path.exists(inituser_done_path):
return
if os.path.exists(path):
return
open(path, 'w').write('')
os.chmod(path, 0600)
open(path, 'w').write('%s:{SHA}%s\n' % (
username,binascii.b2a_base64(hashlib.sha1(password).digest())[:-1]))
open(inituser_done_path, 'w').write('"inituser" file already created once.')
class Recipe(GenericBaseRecipe):
def _options(self, options):
options['password'] = self.generatePassword()
options['deadlock-password'] = self.generatePassword()
def install(self):
"""
All zope have to share file created by portal_classes
(until everything is integrated into the ZODB).
So, do not request zope instance and create multiple in the same partition.
"""
path_list = []
Zope2InitUser(self.options['inituser'], self.options['user'],
self.options['password'])
# Symlink to BT5 repositories defined in instance config.
# Those paths will eventually end up in the ZODB, and having symlinks
# inside the XXX makes it possible to reuse such ZODB with another software
# release[ version].
# Note: this path cannot be used for development, it's really just a
# read-only repository.
repository_path = self.options['bt5-repository']
self.bt5_repository_list = []
append = self.bt5_repository_list.append
for repository in self.options.get('bt5-repository-list', '').split():
repository = repository.strip()
if not repository:
continue
if _isurl(repository) and not repository.startswith("file://"):
# XXX: assume it's a valid URL
append(repository)
continue
if repository.startswith('file://'):
repository = repository.replace('file://', '', '')
if os.path.isabs(repository):
repo_id = hashlib.sha1(repository).hexdigest()
link = os.path.join(repository_path, repo_id)
if os.path.lexists(link):
if not os.path.islink(link):
raise zc.buildout.UserError(
'Target link already %r exists but it is not link' % link)
os.unlink(link)
os.symlink(repository, link)
self.logger.debug('Created link %r -> %r' % (link, repository_path))
# Always provide a URL-Type
append("file://" + link)
# Create zope configuration file
zope_config = dict(
thread_amount=self.options['thread-amount'],
zodb_root_path=self.options['zodb-path'],
zodb_cache_size=int(self.options['zodb-cache-size']),
)
zope_environment = dict(
TMP=self.options['tmp-path'],
TMPDIR=self.options['tmp-path'],
HOME=self.options['tmp-path'],
PATH=self.options['bin-path']
)
# configure default Zope2 zcml
open(self.options['site-zcml'], 'w').write(open(self.getTemplateFilename(
'site.zcml')).read())
zope_config['instance'] = self.options['instance-path']
zope_config['event_log'] = self.options['event-log']
zope_config['z2_log'] = self.options['z2-log']
zope_config['pid-filename'] = self.options['pid-file']
zope_config['lock-filename'] = self.options['lock-file']
zope_config['products'] = 'products %s' % self.options['instance-products']
zope_config['address'] = '%s:%s' % (self.options['ip'], self.options['port'])
zope_config.update(dump_url=self.options['deadlock-path'],
secret=self.options['deadlock-password'])
zope_wrapper_template_location = self.getTemplateFilename('zope.conf.in')
zope_conf_content = self.substituteTemplate(zope_wrapper_template_location,
zope_config)
if ('promise-path' in self.options) and ('site-id' in self.options):
zope_conf_content += self.substituteTemplate(self.getTemplateFilename(
'zope.conf.promise.in'), {
'site-id': self.options['site-id'],
'promise-path': self.options['promise-path'],
})
zope_conf_path = self.createFile(self.options['configuration-file'], zope_conf_content)
path_list.append(zope_conf_path)
# Create init script
path_list.append(self.createPythonScript(self.options['wrapper'], 'slapos.recipe.librecipe.execute.executee', [[self.options['runzope-binary'].strip(), '-C', zope_conf_path], zope_environment]))
return path_list
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:five="http://namespaces.zope.org/five">
<include package="Products.Five" />
<meta:redefinePermission from="zope2.Public" to="zope.Public" />
<!-- Load the meta -->
<include files="package-includes/*-meta.zcml" />
<five:loadProducts file="meta.zcml"/>
<!-- Load the configuration -->
<include files="package-includes/*-configure.zcml" />
<five:loadProducts />
<!-- Load the configuration overrides-->
<includeOverrides files="package-includes/*-overrides.zcml" />
<five:loadProductsOverrides />
<securityPolicy
component="Products.Five.security.FiveSecurityPolicy" />
</configure>
## Zope 2 configuration file generated by SlapOS
# Some defines
%%define INSTANCE %(instance)s
instancehome $INSTANCE
# Used products
%(products)s
# Environment is setup in running wrapper script
# Reason: zope.conf is read too late for some componets
# No need to debug
debug-mode off
# One thread is safe enough
zserver-threads %(thread_amount)s
# File location
pid-filename %(pid-filename)s
lock-filename %(lock-filename)s
# Encoding
rest-input-encoding utf-8
rest-output-encoding utf-8
default-zpublisher-encoding utf-8
# Disable ownership checking to execute codes generated by alarm
skip-ownership-checking on
# Temporary storage database (for sessions)
<zodb_db temporary>
<temporarystorage>
name temporary storage for sessioning
</temporarystorage>
mount-point /temp_folder
container-class Products.TemporaryFolder.TemporaryContainer
</zodb_db>
# Logging configuration
<eventlog>
<logfile>
dateformat
path %(event_log)s
</logfile>
</eventlog>
<logger access>
<logfile>
dateformat
path %(z2_log)s
</logfile>
</logger>
# Serving configuration
<http-server>
address %(address)s
</http-server>
# ZODB configuration
<zodb_db root>
cache-size %(zodb_cache_size)d
<filestorage>
path %(zodb_root_path)s
</filestorage>
mount-point /
</zodb_db>
<zoperunner>
program $INSTANCE/bin/runzope
</zoperunner>
# DeadlockDebugger configuration
<product-config DeadlockDebugger>
dump_url %(dump_url)s
secret %(secret)s
</product-config>
# ERP5 Timer Service
%%import timerserver
<timer-server>
interval 5
</timer-server>
# ERP5 promise
<product-config /%(site-id)s>
promise_path %(promise-path)s
</product-config>
##############################################################################
#
# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from slapos.recipe.librecipe import GenericBaseRecipe
import binascii
import hashlib
import os
import re
import zc.buildout
_isurl = re.compile('([a-zA-Z0-9+.-]+)://').match
# based on Zope2.utilities.mkzopeinstance.write_inituser
def Zope2InitUser(path, username, password):
# Set password only once
# Currently, rely on existence of a simple file:
# Create it the first time, then next time, detect this file and do no-op.
inituser_done_path = '%s_done' % path
if os.path.exists(inituser_done_path):
return
if os.path.exists(path):
return
open(path, 'w').write('')
os.chmod(path, 0600)
open(path, 'w').write('%s:{SHA}%s\n' % (
username,binascii.b2a_base64(hashlib.sha1(password).digest())[:-1]))
open(inituser_done_path, 'w').write('"inituser" file already created once.')
class Recipe(GenericBaseRecipe):
def _options(self, options):
if 'password' not in options:
options['password'] = self.generatePassword()
def install(self):
"""
All zope have to share file created by portal_classes
(until everything is integrated into the ZODB).
So, do not request zope instance and create multiple in the same partition.
"""
path_list = []
Zope2InitUser(self.options['inituser'], self.options['user'],
self.options['password'])
# Symlink to BT5 repositories defined in instance config.
# Those paths will eventually end up in the ZODB, and having symlinks
# inside the XXX makes it possible to reuse such ZODB with another software
# release[ version].
# Note: this path cannot be used for development, it's really just a
# read-only repository.
repository_path = self.options['bt5-repository']
self.bt5_repository_list = []
append = self.bt5_repository_list.append
for repository in self.options.get('bt5-repository-list', '').split():
repository = repository.strip()
if not repository:
continue
if _isurl(repository) and not repository.startswith("file://"):
# XXX: assume it's a valid URL
append(repository)
continue
if repository.startswith('file://'):
repository = repository.replace('file://', '', '')
if os.path.isabs(repository):
repo_id = hashlib.sha1(repository).hexdigest()
link = os.path.join(repository_path, repo_id)
if os.path.lexists(link):
if not os.path.islink(link):
raise zc.buildout.UserError(
'Target link already %r exists but it is not link' % link)
os.unlink(link)
os.symlink(repository, link)
self.logger.debug('Created link %r -> %r' % (link, repository_path))
# Always provide a URL-Type
append("file://" + link)
zope_environment = {
'TMP': self.options['tmp-path'],
'TMPDIR': self.options['tmp-path'],
'HOME': self.options.get('home-path', self.options.get('tmp-path')),
'PATH': self.options['bin-path'],
'TZ': self.options['timezone'],
}
instance_home = self.options.get("instancehome-path", None)
if instance_home:
zope_environment["INSTANCE_HOME"] = instance_home
# configure default Zope2 zcml
open(self.options['site-zcml'], 'w').write(open(self.getTemplateFilename(
'site.zcml')).read())
# Create init script
path_list.append(self.createPythonScript(self.options['wrapper'], 'slapos.recipe.librecipe.execute.executee', [[self.options['runzope-binary'].strip(), '-C', self.options['configuration-file']], zope_environment]))
return path_list
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta"
xmlns:five="http://namespaces.zope.org/five">
<include package="Products.Five" />
<meta:redefinePermission from="zope2.Public" to="zope.Public" />
<!-- Load the meta -->
<include files="package-includes/*-meta.zcml" />
<five:loadProducts file="meta.zcml"/>
<!-- Load the configuration -->
<include files="package-includes/*-configure.zcml" />
<five:loadProducts />
<!-- Load the configuration overrides-->
<includeOverrides files="package-includes/*-overrides.zcml" />
<five:loadProductsOverrides />
<securityPolicy
component="Products.Five.security.FiveSecurityPolicy" />
</configure>
...@@ -120,12 +120,11 @@ class Recipe(GenericBaseRecipe): ...@@ -120,12 +120,11 @@ class Recipe(GenericBaseRecipe):
'server_text': server_snippet}, 'server_text': server_snippet},
) )
) )
wrapper_path = self.createPythonScript( wrapper_path = self.createWrapper(
self.options['wrapper-path'], self.options['wrapper-path'],
'slapos.recipe.librecipe.execute.execute', (self.options['binary-path'].strip(), '-f', configuration_path))
arguments=[self.options['binary-path'].strip(), '-f', configuration_path],)
ctl_path = self.createPythonScript( ctl_path = self.createPythonScript(
self.options['ctl-path'], self.options['ctl-path'],
'%s.haproxy.haproxyctl' % __name__, __name__ + '.haproxy.haproxyctl',
{'socket_path':self.options['socket-path']}) (self.options['socket-path'],))
return [configuration_path, wrapper_path, ctl_path] return [configuration_path, wrapper_path, ctl_path]
...@@ -4,7 +4,7 @@ try: ...@@ -4,7 +4,7 @@ try:
except ImportError: except ImportError:
pass pass
def haproxyctl(conf): def haproxyctl(socket_path):
while True: while True:
try: try:
l = raw_input('> ') l = raw_input('> ')
...@@ -14,7 +14,7 @@ def haproxyctl(conf): ...@@ -14,7 +14,7 @@ def haproxyctl(conf):
if l == 'quit': if l == 'quit':
break break
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(conf['socket_path']) s.connect(socket_path)
s.send('%s\n' % l) s.send('%s\n' % l)
while True: while True:
r = s.recv(1024) r = s.recv(1024)
......
This diff is collapsed.
import os
import subprocess
import time
import ConfigParser
def popenCommunicate(command_list, input=None):
subprocess_kw = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if input is not None:
subprocess_kw.update(stdin=subprocess.PIPE)
popen = subprocess.Popen(command_list, **subprocess_kw)
result = popen.communicate(input)[0]
if popen.returncode is None:
popen.kill()
if popen.returncode != 0:
raise ValueError('Issue during calling %r, result was:\n%s' % (
command_list, result))
return result
class CertificateAuthority:
def __init__(self, key, certificate, openssl_binary,
openssl_configuration, request_dir):
self.key = key
self.certificate = certificate
self.openssl_binary = openssl_binary
self.openssl_configuration = openssl_configuration
self.request_dir = request_dir
def checkAuthority(self):
file_list = [ self.key, self.certificate ]
ca_ready = True
for f in file_list:
if not os.path.exists(f):
ca_ready = False
break
if ca_ready:
return
for f in file_list:
if os.path.exists(f):
os.unlink(f)
try:
# no CA, let us create new one
popenCommunicate([self.openssl_binary, 'req', '-nodes', '-config',
self.openssl_configuration, '-new', '-x509', '-extensions',
'v3_ca', '-keyout', self.key, '-out', self.certificate,
'-days', '10950'], 'Automatic Certificate Authority\n')
except:
try:
for f in file_list:
if os.path.exists(f):
os.unlink(f)
except:
# do not raise during cleanup
pass
raise
def _checkCertificate(self, common_name, key, certificate):
file_list = [key, certificate]
ready = True
for f in file_list:
if not os.path.exists(f):
ready = False
break
if ready:
return False
for f in file_list:
if os.path.exists(f):
os.unlink(f)
csr = certificate + '.csr'
try:
popenCommunicate([self.openssl_binary, 'req', '-config',
self.openssl_configuration, '-nodes', '-new', '-keyout',
key, '-out', csr, '-days', '3650'],
common_name + '\n')
try:
popenCommunicate([self.openssl_binary, 'ca', '-batch', '-config',
self.openssl_configuration, '-out', certificate,
'-infiles', csr])
finally:
if os.path.exists(csr):
os.unlink(csr)
except:
try:
for f in file_list:
if os.path.exists(f):
os.unlink(f)
except:
# do not raise during cleanup
pass
raise
else:
return True
def checkRequestDir(self):
for request_file in os.listdir(self.request_dir):
parser = ConfigParser.RawConfigParser()
parser.readfp(open(os.path.join(self.request_dir, request_file), 'r'))
if self._checkCertificate(parser.get('certificate', 'name'),
parser.get('certificate', 'key_file'), parser.get('certificate',
'certificate_file')):
print 'Created certificate %r' % parser.get('certificate', 'name')
def runCertificateAuthority(args):
ca_conf = args[0]
ca = CertificateAuthority(ca_conf['key'], ca_conf['certificate'],
ca_conf['openssl_binary'], ca_conf['openssl_configuration'],
ca_conf['request_dir'])
while True:
ca.checkAuthority()
ca.checkRequestDir()
time.sleep(60)
#!/bin/sh
exec %(kumo_gateway_binary)s -F -E -m %(kumo_manager_ip)s:%(kumo_manager_port)s -t %(kumo_gateway_ip)s:%(kumo_gateway_port)s -o %(kumo_gateway_log)s
#!/bin/sh
exec %(kumo_manager_binary)s -a -l %(kumo_manager_ip)s:%(kumo_manager_port)s -o %(kumo_manager_log)s
#!/bin/sh
exec %(kumo_server_binary)s -l %(kumo_server_ip)s:%(kumo_server_port)s -L %(kumo_server_listen_port)s -m %(kumo_manager_ip)s:%(kumo_manager_port)s -s %(kumo_server_storage)s -o %(kumo_server_log)s
This diff is collapsed.
foreground = yes
output = %(log)s
pid = %(pid_file)s
syslog = no
CApath = %(ca_path)s
key = %(key)s
CRLpath = %(ca_crl)s
cert = %(cert)s
[service]
accept = %(public_ip)s:%(public_port)s
connect = %(private_ip)s:%(private_port)s
...@@ -298,9 +298,9 @@ class Request(BaseRecipe): ...@@ -298,9 +298,9 @@ class Request(BaseRecipe):
'local_host': local_host, 'local_port': local_port, 'local_host': local_host, 'local_port': local_port,
})) }))
wrapper = zc.buildout.easy_install.scripts([('stunnel', wrapper = zc.buildout.easy_install.scripts([('stunnel',
'slapos.recipe.librecipe.execute', 'execute')], self.ws, 'slapos.recipe.librecipe.execute', 'generic_exec')], self.ws,
sys.executable, self.wrapper_directory, arguments=[ sys.executable, self.wrapper_directory, arguments='%r, %r'
self.options['stunnel_binary'].strip(), stunnel_conf_path] % (self.options['stunnel_binary'].strip(), stunnel_conf_path)
)[0] )[0]
self.path_list.append(wrapper) self.path_list.append(wrapper)
return (local_host, local_port,) return (local_host, local_port,)
...@@ -71,13 +71,12 @@ class Recipe(GenericBaseRecipe): ...@@ -71,13 +71,12 @@ class Recipe(GenericBaseRecipe):
) )
path_list.append(httpd_conf) path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
command=self.options['httpd-binary'], (self.options['httpd-binary'],
parameters=[
'-f', '-f',
self.options['httpd-conf'], self.options['httpd-conf'],
'-DFOREGROUND' '-DFOREGROUND'
]) ))
path_list.append(wrapper) path_list.append(wrapper)
......
...@@ -2,7 +2,6 @@ import sys ...@@ -2,7 +2,6 @@ import sys
import os import os
import signal import signal
import subprocess import subprocess
import time
from collections import defaultdict from collections import defaultdict
from inotify_simple import INotify, flags from inotify_simple import INotify, flags
...@@ -29,65 +28,96 @@ def _wait_files_creation(file_list): ...@@ -29,65 +28,96 @@ def _wait_files_creation(file_list):
if event.name in directory: if event.name in directory:
directory[event.name] = event.mask & (flags.CREATE | flags.MOVED_TO) directory[event.name] = event.mask & (flags.CREATE | flags.MOVED_TO)
def execute(args): def _libc():
"""Portable execution with process replacement""" from ctypes import CDLL, get_errno, c_char_p, c_int, c_ulong, util
# XXX: Kept for backward compatibility libc = CDLL(util.find_library('c'), use_errno=True)
generic_exec([args, None, None]) libc_mount = libc.mount
libc_mount.argtypes = c_char_p, c_char_p, c_char_p, c_ulong, c_char_p
def execute_wait(args): def mount(source, target, filesystemtype, mountflags, data):
"""Execution but after all files in args[1] exists""" if libc_mount(source, target, filesystemtype, mountflags, data):
# XXX: Kept for backward compatibility e = get_errno()
generic_exec([args[0], args[1], None]) raise OSError(e, os.strerror(e))
libc_unshare = libc.unshare
libc_unshare.argtypes = c_int,
def unshare(flags):
if libc_unshare(flags):
e = get_errno()
raise OSError(e, os.strerror(e))
return mount, unshare
def generic_exec(args, extra_environ=None, wait_list=None,
pidfile=None, reserve_cpu=False, private_dev_shm=None,
#shebang_workaround=False, # XXX: still needed ?
):
args = list(args)
if pidfile:
import psutil
try:
with open(pidfile) as f:
pid = int(f.read())
running = psutil.Process(pid).cmdline()
except Exception:
pass
else:
# With chained shebangs, several paths may be inserted at the beginning.
n = len(args)
for i in xrange(1+len(running)-n):
if args == running[i:n+i]:
sys.exit("Already running with pid %s." % pid)
with open(pidfile, 'w') as f:
f.write(str(os.getpid()))
args += sys.argv[1:]
if reserve_cpu:
# If the CGROUPS cpuset is available (and prepared by slap format),
# request an exclusive CPU core for this process.
with open(os.path.expanduser('~/.slapos-cpu-exclusive'), 'a') as f:
f.write('%s\n' % os.getpid())
if wait_list:
_wait_files_creation(wait_list)
if private_dev_shm:
mount, unshare = _libc()
CLONE_NEWNS = 0x00020000
CLONE_NEWUSER = 0x10000000
uid = os.getuid()
gid = os.getgid()
unshare(CLONE_NEWUSER |CLONE_NEWNS)
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)
if extra_environ:
env = os.environ.copy()
env.update(extra_environ)
os.execve(args[0], args, env)
else:
os.execv(args[0], args)
child_pg = None child_pg = None
def executee(args):
"""Portable execution with process replacement and environment manipulation"""
# XXX: Kept for backward compatibility
generic_exec([args[0], None, args[1]])
def executee_wait(args):
"""Portable execution with process replacement and environment manipulation"""
# XXX: Kept for backward compatibility
generic_exec(args)
def generic_exec(args):
exec_list = list(args[0])
file_list = args[1]
environment_overriding = args[2]
exec_env = os.environ.copy()
if environment_overriding is not None:
exec_env.update(environment_overriding)
if file_list is not None:
_wait_files_creation(file_list)
os.execve(exec_list[0], exec_list + sys.argv[1:], exec_env)
def sig_handler(sig, frame): def sig_handler(sig, frame):
print 'Received signal %r, killing children and exiting' % sig print 'Received signal %r, killing children and exiting' % sig
if child_pg is not None: if child_pg is not None:
os.killpg(child_pg, signal.SIGHUP) os.killpg(child_pg, signal.SIGHUP)
os.killpg(child_pg, signal.SIGTERM) os.killpg(child_pg, signal.SIGTERM)
sys.exit(0) sys.exit()
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGQUIT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
def execute_with_signal_translation(args): def execute_with_signal_translation(args):
"""Run process as children and translate from SIGTERM to another signal""" """Run process as children and translate from SIGTERM to another signal"""
global child_pg global child_pg
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGQUIT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
child = subprocess.Popen(args, close_fds=True, preexec_fn=os.setsid) child = subprocess.Popen(args, close_fds=True, preexec_fn=os.setsid)
child_pg = child.pid child_pg = child.pid
try: try:
print 'Process %r started' % args print 'Process %r started' % args
while True: signal.pause()
time.sleep(10)
finally: finally:
os.killpg(child_pg, signal.SIGHUP) os.killpg(child_pg, signal.SIGHUP)
os.killpg(child_pg, signal.SIGTERM) os.killpg(child_pg, signal.SIGTERM)
...@@ -33,7 +33,6 @@ import sys ...@@ -33,7 +33,6 @@ import sys
import inspect import inspect
import re import re
import shutil import shutil
from textwrap import dedent
import urllib import urllib
import urlparse import urlparse
...@@ -61,7 +60,13 @@ class GenericBaseRecipe(object): ...@@ -61,7 +60,13 @@ class GenericBaseRecipe(object):
self._options(options) # Options Hook self._options(options) # Options Hook
self.options = options.copy() # Updated options dict self.options = options.copy() # Updated options dict
self._ws = self.getWorkingSet() @property
def _ws(self):
# getWorkingSet() is slow and it is not always needed.
# So _ws should be a lazy attribute.
if getattr(self, '_ws_internal', None) is None:
self._ws_internal = self.getWorkingSet()
return self._ws_internal
def update(self): def update(self):
"""By default update method does the same thing than install""" """By default update method does the same thing than install"""
...@@ -110,92 +115,60 @@ class GenericBaseRecipe(object): ...@@ -110,92 +115,60 @@ class GenericBaseRecipe(object):
with io.open(filepath, 'w+', encoding=encoding) as f: with io.open(filepath, 'w+', encoding=encoding) as f:
f.write(u'\n'.join(lines)) f.write(u'\n'.join(lines))
def createPythonScript(self, name, absolute_function, arguments=''): def createPythonScript(self, name, absolute_function, args=(), kw={}):
"""Create a python script using zc.buildout.easy_install.scripts """Create a python script using zc.buildout.easy_install.scripts
* function should look like 'module.function', or only 'function' * function should look like 'module.function', or only 'function'
if it is a builtin function.""" if it is a builtin function."""
absolute_function = tuple(absolute_function.rsplit('.', 1)) function = absolute_function.rsplit('.', 1)
if len(absolute_function) == 1: if len(function) == 1:
absolute_function = ('__builtin__',) + absolute_function module = '__builtin__'
if len(absolute_function) != 2: function, = function
raise ValueError("A non valid function was given") else:
module, function = function
module, function = absolute_function
path, filename = os.path.split(os.path.abspath(name)) path, filename = os.path.split(os.path.abspath(name))
script = zc.buildout.easy_install.scripts( assert not isinstance(args, (basestring, dict)), args
args = map(repr, args)
args += map('%s=%r'.__mod__, kw.iteritems())
return zc.buildout.easy_install.scripts(
[(filename, module, function)], self._ws, sys.executable, [(filename, module, function)], self._ws, sys.executable,
path, arguments=arguments)[0] path, arguments=', '.join(args))[0]
return script
def createWrapper(self, name, command, parameters, comments=[], def createWrapper(self, path, args, env=None, **kw):
parameters_extra=False, environment=None, """Create a wrapper script for process replacement"""
pidfile=None, reserve_cpu=False assert args
): if kw:
""" return self.createPythonScript(path,
Creates a shell script for process replacement. 'slapos.recipe.librecipe.execute.generic_exec',
Takes care of quoting. (args, env) if env else (args,), kw)
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,
accepting to run only if no other instance is running.
:param reserve_cpu: bool, try to reserve one core for the `command` # Simple case: creates a basic shell script for process replacement.
""" # This must be kept minimal to avoid code duplication with generic_exec.
# In particular, do not implement workaround for shebang size limitation
# here (note that this can't be done correctly with a POSIX shell, because
# the process can't be given a name).
lines = ['#!/bin/sh']
if env:
for k, v in sorted(env.iteritems()):
lines.append('export %s=%s' % (k, shlex.quote(v)))
lines.append('exec')
lines = [ '#!/bin/sh' ] args = map(shlex.quote, args)
args.append('"$@"')
if comments: for arg in args:
lines += '# ', '\n# '.join(comments), '\n'
lines.append('COMMAND=' + shlex.quote(command))
for key in environment or ():
lines.append('export %s=%s' % (key, environment[key]))
if pidfile:
lines.append(dedent("""
# Check for other instances
pidfile=%s
if [ -s $pidfile ]; then
if pid=`pgrep -F $pidfile -f "$COMMAND" 2>/dev/null`; then
echo "Already running with pid $pid."
exit 1
fi
fi
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
"""))
lines.append(dedent('''
# If the wrapped command uses a shebang, execute the referenced
# executable passing the script path as first argument.
# This is to workaround the limitation of 127 characters in #!
[ ! -f "$COMMAND" ] || {
[ "`head -c2`" != "#!" ] || read -r EXE ARG
} < "$COMMAND"
exec $EXE ${ARG:+"$ARG"} "$COMMAND"'''))
parameters = map(shlex.quote, parameters)
if parameters_extra:
# pass-through further parameters
parameters.append('"$@"')
for param in parameters:
if len(lines[-1]) < 40: if len(lines[-1]) < 40:
lines[-1] += ' ' + param lines[-1] += ' ' + arg
else: else:
lines[-1] += ' \\' lines[-1] += ' \\'
lines.append('\t' + param) lines.append('\t' + arg)
lines.append('') lines.append('')
return self.createFile(name, '\n'.join(lines), 0700) return self.createFile(path, '\n'.join(lines), 0700)
def createDirectory(self, parent, name, mode=0700): def createDirectory(self, parent, name, mode=0700):
path = os.path.join(parent, name) path = os.path.join(parent, name)
......
...@@ -46,10 +46,10 @@ class Recipe(GenericBaseRecipe): ...@@ -46,10 +46,10 @@ class Recipe(GenericBaseRecipe):
state_file = self.options['state-file'] state_file = self.options['state-file']
logrotate = self.createPythonScript( logrotate = self.createWrapper(
self.options['wrapper'], self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute', (self.options['logrotate-binary'],
[self.options['logrotate-binary'], '-s', state_file, logrotate_conf_file, ] '-s', state_file, logrotate_conf_file),
) )
return [logrotate, logrotate_conf_file] return [logrotate, logrotate_conf_file]
......
This diff is collapsed.
import os
import subprocess
import time
import ConfigParser
def popenCommunicate(command_list, input=None):
subprocess_kw = dict(stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if input is not None:
subprocess_kw.update(stdin=subprocess.PIPE)
popen = subprocess.Popen(command_list, **subprocess_kw)
result = popen.communicate(input)[0]
if popen.returncode is None:
popen.kill()
if popen.returncode != 0:
raise ValueError('Issue during calling %r, result was:\n%s' % (
command_list, result))
return result
class CertificateAuthority:
def __init__(self, key, certificate, openssl_binary,
openssl_configuration, request_dir):
self.key = key
self.certificate = certificate
self.openssl_binary = openssl_binary
self.openssl_configuration = openssl_configuration
self.request_dir = request_dir
def checkAuthority(self):
file_list = [ self.key, self.certificate ]
ca_ready = True
for f in file_list:
if not os.path.exists(f):
ca_ready = False
break
if ca_ready:
return
for f in file_list:
if os.path.exists(f):
os.unlink(f)
try:
# no CA, let us create new one
popenCommunicate([self.openssl_binary, 'req', '-nodes', '-config',
self.openssl_configuration, '-new', '-x509', '-extensions',
'v3_ca', '-keyout', self.key, '-out', self.certificate,
'-days', '10950'], 'Automatic Certificate Authority\n')
except:
try:
for f in file_list:
if os.path.exists(f):
os.unlink(f)
except:
# do not raise during cleanup
pass
raise
def _checkCertificate(self, common_name, key, certificate):
file_list = [key, certificate]
ready = True
for f in file_list:
if not os.path.exists(f):
ready = False
break
if ready:
return False
for f in file_list:
if os.path.exists(f):
os.unlink(f)
csr = certificate + '.csr'
try:
popenCommunicate([self.openssl_binary, 'req', '-config',
self.openssl_configuration, '-nodes', '-new', '-keyout',
key, '-out', csr, '-days', '3650'],
common_name + '\n')
try:
popenCommunicate([self.openssl_binary, 'ca', '-batch', '-config',
self.openssl_configuration, '-out', certificate,
'-infiles', csr])
finally:
if os.path.exists(csr):
os.unlink(csr)
except:
try:
for f in file_list:
if os.path.exists(f):
os.unlink(f)
except:
# do not raise during cleanup
pass
raise
else:
return True
def checkRequestDir(self):
for request_file in os.listdir(self.request_dir):
parser = ConfigParser.RawConfigParser()
parser.readfp(open(os.path.join(self.request_dir, request_file), 'r'))
if self._checkCertificate(parser.get('certificate', 'name'),
parser.get('certificate', 'key_file'), parser.get('certificate',
'certificate_file')):
print 'Created certificate %r' % parser.get('certificate', 'name')
def runCertificateAuthority(args):
ca_conf = args[0]
ca = CertificateAuthority(ca_conf['key'], ca_conf['certificate'],
ca_conf['openssl_binary'], ca_conf['openssl_configuration'],
ca_conf['request_dir'])
while True:
ca.checkAuthority()
ca.checkRequestDir()
time.sleep(60)
#!/bin/sh
exec %(memcached_binary)s -p %(memcached_port)s -U %(memcached_port)s -l %(memcached_ip)s
This diff is collapsed.
foreground = yes
output = %(log)s
pid = %(pid_file)s
syslog = no
CApath = %(ca_path)s
key = %(key)s
CRLpath = %(ca_crl)s
cert = %(cert)s
[service]
accept = %(public_ip)s:%(public_port)s
connect = %(private_ip)s:%(private_port)s
...@@ -203,11 +203,10 @@ Include conf/extra/httpd-autoindex.conf ...@@ -203,11 +203,10 @@ Include conf/extra/httpd-autoindex.conf
services_dir = self.options['services_dir'] services_dir = self.options['services_dir']
httpd_wrapper = self.createPythonScript( httpd_wrapper = self.createWrapper(
os.path.join(services_dir, 'httpd_wrapper'), os.path.join(services_dir, 'httpd_wrapper'),
'slapos.recipe.librecipe.execute.execute', (self.options['httpd_binary'],
[self.options['httpd_binary'], '-f', self.options['httpd_conf'], '-f', self.options['httpd_conf'], '-DFOREGROUND'),
'-DFOREGROUND']
) )
path_list.append(httpd_wrapper) path_list.append(httpd_wrapper)
...@@ -220,19 +219,17 @@ Include conf/extra/httpd-autoindex.conf ...@@ -220,19 +219,17 @@ Include conf/extra/httpd-autoindex.conf
site_perl_bin = os.path.join(self.options['site_perl'], 'bin') site_perl_bin = os.path.join(self.options['site_perl'], 'bin')
mioga_conf_path = os.path.join(mioga_base, 'conf', 'Mioga.conf') mioga_conf_path = os.path.join(mioga_base, 'conf', 'Mioga.conf')
notifier_wrapper = self.createPythonScript( notifier_wrapper = self.createWrapper(
os.path.join(services_dir, 'notifier'), os.path.join(services_dir, 'notifier'),
'slapos.recipe.librecipe.execute.execute', (os.path.join(site_perl_bin, 'notifier.pl'),
[ os.path.join(site_perl_bin, 'notifier.pl'), mioga_conf_path),
mioga_conf_path ]
) )
path_list.append(notifier_wrapper) path_list.append(notifier_wrapper)
searchengine_wrapper = self.createPythonScript( searchengine_wrapper = self.createWrapper(
os.path.join(services_dir, 'searchengine'), os.path.join(services_dir, 'searchengine'),
'slapos.recipe.librecipe.execute.execute', (os.path.join(site_perl_bin, 'searchengine.pl'),
[ os.path.join(site_perl_bin, 'searchengine.pl'), mioga_conf_path),
mioga_conf_path ]
) )
path_list.append(searchengine_wrapper) path_list.append(searchengine_wrapper)
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# #
############################################################################## ##############################################################################
import subprocess import os
from slapos.recipe.librecipe import GenericBaseRecipe from slapos.recipe.librecipe import GenericBaseRecipe
...@@ -58,14 +58,14 @@ def do_export(args): ...@@ -58,14 +58,14 @@ def do_export(args):
cmd.extend(['-o', args['directory']]) cmd.extend(['-o', args['directory']])
subprocess.check_call(cmd) os.execv(cmd[0], cmd)
def do_import(args): def do_import(args):
cmd = _mydumper_base_cmd(**args) cmd = _mydumper_base_cmd(**args)
cmd.append('--overwrite-tables') cmd.append('--overwrite-tables')
cmd.extend(['-d', args['directory']]) cmd.extend(['-d', args['directory']])
subprocess.check_call(cmd) os.execv(cmd[0], cmd)
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
...@@ -95,9 +95,5 @@ class Recipe(GenericBaseRecipe): ...@@ -95,9 +95,5 @@ class Recipe(GenericBaseRecipe):
config['compression'] = self.optionIsTrue('compression', default=False) config['compression'] = self.optionIsTrue('compression', default=False)
config['rows'] = self.options.get('rows') config['rows'] = self.options.get('rows')
wrapper = self.createPythonScript(name=self.options['wrapper'], return self.createPythonScript(self.options['wrapper'],
absolute_function = '%s.%s' % (__name__, function.func_name), '%s.%s' % (function.__module__, function.__name__), (config,))
arguments=config)
return [wrapper]
...@@ -53,11 +53,10 @@ class Recipe(GenericBaseRecipe): ...@@ -53,11 +53,10 @@ class Recipe(GenericBaseRecipe):
mysql_binary = self.options['mysql-binary'] mysql_binary = self.options['mysql-binary']
socket = self.options['socket'], socket = self.options['socket'],
post_rotate = self.createPythonScript( post_rotate = self.createWrapper(
self.options['logrotate-post'], self.options['logrotate-post'],
'slapos.recipe.librecipe.execute.execute', (mysql_binary, '--no-defaults', '-B', '-u', 'root',
[mysql_binary, '--no-defaults', '-B', '-u', 'root', '--socket=%s' % socket, '-e', '--socket=%s' % socket, '-e', 'FLUSH LOGS'),
'FLUSH LOGS']
) )
path_list.append(post_rotate) path_list.append(post_rotate)
...@@ -85,12 +84,12 @@ class Recipe(GenericBaseRecipe): ...@@ -85,12 +84,12 @@ class Recipe(GenericBaseRecipe):
mysql_update = self.createPythonScript( mysql_update = self.createPythonScript(
self.options['update-wrapper'], self.options['update-wrapper'],
'%s.mysql.updateMysql' % __name__, '%s.mysql.updateMysql' % __name__,
dict( (dict(
mysql_script=mysql_script, mysql_script=mysql_script,
mysql_binary=mysql_binary, mysql_binary=mysql_binary,
mysql_upgrade_binary=mysql_upgrade_binary, mysql_upgrade_binary=mysql_upgrade_binary,
socket=socket, socket=socket,
) ),)
) )
path_list.append(mysql_update) path_list.append(mysql_update)
...@@ -98,7 +97,7 @@ class Recipe(GenericBaseRecipe): ...@@ -98,7 +97,7 @@ class Recipe(GenericBaseRecipe):
mysqld = self.createPythonScript( mysqld = self.createPythonScript(
self.options['wrapper'], self.options['wrapper'],
'%s.mysql.runMysql' % __name__, '%s.mysql.runMysql' % __name__,
dict( (dict(
mysql_install_binary=self.options['mysql-install-binary'], mysql_install_binary=self.options['mysql-install-binary'],
mysqld_binary=mysqld_binary, mysqld_binary=mysqld_binary,
data_directory=mysql_conf['data_directory'], data_directory=mysql_conf['data_directory'],
...@@ -106,7 +105,7 @@ class Recipe(GenericBaseRecipe): ...@@ -106,7 +105,7 @@ class Recipe(GenericBaseRecipe):
socket=socket, socket=socket,
configuration_file=mysql_conf_file, configuration_file=mysql_conf_file,
cwd=self.options['mysql-base-directory'], cwd=self.options['mysql-base-directory'],
) ),)
) )
path_list.append(mysqld) path_list.append(mysqld)
...@@ -115,12 +114,12 @@ class Recipe(GenericBaseRecipe): ...@@ -115,12 +114,12 @@ class Recipe(GenericBaseRecipe):
backup_script = self.createPythonScript( backup_script = self.createPythonScript(
self.options['backup-script'], self.options['backup-script'],
'%s.do_backup' % __name__, '%s.do_backup' % __name__,
dict( (dict(
mydumper_binary=self.options['mydumper-binary'], mydumper_binary=self.options['mydumper-binary'],
database=mysql_conf['mysql_database'], database=mysql_conf['mysql_database'],
socket=mysql_conf['socket'], socket=mysql_conf['socket'],
backup_directory=self.options['backup-directory'] backup_directory=self.options['backup-directory']
), ),)
) )
path_list.append(backup_script) path_list.append(backup_script)
...@@ -129,7 +128,7 @@ class Recipe(GenericBaseRecipe): ...@@ -129,7 +128,7 @@ class Recipe(GenericBaseRecipe):
recovering_script = self.createPythonScript( recovering_script = self.createPythonScript(
self.options['recovering-wrapper'], self.options['recovering-wrapper'],
'%s.import_dump' % __name__, '%s.import_dump' % __name__,
{ ({
'lock_file': os.path.join(self.work_directory, 'lock_file': os.path.join(self.work_directory,
'import_done'), 'import_done'),
'database': mysql_conf['mysql_database'], 'database': mysql_conf['mysql_database'],
...@@ -140,7 +139,7 @@ class Recipe(GenericBaseRecipe): ...@@ -140,7 +139,7 @@ class Recipe(GenericBaseRecipe):
'local_directory': self.mysql_backup_directory, 'local_directory': self.mysql_backup_directory,
'dump_name': dump_filename, 'dump_name': dump_filename,
'zcat_binary': self.options['zcat-binary'], 'zcat_binary': self.options['zcat-binary'],
} },)
) )
path_list.append(recovering_script) path_list.append(recovering_script)
......
...@@ -42,7 +42,8 @@ class NeoBaseRecipe(GenericBaseRecipe): ...@@ -42,7 +42,8 @@ class NeoBaseRecipe(GenericBaseRecipe):
# Only then can this recipe start succeeding and actually doing anything # Only then can this recipe start succeeding and actually doing anything
# useful, as per NEO deploying constraints. # useful, as per NEO deploying constraints.
raise UserError('"masters" parameter is mandatory') raise UserError('"masters" parameter is mandatory')
option_list = [ args = [
options['binary'],
# Keep the -l option first, as expected by logrotate snippets. # Keep the -l option first, as expected by logrotate snippets.
'-l', options['logfile'], '-l', options['logfile'],
'-m', options['masters'], '-m', options['masters'],
...@@ -53,17 +54,13 @@ class NeoBaseRecipe(GenericBaseRecipe): ...@@ -53,17 +54,13 @@ class NeoBaseRecipe(GenericBaseRecipe):
] ]
if options['ssl']: if options['ssl']:
etc = os.path.join(self.buildout['buildout']['directory'], 'etc', '') etc = os.path.join(self.buildout['buildout']['directory'], 'etc', '')
option_list += ( args += (
'--ca', etc + 'ca.crt', '--ca', etc + 'ca.crt',
'--cert', etc + 'neo.crt', '--cert', etc + 'neo.crt',
'--key', etc + 'neo.key', '--key', etc + 'neo.key',
) )
option_list.extend(self._getOptionList()) args += self._getOptionList()
return [self.createWrapper( return self.createWrapper(options['wrapper'], args)
options['wrapper'],
options['binary'],
option_list
)]
def _getBindingAddress(self): def _getBindingAddress(self):
options = self.options options = self.options
......
...@@ -32,19 +32,15 @@ class Recipe(GenericBaseRecipe): ...@@ -32,19 +32,15 @@ class Recipe(GenericBaseRecipe):
def install(self): def install(self):
options = self.options options = self.options
script = self.createWrapper(name=options['wrapper'], # Script that execute the callback(s) upon receiving a notification.
command=options['server-binary'], return self.createWrapper(options['wrapper'],
parameters=[ (options['server-binary'],
'--callbacks', options['callbacks'], '--callbacks', options['callbacks'],
'--feeds', options['feeds'], '--feeds', options['feeds'],
'--equeue-socket', options['equeue-socket'], '--equeue-socket', options['equeue-socket'],
options['host'], options['port'] options['host'], options['port']
], ),
comments=[ )
'',
'Upon receiving a notification, execute the callback(s).',
''])
return [script]
class Callback(GenericBaseRecipe): class Callback(GenericBaseRecipe):
...@@ -80,35 +76,32 @@ class Notify(GenericBaseRecipe): ...@@ -80,35 +76,32 @@ class Notify(GenericBaseRecipe):
# Just a touch # Just a touch
open(log, 'w').close() open(log, 'w').close()
parameters = [ cmd = [notifier_binary,
'-l', log, '-l', log,
'--title', title, '--title', title,
'--feed', feed_url, '--feed', feed_url,
'--max-run', str(max_run), '--max-run', str(max_run),
'--notification-url', '--notification-url',
] ]
parameters.extend(notification_url.split(' ')) cmd += notification_url.split(' ')
parameters.extend(['--executable', executable]) cmd += '--executable', executable
# For a more verbose mode, writing feed items for any action # For a more verbose mode, writing feed items for any action
instance_root_name = instance_root_name or self.options.get('instance-root-name', None) instance_root_name = instance_root_name or self.options.get('instance-root-name', None)
log_url = log_url or self.options.get('log-url', None) log_url = log_url or self.options.get('log-url', None)
status_item_directory = status_item_directory or self.options.get('status-item-directory', None) status_item_directory = status_item_directory or self.options.get('status-item-directory', None)
if instance_root_name and log_url and status_item_directory: if instance_root_name and log_url and status_item_directory:
parameters.extend([ cmd += (
'--instance-root-name', instance_root_name, '--instance-root-name', instance_root_name,
'--log-url', log_url, '--log-url', log_url,
'--status-item-directory', status_item_directory, '--status-item-directory', status_item_directory,
]) )
return self.createWrapper(name=wrapper, kw = {}
command=notifier_binary, if pidfile:
parameters=parameters, kw['pidfile'] = pidfile
pidfile=pidfile,
parameters_extra=True, # Script that call an executable and send notification(s).
comments=[ return self.createWrapper(wrapper, cmd, **kw)
'',
'Call an executable and send notification(s).',
''])
def install(self): def install(self):
......
...@@ -35,10 +35,9 @@ class Recipe(GenericBaseRecipe): ...@@ -35,10 +35,9 @@ class Recipe(GenericBaseRecipe):
""" """
def install(self): def install(self):
runner_path = self.createPythonScript( return self.createWrapper(
self.options['path'], self.options['path'],
'slapos.recipe.librecipe.execute.execute_wait', (
[[
self.options['websockify-path'], self.options['websockify-path'],
'--web', '--web',
self.options['novnc-location'], self.options['novnc-location'],
...@@ -47,8 +46,7 @@ class Recipe(GenericBaseRecipe): ...@@ -47,8 +46,7 @@ class Recipe(GenericBaseRecipe):
'--ssl-only', '--ssl-only',
'%s:%s' % (self.options['ip'], self.options['port']), '%s:%s' % (self.options['ip'], self.options['port']),
'%s:%s' % (self.options['vnc-ip'], self.options['vnc-port']), '%s:%s' % (self.options['vnc-ip'], self.options['vnc-port']),
], ),
[self.options['ssl-key-path'], self.options['ssl-cert-path']]], wait_list=(self.options['ssl-key-path'],
self.options['ssl-cert-path']),
) )
return [runner_path]
...@@ -39,30 +39,18 @@ from slapos.recipe.notifier import Callback ...@@ -39,30 +39,18 @@ from slapos.recipe.notifier import Callback
from slapos.recipe.librecipe import shlex from slapos.recipe.librecipe import shlex
def promise(args): def promise(ssh_client, user, host, port):
# Redirect output to /dev/null # Redirect output to /dev/null
with open("/dev/null") as _dev_null: with open(os.devnull) as _dev_null:
ssh = subprocess.Popen( ssh = subprocess.Popen(
[args['ssh_client'], '%(user)s@%(host)s' % args, '-p', '%(port)s' % args], (ssh_client, '%s@%s' % (user, host), '-p', str(port)),
stdin=subprocess.PIPE, stdout=_dev_null, stderr=None stdin=subprocess.PIPE, stdout=_dev_null)
) ssh.communicate('q' + chr(255) + chr(0) * 7)
if ssh.returncode:
# Rdiff Backup protocol quit command
quitcommand = 'q' + chr(255) + chr(0) * 7
ssh.stdin.write(quitcommand)
ssh.stdin.flush()
ssh.stdin.close()
ssh.wait()
if ssh.poll() is None:
return 1
if ssh.returncode != 0:
sys.stderr.write("SSH Connection failed\n") sys.stderr.write("SSH Connection failed\n")
return ssh.returncode return ssh.returncode
class Recipe(GenericSlapRecipe, Notify, Callback): class Recipe(GenericSlapRecipe, Notify, Callback):
def _options(self, options): def _options(self, options):
options['rdiff-backup-data-folder'] = "" options['rdiff-backup-data-folder'] = ""
...@@ -244,15 +232,11 @@ class Recipe(GenericSlapRecipe, Notify, Callback): ...@@ -244,15 +232,11 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
print 'Processing PBS slave %s with type %s' % (slave_id, slave_type) print 'Processing PBS slave %s with type %s' % (slave_id, slave_type)
promise_path = os.path.join(self.options['promises-directory'], "ssh-to-%s" % slave_id) path_list.append(self.createPythonScript(
promise_dict = dict(ssh_client=self.options['sshclient-binary'], os.path.join(self.options['promises-directory'], "ssh-to-%s" % slave_id),
user=parsed_url.username, __name__ + '.promise',
host=parsed_url.hostname, (self.options['sshclient-binary'],
port=parsed_url.port) parsed_url.username, parsed_url.hostname, parsed_url.port)))
promise = self.createPythonScript(promise_path,
__name__ + '.promise',
promise_dict)
path_list.append(promise)
# Create known_hosts file by default. # Create known_hosts file by default.
# In some case, we don't want to create it (case where we share IP mong partitions) # In some case, we don't want to create it (case where we share IP mong partitions)
...@@ -336,12 +320,11 @@ class Recipe(GenericSlapRecipe, Notify, Callback): ...@@ -336,12 +320,11 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
else: else:
self.logger.info("Server mode") self.logger.info("Server mode")
wrapper = self.createWrapper(name=self.options['wrapper'], wrapper = self.createWrapper(self.options['wrapper'],
command=self.options['rdiffbackup-binary'], (self.options['rdiffbackup-binary'],
parameters=[
'--restrict', self.options['path'], '--restrict', self.options['path'],
'--server' '--server'
]) ))
path_list.append(wrapper) path_list.append(wrapper)
return path_list return path_list
...@@ -162,7 +162,6 @@ class Recipe(GenericBaseRecipe): ...@@ -162,7 +162,6 @@ class Recipe(GenericBaseRecipe):
return hash_string return hash_string
def install(self): def install(self):
path_list = []
token_save_path = os.path.join(self.options['conf-dir'], 'token.json') token_save_path = os.path.join(self.options['conf-dir'], 'token.json')
token_list_path = self.options['token-dir'] token_list_path = self.options['token-dir']
...@@ -190,20 +189,14 @@ class Recipe(GenericBaseRecipe): ...@@ -190,20 +189,14 @@ class Recipe(GenericBaseRecipe):
self.createFile(token_save_path, json.dumps(token_dict)) self.createFile(token_save_path, json.dumps(token_dict))
service_dict = dict(token_base_path=token_list_path, computer_dict = dict(partition_id=self.computer_partition_id,
token_json=token_save_path, computer_guid=self.computer_id,
partition_id=self.computer_partition_id, master_url=self.server_url,
computer_id=self.computer_id,
registry_url=registry_url,
server_url=self.server_url,
cert_file=self.cert_file, cert_file=self.cert_file,
key_file=self.key_file) key_file=self.key_file)
request_add = self.createPythonScript( return self.createPythonScript(
self.options['manager-wrapper'].strip(), self.options['manager-wrapper'].strip(),
'%s.re6stnet.manage' % __name__, service_dict __name__ + '.re6stnet.manage',
(registry_url, token_list_path, token_save_path, computer_dict)
) )
path_list.append(request_add)
return path_list
...@@ -17,10 +17,8 @@ logging.trace = logging.debug ...@@ -17,10 +17,8 @@ logging.trace = logging.debug
def loadJsonFile(path): def loadJsonFile(path):
if os.path.exists(path): if os.path.exists(path):
with open(path, 'r') as f: with open(path, 'r') as f:
content = f.read() return json.load(f)
return json.loads(content) return {}
else:
return {}
def writeFile(path, data): def writeFile(path, data):
with open(path, 'w') as f: with open(path, 'w') as f:
...@@ -39,29 +37,25 @@ def updateFile(file_path, value): ...@@ -39,29 +37,25 @@ def updateFile(file_path, value):
return True return True
return False return False
def getComputerPartition(server_url, key_file, cert_file, computer_guid, partition_id): def getComputerPartition(master_url, key_file, cert_file,
computer_guid, partition_id):
slap = slapos.slap.slap() slap = slapos.slap.slap()
# Redeploy instance to update published information # Redeploy instance to update published information
slap.initializeConnection(server_url, slap.initializeConnection(master_url, key_file, cert_file)
key_file, return slap.registerComputerPartition(computer_guid, partition_id)
cert_file)
return slap.registerComputerPartition(computer_guid=computer_guid,
partition_id=partition_id)
def requestAddToken(client, base_token_path): def requestAddToken(client, token_base_path):
time.sleep(3) time.sleep(3)
path_list = [x for x in os.listdir(base_token_path) if x.endswith('.add')] path_list = [x for x in os.listdir(token_base_path) if x.endswith('.add')]
log.info("Searching tokens to add at %s and found %s." % (base_token_path, path_list)) log.info("Searching tokens to add at %s and found %s." % (token_base_path, path_list))
if not path_list: if not path_list:
log.info("No new token to add. Exiting...") log.info("No new token to add. Exiting...")
return return
for reference_key in path_list: for reference_key in path_list:
request_file = os.path.join(base_token_path, reference_key) request_file = os.path.join(token_base_path, reference_key)
token = readFile(request_file) token = readFile(request_file)
log.info("Including token %s for %s" % (token, reference_key)) log.info("Including token %s for %s" % (token, reference_key))
if token : if token :
...@@ -79,21 +73,21 @@ def requestAddToken(client, base_token_path): ...@@ -79,21 +73,21 @@ def requestAddToken(client, base_token_path):
# update information # update information
log.info("New token added for slave instance %s. Updating file status..." % log.info("New token added for slave instance %s. Updating file status..." %
reference) reference)
status_file = os.path.join(base_token_path, '%s.status' % reference) status_file = os.path.join(token_base_path, '%s.status' % reference)
updateFile(status_file, 'TOKEN_ADDED') updateFile(status_file, 'TOKEN_ADDED')
os.unlink(request_file) os.unlink(request_file)
else: else:
log.debug('Bad token. Request add token fail for %s...' % request_file) log.debug('Bad token. Request add token fail for %s...' % request_file)
def requestRemoveToken(client, base_token_path): def requestRemoveToken(client, token_base_path):
path_list = [x for x in os.listdir(base_token_path) if x.endswith('.remove')] path_list = [x for x in os.listdir(token_base_path) if x.endswith('.remove')]
if not path_list: if not path_list:
log.info("No token to delete. Exiting...") log.info("No token to delete. Exiting...")
return return
for reference_key in path_list: for reference_key in path_list:
request_file = os.path.join(base_token_path, reference_key) request_file = os.path.join(token_base_path, reference_key)
token = readFile(request_file) token = readFile(request_file)
if token : if token :
reference = reference_key.split('.')[0] reference = reference_key.split('.')[0]
...@@ -108,7 +102,7 @@ def requestRemoveToken(client, base_token_path): ...@@ -108,7 +102,7 @@ def requestRemoveToken(client, base_token_path):
continue continue
else: else:
# certificate is invalidated, it will be revoked # certificate is invalidated, it will be revoked
writeFile(os.path.join(base_token_path, '%s.revoke' % reference), '') writeFile(os.path.join(token_base_path, '%s.revoke' % reference), '')
if result in (True, 'True'): if result in (True, 'True'):
# update information # update information
...@@ -117,33 +111,17 @@ def requestRemoveToken(client, base_token_path): ...@@ -117,33 +111,17 @@ def requestRemoveToken(client, base_token_path):
if result in ['True', 'False']: if result in ['True', 'False']:
os.unlink(request_file) os.unlink(request_file)
status_file = os.path.join(base_token_path, '%s.status' % reference) status_file = os.path.join(token_base_path, '%s.status' % reference)
if os.path.exists(status_file): if os.path.exists(status_file):
os.unlink(status_file) os.unlink(status_file)
ipv6_file = os.path.join(base_token_path, '%s.ipv6' % reference) ipv6_file = os.path.join(token_base_path, '%s.ipv6' % reference)
if os.path.exists(ipv6_file): if os.path.exists(ipv6_file):
os.unlink(ipv6_file) os.unlink(ipv6_file)
else: else:
log.debug('Bad token. Request add token fail for %s...' % request_file) log.debug('Bad token. Request add token fail for %s...' % request_file)
def requestRevoqueCertificate(args): def checkService(client, token_base_path, token_json, computer_partition):
base_token_path = args['token_base_path']
path_list = [x for x in os.listdir(base_token_path) if x.endswith('.revoke')]
for reference_key in path_list:
reference = reference_key.split('.')[0]
if revokeByMail(args['registry_url'],
'%s@slapos' % reference.lower(),
args['db']):
os.unlink(os.path.join(base_token_path, reference_key))
log.info("Certificate revoked for slave instance %s." % reference)
return
log.info("Failed to revoke email for %s" % reference)
def checkService(client, base_token_path, token_json, computer_partition):
token_dict = loadJsonFile(token_json) token_dict = loadJsonFile(token_json)
updated = False updated = False
if not token_dict: if not token_dict:
...@@ -152,7 +130,7 @@ def checkService(client, base_token_path, token_json, computer_partition): ...@@ -152,7 +130,7 @@ def checkService(client, base_token_path, token_json, computer_partition):
# Check token status # Check token status
for slave_reference, token in token_dict.iteritems(): for slave_reference, token in token_dict.iteritems():
log.info("%s %s" % (slave_reference, token)) log.info("%s %s" % (slave_reference, token))
status_file = os.path.join(base_token_path, '%s.status' % slave_reference) status_file = os.path.join(token_base_path, '%s.status' % slave_reference)
if not os.path.exists(status_file): if not os.path.exists(status_file):
# This token is not added yet! # This token is not added yet!
log.info("Token %s dont exist yet." % status_file) log.info("Token %s dont exist yet." % status_file)
...@@ -206,31 +184,22 @@ def checkService(client, base_token_path, token_json, computer_partition): ...@@ -206,31 +184,22 @@ def checkService(client, base_token_path, token_json, computer_partition):
slave_reference, traceback.format_exc()) slave_reference, traceback.format_exc())
def manage(args, can_bang=True): def manage(registry_url, token_base_path, token_json,
computer_dict, can_bang=True):
computer_guid = args['computer_id']
partition_id = args['partition_id']
server_url = args['server_url']
key_file = args['key_file']
cert_file = args['cert_file']
client = registry.RegistryClient(args['registry_url']) client = registry.RegistryClient(registry_url)
base_token_path = args['token_base_path']
token_json = args['token_json']
log.info("ADD TOKEN") log.info("ADD TOKEN")
# Request Add new tokens # Request Add new tokens
requestAddToken(client, base_token_path) requestAddToken(client, token_base_path)
log.info("Remove TOKEN") log.info("Remove TOKEN")
# Request delete removed token # Request delete removed token
requestRemoveToken(client, base_token_path) requestRemoveToken(client, token_base_path)
computer_partition = getComputerPartition(server_url, key_file, computer_partition = getComputerPartition(**computer_dict)
cert_file, computer_guid, partition_id)
log.info("Update Services") log.info("Update Services")
# check status of all token # check status of all token
checkService(client, base_token_path, checkService(client, token_base_path, token_json, computer_partition)
token_json, computer_partition)
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
# #
############################################################################## ##############################################################################
import os import os
import sys
from slapos.recipe.librecipe import GenericBaseRecipe from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
...@@ -56,10 +56,9 @@ class Recipe(GenericBaseRecipe): ...@@ -56,10 +56,9 @@ class Recipe(GenericBaseRecipe):
configuration)) configuration))
path_list.append(config) path_list.append(config)
redis = self.createPythonScript( redis = self.createWrapper(
self.options['wrapper'], self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute', (self.options['server_bin'], config_file),
[self.options['server_bin'], config_file]
) )
path_list.append(redis) path_list.append(redis)
...@@ -67,11 +66,20 @@ class Recipe(GenericBaseRecipe): ...@@ -67,11 +66,20 @@ class Recipe(GenericBaseRecipe):
if promise_script: if promise_script:
promise = self.createPythonScript( promise = self.createPythonScript(
promise_script, promise_script,
'%s.promise.main' % __name__, __name__ + '.promise',
dict(host=self.options['ipv6'], port=self.options['port'], (self.options['ipv6'], int(self.options['port']),
unixsocket = self.options.get('unixsocket') ) self.options.get('unixsocket'))
) )
path_list.append(promise) path_list.append(promise)
return path_list return path_list
def promise(host, port, unixsocket):
from .MyRedis2410 import Redis
try:
r = Redis(host=host, port=port, unix_socket_path=unixsocket, db=0)
r.publish("Promise-Service","SlapOS Promise")
r.connection_pool.disconnect()
except Exception, e:
sys.exit(e)
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import slapos.recipe.redis.MyRedis2410 as redis
import sys
def main(args):
host = args['host']
port = int(args['port'])
unixsocket = args['unixsocket']
try:
r = redis.Redis(host=host, port=port, unix_socket_path=unixsocket, db=0)
r.publish("Promise-Service","SlapOS Promise")
r.connection_pool.disconnect()
sys.exit(0)
except Exception, e:
print str(e)
sys.exit(1)
\ No newline at end of file
...@@ -70,14 +70,12 @@ class Recipe(GenericSlapRecipe): ...@@ -70,14 +70,12 @@ class Recipe(GenericSlapRecipe):
path_list.append(nginx_configuration_file) path_list.append(nginx_configuration_file)
# Generate Nginx wrapper # Generate Nginx wrapper
wrapper = self.createWrapper( path_list.append(self.createWrapper(
name=self.options['wrapper'], self.options['wrapper'],
command=self.options['nginx-executable'], (self.options['nginx-executable'],
parameters=[
'-c', self.options['configuration-file'], '-c', self.options['configuration-file'],
'-p', self.options['home-directory'] '-p', self.options['home-directory']
] )))
)
# TODO: reload configuration or have feature like apache_map # TODO: reload configuration or have feature like apache_map
......
...@@ -25,23 +25,15 @@ ...@@ -25,23 +25,15 @@
# #
############################################################################# #############################################################################
import os
import sys
import zc.buildout
from slapos.recipe.librecipe import BaseSlapRecipe
from slapos.recipe.librecipe import GenericBaseRecipe from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
def install(self):
runner = self.createPythonScript( def install(self):
return self.createPythonScript(
self.options['runner-path'], self.options['runner-path'],
__name__+'.testrunner.run', __name__+'.testrunner.run',
arguments=[self.options['suite-url'], (self.options['suite-url'],
self.options['report-url'], self.options['report-url'],
self.options['report-project'], self.options['report-project'],
self.options['browser'], self.options['browser']))
])
return [runner]
...@@ -36,12 +36,7 @@ import urlparse ...@@ -36,12 +36,7 @@ import urlparse
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import signal import signal
def run(args): def run(suite_url, report_url, project, browser_binary):
suite_url = args[0]
report_url = args[1]
project = args[2]
browser_binary = args[3]
suite_parsed = urlparse.urlparse(suite_url) suite_parsed = urlparse.urlparse(suite_url)
config = { config = {
......
...@@ -31,27 +31,12 @@ from slapos.recipe.librecipe import GenericBaseRecipe ...@@ -31,27 +31,12 @@ from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
def install(self): def install(self):
env = os.environ.copy()
path_list = self.options['path'].split('\n')
env.update(PATH=':'.join(path_list))
env.update(SHELL=self.options['shell'])
env.update(HOME=self.options['home'])
ps1 = self.options.get('ps1') ps1 = self.options.get('ps1')
if ps1 is not None: shell = self.options['shell']
env.update(PS1=str(json.loads(ps1))) env = {
else: 'HOME': self.options['home'],
env.update(PS1=env.get('PS1', '> ')) 'PATH': ':'.join(self.options['path'].split('\n')),
'PS1': str(json.loads(ps1)) if ps1 else os.getenv('PS1', '> '),
wrapper = self.createPythonScript( 'SHELL': shell,
self.options['wrapper'], }
'slapos.recipe.librecipe.execute.executee', return self.createWrapper(self.options['wrapper'], (shell,), env)
[ # Executable
[self.options['shell']],
# Environment
env
]
)
return [wrapper]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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