From 4301d76011b7a06677fb53fabe8da22d841e72c0 Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Wed, 17 Feb 2016 12:32:30 +0000 Subject: [PATCH] Improved performance of webapps and websites change lists --- README.md | 7 ++++--- orchestra/contrib/webapps/admin.py | 9 ++++++--- orchestra/contrib/webapps/backends/__init__.py | 5 +++-- orchestra/contrib/webapps/backends/php.py | 5 ++--- orchestra/contrib/webapps/settings.py | 11 +++++++---- orchestra/contrib/webapps/types/__init__.py | 4 +++- orchestra/contrib/webapps/types/php.py | 2 +- orchestra/contrib/websites/admin.py | 9 ++++++++- orchestra/contrib/websites/backends/apache.py | 2 ++ orchestra/contrib/websites/models.py | 16 +++++++++++----- orchestra/utils/html.py | 2 +- 11 files changed, 48 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 29201309..668b5dd3 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/orchestra/contrib/webapps/admin.py b/orchestra/contrib/webapps/admin.py index 59b5dd5b..40966a16 100644 --- a/orchestra/contrib/webapps/admin.py +++ b/orchestra/contrib/webapps/admin.py @@ -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) diff --git a/orchestra/contrib/webapps/backends/__init__.py b/orchestra/contrib/webapps/backends/__init__.py index 77b8ac4d..57c2c77e 100644 --- a/orchestra/contrib/webapps/backends/__init__.py +++ b/orchestra/contrib/webapps/backends/__init__.py @@ -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 diff --git a/orchestra/contrib/webapps/backends/php.py b/orchestra/contrib/webapps/backends/php.py index 849b7c8c..4119f8e0 100644 --- a/orchestra/contrib/webapps/backends/php.py +++ b/orchestra/contrib/webapps/backends/php.py @@ -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) diff --git a/orchestra/contrib/webapps/settings.py b/orchestra/contrib/webapps/settings.py index ccb437de..b8614dc2 100644 --- a/orchestra/contrib/webapps/settings.py +++ b/orchestra/contrib/webapps/settings.py @@ -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: 127.0.0.1:9%(app_id)03d
" + '127.0.0.1:5%(app_id)04d', + help_text=("TCP socket example: 127.0.0.1:5%(app_id)04d
" + "UDS example: /var/lib/php/sockets/%(user)s-%(app_name)s.sock
" + "Merged TCP example: 127.0.0.1:%(php_version_int)02d%(account_id)03d
" + "Merged UDS example: /var/lib/php/sockets/%(user)s-%(php_version)s.sock
" "Available fromat names: {}").format(', '.join(_php_names)), validators=[Setting.string_format_validator(_php_names)], ) diff --git a/orchestra/contrib/webapps/types/__init__.py b/orchestra/contrib/webapps/types/__init__.py index fdaba1c7..4e07a2a9 100644 --- a/orchestra/contrib/webapps/types/__init__.py +++ b/orchestra/contrib/webapps/types/__init__.py @@ -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, } diff --git a/orchestra/contrib/webapps/types/php.py b/orchestra/contrib/webapps/types/php.py index 3ab2c4df..5764f276 100644 --- a/orchestra/contrib/webapps/types/php.py +++ b/orchestra/contrib/webapps/types/php.py @@ -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 diff --git a/orchestra/contrib/websites/admin.py b/orchestra/contrib/websites/admin.py index a8c7dec3..6bb2f246 100644 --- a/orchestra/contrib/websites/admin.py +++ b/orchestra/contrib/websites/admin.py @@ -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('%s' % (url, name)) + webapps.append('%s %s' % (url, detail, name, site_link)) return '
'.join(webapps) display_webapps.allow_tags = True display_webapps.short_description = _("Web apps") diff --git a/orchestra/contrib/websites/backends/apache.py b/orchestra/contrib/websites/backends/apache.py index 89dd2b55..9ea4f8fa 100644 --- a/orchestra/contrib/websites/backends/apache.py +++ b/orchestra/contrib/websites/backends/apache.py @@ -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), diff --git a/orchestra/contrib/websites/models.py b/orchestra/contrib/websites/models.py index 7e3b57b7..85a82f14 100644 --- a/orchestra/contrib/websites/models.py +++ b/orchestra/contrib/websites/models.py @@ -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) diff --git a/orchestra/utils/html.py b/orchestra/utils/html.py index 16b590bf..f888c256 100644 --- a/orchestra/utils/html.py +++ b/orchestra/utils/html.py @@ -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': '' % static('orchestra/images/view-on-site.png'), }