Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
slapos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
slapos
Commits
f4f72d6b
Commit
f4f72d6b
authored
Mar 05, 2012
by
Cédric de Saint Martin
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into occi
parents
d2562e4b
c7d16ba5
Changes
35
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
1599 additions
and
234 deletions
+1599
-234
CHANGES.txt
CHANGES.txt
+14
-3
MANIFEST.in
MANIFEST.in
+1
-0
component/apache/buildout.cfg
component/apache/buildout.cfg
+2
-12
component/binutils/buildout.cfg
component/binutils/buildout.cfg
+8
-0
component/ca-certificates/buildout.cfg
component/ca-certificates/buildout.cfg
+1
-1
component/cloudooo/buildout.cfg
component/cloudooo/buildout.cfg
+9
-48
component/dropbear/buildout.cfg
component/dropbear/buildout.cfg
+8
-0
component/dropbear/dropbear-0.53.1-static_build_fix.patch
component/dropbear/dropbear-0.53.1-static_build_fix.patch
+11
-0
component/slapos/buildout.cfg
component/slapos/buildout.cfg
+6
-6
setup.py
setup.py
+2
-1
slapos/recipe/README.apache_frontend.txt
slapos/recipe/README.apache_frontend.txt
+4
-0
slapos/recipe/README.helloworld.txt
slapos/recipe/README.helloworld.txt
+0
-4
slapos/recipe/apache_frontend/__init__.py
slapos/recipe/apache_frontend/__init__.py
+442
-0
slapos/recipe/apache_frontend/certificate_authority.py
slapos/recipe/apache_frontend/certificate_authority.py
+114
-0
slapos/recipe/apache_frontend/template/apache.conf.in
slapos/recipe/apache_frontend/template/apache.conf.in
+74
-0
slapos/recipe/apache_frontend/template/apache.conf.path-protected.in
...pe/apache_frontend/template/apache.conf.path-protected.in
+5
-0
slapos/recipe/apache_frontend/template/apache.location-snippet.conf.in
.../apache_frontend/template/apache.location-snippet.conf.in
+5
-0
slapos/recipe/apache_frontend/template/apache.ssl-snippet.conf.in
...ecipe/apache_frontend/template/apache.ssl-snippet.conf.in
+6
-0
slapos/recipe/apache_frontend/template/logrotate_entry.in
slapos/recipe/apache_frontend/template/logrotate_entry.in
+13
-0
slapos/recipe/apache_frontend/template/notfound.html
slapos/recipe/apache_frontend/template/notfound.html
+9
-0
slapos/recipe/apache_frontend/template/openssl.cnf.ca.in
slapos/recipe/apache_frontend/template/openssl.cnf.ca.in
+350
-0
slapos/recipe/apache_frontend/template/stunnel.conf.entry.in
slapos/recipe/apache_frontend/template/stunnel.conf.entry.in
+3
-0
slapos/recipe/apache_frontend/template/stunnel.conf.in
slapos/recipe/apache_frontend/template/stunnel.conf.in
+14
-0
slapos/recipe/apache_frontend/template/varnish.vcl.in
slapos/recipe/apache_frontend/template/varnish.vcl.in
+245
-0
slapos/recipe/helloworld.py
slapos/recipe/helloworld.py
+0
-44
slapos/recipe/pulse2/__init__.py
slapos/recipe/pulse2/__init__.py
+1
-1
software/apache-frontend/instance.cfg
software/apache-frontend/instance.cfg
+18
-0
software/apache-frontend/software.cfg
software/apache-frontend/software.cfg
+141
-0
software/cloudooo/development.cfg
software/cloudooo/development.cfg
+3
-0
software/helloworld/instance.cfg
software/helloworld/instance.cfg
+0
-9
software/helloworld/software.cfg
software/helloworld/software.cfg
+0
-34
software/slaprunner/software.cfg
software/slaprunner/software.cfg
+48
-58
stack/cloudooo.cfg
stack/cloudooo.cfg
+1
-13
stack/lamp.cfg
stack/lamp.cfg
+1
-0
stack/slapos.cfg
stack/slapos.cfg
+40
-0
No files found.
CHANGES.txt
View file @
f4f72d6b
Changes
=======
0.
39 (unreleased
)
0.
40.1 (2012-03-01
)
-----------------
* No changes yet.
* Fix manifest to include files needed for apache. [Cedric de Saint Martin]
0.40 (2012-03-01)
-----------------
* apache_frontend initial release. [Cedric de Saint Martin]
0.39 (2012-02-20)
-----------------
* seleniumrunner initial release. [Cedric de Saint Martin]
0.38 (2011-12-05)
-----------------
...
...
@@ -190,9 +200,10 @@ Changes
-----------------
* Add PHPMyAdmin software release used in SlapOS tutorials
[Cedric de Saint Martin]
[Cedric de Saint Martin]
* Add slaprunner software release [Cedric de Saint Martin]
0.9 (2011-06-24)
----------------
...
...
MANIFEST.in
View file @
f4f72d6b
include CHANGES.txt
include slapos/recipe/generic_zope/template/site.zcml
include slapos/recipe/apache_frontend/template/notfound.html
recursive-include slapos/recipe *.in
recursive-include slapos/recipe *.bin
recursive-include slapos/recipe README.*.txt
component/apache/buildout.cfg
View file @
f4f72d6b
...
...
@@ -13,23 +13,13 @@ extends =
../sqlite3/buildout.cfg
../zlib/buildout.cfg
[apache-CVE-2011-3368.patch]
recipe = hexagonit.recipe.download
md5sum = 1ad598213480ddfc239ce6359b7b2c0b
url = http://www.apache.org/dist/httpd/patches/apply_to_2.2.21/CVE-2011-3368.patch
filename = ${:_buildout_section_name_}
download-only = true
[apache]
# inspired on http://old.aclark.net/team/aclark/blog/a-lamp-buildout-for-wordpress-and-other-php-apps/
recipe = hexagonit.recipe.cmmi
depends =
${gdbm:version}
url = http://mir2.ovh.net/ftp.apache.org/dist//httpd/httpd-2.2.21.tar.bz2
md5sum = 1696ae62cd879ab1d4dd9ff021a470f2
patches =
${apache-CVE-2011-3368.patch:location}/${apache-CVE-2011-3368.patch:filename}
patch-options = -p1
url = http://mir2.ovh.net/ftp.apache.org/dist//httpd/httpd-2.2.22.tar.bz2
md5sum = 9fe3093194c8a57f085ff7c3fc43715f
configure-options = --disable-static
--enable-authn-alias
--enable-bucketeer
...
...
component/binutils/buildout.cfg
0 → 100644
View file @
f4f72d6b
[buildout]
parts =
binutils
[binutils]
recipe = hexagonit.recipe.cmmi
url = http://ftp.gnu.org/gnu/binutils/binutils-2.21.1.tar.bz2
md5sum = bde820eac53fa3a8d8696667418557ad
component/ca-certificates/buildout.cfg
View file @
f4f72d6b
...
...
@@ -14,7 +14,7 @@ download-only = true
[ca-certificates]
recipe = hexagonit.recipe.cmmi
version = 201
11211
version = 201
20212
url = ftp://ftp.free.fr/mirrors/ftp.debian.org/pool/main/c/ca-certificates/ca-certificates_${:version}.tar.gz
patches =
${ca-certificates-sbin-dir.patch:location}/${ca-certificates-sbin-dir.patch:filename}
...
...
component/cloudooo/buildout.cfg
View file @
f4f72d6b
[buildout]
software_home = ${:directory}
extends =
../profiles/versions-common.cfg
../profiles/software-definition.cfg
../profiles/common.cfg
../xpdf/buildout.cfg
../imagemagick/buildout.cfg
../file/buildout.cfg
../pdftk/buildout.cfg
../ffmpeg/buildout.cfg
../python-2.6/buildout.cfg
../libreoffice-bin/buildout.cfg
../lxml-python/buildout.cfg
python = software_definition
versions = versions
parts =
instance_template
cloudooo
imagemagick
instance-egg
libreoffice-bin
file
xpdf
pdftk
ffmpeg
python2.6
bootstrap2.6
cloudooo-packages =
cloudooo.handler.ooo
cloudooo.handler.pdf
cloudooo.handler.ffmpeg
cloudooo.handler.imagemagick
cloudooo
sources = sources
[sources]
# Include information related to official cloudooo source code.
cloudooo = git http://git.erp5.org/repos/cloudooo.git
[instance-egg]
recipe = zc.recipe.egg
[lxml-python]
python = python2.6
eggs =
erp5.recipe.cloudoooinstance
z3c.recipe.mkdir
${buildout:cloudooo-packages}
[cloudooo]
recipe = zc.recipe.egg
python = python2.6
interpreter = pycloudoo
scripts =
eggs =
${lxml-python:egg}
collective.recipe.supervisor
plone.recipe.command
erp5.extension.sectionextender
supervisor
${buildout:cloudooo-packages}
[software_definition]
software_home = ${buildout:directory}
executable = ${python2.6:executable}
cloudooo
PasteScript
scripts =
paster=cloudooo_paster
component/dropbear/buildout.cfg
View file @
f4f72d6b
...
...
@@ -32,6 +32,13 @@ url = ${:_profile_base_location_}/${:filename}
filename = no-shell-checking.patch
download-only = true
[dropbear-static_build_fix.patch]
recipe = hexagonit.recipe.download
md5sum = 6e0ccc1949dfa31b4bc3951b9bb6472e
url = ${:_profile_base_location_}/${:filename}
filename = dropbear-0.53.1-static_build_fix.patch
download-only = true
[dropbear]
recipe = hexagonit.recipe.cmmi
md5sum = 0284ea239083f04c8b874e08e1aca243
...
...
@@ -52,6 +59,7 @@ patches=
${dropbear-userspace-patch:location}/${dropbear-userspace-patch:filename}
${dropbear-ipv6-patch:location}/${dropbear-ipv6-patch:filename}
${dropbear-no-shell-check-patch:location}/${dropbear-no-shell-check-patch:filename}
${dropbear-static_build_fix.patch:location}/${dropbear-static_build_fix.patch:filename}
patch-options=
-p1
component/dropbear/dropbear-0.53.1-static_build_fix.patch
0 → 100644
View file @
f4f72d6b
--- a/Makefile.in 2012-02-13 18:01:23.505279581 +0100
+++ b/Makefile.in 2012-02-13 18:04:17.070140233 +0100
@@ -77,7 +77,7 @@
INSTALL=@INSTALL@
CPPFLAGS=@CPPFLAGS@
CFLAGS+=-I. -I$(srcdir) $(CPPFLAGS) @CFLAGS@
-LIBS+=@LIBS@
+LIBS+=@CRYPTLIB@ @LIBS@
LDFLAGS=@LDFLAGS@
EXEEXT=@EXEEXT@
component/slapos/buildout.cfg
View file @
f4f72d6b
...
...
@@ -123,14 +123,14 @@ hexagonit.recipe.cmmi = 1.5.0
lxml = 2.3.3
meld3 = 0.6.8
netaddr = 0.7.6
slapos.core = 0.2
2
slapos.core = 0.2
3
slapos.libnetworkcache = 0.12
xml-marshaller = 0.9.7
z3c.recipe.scripts = 1.0.1
zc.recipe.egg = 1.3.2
# Required by:
# slapos.core==0.2
2
# slapos.core==0.2
3
Flask = 0.8
# Required by:
...
...
@@ -138,11 +138,11 @@ Flask = 0.8
hexagonit.recipe.download = 1.5.0
# Required by:
# slapos.core==0.2
2
# slapos.core==0.2
3
netifaces = 0.8
# Required by:
# slapos.core==0.2
2
# slapos.core==0.2
3
# slapos.libnetworkcache==0.12
# supervisor==3.0a12
# zc.buildout==1.6.0-dev-SlapOS-004
...
...
@@ -150,9 +150,9 @@ netifaces = 0.8
setuptools = 0.6c12dev-r88846
# Required by:
# slapos.core==0.2
2
# slapos.core==0.2
3
supervisor = 3.0a12
# Required by:
# slapos.core==0.2
2
# slapos.core==0.2
3
zope.interface = 3.8.0
setup.py
View file @
f4f72d6b
...
...
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
import
glob
import
os
version
=
'0.
39-dev
'
version
=
'0.
40.1
'
name
=
'slapos.cookbook'
long_description
=
open
(
"README.txt"
).
read
()
+
"
\
n
"
+
\
open
(
"CHANGES.txt"
).
read
()
+
"
\
n
"
...
...
@@ -40,6 +40,7 @@ setup(name=name,
zip_safe
=
True
,
entry_points
=
{
'zc.buildout'
:
[
'apache.frontend = slapos.recipe.apache_frontend:Recipe'
,
'apachephp = slapos.recipe.apachephp:Recipe'
,
'apacheproxy = slapos.recipe.apacheproxy:Recipe'
,
'apache.zope.backend = slapos.recipe.apache_zope_backend:Recipe'
,
...
...
slapos/recipe/README.apache_frontend.txt
0 → 100644
View file @
f4f72d6b
apache_frontend
==========
Frontend using Apache, allowing to rewrite and proxy URLs like myinstance.myfrontenddomainname.com to real IP/URL of myinstance.
\ No newline at end of file
slapos/recipe/README.helloworld.txt
deleted
100644 → 0
View file @
d2562e4b
helloworld
==========
It only installs a dummy wrapper saying "Hello World!" and sends to the master an "HelloWorld" parameter.
slapos/recipe/apache_frontend/__init__.py
0 → 100644
View file @
f4f72d6b
This diff is collapsed.
Click to expand it.
slapos/recipe/apache_frontend/certificate_authority.py
0 → 100755
View file @
f4f72d6b
import
os
import
subprocess
import
time
import
ConfigParser
import
uuid
def
popenCommunicate
(
command_list
,
input
=
None
):
subprocess_kw
=
dict
(
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
STDOUT
)
if
input
is
not
None
:
subprocess_kw
.
update
(
stdin
=
subprocess
.
PIPE
)
popen
=
subprocess
.
Popen
(
command_list
,
**
subprocess_kw
)
result
=
popen
.
communicate
(
input
)[
0
]
if
popen
.
returncode
is
None
:
popen
.
kill
()
if
popen
.
returncode
!=
0
:
raise
ValueError
(
'Issue during calling %r, result was:
\
n
%s'
%
(
command_list
,
result
))
return
result
class
CertificateAuthority
:
def
__init__
(
self
,
key
,
certificate
,
openssl_binary
,
openssl_configuration
,
request_dir
):
self
.
key
=
key
self
.
certificate
=
certificate
self
.
openssl_binary
=
openssl_binary
self
.
openssl_configuration
=
openssl_configuration
self
.
request_dir
=
request_dir
def
checkAuthority
(
self
):
file_list
=
[
self
.
key
,
self
.
certificate
]
ca_ready
=
True
for
f
in
file_list
:
if
not
os
.
path
.
exists
(
f
):
ca_ready
=
False
break
if
ca_ready
:
return
for
f
in
file_list
:
if
os
.
path
.
exists
(
f
):
os
.
unlink
(
f
)
try
:
# no CA, let us create new one
popenCommunicate
([
self
.
openssl_binary
,
'req'
,
'-nodes'
,
'-config'
,
self
.
openssl_configuration
,
'-new'
,
'-x509'
,
'-extensions'
,
'v3_ca'
,
'-keyout'
,
self
.
key
,
'-out'
,
self
.
certificate
,
'-days'
,
'10950'
],
# Authority name will be random, so no instance has the same issuer
'Certificate Authority %s
\
n
'
%
uuid
.
uuid1
())
except
:
try
:
for
f
in
file_list
:
if
os
.
path
.
exists
(
f
):
os
.
unlink
(
f
)
except
:
# do not raise during cleanup
pass
raise
def
_checkCertificate
(
self
,
common_name
,
key
,
certificate
):
file_list
=
[
key
,
certificate
]
ready
=
True
for
f
in
file_list
:
if
not
os
.
path
.
exists
(
f
):
ready
=
False
break
if
ready
:
return
False
for
f
in
file_list
:
if
os
.
path
.
exists
(
f
):
os
.
unlink
(
f
)
csr
=
certificate
+
'.csr'
try
:
popenCommunicate
([
self
.
openssl_binary
,
'req'
,
'-config'
,
self
.
openssl_configuration
,
'-nodes'
,
'-new'
,
'-keyout'
,
key
,
'-out'
,
csr
,
'-days'
,
'3650'
],
common_name
+
'
\
n
'
)
try
:
popenCommunicate
([
self
.
openssl_binary
,
'ca'
,
'-batch'
,
'-config'
,
self
.
openssl_configuration
,
'-out'
,
certificate
,
'-infiles'
,
csr
])
finally
:
if
os
.
path
.
exists
(
csr
):
os
.
unlink
(
csr
)
except
:
try
:
for
f
in
file_list
:
if
os
.
path
.
exists
(
f
):
os
.
unlink
(
f
)
except
:
# do not raise during cleanup
pass
raise
else
:
return
True
def
checkRequestDir
(
self
):
for
request_file
in
os
.
listdir
(
self
.
request_dir
):
parser
=
ConfigParser
.
RawConfigParser
()
parser
.
readfp
(
open
(
os
.
path
.
join
(
self
.
request_dir
,
request_file
),
'r'
))
if
self
.
_checkCertificate
(
parser
.
get
(
'certificate'
,
'name'
),
parser
.
get
(
'certificate'
,
'key_file'
),
parser
.
get
(
'certificate'
,
'certificate_file'
)):
print
'Created certificate %r'
%
parser
.
get
(
'certificate'
,
'name'
)
def
runCertificateAuthority
(
args
):
ca_conf
=
args
[
0
]
ca
=
CertificateAuthority
(
ca_conf
[
'key'
],
ca_conf
[
'certificate'
],
ca_conf
[
'openssl_binary'
],
ca_conf
[
'openssl_configuration'
],
ca_conf
[
'request_dir'
])
while
True
:
ca
.
checkAuthority
()
ca
.
checkRequestDir
()
time
.
sleep
(
60
)
slapos/recipe/apache_frontend/template/apache.conf.in
0 → 100644
View file @
f4f72d6b
# Apache configuration file for Zope
# Automatically generated
# Basic server configuration
PidFile "%(pid_file)s"
LockFile "%(lock_file)s"
ServerName %(server_name)s
DocumentRoot %(document_root)s
%(listen)s
ServerAdmin %(server_admin)s
DefaultType text/plain
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
# SSL Configuration
%(ssl_snippet)s
# Log configuration
ErrorLog "%(error_log)s"
LogLevel warn
LogFormat "%%h %%{REMOTE_USER}i %%l %%u %%t \"%%r\" %%>s %%b \"%%{Referer}i\" \"%%{User-Agent}i\"" combined
LogFormat "%%h %%{REMOTE_USER}i %%l %%u %%t \"%%r\" %%>s %%b" common
CustomLog "%(access_log)s" common
# Directory protection
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
</Directory>
%(path_enable)s
# Rewrite part
RewriteEngine On
# Define the two rewritemaps : one for zope, one generic
RewriteMap apachemapzope txt:%(apachemapzope_path)s
RewriteMap apachemapgeneric txt:%(apachemap_path)s
# First, we check if we have a zope backend server
# If so, let's use Virtual Host Daemon rewrite
#RewriteCond ${apachemapzope:%%{SERVER_NAME}} >""
#RewriteRule ^/(\w+)($|/.*) ${apachemapzope:$1}/VirtualHostBase/https/%(apache_domain)s:%(port)s/VirtualHostRoot/_vh_$1$2 [L,P]
# If we have generic backend server, let's rewrite without virtual host daemon
RewriteCond ${apachemapgeneric:%%{SERVER_NAME}} >""
RewriteRule ^/(.*)$ ${apachemapgeneric:%%{SERVER_NAME}}/$1 [L,P]
# If nothing exist : put a nice error
ErrorDocument 404 /notfound.html
# List of modules
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 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
LoadModule antiloris_module modules/mod_antiloris.so
slapos/recipe/apache_frontend/template/apache.conf.path-protected.in
0 → 100644
View file @
f4f72d6b
# Path protected
<Location %(path)s>
Order Deny,Allow
Allow from %(access_control_string)s
</Location>
slapos/recipe/apache_frontend/template/apache.location-snippet.conf.in
0 → 100644
View file @
f4f72d6b
<Location %(location)s>
Order Deny,Allow
Deny from all
Allow from %(allow_string)s
</Location>
slapos/recipe/apache_frontend/template/apache.ssl-snippet.conf.in
0 → 100644
View file @
f4f72d6b
SSLEngine on
SSLProxyEngine on
SSLCertificateFile %(login_certificate)s
SSLCertificateKeyFile %(login_key)s
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
slapos/recipe/apache_frontend/template/logrotate_entry.in
0 → 100644
View file @
f4f72d6b
%(file_list)s {
daily
dateext
rotate 30
compress
notifempty
sharedscripts
create
postrotate
%(postrotate)s
endscript
olddir %(olddir)s
}
slapos/recipe/apache_frontend/template/notfound.html
0 → 100644
View file @
f4f72d6b
<html>
<head>
<title>
Instance not found
</title>
</head>
<body>
<h1>
This instance has not been found.
</h1>
<p>
If this error persists, please check your instance URL and status on SlapOS Master.
</p>
</body>
</html>
slapos/recipe/apache_frontend/template/openssl.cnf.ca.in
0 → 100644
View file @
f4f72d6b
This diff is collapsed.
Click to expand it.
slapos/recipe/apache_frontend/template/stunnel.conf.entry.in
0 → 100644
View file @
f4f72d6b
[%(name)s]
accept = %(public_ip)s:%(public_port)s
connect = %(private_ip)s:%(private_port)s
slapos/recipe/apache_frontend/template/stunnel.conf.in
0 → 100644
View file @
f4f72d6b
foreground = yes
output = %(log)s
pid = %(pid_file)s
syslog = no
client = yes
CApath = %(ca_path)s
key = %(key)s
CRLpath = %(ca_crl)s
cert = %(cert)s
sslVersion = SSLv3
socket = l:TCP_NODELAY=1
socket = r:TCP_NODELAY=1
%(entry_str)s
slapos/recipe/apache_frontend/template/varnish.vcl.in
0 → 100644
View file @
f4f72d6b
# This is a basic VCL configuration file for varnish. See the vcl(7)
# man page for details on VCL syntax and semantics.
#
# Default backend definition. Set this to point to your content
# server.
#
backend default {
.host = "%(backend_host)s";
.port = "%(backend_port)s";
.probe = {
.url = "/";
.timeout = 10s;
.interval = 10s;
.window = 4;
.threshold = 3;
}
}
#
# Below is a commented-out copy of the default VCL logic. If you
# redefine any of these subroutines, the built-in logic will be
# appended to your code.
#
# sub vcl_recv {
# if (req.http.x-forwarded-for) {
# set req.http.X-Forwarded-For =
# req.http.X-Forwarded-For ", " client.ip;
# } else {
# set req.http.X-Forwarded-For = client.ip;
# }
# if (req.request != "GET"
&&
# req.request != "HEAD"
&&
# req.request != "PUT"
&&
# req.request != "POST"
&&
# req.request != "TRACE"
&&
# req.request != "OPTIONS"
&&
# req.request != "DELETE") {
# /* Non-RFC2616 or CONNECT which is weird. */
# return (pipe);
# }
# if (req.request != "GET"
&&
req.request != "HEAD") {
# /* We only deal with GET and HEAD by default */
# return (pass);
# }
# if (req.http.Authorization || req.http.Cookie) {
# /* Not cacheable by default */
# return (pass);
# }
# return (lookup);
# }
sub vcl_recv {
if (req.http.cache-control ~ "no-cache") {
purge_url(req.url);
}
if (req.url ~ "\.(css|js|ico)$") {
unset req.http.cookie;
}
# remove bogus cookies
if (req.http.Cookie) {
set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__utm.=[^;]+;? *", "\1");
set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__ac_name=\x22\x22;? *", "\1");
set req.http.Cookie = regsuball(req.http.Cookie, "(^|; ) *__ac=\x22Og.3D.3D\x22;? *", "\1");
}
if (req.http.Cookie == "") {
remove req.http.Cookie;
}
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
req.http.X-Forwarded-For ", " client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
if (req.request != "GET"
&&
req.request != "HEAD"
&&
req.request != "PUT"
&&
req.request != "POST"
&&
req.request != "TRACE"
&&
req.request != "OPTIONS"
&&
req.request != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
if (req.request != "GET"
&&
req.request != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization) {
/* Not cacheable by default */
return (pass);
}
if (req.http.Cookie
&&
req.http.Cookie ~ "(^|; ) *__ac=") {
/* Not cacheable for authorised users,
but KM images are cacheable */
if (!(req.url ~ "/km_img/.*\.(png|gif)$")) {
return (pass);
}
}
# XXX login form can defer based on __ac_name cookie value
if (req.url ~ "/(login_form|WebSite_viewLoginDialog)($|\?)") {
return (pass);
}
if (req.backend.healthy) {
set req.grace = 1h;
} else {
set req.grace = 1w;
}
return (lookup);
}
#
# sub vcl_pipe {
# # Note that only the first request to the backend will have
# # X-Forwarded-For set. If you use X-Forwarded-For and want to
# # have it set for all requests, make sure to have:
# # set req.http.connection = "close";
# # here. It is not set by default as it might break some broken web
# # applications, like IIS with NTLM authentication.
# return (pipe);
# }
#
# sub vcl_pass {
# return (pass);
# }
#
# sub vcl_hash {
# set req.hash += req.url;
# if (req.http.host) {
# set req.hash += req.http.host;
# } else {
# set req.hash += server.ip;
# }
# return (hash);
# }
#
# sub vcl_hit {
# if (!obj.cacheable) {
# return (pass);
# }
# return (deliver);
# }
#
# sub vcl_miss {
# return (fetch);
# }
#
# sub vcl_fetch {
# if (!beresp.cacheable) {
# return (pass);
# }
# if (beresp.http.Set-Cookie) {
# return (pass);
# }
# return (deliver);
# }
sub vcl_fetch {
# we only cache 200 (OK) and 304 (Not Modified) responses.
if (beresp.status != 200
&&
beresp.status != 304) {
set beresp.cacheable = false;
}
if (beresp.http.cache-control ~ "no-cache") {
set beresp.cacheable = false;
}
if (!beresp.cacheable) {
unset beresp.http.expires;
set beresp.http.cache-control = "no-cache";
return (pass);
}
# we don't care haproxy's cookie.
if (beresp.http.Set-Cookie
&&
beresp.http.Set-Cookie !~ "^SERVERID=[^;]+; path=/$") {
return (pass);
}
if (req.url ~ "\.(css|js|ico)$") {
unset beresp.http.set-cookie;
set beresp.http.cache-control = regsub(beresp.http.cache-control, "^", "public,");
set beresp.http.cache-control = regsub(beresp.http.cache-control, ",$", "");
}
# remove some headers added by caching policy manager to avoid
# '304 Not Modified' in case of login
<->
logout switching.
if (beresp.http.content-type ~ "^text/html") {
unset beresp.http.last-modified;
}
if (beresp.cacheable) {
/* Remove Expires from backend, it's not long enough */
unset beresp.http.expires;
/* Set the clients TTL on this object */
set beresp.http.cache-control = "max-age = 900";
/* Set how long Varnish will keep it */
set beresp.ttl = 1w;
/* marker for vcl_deliver to reset Age: */
set beresp.http.magicmarker = "1";
}
set beresp.grace = 1w;
return (deliver);
}
#
# sub vcl_deliver {
# return (deliver);
# }
sub vcl_deliver {
if (resp.http.magicmarker) {
/* Remove the magic marker */
unset resp.http.magicmarker;
/* By definition we have a fresh object */
set resp.http.age = "0";
}
if (obj.hits > 0) {
set resp.http.X-Cache = obj.hits;
} else {
set resp.http.X-Cache = "MISS";
}
return (deliver);
}
#
# sub vcl_error {
# set obj.http.Content-Type = "text/html; charset=utf-8";
# synthetic {"
#
<?xml version="1.0" encoding="utf-8"?>
#
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
#
<html>
#
<head>
#
<title>
"} obj.status " " obj.response {"
</title>
#
</head>
#
<body>
#
<h1>
Error "} obj.status " " obj.response {"
</h1>
#
<p>
"} obj.response {"
</p>
#
<h3>
Guru Meditation:
</h3>
#
<p>
XID: "} req.xid {"
</p>
#
<hr>
#
<p>
Varnish cache server
</p>
#
</body>
#
</html>
# "};
# return (deliver);
# }
slapos/recipe/helloworld.py
deleted
100644 → 0
View file @
d2562e4b
##############################################################################
#
# Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from
slapos.recipe.librecipe
import
BaseSlapRecipe
class
Recipe
(
BaseSlapRecipe
):
def
_install
(
self
):
parameter_dict
=
self
.
computer_partition
.
getInstanceParameterDict
()
dummy_wrapper
=
self
.
createRunningWrapper
(
'dummy'
,
"""#!/bin/sh
while [ true ]
do
sleep 10
echo "Hello World!"
done"""
)
self
.
computer_partition
.
setConnectionDict
(
dict
(
hello_world
=
"Hello World!"
,
))
return
[
dummy_wrapper
]
\ No newline at end of file
slapos/recipe/pulse2/__init__.py
View file @
f4f72d6b
...
...
@@ -267,7 +267,7 @@ class Recipe(BaseSlapRecipe):
memcached_ip
=
config
[
'memcached_ip'
],
memcached_port
=
config
[
'memcached_port'
])
def
createHtdocs
(
self
,
source
,
document_root
):
def
createHtdocs
(
self
,
source
,
document_root
):
source
=
self
.
options
[
'source'
].
strip
()
document_root
=
self
.
createDataDirectory
(
'htdocs'
)
for
p
in
os
.
listdir
(
document_root
):
...
...
software/apache-frontend/instance.cfg
0 → 100644
View file @
f4f72d6b
[buildout]
parts =
instance
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[instance]
recipe = ${instance-recipe:egg}:${instance-recipe:module}
httpd_binary = ${apache:location}/bin/httpd
logrotate_binary = ${logrotate:location}/usr/sbin/logrotate
openssl_binary = ${openssl:location}/bin/openssl
dcrond_binary = ${dcron:location}/sbin/crond
varnishd_binary = ${varnish-2.1:location}/sbin/varnishd
stunnel_binary = ${stunnel:location}/bin/stunnel
rdiff_backup_binary = ${buildout:bin-directory}/rdiff-backup
gcc_binary = ${gcc-java-minimal:location}/bin/gcc
binutils_directory = ${binutils:location}/bin/
software/apache-frontend/software.cfg
0 → 100644
View file @
f4f72d6b
[buildout]
versions = versions
extends =
../../component/binutils/buildout.cfg
../../component/gcc/buildout.cfg
../../component/lxml-python/buildout.cfg
../../component/apache/buildout.cfg
../../component/stunnel/buildout.cfg
../../component/varnish/buildout.cfg
../../component/dcron/buildout.cfg
../../component/logrotate/buildout.cfg
../../component/rdiff-backup/buildout.cfg
../../stack/slapos.cfg
parts =
template
binutils
gcc-java-minimal
apache
apache-antiloris
stunnel
varnish-2.1
dcron
logrotate
rdiff-backup
# Buildoutish
eggs
instance-recipe-egg
[instance-recipe]
# Note: In case if specific instantiation recipe is used this is the place to
# put its name
egg = slapos.cookbook
module = apache.frontend
[instance-recipe-egg]
recipe = zc.recipe.egg
eggs = ${instance-recipe:egg}
[eggs]
recipe = zc.recipe.egg
eggs =
${lxml-python:egg}
[template]
# Default template for apache instance.
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg
md5sum = 17180caef7d1c477fbb037d28b705e8b
output = ${buildout:directory}/template.cfg
mode = 0644
[versions]
# Use SlapOS patched zc.buildout
zc.buildout = 1.6.0-dev-SlapOS-004
Jinja2 = 2.6
Werkzeug = 0.8.3
buildout-versions = 1.7
hexagonit.recipe.cmmi = 1.5.0
meld3 = 0.6.8
rdiff-backup = 1.0.5
slapos.recipe.template = 2.2
slapos.cookbook = 0.40.1
# Required by:
# slapos.core==0.23
Flask = 0.8
# Required by:
# slapos.cookbook==0.40.1
PyXML = 0.8.4
# Required by:
# hexagonit.recipe.cmmi==1.5.0
hexagonit.recipe.download = 1.5.0
# Required by:
# slapos.cookbook==0.40.1
inotifyx = 0.2.0
# Required by:
# slapos.cookbook==0.40.1
# slapos.core==0.23
# xml-marshaller==0.9.7
lxml = 2.3.3
# Required by:
# slapos.cookbook==0.40.1
netaddr = 0.7.6
# Required by:
# slapos.core==0.23
netifaces = 0.8
# Required by:
# slapos.cookbook==0.40.1
# slapos.core==0.23
# zc.buildout==1.6.0-dev-SlapOS-004
# zc.recipe.egg==1.3.2
setuptools = 0.6c12dev-r88846
# Required by:
# slapos.cookbook==0.40.1
slapos.core = 0.23
# Required by:
# slapos.core==0.23
supervisor = 3.0a12
# Required by:
# slapos.cookbook==0.40.1
xml-marshaller = 0.9.7
# Required by:
# slapos.cookbook==0.40.1
zc.recipe.egg = 1.3.2
# Required by:
# slapos.core==0.23
zope.interface = 3.8.0
[networkcache]
# Cedric de Saint Martin signature certificate
signature-certificate-list =
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAO4V/jiMoICoMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtMjMyMCAXDTEyMDIxNjExMTAyM1oYDzIxMTIwMTIzMTExMDIzWjAT
MREwDwYDVQQDDAhDT01QLTIzMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
wi/3Z8W9pUiegUXIk/AiFDQ0UJ4JFAwjqr+HSRUirlUsHHT+8DzH/hfcTDX1I5BB
D1ADk+ydXjMm3OZrQcXjn29OUfM5C+g+oqeMnYQImN0DDQIOcUyr7AJc4xhvuXQ1
P2pJ5NOd3tbd0kexETa1LVhR6EgBC25LyRBRae76qosCAwEAAaNQME4wHQYDVR0O
BBYEFMDmW9aFy1sKTfCpcRkYnP6zUd1cMB8GA1UdIwQYMBaAFMDmW9aFy1sKTfCp
cRkYnP6zUd1cMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAskbFizHr
b6d3iIyN+wffxz/V9epbKIZVEGJd/6LrTdLiUfJPec7FaxVCWNyKBlCpINBM7cEV
Gn9t8mdVQflNqOlAMkOlUv1ZugCt9rXYQOV7rrEYJBWirn43BOMn9Flp2nibblby
If1a2ZoqHRxoNo2yTmm7TSYRORWVS+vvfjY=
-----END CERTIFICATE-----
software/cloudooo/development.cfg
0 → 100644
View file @
f4f72d6b
[buildout]
extends = software.cfg
auto-checkout = cloudooo
software/helloworld/instance.cfg
deleted
100644 → 0
View file @
d2562e4b
[buildout]
parts =
dummy
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
[dummy]
recipe = slapos.recipe.dummy
software/helloworld/software.cfg
deleted
100644 → 0
View file @
d2562e4b
[buildout]
extensions +=
mr.developer
# activates mr.developer
auto-checkout = *
versions = versions
find-links += http://www.nexedi.org/static/packages/source/slapos.buildout/
parts =
template
eggs
unzip = true
[sources]
# XXX-Cedric : either publish the egg or use mr.developer properly, but DELETE
# This repository and use slapos.recipe.helloworld.
slapos.recipe.dummy = git git://github.com/WaterCooled/slapos.recipe.dummy.git
[versions]
zc.buildout = 1.5.3-dev-SlapOS-001
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg
output = ${buildout:directory}/template.cfg
mode = 0644
[eggs]
recipe = zc.recipe.egg
#eggs = slapos.recipe.helloworld
eggs = slapos.recipe.dummy
software/slaprunner/software.cfg
View file @
f4f72d6b
...
...
@@ -3,25 +3,18 @@ extensions =
buildout-versions
extends =
../../stack/slapos.cfg
../../stack/flask.cfg
../../stack/shacache-client.cfg
../../component/dropbear/buildout.cfg
../../component/git/buildout.cfg
develop =
${:parts-directory}/slapos.cookbook
parts =
template
slapos.cookbook
check-local-eggs
eggs
instance-recipe-egg
dropbear
find-links +=
http://www.nexedi.org/static/packages/source/slapos.buildout/
versions = versions
[instance-recipe]
...
...
@@ -40,69 +33,66 @@ output = ${buildout:directory}/template.cfg
mode = 0644
md5sum = cd69efd5c3a7e9adca7387b9a401590a
[slapos.cookbook]
# use official egg from pypi when it is released
recipe = plone.recipe.command
stop-on-error = true
commit = ce891b5070073d4dac9e21b089b8e662c7a9e0bd
repository = http://git.erp5.org/repos/slapos.git
location = ${buildout:parts-directory}/${:_buildout_section_name_}
git-binary = ${git:location}/bin/git
command = export GIT_SSL_NO_VERIFY=true; (${:git-binary} clone --quiet ${:repository} ${:location} && cd ${:location} && ${:git-binary} reset --hard ${:commit}) || (rm -fr ${:location}; exit 1)
update-command =
[check-local-eggs]
recipe = plone.recipe.command
stop-on-error = true
update-command = ${:command}
command = grep parts ${buildout:develop-eggs-directory}/slapos.cookbook.egg-link
depends = ${instance-recipe:egg}
[eggs]
eggs +=
slapos.libnetworkcache
slapos.toolbox
slapos.core
[networkcache]
# signature certificates of the following uploaders.
# Cedric de Saint Martin
signature-certificate-list =
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAO4V/jiMoICoMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtMjMyMCAXDTEyMDIxNjExMTAyM1oYDzIxMTIwMTIzMTExMDIzWjAT
MREwDwYDVQQDDAhDT01QLTIzMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
wi/3Z8W9pUiegUXIk/AiFDQ0UJ4JFAwjqr+HSRUirlUsHHT+8DzH/hfcTDX1I5BB
D1ADk+ydXjMm3OZrQcXjn29OUfM5C+g+oqeMnYQImN0DDQIOcUyr7AJc4xhvuXQ1
P2pJ5NOd3tbd0kexETa1LVhR6EgBC25LyRBRae76qosCAwEAAaNQME4wHQYDVR0O
BBYEFMDmW9aFy1sKTfCpcRkYnP6zUd1cMB8GA1UdIwQYMBaAFMDmW9aFy1sKTfCp
cRkYnP6zUd1cMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAskbFizHr
b6d3iIyN+wffxz/V9epbKIZVEGJd/6LrTdLiUfJPec7FaxVCWNyKBlCpINBM7cEV
Gn9t8mdVQflNqOlAMkOlUv1ZugCt9rXYQOV7rrEYJBWirn43BOMn9Flp2nibblby
If1a2ZoqHRxoNo2yTmm7TSYRORWVS+vvfjY=
-----END CERTIFICATE-----
[versions]
# Use SlapOS patched zc.buildout
zc.buildout = 1.6.0-dev-SlapOS-003
# Pinned to old version (2.4 does not compile well everywhere)
pycrypto = 2.3
Jinja2 = 2.6
Werkzeug = 0.8.
2
apache-libcloud = 0.
7.1
Werkzeug = 0.8.
3
apache-libcloud = 0.
8.0
async = 0.6.1
buildout-versions = 1.7
gitdb = 0.5.4
hexagonit.recipe.cmmi = 1.5.0
meld3 = 0.6.8
plone.recipe.command = 1.1
slapos.libnetworkcache = 0.11
pycrypto = 2.5
slapos.cookbook = 0.39
slapos.libnetworkcache = 0.12
slapos.recipe.template = 2.2
slapos.toolbox = 0.1
6
slapos.toolbox = 0.1
8
smmap = 0.8.2
# Required by:
# slapos.core==0.2
1
# slapos.core==0.2
2
Flask = 0.8
# Required by:
# slapos.toolbox==0.1
6
# slapos.toolbox==0.1
8
GitPython = 0.3.2.RC1
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.cookbook==0.39
PyXML = 0.8.4
# Required by:
# slapos.toolbox==0.1
6
# slapos.toolbox==0.1
8
atomize = 0.1.1
# Required by:
# slapos.toolbox==0.1
6
# slapos.toolbox==0.1
8
feedparser = 5.1
# Required by:
...
...
@@ -110,36 +100,36 @@ feedparser = 5.1
hexagonit.recipe.download = 1.5.0
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.cookbook==0.39
inotifyx = 0.2.0
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.core==0.2
1
# slapos.cookbook==0.39
# slapos.core==0.2
2
# xml-marshaller==0.9.7
lxml = 2.3.3
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.cookbook==0.39
netaddr = 0.7.6
# Required by:
# slapos.core==0.2
1
netifaces = 0.
6
# slapos.core==0.2
2
netifaces = 0.
8
# Required by:
# slapos.toolbox==0.1
6
# slapos.toolbox==0.1
8
paramiko = 1.7.7.1
# Required by:
# slapos.toolbox==0.1
6
# slapos.toolbox==0.1
8
psutil = 0.4.1
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.core==0.2
1
# slapos.libnetworkcache==0.1
1
# slapos.toolbox==0.1
6
# slapos.cookbook==0.39
# slapos.core==0.2
2
# slapos.libnetworkcache==0.1
2
# slapos.toolbox==0.1
8
# supervisor==3.0a12
# zc.buildout==1.6.0-dev-SlapOS-003
# zc.recipe.egg==1.3.2
...
...
@@ -147,21 +137,21 @@ psutil = 0.4.1
setuptools = 0.6c12dev-r88846
# Required by:
# slapos.cookbook==0.39
-dev
slapos.core = 0.2
1
# slapos.cookbook==0.39
slapos.core = 0.2
2
# Required by:
# slapos.core==0.2
1
# slapos.core==0.2
2
supervisor = 3.0a12
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.cookbook==0.39
xml-marshaller = 0.9.7
# Required by:
# slapos.cookbook==0.39
-dev
# slapos.cookbook==0.39
zc.recipe.egg = 1.3.2
# Required by:
# slapos.core==0.2
1
# slapos.core==0.2
2
zope.interface = 3.8.0
stack/cloudooo.cfg
View file @
f4f72d6b
...
...
@@ -20,6 +20,7 @@ extends =
../component/pdftk/buildout.cfg
../component/ffmpeg/buildout.cfg
../component/file/buildout.cfg
../component/cloudooo/buildout.cfg
versions = versions
...
...
@@ -64,19 +65,6 @@ python = python2.6
version = 2
section = python2.7
[lxml-python]
python = python2.6
[cloudooo]
recipe = zc.recipe.egg
python = python2.6
eggs =
${lxml-python:egg}
cloudooo
PasteScript
scripts =
paster=cloudooo_paster
[versions]
# Use SlapOS patched zc.buildout
zc.buildout = 1.5.3-dev-SlapOS-001
stack/lamp.cfg
View file @
f4f72d6b
...
...
@@ -13,6 +13,7 @@ allow-hosts =
dist.repoze.org
effbot.org
github.com
launchpad.net
peak.telecommunity.com
psutil.googlecode.com
www.dabeaz.com
...
...
stack/slapos.cfg
0 → 100644
View file @
f4f72d6b
# This stack list all parameters used in every Software Release or other stack.
# Software Releases or Stacks can safely extend this stack.
[buildout]
# Generate list of automatically chosen eggs version
extensions +=
buildout-versions
# Use shacache
extends =
shacache-client.cfg
# Separate from site eggs
allowed-eggs-from-site-packages =
include-site-packages = false
exec-sitecustomize = false
# Add location for modified non-official slapos.buildout
find-links +=
http://www.nexedi.org/static/packages/source/slapos.buildout/
# Use only quite well working sites.
allow-hosts +=
*.nexedi.org
*.python.org
*.sourceforge.net
alastairs-place.net
dist.repoze.org
effbot.org
github.com
peak.telecommunity.com
psutil.googlecode.com
www.dabeaz.com
www.owlfish.com
launchpad.net
# XXX: Workaround of SlapOS limitation
# Unzippig of eggs is required, as SlapOS do not yet provide nicely working
# development / fast switching environment for whole software
unzip = true
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment