Commit 549c1636 authored by Thomas Gambier's avatar Thomas Gambier 🚴🏼

Update Release Candidate

parents 37efc4a6 b6660c58
[buildout] [buildout]
extends = extends =
../../stack/slapos.cfg ../defaults.cfg
../../component/numpy/buildout.cfg ../git/buildout.cfg
../numpy/buildout.cfg
parts = parts = cythonplus_env.sh
slapos-cookbook
template [gcc]
min_version = 8.4
[python] [python]
part = python3 part = python3
[template] # Dependencies for the Cython+ test suite
recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/template.cfg
template =
inline:[buildout]
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
parts = runTestSuite
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
[directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin
tmp = $${buildout:directory}/tmp
[runTestSuite]
recipe = slapos.recipe.template:jinja2
rendered = $${directory:bin}/$${:_buildout_section_name_}
template = ${runTestSuite.in:target}
mode = 0755
context =
key tmpdir directory:tmp
key slapparameter_dict slap-configuration:configuration
key cython_repository cython-repository:location
raw runTestSuite_py ${runTestSuite_py:bin-directory}/${runTestSuite_py:interpreter}
raw cython_env_sh ${cython_env.sh:rendered}
[cython-repository]
recipe = slapos.recipe.build:gitclone
repository = ${cython-repository:location}
git-executable = ${git:location}/bin/git
shared = true
[cython-repository]
recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/cython.git
git-executable = ${git:location}/bin/git
sparse-checkout = /.gitignore
[runTestSuite.in]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_}
md5sum = 02094e80cde9631081077fc96b401065
[runTestSuite_py]
recipe = zc.recipe.egg
eggs = erp5.util
interpreter = ${:_buildout_section_name_}
[eggs] [eggs]
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = eggs =
...@@ -73,7 +20,13 @@ eggs = ...@@ -73,7 +20,13 @@ eggs =
coverage coverage
pycodestyle pycodestyle
[cython_env.sh] [cythonplus-repository]
recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/cython.git
revision = cythonplus-0.1
git-executable = ${git:location}/bin/git
[cythonplus_env.sh]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
rendered = ${buildout:directory}/${:_buildout_section_name_} rendered = ${buildout:directory}/${:_buildout_section_name_}
template = template =
...@@ -81,25 +34,25 @@ template = ...@@ -81,25 +34,25 @@ template =
{% if 'part' in gcc -%} {% if 'part' in gcc -%}
{% set path = path + ':' + gcc.prefix + '/bin' -%} {% set path = path + ':' + gcc.prefix + '/bin' -%}
{% endif -%} {% endif -%}
export PATH={{ path }}:$PATH export PATH={{ path }}$${PATH:+:$PATH}
export PYTHON={{ python }} export PYTHON={{ python }}
export PYTHONPATH={{ cythonplus_repository }}$${PYTHONPATH:+:$PYTHONPATH}
export PYTHONPATH={{ ':'.join(easy_install.working_set(eggs['eggs'].split(), [ export PYTHONPATH={{ ':'.join(easy_install.working_set(eggs['eggs'].split(), [
eggs['develop-eggs-directory'], eggs['develop-eggs-directory'],
eggs['eggs-directory'], eggs['eggs-directory'],
]).entries) }}$${PYTHONPATH:+:$PYTHONPATH} ]).entries) }}$${PYTHONPATH:+:$PYTHONPATH}
# EmbedTest needs libintl. {# Set path to libintl needed for cython EmbedTest #}
export LD_RUN_PATH={{ gettext }}/lib$${LD_RUN_PATH:+:$LD_RUN_PATH} export LD_RUN_PATH={{ gettext }}/lib$${LD_RUN_PATH:+:$LD_RUN_PATH}
export LIBRARY_PATH={{ gettext }}/lib$${LIBRARY_PATH:+:$LIBRARY_PATH} export LIBRARY_PATH={{ gettext }}/lib$${LIBRARY_PATH:+:$LIBRARY_PATH}
{##}
context = context =
section eggs eggs section eggs eggs
section gcc gcc section gcc gcc
key cythonplus_repository cythonplus-repository:location
key gettext gettext:location key gettext gettext:location
key python python:executable key python python:executable
import os os import os os
import easy_install zc.buildout.easy_install import easy_install zc.buildout.easy_install
[versions] [versions]
slapos.recipe.template = 4.4
coverage = 4.5.1 coverage = 4.5.1
pycodestyle = 2.5.0 pycodestyle = 2.5.0
...@@ -7,8 +7,8 @@ parts = garbage-collector ...@@ -7,8 +7,8 @@ parts = garbage-collector
[garbage-collector] [garbage-collector]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
md5sum = 6f77f9fff5fb5bf96adfc1e93cd035b6 md5sum = 67a5093e2f9f381bd550aa891d00b54b
url = http://www.hboehm.info/gc/gc_source/gc-7.2g.tar.gz url = http://www.hboehm.info/gc/gc_source/gc-8.0.4.tar.gz
configure-options = configure-options =
--enable-cplusplus --enable-cplusplus
--disable-gcj-support --disable-gcj-support
......
...@@ -71,6 +71,11 @@ patches = ...@@ -71,6 +71,11 @@ patches =
version = 8.4.0 version = 8.4.0
md5sum = bb815a8e3b7be43c4a26fa89dbbd9795 md5sum = bb815a8e3b7be43c4a26fa89dbbd9795
[gcc-10.2]
<= gcc-common
version = 10.2.0
md5sum = e9fd9b1789155ad09bcf3ae747596b50
[gcc-minimal] [gcc-minimal]
<= gcc-5.5 <= gcc-5.5
configure-options = configure-options =
......
...@@ -13,8 +13,8 @@ parts = haproxy ...@@ -13,8 +13,8 @@ parts = haproxy
[haproxy] [haproxy]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = http://www.haproxy.org/download/2.0/src/haproxy-2.0.17.tar.gz url = http://www.haproxy.org/download/2.0/src/haproxy-2.0.20.tar.gz
md5sum = 786a967c73cc1455c938d42fbe333bfe md5sum = 9f85ea9e6fd7d49a11cdc4c6269e10dd
configure-command = true configure-command = true
# for Linux kernel 2.6.28 and above, we use "linux-glibc" as the TARGET, # for Linux kernel 2.6.28 and above, we use "linux-glibc" as the TARGET,
# otherwise use "generic". # otherwise use "generic".
......
This diff is collapsed.
This directory is only temporary (until ERP5 is Python3) and will not actively
be maintained.
It has to be removed once ERP5 uses `software/jupyter` or do not use jupyter at
all.
[buildout]
extends =
buildout.hash.cfg
../../stack/slapos.cfg
../openssl/buildout.cfg
../jupyter/buildout.cfg
../../stack/monitor/buildout.cfg
parts +=
slapos-cookbook
jupyter
jupyter-notebook-initialized-scripts
instance-jupyter-notebook
[gcc]
# Always build GCC for Fortran (see openblas).
max_version = 0
[jupyter]
python_executable = ${buildout:bin-directory}/${:interpreter}
[download-file-base]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:filename}
download-only = true
mode = 0644
[jupyter-notebook-config]
<= download-file-base
[jupyter-set-password]
<= download-file-base
[erp5-kernel]
<= download-file-base
[kernel-json]
<= download-file-base
[custom-js]
<= download-file-base
[instance-jupyter-notebook]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}
rendered = ${buildout:directory}/template.cfg
mode = 0644
context =
key bin_directory buildout:bin-directory
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key openssl_output openssl-output:openssl
key python_executable jupyter:python_executable
key jupyter_config_location jupyter-notebook-config:location
key jupyter_config_filename jupyter-notebook-config:filename
key jupyter_set_password_location jupyter-set-password:location
key jupyter_set_password_filename jupyter-set-password:filename
key erp5_kernel_location erp5-kernel:location
key erp5_kernel_filename erp5-kernel:filename
key kernel_json_location kernel-json:location
key kernel_json_filename kernel-json:filename
key custom_js_location custom-js:location
key custom_js_filename custom-js:filename
key monitor_template_rendered buildout:directory
[versions]
Pygments = 2.2.0
astor = 0.5
backports-abc = 0.5
backports.functools-lru-cache = 1.6.1
backports.shutil-get-terminal-size = 1.0.0
cycler = 0.10.0
ipykernel = 4.5.2
ipython = 5.3.0
ipython-genutils = 0.1.0
ipywidgets = 6.0.0
jupyter-client = 5.0.0
jupyter-core = 4.3.0
jupyterlab = 0.26.3
jupyterlab-launcher = 0.3.1
matplotlib = 2.1.2
mistune = 0.7.3
nbformat = 4.3.0
notebook = 4.4.1
pandas = 0.19.2
plone.recipe.command = 1.1
prompt-toolkit = 1.0.13
ptyprocess = 0.5.1
pyzmq = 16.0.2
scikit-learn = 0.18.1
seaborn = 0.7.1
simplegeneric = 0.8.1
statsmodels = 0.8.0
terminado = 0.6
tornado = 4.4.2
traitlets = 4.3.2
widgetsnbextension = 2.0.0
# numpy >= 1.13.1 is required for numpy.core.multiarray
numpy = 1.13.1
# Required by:
# tornado==4.4.2
certifi = 2020.6.20
# Required by:
# notebook==4.3.2
# nbconvert 4.2.0 depends on entrypoints egg that is not available as tar/zip source.
nbconvert = 4.1.0
# Required by:
# ipython==5.3.0
pathlib2 = 2.2.1
# Required by:
# statsmodels==0.8.0
patsy = 0.4.1
# Required by:
# ipython==5.3.0
pexpect = 4.2.1
# Required by:
# ipython==5.3.0
pickleshare = 0.7.4
# Required by:
# matplotlib==2.1.2
# pandas==0.19.2
python-dateutil = 2.6.0
# Required by:
# pathlib2==2.2.1
scandir = 1.5
# Required by:
# statsmodels==0.8.0
scipy = 0.19.0
# Required by:
# tornado==4.4.2
singledispatch = 3.4.0.3
# Required by:
# prompt-toolkit==1.0.13
wcwidth = 0.1.7
jupyter = 1.0.0
jupyter-console = 5.1.0
# Required by:
# jupyter==1.0.0
qtconsole = 4.3.0
et-xmlfile = 1.0.1
h5py = 2.7.1
mpmath = 1.0.0
openpyxl = 2.5.2
sympy = 1.1.1
xlrd = 1.1.0
# Required by:
# openpyxl==2.5.2
jdcal = 1.4
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[instance-jupyter-notebook]
filename = instance.cfg.in
md5sum = 1d5fe6cc4e48672ae7be1c223794a932
[jupyter-notebook-config]
filename = jupyter_notebook_config.py.jinja
md5sum = 720e90a829c63371696bc3009917a743
[jupyter-set-password]
filename = jupyter_set_password.cgi.jinja
md5sum = ac10fbcf790bd8e58750cfdd069812d2
[erp5-kernel]
filename = ERP5kernel.py
md5sum = 7d5309fe79afbcb455c0d8181b42e56c
[kernel-json]
filename = kernel.json.jinja
md5sum = 33547be93a67530165e079dc3ecfdac3
[custom-js]
filename = custom.js
md5sum = 147ccce38f7d7cf10664975d0dd80e33
// leave at least 2 line with only a star on it below, or doc generation fails
/**
*
*
* Placeholder for custom user javascript
* mainly to be overridden in profile/static/custom/custom.js
* This will always be an empty file in IPython
*
* User could add any javascript in the `profile/static/custom/custom.js` file.
* It will be executed by the ipython notebook at load time.
*
* Same thing with `profile/static/custom/custom.css` to inject custom css into the notebook.
*
*
* The object available at load time depend on the version of IPython in use.
* there is no guaranties of API stability.
*
* The example below explain the principle, and might not be valid.
*
* Instances are created after the loading of this file and might need to be accessed using events:
* define([
* 'base/js/namespace',
* 'base/js/events'
* ], function(IPython, events) {
* events.on("app_initialized.NotebookApp", function () {
* IPython.keyboard_manager....
* });
* });
*
* __Example 1:__
*
* Create a custom button in toolbar that execute `%qtconsole` in kernel
* and hence open a qtconsole attached to the same kernel as the current notebook
*
* define([
* 'base/js/namespace',
* 'base/js/events'
* ], function(IPython, events) {
* events.on('app_initialized.NotebookApp', function(){
* IPython.toolbar.add_buttons_group([
* {
* 'label' : 'run qtconsole',
* 'icon' : 'icon-terminal', // select your icon from http://fortawesome.github.io/Font-Awesome/icons
* 'callback': function () {
* IPython.notebook.kernel.execute('%qtconsole')
* }
* }
* // add more button here if needed.
* ]);
* });
* });
*
* __Example 2:__
*
* At the completion of the dashboard loading, load an unofficial javascript extension
* that is installed in profile/static/custom/
*
* define([
* 'base/js/events'
* ], function(events) {
* events.on('app_initialized.DashboardApp', function(){
* require(['custom/unofficial_extension.js'])
* });
* });
*
* __Example 3:__
*
* Use `jQuery.getScript(url [, success(script, textStatus, jqXHR)] );`
* to load custom script into the notebook.
*
* // to load the metadata ui extension example.
* $.getScript('/static/notebook/js/celltoolbarpresets/example.js');
* // or
* // to load the metadata ui extension to control slideshow mode / reveal js for nbconvert
* $.getScript('/static/notebook/js/celltoolbarpresets/slideshow.js');
*
*
* @module IPython
* @namespace IPython
* @class customjs
* @static
*/
$([Jupyter.events]).on('notebook_loaded.Notebook', function(){
var kernelname = Jupyter.notebook.kernel_selector.current_selection;
var display_text="<div class='output_subarea output_text output_result'>\
<pre>Follow these steps to customize your notebook with ERP5 kernel :-</br>\
1. Make sure you have 'erp5_data_notebook' business template installed in your ERP5</br>\
2. <b>%erp5_user &lt;your_erp5_username&gt;</b></br>\
3. <b>%erp5_password &lt;your_erp5_password&gt;</b></br>\
4. <b>%notebook_set_reference &lt;your_notebook_reference&gt;</b></br>\
It would be better to set the reference to match with erp5 reference pattern.</br>\
5. As soon as you see 'Please Proceed' message you can now access your erp5 using notebook.</br>\
<p><u>OTHER USEFUL MAGICS</u> -</br>\
<b>%my_notebooks</b> -This is used to display all the notebooks created by the specific user.</br>\
<b>%notebook_set_title</b> -This sets the title of the current notebook.</br>\
NOTE: Do not dynamically alter imported module objects as they are not being saved in DB, </br>\
so changes to them would be disregarded and would throw an error.</br>\
<p><u>About classes, functions and global state on modules:</u></p>\
Your code is going to be executed by ERP5, which can have many nodes </br>\
and there is no guarantee that your code is always going to be executed by the same server.</br>\
This means that objects which cannot be stored in the ZODB, like functions, classes and modules </br>\
won't be available across nodes. To solve this issue, you need to use a special object </br>\
called 'environment' to store your global setup. This object was designed to hold global </br>\
state and restore it for each code cell. Example:</br></br>\
<b>def my_setup():</br>\
# import modules, define functions and classes</br>\
# and set global state on modules</br>\
# return dict of variables to be available in code cells</br>\
{'my_var': 1}</br>\
environment.define(my_setup, 'my custom setup')</b></br></br>\
After you execute this cell, the <b>my_setup</b> function will run before each of the</br>\
following cells and the <b>my_var</b> variable will be created and set to 1.</br></br>\
<b>WARNING:</b> it is not recommended to have too many setup functions in the environment, </br>\
because they will be executed in every code cell and can cause a substantial slow down.\
</pre></div>";
if (kernelname=="erp5"){
$('div#notebook-container').prepend(display_text);
}
});
[buildout]
parts =
instance
jupyter_notebook
read-knowledge0
publish-connection-parameter
jupyter-notebook-config
erp5-kernel
kernel-json
custom-js
monitor-base
extends =
{{ monitor_template_rendered }}/template-monitor.cfg
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slapconfiguration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
# ERP5 URL to use in Jupyter by default
# default value is empty - which means no default ERP5 URL
configuration.erp5-url =
[instance-parameter]
port = 8888
host = ${slapconfiguration:ipv6-random}
cert_file = ${generate-certificate:cert_file}
key_file = ${generate-certificate:key_file}
logfile = ${directory:log}/jupyter_notebook.log
notebook_dir = ${directory:notebook_dir}
[dynamic-jinja2-template-base]
recipe = slapos.recipe.template:jinja2
mode = 0644
[generate-certificate]
; TODO: there is a slapos recipe to generate certificates. Use it instead
recipe = plone.recipe.command
command =
if [ ! -e ${instance-parameter:key_file} ]
then
{{ openssl_output }} req -x509 -nodes -days 3650 \
-subj "/C=AA/ST=X/L=X/O=Dis/CN=${instance-parameter:host}" \
-newkey rsa:1024 -keyout ${instance-parameter:key_file} \
-out ${instance-parameter:cert_file}
fi
update-command = ${:command}
cert_file = ${directory:etc}/jupyter_cert.crt
key_file = ${directory:etc}/jupyter_cert.key
[instance]
recipe = slapos.cookbook:wrapper
command-line =
{{ bin_directory }}/jupyter-lab
--no-browser
--ip=${instance-parameter:host}
--port=${instance-parameter:port}
--port-retries=0
--certfile=${instance-parameter:cert_file}
--keyfile=${instance-parameter:key_file}
--notebook-dir=${instance-parameter:notebook_dir}
--log-level="DEBUG"
wrapper-path = ${directory:service}/jupyter-lab
environment =
JUPYTER_PATH=${directory:jupyter_dir}
JUPYTER_CONFIG_DIR=${directory:jupyter_config_dir}
JUPYTER_RUNTIME_DIR=${directory:jupyter_runtime_dir}
LANG=C.UTF-8
[jupyter-notebook-config]
<= dynamic-jinja2-template-base
template = {{ jupyter_config_location }}/{{ jupyter_config_filename }}
rendered = ${directory:jupyter_config_dir}/jupyter_notebook_config.py
mode = 0744
context =
raw config_cfg ${buildout:directory}/knowledge0.cfg
[directory]
recipe = slapos.cookbook:mkdirectory
home = ${buildout:directory}
etc = ${:home}/etc
var = ${:home}/var
script = ${:etc}/run/
service = ${:etc}/service
log = ${:var}/log
notebook_dir = ${:var}/notebooks
# Add folders to explicitly define jupyter directory
jupyter_dir = ${:home}/jupyter
jupyter_config_dir = ${:jupyter_dir}/etc
jupyter_kernel_dir = ${:jupyter_dir}/kernels
jupyter_runtime_dir = ${:jupyter_dir}/runtime
jupyter_custom_dir = ${:jupyter_config_dir}/custom
jupyter_nbextensions_dir = ${:jupyter_dir}/nbextensions
erp5_kernel_dir = ${:jupyter_kernel_dir}/ERP5
[jupyter_notebook]
# This part is called like this because knowledge0.write uses the part name for
# the section name in the config file.
recipe = slapos.cookbook:zero-knowledge.write
password =
filename = knowledge0.cfg
[read-knowledge0]
recipe = slapos.cookbook:zero-knowledge.read
filename = knowledge0.cfg
password =
[monitor-instance-parameter]
monitor-base-url = ${monitor-frontend-promise:url}
# In case you're using a developer instance you should edit these in:
# monitor-base-url = ${monitor-httpd-conf-parameter:url}
# cors-domains = softinstXXXXX.host.vifib.net (or equivalent)
# interface-url = https://softinstXXXXX.host.vifib.net/erp5/web_site_module/monitoring_rjs_unsafe
instance-configuration =
raw jupyter-password ${read-knowledge0:password}
[publish-connection-parameter]
recipe = slapos.cookbook:publish.serialised
jupyter-classic-url = https://[${instance-parameter:host}]:${instance-parameter:port}/tree
url = ${:jupyter-classic-url}
jupyterlab-url = https://[${instance-parameter:host}]:${instance-parameter:port}/lab
[erp5-kernel]
recipe = slapos.cookbook:symbolic.link
link-binary = {{ erp5_kernel_location }}/{{ erp5_kernel_filename }}
target-directory = ${directory:erp5_kernel_dir}
[kernel-json]
<= dynamic-jinja2-template-base
template = {{ kernel_json_location }}/{{ kernel_json_filename }}
rendered = ${directory:erp5_kernel_dir}/kernel.json
# Use python2.7 executable bin file for kernel config
context =
raw python_executable {{ python_executable }}
raw kernel_dir ${erp5-kernel:target-directory}/{{ erp5_kernel_filename }}
key erp5_url slapconfiguration:configuration.erp5-url
raw display_name ERP5
raw language_name python
[custom-js]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:jupyter_custom_dir}
link-binary = {{ custom_js_location }}/custom.js
'''
This script initializes Jupyter's configuration such as passwords and other
things. It is run by IPython hence why it can use functions like get_config().
'''
import ConfigParser
import random
from notebook.auth import passwd
import os
def random_password(length = 10):
result = ""
for i in range(0, length):
result = result + chr(random.randint(0, 25) + ord('a'))
return result
knowledge_0 = '{{ config_cfg }}'
if not os.path.exists(knowledge_0):
print "Your software does <b>not</b> embed 0-knowledge. \
This interface is useless in this case</body></html>"
exit(0)
c = get_config()
parser = ConfigParser.ConfigParser()
parser.read(knowledge_0)
if not parser.has_section("jupyter_notebook"):
parser.add_section("jupyter_notebook")
if not parser.has_option("jupyter_notebook", "password") or \
parser.get("jupyter_notebook", "password") == "":
parser.set("jupyter_notebook", "password", random_password())
c.NotebookApp.password = passwd(parser.get("jupyter_notebook", "password"))
with open(knowledge_0, 'w') as file:
parser.write(file)
...@@ -61,4 +61,3 @@ print """<div class="pure-control-group"> ...@@ -61,4 +61,3 @@ print """<div class="pure-control-group">
<script type="text/javascript" src="static/monitor-register.js"></script> <script type="text/javascript" src="static/monitor-register.js"></script>
</body></html> </body></html>
""" """
{
"argv": [
"{{python_executable}}",
"{{kernel_dir}}",
"{{erp5_url}}",
"-f",
"{connection_file}"
],
"display_name": "{{display_name}}",
"language": "{{language_name}}",
"language_info": {"name": "python"}
}
...@@ -8,8 +8,8 @@ parts = logrotate ...@@ -8,8 +8,8 @@ parts = logrotate
[logrotate] [logrotate]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = https://github.com/logrotate/logrotate/releases/download/3.15.0/logrotate-3.15.0.tar.xz url = https://github.com/logrotate/logrotate/releases/download/3.17.0/logrotate-3.17.0.tar.xz
md5sum = 320046f0b9fc38337e8827d4c5a866a0 md5sum = ac2a7151fc8a187201872358a20a2813
# BBB this is only for backward-compatibility. # BBB this is only for backward-compatibility.
post-install = post-install =
ln -nsf . @@LOCATION@@/usr ln -nsf . @@LOCATION@@/usr
......
diff --git a/config.c b/config.c
index e6d5d1d..dd004a9 100644
--- a/config.c
+++ b/config.c
@@ -519,7 +519,11 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
length arrays -- of course, if we aren't run setuid it doesn't
matter much */
+#ifdef O_CLOEXEC
fd = open(configFile, O_RDONLY | O_CLOEXEC);
+#else
+ fd = open(configFile, O_RDONLY);
+#endif
if (fd < 0) {
message(MESS_ERROR, "failed to open config file %s: %s\n",
configFile, strerror(errno));
...@@ -17,8 +17,8 @@ parts = ...@@ -17,8 +17,8 @@ parts =
[openssl] [openssl]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = https://www.openssl.org/source/openssl-1.1.1g.tar.gz url = https://www.openssl.org/source/openssl-1.1.1i.tar.gz
md5sum = 76766e98997660138cdaf13a187bd234 md5sum = 08987c3cf125202e2b0840035efb392c
location = @@LOCATION@@ location = @@LOCATION@@
# 'prefix' option to override --openssldir/--prefix (which is useful # 'prefix' option to override --openssldir/--prefix (which is useful
# when combined with DESTDIR). Used by slapos.package.git/obs # when combined with DESTDIR). Used by slapos.package.git/obs
......
...@@ -8,19 +8,19 @@ extends = ...@@ -8,19 +8,19 @@ extends =
../patch/buildout.cfg ../patch/buildout.cfg
../pcre/buildout.cfg ../pcre/buildout.cfg
../cyrus-sasl/buildout.cfg ../cyrus-sasl/buildout.cfg
../m4/buildout.cfg
[postfix] [postfix]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-2.11.6.tar.gz url = ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-3.5.8.tar.gz
md5sum = c3277d05b78eaaf5955406bc7b6d2b9f md5sum = c7c55ccc1db2a30d35c3867c21fe7109
location = @@LOCATION@@ location = @@LOCATION@@
patch-options = -p1 patch-options = -p1
patches = patches =
${:_profile_base_location_}/noroot.patch#738bcc97b8044c45b58708bdf3a84b8e ${:_profile_base_location_}/noroot.patch#05fc6333e05576ea8e5a49f27a6ef951
${:_profile_base_location_}/skip-libdb-check.patch#f7fdbd8787874b535fee548b0139c0d8
configure-command = make configure-command = make
configure-options = makefiles CCARGS='-DUSE_SASL_AUTH -DUSE_CYRUS_SASL -DUSE_TLS -DHAS_PCRE -DHAS_DB -I${libdb:location}/include -I${pcre:location}/include -I${openssl-1.0:location}/include -I${cyrus-sasl:location}/include/sasl' AUXLIBS='-L${openssl-1.0:location}/lib -L${pcre:location}/lib -L${libdb:location}/lib -L${cyrus-sasl:location}/lib -lssl -lpcre -ldb -lcrypto -lsasl2 -Wl,-rpath=${openssl-1.0:location}/lib -Wl,-rpath=${pcre:location}/lib -Wl,-rpath=${libdb:location}/lib -Wl,-rpath=${cyrus-sasl:location}/lib' configure-options = makefiles CCARGS='-DUSE_SASL_AUTH -DUSE_CYRUS_SASL -DUSE_TLS -DHAS_PCRE -DHAS_DB -I${libdb:location}/include -I${pcre:location}/include -I${openssl-1.0:location}/include -I${cyrus-sasl:location}/include/sasl' AUXLIBS='-L${openssl-1.0:location}/lib -L${pcre:location}/lib -L${libdb:location}/lib -L${cyrus-sasl:location}/lib -lssl -lpcre -ldb -lcrypto -lsasl2 -Wl,-rpath=${openssl-1.0:location}/lib -Wl,-rpath=${pcre:location}/lib -Wl,-rpath=${libdb:location}/lib -Wl,-rpath=${cyrus-sasl:location}/lib'
make-targets = non-interactive-package install_root=${:location} make-targets = non-interactive-package install_root=${:location}
environment = environment =
PATH=${patch:location}/bin:%(PATH)s PATH=${patch:location}/bin:${m4:location}/bin:%(PATH)s
...@@ -2,16 +2,16 @@ diff --git a/src/global/mail_params.c b/src/global/mail_params.c ...@@ -2,16 +2,16 @@ diff --git a/src/global/mail_params.c b/src/global/mail_params.c
index 2d91977..0f06298 100644 index 2d91977..0f06298 100644
--- a/src/global/mail_params.c --- a/src/global/mail_params.c
+++ b/src/global/mail_params.c +++ b/src/global/mail_params.c
@@ -721,7 +721,9 @@ void mail_params_init() @@ -911,7 +911,9 @@ void mail_params_init()
check_default_privs(); check_default_privs();
check_mail_owner(); check_mail_owner();
check_sgid_group(); check_sgid_group();
+ /* + /*
check_overlap(); check_overlap();
+ */ + */
#ifdef HAS_DB
dict_db_cache_size = var_db_read_buf; dict_db_cache_size = var_db_read_buf;
#endif dict_lmdb_map_size = var_lmdb_map_size;
inet_windowsize = var_inet_windowsize;
diff --git a/src/master/master.c b/src/master/master.c diff --git a/src/master/master.c b/src/master/master.c
index a9d5d1b..db88c55 100644 index a9d5d1b..db88c55 100644
--- a/src/master/master.c --- a/src/master/master.c
...@@ -29,12 +29,13 @@ index a9d5d1b..db88c55 100644 ...@@ -29,12 +29,13 @@ index a9d5d1b..db88c55 100644
/* /*
* Process JCL. * Process JCL.
@@ -392,8 +392,10 @@ int main(int argc, char **argv) @@ -433,9 +433,11 @@ int main(int argc, char **argv)
* all MTA processes cleanly. Give up if we can't separate from our * all MTA processes cleanly. Give up if we can't separate from our
* parent process. We're not supposed to blow away the parent. * parent process. We're not supposed to blow away the parent.
*/ */
+ /* + /*
if (debug_me == 0 && master_detach != 0 && setsid() == -1 && getsid(0) != getpid()) if (init_mode == 0 && debug_me == 0 && master_detach != 0
&& setsid() == -1 && getsid(0) != getpid())
msg_fatal("unable to set session and process group ID: %m"); msg_fatal("unable to set session and process group ID: %m");
+ */ + */
......
diff --git a/makedefs b/makedefs
index dd5f256..e90880e 100644
--- a/makedefs
+++ b/makedefs
@@ -299,13 +299,13 @@ case "$SYSTEM.$RELEASE" in
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# No, we're not going to try db1 db2 db3 etc.
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
@@ -372,12 +372,12 @@ EOF
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
@@ -403,12 +403,12 @@ EOF
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
...@@ -7,6 +7,7 @@ parts = ...@@ -7,6 +7,7 @@ parts =
[socat] [socat]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true
url = http://www.dest-unreach.org/socat/download/socat-${:version}.tar.gz url = http://www.dest-unreach.org/socat/download/socat-${:version}.tar.gz
version = 1.7.3.2 version = 1.7.3.2
md5sum = aec3154f7854580cfab0c2d81e910519 md5sum = aec3154f7854580cfab0c2d81e910519
......
...@@ -6,6 +6,7 @@ extends = ...@@ -6,6 +6,7 @@ extends =
../make/buildout.cfg ../make/buildout.cfg
../ncurses/buildout.cfg ../ncurses/buildout.cfg
../openssl/buildout.cfg ../openssl/buildout.cfg
../patch/buildout.cfg
../pcre/buildout.cfg ../pcre/buildout.cfg
../perl/buildout.cfg ../perl/buildout.cfg
../pkgconfig/buildout.cfg ../pkgconfig/buildout.cfg
...@@ -22,9 +23,12 @@ min_version = 8 ...@@ -22,9 +23,12 @@ min_version = 8
[trafficserver] [trafficserver]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = http://apache.claz.org/trafficserver/trafficserver-8.1.0.tar.bz2 url = http://apache.claz.org/trafficserver/trafficserver-8.1.1.tar.bz2
md5sum = 99bfeb61095e55cb151ef58d884cb3f1 md5sum = 4f4d1e7de19c77157be0c2a825b31026
shared = true shared = true
patch-options = -p1
patches =
${:_profile_base_location_}/trafficserver-8.1-stale-negative-cache-not-returnable.patch#e1a2f8a23f00cee1301ccf1a84e46763
configure-options = configure-options =
--with-openssl=${openssl:location} --with-openssl=${openssl:location}
--with-pcre=${pcre:location} --with-pcre=${pcre:location}
...@@ -37,7 +41,7 @@ configure-options = ...@@ -37,7 +41,7 @@ configure-options =
--enable-experimental-plugins --enable-experimental-plugins
--disable-posix-cap --disable-posix-cap
environment = environment =
PATH=${libtool:location}/bin:${make:location}/bin:${perl:location}/bin:${pkgconfig:location}/bin:%(PATH)s PATH=${libtool:location}/bin:${make:location}/bin:${patch:location}/bin:${perl:location}/bin:${pkgconfig:location}/bin:%(PATH)s
LDFLAGS =-L${openssl:location}/lib -Wl,-rpath=${openssl:location}/lib -L${tcl:location}/lib -Wl,-rpath=${tcl:location}/lib -L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib LDFLAGS =-L${openssl:location}/lib -Wl,-rpath=${openssl:location}/lib -L${tcl:location}/lib -Wl,-rpath=${tcl:location}/lib -L${zlib:location}/lib -Wl,-rpath=${zlib:location}/lib
make-target = make-target =
......
--- trafficserver-8.1.1/proxy/http/HttpTransact.cc.orig 2020-12-01 00:30:26.000000000 +0100
+++ trafficserver-8.1.1/proxy/http/HttpTransact.cc 2021-01-11 11:35:41.946893735 +0100
@@ -5752,6 +5752,7 @@
HttpTransact::is_stale_cache_response_returnable(State *s)
{
HTTPHdr *cached_response = s->cache_info.object_read->response_get();
+ HTTPStatus cache_response_code = cached_response->status_get();
// First check if client allows cached response
// Note does_client_permit_lookup was set to
@@ -5760,6 +5761,12 @@
if (!s->cache_info.directives.does_client_permit_lookup) {
return false;
}
+ // We don't serve stale negative cache.
+ if (cache_response_code == HTTP_STATUS_INTERNAL_SERVER_ERROR || cache_response_code == HTTP_STATUS_GATEWAY_TIMEOUT ||
+ cache_response_code == HTTP_STATUS_BAD_GATEWAY || cache_response_code == HTTP_STATUS_SERVICE_UNAVAILABLE) {
+ TxnDebug("http_trans", "[is_stale_cache_response_returnable] stale negative cache");
+ return false;
+ }
// Spec says that we can not serve a stale document with a
// "must-revalidate header"
// How about "s-maxage" and "no-cache" directives?
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
shared = true shared = true
url = https://lab.nexedi.com/nexedi/userhosts/repository/${:revision}/archive.tar.gz url = https://lab.nexedi.com/nexedi/userhosts/repository/${:revision}/archive.tar.gz
revision = 1d3b463e7856db6e674a06258c0840206e6a7b72 revision = a05fe5a3a5cb7005351ef4ec41460089f3ce4d0a
md5sum = 5a80b4d962d975f290a60cf790c3334d
configure-command = true configure-command = true
make-options = PREFIX=@@LOCATION@@ make-options = PREFIX=@@LOCATION@@
make-targets = check install make-targets = check install
...@@ -10,19 +10,10 @@ parts = ...@@ -10,19 +10,10 @@ parts =
wendelin.core wendelin.core
# wendelin.core installed from released egg from pypi # wendelin.core is installed from git checkout
[wendelin.core] [wendelin.core]
recipe = zc.recipe.egg:custom
<= wendelin.core-eggcommon
# wendelin.core installed from latest git version
[wendelin.core-dev]
recipe = zc.recipe.egg:develop recipe = zc.recipe.egg:develop
setup = ${wendelin.core-repository:location} setup = ${wendelin.core-repository:location}
<= wendelin.core-eggcommon
# common parts in between wendelin.core and wendelin.core-dev
[wendelin.core-eggcommon]
egg = wendelin.core egg = wendelin.core
setup-eggs = setup-eggs =
${pygolang:egg}[pyx.build] ${pygolang:egg}[pyx.build]
...@@ -41,6 +32,8 @@ PATH = ${git:location}/bin:%(PATH)s ...@@ -41,6 +32,8 @@ PATH = ${git:location}/bin:%(PATH)s
[wendelin.core-repository] [wendelin.core-repository]
recipe = slapos.recipe.build:gitclone recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/wendelin.core.git repository = https://lab.nexedi.com/nexedi/wendelin.core.git
# dir is pretty name as top-level -dev recipe branch = master
location = ${buildout:parts-directory}/wendelin.core-dev revision = v0.13-0-gb26ba55
# dir is pretty name as top-level recipe
location = ${buildout:parts-directory}/wendelin.core
git-executable = ${git:location}/bin/git git-executable = ${git:location}/bin/git
...@@ -15,7 +15,7 @@ parts = ...@@ -15,7 +15,7 @@ parts =
# keep neoppod first and in parts so that ZODB is built correctly # keep neoppod first and in parts so that ZODB is built correctly
neoppod neoppod
wendelin.core-dev wendelin.core
# for instance # for instance
wendelin.core-python wendelin.core-python
......
...@@ -7,7 +7,7 @@ set up. ...@@ -7,7 +7,7 @@ set up.
How to Use generic_varnish ? How to Use generic_varnish ?
============================ ============================
On slap console, you can instanciate varnish like this:: On slap console, you can instantiate varnish like this::
instance = request( instance = request(
software_type='varnish', software_type='varnish',
......
...@@ -48,5 +48,4 @@ gitdb = 0.6.4 ...@@ -48,5 +48,4 @@ gitdb = 0.6.4
pycrypto = 2.6.1 pycrypto = 2.6.1
pycurl = 7.43.0 pycurl = 7.43.0
slapos.recipe.download = 1.0 slapos.recipe.download = 1.0
slapos.recipe.template = 4.4
smmap = 0.9.0 smmap = 0.9.0
...@@ -84,5 +84,4 @@ numpy = 1.16.4 ...@@ -84,5 +84,4 @@ numpy = 1.16.4
# websockify 0.4.1 doesn't install well # websockify 0.4.1 doesn't install well
websockify = 0.3.0 websockify = 0.3.0
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 2.4.2
z3c.recipe.mkdir = 0.5 z3c.recipe.mkdir = 0.5
...@@ -105,5 +105,4 @@ mode = 0644 ...@@ -105,5 +105,4 @@ mode = 0644
rdiff-backup = 1.0.5+SlapOSPatched001 rdiff-backup = 1.0.5+SlapOSPatched001
gunicorn = 19.1.1 gunicorn = 19.1.1
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 2.4.3
PyRSS2Gen = 1.1 PyRSS2Gen = 1.1
...@@ -82,6 +82,3 @@ packages += ...@@ -82,6 +82,3 @@ packages +=
dh-autoreconf pkg-config doxygen maven xmlto dh-autoreconf pkg-config doxygen maven xmlto
# hellorina (shouldn't parts like lxml-python depend on the python of the SR?) # hellorina (shouldn't parts like lxml-python depend on the python of the SR?)
python-dev python-dev
[versions]
slapos.recipe.template = 4.4
...@@ -59,6 +59,3 @@ template = ...@@ -59,6 +59,3 @@ template =
key slapos_buildout slapos.buildout-repository:location key slapos_buildout slapos.buildout-repository:location
key temp_directory directory:tmp key temp_directory directory:tmp
raw runTestSuite_py ${buildout:bin-directory}/${runTestSuite_py:interpreter} raw runTestSuite_py ${buildout:bin-directory}/${runTestSuite_py:interpreter}
[versions]
slapos.recipe.template = 4.4
...@@ -26,7 +26,7 @@ md5sum = e8db3179e3278c6390a786cdcc947173 ...@@ -26,7 +26,7 @@ md5sum = e8db3179e3278c6390a786cdcc947173
[profile-caddy-replicate] [profile-caddy-replicate]
filename = instance-apache-replicate.cfg.in filename = instance-apache-replicate.cfg.in
md5sum = b29a4764dd489030030a72770162c157 md5sum = 2329022227099971a57f710832509153
[profile-slave-list] [profile-slave-list]
_update_hash_filename_ = templates/apache-custom-slave-list.cfg.in _update_hash_filename_ = templates/apache-custom-slave-list.cfg.in
...@@ -46,7 +46,7 @@ md5sum = 88af61e7abbf30dc99a1a2526161128d ...@@ -46,7 +46,7 @@ md5sum = 88af61e7abbf30dc99a1a2526161128d
[template-default-slave-virtualhost] [template-default-slave-virtualhost]
_update_hash_filename_ = templates/default-virtualhost.conf.in _update_hash_filename_ = templates/default-virtualhost.conf.in
md5sum = 266f175dbdfc588af7a86b0b1884fe73 md5sum = bd9e269130bac989faa639e0903814e2
[template-backend-haproxy-configuration] [template-backend-haproxy-configuration]
_update_hash_filename_ = templates/backend-haproxy.cfg.in _update_hash_filename_ = templates/backend-haproxy.cfg.in
...@@ -62,7 +62,7 @@ md5sum = 975177dedf677d24e14cede5d13187ce ...@@ -62,7 +62,7 @@ md5sum = 975177dedf677d24e14cede5d13187ce
[template-trafficserver-records-config] [template-trafficserver-records-config]
_update_hash_filename_ = templates/trafficserver/records.config.jinja2 _update_hash_filename_ = templates/trafficserver/records.config.jinja2
md5sum = 18076ae37306aca1f6ef11e2173c887f md5sum = b99403e02d1aff471a7d5ebd0afbdb6c
[template-trafficserver-storage-config] [template-trafficserver-storage-config]
_update_hash_filename_ = templates/trafficserver/storage.config.jinja2 _update_hash_filename_ = templates/trafficserver/storage.config.jinja2
......
...@@ -111,7 +111,6 @@ context = ...@@ -111,7 +111,6 @@ context =
{% set authorized_slave_string_list = [] %} {% set authorized_slave_string_list = [] %}
{% set authorized_slave_list = [] %} {% set authorized_slave_list = [] %}
{% set rejected_slave_dict = {} %} {% set rejected_slave_dict = {} %}
{% set rejected_slave_title_dict = {} %}
{% set warning_slave_dict = {} %} {% set warning_slave_dict = {} %}
{% set used_host_list = [] %} {% set used_host_list = [] %}
{% for slave in sorted(instance_parameter_dict['slave-instance-list']) %} {% for slave in sorted(instance_parameter_dict['slave-instance-list']) %}
...@@ -247,7 +246,6 @@ context = ...@@ -247,7 +246,6 @@ context =
{% do authorized_slave_list.append(authorized_slave) %} {% do authorized_slave_list.append(authorized_slave) %}
{% else %} {% else %}
{% do rejected_slave_dict.__setitem__(slave.get('slave_reference'), sorted(slave_error_list)) %} {% do rejected_slave_dict.__setitem__(slave.get('slave_reference'), sorted(slave_error_list)) %}
{% do rejected_slave_title_dict.__setitem__(slave.get('slave_title'), sorted(slave_error_list)) %}
{% endif %} {% endif %}
{% if len(slave_warning_list) > 0 %} {% if len(slave_warning_list) > 0 %}
{% do warning_slave_dict.__setitem__(slave.get('slave_reference'), sorted(slave_warning_list)) %} {% do warning_slave_dict.__setitem__(slave.get('slave_reference'), sorted(slave_warning_list)) %}
...@@ -326,7 +324,7 @@ accepted-slave-amount = {{ authorized_slave_list | length }} ...@@ -326,7 +324,7 @@ accepted-slave-amount = {{ authorized_slave_list | length }}
rejected-slave-amount = {{ rejected_slave_dict | length }} rejected-slave-amount = {{ rejected_slave_dict | length }}
backend-client-caucase-url = {{ caucase_url }} backend-client-caucase-url = {{ caucase_url }}
{# sort_keys are important in order to avoid shuffling parameters on each run #} {# sort_keys are important in order to avoid shuffling parameters on each run #}
rejected-slave-dict = {{ dumps(json_module.dumps(rejected_slave_title_dict, sort_keys=True)) }} rejected-slave-dict = {{ dumps(json_module.dumps(rejected_slave_dict, sort_keys=True)) }}
rejected-slave-promise-url = ${rejected-slave-promise:config-url} rejected-slave-promise-url = ${rejected-slave-promise:config-url}
master-key-upload-url = ${request-kedifa:connection-master-key-upload-url} master-key-upload-url = ${request-kedifa:connection-master-key-upload-url}
master-key-generate-auth-url = ${request-kedifa:connection-master-key-generate-auth-url} master-key-generate-auth-url = ${request-kedifa:connection-master-key-generate-auth-url}
...@@ -485,6 +483,7 @@ user-ca-certificate = ${directory:aikc}/user-ca-certificate.pem ...@@ -485,6 +483,7 @@ user-ca-certificate = ${directory:aikc}/user-ca-certificate.pem
user-crl = ${directory:aikc}/user-crl.pem user-crl = ${directory:aikc}/user-crl.pem
user-created = ${directory:aikc}/user-created user-created = ${directory:aikc}/user-created
csr_id = ${directory:aikc}/csr_id csr_id = ${directory:aikc}/csr_id
data_dir = ${directory:aikc}/caucase-updater
[aikc-user-csr] [aikc-user-csr]
recipe = plone.recipe.command recipe = plone.recipe.command
...@@ -547,7 +546,7 @@ command = ...@@ -547,7 +546,7 @@ command =
buildout_bin_directory=software_parameter_dict['bin_directory'], buildout_bin_directory=software_parameter_dict['bin_directory'],
updater_path='${directory:service}/aikc-user-caucase-updater', updater_path='${directory:service}/aikc-user-caucase-updater',
url='${aikc-config:caucase-url}', url='${aikc-config:caucase-url}',
data_dir='${directory:srv}/caucase-updater', data_dir='${aikc-config:data_dir}',
crt_path='${aikc-config:key}', crt_path='${aikc-config:key}',
ca_path='${aikc-config:user-ca-certificate}', ca_path='${aikc-config:user-ca-certificate}',
crl_path='${aikc-config:user-crl}', crl_path='${aikc-config:user-crl}',
...@@ -620,6 +619,7 @@ user-ca-certificate = ${directory:aibcc}/user-ca-certificate.pem ...@@ -620,6 +619,7 @@ user-ca-certificate = ${directory:aibcc}/user-ca-certificate.pem
user-crl = ${directory:aibcc}/user-crl.pem user-crl = ${directory:aibcc}/user-crl.pem
user-created = ${directory:aibcc}/user-created user-created = ${directory:aibcc}/user-created
csr_id = ${directory:aibcc}/csr_id csr_id = ${directory:aibcc}/csr_id
data_dir = ${directory:aibcc}/caucase-updater
[aibcc-user-csr] [aibcc-user-csr]
recipe = plone.recipe.command recipe = plone.recipe.command
...@@ -684,7 +684,7 @@ command = ...@@ -684,7 +684,7 @@ command =
buildout_bin_directory=software_parameter_dict['bin_directory'], buildout_bin_directory=software_parameter_dict['bin_directory'],
updater_path='${directory:service}/aibcc-user-caucase-updater', updater_path='${directory:service}/aibcc-user-caucase-updater',
url='${aibcc-config:caucase-url}', url='${aibcc-config:caucase-url}',
data_dir='${directory:srv}/caucase-updater', data_dir='${aibcc-config:data_dir}',
crt_path='${aibcc-config:key}', crt_path='${aibcc-config:key}',
ca_path='${aibcc-config:user-ca-certificate}', ca_path='${aibcc-config:user-ca-certificate}',
crl_path='${aibcc-config:user-crl}', crl_path='${aibcc-config:user-crl}',
...@@ -747,9 +747,9 @@ filename = rejected-slave.json ...@@ -747,9 +747,9 @@ filename = rejected-slave.json
directory = ${directory:promise-output} directory = ${directory:promise-output}
rendered = ${:directory}/${:filename} rendered = ${:directory}/${:filename}
template = {{ software_parameter_dict['template_empty'] }} template = {{ software_parameter_dict['template_empty'] }}
{% if rejected_slave_title_dict %} {% if rejected_slave_dict %}
{# sort_keys are important in order to avoid shuffling parameters on each run #} {# sort_keys are important in order to avoid shuffling parameters on each run #}
content = {{ dumps(json_module.dumps(rejected_slave_title_dict, indent=2, sort_keys=True)) }} content = {{ dumps(json_module.dumps(rejected_slave_dict, indent=2, sort_keys=True)) }}
{% else %} {% else %}
content = content =
{% endif %} {% endif %}
......
...@@ -246,7 +246,6 @@ gitdb = 0.6.4 ...@@ -246,7 +246,6 @@ gitdb = 0.6.4
plone.recipe.command = 1.1 plone.recipe.command = 1.1
pycrypto = 2.6.1 pycrypto = 2.6.1
rdiff-backup = 1.0.5+SlapOSPatched001 rdiff-backup = 1.0.5+SlapOSPatched001
slapos.recipe.template = 4.4
smmap = 0.9.0 smmap = 0.9.0
websockify = 0.8.0 websockify = 0.8.0
......
...@@ -43,6 +43,9 @@ ...@@ -43,6 +43,9 @@
timeout {{ slave_parameter['request-timeout'] }}s timeout {{ slave_parameter['request-timeout'] }}s
# force reset of X-Forwarded-For # force reset of X-Forwarded-For
header_upstream X-Forwarded-For {remote} header_upstream X-Forwarded-For {remote}
# workaround for lost connection to haproxy by reconnecting
try_duration 3s
try_interval 250ms
{%- endmacro %} {# proxy_header #} {%- endmacro %} {# proxy_header #}
{%- for tls in [True, False] %} {%- for tls in [True, False] %}
......
...@@ -23,9 +23,19 @@ CONFIG proxy.config.log.logfile_dir STRING {{ ats_directory['log'] }} ...@@ -23,9 +23,19 @@ CONFIG proxy.config.log.logfile_dir STRING {{ ats_directory['log'] }}
# Implement RFC 5861 with core # Implement RFC 5861 with core
CONFIG proxy.config.http.cache.open_write_fail_action INT 2 CONFIG proxy.config.http.cache.open_write_fail_action INT 2
CONFIG proxy.config.body_factory.template_sets_dir STRING {{ ats_configuration['templates-dir'] }} CONFIG proxy.config.body_factory.template_sets_dir STRING {{ ats_configuration['templates-dir'] }}
# Support stale-if-error by returning cached content on backend 5xx or unavailability # Simulate stale-if-error (not supported by TrafficServer), by using internal
# mechanism
# This results with replying last know non-5xx response until max_stale_age is reached
# ignoring max-age returned by the server
CONFIG proxy.config.http.negative_revalidating_enabled INT 1 CONFIG proxy.config.http.negative_revalidating_enabled INT 1
CONFIG proxy.config.http.negative_revalidating_lifetime INT 86400 # max_stale_age set here means that for 1 week since last correct response
# the response will be sent by the system
CONFIG proxy.config.http.cache.max_stale_age INT 604800
# negative_revalidating_lifetime just adds Expires header calculated as
# Expires = Date + negative_revalidating_lifetime
# for case when backend replies 5xx, and Age > max-age and Age < max_stale_age
# and that's not needed, so drop this behaviour
CONFIG proxy.config.http.negative_revalidating_lifetime INT 0
############################################################################## ##############################################################################
# Thread configurations. Docs: # Thread configurations. Docs:
...@@ -80,10 +90,9 @@ CONFIG proxy.config.net.default_inactivity_timeout INT 86400 ...@@ -80,10 +90,9 @@ CONFIG proxy.config.net.default_inactivity_timeout INT 86400
# Origin server connect attempts. Docs: # Origin server connect attempts. Docs:
# https://docs.trafficserver.apache.org/records.config#origin-server-connect-attempts # https://docs.trafficserver.apache.org/records.config#origin-server-connect-attempts
############################################################################## ##############################################################################
# Try only once to connect (do not retry) # workaround for lost connection to haproxy by reconnecting
CONFIG proxy.config.http.connect_attempts_max_retries INT 0 CONFIG proxy.config.http.connect_attempts_max_retries INT 3
# Try only once with server marked dead (do not retry) CONFIG proxy.config.http.connect_attempts_max_retries_dead_server INT 1
CONFIG proxy.config.http.connect_attempts_max_retries_dead_server INT 0
CONFIG proxy.config.http.connect_attempts_rr_retries INT 3 CONFIG proxy.config.http.connect_attempts_rr_retries INT 3
CONFIG proxy.config.http.connect_attempts_timeout INT {{ ats_configuration['request-timeout'] }} CONFIG proxy.config.http.connect_attempts_timeout INT {{ ats_configuration['request-timeout'] }}
CONFIG proxy.config.http.post_connect_attempts_timeout INT {{ ats_configuration['request-timeout'] }} CONFIG proxy.config.http.post_connect_attempts_timeout INT {{ ats_configuration['request-timeout'] }}
......
This diff is collapsed.
...@@ -24,6 +24,3 @@ context = ...@@ -24,6 +24,3 @@ context =
key eggs_directory buildout:eggs-directory key eggs_directory buildout:eggs-directory
key caucase_jinja2_library caucase-jinja2-library:target key caucase_jinja2_library caucase-jinja2-library:target
key instance_caucased instance-caucased:target key instance_caucased instance-caucased:target
[versions]
slapos.recipe.template = 3.0
...@@ -39,4 +39,3 @@ eggs = ...@@ -39,4 +39,3 @@ eggs =
cns.recipe.symlink = 0.2.3 cns.recipe.symlink = 0.2.3
collective.recipe.environment = 0.2.0 collective.recipe.environment = 0.2.0
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 4.4
[instance.cfg]
filename = instance.cfg.in
md5sum = a24384487467a07e827edab17a0b7206
[runTestSuite.in]
_update_hash_filename_ = runTestSuite.in
md5sum = 21a8a202b14475707c414056ba393b3d
[buildout]
parts =
publish-env-path
runTestSuite
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[publish-env-path]
recipe = slapos.cookbook:publish
readme = Source the script to set up the environment.
script = ${cythonplus_env.sh:rendered}
repository = ${cythonplus-repository:repository}
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
[directory]
recipe = slapos.cookbook:mkdirectory
bin = $${buildout:directory}/bin
tmp = $${buildout:directory}/tmp
[cythonplus-repository]
recipe = slapos.recipe.build:gitclone
repository = ${cythonplus-repository:location}
git-executable = ${git:location}/bin/git
shared = true
[runTestSuite]
recipe = slapos.recipe.template:jinja2
rendered = $${directory:bin}/$${:_buildout_section_name_}
template = ${runTestSuite.in:target}
mode = 0755
context =
key tmpdir directory:tmp
key slapparameter_dict slap-configuration:configuration
key cythonplus_repository cythonplus-repository:location
raw runTestSuite_interpreter ${runTestSuite_interpreter:bin-directory}/${runTestSuite_interpreter:interpreter}
raw cythonplus_env_sh ${cythonplus_env.sh:rendered}
#!{{ runTestSuite_py }} #!{{ runTestSuite_interpreter }}
""" """
Script to run the Cython test suite using Nexedi's test node framework. Script to run the Cython test suite using Nexedi's test node framework.
""" """
...@@ -9,7 +9,7 @@ from erp5.util import taskdistribution, testsuite ...@@ -9,7 +9,7 @@ from erp5.util import taskdistribution, testsuite
os.environ['TEMP'] = {{ repr(tmpdir) }} os.environ['TEMP'] = {{ repr(tmpdir) }}
command = """. {{ cython_env_sh }} command = """. {{ cythonplus_env_sh }}
make all test make all test
""" """
...@@ -96,7 +96,7 @@ def main(): ...@@ -96,7 +96,7 @@ def main():
with open(os.devnull) as stdin: with open(os.devnull) as stdin:
p = subprocess.Popen(command, shell=True, stdin=stdin, p = subprocess.Popen(command, shell=True, stdin=stdin,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
cwd={{repr(cython_repository)}}) cwd={{ repr(cythonplus_repository) }})
except Exception: except Exception:
end = time() end = time()
stderr = traceback.format_exc() stderr = traceback.format_exc()
......
[buildout]
extends =
buildout.hash.cfg
../../stack/slapos.cfg
../../component/cythonplus/buildout.cfg
parts =
slapos-cookbook
instance.cfg
[instance.cfg]
recipe = slapos.recipe.template
output = ${buildout:directory}/${:_buildout_section_name_}
url = ${:_profile_base_location_}/${:filename}
[runTestSuite.in]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_update_hash_filename_}
[runTestSuite_interpreter]
recipe = zc.recipe.egg
eggs = erp5.util
interpreter = ${:_buildout_section_name_}
...@@ -34,4 +34,3 @@ command = ...@@ -34,4 +34,3 @@ command =
[versions] [versions]
openssl = 1.0.1c openssl = 1.0.1c
slapos.recipe.template = 2.4.2
...@@ -34,4 +34,3 @@ command = ...@@ -34,4 +34,3 @@ command =
[versions] [versions]
openssl = 1.0.1c openssl = 1.0.1c
slapos.recipe.template = 2.4.2
...@@ -49,7 +49,6 @@ mysqlclient = 1.3.12 ...@@ -49,7 +49,6 @@ mysqlclient = 1.3.12
# indirect dependancies # indirect dependancies
cp.recipe.cmd = 0.5 cp.recipe.cmd = 0.5
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 4.4
zope.exceptions = 4.0.7 zope.exceptions = 4.0.7
zope.testing = 4.1.3 zope.testing = 4.1.3
zc.recipe.testrunner = 2.0.0 zc.recipe.testrunner = 2.0.0
......
...@@ -59,7 +59,7 @@ Setting up replication ...@@ -59,7 +59,7 @@ Setting up replication
In addition to your usual parameter set, you needs to provide the following parameters:: In addition to your usual parameter set, you needs to provide the following parameters::
{ {
"zope-partition-dict": {}, So no zope is instanciated "zope-partition-dict": {}, So no zope is instantiated
"zodb": [ "zodb": [
{ {
"storage-dict": { "storage-dict": {
......
...@@ -48,10 +48,6 @@ def setUpModule(): ...@@ -48,10 +48,6 @@ def setUpModule():
class ERP5InstanceTestCase(SlapOSInstanceTestCase): class ERP5InstanceTestCase(SlapOSInstanceTestCase):
"""ERP5 base test case """ERP5 base test case
""" """
# ERP5 instanciation needs to run several times before being ready, as
# the root instance request more instances.
instance_max_retry = 7 # XXX how many times ?
def getRootPartitionConnectionParameterDict(self): def getRootPartitionConnectionParameterDict(self):
"""Return the output paramters from the root partition""" """Return the output paramters from the root partition"""
return json.loads( return json.loads(
......
This diff is collapsed.
...@@ -43,23 +43,44 @@ setUpModule # pyflakes ...@@ -43,23 +43,44 @@ setUpModule # pyflakes
class TestPublishedURLIsReachableMixin(object): class TestPublishedURLIsReachableMixin(object):
"""Mixin that checks that default page of ERP5 is reachable. """Mixin that checks that default page of ERP5 is reachable.
""" """
def _checkERP5IsReachable(self, url):
# What happens is that instanciation just create the services, but does not def _checkERP5IsReachable(self, base_url, site_id, verify):
# We access ERP5 trough a "virtual host", which should make
# ERP5 produce URLs using https://virtual-host-name:1234/virtual_host_root
# as base.
virtual_host_url = urlparse.urljoin(
base_url,
'/VirtualHostBase/https/virtual-host-name:1234/{}/VirtualHostRoot/_vh_virtual_host_root/'
.format(site_id))
# What happens is that instantiation just create the services, but does not
# wait for ERP5 to be initialized. When this test run ERP5 instance is # wait for ERP5 to be initialized. When this test run ERP5 instance is
# instanciated, but zope is still busy creating the site and haproxy replies # instantiated, but zope is still busy creating the site and haproxy replies
# with 503 Service Unavailable when zope is not started yet, with 404 when # with 503 Service Unavailable when zope is not started yet, with 404 when
# erp5 site is not created, with 500 when mysql is not yet reachable, so we # erp5 site is not created, with 500 when mysql is not yet reachable, so we
# retry in a loop until we get a succesful response. # configure this requests session to retry.
for i in range(1, 60): # XXX we should probably add a promise instead
r = requests.get(url, verify=False) # XXX can we get CA from caucase already ? session = requests.Session()
if r.status_code != requests.codes.ok: session.mount(
delay = i * 2 base_url,
self.logger.warn("ERP5 was not available, sleeping for %ds and retrying", delay) requests.adapters.HTTPAdapter(
time.sleep(delay) max_retries=requests.packages.urllib3.util.retry.Retry(
continue total=60,
r.raise_for_status() backoff_factor=.5,
break status_forcelist=(404, 500, 503))))
r = session.get(virtual_host_url, verify=verify, allow_redirects=False)
self.assertEqual(r.status_code, requests.codes.found)
# access on / are redirected to login form, with virtual host preserved
self.assertEqual(r.headers.get('location'), 'https://virtual-host-name:1234/virtual_host_root/login_form')
# login page can be rendered and contain the text "ERP5"
r = session.get(
urlparse.urljoin(base_url, '{}/login_form'.format(site_id)),
verify=verify,
allow_redirects=False,
)
self.assertEqual(r.status_code, requests.codes.ok)
self.assertIn("ERP5", r.text) self.assertIn("ERP5", r.text)
def test_published_family_default_v6_is_reachable(self): def test_published_family_default_v6_is_reachable(self):
...@@ -67,18 +88,24 @@ class TestPublishedURLIsReachableMixin(object): ...@@ -67,18 +88,24 @@ class TestPublishedURLIsReachableMixin(object):
""" """
param_dict = self.getRootPartitionConnectionParameterDict() param_dict = self.getRootPartitionConnectionParameterDict()
self._checkERP5IsReachable( self._checkERP5IsReachable(
urlparse.urljoin(param_dict['family-default-v6'], param_dict['site-id'])) param_dict['family-default-v6'],
param_dict['site-id'],
verify=False,
)
def test_published_family_default_v4_is_reachable(self): def test_published_family_default_v4_is_reachable(self):
"""Tests the IPv4 URL published by the root partition is reachable. """Tests the IPv4 URL published by the root partition is reachable.
""" """
param_dict = self.getRootPartitionConnectionParameterDict() param_dict = self.getRootPartitionConnectionParameterDict()
self._checkERP5IsReachable( self._checkERP5IsReachable(
urlparse.urljoin(param_dict['family-default'], param_dict['site-id'])) param_dict['family-default'],
param_dict['site-id'],
verify=False,
)
class TestDefaultParameters(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): class TestDefaultParameters(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated with no parameters """Test ERP5 can be instantiated with no parameters
""" """
__partition_reference__ = 'defp' __partition_reference__ = 'defp'
...@@ -92,9 +119,32 @@ class TestMedusa(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): ...@@ -92,9 +119,32 @@ class TestMedusa(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return {'_': json.dumps({'wsgi': False})} return {'_': json.dumps({'wsgi': False})}
class TestJupyter(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 Jupyter notebook
"""
__partition_reference__ = 'jupyter'
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({'jupyter': {'enable': True}})}
class TestApacheBalancerPorts(ERP5InstanceTestCase): def test_jupyter_notebook_is_reachable(self):
"""Instanciate with two zope families, this should create for each family: param_dict = self.getRootPartitionConnectionParameterDict()
self.assertEqual(
'https://[%s]:8888/tree' % self._ipv6_address,
param_dict['jupyter-url']
)
result = requests.get(
param_dict['jupyter-url'], verify=False, allow_redirects=False)
self.assertEqual(
[requests.codes.found, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
class TestBalancerPorts(ERP5InstanceTestCase):
"""Instantiate with two zope families, this should create for each family:
- a balancer entry point with corresponding haproxy - a balancer entry point with corresponding haproxy
- a balancer entry point for test runner - a balancer entry point for test runner
""" """
...@@ -151,36 +201,25 @@ class TestApacheBalancerPorts(ERP5InstanceTestCase): ...@@ -151,36 +201,25 @@ class TestApacheBalancerPorts(ERP5InstanceTestCase):
3 + 5, 3 + 5,
len([p for p in all_process_info if p['name'].startswith('zope-')])) len([p for p in all_process_info if p['name'].startswith('zope-')]))
def test_apache_listen(self): def test_haproxy_listen(self):
# We have 2 families, apache should listen to a total of 3 ports per family # We have 2 families, haproxy should listen to a total of 3 ports per family
# normal access on ipv4 and ipv6 and test runner access on ipv4 only # normal access on ipv4 and ipv6 and test runner access on ipv4 only
with self.slap.instance_supervisor_rpc as supervisor: with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo() all_process_info = supervisor.getAllProcessInfo()
process_info, = [p for p in all_process_info if p['name'] == 'apache'] process_info, = [p for p in all_process_info if p['name'].startswith('haproxy-')]
apache_process = psutil.Process(process_info['pid']) haproxy_master_process = psutil.Process(process_info['pid'])
haproxy_worker_process, = haproxy_master_process.children()
self.assertEqual( self.assertEqual(
sorted([socket.AF_INET] * 4 + [socket.AF_INET6] * 2), sorted([socket.AF_INET] * 4 + [socket.AF_INET6] * 2),
sorted([ sorted([
c.family c.family
for c in apache_process.connections() for c in haproxy_worker_process.connections()
if c.status == 'LISTEN' if c.status == 'LISTEN'
])) ]))
def test_haproxy_listen(self):
# There is one haproxy per family
with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo()
process_info, = [
p for p in all_process_info if p['name'].startswith('haproxy-')
]
haproxy_process = psutil.Process(process_info['pid'])
self.assertEqual([socket.AF_INET, socket.AF_INET], [
c.family for c in haproxy_process.connections() if c.status == 'LISTEN'
])
class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test ERP5 can be instanciated without test runner. """Test ERP5 can be instantiated without test runner.
""" """
__partition_reference__ = 'distr' __partition_reference__ = 'distr'
@classmethod @classmethod
...@@ -199,20 +238,22 @@ class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMix ...@@ -199,20 +238,22 @@ class TestDisableTestRunner(ERP5InstanceTestCase, TestPublishedURLIsReachableMix
self.assertNotIn('runUnitTest', bin_programs) self.assertNotIn('runUnitTest', bin_programs)
self.assertNotIn('runTestSuite', bin_programs) self.assertNotIn('runTestSuite', bin_programs)
def test_no_apache_testrunner_port(self): def test_no_haproxy_testrunner_port(self):
# Apache only listen on two ports, there is no apache ports allocated for test runner # Haproxy only listen on two ports, there is no haproxy ports allocated for test runner
with self.slap.instance_supervisor_rpc as supervisor: with self.slap.instance_supervisor_rpc as supervisor:
all_process_info = supervisor.getAllProcessInfo() all_process_info = supervisor.getAllProcessInfo()
process_info, = [p for p in all_process_info if p['name'] == 'apache'] process_info, = [p for p in all_process_info if p['name'].startswith('haproxy')]
apache_process = psutil.Process(process_info['pid']) haproxy_master_process = psutil.Process(process_info['pid'])
haproxy_worker_process, = haproxy_master_process.children()
self.assertEqual( self.assertEqual(
sorted([socket.AF_INET, socket.AF_INET6]), sorted([socket.AF_INET, socket.AF_INET6]),
sorted( sorted(
c.family c.family
for c in apache_process.connections() for c in haproxy_worker_process.connections()
if c.status == 'LISTEN' if c.status == 'LISTEN'
)) ))
class TestZopeNodeParameterOverride(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin): class TestZopeNodeParameterOverride(ERP5InstanceTestCase, TestPublishedURLIsReachableMixin):
"""Test override zope node parameters """Test override zope node parameters
""" """
......
Upgrade tests for ERP5 software release
##############################################################################
#
# Copyright (c) 2020 Nexedi SA 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 setuptools import setup, find_packages
version = '0.0.1.dev0'
name = 'slapos.test.upgrade_erp5'
with open("README.md") as f:
long_description = f.read()
setup(name=name,
version=version,
description="Upgrade test for SlapOS' ERP5 software release",
long_description=long_description,
long_description_content_type='text/markdown',
maintainer="Nexedi",
maintainer_email="info@nexedi.com",
url="https://lab.nexedi.com/nexedi/slapos",
packages=find_packages(),
install_requires=[
'slapos.core',
'supervisor',
'slapos.libnetworkcache',
'typing; python_version<"3"',
],
test_suite='test',
)
##############################################################################
#
# Copyright (c) 2020 Nexedi SA 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.
#
##############################################################################
import glob
import json
import os
import tempfile
import time
import requests
import urlparse
from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass
from slapos.testing.testcase import installSoftwareUrlList
from slapos.testing.testcase import SlapOSNodeCommandError
from slapos.grid.utils import md5digest
old_software_release_url = 'https://lab.nexedi.com/nexedi/slapos/raw/1.0.167/software/erp5/software.cfg'
new_software_release_url = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'software.cfg'))
_, SlapOSInstanceTestCase = makeModuleSetUpAndTestCaseClass(
old_software_release_url, software_id="upgrade_erp5")
def setUpModule():
installSoftwareUrlList(
SlapOSInstanceTestCase,
[old_software_release_url, new_software_release_url],
debug=SlapOSInstanceTestCase._debug,
)
class ERP5UpgradeTestCase(SlapOSInstanceTestCase):
# use short partition names for unix sockets
__partition_reference__ = 'u'
@classmethod
def setUpOldInstance(cls):
"""setUp hook executed while to old instance is running, before update
"""
pass
_current_software_url = old_software_release_url
@classmethod
def getSoftwareURL(cls):
return cls._current_software_url
@classmethod
def setUpClass(cls):
# request and instanciate with old software url
super(ERP5UpgradeTestCase, cls).setUpClass()
cls.setUpOldInstance()
# request instance on new software
cls._current_software_url = new_software_release_url
cls.logger.debug('requesting instance on new software')
cls.requestDefaultInstance()
# wait for slapos node instance
snapshot_name = "{}.{}.setUpClass new instance".format(
cls.__module__, cls.__name__)
try:
if cls._debug and cls.instance_max_retry:
try:
cls.slap.waitForInstance(max_retry=cls.instance_max_retry - 1)
except SlapOSNodeCommandError:
cls.slap.waitForInstance(debug=True)
else:
cls.slap.waitForInstance(max_retry=cls.instance_max_retry,
debug=cls._debug)
cls.logger.debug("instance on new software done")
except BaseException:
cls.logger.exception("Error during instance on new software")
cls._storeSystemSnapshot(snapshot_name)
cls._cleanup(snapshot_name)
cls.setUp = lambda self: self.fail('Setup Class failed.')
raise
else:
cls._storeSystemSnapshot(snapshot_name)
cls.computer_partition = cls.requestDefaultInstance()
class TestERP5Upgrade(ERP5UpgradeTestCase):
@classmethod
def setUpOldInstance(cls):
cls._default_instance_old_parameter_dict = json.loads(
cls.computer_partition.getConnectionParameterDict()['_'])
def test_published_url_is_same(self):
default_instance_new_parameter_dict = json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
self.assertEqual(
default_instance_new_parameter_dict['family-default-v6'],
self._default_instance_old_parameter_dict['family-default-v6'],
)
def test_published_url_is_reachable(self):
default_instance_new_parameter_dict = json.loads(
self.computer_partition.getConnectionParameterDict()['_'])
# get certificate from caucase
with tempfile.NamedTemporaryFile(
prefix="ca.crt.pem",
mode="w",
delete=False,
) as ca_cert:
ca_cert.write(
requests.get(
urlparse.urljoin(
default_instance_new_parameter_dict['caucase-http-url'],
'/cas/crt/ca.crt.pem',
)).text)
ca_cert.flush()
# use a session to retry on failures, when ERP5 is not ready.
# (see also TestPublishedURLIsReachableMixin)
session = requests.Session()
session.mount(
default_instance_new_parameter_dict['family-default-v6'],
requests.adapters.HTTPAdapter(
max_retries=requests.packages.urllib3.util.retry.Retry(
total=60,
backoff_factor=.5,
status_forcelist=(404, 500, 503))))
session.get(
'{}/{}/login_form'.format(
default_instance_new_parameter_dict['family-default-v6'],
default_instance_new_parameter_dict['site-id'],
),
verify=False,
# TODO: we don't use caucase yet here.
# verify=ca_cert.name,
).raise_for_status()
def test_all_instances_use_new_software_release(self):
self.assertEqual(
{
os.path.basename(os.readlink(sr))
for sr in glob.glob(
os.path.join(
self.slap.instance_directory,
'*',
'software_release',
))
},
{md5digest(self.getSoftwareURL())},)
...@@ -42,7 +42,6 @@ output = ${buildout:directory}/template-default.cfg ...@@ -42,7 +42,6 @@ output = ${buildout:directory}/template-default.cfg
mode = 0644 mode = 0644
[versions] [versions]
slapos.recipe.template = 4.4
dnspython = 1.15.0 dnspython = 1.15.0
PyXML = 0.8.5 PyXML = 0.8.5
WebOb = 1.8.5 WebOb = 1.8.5
......
...@@ -13,6 +13,3 @@ url = ${:_profile_base_location_}/instance.cfg ...@@ -13,6 +13,3 @@ url = ${:_profile_base_location_}/instance.cfg
output = ${buildout:directory}/template.cfg output = ${buildout:directory}/template.cfg
md5sum = 9fccb9600a085691ab0f9a20cd615c01 md5sum = 9fccb9600a085691ab0f9a20cd615c01
mode = 0644 mode = 0644
[versions]
slapos.recipe.template = 4.4
...@@ -21,6 +21,3 @@ context = ...@@ -21,6 +21,3 @@ context =
gems += gems +=
fluent-plugin-wendelin==0.4 fluent-plugin-wendelin==0.4
fluent-plugin-bin fluent-plugin-bin
[versions]
slapos.recipe.template = 4.4
# THIS IS NOT A BUILDOUT FILE, despite purposedly using a compatible syntax.
# The only allowed lines here are (regexes):
# - "^#" comments, copied verbatim
# - "^[" section beginings, copied verbatim
# - lines containing an "=" sign which must fit in the following categorie.
# - "^\s*filename\s*=\s*path\s*$" where "path" is relative to this file
# Copied verbatim.
# - "^\s*hashtype\s*=.*" where "hashtype" is one of the values supported
# by the re-generation script.
# Re-generated.
# - other lines are copied verbatim
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[instance-cfg]
filename = instance.cfg.in
md5sum = 270b39f448ec553fa9e203c5fbb49856
[buildout]
parts =
publish-connection-parameter
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[publish-connection-parameter]
recipe = slapos.cookbook:publish
url = https://[$${galene-wrapper:ip}]:$${galene-wrapper:port}
admin-user = $${admin-password:username}
admin-password = $${admin-password:passwd}
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap-connection:computer-id}
partition = $${slap-connection:partition-id}
url = $${slap-connection:server-url}
key = $${slap-connection:key-file}
cert = $${slap-connection:cert-file}
configuration.ice-servers.json = [{"urls":["stun:turn.api.nexedi.net:3478"]}]
[directory]
recipe = slapos.cookbook:mkdirectory
etc = $${buildout:directory}/etc
var = $${buildout:directory}/var
srv = $${buildout:directory}/srv
bin = $${buildout:directory}/bin
tmp = $${buildout:directory}/tmp
run = $${:var}/run
services = $${:etc}/service
data = $${:srv}/data
groups = $${:srv}/groups
recordings = $${:srv}/recordings
[galene-ssl]
recipe = plone.recipe.command
cert-file = $${directory:data}/cert.pem
key-file = $${directory:data}/key.pem
command = ${openssl:location}/bin/openssl req -newkey rsa:2048 -batch -new -x509 -days 3650 -nodes -keyout "$${:key-file}" -out "$${:cert-file}"
update-command =
stop-on-error = true
[admin-password]
recipe = slapos.cookbook:generate.password
storage-path = $${directory:data}/.passwd
username = admin
[ice-servers.json]
recipe = collective.recipe.template
input = inline:
$${slap-configuration:configuration.ice-servers.json}
output = $${directory:data}/ice-servers.json
[groups-json]
recipe = collective.recipe.template
input = inline:{
"public":true,
"op": [{"username":"$${admin-password:username}","password":"$${admin-password:passwd}"}],
"other": [],
"presenter": [{"username": "", "password": "nexedi"}],
"max-users":100
}
output = $${directory:groups}/public.json
[galene-wrapper]
recipe = slapos.cookbook:wrapper
port = 8443
ip = $${slap-configuration:ipv6-random}
command-line =
${galene:location}/bin/galene
-static ${galene-repository:location}/static
-recordings $${directory:recordings}
-groups $${directory:groups}
-data $${directory:data}
-http [$${:ip}]:$${:port}
wrapper-path = $${directory:services}/galene
depends =
$${ice-servers.json:recipe}
$${groups-json:recipe}
$${galene-ssl:recipe}
[buildout]
extends =
../../component/golang/buildout.cfg
../../component/openssl/buildout.cfg
../../stack/slapos.cfg
buildout.hash.cfg
parts =
slapos-cookbook
galene
eggs
instance-cfg
# eggs for instance.cfg
[eggs]
recipe = zc.recipe.egg
eggs =
plone.recipe.command
collective.recipe.template
[galene-repository]
<= git-repository
repository = https://lab.nexedi.com/nexedi/galene.git
revision = galene-0.2
location = ${buildout:parts-directory}/galene-repository
[galene]
recipe = slapos.recipe.cmmi
path = ${galene-repository:location}
location = @@LOCATION@@
golang = ${golang1.13:location}
configure-command = true
make-binary =
make-targets =
go install -ldflags='-s -w'
environment =
PATH=${:location}/bin:${:golang}/bin:${git:location}/bin:${pkgconfig:location}/bin:$PATH
GOPATH=${:location}
CGO_ENABLED=0
[instance-cfg]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/instance.cfg
...@@ -405,5 +405,4 @@ strip-top-level-dir = true ...@@ -405,5 +405,4 @@ strip-top-level-dir = true
cns.recipe.symlink = 0.2.3 cns.recipe.symlink = 0.2.3
docutils = 0.12 docutils = 0.12
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 4.3
z3c.recipe.scripts = 1.0.1 z3c.recipe.scripts = 1.0.1
...@@ -157,5 +157,4 @@ curl-bin = ${curl:location}/bin/curl ...@@ -157,5 +157,4 @@ curl-bin = ${curl:location}/bin/curl
dash-bin = ${dash:location}/bin/dash dash-bin = ${dash:location}/bin/dash
[versions] [versions]
slapos.recipe.template = 4.2
inotifyx = 0.2.2 inotifyx = 0.2.2
...@@ -40,6 +40,3 @@ recipe = slapos.recipe.build:download ...@@ -40,6 +40,3 @@ recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_} url = ${:_profile_base_location_}/${:_buildout_section_name_}
mode = 755 mode = 755
md5sum = 78b77a6bda9958f547f7d89b747731e3 md5sum = 78b77a6bda9958f547f7d89b747731e3
[versions]
slapos.recipe.template = 4.4
...@@ -53,7 +53,3 @@ context = ...@@ -53,7 +53,3 @@ context =
raw template_monitor ${monitor2-template:rendered} raw template_monitor ${monitor2-template:rendered}
# md5sum is fetched from buildout.hash.cfg and can be recalculated automatically by # md5sum is fetched from buildout.hash.cfg and can be recalculated automatically by
# calling update-hash # calling update-hash
# Pin versions of eggs used that are not already pinned by stack/slapos.cfg
[versions]
slapos.recipe.template = 4.4
[buildout]
parts =
switch-softwaretype
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = ${instance_html5as:output}
[buildout]
parts =
switch-softwaretype
eggs-directory = {{ buildout['eggs-directory'] }}
develop-eggs-directory = {{ buildout['develop-eggs-directory'] }}
offline = true
[profile-common]
nginx_location = {{ nginx_location }}
dash_location = {{ dash_location }}
template_nginx_conf = {{ template_nginx_conf_target }}
template_mime_types = {{ template_mime_types_target }}
template_launcher = {{ template_launcher_target }}
[instance-html5as]
recipe = slapos.recipe.template:jinja2
template = {{ template_instance_html5as_target }}
rendered = ${buildout:directory}/${:filename}
filename = instance-html5as.cfg
context =
section buildout buildout
section parameter_list profile-common
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = ${instance-html5as:rendered}
#############################
#
# Deploy html5as instance
#
#############################
[buildout] [buildout]
parts = parts =
nginx_conf nginx_conf
downloader downloader
launcher
mime_types mime_types
launcher
publish-connection-information publish-connection-information
eggs-directory = ${buildout:eggs-directory} # Define egg directories to be the one from Software Release
develop-eggs-directory = ${buildout:develop-eggs-directory} # (/opt/slapgrid/...)
# Always the same.
eggs-directory = {{ buildout['eggs-directory'] }}
develop-eggs-directory = {{ buildout['develop-eggs-directory'] }}
offline = true offline = true
# partition tree # partition tree
...@@ -27,90 +35,97 @@ offline = true ...@@ -27,90 +35,97 @@ offline = true
# | | |- index.html # | | |- index.html
# | |- backup/ # | |- backup/
[rootdirectory] # Create all needed directories, depending on your needs
[directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
etc = $${buildout:directory}/etc home = ${buildout:directory}
var = $${buildout:directory}/var etc = ${:home}/etc
srv = $${buildout:directory}/srv var = ${:home}/var
tmp = $${buildout:directory}/tmp srv = ${:home}/srv
[basedirectory] [basedirectory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
services = $${rootdirectory:etc}/run # Executables put here will be started but not monitored (for startup scripts)
log = $${rootdirectory:var}/log script = ${directory:etc}/run
run = $${rootdirectory:var}/run # Executables put here will be started and monitored (for daemons)
backup = $${rootdirectory:srv}/backup service = ${directory:etc}/service
data = $${rootdirectory:srv}/html5as log = ${directory:var}/log
run = ${directory:var}/run
backup = ${directory:srv}/backup
data = ${directory:srv}/html5as
[tempdirectory] [tempdirectory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
client_body_temp_path = $${rootdirectory:tmp}/client_body_temp_path tmp = ${directory:home}/tmp
proxy_temp_path = $${rootdirectory:tmp}/proxy_temp_path client_body_temp_path = ${:tmp}/client_body_temp_path
fastcgi_temp_path = $${rootdirectory:tmp}/fastcgi_temp_path proxy_temp_path = ${:tmp}/proxy_temp_path
uwsgi_temp_path = $${rootdirectory:tmp}/uwsgi_temp_path fastcgi_temp_path = ${:tmp}/fastcgi_temp_path
scgi_temp_path = $${rootdirectory:tmp}/scgi_temp_path uwsgi_temp_path = ${:tmp}/uwsgi_temp_path
scgi_temp_path = ${:tmp}/scgi_temp_path
# List of options for html5as configuration
# It will run a simple nginx serving the content of srv/html5as
[html5as] [html5as]
# Options # Options
nb_workers = 2 nb_workers = 2
# Network # Network
ip = $${slap-network-information:global-ipv6} ip = ${slap-network-information:global-ipv6}
port = 8081 port = 8081
access_url = http://[${:ip}]:${:port}
# Paths # Paths
# Log # Log
path_pid = $${basedirectory:run}/nginx.pid path_pid = ${basedirectory:run}/nginx.pid
path_log = $${basedirectory:log}/nginx.log path_log = ${basedirectory:log}/nginx.log
path_access_log = $${basedirectory:log}/nginx.access.log path_access_log = ${basedirectory:log}/nginx.access.log
path_error_log = $${basedirectory:log}/nginx.error.log path_error_log = ${basedirectory:log}/nginx.error.log
path_tmp = $${buildout:directory}/tmp path_tmp = ${tempdirectory:tmp}
# Docroot # Docroot
docroot = $${basedirectory:data} docroot = ${basedirectory:data}
default_index = $${basedirectory:data}/index.html default_index = ${basedirectory:data}/index.html
# Config files # Config files
path_nginx_conf = $${rootdirectory:etc}/nginx.conf path_nginx_conf = ${directory:etc}/nginx.conf
path_mime_types = $${rootdirectory:etc}/mime_types path_mime_types = ${directory:etc}/mime_types
# Binaries
path_shell = {{ parameter_list['dash_location'] }}/bin/dash
# Executables # Executables
bin_nginx = ${nginx:location}/sbin/nginx bin_launcher = ${basedirectory:script}/launcher
bin_launcher = $${basedirectory:services}/launcher
bin_downloader = $${basedirectory:services}/downloader
# Utils # Utils
path_shell = ${dash:location}/bin/dash path_nginx = {{ parameter_list['nginx_location'] }}/sbin/nginx
path_curl = ${curl:location}/bin/curl
path_tar = ${tar:location}/bin/tar
# Render nginx conf
[nginx_conf] [nginx_conf]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${template_nginx_conf:location}/${template_nginx_conf:filename} template = {{ parameter_list['template_nginx_conf'] }}
rendered = $${html5as:path_nginx_conf} rendered = ${html5as:path_nginx_conf}
context = context =
section param_html5as html5as section param_html5as html5as
section param_tempdir tempdirectory section param_tempdir tempdirectory
# Render necessary mime types file for nginx
[mime_types] [mime_types]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${template_mime_types:location}/${template_mime_types:filename} template = {{ parameter_list['template_mime_types'] }}
rendered = $${html5as:path_mime_types} rendered = ${html5as:path_mime_types}
[downloader]
recipe = slapos.recipe.template:jinja2
template = ${template_downloader:location}/${template_downloader:filename}
rendered = $${html5as:bin_downloader}
mode = 700
context =
section param_html5as html5as
key download_url slap-parameter:download_url
# Render the script launching nginx
[launcher] [launcher]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${template_launcher:location}/${template_launcher:filename} template = {{ parameter_list['template_launcher'] }}
rendered = $${html5as:bin_launcher} rendered = ${html5as:bin_launcher}
mode = 700 mode = 700
context = context =
section param_html5as html5as section param_html5as html5as
# Simple command to put content in the docroot
[downloader]
recipe = plone.recipe.command
command = rm -r ${html5as:docroot}/*; echo "Hello World!" > ${html5as:docroot}/index.html
# Publish nginx address
[publish-connection-information] [publish-connection-information]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:publish
server_url = http://[$${html5as:ip}]:$${html5as:port} server_url = ${html5as:access_url}
[buildout] [buildout]
extends = extends =
# "slapos" stack describes basic things needed for 99.9% of SlapOS Software
# Releases
../../stack/slapos.cfg ../../stack/slapos.cfg
# Extend here component profiles, like openssl, apache, mariadb, curl...
# Or/and extend a stack (lamp, tomcat) that does most of the work for you
# In this example we extend needed components for html5as.
../../component/nginx/buildout.cfg ../../component/nginx/buildout.cfg
../../component/curl/buildout.cfg
../../component/dash/buildout.cfg ../../component/dash/buildout.cfg
../../component/tar/buildout.cfg
parts = parts =
dash # Call installation of slapos.cookbook egg defined in stack/slapos.cfg (needed
tar # in 99,9% of Slapos Software Releases)
curl
nginx
slapos-cookbook slapos-cookbook
template # Call creation of instance.cfg file that will be called for deployment of
template_nginx_conf # instance
template_downloader template-cfg
template_launcher
template_mime_types
instance_html5as
# Download instance.cfg.in (buildout profile used to deployment of instance),
[template] # replace all {{ foo_bar }} parameters by real values
recipe = slapos.recipe.template # The recipe, template and mode are fetched from jijna-template
url = ${:_profile_base_location_}/instance.cfg [template-cfg]
output = ${buildout:directory}/template.cfg recipe = slapos.recipe.template:jinja2
md5sum = 918e0d6513e4d1c92051431d83261dab rendered = ${buildout:directory}/template.cfg
template = ${:_profile_base_location_}/${:filename}
filename = instance.cfg.in
md5sum = 5a6ebc126bcad3cdff1b51fb51f82a35
mode = 0644 mode = 0644
context =
section buildout buildout
key nginx_location nginx:location
key dash_location dash:location
key template_nginx_conf_target template_nginx_conf:target
key template_mime_types_target template_mime_types:target
key template_launcher_target template_launcher:target
key template_instance_html5as_target instance_html5as:target
# Download instance_html5as.cfg.in
[instance_html5as] [instance_html5as]
recipe = slapos.recipe.template recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/instance_html5as.cfg url = ${:_profile_base_location_}/${:_update_hash_filename_}
output = ${buildout:directory}/template_html5as.cfg _update_hash_filename_ = instance_html5as.cfg.in
md5sum = 41cb6178f760238ca276854873ef9364 md5sum = 4a8c98cc5ca141f78f14fb9cec203cb8
mode = 0644 mode = 0644
[template_nginx_conf] [template_nginx_conf]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/nginx_conf.in url = ${:_profile_base_location_}/${:_update_hash_filename_}
_update_hash_filename_ = templates/nginx_conf.in
md5sum = 61dc4c82bf48563228ce4dea6c5c6319 md5sum = 61dc4c82bf48563228ce4dea6c5c6319
filename = nginx_conf.in
mode = 0644 mode = 0644
location = ${buildout:parts-directory}/${:_buildout_section_name_}
[template_launcher] [template_launcher]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/launcher.in url = ${:_profile_base_location_}/${:_update_hash_filename_}
md5sum = acf5bb55ceac2e826259d28ed5c1de3a _update_hash_filename_ = templates/launcher.in
filename = launcher.in md5sum = 8d4d3152f5125f73d0c3f3ea1c3699dd
mode = 0644
location = ${buildout:parts-directory}/${:_buildout_section_name_}
[template_downloader]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/downloader.in
md5sum = 9779e2db6c73d282f802b3407b390ede
filename = downloader.in
mode = 0644 mode = 0644
location = ${buildout:parts-directory}/${:_buildout_section_name_}
[template_mime_types] [template_mime_types]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/templates/mime_types.in url = ${:_profile_base_location_}/${:_update_hash_filename_}
_update_hash_filename_ = templates/mime_types.in
md5sum = 4ef94a7b458d885cd79ba0b930a5727e md5sum = 4ef94a7b458d885cd79ba0b930a5727e
filename = mime_types.in
mode = 0644 mode = 0644
location = ${buildout:parts-directory}/${:_buildout_section_name_}
# Pin versions of eggs used that are not already pinned by stack/slapos.cfg
[versions] [versions]
async = 0.6.1
gitdb = 0.5.4
pycrypto = 2.6
rdiff-backup = 1.0.5+SlapOSPatched001
slapos.recipe.template = 4.4 slapos.recipe.template = 4.4
smmap = 0.8.2
plone.recipe.command = 1.1
#! {{ param_html5as['path_shell'] }}
# BEWARE: This file is operated by slapgrid
# BEWARE: It will be overwritten automatically
# Remove exsistant website
rm -r {{ param_html5as['docroot'] }}/*
# Download and extract website tarball into docroot directory
exec {{ param_html5as['path_curl'] }} -ks {{ download_url }} | {{ param_html5as['path_tar'] }} -z -x -C {{ param_html5as['docroot'] }}
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# BEWARE: It will be overwritten automatically # BEWARE: It will be overwritten automatically
# Run nginx # Run nginx
exec {{ param_html5as['bin_nginx'] }} -c {{ param_html5as['path_nginx_conf'] }} exec {{ param_html5as['path_nginx'] }} -c {{ param_html5as['path_nginx_conf'] }}
...@@ -47,4 +47,3 @@ md5sum = 8cde04bfd0c0e9bd56744b988275cfd8 ...@@ -47,4 +47,3 @@ md5sum = 8cde04bfd0c0e9bd56744b988275cfd8
PyRSS2Gen = 1.1 PyRSS2Gen = 1.1
cns.recipe.symlink = 0.2.3 cns.recipe.symlink = 0.2.3
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 4.4
...@@ -50,5 +50,4 @@ mode = 0644 ...@@ -50,5 +50,4 @@ mode = 0644
# but '1.3.4nxd2-SlapOSPatched001'. # but '1.3.4nxd2-SlapOSPatched001'.
gunicorn = 19.1.1 gunicorn = 19.1.1
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 2.4.3
inotifyx = 0.2.2 inotifyx = 0.2.2
...@@ -118,7 +118,6 @@ output = ${buildout:directory}/runTestSuite.in ...@@ -118,7 +118,6 @@ output = ${buildout:directory}/runTestSuite.in
[versions] [versions]
slapos.recipe.template = 4.4
selenium = 3.14.1 selenium = 3.14.1
urllib3 = 1.24 urllib3 = 1.24
certifi = 2018.10.15 certifi = 2018.10.15
...@@ -75,7 +75,7 @@ class ERP5Kernel(Kernel): ...@@ -75,7 +75,7 @@ class ERP5Kernel(Kernel):
self.title = None self.title = None
# Allowed HTTP request code list for making request to erp5 from Kernel # Allowed HTTP request code list for making request to erp5 from Kernel
# This list should be to used check status_code before making requests to erp5 # This list should be to used check status_code before making requests to erp5
self.allowed_HTTP_request_code_list = range(500, 511) self.allowed_HTTP_request_code_list = list(range(500, 511))
# Append request code 200 in the allowed HTTP status code list # Append request code 200 in the allowed HTTP status code list
self.allowed_HTTP_request_code_list.append(200) self.allowed_HTTP_request_code_list.append(200)
......
...@@ -13,21 +13,21 @@ ...@@ -13,21 +13,21 @@
# section inheritance (< = ...) are NOT supported (but you should really # section inheritance (< = ...) are NOT supported (but you should really
# not need these here). # not need these here).
[instance-jupyter-notebook] [instance]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = 1d5fe6cc4e48672ae7be1c223794a932 md5sum = f33fc954eba47b5ddbebc72c453304e3
[instance-jupyter]
filename = instance-jupyter.cfg.in
md5sum = 9340498841caa5771f40f8c9e561eacd
[jupyter-notebook-config] [jupyter-notebook-config]
filename = jupyter_notebook_config.py.jinja filename = jupyter_notebook_config.py.jinja
md5sum = 720e90a829c63371696bc3009917a743 md5sum = 6e01da7d35c1d65d4a450b0f011b296d
[jupyter-set-password]
filename = jupyter_set_password.cgi.jinja
md5sum = b8d31441780b524a7e52d1710dd78385
[erp5-kernel] [erp5-kernel]
filename = ERP5kernel.py filename = ERP5kernel.py
md5sum = 7d5309fe79afbcb455c0d8181b42e56c md5sum = da04b99b70b2e327c9e9b4cdd056098e
[kernel-json] [kernel-json]
filename = kernel.json.jinja filename = kernel.json.jinja
...@@ -35,4 +35,4 @@ md5sum = 33547be93a67530165e079dc3ecfdac3 ...@@ -35,4 +35,4 @@ md5sum = 33547be93a67530165e079dc3ecfdac3
[custom-js] [custom-js]
filename = custom.js filename = custom.js
md5sum = 40d938bb09261c65421a7725b40f87dc md5sum = 295aeee765bc4d09bf0686021f32f72c
...@@ -81,41 +81,51 @@ ...@@ -81,41 +81,51 @@
* @static * @static
*/ */
$([Jupyter.events]).on('notebook_loaded.Notebook', function(){ function prependERP5Help() {
var kernelname = Jupyter.notebook.kernel_selector.current_selection; var kernelname = Jupyter.notebook.kernel_selector.current_selection;
var display_text="<div class='output_subarea output_text output_result'>\ var display_text = "<div class='output_subarea output_text output_result'>\
<pre>Follow these steps to customize your notebook with ERP5 kernel :-</br>\ <pre>Follow these steps to customize your notebook with ERP5 kernel :-</br>\
1. Make sure you have 'erp5_data_notebook' business template installed in your ERP5</br>\ 1. Make sure you have 'erp5_data_notebook' business template installed in your ERP5</br>\
2. <b>%erp5_user &lt;your_erp5_username&gt;</b></br>\ 2. <b>%erp5_url &lt;your_erp5_url&gt;/Base_executeJupyter</b></br>\
3. <b>%erp5_password &lt;your_erp5_password&gt;</b></br>\ 3. <b>%erp5_user &lt;your_erp5_username&gt;</b></br>\
4. <b>%notebook_set_reference &lt;your_notebook_reference&gt;</b></br>\ 4. <b>%erp5_password &lt;your_erp5_password&gt;</b></br>\
It would be better to set the reference to match with erp5 reference pattern.</br>\ 5. <b>%notebook_set_reference &lt;your_notebook_reference&gt;</b></br>\
5. As soon as you see 'Please Proceed' message you can now access your erp5 using notebook.</br>\ It would be better to set the reference to match with erp5 reference pattern.</br>\
<p><u>OTHER USEFUL MAGICS</u> -</br>\ 6. As soon as you see 'Please Proceed' message you can now access your erp5 using notebook.</br>\
<b>%my_notebooks</b> -This is used to display all the notebooks created by the specific user.</br>\ <p><u>OTHER USEFUL MAGICS</u> -</br>\
<b>%notebook_set_title</b> -This sets the title of the current notebook.</br>\ <b>%my_notebooks</b> -This is used to display all the notebooks created by the specific user.</br>\
NOTE: Do not dynamically alter imported module objects as they are not being saved in DB, </br>\ <b>%notebook_set_title</b> -This sets the title of the current notebook.</br>\
so changes to them would be disregarded and would throw an error.</br>\ NOTE: Do not dynamically alter imported module objects as they are not being saved in DB, </br>\
<p><u>About classes, functions and global state on modules:</u></p>\ so changes to them would be disregarded and would throw an error.</br>\
Your code is going to be executed by ERP5, which can have many nodes </br>\ <p><u>About classes, functions and global state on modules:</u></p>\
and there is no guarantee that your code is always going to be executed by the same server.</br>\ Your code is going to be executed by ERP5, which can have many nodes </br>\
This means that objects which cannot be stored in the ZODB, like functions, classes and modules </br>\ and there is no guarantee that your code is always going to be executed by the same server.</br>\
won't be available across nodes. To solve this issue, you need to use a special object </br>\ This means that objects which cannot be stored in the ZODB, like functions, classes and modules </br>\
called 'environment' to store your global setup. This object was designed to hold global </br>\ won't be available across nodes. To solve this issue, you need to use a special object </br>\
state and restore it for each code cell. Example:</br></br>\ called 'environment' to store your global setup. This object was designed to hold global </br>\
<b>def my_setup():</br>\ state and restore it for each code cell. Example:</br></br>\
# import modules, define functions and classes</br>\ <b>def my_setup():</br>\
# and set global state on modules</br>\ # import modules, define functions and classes</br>\
# return dict of variables to be available in code cells</br>\ # and set global state on modules</br>\
{'my_var': 1}</br>\ # return dict of variables to be available in code cells</br>\
environment.define(my_setup, 'my custom setup')</b></br></br>\ {'my_var': 1}</br>\
After you execute this cell, the <b>my_setup</b> function will run before each of the</br>\ environment.define(my_setup, 'my custom setup')</b></br></br>\
following cells and the <b>my_var</b> variable will be created and set to 1.</br></br>\ After you execute this cell, the <b>my_setup</b> function will run before each of the</br>\
<b>WARNING:</b> it is not recommended to have too many setup functions in the environment, </br>\ following cells and the <b>my_var</b> variable will be created and set to 1.</br></br>\
because they will be executed in every code cell and can cause a substantial slow down.\ <b>WARNING:</b> it is not recommended to have too many setup functions in the environment, </br>\
</pre></div>"; because they will be executed in every code cell and can cause a substantial slow down.\
if (kernelname=="erp5"){ </pre></div>";
$('div#notebook-container').prepend(display_text);
} if (kernelname=="erp5"){
$('div#notebook-container').prepend(display_text);
}
}
define([
'base/js/namespace',
'base/js/promises'
], function(Jupyter, promises) {
promises.notebook_loaded.then(function() {
prependERP5Help();
}); });
});
\ No newline at end of file
{% set additional_frontend = slapparameter_dict.get('frontend-additional-instance-guid') %}
[buildout]
parts =
instance
publish-connection-parameter
jupyter-notebook-config
erp5-kernel
kernel-json
custom-js
frontend-promise
{% if additional_frontend %}
frontend-additional-promise
{% endif %}
monitor-base
extends =
{{ monitor_template_rendered }}/template-monitor.cfg
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slapconfiguration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
# ERP5 URL to use in Jupyter by default
# default value is empty - which means no default ERP5 URL
configuration.erp5-url =
[instance-parameter]
port = 8888
host = ${slapconfiguration:ipv6-random}
cert_file = ${generate-certificate:cert_file}
key_file = ${generate-certificate:key_file}
logfile = ${directory:log}/jupyter_notebook.log
notebook_dir = ${directory:notebook_dir}
[slap-parameter]
frontend-software-type = RootSoftwareInstance
frontend-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
frontend-instance-guid =
frontend-instance-name = Jupyter Frontend
frontend-additional-software-type = RootSoftwareInstance
frontend-additional-software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
frontend-additional-instance-guid =
frontend-additional-instance-name = Jupyter Frontend Additional
[dynamic-jinja2-template-base]
recipe = slapos.recipe.template:jinja2
mode = 0644
[generate-certificate]
; TODO: there is a slapos recipe to generate certificates. Use it instead
recipe = plone.recipe.command
command =
if [ ! -e ${instance-parameter:key_file} ]
then
{{ openssl_output }} req -x509 -nodes -days 3650 \
-subj "/C=AA/ST=X/L=X/O=Dis/CN=${instance-parameter:host}" \
-newkey rsa:1024 -keyout ${instance-parameter:key_file} \
-out ${instance-parameter:cert_file}
fi
update-command = ${:command}
cert_file = ${directory:etc}/jupyter_cert.crt
key_file = ${directory:etc}/jupyter_cert.key
[instance]
recipe = slapos.cookbook:wrapper
command-line =
{{ bin_directory }}/jupyter-lab
--no-browser
--ip=${instance-parameter:host}
--port=${instance-parameter:port}
--port-retries=0
--certfile=${instance-parameter:cert_file}
--keyfile=${instance-parameter:key_file}
--notebook-dir=${instance-parameter:notebook_dir}
--log-level="DEBUG"
wrapper-path = ${directory:service}/jupyter-lab
environment =
JUPYTER_PATH=${directory:jupyter_dir}
JUPYTER_CONFIG_DIR=${directory:jupyter_config_dir}
JUPYTER_RUNTIME_DIR=${directory:jupyter_runtime_dir}
LANG=C.UTF-8
[jupyter-password]
recipe = slapos.cookbook:generate.password
bytes = 10
[jupyter-notebook-config]
<= dynamic-jinja2-template-base
template = {{ jupyter_config_location }}/{{ jupyter_config_filename }}
rendered = ${directory:jupyter_config_dir}/jupyter_notebook_config.py
mode = 0744
context =
key password jupyter-password:passwd
raw gcc_location {{ gcc_location }}
raw cythonplus_repository {{ cythonplus_repository }}
[directory]
recipe = slapos.cookbook:mkdirectory
home = ${buildout:directory}
etc = ${:home}/etc
var = ${:home}/var
script = ${:etc}/run/
service = ${:etc}/service
log = ${:var}/log
notebook_dir = ${:var}/notebooks
# Add folders to explicitly define jupyter directory
jupyter_dir = ${:home}/jupyter
jupyter_config_dir = ${:jupyter_dir}/etc
jupyter_kernel_dir = ${:jupyter_dir}/kernels
jupyter_runtime_dir = ${:jupyter_dir}/runtime
jupyter_custom_dir = ${:jupyter_config_dir}/custom
jupyter_nbextensions_dir = ${:jupyter_dir}/nbextensions
erp5_kernel_dir = ${:jupyter_kernel_dir}/ERP5
[request-slave-frontend-base]
recipe = slapos.cookbook:requestoptional
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
slave = true
config-type = notebook
config-url = https://[${instance-parameter:host}]:${instance-parameter:port}
return = secure_access
[request-slave-frontend]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-software-url}
software-type = ${slap-parameter:frontend-software-type}
name = ${slap-parameter:frontend-instance-name}
sla-instance_guid = ${slap-parameter:frontend-instance-guid}
[frontend-promise]
<= monitor-promise-base
module = check_url_available
name = frontend_promise.py
config-url = ${publish-connection-parameter:url}
{% if additional_frontend %}
[request-slave-frontend-additional]
<= request-slave-frontend-base
software-url = ${slap-parameter:frontend-additional-software-url}
software-type = ${slap-parameter:frontend-additional-software-type}
name = ${slap-parameter:frontend-additional-instance-name}
sla-instance_guid = ${slap-parameter:frontend-additional-instance-guid}
[frontend-additional-promise]
<= monitor-promise-base
module = check_url_available
name = frontend_additional_promise.py
config-url = ${publish-connection-parameter:url-additional}
{% endif %}
[monitor-instance-parameter]
monitor-base-url = ${monitor-frontend-promise:url}
# In case you're using a developer instance you should edit these in:
# monitor-base-url = ${monitor-httpd-conf-parameter:url}
# cors-domains = softinstXXXXX.host.vifib.net (or equivalent)
# interface-url = https://softinstXXXXX.host.vifib.net/erp5/web_site_module/monitoring_rjs_unsafe
instance-configuration =
raw jupyter-password ${jupyter-password:passwd}
[publish-connection-parameter]
recipe = slapos.cookbook:publish.serialised
jupyter-classic-url = ${request-slave-frontend:connection-secure_access}/tree
url = ${:jupyter-classic-url}
jupyterlab-url = ${request-slave-frontend:connection-secure_access}/lab
{% if additional_frontend %}
jupyter-classic-url-additional = ${request-slave-frontend-additional:connection-secure_access}/tree
url-additional = ${:jupyter-classic-url-additional}
jupyterlab-url-additional = ${request-slave-frontend-additional:connection-secure_access}/lab
{% endif %}
password = ${jupyter-password:passwd}
[erp5-kernel]
recipe = slapos.cookbook:symbolic.link
link-binary = {{ erp5_kernel_location }}/{{ erp5_kernel_filename }}
target-directory = ${directory:erp5_kernel_dir}
[kernel-json]
<= dynamic-jinja2-template-base
template = {{ kernel_json_location }}/{{ kernel_json_filename }}
rendered = ${directory:erp5_kernel_dir}/kernel.json
# Use python2.7 executable bin file for kernel config
context =
raw python_executable {{ python_executable }}
raw kernel_dir ${erp5-kernel:target-directory}/{{ erp5_kernel_filename }}
key erp5_url slapconfiguration:configuration.erp5-url
raw display_name ERP5
raw language_name python
[custom-js]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:jupyter_custom_dir}
link-binary = {{ custom_js_location }}/custom.js
[buildout] [buildout]
parts = parts =
instance switch_softwaretype
jupyter_notebook
read-knowledge0
publish-connection-parameter
jupyter-notebook-config
erp5-kernel
kernel-json
custom-js
monitor-base
extends =
{{ monitor_template_rendered }}/template-monitor.cfg
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
eggs-directory = {{ eggs_directory }} [switch_softwaretype]
develop-eggs-directory = {{ develop_eggs_directory }} recipe = slapos.cookbook:switch-softwaretype
offline = true default = $${:jupyter}
jupyter = instance-jupyter:rendered
RootSoftwareInstance = $${:default}
[slapconfiguration] [slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id} computer = $${slap-connection:computer-id}
partition = ${slap-connection:partition-id} partition = $${slap-connection:partition-id}
url = ${slap-connection:server-url} url = $${slap-connection:server-url}
key = ${slap-connection:key-file} key = $${slap-connection:key-file}
cert = ${slap-connection:cert-file} cert = $${slap-connection:cert-file}
# ERP5 URL to use in Jupyter by default [instance-jupyter]
# default value is empty - which means no default ERP5 URL
configuration.erp5-url =
[instance-parameter]
port = 8888
host = ${slapconfiguration:ipv6-random}
cert_file = ${generate-certificate:cert_file}
key_file = ${generate-certificate:key_file}
logfile = ${directory:log}/jupyter_notebook.log
notebook_dir = ${directory:notebook_dir}
[dynamic-jinja2-template-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
filename = instance-jupyter.cfg.in
template = ${instance:_profile_base_location_}/$${:filename}
rendered = $${buildout:directory}/template.cfg
mode = 0644 mode = 0644
[generate-certificate]
; TODO: there is a slapos recipe to generate certificates. Use it instead
recipe = plone.recipe.command
command =
if [ ! -e ${instance-parameter:key_file} ]
then
{{ openssl_output }} req -x509 -nodes -days 3650 \
-subj "/C=AA/ST=X/L=X/O=Dis/CN=${instance-parameter:host}" \
-newkey rsa:1024 -keyout ${instance-parameter:key_file} \
-out ${instance-parameter:cert_file}
fi
update-command = ${:command}
cert_file = ${directory:etc}/jupyter_cert.crt
key_file = ${directory:etc}/jupyter_cert.key
[instance]
recipe = slapos.cookbook:wrapper
command-line =
{{ bin_directory }}/jupyter-lab
--no-browser
--ip=${instance-parameter:host}
--port=${instance-parameter:port}
--port-retries=0
--certfile=${instance-parameter:cert_file}
--keyfile=${instance-parameter:key_file}
--notebook-dir=${instance-parameter:notebook_dir}
--log-level="DEBUG"
wrapper-path = ${directory:service}/jupyter-lab
environment =
JUPYTER_PATH=${directory:jupyter_dir}
JUPYTER_CONFIG_DIR=${directory:jupyter_config_dir}
JUPYTER_RUNTIME_DIR=${directory:jupyter_runtime_dir}
LANG=C.UTF-8
[jupyter-notebook-config]
<= dynamic-jinja2-template-base
template = {{ jupyter_config_location }}/{{ jupyter_config_filename }}
rendered = ${directory:jupyter_config_dir}/jupyter_notebook_config.py
mode = 0744
context =
raw config_cfg ${buildout:directory}/knowledge0.cfg
[directory]
recipe = slapos.cookbook:mkdirectory
home = ${buildout:directory}
etc = ${:home}/etc
var = ${:home}/var
script = ${:etc}/run/
service = ${:etc}/service
log = ${:var}/log
notebook_dir = ${:var}/notebooks
# Add folders to explicitly define jupyter directory
jupyter_dir = ${:home}/jupyter
jupyter_config_dir = ${:jupyter_dir}/etc
jupyter_kernel_dir = ${:jupyter_dir}/kernels
jupyter_runtime_dir = ${:jupyter_dir}/runtime
jupyter_custom_dir = ${:jupyter_config_dir}/custom
jupyter_nbextensions_dir = ${:jupyter_dir}/nbextensions
erp5_kernel_dir = ${:jupyter_kernel_dir}/ERP5
[jupyter_notebook]
# This part is called like this because knowledge0.write uses the part name for
# the section name in the config file.
recipe = slapos.cookbook:zero-knowledge.write
password =
filename = knowledge0.cfg
[read-knowledge0]
recipe = slapos.cookbook:zero-knowledge.read
filename = knowledge0.cfg
password =
[monitor-instance-parameter]
monitor-base-url = ${monitor-frontend-promise:url}
# In case you're using a developer instance you should edit these in:
# monitor-base-url = ${monitor-httpd-conf-parameter:url}
# cors-domains = softinstXXXXX.host.vifib.net (or equivalent)
# interface-url = https://softinstXXXXX.host.vifib.net/erp5/web_site_module/monitoring_rjs_unsafe
instance-configuration =
raw jupyter-password ${read-knowledge0:password}
[publish-connection-parameter]
recipe = slapos.cookbook:publish.serialised
jupyter-classic-url = https://[${instance-parameter:host}]:${instance-parameter:port}/tree
url = ${:jupyter-classic-url}
jupyterlab-url = https://[${instance-parameter:host}]:${instance-parameter:port}/lab
[erp5-kernel]
recipe = slapos.cookbook:symbolic.link
link-binary = {{ erp5_kernel_location }}/{{ erp5_kernel_filename }}
target-directory = ${directory:erp5_kernel_dir}
[kernel-json]
<= dynamic-jinja2-template-base
template = {{ kernel_json_location }}/{{ kernel_json_filename }}
rendered = ${directory:erp5_kernel_dir}/kernel.json
# Use python2.7 executable bin file for kernel config
context = context =
raw python_executable {{ python_executable }} key slapparameter_dict slap-configuration:configuration
raw kernel_dir ${erp5-kernel:target-directory}/{{ erp5_kernel_filename }} raw bin_directory ${buildout:bin-directory}
key erp5_url slapconfiguration:configuration.erp5-url raw develop_eggs_directory ${buildout:develop-eggs-directory}
raw display_name ERP5 raw eggs_directory ${buildout:eggs-directory}
raw language_name python raw openssl_output ${openssl-output:openssl}
raw python_executable ${jupyter:python_executable}
[custom-js] raw jupyter_config_location ${jupyter-notebook-config:location}
recipe = slapos.cookbook:symbolic.link raw jupyter_config_filename ${jupyter-notebook-config:filename}
target-directory = ${directory:jupyter_custom_dir} raw erp5_kernel_location ${erp5-kernel:location}
link-binary = {{ custom_js_location }}/custom.js raw erp5_kernel_filename ${erp5-kernel:filename}
raw kernel_json_location ${kernel-json:location}
raw kernel_json_filename ${kernel-json:filename}
raw custom_js_location ${custom-js:location}
raw custom_js_filename ${custom-js:filename}
raw monitor_template_rendered ${buildout:directory}
raw cythonplus_repository ${cythonplus-repository:location}
raw gcc_location ${gcc:prefix}
...@@ -2,37 +2,13 @@ ...@@ -2,37 +2,13 @@
This script initializes Jupyter's configuration such as passwords and other This script initializes Jupyter's configuration such as passwords and other
things. It is run by IPython hence why it can use functions like get_config(). things. It is run by IPython hence why it can use functions like get_config().
''' '''
import ConfigParser import configparser
import random
from notebook.auth import passwd from notebook.auth import passwd
import os import os
def random_password(length = 10):
result = ""
for i in range(0, length):
result = result + chr(random.randint(0, 25) + ord('a'))
return result
knowledge_0 = '{{ config_cfg }}'
if not os.path.exists(knowledge_0):
print "Your software does <b>not</b> embed 0-knowledge. \
This interface is useless in this case</body></html>"
exit(0)
c = get_config() c = get_config()
parser = ConfigParser.ConfigParser() c.NotebookApp.password = passwd("{{ password }}")
parser.read(knowledge_0)
if not parser.has_section("jupyter_notebook"):
parser.add_section("jupyter_notebook")
if not parser.has_option("jupyter_notebook", "password") or \
parser.get("jupyter_notebook", "password") == "":
parser.set("jupyter_notebook", "password", random_password())
c.NotebookApp.password = passwd(parser.get("jupyter_notebook", "password"))
with open(knowledge_0, 'w') as file: os.environ['PATH'] = "{{ gcc_location }}/bin" + os.pathsep + os.environ['PATH']
parser.write(file) os.environ['PYTHONPATH'] = "{{ cythonplus_repository }}" + os.pathsep + os.environ['PYTHONPATH']
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
extends = extends =
buildout.hash.cfg buildout.hash.cfg
../../stack/slapos.cfg ../../stack/slapos.cfg
../../component/cythonplus/buildout.cfg
../../component/openssl/buildout.cfg ../../component/openssl/buildout.cfg
../../component/jupyter/buildout.cfg ../../component/jupyter/buildout.cfg
../../stack/monitor/buildout.cfg ../../stack/monitor/buildout.cfg
...@@ -9,7 +10,10 @@ parts += ...@@ -9,7 +10,10 @@ parts +=
slapos-cookbook slapos-cookbook
jupyter jupyter
jupyter-notebook-initialized-scripts jupyter-notebook-initialized-scripts
instance-jupyter-notebook instance
[python]
part = python3
[gcc] [gcc]
# Always build GCC for Fortran (see openblas). # Always build GCC for Fortran (see openblas).
...@@ -27,9 +31,6 @@ mode = 0644 ...@@ -27,9 +31,6 @@ mode = 0644
[jupyter-notebook-config] [jupyter-notebook-config]
<= download-file-base <= download-file-base
[jupyter-set-password]
<= download-file-base
[erp5-kernel] [erp5-kernel]
<= download-file-base <= download-file-base
...@@ -39,64 +40,55 @@ mode = 0644 ...@@ -39,64 +40,55 @@ mode = 0644
[custom-js] [custom-js]
<= download-file-base <= download-file-base
[instance-jupyter-notebook] [instance]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template
template = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/${:filename}
rendered = ${buildout:directory}/template.cfg output = ${buildout:directory}/template.cfg
mode = 0644 mode = 0644
context =
key bin_directory buildout:bin-directory
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key openssl_output openssl-output:openssl
key python_executable jupyter:python_executable
key jupyter_config_location jupyter-notebook-config:location
key jupyter_config_filename jupyter-notebook-config:filename
key jupyter_set_password_location jupyter-set-password:location
key jupyter_set_password_filename jupyter-set-password:filename
key erp5_kernel_location erp5-kernel:location
key erp5_kernel_filename erp5-kernel:filename
key kernel_json_location kernel-json:location
key kernel_json_filename kernel-json:filename
key custom_js_location custom-js:location
key custom_js_filename custom-js:filename
key monitor_template_rendered buildout:directory
[versions] [versions]
Pygments = 2.2.0 Pygments = 2.7.2
astor = 0.5 astor = 0.5
async-generator = 1.10
backports-abc = 0.5 backports-abc = 0.5
backports.functools-lru-cache = 1.6.1 backports.functools-lru-cache = 1.6.1
backports.shutil-get-terminal-size = 1.0.0 backports.shutil-get-terminal-size = 1.0.0
bleach = 3.2.1
cycler = 0.10.0 cycler = 0.10.0
ipykernel = 4.5.2 defusedxml = 0.6.0
entrypoints = 0.3
ipykernel = 5.3.4
ipython = 5.3.0 ipython = 5.3.0
ipython-genutils = 0.1.0 ipython-genutils = 0.1.0
ipywidgets = 6.0.0 ipywidgets = 6.0.0
jupyter-client = 5.0.0 jupyter-client = 6.1.7
jupyter-core = 4.3.0 jupyter-core = 4.7.0
jupyterlab = 0.26.3 jupyterlab = 0.26.3
jupyterlab-launcher = 0.3.1 jupyterlab-launcher = 0.3.1
jupyterlab-pygments = 0.1.2
matplotlib = 2.1.2 matplotlib = 2.1.2
mistune = 0.7.3 mistune = 0.8.4
nbformat = 4.3.0 nest-asyncio = 1.4.3
notebook = 4.4.1 nbclient = 0.5.1
pandas = 0.19.2 nbformat = 5.0.8
notebook = 6.1.5
numpy = 1.14.6
pandas = 0.25.3
pandocfilters = 1.4.3
plone.recipe.command = 1.1 plone.recipe.command = 1.1
prompt-toolkit = 1.0.13 prompt-toolkit = 1.0.13
ptyprocess = 0.5.1 ptyprocess = 0.5.1
pyzmq = 16.0.2 pyzmq = 20.0.0
scikit-learn = 0.18.1 scikit-learn = 0.20.4
seaborn = 0.7.1 seaborn = 0.7.1
simplegeneric = 0.8.1 simplegeneric = 0.8.1
slapos.recipe.template = 4.4 statsmodels = 0.11.1
statsmodels = 0.8.0 testpath = 0.4.4
terminado = 0.6 terminado = 0.9.1
tornado = 4.4.2 tornado = 6.1
traitlets = 4.3.2 traitlets = 5.0.5
webencodings = 0.5.1
widgetsnbextension = 2.0.0 widgetsnbextension = 2.0.0
# numpy >= 1.13.1 is required for numpy.core.multiarray
numpy = 1.13.1
# Required by: # Required by:
...@@ -104,41 +96,55 @@ numpy = 1.13.1 ...@@ -104,41 +96,55 @@ numpy = 1.13.1
certifi = 2020.6.20 certifi = 2020.6.20
# Required by: # Required by:
# notebook==4.3.2 # notebook==6.1.5
# nbconvert 4.2.0 depends on entrypoints egg that is not available as tar/zip source. Send2Trash = 1.5.0
nbconvert = 4.1.0
# Required by:
# notebook==6.1.5
argon2-cffi = 20.1.0
# Required by:
# notebook==6.1.5
nbconvert = 6.0.7
# Required by: # Required by:
# ipython==5.3.0 # ipython==5.3.0
pathlib2 = 2.2.1 pathlib2 = 2.2.1
# Required by: # Required by:
# statsmodels==0.8.0 # statsmodels==0.11.1
patsy = 0.4.1 patsy = 0.5.1
# Required by: # Required by:
# ipython==5.3.0 # ipython==5.3.0
pexpect = 4.2.1 pexpect = 4.8.0
# Required by: # Required by:
# ipython==5.3.0 # ipython==5.3.0
pickleshare = 0.7.4 pickleshare = 0.7.4
# Required by: # Required by:
# matplotlib==2.1.2 # notebook==6.1.5
# pandas==0.19.2 prometheus-client = 0.9.0
python-dateutil = 2.6.0
# Required by:
# statsmodels==0.11.1
python-dateutil = 2.8.1
# Required by: # Required by:
# pathlib2==2.2.1 # pathlib2==2.2.1
scandir = 1.5 scandir = 1.5
# Required by: # Required by:
# statsmodels==0.8.0 # statsmodels==0.11.1
scipy = 0.19.0 pytz = 2020.4
# Required by: # Required by:
# tornado==4.4.2 # statsmodels==0.11.1
scipy = 1.0.1
# Required by:
# tornado==6.1
singledispatch = 3.4.0.3 singledispatch = 3.4.0.3
# Required by: # Required by:
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
############################################################################## ##############################################################################
import httplib import http.client
import json import json
import os import os
import requests import requests
...@@ -48,10 +48,14 @@ class TestJupyter(InstanceTestCase): ...@@ -48,10 +48,14 @@ class TestJupyter(InstanceTestCase):
except Exception as e: except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e)) self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
self.assertTrue('password' in connection_dict)
password = connection_dict['password']
self.assertEqual( self.assertEqual(
{ {
'jupyter-classic-url': 'https://[%s]:8888/tree' % (self._ipv6_address, ), 'jupyter-classic-url': 'https://[%s]:8888/tree' % (self._ipv6_address, ),
'jupyterlab-url': 'https://[%s]:8888/lab' % (self._ipv6_address, ), 'jupyterlab-url': 'https://[%s]:8888/lab' % (self._ipv6_address, ),
'password': '%s' % (password, ),
'url': 'https://[%s]:8888/tree' % (self._ipv6_address, ) 'url': 'https://[%s]:8888/tree' % (self._ipv6_address, )
}, },
connection_dict connection_dict
...@@ -60,7 +64,7 @@ class TestJupyter(InstanceTestCase): ...@@ -60,7 +64,7 @@ class TestJupyter(InstanceTestCase):
result = requests.get( result = requests.get(
connection_dict['url'], verify=False, allow_redirects=False) connection_dict['url'], verify=False, allow_redirects=False)
self.assertEqual( self.assertEqual(
[httplib.FOUND, True, '/login?next=%2Ftree'], [http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']] [result.status_code, result.is_redirect, result.headers['Location']]
) )
...@@ -68,7 +72,7 @@ class TestJupyter(InstanceTestCase): ...@@ -68,7 +72,7 @@ class TestJupyter(InstanceTestCase):
connection_dict['jupyter-classic-url'], connection_dict['jupyter-classic-url'],
verify=False, allow_redirects=False) verify=False, allow_redirects=False)
self.assertEqual( self.assertEqual(
[httplib.FOUND, True, '/login?next=%2Ftree'], [http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']] [result.status_code, result.is_redirect, result.headers['Location']]
) )
...@@ -76,6 +80,92 @@ class TestJupyter(InstanceTestCase): ...@@ -76,6 +80,92 @@ class TestJupyter(InstanceTestCase):
connection_dict['jupyterlab-url'], connection_dict['jupyterlab-url'],
verify=False, allow_redirects=False) verify=False, allow_redirects=False)
self.assertEqual( self.assertEqual(
[httplib.FOUND, True, '/login?next=%2Flab'], [http.client.FOUND, True, '/login?next=%2Flab'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
class TestJupyterPassword(InstanceTestCase):
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertTrue('_' in parameter_dict)
try:
connection_dict = json.loads(parameter_dict['_'])
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
url = connection_dict['url']
with requests.Session() as s:
resp = s.get(url, verify=False)
result = s.post(
resp.url,
verify = False,
data={"_xsrf": s.cookies["_xsrf"], "password": connection_dict['password']}
)
self.assertEqual(
[http.client.OK, url],
[result.status_code, result.url]
)
class TestJupyterAdditional(InstanceTestCase):
@classmethod
def getInstanceParameterDict(cls):
return {
'frontend-additional-instance-guid': 'SOMETHING'
}
def test(self):
parameter_dict = self.computer_partition.getConnectionParameterDict()
self.assertTrue('_' in parameter_dict)
try:
connection_dict = json.loads(parameter_dict['_'])
except Exception as e:
self.fail("Can't parse json in %s, error %s" % (parameter_dict['_'], e))
result = requests.get(
connection_dict['url'], verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
result = requests.get(
connection_dict['jupyter-classic-url'],
verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
result = requests.get(
connection_dict['jupyterlab-url'],
verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Flab'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
result = requests.get(
connection_dict['url-additional'], verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
result = requests.get(
connection_dict['jupyter-classic-url-additional'],
verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Ftree'],
[result.status_code, result.is_redirect, result.headers['Location']]
)
result = requests.get(
connection_dict['jupyterlab-url-additional'],
verify=False, allow_redirects=False)
self.assertEqual(
[http.client.FOUND, True, '/login?next=%2Flab'],
[result.status_code, result.is_redirect, result.headers['Location']] [result.status_code, result.is_redirect, result.headers['Location']]
) )
...@@ -205,5 +205,4 @@ websockify = 0.9.0 ...@@ -205,5 +205,4 @@ websockify = 0.9.0
collective.recipe.environment = 0.2.0 collective.recipe.environment = 0.2.0
gitdb = 0.6.4 gitdb = 0.6.4
pycurl = 7.43.0 pycurl = 7.43.0
slapos.recipe.template = 4.4
smmap = 0.9.0 smmap = 0.9.0
...@@ -24,6 +24,3 @@ md5sum = 0a5e780dcf7d9ffe73f1ed789f863a57 ...@@ -24,6 +24,3 @@ md5sum = 0a5e780dcf7d9ffe73f1ed789f863a57
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/instance.cfg output = ${buildout:directory}/instance.cfg
[versions]
slapos.recipe.template = 4.4
...@@ -76,7 +76,6 @@ eggs += ...@@ -76,7 +76,6 @@ eggs +=
scripts = scripts =
[versions] [versions]
slapos.recipe.template = 4.4
surykatka = 0.5.0 surykatka = 0.5.0
......
...@@ -45,4 +45,3 @@ mode = 0644 ...@@ -45,4 +45,3 @@ mode = 0644
[versions] [versions]
rdiff-backup = 1.0.5+SlapOSPatched001 rdiff-backup = 1.0.5+SlapOSPatched001
slapos.recipe.template = 2.2
...@@ -67,6 +67,3 @@ dependencies = ...@@ -67,6 +67,3 @@ dependencies =
libexpat libexpat
libaio libaio
boost-lib boost-lib
[versions]
slapos.recipe.template = 4.4
...@@ -146,7 +146,6 @@ persistent = 4.6.4 ...@@ -146,7 +146,6 @@ persistent = 4.6.4
pycrypto = 2.6.1 pycrypto = 2.6.1
pycurl = 7.43.0 pycurl = 7.43.0
setproctitle = 1.1.10 setproctitle = 1.1.10
slapos.recipe.template = 4.4
transaction = 1.7.0 transaction = 1.7.0
zodbpickle = 1.0.4 zodbpickle = 1.0.4
cython-zstd = 0.2 cython-zstd = 0.2
......
...@@ -84,6 +84,3 @@ packages += ...@@ -84,6 +84,3 @@ packages +=
libnetfilter-queue-dev nftables libnetfilter-queue-dev nftables
# extra requirements for this SR # extra requirements for this SR
screen xz-utils screen xz-utils
[versions]
slapos.recipe.template = 4.4
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# list of go git repositories to fetch # list of go git repositories to fetch
[gowork.goinstall] [gowork.goinstall]
depends_gitfetch = depends_gitfetch =
${go_crawshaw.io_sqlite:recipe}
${go_github.com_DataDog_czlib:recipe} ${go_github.com_DataDog_czlib:recipe}
${go_github.com_cznic_strutil:recipe} ${go_github.com_cznic_strutil:recipe}
${go_github.com_davecgh_go-spew:recipe} ${go_github.com_davecgh_go-spew:recipe}
...@@ -37,6 +38,12 @@ depends_gitfetch = ...@@ -37,6 +38,12 @@ depends_gitfetch =
${go_lab.nexedi.com_kirr_neo:recipe} ${go_lab.nexedi.com_kirr_neo:recipe}
[go_crawshaw.io_sqlite]
<= go-git-package
go.importpath = crawshaw.io/sqlite
repository = https://github.com/crawshaw/sqlite
revision = v0.3.2-7-gc582b9de4f
[go_github.com_DataDog_czlib] [go_github.com_DataDog_czlib]
<= go-git-package <= go-git-package
go.importpath = github.com/DataDog/czlib go.importpath = github.com/DataDog/czlib
...@@ -221,10 +228,10 @@ revision = v2.1.1-97-geeeca48fe7 ...@@ -221,10 +228,10 @@ revision = v2.1.1-97-geeeca48fe7
<= go-git-package <= go-git-package
go.importpath = lab.nexedi.com/kirr/go123 go.importpath = lab.nexedi.com/kirr/go123
repository = https://lab.nexedi.com/kirr/go123.git repository = https://lab.nexedi.com/kirr/go123.git
revision = 316617668e revision = c8d9907ef7
[go_lab.nexedi.com_kirr_neo] [go_lab.nexedi.com_kirr_neo]
<= go-git-package <= go-git-package
go.importpath = lab.nexedi.com/kirr/neo go.importpath = lab.nexedi.com/kirr/neo
repository = https://lab.nexedi.com/kirr/neo.git repository = https://lab.nexedi.com/kirr/neo.git
revision = v1.9-2480-g5ee3c077b3 revision = v1.12-2791-gf3effa6c53
...@@ -34,7 +34,7 @@ parts = ...@@ -34,7 +34,7 @@ parts =
neoppod-develop neoppod-develop
neoppod neoppod
wendelin.core-dev wendelin.core
scripts scripts
# for ZEO scripts (runzeo) # for ZEO scripts (runzeo)
...@@ -107,7 +107,7 @@ template = inline: ...@@ -107,7 +107,7 @@ template = inline:
[neotest-python] [neotest-python]
<= python-interpreter <= python-interpreter
eggs += eggs +=
${wendelin.core-dev:egg} ${wendelin.core:egg}
${neoppod:eggs} ${neoppod:eggs}
# for instance # for instance
plone.recipe.command plone.recipe.command
...@@ -116,7 +116,7 @@ eggs += ...@@ -116,7 +116,7 @@ eggs +=
recipe = zc.recipe.egg:scripts recipe = zc.recipe.egg:scripts
eggs = eggs =
# to install not only wendelin.core modules but also scripts # to install not only wendelin.core modules but also scripts
${wendelin.core-dev:egg} ${wendelin.core:egg}
# wendelin.core: latest not yet released # wendelin.core: latest not yet released
......
...@@ -42,5 +42,4 @@ output = ${buildout:directory}/instance-nginx.cfg.in ...@@ -42,5 +42,4 @@ output = ${buildout:directory}/instance-nginx.cfg.in
mode = 0644 mode = 0644
[versions] [versions]
slapos.recipe.template = 4.4
inotifyx = 0.2.2 inotifyx = 0.2.2
...@@ -32,7 +32,3 @@ output = ${buildout:directory}/${:_buildout_section_name_} ...@@ -32,7 +32,3 @@ output = ${buildout:directory}/${:_buildout_section_name_}
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = https://sourceforge.net/projects/plantuml/files/1.2020.15/plantuml.1.2020.15.war url = https://sourceforge.net/projects/plantuml/files/1.2020.15/plantuml.1.2020.15.war
md5sum = ed203cb3b90df8f77492fa36ea6490a5 md5sum = ed203cb3b90df8f77492fa36ea6490a5
[versions]
slapos.recipe.template = 4.4
...@@ -19,6 +19,3 @@ url = ${:_profile_base_location_}/instance.cfg.in ...@@ -19,6 +19,3 @@ url = ${:_profile_base_location_}/instance.cfg.in
output = ${buildout:directory}/instance.cfg output = ${buildout:directory}/instance.cfg
md5sum = d8b833a2054b82b6031a9420008b58fd md5sum = d8b833a2054b82b6031a9420008b58fd
mode = 0644 mode = 0644
[versions]
slapos.recipe.template = 2.4.2
...@@ -26,7 +26,7 @@ md5sum = 20c37ea06a8fa405bc02470d5115fd11 ...@@ -26,7 +26,7 @@ md5sum = 20c37ea06a8fa405bc02470d5115fd11
[template-dns-replicate] [template-dns-replicate]
_update_hash_filename_ = instance-powerdns-replicate.cfg.jinja2 _update_hash_filename_ = instance-powerdns-replicate.cfg.jinja2
md5sum = c2bd424f588ad57d37f4cf1329734fb6 md5sum = 72ce30bee3b8a9da8ac9be7eb65d83a2
[iso-list] [iso-list]
_update_hash_filename_ = template/zz.countries.nexedi.dk.rbldnsd _update_hash_filename_ = template/zz.countries.nexedi.dk.rbldnsd
...@@ -34,4 +34,4 @@ md5sum = c4dc8c141d81b92d92cdb82ca67a13ee ...@@ -34,4 +34,4 @@ md5sum = c4dc8c141d81b92d92cdb82ca67a13ee
[template-zones-file] [template-zones-file]
_update_hash_filename_ = template/zones-file.yml.jinja2 _update_hash_filename_ = template/zones-file.yml.jinja2
md5sum = 03037141ad1d3467ae878c9798724f70 md5sum = 612de569ac3d1e8cc10b830683ff92ae
...@@ -33,12 +33,12 @@ ...@@ -33,12 +33,12 @@
"default": "", "default": "",
"type": "string" "type": "string"
}, },
"zone": { "supported-zone-list": {
"title": "Zone", "title": "Zone",
"description": "Zone to be handled by the DNS cluster", "description": "Zone to be handled by the DNS cluster",
"type": "string", "type": "string",
"default": "domain.com", "default": "domain.com",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$" "pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(\\s([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6})*$"
}, },
"server-admin": { "server-admin": {
"title": "Zone Administrator Email", "title": "Zone Administrator Email",
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
"title": "DNS domains template string", "title": "DNS domains template string",
"description": "Template used to generate DNS domain name", "description": "Template used to generate DNS domain name",
"type": "string", "type": "string",
"default": "ns%s. + zone" "default": "ns%s.domain.com"
}, },
"monitor-interface-url": { "monitor-interface-url": {
"title": "Monitor Web Interface URL", "title": "Monitor Web Interface URL",
......
...@@ -33,9 +33,9 @@ context = ...@@ -33,9 +33,9 @@ context =
{% endif -%} {% endif -%}
## DNS set up ## DNS set up
{% set zone = slapparameter_dict.pop('zone', 'domain.com') %} {%- set supported_zone_list = slapparameter_dict.pop('supported-zone-list', 'domain.com').split() %}
{% set server_admin = slapparameter_dict.pop('server-admin', 'admin@domain.com') %} {% set server_admin = slapparameter_dict.pop('server-admin', 'admin@domain.com') %}
{% set dns_name_template_string = slapparameter_dict.pop('dns-name-template-string', 'ns%s.' + zone) %} {% set dns_name_template_string = slapparameter_dict.pop('dns-name-template-string', 'ns%s.domain.com') %}
# Here we request individualy each dns. # Here we request individualy each dns.
# The presence of sla parameters is checked and added if found # The presence of sla parameters is checked and added if found
...@@ -65,7 +65,7 @@ name = {{dns_name}} ...@@ -65,7 +65,7 @@ name = {{dns_name}}
{% if state_key in slapparameter_dict %} {% if state_key in slapparameter_dict %}
state = {{ slapparameter_dict.pop(state_key) }} state = {{ slapparameter_dict.pop(state_key) }}
{% endif%} {% endif%}
config-zone = {{ zone }} config-supported-zone-list = {{ ' '.join(supported_zone_list) }}
config-soa = {{ "%s,%s" % (dns_domain, server_admin) }} config-soa = {{ "%s,%s" % (dns_domain, server_admin) }}
{% for parameter in sla_parameters -%} {% for parameter in sla_parameters -%}
sla-{{ parameter }} = {{ slapparameter_dict.pop( sla_key + parameter ) }} sla-{{ parameter }} = {{ slapparameter_dict.pop( sla_key + parameter ) }}
...@@ -74,11 +74,9 @@ sla-{{ parameter }} = {{ slapparameter_dict.pop( sla_key + parameter ) }} ...@@ -74,11 +74,9 @@ sla-{{ parameter }} = {{ slapparameter_dict.pop( sla_key + parameter ) }}
[{{promise_section_title}}] [{{promise_section_title}}]
<= monitor-promise-base <= monitor-promise-base
module = check_port_listening module = check_port_listening
name = pdns-port-listening.py name = {{promise_section_title}}.py
{% set ipv6 = '${' ~ request_section_title ~ ':connection-powerdns-ipv6}' -%} config-hostname = {{ '${' ~ request_section_title ~ ':connection-powerdns-ipv6}' }}
config-hostname = {{ipv6}} config-port = {{ '${' ~ request_section_title ~ ':connection-powerdns-port}' }}
{% set port = '${' ~ request_section_title ~ ':connection-powerdns-port}' -%}
config-port = {{port}}
{% do monitor_url_list.append('${' ~ request_section_title ~ ':connection-monitor-base-url}') -%} {% do monitor_url_list.append('${' ~ request_section_title ~ ':connection-monitor-base-url}') -%}
{% endfor -%} {% endfor -%}
......
...@@ -8,6 +8,13 @@ ...@@ -8,6 +8,13 @@
"description": "Record for the configuration", "description": "Record for the configuration",
"type": "string" "type": "string"
}, },
"applicable-zone": {
"title": "Applicable Zone",
"description": "Zone to which this record belongs. You can put only one zone here. If the record belongs to several zones, you should create several slaves.",
"pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$",
"default": "domain.com",
"type": "string"
},
"origin": { "origin": {
"title": "Origin", "title": "Origin",
"description": "Used to qualify RR in the configuration. i.e.: if your origin is a.example.com and the RR for Europe is 'eu' the european clients will use eu.a.example.com", "description": "Used to qualify RR in the configuration. i.e.: if your origin is a.example.com and the RR for Europe is 'eu' the european clients will use eu.a.example.com",
......
...@@ -54,7 +54,6 @@ mode = 0644 ...@@ -54,7 +54,6 @@ mode = 0644
PyRSS2Gen = 1.1 PyRSS2Gen = 1.1
cns.recipe.symlink = 0.2.3 cns.recipe.symlink = 0.2.3
plone.recipe.command = 1.1 plone.recipe.command = 1.1
slapos.recipe.template = 4.4
passlib = 1.7.1 passlib = 1.7.1
GitPython = 2.1.11 GitPython = 2.1.11
lockfile = 0.12.2 lockfile = 0.12.2
......
# See https://doc.powerdns.com/authoritative/backends/geoip.html # See https://doc.powerdns.com/authoritative/backends/geoip.html
{%- set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '[]')) %} {%- set slave_instance_list = json_module.loads(slapparameter_dict.get('extra_slave_instance_list', '[]')) %}
{%- set zone = slapparameter_dict.get('zone', 'example.com') %} {%- set supported_zone_list = slapparameter_dict.get('supported-zone-list', 'example.com').split() %}
{%- macro disambiguate_domain_name(a, b) %} {%- macro disambiguate_domain_name(a, b) %}
{#- See http://www.dns-sd.org/trailingdotsindomainnames.html #} {#- See http://www.dns-sd.org/trailingdotsindomainnames.html #}
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
{%- endmacro %} {%- endmacro %}
domains: domains:
{%- for zone in supported_zone_list %}
- domain: {{ zone }} - domain: {{ zone }}
# TODO: what value for ttl? # TODO: what value for ttl?
ttl: 300 ttl: 300
...@@ -48,6 +50,7 @@ domains: ...@@ -48,6 +50,7 @@ domains:
{%- for slave in slave_instance_list %} {%- for slave in slave_instance_list %}
{%- if slave['applicable-zone'] == zone %}
{%- set origin = slave['origin'] %} {%- set origin = slave['origin'] %}
{%- set unique_slave_id = slave['slave_reference'] %} {%- set unique_slave_id = slave['slave_reference'] %}
{#- Set the RR to use for each region, as described in {#- Set the RR to use for each region, as described in
...@@ -77,13 +80,15 @@ domains: ...@@ -77,13 +80,15 @@ domains:
- cname: {{ disambiguate_domain_name(rr_dict[region], origin) }} - cname: {{ disambiguate_domain_name(rr_dict[region], origin) }}
{%- endfor %} {%- endfor %}
{%- endfor %} {%- endfor %}
{%- endif %}
{%- endfor %} {%- endfor %}
services: services:
{%- for slave in slave_instance_list %} {%- for slave in slave_instance_list %}
{%- if slave['applicable-zone'] == zone %}
{%- set origin = slave['origin'] %} {%- set origin = slave['origin'] %}
{%- set unique_slave_id = slave['slave_reference'] %} {%- set unique_slave_id = slave['slave_reference'] %}
{{ disambiguate_domain_name(slave['record'], zone) }}: {{ disambiguate_domain_name(slave['record'], slave['applicable-zone']) }}:
{#- Note: Placeholders (i.e. "country." and "continent.") are used to avoid {#- Note: Placeholders (i.e. "country." and "continent.") are used to avoid
possible name collisions, e.g.: possible name collisions, e.g.:
- %cc for American Samoa is 'as' - %cc for American Samoa is 'as'
...@@ -94,4 +99,6 @@ domains: ...@@ -94,4 +99,6 @@ domains:
{%- for ip_range, country_code in china %} {%- for ip_range, country_code in china %}
{{ ip_range }}: {{ country_code }}.country.{{ unique_slave_id }} {{ ip_range }}: {{ country_code }}.country.{{ unique_slave_id }}
{%- endfor %} {%- endfor %}
{%- endif %}
{%- endfor %} {%- endfor %}
{%- endfor %}
This diff is collapsed.
...@@ -46,5 +46,4 @@ context = ...@@ -46,5 +46,4 @@ context =
[versions] [versions]
collective.recipe.environment = 1.1.0 collective.recipe.environment = 1.1.0
collective.recipe.grp = 1.1.0 collective.recipe.grp = 1.1.0
slapos.recipe.template = 4.4
plone.recipe.command = 1.1 plone.recipe.command = 1.1
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