Only reload apache only when strictly necessary

This commit is contained in:
Marc Aymerich 2015-04-12 18:18:10 +00:00
parent 79ae1a79b0
commit 525d38750e
8 changed files with 48 additions and 39 deletions

12
TODO.md
View file

@ -286,6 +286,14 @@ https://code.djangoproject.com/ticket/24576
# 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?
# php version update should trigger webiste upgrade (wrapper name/fpm config for apache), public root and other config also needs apache to execute
* 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?
# Delete webapps deletes wrapper that may be used for other sites, maybe merging webapps is a bad idea after all? * replace unique_name by natural_key?
* do not require contact or create default
* 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
* fpm reload starts new pools?
* more processes for webmail, or use fpm pool
* rename resource.monitors to resource.backends ?
* abstract model classes enabling overriding?

View file

@ -142,8 +142,9 @@ def collect(instance, action, **kwargs):
operations = kwargs.get('operations', set()) operations = kwargs.get('operations', set())
route_cache = kwargs.get('route_cache', {}) route_cache = kwargs.get('route_cache', {})
for backend_cls in ServiceBackend.get_backends(): for backend_cls in ServiceBackend.get_backends():
# Check if there exists a related instance to be executed for this backend # Check if there exists a related instance to be executed for this backend and action
instances = [] instances = []
if action in backend_cls.actions:
if backend_cls.is_main(instance): if backend_cls.is_main(instance):
instances = [(instance, action)] instances = [(instance, action)]
else: else:

View file

@ -10,11 +10,9 @@ def run_monitor(modeladmin, request, queryset):
async = modeladmin.model.monitor.__defaults__[0] async = modeladmin.model.monitor.__defaults__[0]
logs = set() logs = set()
for resource in queryset: for resource in queryset:
results = resource.monitor() rlogs = resource.monitor()
if not async: if not async:
for result in results: logs = logs.union(set([str(rlog.pk) for rlog in rlogs]))
if hasattr(result, 'log'):
logs.add(str(result.log.pk))
modeladmin.log_change(request, resource, _("Run monitors")) modeladmin.log_change(request, resource, _("Run monitors"))
if async: if async:
num = len(queryset) num = len(queryset)

View file

@ -42,7 +42,7 @@ class ServiceMonitor(ServiceBackend):
from .models import MonitorData from .models import MonitorData
try: try:
return MonitorData.objects.filter(content_type=self.content_type, return MonitorData.objects.filter(content_type=self.content_type,
object_id=object_id).latest() monitor=type(self).get_name(), object_id=object_id).latest()
except MonitorData.DoesNotExist: except MonitorData.DoesNotExist:
return None return None

View file

@ -12,7 +12,7 @@ def monitor(resource_id, ids=None, async=True):
resource = Resource.objects.get(pk=resource_id) resource = Resource.objects.get(pk=resource_id)
resource_model = resource.content_type.model_class() resource_model = resource.content_type.model_class()
operations = [] logs = []
# Execute monitors # Execute monitors
for monitor_name in resource.monitors: for monitor_name in resource.monitors:
backend = ServiceMonitor.get_backend(monitor_name) backend = ServiceMonitor.get_backend(monitor_name)
@ -28,10 +28,9 @@ def monitor(resource_id, ids=None, async=True):
monitorings = [] monitorings = []
for obj in model.objects.filter(**kwargs): for obj in model.objects.filter(**kwargs):
op = Operation(backend, obj, Operation.MONITOR) op = Operation(backend, obj, Operation.MONITOR)
operations.append(op)
monitorings.append(op) monitorings.append(op)
# TODO async=True only when running with celery # TODO async=True only when running with celery
Operation.execute(monitorings, async=async) logs += Operation.execute(monitorings, async=async)
kwargs = {'id__in': ids} if ids else {} kwargs = {'id__in': ids} if ids else {}
# Update used resources and trigger resource exceeded and revovery # Update used resources and trigger resource exceeded and revovery
@ -50,4 +49,4 @@ def monitor(resource_id, ids=None, async=True):
op = Operation(backend, obj, Operation.RECOVERY) op = Operation(backend, obj, Operation.RECOVERY)
triggers.append(op) triggers.append(op)
Operation.execute(triggers) Operation.execute(triggers)
return operations return logs

View file

@ -33,7 +33,7 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
echo -e "${fpm_config}" | diff -N -I'^\s*;;' %(fpm_path)s - echo -e "${fpm_config}" | diff -N -I'^\s*;;' %(fpm_path)s -
} || { } || {
echo -e "${fpm_config}" > %(fpm_path)s echo -e "${fpm_config}" > %(fpm_path)s
UPDATEDFPM=1 UPDATED_FPM=1
} }
""") % context """) % context
) )
@ -46,7 +46,10 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
echo -e "${wrapper}" | diff -N -I'^\s*#' %(wrapper_path)s - echo -e "${wrapper}" | diff -N -I'^\s*#' %(wrapper_path)s -
} || { } || {
echo -e "${wrapper}" > %(wrapper_path)s echo -e "${wrapper}" > %(wrapper_path)s
[[ ${UPDATED_APACHE} -eq 0 ]] && UPDATED_APACHE=%(is_mounted)i if [[ %(is_mounted)i -eq 1 ]]; then
# Reload fcgid wrapper
pkill -SIGHUP -U %(user)s "^%(php_binary)s$" || true
fi
} }
""") % context """) % context
) )
@ -93,15 +96,14 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
def commit(self): def commit(self):
self.append(textwrap.dedent(""" self.append(textwrap.dedent("""
if [[ $UPDATEDFPM == 1 ]]; then if [[ $UPDATED_FPM -eq 1 ]]; then
service php5-fpm reload service php5-fpm reload
service php5-fpm start
fi fi
# Coordinate apache restart with apache backend # Coordinate apache restart with apache backend
locked=1 locked=1
state="$(grep -v 'PHPBackend' /dev/shm/restart.apache2)" || locked=0 state="$(grep -v 'PHPBackend' /dev/shm/restart.apache2)" || locked=0
echo -n "$state" > /dev/shm/restart.apache2 echo -n "$state" > /dev/shm/restart.apache2
if [[ $UPDATED_APACHE == 1 ]]; then if [[ $UPDATED_APACHE -eq 1 ]]; then
if [[ $locked == 0 ]]; then if [[ $locked == 0 ]]; then
service apache2 reload service apache2 reload
else else
@ -151,18 +153,19 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
init_vars = [ "-d %s='%s'" % (k, v.replace("'", '"')) for k,v in init_vars.items() ] init_vars = [ "-d %s='%s'" % (k, v.replace("'", '"')) for k,v in init_vars.items() ]
init_vars = ' \\\n '.join(init_vars) init_vars = ' \\\n '.join(init_vars)
context.update({ context.update({
'php_binary': os.path.normpath(settings.WEBAPPS_PHP_CGI_BINARY_PATH % context), 'php_binary_path': os.path.normpath(settings.WEBAPPS_PHP_CGI_BINARY_PATH % context),
'php_rc': os.path.normpath(settings.WEBAPPS_PHP_CGI_RC_DIR % context), 'php_rc': os.path.normpath(settings.WEBAPPS_PHP_CGI_RC_DIR % context),
'php_ini_scan': os.path.normpath(settings.WEBAPPS_PHP_CGI_INI_SCAN_DIR % context), 'php_ini_scan': os.path.normpath(settings.WEBAPPS_PHP_CGI_INI_SCAN_DIR % context),
'php_init_vars': init_vars, 'php_init_vars': init_vars,
}) })
context['php_binary'] = os.path.basename(context['php_binary_path'])
return textwrap.dedent("""\ return textwrap.dedent("""\
#!/bin/sh #!/bin/sh
# %(banner)s # %(banner)s
export PHPRC=%(php_rc)s export PHPRC=%(php_rc)s
export PHP_INI_SCAN_DIR=%(php_ini_scan)s export PHP_INI_SCAN_DIR=%(php_ini_scan)s
export PHP_FCGI_MAX_REQUESTS=%(max_requests)s export PHP_FCGI_MAX_REQUESTS=%(max_requests)s
exec %(php_binary)s %(php_init_vars)s""") % context exec %(php_binary_path)s %(php_init_vars)s""") % context
def get_fcgid_cmd_options(self, webapp, context): def get_fcgid_cmd_options(self, webapp, context):
maps = { maps = {

View file

@ -88,7 +88,7 @@ class Processes(AppOption):
# FPM pm.max_children # FPM pm.max_children
verbose_name = _("Number of processes") 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).") help_text = _("Maximum number of children that can be alive at the same time (a number between 0 and 9).")
regex = r'^[0-9]$' regex = r'^[0-9]{1,2}$'
group = AppOption.PROCESS group = AppOption.PROCESS

View file

@ -49,7 +49,7 @@
<div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">Pangea Hosting Management <span class="version">0.0.1a1</span></a></h1></div> <div id="branding"><a href="/admin/"></a><h1 id="site-name"><a href="/admin/">Pangea Hosting Management <span class="version">0.0.1a1</span></a></h1></div>
{% for item in menu.children %}{% admin_tools_render_menu_item item forloop.counter %}{% endfor %} {% for item in menu.children %}{% admin_tools_render_menu_item item forloop.counter %}{% endfor %}
<span style="float:right;color:grey;padding:10px;font-size:11px;">{% trans 'Welcome' %}, <span style="float:right;color:grey;padding:10px;font-size:11px;">{% trans 'Welcome' %},
{% url 'admin:users_user_change' user.pk as user_change_url %} {% url 'admin:accounts_account_change' user.pk as user_change_url %}
<a href="{{ user_change_url }}" style="color:#555;"><strong>{% filter force_escape %}{% firstof user.get_short_name user.username %}{% endfilter %}</strong></a>. <a href="{{ user_change_url }}" style="color:#555;"><strong>{% filter force_escape %}{% firstof user.get_short_name user.username %}{% endfilter %}</strong></a>.
<a href="{% url 'admin:password_change' %}" style="color:#555;">Change password</a> / <a href="{% url 'admin:logout' %}" style="color:#555;">Log out</a></span> <a href="{% url 'admin:password_change' %}" style="color:#555;">Change password</a> / <a href="{% url 'admin:logout' %}" style="color:#555;">Log out</a></span>
</div> </div>