Commit f2183d38 authored by Vincent Pelletier's avatar Vincent Pelletier

erp5: Add webdav support.

Move haproxy httpchk configuration per-listen as zope's webdav returns 401
on (at least) GET / . TCP-level checks are still active, which should be
sufficient.
Also, change zope_family_address_list check to getitem as it's more natural
than concatenating.
Also, stop using apache.zope.backend recipe to add support for per-port
scheme so automatic ERP5Site creation knows which URL is really HTTP.
Also, stop using certificate_authority recipe and call openssl directly
when generating self-signed cert for https/webdavs support.
Also, rework balancer parameters a bit (still undocumented).
Also, make instance-balancer always publish ipv6 value (empty when no ipv6
available), so instance-erp5 always succeeds.
parent efc8d32a
......@@ -90,6 +90,11 @@
"default": 5,
"type": "integer"
},
"webdav": {
"description": "Serve webdav queries, implies timerserver-interval=0 (disabled). Mixing webdav and non-webdav nodes in a single family will give unspecified results.",
"default": false,
"type": "boolean"
},
"longrequest-logger-interval": {
"description": "Period, in seconds, with which LongRequestLogger polls worker thread stack traces, or -1 to disable",
"default": -1,
......
General:
- varnish/squid
- enable zope webdav service and provide access through haproxy & backend apache
- ipv6 support (besides frontend-backend apache connection)
requires important changes at ERP5 level
- resilience
......
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
PidFile "{{ parameter_dict['pid-file'] }}"
ServerAdmin admin@
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
TimeOut {{ parameter_dict['timeout'] }}
SSLCertificateFile {{ parameter_dict['cert'] }}
SSLCertificateKeyFile {{ parameter_dict['key'] }}
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLProtocol All -SSLv2
#SSLHonorCipherOrder on
{% if parameter_dict['cipher'] -%}
SSLCipherSuite {{ parameter_dict['cipher'] }}
{%- endif %}
SSLSessionCache shmcb:{{ parameter_dict['ssl-session-cache'] }}(512000)
SSLProxyEngine On
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
{% if parameter_dict['ca-cert'] -%}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
{%- endif %}
ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
CustomLog "{{ parameter_dict['access-log'] }}" combined
<Directory />
Options FollowSymLinks
AllowOverride None
Allow from all
</Directory>
RewriteEngine On
{% for port, _, backend in parameter_dict['backend-list'] -%}
{% for ip in parameter_dict['ip-list'] -%}
Listen {{ ip }}:{{ port }}
{% endfor -%}
<VirtualHost *:{{ port }}>
SSLEngine on
RewriteRule ^/(.*) {{ backend }}/$1 [L,P]
</VirtualHost>
{% endfor -%}
......@@ -207,7 +207,7 @@ md5sum = 6d52007d9bdc25ed0c83a49d63d59a18
[template-zope-conf]
< = download-base
filename = zope.conf.in
md5sum = a7247c0d27cbb0f8ad90f3277f789ba4
md5sum = 43b27a5e9c641ab780a083223c693d04
[template-my-cnf]
< = download-base
......@@ -227,14 +227,14 @@ md6sum = 4504b8e58cf6eb0f17ef30c29c04432d
[template-create-erp5-site-real]
< = download-base
filename = instance-create-erp5-site-real.cfg.in
md5sum = a88881e00d56286e16fcaf36d94c025e
md5sum = ba1b23177e101b5b9f03e1c5009c81fc
[template]
< = template-jinja2-base
# XXX: "template.cfg" is hardcoded in instanciation recipe
filename = template.cfg
template = ${:_profile_base_location_}/instance.cfg.in
md5sum = 6b7c9a4e64e488270d1d3b62e6d81f3b
md5sum = 95f85fdc55e70937eac39bbfe32042cf
extra-context =
key mariadb_link_binary template-mariadb:link-binary
key zope_link_binary template-zope:link-binary
......@@ -277,6 +277,7 @@ extra-context =
key openssl_location openssl:location
key sixtunnel_location 6tunnel:location
key stunnel_location stunnel:location
key template_apache_conf template-apache-conf:target
key template_balancer template-balancer:target
key template_cloudooo template-cloudooo:target
key template_create_erp5_site template-create-erp5-site:target
......@@ -298,7 +299,7 @@ extra-context =
[template-erp5]
< = download-base
filename = instance-erp5.cfg.in
md5sum = 629e4f00e930ede95ba249e150f554a6
md5sum = f05ca816cdd8af592f56c844c2420daa
[template-neo]
< = download-base
......@@ -313,7 +314,7 @@ md5sum = 6b99d2712aff3a8a717400a557dc5191
[template-zope]
< = download-base
filename = instance-zope.cfg.in
md5sum = 3649f1c77745b9f96049b6cb43931090
md5sum = a30c105d4059f29dd36b09ab276fbd5e
link-binary =
${aspell:location}/bin/aspell
${coreutils:location}/bin/basename
......@@ -343,12 +344,17 @@ link-binary =
[template-balancer]
< = download-base
filename = instance-balancer.cfg.in
md5sum = e0b8ba297c4ab92f6ecb61c3384d893e
md5sum = 796bcba17e4e8e7e86c2d1cf9a1e67dd
[template-apache-conf]
< = download-base
filename = apache.conf.in
md5sum = dedfe759c3421e0186703fe1257bae8f
[template-haproxy-cfg]
< = download-base
filename = haproxy.cfg.in
md5sum = 9f8bdf49366eee04c2add5c203d20cd0
md5sum = 1dcb02721a606360271ca19d2f4d135b
[template-logrotate-base]
< = template-jinja2-base
......
{% set server_check_path = parameter_dict['server-check-path'] -%}
global
maxconn 4096
stats socket {{ parameter_dict['socket-path'] }} level admin
......@@ -14,10 +15,6 @@ defaults
balance roundrobin
stats uri /haproxy
stats realm Global\ statistics
{% set server_check_path = parameter_dict['server-check-path'] -%}
{% if server_check_path -%}
option httpchk GET {{ server_check_path }}
{% endif -%}
# it is useless to have timeout much bigger than the one of apache.
# By default apache use 300s, so we set slightly more in order to
# make sure that apache will first stop the connection.
......@@ -40,8 +37,13 @@ defaults
{% for name, (port, backend_list) in parameter_dict['backend-dict'].items() -%}
listen {{ name }} {{ parameter_dict['ip'] }}:{{ port }}
{% for address, connection_count in backend_list -%}
{% set has_webdav = [] -%}
{% for address, connection_count, webdav in backend_list -%}
{% if webdav %}{% do has_webdav.append(None) %}{% endif -%}
{% set server_name = name ~ '-' ~ loop.index0 -%}
server {{ server_name }} {{ address }} cookie {{ server_name }} check inter 3s rise 1 fall 2 maxqueue 5 maxconn {{ connection_count }}
{% endfor -%}
{%- if not has_webdav and server_check_path %}
option httpchk GET {{ server_check_path }}
{% endif -%}
{% endfor %}
{% if software_type == slap_software_type -%}
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{#
......@@ -16,6 +17,22 @@ per partition. No more (undefined result), no less (IndexError).
{% do apache_ip_list.append('[' ~ ipv6 ~ ']') -%}
{% endif -%}
[simplefile]
recipe = slapos.recipe.template:jinja2
template = inline:{{ '{{ content }}' }}
{% macro simplefile(section_name, file_path, content, mode='') -%}
{% set content_section_name = section_name ~ '-content' -%}
[{{ content_section_name }}]
content = {{ dumps(content) }}
[{{ section(section_name) }}]
< = simplefile
rendered = {{ file_path }}
context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}
{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
......@@ -30,9 +47,13 @@ ipv4 = {{ ipv4 }}
{% set next_port = slapparameter_dict['tcpv4-port'] -%}
{% for family_name, parameter_id_list in slapparameter_dict['zope-family-dict'].items() -%}
{% set zope_family_address_list = [] -%}
{% set has_webdav = [] -%}
{% for parameter_id in parameter_id_list -%}
{% set zope_address_list = slapparameter_dict[parameter_id] -%}
{% for zope_address, maxconn in zope_address_list -%}
{% for zope_address, maxconn, webdav in zope_address_list -%}
{% if webdav -%}
{% do has_webdav.append(None) %}
{% endif -%}
{% if use_ipv6 -%}
[{{ section('zope-tunnel-' ~ next_port) }}]
< = zope-tunnel-base
......@@ -45,20 +66,27 @@ ipv6 = {{ zope_address.split(']:')[0][1:] }}
{% else -%}
{% set zope_effective_address = zope_address -%}
{% endif -%}
{% do zope_family_address_list.append((zope_effective_address, maxconn)) -%}
{% do zope_family_address_list.append((zope_effective_address, maxconn, webdav)) -%}
{% endfor -%}
{% endfor -%}
{# Make rendering fail artificially if any family has no known backend.
# This is useful as haproxy's hot-reconfiguration mechanism is
# supervisord-incompatible.
# As jinja2 postpones KeyError until place-holder value is actually used,
# do a no-op, type-safe concatenation.
# do a no-op getitem.
-#}
{% do '#' ~ zope_family_address_list[0] -%}
{% do zope_family_address_list[0][0] -%}
{% set haproxy_port = next_port -%}
{% set next_port = next_port + 1 -%}
{% do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{% do apache_dict.__setitem__(family_name, (next_port, 'http://' ~ ipv4 ~ ':' ~ haproxy_port)) -%}
{% if has_webdav -%}
{% set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
{% set external_scheme = 'webdavs' -%}
{% else %}
{% set internal_scheme = 'http' -%}
{% set external_scheme = 'https' -%}
{% endif -%}
{% do apache_dict.__setitem__(family_name, (next_port, external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ slapparameter_dict['backend-path'])) -%}
{% set next_port = next_port + 1 -%}
{% endfor -%}
......@@ -73,6 +101,7 @@ recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-haproxy-cfg'] }}
rendered = ${directory:etc}/haproxy.cfg
context = section parameter_dict haproxy-cfg-parameter-dict
extensions = jinja2.ext.do
[{{ section('haproxy') }}]
recipe = slapos.cookbook:wrapper
......@@ -81,69 +110,78 @@ command-line = "{{ parameter_dict['haproxy'] }}/sbin/haproxy" -f "${haproxy-cfg:
{# TODO: build socat and wrap it as "${directory:bin}/haproxy-ctl" to connect to "${haproxy-cfg-parameter-dict:socket-path}" #}
[apache]
recipe = slapos.cookbook:apache.zope.backend
[apache-conf-ssl]
cert = ${directory:apache-conf}/apache.crt
key = ${directory:apache-conf}/apache.pem
ca-cert = ${directory:apache-conf}/ca.crt
crl = ${directory:apache-conf}/crl.pem
[apache-conf-parameter-dict]
backend-list = {{ dumps(apache_dict.values()) }}
ip = {{ dumps(apache_ip_list) }}
wrapper = ${directory:bin}/apache
scheme = https
key-file = ${directory:apache-conf}/apache.key
cert-file = ${directory:apache-conf}/apache.crt
configuration-file = ${directory:apache-conf}/apache.conf
access-control-string = {{ dumps(slapparameter_dict['apache-access-control-string']) }}
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
lock-file = ${directory:run}/apache.lock
ssl-session-cache = $${directory:log}/apache-ssl-session-cache
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
apache-binary = {{ parameter_dict['apache'] }}/bin/httpd
ssl-authentication = {{ dumps(slapparameter_dict['apache-ssl-authentication']) }}
backend-path = {{ dumps(slapparameter_dict['apache-backend-path']) }}
# Note: Without certificate-authority main certificate have to be hardcoded
ssl-authentication-certificate = ${certificate-authority:ca-dir}/cacert.pem
ssl-authentication-crl = ${certificate-authority:ca-crl}
# Apache 2.4's default value (60 seconds) can be a bit too short
timeout = 300
# Basic SSL server configuration
cert = ${apache-ssl:cert}
key = ${apache-ssl:key}
cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache
# Client x509 auth
ca-cert = ${apache-ssl-client:cert}
crl = ${apache-ssl-client:crl}
[apache-conf]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-apache-conf'] }}
rendered = ${directory:apache-conf}/apache.conf
context = section parameter_dict apache-conf-parameter-dict
[{{ section('apache') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND
[publish]
recipe = slapos.cookbook:publish.serialised
{% for family_name, (apache_port, _) in apache_dict.items() -%}
{% if ipv6_set -%}
{{ family_name ~ '-v6' }} = ${apache:scheme}://[{{ ipv6 }}]:{{ apache_port }}
{% endif -%}
{{ family_name }} = ${apache:scheme}://{{ ipv4 }}:{{ apache_port }}
{% for family_name, (apache_port, scheme, _) in apache_dict.items() -%}
{{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ parameter_dict['openssl'] }}/bin/openssl
ca-dir = ${directory:ca-dir}
requests-directory = ${directory:requests}
wrapper = ${directory:services}/ca
ca-private = ${directory:private}
ca-certs = ${directory:certs}
ca-newcerts = ${directory:newcerts}
ca-crl = ${directory:crl}
{% set ca = slapparameter_dict['ca'] -%}
country-code = {{ dumps(ca.get('country-code', 'ZZ')) }}
email = {{ dumps(ca.get('email', 'nobody@example.com')) }}
state = {{ dumps(ca.get('state', 'Dummy State')) }}
city = {{ dumps(ca.get('city', 'Dummy City')) }}
company = {{ dumps(ca.get('company', 'Dummy Company')) }}
[ca-apache]
< = certificate-authority
recipe = slapos.cookbook:certificate_authority.request
key-file = ${apache:key-file}
cert-file = ${apache:cert-file}
executable = ${apache:wrapper}
wrapper = ${directory:services}/apache
[apache-ssl]
{% if ssl_parameter_dict.get('key') -%}
key = ${apache-ssl-key:rendered}
cert = ${apache-ssl-cert:rendered}
{{ simplefile('apache-ssl-key', '${apache-conf-ssl:key}', ssl_parameter_dict['key']) }}
{{ simplefile('apache-ssl-cert', '${apache-conf-ssl:cert}', ssl_parameter_dict['cert']) }}
{% else %}
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
{%- endif %}
[apache-ssl-client]
{% if ssl_parameter_dict.get('ca-cert') -%}
cert = ${apache-ssl-ca:rendered}
crl = ${apache-ssl-crl:rendered}
{{ simplefile('apache-ssl-ca', '${apache-conf-ssl:ca-cert}', ssl_parameter_dict['ca-cert']) }}
{{ simplefile('apache-ssl-crl', '${apache-conf-ssl:crl}', ssl_parameter_dict['crl']) }}
{% else %}
cert =
crl =
{%- endif %}
[logrotate-apache]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = apache
log = ${apache:error-log} ${apache:access-log}
post = {{ parameter_dict['bin-directory'] }}/killpidfromfile ${apache:pid-file} SIGUSR1
log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log}
post = {{ parameter_dict['bin-directory'] }}/killpidfromfile ${apache-conf-parameter-dict:pid-file} SIGUSR1
[directory]
recipe = slapos.cookbook:mkdirectory
......@@ -166,8 +204,6 @@ extends = {{ parameter_dict['instance-logrotate-cfg'] }}
parts +=
publish
logrotate-apache
haproxy
ca-apache
{{ part_list | join('\n ') }}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
......
......@@ -9,10 +9,10 @@ recipe = slapos.cookbook:erp5.bootstrap
runner-path = ${directory:services}/erp5-bootstrap
{# XXX: Expect the first database to be the one to use for catalog. -#}
mysql-url = {{ publish['mariadb-database-list'][0] }}
{# Pick the first family found, they should be all equivalent anyway. -#}
{# Pick the first http[s] family found, they should be all equivalent anyway. -#}
{% set family_list = [] -%}
{% for key, value in publish.items() -%}
{% if key.startswith('family-') -%}
{% if key.startswith('family-') and value.startswith('http') -%}
{% do family_list.append(value.split('://', 1)) -%}
{% endif -%}
{% endfor -%}
......
......@@ -92,6 +92,7 @@ extra-config =
inituser-login
inituser-password
developer-list
webdav
config-mysql-url-list = ${request-mariadb:connection-database-list}
config-mysql-test-url-list = ${request-mariadb:connection-test-database-list}
config-memcached-url = ${request-memcached-volatile:connection-url}
......@@ -126,6 +127,7 @@ config-timerserver-interval = {{ dumps(zope_parameter_dict.get('timerserver-inte
config-longrequest-logger-interval = {{ dumps(zope_parameter_dict.get('longrequest-logger-interval', -1)) }}
config-longrequest-logger-timeout = {{ dumps(zope_parameter_dict.get('longrequest-logger-timeout', 1)) }}
config-port-base = {{ dumps(zope_parameter_dict.get('port-base', 2200)) }}
config-webdav = {{ dumps(zope_parameter_dict.get('webdav', False)) }}
sla-computer_guid = {{ dumps(zope_parameter_dict.get('computer-guid', computer_id)) }}
{% endfor -%}
......@@ -160,10 +162,8 @@ sla-computer_guid = {{ dumps(slapparameter_dict.get('balancer-computer-guid', co
extra-config =
tcpv4-port
haproxy-server-check-path
apache-access-control-string
apache-ssl-authentication
apache-backend-path
ca
backend-path
ssl
zope-family-dict
{{ zope_address_list_id_dict.values() | join(' ') }}
return =
......@@ -178,10 +178,8 @@ config-{{ name }} = {{ ' ${' ~ zope_section_id ~ ':connection-zope-address-list}
{% endfor -%}
# XXX: should those really be same for all families ?
config-haproxy-server-check-path = {{ dumps(balancer_dict.get('haproxy-server-check-path', '/') % {'site-id': site_id}) }}
config-apache-access-control-string = {{ dumps(balancer_dict.get('apache-access-control-string', 'all')) }}
config-apache-ssl-authentication = {{ dumps(balancer_dict.get('apache-ssl-authentication', '0')) }}
config-apache-backend-path = {{ dumps(balancer_dict.get('apache-backend-path', '/') % {'site-id': site_id}) }}
config-ca = {{ dumps(balancer_dict.get('ca', {})) }}
config-backend-path = {{ dumps(balancer_dict.get('apache-backend-path', '/') % {'site-id': site_id}) }}
config-ssl = {{ dumps(balancer_dict.get('ssl', {})) }}
[request-frontend-base]
{% if has_frontend -%}
......
......@@ -198,7 +198,14 @@ tidstorage-port = ${tidstorage:ipv4-port}
promise-path = ${erp5-promise:promise-path}
{% set thread_amount = slapparameter_dict['thread-amount'] -%}
thread-amount = {{ thread_amount }}
timerserver-interval = {{ dumps(slapparameter_dict['timerserver-interval']) }}
{% set webdav = slapparameter_dict['webdav'] -%}
webdav = {{ dumps(webdav) }}
{% if webdav -%}
{% set timerserver_interval = 0 -%}
{% else -%}
{% set timerserver_interval = slapparameter_dict['timerserver-interval'] -%}
{%- endif %}
timerserver-interval = {{ dumps(timerserver_interval) }}
[zope-conf-base]
recipe = slapos.recipe.template:jinja2
......@@ -260,7 +267,7 @@ path = ${directory:promises}/{{ name }}
base-name = {{ zope_tunnel_base_name }}
ipv6-port = {{ port }}
ipv4-port = {{ port }}
{% do publish_list.append(("[" ~ ipv6 ~ "]:" ~ port, thread_amount)) -%}
{% do publish_list.append(("[" ~ ipv6 ~ "]:" ~ port, thread_amount, webdav)) -%}
[{{ section("promise-tunnel-" ~ name) }}]
recipe = slapos.cookbook:check_port_listening
......@@ -268,7 +275,7 @@ hostname = {{ '${' ~ zope_tunnel_section_name ~ ':ipv6}' }}
port = {{ '${' ~ zope_tunnel_section_name ~ ':ipv6-port}' }}
path = ${directory:promises}/{{ zope_tunnel_base_name }}
{% else -%}
{% do publish_list.append((ipv4 ~ ":" ~ port, thread_amount)) -%}
{% do publish_list.append((ipv4 ~ ":" ~ port, thread_amount, webdav)) -%}
{% endif -%}
[{{ section('logrotate-entry-' ~ name) }}]
......
......@@ -96,6 +96,7 @@ bin-directory = {{ bin_directory }}
6tunnel = {{ sixtunnel_location }}
dash = {{ dash_location }}
template-haproxy-cfg = {{ template_haproxy_cfg }}
template-apache-conf = {{ template_apache_conf }}
[dynamic-template-balancer]
< = jinja2-template-base
......
......@@ -22,19 +22,17 @@ rest-output-encoding utf-8
# XXX: isn't this entry implicit ?
products {{ parameter_dict['instance-products'] }}
<http-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
</http-server>
{# TODO: enable
{% if webdav_port -%}
{% if parameter_dict['webdav'] -%}
<webdav-source-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['webdav_port'] }}
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
force-connection-close off
</webdav-source-server>
{% else %}
<http-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
</http-server>
{%- endif %}
{% endif -%}
-#}
<zoperunner>
program $INSTANCE/bin/runzope
</zoperunner>
......
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