Apache2 backend, replace FcgidWrapper directive by Alias /fcgi-bin/

This commit is contained in:
Marc Aymerich 2015-04-13 14:46:10 +00:00
parent 525d38750e
commit 711951d1bd
8 changed files with 44 additions and 34 deletions

View File

@ -285,15 +285,12 @@ https://code.djangoproject.com/ticket/24576
# Apache restart fails: detect if appache running, and execute start # Apache restart fails: detect if appache running, and execute start
# Change crons, create cron for deleted webapps and users # Change crons, create cron for deleted webapps and users
* UNIFY PHP FPM settings name * UNIFY PHP FPM settings name
# virtualhost name name-account? # virtualhost name: name-account?
* add a delay to changes on the webserver apache to no overwelm it with backend executions? * add a delay to changes on the webserver apache to no overwelm it with backend executions?
* replace unique_name by natural_key? * replace unique_name by natural_key?
* do not require contact or create default * do not require contact or create default
* send signals for backend triggers * send signals for backend triggers
* monitor resources with multiple backends not possible to identify the correct last execution, allow to specify backends only once or change backend.model = 'resources.MonitorData'
* force ignore slack billing period overridig when billing * force ignore slack billing period overridig when billing
* fpm reload starts new pools? * fpm reload starts new pools?
* more processes for webmail, or use fpm pool
* rename resource.monitors to resource.backends ? * rename resource.monitors to resource.backends ?
* abstract model classes enabling overriding? * abstract model classes enabling overriding?

View File

@ -57,7 +57,7 @@ class WebApp(models.Model):
@cached @cached
def get_options(self): def get_options(self):
return OrderedDict((opt.name, opt.value) for opt in self.options.all()) return OrderedDict((opt.name, opt.value) for opt in self.options.all().order_by('name'))
def get_directive(self): def get_directive(self):
return self.type_instance.get_directive() return self.type_instance.get_directive()

View File

@ -92,9 +92,9 @@ class Processes(AppOption):
group = AppOption.PROCESS group = AppOption.PROCESS
class PHPEnabledFunctions(PHPAppOption): class PHPEnableFunctions(PHPAppOption):
name = 'enabled_functions' name = 'enable_functions'
verbose_name = _("Enabled functions") verbose_name = _("Enable functions")
help_text = ','.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS) help_text = ','.join(settings.WEBAPPS_PHP_DISABLED_FUNCTIONS)
regex = r'^[\w\.,-]+$' regex = r'^[\w\.,-]+$'

View File

@ -139,7 +139,7 @@ WEBAPPS_ENABLED_OPTIONS = getattr(settings, 'WEBAPPS_ENABLED_OPTIONS', (
'orchestra.contrib.webapps.options.PublicRoot', 'orchestra.contrib.webapps.options.PublicRoot',
'orchestra.contrib.webapps.options.Timeout', 'orchestra.contrib.webapps.options.Timeout',
'orchestra.contrib.webapps.options.Processes', 'orchestra.contrib.webapps.options.Processes',
'orchestra.contrib.webapps.options.PHPEnabledFunctions', 'orchestra.contrib.webapps.options.PHPEnableFunctions',
'orchestra.contrib.webapps.options.PHPAllowURLInclude', 'orchestra.contrib.webapps.options.PHPAllowURLInclude',
'orchestra.contrib.webapps.options.PHPAllowURLFopen', 'orchestra.contrib.webapps.options.PHPAllowURLFopen',
'orchestra.contrib.webapps.options.PHPAutoAppendFile', 'orchestra.contrib.webapps.options.PHPAutoAppendFile',

View File

@ -71,7 +71,7 @@ class PHPApp(AppType):
per_account=True merges all (account, webapp.type) options per_account=True merges all (account, webapp.type) options
""" """
init_vars = OrderedDict() init_vars = OrderedDict()
options = self.instance.options.all() options = self.instance.options.all().order_by('name')
if merge: if merge:
# Get options from the same account and php_version webapps # Get options from the same account and php_version webapps
options = [] options = []
@ -84,7 +84,7 @@ class PHPApp(AppType):
enabled_functions = set() enabled_functions = set()
for opt in options: for opt in options:
if opt.name in php_options: if opt.name in php_options:
if opt.name == 'enabled_functions': if opt.name == 'enable_functions':
enabled_functions = enabled_functions.union(set(opt.value.split(','))) enabled_functions = enabled_functions.union(set(opt.value.split(',')))
else: else:
init_vars[opt.name] = opt.value init_vars[opt.name] = opt.value
@ -93,7 +93,7 @@ class PHPApp(AppType):
for function in self.PHP_DISABLED_FUNCTIONS: for function in self.PHP_DISABLED_FUNCTIONS:
if function not in enabled_functions: if function not in enabled_functions:
disabled_functions.append(function) disabled_functions.append(function)
init_vars['dissabled_functions'] = ','.join(disabled_functions) init_vars['disable_functions'] = ','.join(disabled_functions)
timeout = self.instance.options.filter(name='timeout').first() timeout = self.instance.options.filter(name='timeout').first()
if timeout: if timeout:
# Give a little slack here # Give a little slack here

View File

@ -25,7 +25,7 @@ class Apache2Backend(ServiceController):
def render_virtual_host(self, site, context, ssl=False): def render_virtual_host(self, site, context, ssl=False):
context['port'] = self.HTTPS_PORT if ssl else self.HTTP_PORT context['port'] = self.HTTPS_PORT if ssl else self.HTTP_PORT
extra_conf = self.get_content_directives(site) extra_conf = self.get_content_directives(site, context)
directives = site.get_directives() directives = site.get_directives()
if ssl: if ssl:
extra_conf += self.get_ssl(directives) extra_conf += self.get_ssl(directives)
@ -147,11 +147,11 @@ class Apache2Backend(ServiceController):
(self.__class__.__name__, method)) (self.__class__.__name__, method))
return method(context, *args) return method(context, *args)
def get_content_directives(self, site): def get_content_directives(self, site, context):
directives = [] directives = []
for content in site.content_set.all(): for content in site.content_set.all():
directive = content.webapp.get_directive() directive = content.webapp.get_directive()
context = self.get_content_context(content) self.set_content_context(content, context)
directives += self.get_directives(directive, context) directives += self.get_directives(directive, context)
return directives return directives
@ -189,15 +189,27 @@ class Apache2Backend(ServiceController):
def get_fcgid_directives(self, context, app_path, wrapper_path): def get_fcgid_directives(self, context, app_path, wrapper_path):
context.update({ context.update({
'app_path': os.path.normpath(app_path), 'app_path': os.path.normpath(app_path),
'wrapper_path': wrapper_path, 'wrapper_name': os.path.basename(wrapper_path),
}) })
directives = self.get_location_filesystem_map(context) directives = ''
# This Alias trick is used instead of FcgidWrapper because we don't want to define
# a new fcgid process class each time an app is mounted (num proc limits enforcement).
if 'wrapper_dir' not in context:
# fcgi-bin only needs to be defined once per vhots
context['wrapper_dir'] = os.path.dirname(wrapper_path)
directives = textwrap.dedent("""\
Alias /fcgi-bin/ %(wrapper_dir)s/
<Location /fcgi-bin/>
SetHandler fcgid-script
Options +ExecCGI
</Location>
""") % context
directives += self.get_location_filesystem_map(context)
directives += textwrap.dedent(""" directives += textwrap.dedent("""
ProxyPass %(location)s/ ! ProxyPass %(location)s/ !
<Directory %(app_path)s/> <Directory %(app_path)s/>
Options +ExecCGI AddHandler php-fcgi .php
AddHandler fcgid-script .php Action php-fcgi /fcgi-bin/%(wrapper_name)s
FcgidWrapper %(wrapper_path)s
</Directory>""") % context </Directory>""") % context
return [ return [
(context['location'], directives), (context['location'], directives),
@ -295,7 +307,7 @@ class Apache2Backend(ServiceController):
def get_server_names(self, site): def get_server_names(self, site):
server_name = None server_name = None
server_alias = [] server_alias = []
for domain in site.domains.all(): for domain in site.domains.all().order_by('name'):
if not server_name and not domain.name.startswith('*'): if not server_name and not domain.name.startswith('*'):
server_name = domain.name server_name = domain.name
else: else:
@ -311,29 +323,28 @@ class Apache2Backend(ServiceController):
'site': site, 'site': site,
'site_name': site.name, 'site_name': site.name,
'ip': settings.WEBSITES_DEFAULT_IP, 'ip': settings.WEBSITES_DEFAULT_IP,
'site_unique_name': '0-'+site.unique_name, 'site_unique_name': site.unique_name,
'user': self.get_username(site), 'user': self.get_username(site),
'group': self.get_groupname(site), 'group': self.get_groupname(site),
'server_name': server_name, 'server_name': server_name,
'server_alias': server_alias, 'server_alias': server_alias,
# TODO remove '0-' 'sites_enabled': "%s.conf" % os.path.join(sites_enabled, site.unique_name),
'sites_enabled': "%s.conf" % os.path.join(sites_enabled, '0-'+site.unique_name), 'sites_available': "%s.conf" % os.path.join(sites_available, site.unique_name),
'sites_available': "%s.conf" % os.path.join(sites_available, '0-'+site.unique_name),
'access_log': site.get_www_access_log_path(), 'access_log': site.get_www_access_log_path(),
'error_log': site.get_www_error_log_path(), 'error_log': site.get_www_error_log_path(),
'banner': self.get_banner(), 'banner': self.get_banner(),
} }
return replace(context, "'", '"') return replace(context, "'", '"')
def get_content_context(self, content): def set_content_context(self, content, context):
context = self.get_context(content.website) content_context = {
context.update({
'type': content.webapp.type, 'type': content.webapp.type,
'location': normurlpath(content.path), 'location': normurlpath(content.path),
'app_name': content.webapp.name, 'app_name': content.webapp.name,
'app_path': content.webapp.get_path(), 'app_path': content.webapp.get_path(),
}) }
return replace(context, "'", '"') content_context = replace(content_context, "'", '"')
context.update(content_context)
class Apache2Traffic(ServiceMonitor): class Apache2Traffic(ServiceMonitor):

View File

@ -1,4 +1,5 @@
import os import os
from collections import OrderedDict
from django.db import models from django.db import models
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -69,8 +70,8 @@ class Website(models.Model):
@cached @cached
def get_directives(self): def get_directives(self):
directives = {} directives = OrderedDict()
for opt in self.directives.all(): for opt in self.directives.all().order_by('name', 'value'):
try: try:
directives[opt.name].append(opt.value) directives[opt.name].append(opt.value)
except KeyError: except KeyError:
@ -104,7 +105,7 @@ class Website(models.Model):
class WebsiteDirective(models.Model): class WebsiteDirective(models.Model):
website = models.ForeignKey(Website, verbose_name=_("web site"), website = models.ForeignKey(Website, verbose_name=_("web site"),
related_name='directives') related_name='directives')
name = models.CharField(_("name"), max_length=128, name = models.CharField(_("name"), max_length=128,
choices=SiteDirective.get_choices()) choices=SiteDirective.get_choices())
value = models.CharField(_("value"), max_length=256) value = models.CharField(_("value"), max_length=256)

View File

@ -64,7 +64,8 @@ class SelectPluginAdminMixin(object):
plugin_value = request.GET.get(self.plugin_field) or request.POST.get(self.plugin_field) plugin_value = request.GET.get(self.plugin_field) or request.POST.get(self.plugin_field)
if not plugin_value and request.method == 'POST': if not plugin_value and request.method == 'POST':
# HACK baceuse django add_preserved_filters removes extising queryargs # HACK baceuse django add_preserved_filters removes extising queryargs
value = re.search(r"type=([^&^']+)[&']", request.META.get('HTTP_REFERER', '')) value = re.search(r"%s=([^&^']+)[&']" % self.plugin_field,
request.META.get('HTTP_REFERER', ''))
if value: if value:
plugin_value = value.groups()[0] plugin_value = value.groups()[0]
return plugin_value return plugin_value