Improved performance of webapps and websites change lists

This commit is contained in:
Marc Aymerich 2016-02-17 12:32:30 +00:00
parent 50ff252be7
commit 4301d76011
11 changed files with 48 additions and 24 deletions

View File

@ -11,6 +11,7 @@ Orchestra is a Django-based framework for building web hosting control panels.
Motivation
----------
There are a lot of widely used open source hosting control panels, however, none of them seems apropiate when you already have an existing service infrastructure or simply you want your services to run on a particular architecture.
The goal of this project is to provide the tools for easily build a fully featured control panel that is not tied to any particular service architecture.
@ -33,9 +34,9 @@ Overview
Fast Deployment Setup
---------------------
This deployment is **not suitable for production** but more than enough for checking out this project. Checkout the steps for other deployments:
* [development](INSTALLDEV.md)
* [production](INSTALL.md)
This deployment is **not suitable for production** but more than enough for checking out this project. For other deployments checkout these links:
* [Development](INSTALLDEV.md)
* [Production](INSTALL.md)
```bash
# Create and activate a Python virtualenv

View File

@ -50,13 +50,15 @@ class WebAppOptionInline(admin.TabularInline):
class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin):
list_display = ('name', 'display_type', 'display_detail', 'display_websites', 'account_link')
list_display = (
'name', 'display_type', 'display_detail', 'display_websites', 'account_link'
)
list_filter = ('type', HasWebsiteListFilter, PHPVersionListFilter)
inlines = [WebAppOptionInline]
readonly_fields = ('account_link', )
change_readonly_fields = ('name', 'type', 'display_websites')
search_fields = ('name', 'account__username', 'data', 'website__domains__name')
list_prefetch_related = ('content_set__website',)
list_prefetch_related = ('content_set__website', 'content_set__website__domains')
plugin = AppType
plugin_field = 'type'
plugin_title = _("Web application type")
@ -67,7 +69,8 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
def display_websites(self, webapp):
websites = []
for content in webapp.content_set.all():
site_link = get_on_site_link(content.get_absolute_url())
site_url = content.get_absolute_url()
site_link = get_on_site_link(site_url)
website = content.website
admin_url = change_url(website)
name = "%s on %s" % (website.name, content.path)

View File

@ -55,7 +55,8 @@ class WebAppServiceMixin(object):
self.append("rm -fr %(app_path)s" % context)
def get_context(self, webapp):
context = {
context = webapp.type_instance.get_directive_context()
context.update({
'user': webapp.get_username(),
'group': webapp.get_groupname(),
'app_name': webapp.name,
@ -64,7 +65,7 @@ class WebAppServiceMixin(object):
'banner': self.get_banner(),
'under_construction_path': settings.WEBAPPS_UNDER_CONSTRUCTION_PATH,
'is_mounted': webapp.content_set.exists(),
}
})
context['deleted_app_path'] = settings.WEBAPPS_MOVE_ON_DELETE_PATH % context
return context

View File

@ -167,6 +167,7 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
echo "$state" | grep -v ' RESTART$' || is_last=1
}
if [[ $is_last -eq 1 ]]; then
echo "Last backend to run, update: $UPDATED_APACHE, state: '$state'"
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
if service apache2 status > /dev/null; then
service apache2 reload
@ -280,10 +281,8 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
return context
def get_context(self, webapp):
context = super(PHPBackend, self).get_context(webapp)
context = super().get_context(webapp)
context.update({
'php_version': webapp.type_instance.get_php_version(),
'php_version_number': webapp.type_instance.get_php_version_number(),
'max_requests': settings.WEBAPPS_PHP_MAX_REQUESTS,
})
self.update_fpm_context(webapp, context)

View File

@ -4,8 +4,8 @@ from orchestra.settings import ORCHESTRA_BASE_DOMAIN
from .. import webapps
_names = ('home', 'user', 'group', 'app_type', 'app_name', 'app_type', 'app_id')
_php_names = _names + ('php_version', 'php_version_number',)
_names = ('home', 'user', 'user_id', 'group', 'app_type', 'app_name', 'app_type', 'app_id', 'account_id')
_php_names = _names + ('php_version', 'php_version_number', 'php_version_int')
_python_names = _names + ('python_version', 'python_version_number',)
@ -17,8 +17,11 @@ WEBAPPS_BASE_DIR = Setting('WEBAPPS_BASE_DIR',
WEBAPPS_FPM_LISTEN = Setting('WEBAPPS_FPM_LISTEN',
'/opt/php/5.4/socks/%(user)s-%(app_name)s.sock',
help_text=("TCP socket example: <tt>127.0.0.1:9%(app_id)03d</tt><br>"
'127.0.0.1:5%(app_id)04d',
help_text=("TCP socket example: <tt>127.0.0.1:5%(app_id)04d</tt><br>"
"UDS example: <tt>/var/lib/php/sockets/%(user)s-%(app_name)s.sock</tt><br>"
"Merged TCP example: <tt>127.0.0.1:%(php_version_int)02d%(account_id)03d</tt></br>"
"Merged UDS example: <tt>/var/lib/php/sockets/%(user)s-%(php_version)s.sock</tt></br>"
"Available fromat names: <tt>{}</tt>").format(', '.join(_php_names)),
validators=[Setting.string_format_validator(_php_names)],
)

View File

@ -85,6 +85,8 @@ class AppType(plugins.Plugin, metaclass=plugins.PluginMount):
return {
'app_id': self.instance.id,
'app_name': self.instance.name,
'user': self.instance.account.username,
'user': self.instance.get_username(),
'user_id': self.instance.account.main_systemuser_id,
'home': self.instance.account.main_systemuser.get_home(),
'account_id': self.instance.account_id,
}

View File

@ -121,7 +121,6 @@ class PHPApp(AppType):
init_vars['post_max_size'] = post_max_size
if upload_max_filesize_value > post_max_size_value:
init_vars['post_max_size'] = upload_max_filesize
print(init_vars)
return init_vars
def get_directive_context(self):
@ -129,6 +128,7 @@ class PHPApp(AppType):
context.update({
'php_version': self.get_php_version(),
'php_version_number': self.get_php_version_number(),
'php_version_int': int(self.get_php_version_number().replace('.', '')),
})
return context

View File

@ -11,6 +11,7 @@ from orchestra.admin.utils import admin_link, change_url
from orchestra.contrib.accounts.actions import list_accounts
from orchestra.contrib.accounts.admin import AccountAdminMixin, SelectAccountAdminMixin
from orchestra.forms.widgets import DynamicHelpTextSelect
from orchestra.utils.html import get_on_site_link
from .directives import SiteDirective
from .forms import WebsiteAdminForm, WebsiteDirectiveInlineFormSet
@ -84,10 +85,16 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
def display_webapps(self, website):
webapps = []
for content in website.content_set.all():
site_link = get_on_site_link(content.get_absolute_url())
webapp = content.webapp
detail = webapp.get_type_display()
try:
detail += ' ' + webapp.type_instance.get_detail()
except KeyError:
pass
url = change_url(webapp)
name = "%s on %s" % (webapp.name, content.path or '/')
webapps.append('<a href="%s">%s</a>' % (url, name))
webapps.append('<a href="%s" title="%s">%s %s</a>' % (url, detail, name, site_link))
return '<br>'.join(webapps)
display_webapps.allow_tags = True
display_webapps.short_description = _("Web apps")

View File

@ -160,6 +160,7 @@ class Apache2Backend(ServiceController):
echo "$state" | grep -v ' RESTART$' || is_last=1
}
if [[ $is_last -eq 1 ]]; then
echo "Last backend to run, update: $UPDATED_APACHE, state: '$state'"
if [[ $UPDATED_APACHE -eq 1 || "$state" =~ .*RESTART$ ]]; then
if service apache2 status > /dev/null; then
service apache2 reload
@ -218,6 +219,7 @@ class Apache2Backend(ServiceController):
# UNIX socket
target = 'unix:%(socket)s|fcgi://127.0.0.1%(app_path)s/'
if context['location']:
# FIXME unix sockets do not support $1
target = 'unix:%(socket)s|fcgi://127.0.0.1%(app_path)s/$1'
context.update({
'app_path': os.path.normpath(app_path),

View File

@ -83,8 +83,11 @@ class Website(models.Model):
return directives
def get_absolute_url(self):
domain = self.domains.first()
if domain:
try:
domain = self.domains.all()[0]
except IndexError:
return
else:
return '%s://%s' % (self.get_protocol(), domain)
def get_user(self):
@ -113,7 +116,7 @@ class WebsiteDirective(models.Model):
website = models.ForeignKey(Website, verbose_name=_("web site"),
related_name='directives')
name = models.CharField(_("name"), max_length=128,
choices=SiteDirective.get_choices())
choices=SiteDirective.get_choices())
value = models.CharField(_("value"), max_length=256)
def __str__(self):
@ -157,6 +160,9 @@ class Content(models.Model):
self.path = '/'
def get_absolute_url(self):
domain = self.website.domains.first()
if domain:
try:
domain = self.website.domains.all()[0]
except IndexError:
return
else:
return '%s://%s%s' % (self.website.get_protocol(), domain, self.path)

View File

@ -29,7 +29,7 @@ def html_to_pdf(html, pagination=False):
def get_on_site_link(url):
context = {
'title': _("View on site"),
'title': _("View on site %s") % url,
'url': url,
'image': '<img src="%s"></img>' % static('orchestra/images/view-on-site.png'),
}