Fixes on webapps and websites backend execution
This commit is contained in:
parent
2a8d20910f
commit
44e8b29b43
4
TODO.md
4
TODO.md
|
@ -213,3 +213,7 @@ ssh-copy-id root@<server-address>
|
|||
|
||||
* webalizer backend on webapps and check webapps.websites.all()
|
||||
* monitor in batches doesnt work!!!
|
||||
|
||||
|
||||
* mv: cannot move `/home/marcay/webapps/webalizer/' to a subdirectory of itself, `/home/marcay/webapps/webalizer/.deleted'
|
||||
* Create utility for dealing with web paths '//', leading and ending '/'
|
||||
|
|
|
@ -31,8 +31,8 @@ class MySQLBackend(ServiceController):
|
|||
})
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'GRANT ALL PRIVILEGES ON `%(database)s`.* TO "%(username)s"@"%(host)s" %(grant)s;' \
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
|
||||
def delete(self, database):
|
||||
if database.type != database.MYSQL:
|
||||
|
@ -62,12 +62,12 @@ class MySQLUserBackend(ServiceController):
|
|||
context = self.get_context(user)
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'CREATE USER "%(username)s"@"%(host)s";' || true \
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'UPDATE mysql.user SET Password="%(password)s" WHERE User="%(username)s";' \
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
|
||||
def delete(self, user):
|
||||
if user.type != user.MYSQL:
|
||||
|
@ -75,8 +75,8 @@ class MySQLUserBackend(ServiceController):
|
|||
context = self.get_context(user)
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'DROP USER "%(username)s"@"%(host)s";' \
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
|
||||
def commit(self):
|
||||
self.append("mysql -e 'FLUSH PRIVILEGES;'")
|
||||
|
@ -99,8 +99,8 @@ class MysqlDisk(ServiceMonitor):
|
|||
context = self.get_context(db)
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'UPDATE db SET Insert_priv="N", Create_priv="N" WHERE Db="%(db_name)s";'\
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
|
||||
def recovery(self, db):
|
||||
if db.type != db.MYSQL:
|
||||
|
@ -108,8 +108,8 @@ class MysqlDisk(ServiceMonitor):
|
|||
context = self.get_context(db)
|
||||
self.append(textwrap.dedent("""\
|
||||
mysql -e 'UPDATE db SET Insert_priv="Y", Create_priv="Y" WHERE Db="%(db_name)s";'\
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
|
||||
def prepare(self):
|
||||
super(MysqlDisk, self).prepare()
|
||||
|
|
|
@ -36,8 +36,8 @@ class Bind9MasterDomainBackend(ServiceController):
|
|||
mv %(zone_path)s.tmp %(zone_path)s
|
||||
# Because bind realod will not display any fucking error
|
||||
named-checkzone -k fail -n fail %(name)s %(zone_path)s
|
||||
""" % context
|
||||
))
|
||||
""") % context
|
||||
)
|
||||
self.update_conf(context)
|
||||
|
||||
def update_conf(self, context):
|
||||
|
@ -47,13 +47,13 @@ class Bind9MasterDomainBackend(ServiceController):
|
|||
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s
|
||||
echo '%(conf)s' >> %(conf_path)s
|
||||
UPDATED=1
|
||||
}""" % context
|
||||
))
|
||||
}""") % context
|
||||
)
|
||||
# Delete ex-top-domains that are now subdomains
|
||||
self.append(textwrap.dedent("""\
|
||||
sed -i -e '/zone\s\s*".*\.%(name)s".*/,/^\s*};\s*$/d' \\
|
||||
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s""" % context
|
||||
))
|
||||
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s""") % context
|
||||
)
|
||||
if 'zone_path' in context:
|
||||
context['zone_subdomains_path'] = re.sub(r'^(.*/)', r'\1*.', context['zone_path'])
|
||||
self.append('rm -f %(zone_subdomains_path)s' % context)
|
||||
|
@ -69,19 +69,19 @@ class Bind9MasterDomainBackend(ServiceController):
|
|||
return
|
||||
self.append(textwrap.dedent("""\
|
||||
sed -e '/zone\s\s*"%(name)s".*/,/^\s*};\s*$/d' \\
|
||||
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s > %(conf_path)s.tmp""" % context
|
||||
))
|
||||
-e 'N; /^\s*\\n\s*$/d; P; D' %(conf_path)s > %(conf_path)s.tmp""") % context
|
||||
)
|
||||
self.append('diff -B -I"^\s*//" %(conf_path)s.tmp %(conf_path)s || UPDATED=1' % context)
|
||||
self.append('mv %(conf_path)s.tmp %(conf_path)s' % context)
|
||||
|
||||
def commit(self):
|
||||
""" reload bind if needed """
|
||||
self.append('[[ $UPDATED == 1 ]] && service bind9 reload')
|
||||
self.append('if [[ $UPDATED == 1 ]]; then service bind9 reload; fi')
|
||||
|
||||
def get_servers(self, domain, backend):
|
||||
""" Get related server IPs from registered backend routes """
|
||||
from orchestra.apps.orchestration.manager import router
|
||||
operation = Operation.create(backend, peration.SAVE, domain)
|
||||
operation = Operation.create(backend, domain, Operation.SAVE)
|
||||
servers = []
|
||||
for server in router.get_servers(operation):
|
||||
servers.append(server.get_ip())
|
||||
|
@ -110,7 +110,7 @@ class Bind9MasterDomainBackend(ServiceController):
|
|||
allow-transfer { %(slaves)s; };
|
||||
also-notify { %(also_notify)s };
|
||||
notify yes;
|
||||
};""" % context)
|
||||
};""") % context
|
||||
})
|
||||
return context
|
||||
|
||||
|
@ -131,7 +131,7 @@ class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
|
|||
|
||||
def commit(self):
|
||||
""" ideally slave should be restarted after master """
|
||||
self.append('[[ $UPDATED == 1 ]] && { sleep 1 && service bind9 reload; } &')
|
||||
self.append('if [[ $UPDATED == 1 ]]; then { sleep 1 && service bind9 reload; } & fi')
|
||||
|
||||
def get_masters(self, domain):
|
||||
return self.get_servers(domain, Bind9MasterDomainBackend)
|
||||
|
@ -152,6 +152,6 @@ class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
|
|||
file "%(name)s";
|
||||
masters { %(masters)s; };
|
||||
allow-notify { %(masters)s; };
|
||||
};""" % context)
|
||||
};""") % context
|
||||
})
|
||||
return context
|
||||
|
|
|
@ -33,8 +33,8 @@ class PasswdVirtualUserBackend(ServiceController):
|
|||
sed -i 's#^%(username)s:.*#%(passwd)s#' %(passwd_path)s
|
||||
else
|
||||
echo '%(passwd)s' >> %(passwd_path)s
|
||||
fi""" % context
|
||||
))
|
||||
fi""") % context
|
||||
)
|
||||
self.append("mkdir -p %(home)s" % context)
|
||||
self.append("chown %(uid)s:%(gid)s %(home)s" % context)
|
||||
|
||||
|
@ -43,7 +43,8 @@ class PasswdVirtualUserBackend(ServiceController):
|
|||
if [[ ! $(grep "^%(username)s@%(mailbox_domain)s\s" %(virtual_mailbox_maps)s) ]]; then
|
||||
echo "%(username)s@%(mailbox_domain)s\tOK" >> %(virtual_mailbox_maps)s
|
||||
UPDATED_VIRTUAL_MAILBOX_MAPS=1
|
||||
fi""" % context))
|
||||
fi""") % context
|
||||
)
|
||||
|
||||
def generate_filter(self, mailbox, context):
|
||||
self.append("doveadm mailbox create -u %(username)s Spam" % context)
|
||||
|
@ -92,7 +93,8 @@ class PasswdVirtualUserBackend(ServiceController):
|
|||
self.append(textwrap.dedent("""\
|
||||
[[ $UPDATED_VIRTUAL_MAILBOX_MAPS == 1 ]] && {
|
||||
postmap %(virtual_mailbox_maps)s
|
||||
}""" % context))
|
||||
}""") % context
|
||||
)
|
||||
|
||||
def get_context(self, mailbox):
|
||||
context = {
|
||||
|
|
|
@ -154,7 +154,7 @@ class BackendOperation(models.Model):
|
|||
"""
|
||||
if self.action == self.DELETE:
|
||||
if hasattr(self.backend, 'get_context'):
|
||||
self.backend.get_context(self.instance)
|
||||
self.backend().get_context(self.instance)
|
||||
|
||||
def backend_class(self):
|
||||
return ServiceBackend.get_backend(self.backend)
|
||||
|
|
|
@ -26,8 +26,8 @@ class SystemUserBackend(ServiceController):
|
|||
fi
|
||||
mkdir -p %(home)s
|
||||
chmod 750 %(home)s
|
||||
chown %(username)s:%(username)s %(home)s""" % context
|
||||
))
|
||||
chown %(username)s:%(username)s %(home)s""") % context
|
||||
)
|
||||
for member in settings.SYSTEMUSERS_DEFAULT_GROUP_MEMBERS:
|
||||
context['member'] = member
|
||||
self.append('usermod -a -G %(username)s %(member)s' % context)
|
||||
|
@ -40,8 +40,8 @@ class SystemUserBackend(ServiceController):
|
|||
{ sleep 2 && killall -u %(username)s -s KILL; } &
|
||||
killall -u %(username)s || true
|
||||
userdel %(username)s || true
|
||||
groupdel %(username)s || true""" % context
|
||||
))
|
||||
groupdel %(username)s || true""") % context
|
||||
)
|
||||
self.delete_home(context, user)
|
||||
|
||||
def grant_permission(self, user):
|
||||
|
@ -145,7 +145,7 @@ class FTPTraffic(ServiceMonitor):
|
|||
print sum
|
||||
}' || [[ $? == 1 ]] && true
|
||||
} | xargs echo ${OBJECT_ID}
|
||||
}""" % current_date))
|
||||
}""") % current_date)
|
||||
|
||||
def monitor(self, user):
|
||||
context = self.get_context(user)
|
||||
|
|
|
@ -53,7 +53,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
|
|||
inlines = [WebAppOptionInline]
|
||||
readonly_fields = ('account_link',)
|
||||
change_readonly_fields = ('name', 'type')
|
||||
list_prefetch_related = ('contents__website',)
|
||||
list_prefetch_related = ('content_set__website',)
|
||||
plugin = AppType
|
||||
plugin_field = 'type'
|
||||
plugin_title = _("Web application type")
|
||||
|
@ -64,7 +64,7 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
|
|||
|
||||
def display_websites(self, webapp):
|
||||
websites = []
|
||||
for content in webapp.contents.all():
|
||||
for content in webapp.content_set.all():
|
||||
website = content.website
|
||||
url = change_url(website)
|
||||
name = "%s on %s" % (website.name, content.path)
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
import pkgutil
|
||||
import textwrap
|
||||
|
||||
from .. import settings
|
||||
|
||||
|
||||
class WebAppServiceMixin(object):
|
||||
model = 'webapps.WebApp'
|
||||
directive = None
|
||||
|
||||
def create_webapp_dir(self, context):
|
||||
self.append("[[ ! -e %(app_path)s ]] && CREATED=true" % context)
|
||||
self.append("mkdir -p %(app_path)s" % context)
|
||||
self.append("chown %(user)s:%(group)s %(app_path)s" % context)
|
||||
|
||||
def set_under_construction(self, context):
|
||||
if context['under_construction_path']:
|
||||
self.append("[[ $CREATED ]] && cp -r %(under_construction_path)s %(app_path)s" % context)
|
||||
|
||||
def delete_webapp_dir(self, context):
|
||||
self.append("rm -fr %(app_path)s" % context)
|
||||
|
||||
|
@ -21,6 +28,7 @@ class WebAppServiceMixin(object):
|
|||
'type': webapp.type,
|
||||
'app_path': webapp.get_path().rstrip('/'),
|
||||
'banner': self.get_banner(),
|
||||
'under_construction_path': settings.settings.WEBAPPS_UNDER_CONSTRUCTION_PATH
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,54 +12,82 @@ from .. import settings
|
|||
class PHPFcgidBackend(WebAppServiceMixin, ServiceController):
|
||||
""" Per-webapp fcgid application """
|
||||
verbose_name = _("PHP-Fcgid")
|
||||
directive = 'fcgi'
|
||||
default_route_match = "webapp.type.endswith('-fcgi')"
|
||||
directive = 'fcgid'
|
||||
default_route_match = "webapp.type.endswith('-fcgid')"
|
||||
|
||||
def save(self, webapp):
|
||||
if not self.valid_directive(webapp):
|
||||
return
|
||||
context = self.get_context(webapp)
|
||||
self.create_webapp_dir(context)
|
||||
self.set_under_construction(context)
|
||||
self.append("mkdir -p %(wrapper_dir)s" % context)
|
||||
self.append(textwrap.dedent("""\
|
||||
{
|
||||
echo -e '%(wrapper_content)s' | diff -N -I'^\s*#' %(wrapper_path)s -
|
||||
echo -e '%(wrapper)s' | diff -N -I'^\s*#' %(wrapper_path)s -
|
||||
} || {
|
||||
echo -e '%(wrapper_content)s' > %(wrapper_path)s; UPDATED_APACHE=1
|
||||
}""" % context))
|
||||
echo -e '%(wrapper)s' > %(wrapper_path)s; UPDATED_APACHE=1
|
||||
}""") % context
|
||||
)
|
||||
self.append("chmod +x %(wrapper_path)s" % context)
|
||||
self.append("chown -R %(user)s:%(group)s %(wrapper_dir)s" % context)
|
||||
if context['cmd_options']:
|
||||
self.append(textwrap.dedent("""
|
||||
{
|
||||
echo -e '%(cmd_options)s' | diff -N -I'^\s*#' %(cmd_options_path)s -
|
||||
} || {
|
||||
echo -e '%(cmd_options)s' > %(cmd_options_path)s; UPDATED_APACHE=1
|
||||
}""" ) % context
|
||||
)
|
||||
|
||||
def delete(self, webapp):
|
||||
if not self.valid_directive(webapp):
|
||||
return
|
||||
context = self.get_context(webapp)
|
||||
self.append("rm '%(wrapper_path)s'" % context)
|
||||
self.delete_webapp_dir(context)
|
||||
|
||||
def commit(self):
|
||||
if not self.cmds:
|
||||
return
|
||||
super(PHPFcgidBackend, self).commit()
|
||||
self.append("[[ $UPDATED_APACHE == 1 ]] && { service apache2 reload; }")
|
||||
self.append('if [[ $UPDATED_APACHE == 1 ]]; then service apache2 reload; fi')
|
||||
|
||||
def get_fcgid_wrapper(self, webapp, context):
|
||||
opt = webapp.type_instance
|
||||
# Format PHP init vars
|
||||
init_vars = opt.get_php_init_vars(webapp)
|
||||
if init_vars:
|
||||
init_vars = [ '-d %s="%s"' % (k,v) for k,v in init_vars.iteritems() ]
|
||||
init_vars = ', '.join(init_vars)
|
||||
|
||||
context.update({
|
||||
'php_binary': opt.php_binary,
|
||||
'php_rc': opt.php_rc,
|
||||
'php_init_vars': init_vars,
|
||||
})
|
||||
return textwrap.dedent("""\
|
||||
#!/bin/sh
|
||||
# %(banner)s
|
||||
export PHPRC=%(php_rc)s
|
||||
exec %(php_binary)s %(php_init_vars)s""") % context
|
||||
|
||||
def get_fcgid_cmd_options(self, webapp, context):
|
||||
maps = {
|
||||
'MaxProcesses': webapp.get_options().get('processes', None),
|
||||
'IOTimeout': webapp.get_options().get('timeout', None),
|
||||
}
|
||||
cmd_options = []
|
||||
for directive, value in maps.iteritems():
|
||||
if value:
|
||||
cmd_options.append("%s %s" % (directive, value))
|
||||
if cmd_options:
|
||||
cmd_options.insert(0, 'FcgidCmdOptions %(wrapper_path)s' % context)
|
||||
return ' \\\n '.join(cmd_options)
|
||||
|
||||
def get_context(self, webapp):
|
||||
context = super(PHPFcgidBackend, self).get_context(webapp)
|
||||
init_vars = self.get_php_init_vars(webapp)
|
||||
if init_vars:
|
||||
init_vars = [ '%s="%s"' % (k,v) for k,v in init_vars ]
|
||||
init_vars = ', -d '.join(init_vars)
|
||||
context['init_vars'] = '-d %s' % init_vars
|
||||
else:
|
||||
context['init_vars'] = ''
|
||||
wrapper_path = settings.WEBAPPS_FCGID_PATH % context
|
||||
context.update({
|
||||
'wrapper_content': textwrap.dedent("""\
|
||||
#!/bin/sh
|
||||
# %(banner)s
|
||||
export PHPRC=/etc/%(type)s/cgi/
|
||||
exec /usr/bin/%(type)s-cgi %(init_vars)s""" % context),
|
||||
'wrapper': self.get_fcgid_wrapper(webapp, context),
|
||||
'wrapper_path': wrapper_path,
|
||||
'wrapper_dir': os.path.dirname(wrapper_path),
|
||||
})
|
||||
context.update({
|
||||
'cmd_options': self.get_fcgid_cmd_options(webapp, context),
|
||||
'cmd_options_path': settings.WEBAPPS_FCGID_CMD_OPTIONS_PATH % context,
|
||||
})
|
||||
return context
|
||||
|
|
|
@ -18,14 +18,15 @@ class PHPFPMBackend(WebAppServiceMixin, ServiceController):
|
|||
def save(self, webapp):
|
||||
context = self.get_context(webapp)
|
||||
self.create_webapp_dir(context)
|
||||
self.set_under_construction(context)
|
||||
self.append(textwrap.dedent("""\
|
||||
{
|
||||
echo -e '%(fpm_config)s' | diff -N -I'^\s*;;' %(fpm_path)s -
|
||||
} || {
|
||||
echo -e '%(fpm_config)s' > %(fpm_path)s
|
||||
UPDATEDFPM=1
|
||||
}""" % context
|
||||
))
|
||||
}""") % context
|
||||
)
|
||||
|
||||
def delete(self, webapp):
|
||||
context = self.get_context(webapp)
|
||||
|
@ -37,18 +38,17 @@ class PHPFPMBackend(WebAppServiceMixin, ServiceController):
|
|||
return
|
||||
super(PHPFPMBackend, self).commit()
|
||||
self.append(textwrap.dedent("""
|
||||
[[ $UPDATEDFPM == 1 ]] && {
|
||||
if [[ $UPDATEDFPM == 1 ]]; then
|
||||
service php5-fpm reload
|
||||
service php5-fpm start
|
||||
}"""))
|
||||
fi"""))
|
||||
|
||||
def get_context(self, webapp):
|
||||
if not self.valid_directive(webapp):
|
||||
return
|
||||
context = super(PHPFPMBackend, self).get_context(webapp)
|
||||
def get_fpm_config(self, webapp, context):
|
||||
context.update({
|
||||
'init_vars': self.get_php_init_vars(webapp),
|
||||
'init_vars': webapp.type_instance.get_php_init_vars(webapp),
|
||||
'fpm_port': webapp.get_fpm_port(),
|
||||
'max_children': webapp.get_options().get('processes', False),
|
||||
'request_terminate_timeout': webapp.get_options().get('timeout', False),
|
||||
})
|
||||
context['fpm_listen'] = settings.WEBAPPS_FPM_LISTEN % context
|
||||
fpm_config = Template(textwrap.dedent("""\
|
||||
|
@ -61,12 +61,18 @@ class PHPFPMBackend(WebAppServiceMixin, ServiceController):
|
|||
listen.owner = {{ user }}
|
||||
listen.group = {{ group }}
|
||||
pm = ondemand
|
||||
pm.max_children = 4
|
||||
{% for name, value in init_vars %}
|
||||
php_admin_value[{{ name | safe }}] = {{ value | safe }}{% endfor %}"""
|
||||
{% if max_children %}pm.max_children = {{ max_children }}{% endif %}
|
||||
{% if request_terminate_timeout %}request_terminate_timeout = {{ request_terminate_timeout }}{% endif %}
|
||||
{% for name, value in init_vars.iteritems %}
|
||||
php_admin_value[{{ name | safe }}] = {{ value | safe }}{% endfor %}
|
||||
"""
|
||||
))
|
||||
return fpm_config.render(Context(context))
|
||||
|
||||
def get_context(self, webapp):
|
||||
context = super(PHPFPMBackend, self).get_context(webapp)
|
||||
context.update({
|
||||
'fpm_config': fpm_config.render(Context(context)),
|
||||
'fpm_config': self.get_fpm_config(webapp, context),
|
||||
'fpm_path': settings.WEBAPPS_PHPFPM_POOL_PATH % context,
|
||||
})
|
||||
return context
|
||||
|
|
|
@ -7,17 +7,13 @@ from . import WebAppServiceMixin
|
|||
|
||||
class StaticBackend(WebAppServiceMixin, ServiceController):
|
||||
verbose_name = _("Static")
|
||||
directive = 'static'
|
||||
default_route_match = "webapp.type == 'static'"
|
||||
|
||||
def save(self, webapp):
|
||||
if not self.valid_directive(webapp):
|
||||
return
|
||||
context = self.get_context(webapp)
|
||||
self.create_webapp_dir(context)
|
||||
self.set_under_construction(context)
|
||||
|
||||
def delete(self, webapp):
|
||||
if not self.valid_directive(webapp):
|
||||
return
|
||||
context = self.get_context(webapp)
|
||||
self.delete_webapp_dir(context)
|
||||
|
|
|
@ -30,8 +30,8 @@ class WordPressBackend(WebAppServiceMixin, ServiceController):
|
|||
mkdir %(app_path)s/wp-content/uploads
|
||||
chmod 750 %(app_path)s/wp-content/uploads
|
||||
chown -R %(user)s:%(group)s %(app_path)s
|
||||
fi""" % context
|
||||
))
|
||||
fi""") % context
|
||||
)
|
||||
|
||||
def delete(self, webapp):
|
||||
context = self.get_context(webapp)
|
||||
|
|
|
@ -12,6 +12,7 @@ from orchestra.core import validators, services
|
|||
from orchestra.utils.functional import cached
|
||||
|
||||
from . import settings
|
||||
from .options import AppOption
|
||||
from .types import AppType
|
||||
|
||||
|
||||
|
@ -55,9 +56,6 @@ class WebApp(models.Model):
|
|||
opt.name: opt.value for opt in self.options.all()
|
||||
}
|
||||
|
||||
def get_fpm_port(self):
|
||||
return settings.WEBAPPS_FPM_START_PORT + self.account_id
|
||||
|
||||
def get_directive(self):
|
||||
return self.type_instance.get_directive(self)
|
||||
|
||||
|
@ -67,6 +65,9 @@ class WebApp(models.Model):
|
|||
'app_name': self.name,
|
||||
}
|
||||
path = settings.WEBAPPS_BASE_ROOT % context
|
||||
public_root = self.options.filter(name='public-root').first()
|
||||
if public_root:
|
||||
path = os.path.join(path, public_root.value)
|
||||
return path.replace('//', '/')
|
||||
|
||||
def get_user(self):
|
||||
|
@ -95,7 +96,7 @@ class WebAppOption(models.Model):
|
|||
|
||||
@cached_property
|
||||
def option_class(self):
|
||||
return SiteDirective.get_plugin(self.name)
|
||||
return AppOption.get_plugin(self.name)
|
||||
|
||||
@cached_property
|
||||
def option_instance(self):
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
@ -54,15 +56,6 @@ class PublicRoot(AppOption):
|
|||
group = AppOption.FILESYSTEM
|
||||
|
||||
|
||||
class DirectoryProtection(AppOption):
|
||||
name = 'directory-protection'
|
||||
verbose_name = _("Directory protection")
|
||||
help_text = _("Space separated ...")
|
||||
regex = r'^([\w/_]+)\s+(\".*\")\s+([\w/_\.]+)$'
|
||||
group = AppOption.FILESYSTEM
|
||||
|
||||
|
||||
|
||||
class Timeout(AppOption):
|
||||
name = 'timeout'
|
||||
# FCGID FcgidIOTimeout
|
||||
|
@ -78,273 +71,273 @@ class Processes(AppOption):
|
|||
name = 'processes'
|
||||
# FCGID MaxProcesses
|
||||
# FPM pm.max_children
|
||||
verbose_name=_("Number of processes")
|
||||
help_text=_("Maximum number of children that can be alive at the same time (a number between 0 and 9).")
|
||||
regex=r'^[0-9]$'
|
||||
verbose_name = _("Number of processes")
|
||||
help_text = _("Maximum number of children that can be alive at the same time (a number between 0 and 9).")
|
||||
regex = r'^[0-9]$'
|
||||
group = AppOption.PROCESS
|
||||
|
||||
|
||||
class PHPEnabledFunctions(AppOption):
|
||||
name = 'enabled_functions'
|
||||
verbose_name=_("Enabled functions")
|
||||
verbose_name = _("Enabled functions")
|
||||
help_text = ' '.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS)
|
||||
regex=r'^[\w\.,-]+$'
|
||||
regex = r'^[\w\.,-]+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPAllowURLInclude(AppOption):
|
||||
name = 'allow_url_include'
|
||||
verbose_name=_("Allow URL include")
|
||||
help_text=_("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
|
||||
verbose_name = _("Allow URL include")
|
||||
help_text = _("Allows the use of URL-aware fopen wrappers with include, include_once, require, "
|
||||
"require_once (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPAllowURLFopen(AppOption):
|
||||
name = 'allow_url_fopen'
|
||||
verbose_name=_("Allow URL fopen")
|
||||
help_text=_("Enables the URL-aware fopen wrappers that enable accessing URL object like files (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("Allow URL fopen")
|
||||
help_text = _("Enables the URL-aware fopen wrappers that enable accessing URL object like files (On or Off).")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPAutoAppendFile(AppOption):
|
||||
name = 'auto_append_file'
|
||||
verbose_name=_("Auto append file")
|
||||
help_text=_("Specifies the name of a file that is automatically parsed after the main file.")
|
||||
regex=r'^[\w\.,-/]+$'
|
||||
verbose_name = _("Auto append file")
|
||||
help_text = _("Specifies the name of a file that is automatically parsed after the main file.")
|
||||
regex = r'^[\w\.,-/]+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPAutoPrependFile(AppOption):
|
||||
name = 'auto_prepend_file'
|
||||
verbose_name=_("Auto prepend file")
|
||||
help_text=_("Specifies the name of a file that is automatically parsed before the main file.")
|
||||
regex=r'^[\w\.,-/]+$'
|
||||
verbose_name = _("Auto prepend file")
|
||||
help_text = _("Specifies the name of a file that is automatically parsed before the main file.")
|
||||
regex = r'^[\w\.,-/]+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPDateTimeZone(AppOption):
|
||||
name = 'date.timezone'
|
||||
verbose_name=_("date.timezone")
|
||||
help_text=_("Sets the default timezone used by all date/time functions (Timezone string 'Europe/London').")
|
||||
regex=r'^\w+/\w+$'
|
||||
verbose_name = _("date.timezone")
|
||||
help_text = _("Sets the default timezone used by all date/time functions (Timezone string 'Europe/London').")
|
||||
regex = r'^\w+/\w+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPDefaultSocketTimeout(AppOption):
|
||||
name = 'default_socket_timeout'
|
||||
verbose_name=_("Default socket timeout")
|
||||
help_text=_("Number between 0 and 999.")
|
||||
regex=r'^[0-9]{1,3}$'
|
||||
verbose_name = _("Default socket timeout")
|
||||
help_text = _("Number between 0 and 999.")
|
||||
regex = r'^[0-9]{1,3}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPDisplayErrors(AppOption):
|
||||
name = 'display_errors'
|
||||
verbose_name=_("Display errors")
|
||||
help_text=_("Determines whether errors should be printed to the screen as part of the output or "
|
||||
verbose_name = _("Display errors")
|
||||
help_text = _("Determines whether errors should be printed to the screen as part of the output or "
|
||||
"if they should be hidden from the user (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPExtension(AppOption):
|
||||
name = 'extension'
|
||||
verbose_name=_("Extension")
|
||||
regex=r'^[^ ]+$'
|
||||
verbose_name = _("Extension")
|
||||
regex = r'^[^ ]+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMagicQuotesGPC(AppOption):
|
||||
name = 'magic_quotes_gpc'
|
||||
verbose_name=_("Magic quotes GPC")
|
||||
help_text=_("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
|
||||
verbose_name = _("Magic quotes GPC")
|
||||
help_text = _("Sets the magic_quotes state for GPC (Get/Post/Cookie) operations (On or Off) "
|
||||
"<b>DEPRECATED as of PHP 5.3.0</b>.")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
deprecated=5.3
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMagicQuotesRuntime(AppOption):
|
||||
name = 'magic_quotes_runtime'
|
||||
verbose_name=_("Magic quotes runtime")
|
||||
help_text=_("Functions that return data from any sort of external source will have quotes escaped "
|
||||
verbose_name = _("Magic quotes runtime")
|
||||
help_text = _("Functions that return data from any sort of external source will have quotes escaped "
|
||||
"with a backslash (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>.")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
deprecated=5.3
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMaginQuotesSybase(AppOption):
|
||||
name = 'magic_quotes_sybase'
|
||||
verbose_name=_("Magic quotes sybase")
|
||||
help_text=_("Single-quote is escaped with a single-quote instead of a backslash (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("Magic quotes sybase")
|
||||
help_text = _("Single-quote is escaped with a single-quote instead of a backslash (On or Off).")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMaxExecutonTime(AppOption):
|
||||
name = 'max_execution_time'
|
||||
verbose_name=_("Max execution time")
|
||||
help_text=_("Maximum time in seconds a script is allowed to run before it is terminated by "
|
||||
verbose_name = _("Max execution time")
|
||||
help_text = _("Maximum time in seconds a script is allowed to run before it is terminated by "
|
||||
"the parser (Integer between 0 and 999).")
|
||||
regex=r'^[0-9]{1,3}$'
|
||||
regex = r'^[0-9]{1,3}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMaxInputTime(AppOption):
|
||||
name = 'max_input_time'
|
||||
verbose_name=_("Max input time")
|
||||
help_text=_("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
|
||||
verbose_name = _("Max input time")
|
||||
help_text = _("Maximum time in seconds a script is allowed to parse input data, like POST and GET "
|
||||
"(Integer between 0 and 999).")
|
||||
regex=r'^[0-9]{1,3}$'
|
||||
regex = r'^[0-9]{1,3}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMaxInputVars(AppOption):
|
||||
name = 'max_input_vars'
|
||||
verbose_name=_("Max input vars")
|
||||
help_text=_("How many input variables may be accepted (limit is applied to $_GET, $_POST "
|
||||
verbose_name = _("Max input vars")
|
||||
help_text = _("How many input variables may be accepted (limit is applied to $_GET, $_POST "
|
||||
"and $_COOKIE superglobal separately) (Integer between 0 and 9999).")
|
||||
regex=r'^[0-9]{1,4}$'
|
||||
regex = r'^[0-9]{1,4}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMemoryLimit(AppOption):
|
||||
name = 'memory_limit'
|
||||
verbose_name=_("Memory limit")
|
||||
help_text=_("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
|
||||
verbose_name = _("Memory limit")
|
||||
help_text = _("This sets the maximum amount of memory in bytes that a script is allowed to allocate "
|
||||
"(Value between 0M and 999M).")
|
||||
regex=r'^[0-9]{1,3}M$'
|
||||
regex = r'^[0-9]{1,3}M$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPMySQLConnectTimeout(AppOption):
|
||||
name = 'mysql.connect_timeout'
|
||||
verbose_name=_("Mysql connect timeout")
|
||||
help_text=_("Number between 0 and 999.")
|
||||
regex=r'^([0-9]){1,3}$'
|
||||
verbose_name = _("Mysql connect timeout")
|
||||
help_text = _("Number between 0 and 999.")
|
||||
regex = r'^([0-9]){1,3}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPOutputBuffering(AppOption):
|
||||
name = 'output_buffering'
|
||||
verbose_name=_("Output buffering")
|
||||
help_text=_("Turn on output buffering (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("Output buffering")
|
||||
help_text = _("Turn on output buffering (On or Off).")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPRegisterGlobals(AppOption):
|
||||
name = 'register_globals'
|
||||
verbose_name=_("Register globals")
|
||||
help_text=_("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
|
||||
verbose_name = _("Register globals")
|
||||
help_text = _("Whether or not to register the EGPCS (Environment, GET, POST, Cookie, Server) "
|
||||
"variables as global variables (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPPostMaxSize(AppOption):
|
||||
name = 'post_max_size'
|
||||
verbose_name=_("Post max size")
|
||||
help_text=_("Sets max size of post data allowed (Value between 0M and 999M).")
|
||||
regex=r'^[0-9]{1,3}M$'
|
||||
verbose_name = _("Post max size")
|
||||
help_text = _("Sets max size of post data allowed (Value between 0M and 999M).")
|
||||
regex = r'^[0-9]{1,3}M$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSendmailPath(AppOption):
|
||||
name = 'sendmail_path'
|
||||
verbose_name=_("sendmail_path")
|
||||
help_text=_("Where the sendmail program can be found.")
|
||||
regex=r'^[^ ]+$'
|
||||
verbose_name = _("sendmail_path")
|
||||
help_text = _("Where the sendmail program can be found.")
|
||||
regex = r'^[^ ]+$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSessionBugCompatWarn(AppOption):
|
||||
name = 'session.bug_compat_warn'
|
||||
verbose_name=_("session.bug_compat_warn")
|
||||
help_text=_("Enables an PHP bug on session initialization for legacy behaviour (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("session.bug_compat_warn")
|
||||
help_text = _("Enables an PHP bug on session initialization for legacy behaviour (On or Off).")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSessionAutoStart(AppOption):
|
||||
name = 'session.auto_start',
|
||||
verbose_name=_("session.auto_start")
|
||||
help_text=_("Specifies whether the session module starts a session automatically on request "
|
||||
name = 'session.auto_start'
|
||||
verbose_name = _("session.auto_start")
|
||||
help_text = _("Specifies whether the session module starts a session automatically on request "
|
||||
"startup (On or Off).")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSafeMode(AppOption):
|
||||
name = 'safe_mode'
|
||||
verbose_name=_("Safe mode")
|
||||
help_text=_("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("Safe mode")
|
||||
help_text = _("Whether to enable PHP's safe mode (On or Off) <b>DEPRECATED as of PHP 5.3.0</b>")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
deprecated=5.3
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinPostMaxVars(AppOption):
|
||||
name = 'suhosin.post.max_vars',
|
||||
verbose_name=_("Suhosin POST max vars")
|
||||
help_text=_("Number between 0 and 9999.")
|
||||
regex=r'^[0-9]{1,4}$'
|
||||
name = 'suhosin.post.max_vars'
|
||||
verbose_name = _("Suhosin POST max vars")
|
||||
help_text = _("Number between 0 and 9999.")
|
||||
regex = r'^[0-9]{1,4}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinGetMaxVars(AppOption):
|
||||
name = 'suhosin.get.max_vars'
|
||||
verbose_name=_("Suhosin GET max vars")
|
||||
help_text=_("Number between 0 and 9999.")
|
||||
regex=r'^[0-9]{1,4}$'
|
||||
verbose_name = _("Suhosin GET max vars")
|
||||
help_text = _("Number between 0 and 9999.")
|
||||
regex = r'^[0-9]{1,4}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinRequestMaxVars(AppOption):
|
||||
name = 'suhosin.request.max_vars'
|
||||
verbose_name=_("Suhosin request max vars")
|
||||
help_text=_("Number between 0 and 9999.")
|
||||
regex=r'^[0-9]{1,4}$'
|
||||
verbose_name = _("Suhosin request max vars")
|
||||
help_text = _("Number between 0 and 9999.")
|
||||
regex = r'^[0-9]{1,4}$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinSessionEncrypt(AppOption):
|
||||
name = 'suhosin.session.encrypt'
|
||||
verbose_name=_("suhosin.session.encrypt")
|
||||
help_text=_("On or Off")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("suhosin.session.encrypt")
|
||||
help_text = _("On or Off")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinSimulation(AppOption):
|
||||
name = 'suhosin.simulation'
|
||||
verbose_name=_("Suhosin simulation")
|
||||
help_text=_("On or Off")
|
||||
regex=r'^(On|Off|on|off)$'
|
||||
verbose_name = _("Suhosin simulation")
|
||||
help_text = _("On or Off")
|
||||
regex = r'^(On|Off|on|off)$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPSuhosinExecutorIncludeWhitelist(AppOption):
|
||||
name = 'suhosin.executor.include.whitelist'
|
||||
verbose_name=_("suhosin.executor.include.whitelist")
|
||||
regex=r'.*$'
|
||||
verbose_name = _("suhosin.executor.include.whitelist")
|
||||
regex = r'.*$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPUploadMaxFileSize(AppOption):
|
||||
name = 'upload_max_filesize',
|
||||
verbose_name=_("upload_max_filesize")
|
||||
help_text=_("Value between 0M and 999M.")
|
||||
regex=r'^[0-9]{1,3}M$'
|
||||
name = 'upload_max_filesize'
|
||||
verbose_name = _("upload_max_filesize")
|
||||
help_text = _("Value between 0M and 999M.")
|
||||
regex = r'^[0-9]{1,3}M$'
|
||||
group = AppOption.PHP
|
||||
|
||||
|
||||
class PHPPostMaxSize(AppOption):
|
||||
name = 'post_max_size'
|
||||
verbose_name=_("zend_extension")
|
||||
regex=r'^[^ ]+$'
|
||||
verbose_name = _("zend_extension")
|
||||
regex = r'^[^ ]+$'
|
||||
group = AppOption.PHP
|
||||
|
|
|
@ -2,28 +2,31 @@ from django.conf import settings
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
WEBAPPS_BASE_ROOT = getattr(settings, 'WEBAPPS_BASE_ROOT', '{home}/webapps/{app_name}/')
|
||||
|
||||
|
||||
WEBAPPS_BASE_ROOT = getattr(settings, 'WEBAPPS_BASE_ROOT', '%(home)s/webapps/%(app_name)s/')
|
||||
|
||||
WEBAPPS_FPM_LISTEN = getattr(settings, 'WEBAPPS_FPM_LISTEN',
|
||||
# '127.0.0.1:9{app_id:03d}
|
||||
'/opt/php/5.4/socks/{user}-{app_name}.sock'
|
||||
# '127.0.0.1:9%(app_id)03d
|
||||
'/opt/php/5.4/socks/%(user)s-%(app_name)s.sock'
|
||||
)
|
||||
|
||||
WEBAPPS_FPM_START_PORT = getattr(settings, 'WEBAPPS_FPM_START_PORT', 10000)
|
||||
|
||||
|
||||
WEBAPPS_PHPFPM_POOL_PATH = getattr(settings, 'WEBAPPS_PHPFPM_POOL_PATH',
|
||||
'/etc/php5/fpm/pool.d/{user}-{app_name}.conf')
|
||||
'/etc/php5/fpm/pool.d/%(user)s-%(app_name)s.conf')
|
||||
|
||||
|
||||
WEBAPPS_FCGID_PATH = getattr(settings, 'WEBAPPS_FCGID_PATH',
|
||||
'/home/httpd/fcgid/{user}/{app_name}-wrapper')
|
||||
'/home/httpd/fcgi-bin.d/%(user)s/%(app_name)s-wrapper')
|
||||
|
||||
|
||||
WEBAPPS_FCGID_CMD_OPTIONS_PATH = getattr(settings, 'WEBAPPS_FCGID_CMD_OPTIONS_PATH',
|
||||
'/etc/apache2/fcgid-conf/%(user)s-%(app_name)s.conf')
|
||||
|
||||
|
||||
WEBAPPS_PHP_ERROR_LOG_PATH = getattr(settings, 'WEBAPPS_PHP_ERROR_LOG_PATH',
|
||||
'')
|
||||
|
||||
WEBAPPS_TYPES = getattr(settings, 'WEBAPPS_TYPES', (
|
||||
'orchestra.apps.webapps.types.PHP54App',
|
||||
'orchestra.apps.webapps.types.PHP53App',
|
||||
'orchestra.apps.webapps.types.PHP52App',
|
||||
'orchestra.apps.webapps.types.PHP4App',
|
||||
'orchestra.apps.webapps.types.StaticApp',
|
||||
|
@ -35,7 +38,10 @@ WEBAPPS_TYPES = getattr(settings, 'WEBAPPS_TYPES', (
|
|||
'orchestra.apps.webapps.types.WordPressApp',
|
||||
))
|
||||
|
||||
|
||||
WEBAPPS_UNDER_CONSTRUCTION_PATH = getattr(settings, 'WEBAPPS_UNDER_CONSTRUCTION_PATH',
|
||||
# Server-side path where a under construction stock page is
|
||||
# '/var/www/undercontruction/index.html',
|
||||
'')
|
||||
|
||||
#WEBAPPS_TYPES_OVERRIDE = getattr(settings, 'WEBAPPS_TYPES_OVERRIDE', {})
|
||||
#for webapp_type, value in WEBAPPS_TYPES_OVERRIDE.iteritems():
|
||||
|
@ -79,7 +85,6 @@ WEBAPPS_PHP_DISABLED_FUNCTIONS = getattr(settings, 'WEBAPPS_PHP_DISABLED_FUNCTIO
|
|||
|
||||
WEBAPPS_ENABLED_OPTIONS = getattr(settings, 'WEBAPPS_ENABLED_OPTIONS', (
|
||||
'orchestra.apps.webapps.options.PublicRoot',
|
||||
'orchestra.apps.webapps.options.DirectoryProtection',
|
||||
'orchestra.apps.webapps.options.Timeout',
|
||||
'orchestra.apps.webapps.options.Processes',
|
||||
'orchestra.apps.webapps.options.PHPEnabledFunctions',
|
||||
|
@ -140,7 +145,7 @@ WEBAPPS_DOKUWIKIMU_LISTEN = getattr(settings, 'WEBAPPS_DOKUWIKIMU_LISTEN',
|
|||
|
||||
|
||||
WEBAPPS_DRUPALMU_SITES_PATH = getattr(settings, 'WEBAPPS_DRUPALMU_SITES_PATH',
|
||||
'/home/httpd/htdocs/drupal-mu/sites/{site_name}')
|
||||
'/home/httpd/htdocs/drupal-mu/sites/%(site_name)s')
|
||||
|
||||
WEBAPPS_DRUPALMU_LISTEN = getattr(settings, 'WEBAPPS_DRUPALMU_LISTEN',
|
||||
'/opt/php/5.4/socks/drupal-mu.sock'
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import os
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.safestring import mark_safe
|
||||
|
@ -129,25 +131,31 @@ class PHPAppType(AppType):
|
|||
socket_type = 'unix'
|
||||
if ':' in self.fpm_listen:
|
||||
socket_type = 'tcp'
|
||||
socket = self.fpm_listen.format(context)
|
||||
socket = self.fpm_listen % context
|
||||
return ('fpm', socket_type, socket, webapp.get_path())
|
||||
|
||||
def get_context(self, webapp):
|
||||
""" context used to format settings """
|
||||
return {
|
||||
'home': webapp.account.main_systemuser.get_home(),
|
||||
'account': webapp.account.username,
|
||||
'user': webapp.account.username,
|
||||
'app_name': webapp.name,
|
||||
}
|
||||
|
||||
def get_php_init_vars(self, webapp, per_account=False):
|
||||
"""
|
||||
process php options for inclusion on php.ini
|
||||
per_account=True merges all (account, webapp.type) options
|
||||
"""
|
||||
init_vars = []
|
||||
php_options = type(self).get_php_options()
|
||||
init_vars = {}
|
||||
options = webapp.options.all()
|
||||
if per_account:
|
||||
options = webapp.account.webapps.filter(webapp_type=webapp.type)
|
||||
php_options = [option.name for option in php_options]
|
||||
php_options = [option.name for option in type(self).get_php_options()]
|
||||
for opt in options:
|
||||
if opt.option_class in php_options:
|
||||
init_vars.append(
|
||||
(opt.name, opt.value)
|
||||
)
|
||||
if opt.name in php_options:
|
||||
init_vars[opt.name] = opt.value
|
||||
enabled_functions = []
|
||||
for value in options.filter(name='enabled_functions').values_list('value', flat=True):
|
||||
enabled_functions += enabled_functions.get().value.split(',')
|
||||
|
@ -156,9 +164,10 @@ class PHPAppType(AppType):
|
|||
for function in settings.WEBAPPS_PHP_DISABLED_FUNCTIONS:
|
||||
if function not in enabled_functions:
|
||||
disabled_functions.append(function)
|
||||
init_vars.append(
|
||||
('dissabled_functions', ','.join(disabled_functions))
|
||||
)
|
||||
init_vars['dissabled_functions'] = ','.join(disabled_functions)
|
||||
if settings.WEBAPPS_PHP_ERROR_LOG_PATH and 'error_log' not in init_vars:
|
||||
context = self.get_context(webapp)
|
||||
init_vars['error_log'] = settings.WEBAPPS_PHP_ERROR_LOG_PATH % context
|
||||
return init_vars
|
||||
|
||||
|
||||
|
@ -171,23 +180,37 @@ class PHP54App(PHPAppType):
|
|||
icon = 'orchestra/icons/apps/PHPFPM.png'
|
||||
|
||||
|
||||
class PHP52App(PHPAppType):
|
||||
name = 'php5.2-fcgid'
|
||||
php_version = 5.2
|
||||
verbose_name = "PHP 5.2 FCGID"
|
||||
help_text = _("This creates a PHP5.2 application under ~/webapps/<app_name><br>"
|
||||
class PHP53App(PHPAppType):
|
||||
name = 'php5.3-fcgid'
|
||||
php_version = 5.3
|
||||
php_binary = '/usr/bin/php5-cgi'
|
||||
php_rc = '/etc/php5/cgi/'
|
||||
verbose_name = "PHP 5.3 FCGID"
|
||||
help_text = _("This creates a PHP5.3 application under ~/webapps/<app_name><br>"
|
||||
"Apache-mod-fcgid will be used to execute PHP files.")
|
||||
icon = 'orchestra/icons/apps/PHPFCGI.png'
|
||||
|
||||
def get_directive(self, webapp):
|
||||
context = self.get_directive_context(webapp)
|
||||
wrapper_path = settings.WEBAPPS_FCGID_PATH.format(context)
|
||||
return ('fcgi', webapp.get_path(), wrapper_path)
|
||||
wrapper_path = settings.WEBAPPS_FCGID_PATH % context
|
||||
return ('fcgid', webapp.get_path(), wrapper_path)
|
||||
|
||||
|
||||
class PHP4App(PHP52App):
|
||||
class PHP52App(PHP53App):
|
||||
name = 'php5.2-fcgid'
|
||||
php_version = 5.2
|
||||
php_binary = '/usr/bin/php5.2-cgi'
|
||||
php_rc = '/etc/php5.2/cgi/'
|
||||
verbose_name = "PHP 5.2 FCGID"
|
||||
help_text = _("This creates a PHP5.2 application under ~/webapps/<app_name><br>"
|
||||
"Apache-mod-fcgid will be used to execute PHP files.")
|
||||
icon = 'orchestra/icons/apps/PHPFCGI.png'
|
||||
|
||||
|
||||
class PHP4App(PHP53App):
|
||||
name = 'php4-fcgid'
|
||||
php_version = 4
|
||||
php_binary = '/usr/bin/php4-cgi'
|
||||
verbose_name = "PHP 4 FCGID"
|
||||
help_text = _("This creates a PHP4 application under ~/webapps/<app_name><br>"
|
||||
"Apache-mod-fcgid will be used to execute PHP files.")
|
||||
|
@ -213,7 +236,7 @@ class WebalizerApp(AppType):
|
|||
option_groups = ()
|
||||
|
||||
def get_directive(self, webapp):
|
||||
return ('static', webapp.get_path())
|
||||
return ('static', os.path.join(webapp.get_path(), '%(site_name)s/'))
|
||||
|
||||
|
||||
class WordPressMuApp(PHPAppType):
|
||||
|
|
|
@ -35,7 +35,7 @@ class DirectiveInline(admin.TabularInline):
|
|||
if db_field.name == 'name':
|
||||
# Help text based on select widget
|
||||
kwargs['widget'] = DynamicHelpTextSelect(
|
||||
'this.id.replace("name", "value")', self.DIECTIVES_HELP_TEXT
|
||||
'this.id.replace("name", "value")', self.DIRECTIVES_HELP_TEXT
|
||||
)
|
||||
return super(DirectiveInline, self).formfield_for_dbfield(db_field, **kwargs)
|
||||
|
||||
|
@ -71,7 +71,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
)
|
||||
form = WebsiteAdminForm
|
||||
filter_by_account_fields = ['domains']
|
||||
list_prefetch_related = ('domains', 'contents__webapp')
|
||||
list_prefetch_related = ('domains', 'content_set__webapp')
|
||||
search_fields = ('name', 'account__username', 'domains__name')
|
||||
|
||||
def display_domains(self, website):
|
||||
|
@ -86,7 +86,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
|
||||
def display_webapps(self, website):
|
||||
webapps = []
|
||||
for content in website.contents.all():
|
||||
for content in website.content_set.all():
|
||||
webapp = content.webapp
|
||||
url = change_url(webapp)
|
||||
name = "%s on %s" % (webapp.get_type_display(), content.path)
|
||||
|
|
|
@ -44,7 +44,7 @@ class Apache2Backend(ServiceController):
|
|||
</VirtualHost>"""
|
||||
))
|
||||
apache_conf = apache_conf.render(Context(context))
|
||||
apache_conf += self.get_protections(site)
|
||||
# apache_conf += self.get_protections(site)
|
||||
context['apache_conf'] = apache_conf
|
||||
|
||||
self.append(textwrap.dedent("""\
|
||||
|
@ -64,21 +64,21 @@ class Apache2Backend(ServiceController):
|
|||
|
||||
def commit(self):
|
||||
""" reload Apache2 if necessary """
|
||||
self.append('[[ $UPDATED == 1 ]] && service apache2 reload || true')
|
||||
self.append('if [[ $UPDATED == 1 ]]; then service apache2 reload; fi')
|
||||
|
||||
def get_content_directives(self, site):
|
||||
directives = ''
|
||||
for content in site.contents.all().order_by('-path'):
|
||||
for content in site.content_set.all().order_by('-path'):
|
||||
directive = content.webapp.get_directive()
|
||||
method, agrs = directive[0], directive[1:]
|
||||
method, args = directive[0], directive[1:]
|
||||
method = getattr(self, 'get_%s_directives' % method)
|
||||
directives += method(content, *args)
|
||||
return directives
|
||||
|
||||
def get_static_directives(self, content, app_path):
|
||||
context = self.get_content_context(content)
|
||||
context['app_path'] = app_path
|
||||
return "Alias %(location)s %(path)s\n" % context
|
||||
context['app_path'] = app_path % context
|
||||
return "Alias %(location)s %(app_path)s\n" % context
|
||||
|
||||
def get_fpm_directives(self, content, socket_type, socket, app_path):
|
||||
if socket_type == 'unix':
|
||||
|
@ -95,29 +95,26 @@ class Apache2Backend(ServiceController):
|
|||
'socket': socket,
|
||||
})
|
||||
return textwrap.dedent("""\
|
||||
ProxyPassMatch ^%(location)s/(.*\.php(/.*)?)$ {target}
|
||||
Alias %(location)s/ %(app_path)s/
|
||||
ProxyPassMatch ^%(location)s(.*\.php(/.*)?)$ {target}
|
||||
Alias %(location)s %(app_path)s/
|
||||
""".format(target=target) % context
|
||||
)
|
||||
|
||||
def get_fcgi_directives(self, content, app_path, wrapper_path):
|
||||
def get_fcgid_directives(self, content, app_path, wrapper_path):
|
||||
context = self.get_content_context(content)
|
||||
context.update({
|
||||
'app_path': app_path,
|
||||
'wrapper_path': wrapper_path,
|
||||
})
|
||||
fcgid = textwrap.dedent("""\
|
||||
return textwrap.dedent("""\
|
||||
Alias %(location)s %(app_path)s
|
||||
ProxyPass %(location)s !
|
||||
<Directory %(app_path)s>
|
||||
Options +ExecCGI
|
||||
AddHandler fcgid-script .php
|
||||
FcgidWrapper %(wrapper_path)s\
|
||||
FcgidWrapper %(wrapper_path)s
|
||||
</Directory>
|
||||
""") % context
|
||||
for option in content.webapp.options.filter(name__startswith='Fcgid'):
|
||||
fcgid += " %s %s\n" % (option.name, option.value)
|
||||
fcgid += "</Directory>\n"
|
||||
return fcgid
|
||||
|
||||
def get_ssl(self, site):
|
||||
cert = settings.WEBSITES_DEFAULT_HTTPS_CERT
|
||||
|
@ -129,54 +126,53 @@ class Apache2Backend(ServiceController):
|
|||
SSLEngine on
|
||||
SSLCertificateFile %s
|
||||
SSLCertificateKeyFile %s\
|
||||
""" % cert
|
||||
)
|
||||
""") % cert
|
||||
return directives
|
||||
|
||||
def get_security(self, site):
|
||||
directives = ''
|
||||
for rules in site.options.filter(name='sec_rule_remove'):
|
||||
for rules in site.directives.filter(name='sec_rule_remove'):
|
||||
for rule in rules.value.split():
|
||||
directives += "SecRuleRemoveById %i\n" % int(rule)
|
||||
for modsecurity in site.options.filter(name='sec_rule_off'):
|
||||
for modsecurity in site.directives.filter(name='sec_rule_off'):
|
||||
directives += textwrap.dedent("""\
|
||||
<LocationMatch %s>
|
||||
SecRuleEngine Off
|
||||
</LocationMatch>\
|
||||
""" % modsecurity.value)
|
||||
""") % modsecurity.value
|
||||
if directives:
|
||||
directives = '<IfModule mod_security2.c>\n%s\n</IfModule>' % directives
|
||||
return directives
|
||||
|
||||
def get_redirect(self, site):
|
||||
directives = ''
|
||||
for redirect in site.options.filter(name='redirect'):
|
||||
for redirect in site.directives.filter(name='redirect'):
|
||||
if re.match(r'^.*[\^\*\$\?\)]+.*$', redirect.value):
|
||||
directives += "RedirectMatch %s" % redirect.value
|
||||
else:
|
||||
directives += "Redirect %s" % redirect.value
|
||||
return directives
|
||||
|
||||
def get_protections(self, site):
|
||||
protections = ''
|
||||
context = self.get_context(site)
|
||||
for protection in site.options.filter(name='directory_protection'):
|
||||
path, name, passwd = protection.value.split()
|
||||
path = os.path.join(context['root'], path)
|
||||
passwd = os.path.join(self.USER_HOME % context, passwd)
|
||||
protections += textwrap.dedent("""
|
||||
<Directory %s>
|
||||
AllowOverride All
|
||||
#AuthPAM_Enabled off
|
||||
AuthType Basic
|
||||
AuthName %s
|
||||
AuthUserFile %s
|
||||
<Limit GET POST>
|
||||
require valid-user
|
||||
</Limit>
|
||||
</Directory>""" % (path, name, passwd)
|
||||
)
|
||||
return protections
|
||||
# def get_protections(self, site):
|
||||
# protections = ''
|
||||
# context = self.get_context(site)
|
||||
# for protection in site.directives.filter(name='directory_protection'):
|
||||
# path, name, passwd = protection.value.split()
|
||||
# path = os.path.join(context['root'], path)
|
||||
# passwd = os.path.join(self.USER_HOME % context, passwd)
|
||||
# protections += textwrap.dedent("""
|
||||
# <Directory %s>
|
||||
# AllowOverride All
|
||||
# #AuthPAM_Enabled off
|
||||
# AuthType Basic
|
||||
# AuthName %s
|
||||
# AuthUserFile %s
|
||||
# <Limit GET POST>
|
||||
# require valid-user
|
||||
# </Limit>
|
||||
# </Directory>""" % (path, name, passwd)
|
||||
# )
|
||||
# return protections
|
||||
|
||||
def enable_or_disable(self, site):
|
||||
context = self.get_context(site)
|
||||
|
@ -184,27 +180,25 @@ class Apache2Backend(ServiceController):
|
|||
self.append(textwrap.dedent("""\
|
||||
if [[ ! -f %(sites_enabled)s ]]; then
|
||||
a2ensite %(site_unique_name)s.conf
|
||||
else
|
||||
UPDATED=0
|
||||
fi""" % context
|
||||
))
|
||||
UPDATED=1
|
||||
fi""") % context
|
||||
)
|
||||
else:
|
||||
self.append(textwrap.dedent("""\
|
||||
if [[ -f %(sites_enabled)s ]]; then
|
||||
a2dissite %(site_unique_name)s.conf;
|
||||
else
|
||||
UPDATED=0
|
||||
fi""" % context
|
||||
))
|
||||
UPDATED=1
|
||||
fi""") % context
|
||||
)
|
||||
|
||||
def get_username(self, site):
|
||||
option = site.options.filter(name='user_group').first()
|
||||
option = site.directives.filter(name='user_group').first()
|
||||
if option:
|
||||
return option.value.split()[0]
|
||||
return site.account.username
|
||||
|
||||
def get_groupname(self, site):
|
||||
option = site.options.filter(name='user_group').first()
|
||||
option = site.directives.filter(name='user_group').first()
|
||||
if option and ' ' in option.value:
|
||||
user, group = option.value.split()
|
||||
return group
|
||||
|
@ -236,7 +230,6 @@ class Apache2Backend(ServiceController):
|
|||
'location': content.path,
|
||||
'app_name': content.webapp.name,
|
||||
'app_path': content.webapp.get_path(),
|
||||
'fpm_port': content.webapp.get_fpm_port(),
|
||||
})
|
||||
return context
|
||||
|
||||
|
@ -292,7 +285,7 @@ class Apache2Traffic(ServiceMonitor):
|
|||
print sum
|
||||
}' || [[ $? == 1 ]] && true
|
||||
} | xargs echo ${OBJECT_ID}
|
||||
}""" % context))
|
||||
}""") % context)
|
||||
|
||||
def monitor(self, site):
|
||||
context = self.get_context(site)
|
||||
|
|
|
@ -20,18 +20,17 @@ class WebalizerBackend(ServiceController):
|
|||
echo 'Webstats are coming soon' > %(webalizer_path)s/index.html
|
||||
fi
|
||||
echo '%(webalizer_conf)s' > %(webalizer_conf_path)s
|
||||
chown %(user)s:www-data %(webalizer_path)s""" % context
|
||||
))
|
||||
chown %(user)s:www-data %(webalizer_path)s""") % context
|
||||
)
|
||||
|
||||
def delete(self, content):
|
||||
context = self.get_context(content)
|
||||
delete_webapp = not content.webapp.pk
|
||||
# TODO remove when confirmed that it works, otherwise create a second WebalizerBackend for WebApps
|
||||
delete_webapp = type(content.webapp).objects.filter(pk=content.webapp.pk).exists()
|
||||
if delete_webapp:
|
||||
self.append("mv %(webapp_path)s %(webapp_path)s.deleted" % context)
|
||||
if delete_webapp or not content.webapp.contents.filter(website=content.website).exists():
|
||||
self.append("mv %(webalizer_path)s %(webalizer_path)s.deleted" % context)
|
||||
self.append("rm %(webalizer_conf_path)s" % context)
|
||||
if delete_webapp or not content.webapp.content_set.filter(website=content.website).exists():
|
||||
self.append("rm -fr %(webalizer_path)s" % context)
|
||||
self.append("rm -f %(webalizer_conf_path)s" % context)
|
||||
|
||||
def get_context(self, content):
|
||||
conf_file = "%s.conf" % content.website.unique_name
|
||||
|
@ -88,6 +87,5 @@ class WebalizerBackend(ServiceController):
|
|||
SearchEngine mamma.com query=
|
||||
SearchEngine alltheweb.com query=
|
||||
|
||||
DumpSites yes""" % context
|
||||
)
|
||||
DumpSites yes""") % context
|
||||
return context
|
||||
|
|
|
@ -10,9 +10,9 @@ from . import settings
|
|||
|
||||
# TODO multiple and unique validation support in the formset
|
||||
class SiteDirective(Plugin):
|
||||
HTTPD = 'httpd'
|
||||
SEC = 'sec'
|
||||
SSL = 'ssl'
|
||||
HTTPD = 'HTTPD'
|
||||
SEC = 'ModSecurity'
|
||||
SSL = 'SSL'
|
||||
|
||||
help_text = ""
|
||||
unique = True
|
||||
|
|
|
@ -66,7 +66,8 @@ class Website(models.Model):
|
|||
return {
|
||||
'home': self.account.main_systemuser.get_home(),
|
||||
'account': self.account.username,
|
||||
'name': self.name,
|
||||
'user': self.account.username,
|
||||
'site_name': self.name,
|
||||
'unique_name': self.unique_name
|
||||
}
|
||||
|
||||
|
@ -105,10 +106,9 @@ class Directive(models.Model):
|
|||
|
||||
|
||||
class Content(models.Model):
|
||||
webapp = models.ForeignKey('webapps.WebApp', verbose_name=_("web application"),
|
||||
related_name='contents')
|
||||
website = models.ForeignKey('websites.Website', verbose_name=_("web site"),
|
||||
related_name='contents')
|
||||
# related_name is content_set to differentiate between website.content -> webapp
|
||||
webapp = models.ForeignKey('webapps.WebApp', verbose_name=_("web application"))
|
||||
website = models.ForeignKey('websites.Website', verbose_name=_("web site"))
|
||||
path = models.CharField(_("path"), max_length=256, blank=True,
|
||||
validators=[validators.validate_url_path])
|
||||
|
||||
|
@ -124,6 +124,8 @@ class Content(models.Model):
|
|||
def clean(self):
|
||||
if not self.path.startswith('/'):
|
||||
self.path = '/' + self.path
|
||||
if not self.path.endswith('/'):
|
||||
self.path = self.path + '/'
|
||||
|
||||
def get_absolute_url(self):
|
||||
domain = self.website.domains.first()
|
||||
|
|
|
@ -43,7 +43,7 @@ class ContentSerializer(serializers.HyperlinkedModelSerializer):
|
|||
class WebsiteSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
||||
domains = RelatedDomainSerializer(many=True, allow_add_remove=True, required=False)
|
||||
contents = ContentSerializer(required=False, many=True, allow_add_remove=True,
|
||||
source='contents')
|
||||
source='content_set')
|
||||
options = OptionField(required=False)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -36,7 +36,9 @@ MEDIA_URL = '/media/'
|
|||
ALLOWED_HOSTS = '*'
|
||||
|
||||
# Set this to True to wrap each HTTP request in a transaction on this database.
|
||||
ATOMIC_REQUESTS = True
|
||||
# ATOMIC REQUESTS do not wrap middlewares (orchestra.apps.orchestration.middlewares.OperationsMiddleware)
|
||||
ATOMIC_REQUESTS = False
|
||||
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.gzip.GZipMiddleware',
|
||||
|
@ -46,9 +48,12 @@ MIDDLEWARE_CLASSES = (
|
|||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'orchestra.core.caches.RequestCacheMiddleware',
|
||||
# ATOMIC REQUESTS do not wrap middlewares
|
||||
'orchestra.core.middlewares.TransactionMiddleware',
|
||||
'orchestra.apps.orchestration.middlewares.OperationsMiddleware',
|
||||
# Uncomment the next line for simple clickjacking protection:
|
||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
from django.db import connection, transaction
|
||||
|
||||
|
||||
class TransactionMiddleware(object):
|
||||
"""
|
||||
Transaction middleware. If this is enabled, each view function will be run
|
||||
with commit_on_response activated - that way a save() doesn't do a direct
|
||||
commit, the commit is done when a successful response is created. If an
|
||||
exception happens, the database is rolled back.
|
||||
"""
|
||||
|
||||
def process_request(self, request):
|
||||
"""Enters transaction management"""
|
||||
transaction.enter_transaction_management()
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
"""Rolls back the database and leaves transaction management"""
|
||||
if transaction.is_dirty():
|
||||
# This rollback might fail because of network failure for example.
|
||||
# If rollback isn't possible it is impossible to clean the
|
||||
# connection's state. So leave the connection in dirty state and
|
||||
# let request_finished signal deal with cleaning the connection.
|
||||
transaction.rollback()
|
||||
transaction.leave_transaction_management()
|
||||
|
||||
def process_response(self, request, response):
|
||||
"""Commits and leaves transaction management."""
|
||||
if not transaction.get_autocommit():
|
||||
if transaction.is_dirty():
|
||||
# Note: it is possible that the commit fails. If the reason is
|
||||
# closed connection or some similar reason, then there is
|
||||
# little hope to proceed nicely. However, in some cases (
|
||||
# deferred foreign key checks for exampl) it is still possible
|
||||
# to rollback().
|
||||
try:
|
||||
transaction.commit()
|
||||
except Exception:
|
||||
# If the rollback fails, the transaction state will be
|
||||
# messed up. It doesn't matter, the connection will be set
|
||||
# to clean state after the request finishes. And, we can't
|
||||
# clean the state here properly even if we wanted to, the
|
||||
# connection is in transaction but we can't rollback...
|
||||
transaction.rollback()
|
||||
transaction.leave_transaction_management()
|
||||
raise
|
||||
transaction.leave_transaction_management()
|
||||
return response
|
Loading…
Reference in New Issue