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

Merge branch 'master' into clearroad

parents c44e2f89 503a278b
......@@ -2,6 +2,7 @@
extends =
../coreutils/buildout.cfg
../patch/buildout.cfg
../randomsleep/buildout.cfg
parts = dcron-output
......@@ -18,6 +19,7 @@ make-options =
post-make-hook = ${:_profile_base_location_}/dcron-hooks.py#860e914dff4108b47565965fe5ebc7b5:post_make_hook
environment =
PATH=${patch:location}/bin:%(PATH)s
randomsleep_install = ${randomsleep:location}
[dcron-output]
# Shared binary location to ease migration
......
......@@ -7,14 +7,15 @@ extends =
../bzip2/buildout.cfg
../zlib/buildout.cfg
../bzip2/buildout.cfg
../gperf/buildout.cfg
parts =
fontconfig
[fontconfig]
recipe = slapos.recipe.cmmi
url = http://fontconfig.org/release/fontconfig-2.12.1.tar.bz2
md5sum = b5af5a423ee3b5cfc34846838963c058
url = http://fontconfig.org/release/fontconfig-2.12.6.tar.bz2
md5sum = 733f5e2371ca77b69707bd7b30cc2163
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?
configure-options =
......@@ -23,7 +24,7 @@ configure-options =
--enable-libxml2
--with-default-fonts=${fonts:location}
environment =
PATH=${pkgconfig:location}/bin:%(PATH)s
PATH=${pkgconfig:location}/bin:${gperf:location}/bin:%(PATH)s
PKG_CONFIG_PATH=${:pkg_config_depends}
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
......@@ -2,6 +2,7 @@
# Mostly required to support languages different than C or C++
[buildout]
extends =
../gettext/buildout.cfg
../gmp/buildout.cfg
../perl/buildout.cfg
../tar/buildout.cfg
......@@ -32,7 +33,7 @@ configure-options =
--with-as=${binutils:location}/bin/as
environment =
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-common
......
......@@ -34,8 +34,8 @@ make-targets= cd src && ./make.bash && cp -alf .. ${:location}
[golang18]
<= golang-common
url = https://storage.googleapis.com/golang/go1.8.3.src.tar.gz
md5sum = 64e9380e07bba907e26a00cf5fcbe77e
url = https://dl.google.com/go/go1.8.7.src.tar.gz
md5sum = c61cfe9c85e7d42f903d3fe146d7cde6
# go1.8 needs go1.4 to bootstrap
environment-extra =
......@@ -43,8 +43,8 @@ environment-extra =
[golang19]
<= golang-common
url = https://storage.googleapis.com/golang/go1.9.2.src.tar.gz
md5sum = 44105c865a1a810464df79233a05a568
url = https://dl.google.com/go/go1.9.4.src.tar.gz
md5sum = 6816441fd6680c63865cdd5cb8bc1960
# go1.9 needs go1.4 to bootstrap
environment-extra =
......@@ -63,6 +63,11 @@ environment-extra =
# lab.nexedi.com/kirr/neo/go/... \
# github.com/pkg/profile \
# 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]
directory = ${buildout:directory}/go.work
src = ${:directory}/src
......@@ -72,6 +77,9 @@ depends = ${gowork.goinstall:recipe}
# go version used for the workspace (possible to override in applications)
golang = ${golang19:location}
# no special build flags by default
buildflags =
# everything is done by dependent parts
recipe = plone.recipe.command
command = :
......@@ -100,7 +108,7 @@ stop-on-error = true
# clients should put package list to install to gowork:install ("..." requests installing everything)
[gowork.goinstall]
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}
stop-on-error = true
......@@ -115,7 +123,7 @@ git-executable = ${git:location}/bin/git
# 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
# generated with the help of go-pkg-snapshot tool.
# generated with the help of gowork-snapshot tool.
[go-git-package]
<= git-repository
location = ${gowork:src}/${:go.importpath}
......@@ -25,9 +25,16 @@ gogit_list() {
# git_upstream_url <repo> - show current branch upstream URL
git_upstream_url() {
repo=$1
head="`git -C $repo symbolic-ref --short HEAD`" # current branch - e.g. "t"
remote="`git -C $repo config --get branch.$head.remote`" # upstream name, e.g. "kirr"
url="`git -C $repo config --get remote.$remote.url`" # upstream URL
head="`git -C $repo symbolic-ref -q --short HEAD`" # current branch - e.g. "master"
if [ -z $head ] ; then
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"
}
......@@ -59,5 +66,5 @@ while read pkg url rev; do
echo "<= go-git-package"
echo "go.importpath = $pkg"
echo "repository = $url"
echo "revision = $rev"
echo "revision = $rev"
done
......@@ -2,6 +2,7 @@
extends =
../hdf5/buildout.cfg
../cython/buildout.cfg
../numpy/buildout.cfg
parts =
h5py
......@@ -12,7 +13,9 @@ CPPFLAGS = -I${hdf5:location}/include
[h5py]
recipe = zc.recipe.egg:custom
egg = h5py
setup-eggs = ${cython:egg}
setup-eggs =
${cython:egg}
${numpy:egg}
include-dirs =
${hdf5:location}/include
library-dirs =
......
......@@ -11,8 +11,8 @@ parts =
[libxml2]
recipe = slapos.recipe.cmmi
url = http://xmlsoft.org/sources/libxml2-2.9.5.tar.gz
md5sum = 5ce0da9bdaa267b40c4ca36d35363b8b
url = http://xmlsoft.org/sources/libxml2-2.9.7.tar.gz
md5sum = 896608641a08b465098a40ddf51cefba
configure-options =
--disable-static
--without-python
......
......@@ -7,8 +7,8 @@ parts =
libxslt
[libxslt]
url = ftp://xmlsoft.org/libxslt/libxslt-1.1.30.tar.gz
md5sum = 70becbbcb1dad55f14de0b84171b91d5
url = ftp://xmlsoft.org/libxslt/libxslt-1.1.32.tar.gz
md5sum = 1fc72f98e98bf4443f1651165f3aa146
recipe = slapos.recipe.cmmi
configure-options =
--disable-static
......@@ -20,5 +20,3 @@ configure-options =
environment =
CPPFLAGS=-I${zlib:location}/include
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 =
[mariadb]
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
version = 10.1.29
md5sum = 6d2cc6b0f8c5c7525e08aaddad8dca96
version = 10.1.31
md5sum = 14ab0398c019eb531bc29f2c437ccb51
patch-options = -p0
patches =
${:_profile_base_location_}/mariadb_10.1.21_create_system_tables__no_test.patch#3c76aa9564a162f13aced7c0a3f783b3
......
# Do not extend any file that touch buildout:parts.
[mariadb]
version = 10.2.11
md5sum = 954088299fe5f11b4fda3b540558adbd
version = 10.2.13
md5sum = 20c61bd4059ba287e54cfb2862bae81d
stable-patches =
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_CXX_COMPILER=${gcc:location}/bin/g++
extra_cflags = -I${zstd:location}/include
......
......@@ -18,6 +18,7 @@ patch-options = -p0
patch-binary = ${patch:location}/bin/patch
patches =
http://nginx.org/download/patch.2017.ranges.txt#40bf9f37c881cb3b10cfefd84ca92f6a
${:_profile_base_location_}/fix-gcc7-implicit-fallthrough-errors.patch
[nginx]
<= 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 =
${matplotlib:egg}
${pillow-python:egg}
patches =
${:_profile_base_location_}/ocropy.patch
patch-options = -p0
${:_profile_base_location_}/ocropy.patch#dd7a02e1e63ed9df68e3a539b3e919eb
patch-options = -p1
patch-binary = ${patch:location}/bin/patch
environment = ocropy-env
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
--- ocrolib/__init__.py
+++ ocrolib/__init__.py
--- a/ocrolib/__init__.py
+++ b/ocrolib/__init__.py
@@ -1,7 +1,7 @@
__all__ = [
"binnednn","cairoextras","common","components","dbtables",
......@@ -11,18 +27,18 @@ index 1e0d627..81e85fb 100644
]
################################################################
@@ -9,5 +9,6 @@ __all__ = [
@@ -9,5 +9,6 @@
################################################################
import default
+from psegutils import *
from common import *
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
--- ocrolib/common.py
+++ ocrolib/common.py
@@ -14,6 +14,7 @@ import unicodedata
--- a/ocrolib/common.py
+++ b/ocrolib/common.py
@@ -14,6 +14,7 @@
import inspect
import glob
import cPickle
......@@ -38,7 +54,7 @@ index 27c0f26..14f088f 100644
def load_object(fname,zip=0,nofind=0,verbose=0):
"""Loads an object from disk. By default, this handles zipped files
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"):
zip = 1
if zip>0:
......@@ -57,10 +73,10 @@ index 27c0f26..14f088f 100644
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
--- ocrolib/native.py
+++ ocrolib/native.py
--- a/ocrolib/native.py
+++ b/ocrolib/native.py
@@ -44,6 +44,7 @@ class CompileError(Exception):
def compile_and_find(c_string,prefix=".pynative",opt="-g -O4",libs="-lm",
......@@ -69,22 +85,22 @@ index b7a207f..240450b 100644
if not os.path.exists(prefix):
os.mkdir(prefix)
m = hashlib.md5()
diff --git setup.py setup.py
index 2ec5832..6697b12 100644
--- setup.py
+++ setup.py
@@ -10,7 +10,9 @@ assert sys.version_info[0]==2 and sys.version_info[1]>=7,\
diff --git a/setup.py b/setup.py
index 2ec5832..0ad4d85 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,9 @@
from distutils.core import setup #, Extension, Command
#from distutils.command.install_data import install_data
-if not os.path.exists("models/en-default.pyrnn.gz"):
+models = os.environ.get('OCROPY_MODEL_PATH', '').split(':') or \
+ [c for c in glob.glob("models/*pyrnn.gz")]
+models = os.environ.get('OCROPY_MODEL_PATH')
+models = models.split(':') if models else glob.glob("models/*pyrnn.gz")
+if not models:
print()
print("You should download the default model 'en-default.pyrnn.gz'")
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("of model files.")
print()
......@@ -110,3 +126,6 @@ index 2ec5832..6697b12 100644
+ data_files= [('share/ocropus', models), ("", ["LICENSE"])],
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 =
${:_profile_base_location_}/fix_compiler_module_issue_20613.patch#94443a77f903e9de880a029967fa6aa7
${:_profile_base_location_}/pytracemalloc_pep445.patch#46662cf0ccc7cb7cfb8289bbfd68b21a
${:_profile_base_location_}/disabled_module_list.patch#71ad30d32bcdbc50c19cf48675b1246e
${:_profile_base_location_}/asyncore_poll_insteadof_select.patch#ab6991c0ee6e25aeb8951e71f280a2f1
url =
http://www.python.org/ftp/python/${:package_version}/Python-${:package_version}${:package_version_suffix}.tar.xz
configure-options =
......
......@@ -19,12 +19,11 @@ extends =
[kvm]
recipe = slapos.recipe.cmmi
# qemu-kvm and qemu are now the same since 1.3.
url = http://wiki.qemu-project.org/download/qemu-2.8.0.tar.bz2
md5sum = 17940dce063b6ce450a12e719a6c9c43
url = http://wiki.qemu-project.org/download/qemu-2.11.0.tar.bz2
md5sum = 335994a755bc655e88a87aeb36bfc0b9
configure-options =
--target-list="$(uname -m 2>/dev/null|sed 's,^i[456]86$,i386,')-softmmu"
--enable-system
--with-system-pixman
--disable-sdl
--disable-xen
--disable-vnc-sasl
......@@ -58,25 +57,26 @@ location = ${buildout:parts-directory}/${:_buildout_section_name_}
<= debian-netinst-base
arch = amd64
[debian-amd64-squeeze-netinst.iso]
<= debian-amd64-netinst-base
version = 6.0.10
md5sum = 7f82d341561035f65933da43f94d5b52
[debian-amd64-wheezy-netinst.iso]
<= debian-amd64-netinst-base
version = 7.11.0
md5sum = 096c1c18b44c269808bd815d58c53c8f
[debian-amd64-jessie-netinst.iso]
<= debian-amd64-netinst-base
release = archive
version = 8.10.0
md5sum = 19dcfc381bd3e609c6056216d203f5bc
[debian-amd64-netinst.iso]
# Download the installer of Debian 8 (Jessie)
# Download the installer of Debian 9 (Stretch)
<= debian-amd64-netinst-base
release = release/current
version = 8.6.0
md5sum = e9f61bf327db6d8f7cee05a99f2353cc
version = 9.3.0
md5sum = db8ab7871bc2b7d456c4746e706fb5d3
[debian-amd64-testing-netinst.iso]
# Download the installer of Debian Stretch
# Download the installer of Debian Buster
<= debian-amd64-netinst-base
release = 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 =
[rsync]
recipe = slapos.recipe.cmmi
url = http://rsync.samba.org/ftp/rsync/src/rsync-3.1.1.tar.gz
md5sum = 43bd6676f0b404326eee2d63be3cdcfe
url = https://download.samba.org/pub/rsync/rsync-3.1.2.tar.gz
md5sum = 0f758d7e000c0f7f7d3792610fad70cb
make-options =
PREFIX=${buildout:parts-directory}/${:_buildout_section_name_}
environment =
......
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
+++ b/tensorboard/pip_package/build_pip_package.sh
@@ -26,6 +26,7 @@ function main() {
......@@ -10,14 +10,14 @@ index b386d59..f03b056 100755
echo $(date) : "=== Using tmpdir: ${TMPDIR}"
@@ -45,8 +46,8 @@ function main() {
@@ -44,9 +45,7 @@ function main() {
pushd ${TMPDIR} >/dev/null
rm -f MANIFEST
echo $(date) : "=== Building wheel"
echo $(pwd)
- python setup.py bdist_wheel >/dev/null
- python3 setup.py bdist_wheel >/dev/null
echo $(date) : "=== Building python2 wheel in $PWD"
- python setup.py bdist_wheel --python-tag py2 >/dev/null
- echo $(date) : "=== Building python3 wheel in $PWD"
- python setup.py bdist_wheel --python-tag py3 >/dev/null
+ PYTHONPATH=${WORKDIR}/${RUNFILES} $PYTHON_BIN_PATH setup.py bdist_egg >/dev/null
+ #python3 setup.py bdist_wheel >/dev/null
mkdir -p ${DEST}
cp dist/* ${DEST}
popd
popd >/dev/null
......@@ -11,11 +11,11 @@ parts =
recipe = plone.recipe.command
stop-on-error = true
repository = https://github.com/tensorflow/tensorboard
tag = 0.4
tag = 0.4.0
git-binary = ${git:location}/bin/git
patch-binary = ${patch:location}/bin/patch
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]
recipe = slapos.recipe.build
......@@ -61,7 +61,7 @@ numpy-python-command = ${buildout:bin-directory}/${numpy-egg:interpreter}
script =
os.makedirs(location)
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')
dest_dir = os.path.join(self.buildout['buildout']['eggs-directory'], egg_name)
env = {'PATH':':'.join([self.options['bazel-bin'],
......
......@@ -5,8 +5,8 @@ extends =
[util-linux]
recipe = slapos.recipe.cmmi
url = http://www.kernel.org/pub/linux/utils/util-linux/v2.29/util-linux-2.29.tar.xz
md5sum = 07b6845f48a421ad5844aa9d58edb837
url = https://www.kernel.org/pub/linux/utils/util-linux/v2.31/util-linux-2.31.1.tar.xz
md5sum = 7733b583dcb51518944d42aa62ef19ea
configure-options =
--disable-static
--enable-libuuid
......@@ -29,7 +29,7 @@ configure-options =
--disable-rename
--disable-schedutils
--disable-setterm
--disable-libsmartcols
--enable-libsmartcols
--disable-switch_root
--disable-tinfo
--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 =
[zstd]
recipe = slapos.recipe.cmmi
location = ${buildout:parts-directory}/${:_buildout_section_name_}
url = https://github.com/facebook/zstd/archive/v1.3.1.tar.gz
md5sum = e849ceef2f090240f690c13fba6ca70b
url = https://github.com/facebook/zstd/archive/v1.3.3.tar.gz
md5sum = 187f8df17a75a74f78a23ea4806ac65f
configure-command = :
make-options = PREFIX=${:location}
......@@ -72,7 +72,6 @@ setup(name=name,
'zc.buildout': [
'addresiliency = slapos.recipe.addresiliency:Recipe',
'accords = slapos.recipe.accords:Recipe',
'apache.zope.backend = slapos.recipe.apache_zope_backend:Recipe',
'apacheperl = slapos.recipe.apacheperl:Recipe',
'apachephp = slapos.recipe.apachephp:Recipe',
'apachephpconfigure = slapos.recipe.apachephpconfigure:Recipe',
......@@ -118,14 +117,11 @@ setup(name=name,
'generic.mysql.wrap_update_mysql = slapos.recipe.generic_mysql:WrapUpdateMySQL',
'generic.mysql.wrap_mysqld = slapos.recipe.generic_mysql:WrapMySQLd',
'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',
'haproxy = slapos.recipe.haproxy:Recipe',
'ipv4toipv6 = slapos.recipe.6tunnel:FourToSix',
'ipv6toipv4 = slapos.recipe.6tunnel:SixToFour',
'jsondump = slapos.recipe.jsondump:Recipe',
'kumofs = slapos.recipe.kumofs:Recipe',
'kvm.frontend = slapos.recipe.kvm_frontend:Recipe',
'lamp = slapos.recipe.lamp:Request',
'lamp.generic = slapos.recipe.lampgeneric:Recipe',
......@@ -136,7 +132,6 @@ setup(name=name,
'libcloudrequest = slapos.recipe.libcloudrequest:Recipe',
'logrotate = slapos.recipe.logrotate:Recipe',
'logrotate.d = slapos.recipe.logrotate:Part',
'memcached = slapos.recipe.memcached:Recipe',
'mkdirectory = slapos.recipe.mkdirectory:Recipe',
'mioga.instantiate = slapos.recipe.mioga.instantiate:Recipe',
'mydumper = slapos.recipe.mydumper:Recipe',
......@@ -196,7 +191,6 @@ setup(name=name,
'urlparse = slapos.recipe._urlparse:Recipe',
'uuid = slapos.recipe._uuid:Recipe',
'userinfo = slapos.recipe.userinfo:Recipe',
'waitfor = slapos.recipe.waitfor:Recipe',
'webchecker = slapos.recipe.web_checker:Recipe',
'wrapper = slapos.recipe.wrapper:Recipe',
'xvfb = slapos.recipe.xvfb:Recipe',
......
......@@ -91,8 +91,8 @@ class Recipe(GenericSlapRecipe):
# Generate wrapper
wrapper_location = self.createPythonScript(self.options['accords-wrapper'],
'%s.accords.runAccords' % __name__,
parameter_dict)
__name__ + '.accords.runAccords',
(parameter_dict,))
path_list.append(wrapper_location)
# Generate helper for debug
......
......@@ -38,26 +38,18 @@ class Recipe(GenericSlapRecipe):
"""
def _install(self):
path_list = []
slap_connection = self.buildout['slap-connection']
takeover_wrapper = self.createPythonScript(
name=self.options['wrapper-takeover'],
absolute_function='slapos.recipe.addresiliency.takeover.run',
arguments={
return self.createPythonScript(
self.options['wrapper-takeover'],
__name__ + '.takeover.takeover',
kw={
'server_url': slap_connection['server-url'],
'key_file': slap_connection.get('key-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'],
'software': slap_connection['software-release-url'],
'software_release': slap_connection['software-release-url'],
'namebase': self.parameter_dict['namebase'],
'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,
# Create "lock" file preventing equeue to run import scripts
# XXX hardcoded
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):
)
path_list.append(httpd_conf)
wrapper = self.createPythonScript(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute',
[self.options['httpd-binary'], '-f', self.options['httpd-conf'],
'-DFOREGROUND']
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['httpd-binary'], '-f', self.options['httpd-conf'],
'-DFOREGROUND'),
)
path_list.append(wrapper)
......
......@@ -92,14 +92,13 @@ class Recipe(GenericBaseRecipe):
)
path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['httpd-binary'],
parameters=[
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['httpd-binary'],
'-f',
self.options['httpd-conf'],
'-DFOREGROUND'
],
environment=self.environ)
),
self.environ)
path_list.append(wrapper)
secret_key_filename = os.path.join(self.buildout['buildout']['directory'],
......
......@@ -118,7 +118,7 @@ class Recipe(GenericBaseRecipe):
configureinstall_wrapper_path = self.createPythonScript(
self.options['configureinstall-location'],
__name__ + '.runner.executeRunner',
[argument, delete, rename, chmod, data]
(argument, delete, rename, chmod, data)
)
#TODO finish to port this and remove upper one
......
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
file or directory when dondition is filled. the condition may be when file exist or when an entry
exist into database.
"""
arguments, delete, rename, chmod, data = args
if delete != []:
if delete:
print "Calling lampconfigure with 'delete' arguments"
result = subprocess.Popen(arguments + delete)
result.wait()
if rename != []:
subprocess.call(arguments + delete)
if rename:
for parameters in rename:
print "Calling lampconfigure with 'rename' arguments"
result = subprocess.Popen(arguments + parameters)
result.wait()
if chmod != []:
subprocess.call(arguments + parameters)
if chmod:
print "Calling lampconfigure with 'chmod' arguments"
result = subprocess.Popen(arguments + chmod)
result.wait()
if data != []:
subprocess.call(arguments + chmod)
if data:
print "Calling lampconfigure with 'run' arguments"
print arguments + data
result = subprocess.Popen(arguments + data)
result.wait()
return
subprocess.call(arguments + data)
......@@ -49,13 +49,12 @@ class Recipe(GenericBaseRecipe):
)
path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['httpd-binary'],
parameters=[
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['httpd-binary'],
'-f',
self.options['httpd-conf'],
'-DFOREGROUND',
])
))
path_list.append(wrapper)
......
......@@ -124,12 +124,15 @@ class Recipe(GenericBaseRecipe):
#Generate wrapper for php
wrapperphp = os.path.join(self.home, 'bin/php')
php_wrapper = self.createPythonScript(wrapperphp,
'slapos.recipe.librecipe.execute.executee',
([self.phpbin, '-c', self.phpini], os.environ)
php_wrapper = self.createWrapper(wrapperphp,
(self.phpbin, '-c', self.phpini),
)
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)
file_status = os.path.join(self.home, '.boinc_config')
if os.path.exists(file_status):
......@@ -137,11 +140,7 @@ class Recipe(GenericBaseRecipe):
mysql_wrapper = self.createPythonScript(
os.path.join(self.wrapperdir, 'start_config'),
'%s.configure.checkMysql' % __name__,
dict(mysql_port=self.mysqlport, mysql_host=self.mysqlhost,
mysql_user=self.username, mysql_password=self.password,
database=self.database,
file_status=file_status, environment=environment
)
(environment, mysql_dict, file_status)
)
# Generate make project wrapper file
......@@ -164,8 +163,7 @@ class Recipe(GenericBaseRecipe):
install_wrapper = self.createPythonScript(
os.path.join(self.wrapperdir, 'make_project'),
'%s.configure.makeProject' % __name__,
dict(launch_args=launch_args, request_file=request_make_boinc,
make_sig=file_status, env=environment)
(file_status, launch_args, request_make_boinc, environment)
)
path_list.append(install_wrapper)
......@@ -197,7 +195,7 @@ class Recipe(GenericBaseRecipe):
)
start_service = self.createPythonScript(
os.path.join(self.wrapperdir, 'config_project'),
'%s.configure.services' % __name__, parameter
'%s.configure.services' % __name__, (parameter,)
)
path_list.append(start_service)
......@@ -208,14 +206,12 @@ class Recipe(GenericBaseRecipe):
os.unlink(start_boinc)
boinc_parameter = dict(service_status=service_status,
installroot=self.installroot, drop_install=drop_install,
mysql_port=self.mysqlport, mysql_host=self.mysqlhost,
mysql_user=self.username, mysql_password=self.password,
database=self.database, environment=environment,
mysql_dict=mysql_dict, environment=environment,
start_boinc=start_boinc)
start_wrapper = self.createPythonScript(os.path.join(self.wrapperdir,
'start_boinc'),
'%s.configure.restart_boinc' % __name__,
boinc_parameter
(boinc_parameter,)
)
path_list.append(start_wrapper)
......@@ -362,7 +358,7 @@ class App(GenericBaseRecipe):
)
deploy_app = self.createPythonScript(
os.path.join(wrapperdir, 'boinc_%s' % appname),
'%s.configure.deployApp' % __name__, parameter
'%s.configure.deployApp' % __name__, (parameter,)
)
path_list.append(deploy_app)
......@@ -404,17 +400,15 @@ class Client(GenericBaseRecipe):
cc_cmd = '--read_cc_config'
cmd = self.createPythonScript(cmd_wrapper,
'%s.configure.runCmd' % __name__,
dict(base_cmd=base_cmd, cc_cmd=cc_cmd, installdir=installdir,
project_url=url, key=key)
(base_cmd, cc_cmd, installdir, url, key)
)
path_list.append(cmd)
#Generate BOINC client wrapper
boinc = self.createPythonScript(boinc_wrapper,
'slapos.recipe.librecipe.execute.execute',
[boincbin, '--allow_multiple_clients', '--gui_rpc_port',
boinc = self.createWrapper(boinc_wrapper,
(boincbin, '--allow_multiple_clients', '--gui_rpc_port',
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)
......
......@@ -35,27 +35,21 @@ import filecmp
from lock_file import LockFile
def checkMysql(args):
sys.path += args['environment']['PYTHONPATH'].split(':')
def checkMysql(environment, connect_kw, file_status=None):
sys.path += environment['PYTHONPATH'].split(':')
import MySQLdb
#Sleep until mysql server becomes available
while True:
try:
conn = MySQLdb.connect(host = args['mysql_host'],
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")
MySQLdb.connect(**connect_kw).close()
break
except Exception, ex:
print "The result is: \n" + ex.message
print "Could not connect to MySQL database... sleep for 2 secondes"
time.sleep(2)
print "Successfully connect to MySQL database... "
if file_status:
writeFile(file_status, "starting")
def checkFile(file, stime):
"""Loop until 'file' is created (exist)"""
......@@ -70,18 +64,16 @@ def checkFile(file, stime):
def restart_boinc(args):
"""Stop (if currently is running state) and start all Boinc service"""
environment = args['environment']
if args['drop_install']:
checkFile(args['service_status'], 3)
else:
checkMysql(args)
checkMysql(environment, args['mysql_dict'], args.get('file_status'))
print "Restart Boinc..."
env = os.environ
env['PATH'] = args['environment']['PATH']
env['PYTHONPATH'] = args['environment']['PYTHONPATH']
binstart = os.path.join(args['installroot'], 'bin/start')
binstop = os.path.join(args['installroot'], 'bin/stop')
os.system(binstop)
os.system(binstart)
env = os.environ.copy()
env.update(environment)
subprocess.call((os.path.join(args['installroot'], 'bin', 'stop'),), env=env)
subprocess.call((os.path.join(args['installroot'], 'bin', 'start'),), env=env)
writeFile(args['start_boinc'], "started")
print "Done."
......@@ -122,17 +114,16 @@ def startProcess(launch_args, env=None, cwd=None, stdout=subprocess.PIPE):
return False
return True
def makeProject(args):
def makeProject(make_sig, launch_args, request_file, extra_environ):
"""Run BOINC make_project script but once only"""
#Wait for DateBase initialization...
checkFile(args['make_sig'], 3)
checkFile(make_sig, 3)
print "Cheking if needed to run BOINC make_project..."
if os.path.exists(args['request_file']):
env = os.environ
env['PATH'] = args['env']['PATH']
env['PYTHONPATH'] = args['env']['PYTHONPATH']
if startProcess(args['launch_args'], env=env):
os.unlink(args['request_file'])
if os.path.exists(request_file):
env = os.environ.copy()
env.update(extra_environ)
if startProcess(launch_args, env=env):
os.unlink(request_file)
print "Finished running BOINC make_projet...Ending"
else:
print "No new request for make_project. Exiting..."
......@@ -155,9 +146,8 @@ def services(args):
return
print "execute script xadd..."
env = os.environ
env['PATH'] = args['environment']['PATH']
env['PYTHONPATH'] = args['environment']['PYTHONPATH']
env = os.environ.copy()
env.update(args['environment'])
if not startProcess([os.path.join(args['installroot'], 'bin/xadd')], env):
return
print "Update files and directories permissions..."
......@@ -212,9 +202,8 @@ def deployManagement(args):
newInstall = True
#Sleep until file .start_boinc exist (File indicate that BOINC has been started)
checkFile(args['start_boinc'], 3)
env = os.environ
env['PATH'] = args['environment']['PATH']
env['PYTHONPATH'] = args['environment']['PYTHONPATH']
env = os.environ.copy()
env.update(args['environment'])
print "setup directories..."
numversion = args['version'].replace('.', '')
......@@ -263,7 +252,7 @@ def deployManagement(args):
privateKeyFile = os.path.join(args['installroot'], 'keys/code_sign_private')
output = open(binary + '.sig', 'w')
p_sign = subprocess.Popen([sign, binary, privateKeyFile], stdout=output,
stderr=subprocess.STDOUT)
stderr=subprocess.STDOUT, env=env)
result = p_sign.communicate()[0]
if p_sign.returncode is None or p_sign.returncode != 0:
print "Failed to execute bin/sign_executable.\nThe error was: %s" % result
......@@ -290,10 +279,8 @@ def deployManagement(args):
create_wu(args, env)
print "Restart Boinc..."
binstart = os.path.join(args['installroot'], 'bin/start')
binstop = os.path.join(args['installroot'], 'bin/stop')
os.system(binstop)
os.system(binstart)
subprocess.call((os.path.join(args['installroot'], 'bin', 'stop'),), env=env)
subprocess.call((os.path.join(args['installroot'], 'bin', 'start'),), env=env)
print "Boinc Application deployment is done... writing end signal file..."
writeFile(token, str(args['wu_number']))
......@@ -315,22 +302,21 @@ def create_wu(args, env):
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"""
client_config = os.path.join(args['installdir'], 'client_state.xml')
client_config = os.path.join(installdir, 'client_state.xml')
checkFile(client_config, 5)
time.sleep(10)
#Scan client state xml to find client ipv4 adress
host = re.search("<ip_addr>([\w\d\.:]+)</ip_addr>",
open(client_config, 'r').read()).group(1)
args['base_cmd'][2] = host + ':' + args['base_cmd'][2]
print "Run boinccmd with host at %s " % args['base_cmd'][2]
project_args = args['base_cmd'] + ['--project_attach', args['project_url'],
args['key']]
startProcess(project_args, cwd=args['installdir'])
if args['cc_cmd'] != '':
base_cmd[2] = host + ':' + base_cmd[2]
print "Run boinccmd with host at %s " % base_cmd[2]
project_args = base_cmd + ['--project_attach', url, key]
startProcess(project_args, cwd=installdir)
if cc_cmd:
#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):
......
......@@ -62,8 +62,8 @@ class Recipe(GenericBaseRecipe):
condor_wrapper_list=condor_wrapper_list,
boinc_wrapper_list=boinc_wrapper_list)
bonjourGrid_wrapper = self.createPythonScript(grid_wrapper,
'%s.configure.launchScript' % __name__,
parameters
__name__ + '.configure.launchScript',
(parameters,)
)
path_list.append(bonjourGrid_wrapper)
......@@ -73,16 +73,15 @@ class Recipe(GenericBaseRecipe):
bg_wrapper = self.options['wrapper'].strip()
log = self.options['log_file'].strip()
pid_file = self.options['pid_file'].strip()
wrapper = self.createPythonScript(bg_wrapper,
'slapos.recipe.librecipe.execute.execute',
([python, bonjourgrid_master, '--log_file', log,
wrapper = self.createWrapper(bg_wrapper,
(python, bonjourgrid_master, '--log_file', log,
'--pid_file', pid_file,
'--master_wrapper', grid_wrapper,
'--directory', self.options['work_dir'].strip(),
'--server', self.options['redis-url'].strip(),
'--port', self.options['redis-port'].strip(),
'--num_workers', self.options['nworkers'].strip(),
])
),
)
path_list.append(wrapper)
......@@ -113,9 +112,8 @@ class Client(GenericBaseRecipe):
bg_wrapper = self.options['wrapper'].strip()
log = self.options['log_file'].strip()
pid_file = self.options['pid_file'].strip()
wrapper = self.createPythonScript(bg_wrapper,
'slapos.recipe.librecipe.execute.execute',
([python, bonjourgrid_client, '--log_file', log,
wrapper = self.createWrapper(bg_wrapper,
(python, bonjourgrid_client, '--log_file', log,
'--pid_file', pid_file,
'--boinc_wrapper', boinc_script,
'--condor_wrapper', condor_script,
......@@ -123,7 +121,7 @@ class Client(GenericBaseRecipe):
'--install_directory', self.options['install_dir'].strip(),
'--server', self.options['redis-url'].strip(),
'--port', self.options['redis-port'].strip(),
])
),
)
path_list.append(wrapper)
......
......@@ -40,13 +40,10 @@ class Recipe(GenericBaseRecipe):
self.ca_private = self.options['ca-private']
self.ca_certs = self.options['ca-certs']
self.ca_newcerts = self.options['ca-newcerts']
self.ca_crl = self.options['ca-crl']
self.ca_key_ext = '.key'
self.ca_crt_ext = '.crt'
def install(self):
path_list = []
ca_country_code = self.options.get('country-code', 'XX')
ca_email = self.options.get('email', 'xx@example.com')
# XXX-BBB: State by mistake has been configured as string "('State',)"
......@@ -77,21 +74,15 @@ class Recipe(GenericBaseRecipe):
self.createFile(openssl_configuration, self.substituteTemplate(
self.getTemplateFilename('openssl.cnf.ca.in'), config))
ca_wrapper = self.createPythonScript(
return self.createPythonScript(
self.options['wrapper'],
'%s.certificate_authority.runCertificateAuthority' % __name__,
dict(
openssl_configuration=openssl_configuration,
openssl_binary=self.options['openssl-binary'],
certificate=os.path.join(self.ca_dir, 'cacert.pem'),
key=os.path.join(self.ca_private, 'cakey.pem'),
crl=self.ca_crl,
request_dir=self.request_directory
)
__name__ + '.certificate_authority.runCertificateAuthority',
(os.path.join(self.ca_private, 'cakey.pem'),
os.path.join(self.ca_dir, 'cacert.pem'),
self.options['openssl-binary'],
openssl_configuration,
self.request_directory)
)
path_list.append(ca_wrapper)
return path_list
class Request(Recipe):
......@@ -146,11 +137,10 @@ class Request(Recipe):
path_list = [key_file, cert_file]
if request_needed:
wrapper = self.createPythonScript(
wrapper = self.createWrapper(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute_wait',
[ [self.options['executable']],
[certificate, key] ],
(self.options['executable'],),
wait_list=(certificate, key),
)
path_list.append(wrapper)
......
......@@ -102,10 +102,8 @@ class CertificateAuthority:
'certificate_file')):
print 'Created certificate %r' % parser.get('certificate', 'name')
def runCertificateAuthority(ca_conf):
ca = CertificateAuthority(ca_conf['key'], ca_conf['certificate'],
ca_conf['openssl_binary'], ca_conf['openssl_configuration'],
ca_conf['request_dir'])
def runCertificateAuthority(*args):
ca = CertificateAuthority(*args)
while True:
ca.checkAuthority()
ca.checkRequestDir()
......
......@@ -42,8 +42,6 @@ class Recipe(GenericBaseRecipe):
options['access-url'] = 'http://[%s]:%s' % (self.ip, self.port)
def install(self):
path_list = []
environment = {
'PATH': os.path.dirname(self.git) + ':' + os.environ['PATH'],
}
......@@ -51,10 +49,4 @@ class Recipe(GenericBaseRecipe):
cloud9_args = [self.node_executable, self.cloud9, '-l', self.ip, '-p',
self.port, '-w', self.workdir]
wrapper = self.createPythonScript(self.wrapper,
'slapos.recipe.librecipe.execute.executee',
(cloud9_args, environment)
)
path_list.append(wrapper)
return path_list
return self.createWrapper(self.wrapper, cloud9_args, environment)
......@@ -178,12 +178,11 @@ class Recipe(GenericBaseRecipe):
os.chmod(wrapper_location, 0744)
#generate script for start condor
start_condor = os.path.join(self.wrapperdir, 'start_condor')
start_bin = os.path.join(self.wrapper_sbin, 'condor_master')
condor_reconfig = os.path.join(self.wrapper_sbin, 'condor_reconfig')
wrapper = self.createPythonScript(start_condor,
'%s.configure.condorStart' % __name__,
dict(start_bin=start_bin, condor_reconfig=condor_reconfig)
wrapper = self.createPythonScript(
os.path.join(self.wrapperdir, 'start_condor'),
__name__ + '.configure.condorStart',
(os.path.join(self.wrapper_sbin, 'condor_reconfig'),
os.path.join(self.wrapper_sbin, 'condor_master'))
)
path_list.append(wrapper)
return path_list
......@@ -276,13 +275,11 @@ class AppSubmit(GenericBaseRecipe):
os.unlink(destination)
os.symlink(app_list[appname]['files'][file], destination)
#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(
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)
return path_list
\ No newline at end of file
......@@ -29,27 +29,25 @@ import os
import subprocess
import time
def submitJob(args):
def submitJob(submit, submit_file, appdir, appname, sig_install):
"""Run condor_submit (if needed) for job deployment"""
time.sleep(10)
print "Check if needed to submit %s job's" % args['appname']
if not os.path.exists(args['sig_install']):
print "Check if needed to submit %s job's" % appname
if not os.path.exists(sig_install):
print "Nothing for install or update...Exited"
return
# '-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,
stderr=subprocess.STDOUT, cwd=args['appdir'])
stderr=subprocess.STDOUT, cwd=appdir)
result = process.communicate()[0]
if process.returncode is None or process.returncode != 0:
print "Failed to execute condor_submit.\nThe error was: %s" % result
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"""
result = os.system(args['condor_reconfig'])
if result != 0:
if subprocess.call(condor_reconfig):
#process failled to reconfig condor that mean that condor deamons is not curently started
os.system(args['start_bin'])
\ No newline at end of file
subprocess.call(start_bin)
......@@ -98,26 +98,19 @@ class Recipe(GenericBaseRecipe):
)
path_list.append(config_file)
wrapper = self.createPythonScript(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute',
[self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'])
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'))
path_list.append(wrapper)
promise = self.createPythonScript(self.options['promise'],
__name__ + '.promise',
dict(host=self.options['ip'], port=int(self.options['port_webdav']),
user=self.options['user'], password=self.options['password'])
)
(self.options['ip'], int(self.options['port_webdav']),
self.options['user'], self.options['password']))
path_list.append(promise)
return path_list
def promise(args):
host = args['host']
port = args['port']
user = args['user']
password = args['password']
def promise(host, port, user, password):
connection = httplib.HTTPSConnection(host, port)
auth = base64.b64encode('%s:%s' % (user, password))
connection.request('OPTIONS', '/',
......
......@@ -35,15 +35,14 @@ class Recipe(GenericBaseRecipe):
self.logger.info("Installing dcron...")
options = self.options
script = self.createWrapper(name=options['binary'],
command=options['dcrond-binary'].strip(),
parameters=[
script = self.createWrapper(options['binary'],
(options['dcrond-binary'].strip(),
'-s', options['cron-entries'],
'-c', options['crontabs'],
'-t', options['cronstamps'],
'-f', '-l', '5',
'-M', options['catcher']
])
))
self.logger.debug('Main cron executable created at : %r', script)
......
......@@ -57,8 +57,6 @@ class KnownHostsFile(dict):
class Recipe(GenericBaseRecipe):
def install(self):
path_list = []
dropbear_cmd = [self.options['dropbear-binary']]
# Don't fork into background
dropbear_cmd.append('-F')
......@@ -95,19 +93,12 @@ class Recipe(GenericBaseRecipe):
if 'shell' in self.options:
env['DROPBEAR_OVERRIDE_SHELL'] = self.options['shell']
wrapper = self.createPythonScript(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
(dropbear_cmd, env, )
)
path_list.append(wrapper)
return path_list
return self.createWrapper(self.options['wrapper'], dropbear_cmd, env)
class Client(GenericBaseRecipe):
def install(self):
env = dict()
env = {}
if 'home' in self.options:
env['HOME'] = self.options['home']
......@@ -120,13 +111,7 @@ class Client(GenericBaseRecipe):
if 'identity-file' in self.options:
dropbear_cmd.extend(['-i', self.options['identity-file']])
wrapper = self.createPythonScript(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
(dropbear_cmd, env, )
)
return [wrapper]
return self.createWrapper(self.options['wrapper'], dropbear_cmd, env)
class AddAuthorizedKey(GenericBaseRecipe):
......
......@@ -46,7 +46,4 @@ class Recipe(GenericBaseRecipe):
cmd.extend(options)
cmd.extend([backup_directory, remote_url])
wrapper = self.createPythonScript(self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute', cmd)
return [wrapper]
return self.createWrapper(self.options['wrapper'], cmd)
......@@ -30,23 +30,20 @@ class Recipe(GenericBaseRecipe):
def install(self):
parameters = [
args = [
self.options['equeue-binary'],
'--database', self.options['database'],
'--logfile', self.options['log'],
'--lockfile', self.options['lockfile']
]
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:
parameters.extend(['--loglevel', self.options['loglevel']])
args += '--loglevel', self.options['loglevel']
parameters.append(self.options['socket'])
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['equeue-binary'],
parameters=parameters)
return [wrapper]
args.append(self.options['socket'])
return self.createWrapper(self.options['wrapper'], args)
......@@ -67,7 +67,7 @@ class Recipe(GenericBaseRecipe):
openssl_binary=self.options['openssl-binary'],
test_ca_path=self.options['certificate-authority-path'],
)
common_list = [
common_list = (
'--conversion_server_url=' + cloudooo_url,
# BBB: We still have test suites that only accept the following 2 options.
'--conversion_server_hostname=%s' % cloudooo_parsed.hostname,
......@@ -76,19 +76,19 @@ class Recipe(GenericBaseRecipe):
'--volatile_memcached_server_port=%s' % memcached_parsed.port,
'--persistent_memcached_server_hostname=%s' % kumofs_parsed.hostname,
'--persistent_memcached_server_port=%s' % kumofs_parsed.port,
]
)
path_list.append(self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest', [dict(
call_list=[self.options['run-unit-test-binary'],
__name__ + '.test.runUnitTest',
((self.options['run-unit-test-binary'],
'--erp5_sql_connection_string', mysql_connection_string,
'--extra_sql_connection_string_list', ','.join(
mysql_connection_string_list),
] + common_list, **common_dict)]))
) + common_list, common_dict)))
path_list.append(self.createPythonScript(self.options['run-test-suite'],
__name__ + '.test.runUnitTest', [dict(
call_list=[self.options['run-test-suite-binary'],
__name__ + '.test.runTestSuite',
((self.options['run-test-suite-binary'],
'--db_list', ','.join(mysql_connection_string_list),
] + common_list, **common_dict)]))
) + common_list, common_dict)))
return path_list
......@@ -98,20 +98,18 @@ class CloudoooRecipe(GenericBaseRecipe):
common_dict = dict(
prepend_path=self.options['prepend-path'],
)
common_list = [
common_list = (
"--paster_path", self.options['ooo-paster'],
self.options['configuration-file']
]
run_unit_test_path = self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest', [dict(
call_list=[self.options['run-unit-test-binary'],
] + common_list, **common_dict)])
path_list.append(run_unit_test_path)
)
path_list.append(self.createPythonScript(self.options['run-unit-test'],
__name__ + '.test.runUnitTest',
((self.options['run-unit-test-binary'],
) + common_list, common_dict)))
path_list.append(self.createPythonScript(self.options['run-test-suite'],
__name__ + '.test.runTestSuite', [dict(
call_list=[self.options['run-test-suite-binary'],
], **common_dict)]))
__name__ + '.test.runTestSuite',
((self.options['run-test-suite-binary'],
), common_dict)))
return path_list
......@@ -121,32 +119,20 @@ class EggTestRecipe(GenericBaseRecipe):
off a list of Python eggs.
"""
def install(self):
path_list = []
test_list = self.options['test-list'].strip().replace('\n', ',')
common_dict = {}
environment_dict = {}
common_dict = {}
if self.options.get('environment'):
environment_part = self.buildout.get(self.options['environment'])
if environment_part:
for key, value in environment_part.iteritems():
environment_dict[key] = value
common_dict['environment'] = dict(environment_part)
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:
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',
[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 @@
##############################################################################
import os
import sys
def runTestSuite(args):
def runTestSuite(args, d):
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(':'))
try:
env['PATH'] = d['prepend_path'] + ':' + env['PATH']
except KeyError:
env['PATH'] = d['prepend_path']
if 'instance_home' in d:
env['INSTANCE_HOME'] = d['instance_home']
env['REAL_INSTANCE_HOME'] = d['instance_home']
......@@ -44,42 +47,15 @@ def runTestSuite(args):
env.update(d['environment'])
# 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 = []
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()
executable_filepath = args[0]
with open(executable_filepath, 'r') as f:
line = f.readline()
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)
argument_list += args
argument_list += sys.argv[1:]
os.execve(executable_filepath, argument_list, env)
runUnitTest = runTestSuite
......@@ -68,17 +68,14 @@ class Recipe(GenericBaseRecipe):
)
self.path_list.append(configuration_file)
self.path_list.append(
self.createPythonScript(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
[ # Executable
[ self.options['testnode'], '-l', self.options['log-file'],
configuration_file],
self.createWrapper(self.options['wrapper'],
# Command
( self.options['testnode'], '-l', self.options['log-file'],
configuration_file),
# Environment
{
'GIT_SSL_NO_VERIFY': '1',
}
],
)
)
self.installApache()
......@@ -106,9 +103,8 @@ class Recipe(GenericBaseRecipe):
apache_config)
)
self.path_list.append(config_file)
wrapper = self.createPythonScript(self.options['httpd-wrapper'],
'slapos.recipe.librecipe.execute.execute',
[self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'])
wrapper = self.createWrapper(self.options['httpd-wrapper'],
(self.options['apache-binary'], '-f', config_file, '-DFOREGROUND'))
self.path_list.append(wrapper)
# create empty html page to not allow listing of /
page = open(os.path.join(self.options['log-directory'], "index.html"), "w")
......
......@@ -118,5 +118,5 @@ class Recipe(GenericBaseRecipe):
path_list.append(config_file)
path_list.append(self.createPythonScript(self.options['wrapper'],
'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
......@@ -154,7 +154,7 @@ class Recipe(GenericBaseRecipe):
)]
)
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)
if 'backup-script' in self.options:
# backup configuration
......@@ -165,9 +165,13 @@ class Recipe(GenericBaseRecipe):
'--defaults-file=%s' % mysql_conf_file,
'--socket=%s' % socket.strip(), '--user=root',
'--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)
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)
backup_controller = self.createPythonScript(self.options['backup-script'], __name__ + '.innobackupex.controller', [innobackupex_incremental, innobackupex_full, full_backup, incremental_backup])
path_list.append(backup_controller)
......@@ -215,7 +219,9 @@ class Recipe(GenericBaseRecipe):
'--defaults-file=%s' % mysql_conf_file,
'--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)
return path_list
......
import os
import glob
def controller(args):
def controller(innobackupex_incremental, innobackupex_full,
full_backup, incremental_backup):
"""Creates full or incremental backup
If no full backup is done, it is created
......@@ -9,8 +10,6 @@ def controller(args):
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:
print 'Doing full backup in %r' % full_backup
os.execv(innobackupex_full, [innobackupex_full, full_backup])
......
......@@ -5,9 +5,8 @@ import sys
import pytz
def runMysql(args):
def runMysql(conf):
sleep = 60
conf = args[0]
mysqld_wrapper_list = [conf['mysqld_binary'], '--defaults-file=%s' %
conf['configuration_file']]
# we trust mysql_install that if mysql directory is available mysql was
......@@ -54,8 +53,7 @@ def runMysql(args):
os.execl(mysqld_wrapper_list[0], *mysqld_wrapper_list)
def updateMysql(args):
conf = args[0]
def updateMysql(conf):
sleep = 30
is_succeed = False
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):
'server_text': server_snippet},
)
)
wrapper_path = self.createPythonScript(
wrapper_path = self.createWrapper(
self.options['wrapper-path'],
'slapos.recipe.librecipe.execute.execute',
arguments=[self.options['binary-path'].strip(), '-f', configuration_path],)
(self.options['binary-path'].strip(), '-f', configuration_path))
ctl_path = self.createPythonScript(
self.options['ctl-path'],
'%s.haproxy.haproxyctl' % __name__,
{'socket_path':self.options['socket-path']})
__name__ + '.haproxy.haproxyctl',
(self.options['socket-path'],))
return [configuration_path, wrapper_path, ctl_path]
......@@ -4,7 +4,7 @@ try:
except ImportError:
pass
def haproxyctl(conf):
def haproxyctl(socket_path):
while True:
try:
l = raw_input('> ')
......@@ -14,7 +14,7 @@ def haproxyctl(conf):
if l == 'quit':
break
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(conf['socket_path'])
s.connect(socket_path)
s.send('%s\n' % l)
while True:
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):
'local_host': local_host, 'local_port': local_port,
}))
wrapper = zc.buildout.easy_install.scripts([('stunnel',
'slapos.recipe.librecipe.execute', 'execute')], self.ws,
sys.executable, self.wrapper_directory, arguments=[
self.options['stunnel_binary'].strip(), stunnel_conf_path]
'slapos.recipe.librecipe.execute', 'generic_exec')], self.ws,
sys.executable, self.wrapper_directory, arguments='%r, %r'
% (self.options['stunnel_binary'].strip(), stunnel_conf_path)
)[0]
self.path_list.append(wrapper)
return (local_host, local_port,)
......@@ -71,13 +71,12 @@ class Recipe(GenericBaseRecipe):
)
path_list.append(httpd_conf)
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['httpd-binary'],
parameters=[
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['httpd-binary'],
'-f',
self.options['httpd-conf'],
'-DFOREGROUND'
])
))
path_list.append(wrapper)
......
......@@ -2,7 +2,6 @@ import sys
import os
import signal
import subprocess
import time
from collections import defaultdict
from inotify_simple import INotify, flags
......@@ -29,65 +28,96 @@ def _wait_files_creation(file_list):
if event.name in directory:
directory[event.name] = event.mask & (flags.CREATE | flags.MOVED_TO)
def execute(args):
"""Portable execution with process replacement"""
# XXX: Kept for backward compatibility
generic_exec([args, None, None])
def execute_wait(args):
"""Execution but after all files in args[1] exists"""
# XXX: Kept for backward compatibility
generic_exec([args[0], args[1], None])
def _libc():
from ctypes import CDLL, get_errno, c_char_p, c_int, c_ulong, util
libc = CDLL(util.find_library('c'), use_errno=True)
libc_mount = libc.mount
libc_mount.argtypes = c_char_p, c_char_p, c_char_p, c_ulong, c_char_p
def mount(source, target, filesystemtype, mountflags, data):
if libc_mount(source, target, filesystemtype, mountflags, data):
e = get_errno()
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
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):
print 'Received signal %r, killing children and exiting' % sig
if child_pg is not None:
os.killpg(child_pg, signal.SIGHUP)
os.killpg(child_pg, signal.SIGTERM)
sys.exit(0)
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGQUIT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
sys.exit()
def execute_with_signal_translation(args):
"""Run process as children and translate from SIGTERM to another signal"""
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_pg = child.pid
try:
print 'Process %r started' % args
while True:
time.sleep(10)
signal.pause()
finally:
os.killpg(child_pg, signal.SIGHUP)
os.killpg(child_pg, signal.SIGTERM)
......@@ -33,7 +33,6 @@ import sys
import inspect
import re
import shutil
from textwrap import dedent
import urllib
import urlparse
......@@ -61,7 +60,13 @@ class GenericBaseRecipe(object):
self._options(options) # Options Hook
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):
"""By default update method does the same thing than install"""
......@@ -110,92 +115,60 @@ class GenericBaseRecipe(object):
with io.open(filepath, 'w+', encoding=encoding) as f:
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
* function should look like 'module.function', or only 'function'
if it is a builtin function."""
absolute_function = tuple(absolute_function.rsplit('.', 1))
if len(absolute_function) == 1:
absolute_function = ('__builtin__',) + absolute_function
if len(absolute_function) != 2:
raise ValueError("A non valid function was given")
module, function = absolute_function
function = absolute_function.rsplit('.', 1)
if len(function) == 1:
module = '__builtin__'
function, = function
else:
module, function = function
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,
path, arguments=arguments)[0]
return script
path, arguments=', '.join(args))[0]
def createWrapper(self, name, command, parameters, comments=[],
parameters_extra=False, environment=None,
pidfile=None, reserve_cpu=False
):
"""
Creates a shell script for process replacement.
Takes care of quoting.
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.
def createWrapper(self, path, args, env=None, **kw):
"""Create a wrapper script for process replacement"""
assert args
if kw:
return self.createPythonScript(path,
'slapos.recipe.librecipe.execute.generic_exec',
(args, env) if env else (args,), kw)
: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' ]
if comments:
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:
args = map(shlex.quote, args)
args.append('"$@"')
for arg in args:
if len(lines[-1]) < 40:
lines[-1] += ' ' + param
lines[-1] += ' ' + arg
else:
lines[-1] += ' \\'
lines.append('\t' + param)
lines.append('\t' + arg)
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):
path = os.path.join(parent, name)
......
......@@ -46,10 +46,10 @@ class Recipe(GenericBaseRecipe):
state_file = self.options['state-file']
logrotate = self.createPythonScript(
logrotate = self.createWrapper(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute',
[self.options['logrotate-binary'], '-s', state_file, logrotate_conf_file, ]
(self.options['logrotate-binary'],
'-s', state_file, 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
services_dir = self.options['services_dir']
httpd_wrapper = self.createPythonScript(
httpd_wrapper = self.createWrapper(
os.path.join(services_dir, 'httpd_wrapper'),
'slapos.recipe.librecipe.execute.execute',
[self.options['httpd_binary'], '-f', self.options['httpd_conf'],
'-DFOREGROUND']
(self.options['httpd_binary'],
'-f', self.options['httpd_conf'], '-DFOREGROUND'),
)
path_list.append(httpd_wrapper)
......@@ -220,19 +219,17 @@ Include conf/extra/httpd-autoindex.conf
site_perl_bin = os.path.join(self.options['site_perl'], 'bin')
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'),
'slapos.recipe.librecipe.execute.execute',
[ os.path.join(site_perl_bin, 'notifier.pl'),
mioga_conf_path ]
(os.path.join(site_perl_bin, 'notifier.pl'),
mioga_conf_path),
)
path_list.append(notifier_wrapper)
searchengine_wrapper = self.createPythonScript(
searchengine_wrapper = self.createWrapper(
os.path.join(services_dir, 'searchengine'),
'slapos.recipe.librecipe.execute.execute',
[ os.path.join(site_perl_bin, 'searchengine.pl'),
mioga_conf_path ]
(os.path.join(site_perl_bin, 'searchengine.pl'),
mioga_conf_path),
)
path_list.append(searchengine_wrapper)
......
......@@ -24,7 +24,7 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import subprocess
import os
from slapos.recipe.librecipe import GenericBaseRecipe
......@@ -58,14 +58,14 @@ def do_export(args):
cmd.extend(['-o', args['directory']])
subprocess.check_call(cmd)
os.execv(cmd[0], cmd)
def do_import(args):
cmd = _mydumper_base_cmd(**args)
cmd.append('--overwrite-tables')
cmd.extend(['-d', args['directory']])
subprocess.check_call(cmd)
os.execv(cmd[0], cmd)
class Recipe(GenericBaseRecipe):
......@@ -95,9 +95,5 @@ class Recipe(GenericBaseRecipe):
config['compression'] = self.optionIsTrue('compression', default=False)
config['rows'] = self.options.get('rows')
wrapper = self.createPythonScript(name=self.options['wrapper'],
absolute_function = '%s.%s' % (__name__, function.func_name),
arguments=config)
return [wrapper]
return self.createPythonScript(self.options['wrapper'],
'%s.%s' % (function.__module__, function.__name__), (config,))
......@@ -53,11 +53,10 @@ class Recipe(GenericBaseRecipe):
mysql_binary = self.options['mysql-binary']
socket = self.options['socket'],
post_rotate = self.createPythonScript(
post_rotate = self.createWrapper(
self.options['logrotate-post'],
'slapos.recipe.librecipe.execute.execute',
[mysql_binary, '--no-defaults', '-B', '-u', 'root', '--socket=%s' % socket, '-e',
'FLUSH LOGS']
(mysql_binary, '--no-defaults', '-B', '-u', 'root',
'--socket=%s' % socket, '-e', 'FLUSH LOGS'),
)
path_list.append(post_rotate)
......@@ -85,12 +84,12 @@ class Recipe(GenericBaseRecipe):
mysql_update = self.createPythonScript(
self.options['update-wrapper'],
'%s.mysql.updateMysql' % __name__,
dict(
(dict(
mysql_script=mysql_script,
mysql_binary=mysql_binary,
mysql_upgrade_binary=mysql_upgrade_binary,
socket=socket,
)
),)
)
path_list.append(mysql_update)
......@@ -98,7 +97,7 @@ class Recipe(GenericBaseRecipe):
mysqld = self.createPythonScript(
self.options['wrapper'],
'%s.mysql.runMysql' % __name__,
dict(
(dict(
mysql_install_binary=self.options['mysql-install-binary'],
mysqld_binary=mysqld_binary,
data_directory=mysql_conf['data_directory'],
......@@ -106,7 +105,7 @@ class Recipe(GenericBaseRecipe):
socket=socket,
configuration_file=mysql_conf_file,
cwd=self.options['mysql-base-directory'],
)
),)
)
path_list.append(mysqld)
......@@ -115,12 +114,12 @@ class Recipe(GenericBaseRecipe):
backup_script = self.createPythonScript(
self.options['backup-script'],
'%s.do_backup' % __name__,
dict(
(dict(
mydumper_binary=self.options['mydumper-binary'],
database=mysql_conf['mysql_database'],
socket=mysql_conf['socket'],
backup_directory=self.options['backup-directory']
),
),)
)
path_list.append(backup_script)
......@@ -129,7 +128,7 @@ class Recipe(GenericBaseRecipe):
recovering_script = self.createPythonScript(
self.options['recovering-wrapper'],
'%s.import_dump' % __name__,
{
({
'lock_file': os.path.join(self.work_directory,
'import_done'),
'database': mysql_conf['mysql_database'],
......@@ -140,7 +139,7 @@ class Recipe(GenericBaseRecipe):
'local_directory': self.mysql_backup_directory,
'dump_name': dump_filename,
'zcat_binary': self.options['zcat-binary'],
}
},)
)
path_list.append(recovering_script)
......
......@@ -42,7 +42,8 @@ class NeoBaseRecipe(GenericBaseRecipe):
# Only then can this recipe start succeeding and actually doing anything
# useful, as per NEO deploying constraints.
raise UserError('"masters" parameter is mandatory')
option_list = [
args = [
options['binary'],
# Keep the -l option first, as expected by logrotate snippets.
'-l', options['logfile'],
'-m', options['masters'],
......@@ -53,17 +54,13 @@ class NeoBaseRecipe(GenericBaseRecipe):
]
if options['ssl']:
etc = os.path.join(self.buildout['buildout']['directory'], 'etc', '')
option_list += (
args += (
'--ca', etc + 'ca.crt',
'--cert', etc + 'neo.crt',
'--key', etc + 'neo.key',
)
option_list.extend(self._getOptionList())
return [self.createWrapper(
options['wrapper'],
options['binary'],
option_list
)]
args += self._getOptionList()
return self.createWrapper(options['wrapper'], args)
def _getBindingAddress(self):
options = self.options
......
......@@ -32,19 +32,15 @@ class Recipe(GenericBaseRecipe):
def install(self):
options = self.options
script = self.createWrapper(name=options['wrapper'],
command=options['server-binary'],
parameters=[
# Script that execute the callback(s) upon receiving a notification.
return self.createWrapper(options['wrapper'],
(options['server-binary'],
'--callbacks', options['callbacks'],
'--feeds', options['feeds'],
'--equeue-socket', options['equeue-socket'],
options['host'], options['port']
],
comments=[
'',
'Upon receiving a notification, execute the callback(s).',
''])
return [script]
),
)
class Callback(GenericBaseRecipe):
......@@ -80,35 +76,32 @@ class Notify(GenericBaseRecipe):
# Just a touch
open(log, 'w').close()
parameters = [
cmd = [notifier_binary,
'-l', log,
'--title', title,
'--feed', feed_url,
'--max-run', str(max_run),
'--notification-url',
]
parameters.extend(notification_url.split(' '))
parameters.extend(['--executable', executable])
cmd += notification_url.split(' ')
cmd += '--executable', executable
# 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)
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)
if instance_root_name and log_url and status_item_directory:
parameters.extend([
cmd += (
'--instance-root-name', instance_root_name,
'--log-url', log_url,
'--status-item-directory', status_item_directory,
])
return self.createWrapper(name=wrapper,
command=notifier_binary,
parameters=parameters,
pidfile=pidfile,
parameters_extra=True,
comments=[
'',
'Call an executable and send notification(s).',
''])
)
kw = {}
if pidfile:
kw['pidfile'] = pidfile
# Script that call an executable and send notification(s).
return self.createWrapper(wrapper, cmd, **kw)
def install(self):
......
......@@ -35,10 +35,9 @@ class Recipe(GenericBaseRecipe):
"""
def install(self):
runner_path = self.createPythonScript(
return self.createWrapper(
self.options['path'],
'slapos.recipe.librecipe.execute.execute_wait',
[[
(
self.options['websockify-path'],
'--web',
self.options['novnc-location'],
......@@ -47,8 +46,7 @@ class Recipe(GenericBaseRecipe):
'--ssl-only',
'%s:%s' % (self.options['ip'], self.options['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
from slapos.recipe.librecipe import shlex
def promise(args):
def promise(ssh_client, user, host, port):
# Redirect output to /dev/null
with open("/dev/null") as _dev_null:
with open(os.devnull) as _dev_null:
ssh = subprocess.Popen(
[args['ssh_client'], '%(user)s@%(host)s' % args, '-p', '%(port)s' % args],
stdin=subprocess.PIPE, stdout=_dev_null, stderr=None
)
# 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:
(ssh_client, '%s@%s' % (user, host), '-p', str(port)),
stdin=subprocess.PIPE, stdout=_dev_null)
ssh.communicate('q' + chr(255) + chr(0) * 7)
if ssh.returncode:
sys.stderr.write("SSH Connection failed\n")
return ssh.returncode
class Recipe(GenericSlapRecipe, Notify, Callback):
def _options(self, options):
options['rdiff-backup-data-folder'] = ""
......@@ -244,15 +232,11 @@ class Recipe(GenericSlapRecipe, Notify, Callback):
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)
promise_dict = dict(ssh_client=self.options['sshclient-binary'],
user=parsed_url.username,
host=parsed_url.hostname,
port=parsed_url.port)
promise = self.createPythonScript(promise_path,
__name__ + '.promise',
promise_dict)
path_list.append(promise)
path_list.append(self.createPythonScript(
os.path.join(self.options['promises-directory'], "ssh-to-%s" % slave_id),
__name__ + '.promise',
(self.options['sshclient-binary'],
parsed_url.username, parsed_url.hostname, parsed_url.port)))
# Create known_hosts file by default.
# 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):
else:
self.logger.info("Server mode")
wrapper = self.createWrapper(name=self.options['wrapper'],
command=self.options['rdiffbackup-binary'],
parameters=[
wrapper = self.createWrapper(self.options['wrapper'],
(self.options['rdiffbackup-binary'],
'--restrict', self.options['path'],
'--server'
])
))
path_list.append(wrapper)
return path_list
......@@ -162,7 +162,6 @@ class Recipe(GenericBaseRecipe):
return hash_string
def install(self):
path_list = []
token_save_path = os.path.join(self.options['conf-dir'], 'token.json')
token_list_path = self.options['token-dir']
......@@ -190,20 +189,14 @@ class Recipe(GenericBaseRecipe):
self.createFile(token_save_path, json.dumps(token_dict))
service_dict = dict(token_base_path=token_list_path,
token_json=token_save_path,
partition_id=self.computer_partition_id,
computer_id=self.computer_id,
registry_url=registry_url,
server_url=self.server_url,
computer_dict = dict(partition_id=self.computer_partition_id,
computer_guid=self.computer_id,
master_url=self.server_url,
cert_file=self.cert_file,
key_file=self.key_file)
request_add = self.createPythonScript(
return self.createPythonScript(
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
def loadJsonFile(path):
if os.path.exists(path):
with open(path, 'r') as f:
content = f.read()
return json.loads(content)
else:
return {}
return json.load(f)
return {}
def writeFile(path, data):
with open(path, 'w') as f:
......@@ -39,29 +37,25 @@ def updateFile(file_path, value):
return True
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()
# Redeploy instance to update published information
slap.initializeConnection(server_url,
key_file,
cert_file)
return slap.registerComputerPartition(computer_guid=computer_guid,
partition_id=partition_id)
slap.initializeConnection(master_url, key_file, cert_file)
return slap.registerComputerPartition(computer_guid, partition_id)
def requestAddToken(client, base_token_path):
def requestAddToken(client, token_base_path):
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:
log.info("No new token to add. Exiting...")
return
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)
log.info("Including token %s for %s" % (token, reference_key))
if token :
......@@ -79,21 +73,21 @@ def requestAddToken(client, base_token_path):
# update information
log.info("New token added for slave instance %s. Updating file status..." %
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')
os.unlink(request_file)
else:
log.debug('Bad token. Request add token fail for %s...' % request_file)
def requestRemoveToken(client, base_token_path):
path_list = [x for x in os.listdir(base_token_path) if x.endswith('.remove')]
def requestRemoveToken(client, token_base_path):
path_list = [x for x in os.listdir(token_base_path) if x.endswith('.remove')]
if not path_list:
log.info("No token to delete. Exiting...")
return
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)
if token :
reference = reference_key.split('.')[0]
......@@ -108,7 +102,7 @@ def requestRemoveToken(client, base_token_path):
continue
else:
# 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'):
# update information
......@@ -117,33 +111,17 @@ def requestRemoveToken(client, base_token_path):
if result in ['True', 'False']:
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):
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):
os.unlink(ipv6_file)
else:
log.debug('Bad token. Request add token fail for %s...' % request_file)
def requestRevoqueCertificate(args):
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):
def checkService(client, token_base_path, token_json, computer_partition):
token_dict = loadJsonFile(token_json)
updated = False
if not token_dict:
......@@ -152,7 +130,7 @@ def checkService(client, base_token_path, token_json, computer_partition):
# Check token status
for slave_reference, token in token_dict.iteritems():
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):
# This token is not added yet!
log.info("Token %s dont exist yet." % status_file)
......@@ -206,31 +184,22 @@ def checkService(client, base_token_path, token_json, computer_partition):
slave_reference, traceback.format_exc())
def manage(args, 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']
def manage(registry_url, token_base_path, token_json,
computer_dict, can_bang=True):
client = registry.RegistryClient(args['registry_url'])
base_token_path = args['token_base_path']
token_json = args['token_json']
client = registry.RegistryClient(registry_url)
log.info("ADD TOKEN")
# Request Add new tokens
requestAddToken(client, base_token_path)
requestAddToken(client, token_base_path)
log.info("Remove TOKEN")
# Request delete removed token
requestRemoveToken(client, base_token_path)
requestRemoveToken(client, token_base_path)
computer_partition = getComputerPartition(server_url, key_file,
cert_file, computer_guid, partition_id)
computer_partition = getComputerPartition(**computer_dict)
log.info("Update Services")
# check status of all token
checkService(client, base_token_path,
token_json, computer_partition)
checkService(client, token_base_path, token_json, computer_partition)
......@@ -25,7 +25,7 @@
#
##############################################################################
import os
import sys
from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe):
......@@ -56,10 +56,9 @@ class Recipe(GenericBaseRecipe):
configuration))
path_list.append(config)
redis = self.createPythonScript(
redis = self.createWrapper(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.execute',
[self.options['server_bin'], config_file]
(self.options['server_bin'], config_file),
)
path_list.append(redis)
......@@ -67,11 +66,20 @@ class Recipe(GenericBaseRecipe):
if promise_script:
promise = self.createPythonScript(
promise_script,
'%s.promise.main' % __name__,
dict(host=self.options['ipv6'], port=self.options['port'],
unixsocket = self.options.get('unixsocket') )
__name__ + '.promise',
(self.options['ipv6'], int(self.options['port']),
self.options.get('unixsocket'))
)
path_list.append(promise)
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):
path_list.append(nginx_configuration_file)
# Generate Nginx wrapper
wrapper = self.createWrapper(
name=self.options['wrapper'],
command=self.options['nginx-executable'],
parameters=[
path_list.append(self.createWrapper(
self.options['wrapper'],
(self.options['nginx-executable'],
'-c', self.options['configuration-file'],
'-p', self.options['home-directory']
]
)
)))
# TODO: reload configuration or have feature like apache_map
......
......@@ -25,23 +25,15 @@
#
#############################################################################
import os
import sys
import zc.buildout
from slapos.recipe.librecipe import BaseSlapRecipe
from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe):
def install(self):
runner = self.createPythonScript(
def install(self):
return self.createPythonScript(
self.options['runner-path'],
__name__+'.testrunner.run',
arguments=[self.options['suite-url'],
self.options['report-url'],
self.options['report-project'],
self.options['browser'],
])
return [runner]
(self.options['suite-url'],
self.options['report-url'],
self.options['report-project'],
self.options['browser']))
......@@ -36,12 +36,7 @@ import urlparse
from subprocess import Popen, PIPE
import signal
def run(args):
suite_url = args[0]
report_url = args[1]
project = args[2]
browser_binary = args[3]
def run(suite_url, report_url, project, browser_binary):
suite_parsed = urlparse.urlparse(suite_url)
config = {
......
......@@ -31,27 +31,12 @@ from slapos.recipe.librecipe import GenericBaseRecipe
class Recipe(GenericBaseRecipe):
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')
if ps1 is not None:
env.update(PS1=str(json.loads(ps1)))
else:
env.update(PS1=env.get('PS1', '> '))
wrapper = self.createPythonScript(
self.options['wrapper'],
'slapos.recipe.librecipe.execute.executee',
[ # Executable
[self.options['shell']],
# Environment
env
]
)
return [wrapper]
shell = self.options['shell']
env = {
'HOME': self.options['home'],
'PATH': ':'.join(self.options['path'].split('\n')),
'PS1': str(json.loads(ps1)) if ps1 else os.getenv('PS1', '> '),
'SHELL': shell,
}
return self.createWrapper(self.options['wrapper'], (shell,), env)
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