Random fixes

This commit is contained in:
Marc Aymerich 2015-03-18 21:51:12 +00:00
parent e5e0d3aa96
commit 7711988a63
16 changed files with 86 additions and 59 deletions

View file

@ -206,6 +206,12 @@ Php binaries should have this format: /usr/bin/php5.2-cgi
* better validate options and directives (url locations, filesystem paths, etc..)
* filter php deprecated options out based on version
* order virtualhost locations /hola / including directive
* make sure that you understand the risks
* full support for deactivation of services/accounts
* Display admin.is_active (disabled account/order by)
* show details data on webapp changelist

View file

@ -79,16 +79,10 @@ class Account(auth.AbstractBaseUser):
# Trigger save() on related objects that depend on this account
for rel in self._meta.get_all_related_objects():
source = getattr(rel, 'related_model', rel.model)
if not source in services:
continue
try:
source._meta.get_field_by_name('is_active')
except models.FieldDoesNotExist:
continue
else:
if source in services and hasattr(source, 'active'):
for obj in getattr(self, rel.get_accessor_name()).all():
obj.save(update_fields=[])
def send_email(self, template, context, contacts=[], attachments=[], html=None):
contacts = self.contacts.filter(email_usages=contacts)
email_to = contacts.values_list('email', flat=True)

View file

@ -46,7 +46,7 @@ class MailmanBackend(ServiceController):
self.append('sed -i "/^%(address_domain)s\s*$/d" %(virtual_alias_domains)s' % context)
def get_virtual_aliases(self, context):
aliases = []
aliases = ['# %(banner)s' % context]
for address in self.addresses:
context['address'] = address
aliases.append("%(address_name)s%(address)s@%(domain)s\t%(name)s%(address)s" % context)
@ -65,15 +65,13 @@ class MailmanBackend(ServiceController):
# Preserve indentation
self.append(textwrap.dedent("""\
if [[ ! $(grep '\s\s*%(name)s\s*$' %(virtual_alias)s) ]]; then
echo '# %(banner)s\n%(aliases)s
' >> %(virtual_alias)s
echo '%(aliases)s' >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
else
if [[ ! $(grep '^\s*%(address_name)s@%(address_domain)s\s\s*%(name)s\s*$' %(virtual_alias)s) ]]; then
sed -i -e '/^.*\s%(name)s\(%(address_regex)s\)\s*$/d' \\
-e 'N; /^\s*\\n\s*$/d; P; D' %(virtual_alias)s
echo '# %(banner)s\n%(aliases)s
' >> %(virtual_alias)s
echo '%(aliases)s' >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
fi
fi""") % context
@ -99,15 +97,19 @@ class MailmanBackend(ServiceController):
'%(mailman_root)s/bin/change_pw --listname="%(name)s" --password="%(password)s"' % context
)
self.include_virtual_alias_domain(context)
if mail_list.active:
self.append('chmod 775 %(mailman_root)s/lists/%(name)s' % context)
else:
self.append('chmod 000 %(mailman_root)s/lists/%(name)s' % context)
def delete(self, mail_list):
context = self.get_context(mail_list)
self.exclude_virtual_alias_domain(context)
self.append(textwrap.dedent("""\
self.append(textwrap.dedent("""
sed -i -e '/^.*\s%(name)s\(%(address_regex)s\)\s*$/d' \\
-e 'N; /^\s*\\n\s*$/d; P; D' %(virtual_alias)s""") % context
)
self.append(textwrap.dedent("""\
self.append(textwrap.dedent("""
# Non-existent list archives produce exit code 1
exit_code=0
rmlist -a %(name)s || exit_code=$?
@ -119,9 +121,12 @@ class MailmanBackend(ServiceController):
def commit(self):
context = self.get_context_files()
self.append(textwrap.dedent("""
[[ $UPDATED_VIRTUAL_ALIAS == 1 ]] && { postmap %(virtual_alias)s; }
[[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]] && { /etc/init.d/postfix reload; }
""") % context
if [[ $UPDATED_VIRTUAL_ALIAS == 1 ]]; then
postmap %(virtual_alias)s
fi
if [[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]]; then
/etc/init.d/postfix reload
fi""") % context
)
def get_context_files(self):

View file

@ -1,4 +1,5 @@
from django.db import models
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from orchestra.core import services
@ -20,7 +21,10 @@ class List(models.Model):
help_text=_("Administration email address"))
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
related_name='lists')
# TODO also admin
# TODO is_active = models.BooleanField(_("active"), default=True,
# help_text=_("Designates whether this account should be treated as active. "
# "Unselect this instead of deleting accounts."))
password = None
class Meta:
@ -35,6 +39,10 @@ class List(models.Model):
return "%s@%s" % (self.address_name, self.address_domain)
return ''
@cached_property
def active(self):
return self.is_active and self.account.is_active
def get_address_name(self):
return self.address_name or self.name

View file

@ -21,16 +21,13 @@ def compute_resource_usage(data):
slot = (data.created_at-ini).total_seconds()
result += data.value * slot/total
ini = data.created_at
elif resource.period == resource.MONTHLY_SUM:
elif resource.period in (resource.MONTHLY_SUM, resource.LAST):
# FIXME Aggregation of 0s returns None! django bug?
# value = dataset.aggregate(models.Sum('value'))['value__sum']
values = dataset.values_list('value', flat=True)
if values:
has_result = True
result += sum(values)
elif resource.period == resource.LAST:
result += dataset.value
has_result = True
else:
raise NotImplementedError("%s support not implemented" % data.period)
return float(result)/resource.get_scale() if has_result else None

View file

@ -239,8 +239,11 @@ class ResourceData(models.Model):
)
)
elif resource.period == resource.LAST:
# Get last monitoring data per object_id
try:
datasets.append(dataset.latest())
datasets.append(
dataset.order_by('object_id', '-id').distinct('object_id')
)
except MonitorData.DoesNotExist:
continue
else:

View file

@ -30,7 +30,7 @@ def monitor(resource_id, ids=None, async=True):
op = Operation.create(backend, obj, Operation.MONITOR)
operations.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)
kwargs = {'id__in': ids} if ids else {}

View file

@ -24,7 +24,8 @@ class WebApp(models.Model):
choices=AppType.get_plugin_choices())
account = models.ForeignKey('accounts.Account', verbose_name=_("Account"),
related_name='webapps')
data = JSONField(_("data"), help_text=_("Extra information dependent of each service."))
data = JSONField(_("data"), blank=True,
help_text=_("Extra information dependent of each service."))
class Meta:
unique_together = ('name', 'account')
@ -122,4 +123,7 @@ def type_save(sender, *args, **kwargs):
@receiver(pre_delete, sender=WebApp, dispatch_uid='webapps.type.delete')
def type_delete(sender, *args, **kwargs):
instance = kwargs['instance']
instance.type_instance.delete()
try:
instance.type_instance.delete()
except KeyError:
pass

View file

@ -336,8 +336,8 @@ class PHPUploadMaxFileSize(AppOption):
group = AppOption.PHP
class PHPPostMaxSize(AppOption):
name = 'post_max_size'
verbose_name = _("zend_extension")
class PHPZendExtension(AppOption):
name = 'zend_extension'
verbose_name = _("Zend extension")
regex = r'^[^ ]+$'
group = AppOption.PHP

View file

@ -142,7 +142,7 @@ WEBAPPS_ENABLED_OPTIONS = getattr(settings, 'WEBAPPS_ENABLED_OPTIONS', (
'orchestra.apps.webapps.options.PHPSuhosinSimulation',
'orchestra.apps.webapps.options.PHPSuhosinExecutorIncludeWhitelist',
'orchestra.apps.webapps.options.PHPUploadMaxFileSize',
'orchestra.apps.webapps.options.PHPPostMaxSize',
'orchestra.apps.webapps.options.PHPZendExtension',
))

View file

@ -13,11 +13,11 @@ from orchestra.forms.widgets import DynamicHelpTextSelect
from . import settings
from .directives import SiteDirective
from .forms import WebsiteAdminForm
from .models import Content, Website, Directive
from .models import Content, Website, WebsiteDirective
class DirectiveInline(admin.TabularInline):
model = Directive
class WebsiteDirectiveInline(admin.TabularInline):
model = WebsiteDirective
extra = 1
DIRECTIVES_HELP_TEXT = {
@ -37,7 +37,7 @@ class DirectiveInline(admin.TabularInline):
kwargs['widget'] = DynamicHelpTextSelect(
'this.id.replace("name", "value")', self.DIRECTIVES_HELP_TEXT
)
return super(DirectiveInline, self).formfield_for_dbfield(db_field, **kwargs)
return super(WebsiteDirectiveInline, self).formfield_for_dbfield(db_field, **kwargs)
class ContentInline(AccountAdminMixin, admin.TabularInline):
@ -61,7 +61,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
list_display = ('name', 'display_domains', 'display_webapps', 'account_link')
list_filter = ('protocol', 'is_active',)
change_readonly_fields = ('name',)
inlines = [ContentInline, DirectiveInline]
inlines = [ContentInline, WebsiteDirectiveInline]
filter_horizontal = ['domains']
fieldsets = (
(None, {

View file

@ -245,14 +245,14 @@ class Apache2Backend(ServiceController):
option = site.get_directives().get('user_group')
if option:
return option[0]
return site.account.username
return site.get_username()
def get_groupname(self, site):
option = site.get_directives().get('user_group')
if option and ' ' in option:
user, group = option.split()
return group
return site.account.username
return site.get_groupname()
def get_context(self, site):
base_apache_conf = settings.WEBSITES_BASE_APACHE_CONF

View file

@ -21,7 +21,9 @@ 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
chmod g+xr %(webalizer_path)s
""") % context
)
def delete(self, content):

View file

@ -84,13 +84,13 @@ class UserGroup(SiteDirective):
group = SiteDirective.HTTPD
def validate(self, directive):
super(UserGroupDirective, self).validate(directive)
options = directive.split()
syetmusers = [options[0]]
super(UserGroup, self).validate(directive)
options = directive.value.split()
systemusers = [options[0]]
if len(options) > 1:
systemusers.append(options[1])
# TODO not sure about this dependency maybe make it part of pangea only
from orchestra.apps.users.models import SystemUser
from orchestra.apps.systemusers.models import SystemUser
errors = []
for user in systemusers:
if not SystemUser.objects.filter(username=user).exists():

View file

@ -46,12 +46,19 @@ class Website(models.Model):
@property
def unique_name(self):
return settings.WEBSITES_UNIQUE_NAME_FORMAT % {
context = self.get_settings_context()
return settings.WEBSITES_UNIQUE_NAME_FORMAT % context
def get_settings_context(self):
""" format settings strings """
return {
'id': self.id,
'pk': self.pk,
'account': self.account.username,
'home': self.get_user().get_home(),
'user': self.get_username(),
'group': self.get_groupname(),
'site_name': self.name,
'protocol': self.protocol,
'name': self.name,
}
def get_protocol(self):
@ -74,27 +81,27 @@ class Website(models.Model):
if domain:
return '%s://%s' % (self.get_protocol(), domain)
def get_www_log_context(self):
return {
'home': self.account.main_systemuser.get_home(),
'account': self.account.username,
'user': self.account.username,
'site_name': self.name,
'unique_name': self.unique_name
}
def get_user(self):
return self.account.main_systemuser
def get_username(self):
return self.get_user().username
def get_groupname(self):
return self.get_username()
def get_www_access_log_path(self):
context = self.get_www_log_context()
context = self.get_settings_context()
path = settings.WEBSITES_WEBSITE_WWW_ACCESS_LOG_PATH % context
return os.path.normpath(path.replace('//', '/'))
def get_www_error_log_path(self):
context = self.get_www_log_context()
context = self.get_settings_context()
path = settings.WEBSITES_WEBSITE_WWW_ERROR_LOG_PATH % context
return os.path.normpath(path.replace('//', '/'))
class Directive(models.Model):
class WebsiteDirective(models.Model):
website = models.ForeignKey(Website, verbose_name=_("web site"),
related_name='directives')
name = models.CharField(_("name"), max_length=128,

View file

@ -3,7 +3,7 @@ from django.utils.translation import ugettext_lazy as _
WEBSITES_UNIQUE_NAME_FORMAT = getattr(settings, 'WEBSITES_UNIQUE_NAME_FORMAT',
'%(account)s-%(name)s')
'%(user)s-%(site_name)s')
# TODO 'http', 'https', 'https-only', 'http and https' and rename to PROTOCOL
@ -72,3 +72,4 @@ WEBSITES_TRAFFIC_IGNORE_HOSTS = getattr(settings, 'WEBSITES_TRAFFIC_IGNORE_HOSTS
#WEBSITES_DEFAULT_SSl_KEY = getattr(settings, 'WEBSITES_DEFAULT_SSl_KEY',
# '')