Improved db indexes
This commit is contained in:
parent
4301d76011
commit
ebd5ff03ce
2
TODO.md
2
TODO.md
|
@ -461,6 +461,6 @@ mkhomedir_helper or create ssh homes with bash.rc and such
|
|||
# TODO save serialized versions ob backendoperation.instance in order to allow backend reexecution of deleted objects
|
||||
|
||||
|
||||
|
||||
# INDEXES for most used queries: account FK
|
||||
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ def admin_link(*args, **kwargs):
|
|||
return '---'
|
||||
display = kwargs.get('display')
|
||||
if display:
|
||||
display = getattr(obj, display, None)
|
||||
display = getattr(obj, display, display)
|
||||
else:
|
||||
display = obj
|
||||
try:
|
||||
|
@ -123,7 +123,8 @@ def admin_link(*args, **kwargs):
|
|||
extra = ''
|
||||
if kwargs['popup']:
|
||||
extra = 'onclick="return showAddAnotherPopup(this);"'
|
||||
return mark_safe('<a href="%s" %s>%s</a>' % (url, extra, display))
|
||||
title = "Change %s" % obj._meta.verbose_name
|
||||
return mark_safe('<a href="%s" title="%s" %s>%s</a>' % (url, title, extra, display))
|
||||
|
||||
|
||||
@admin_field
|
||||
|
|
|
@ -16,7 +16,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
||||
from orchestra.admin.actions import SendEmail
|
||||
from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query, change_url
|
||||
from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query
|
||||
from orchestra.core import services, accounts
|
||||
from orchestra.forms import UserChangeForm
|
||||
|
||||
|
@ -189,8 +189,7 @@ class AccountAdminMixin(object):
|
|||
|
||||
def account_link(self, instance):
|
||||
account = instance.account if instance.pk else self.account
|
||||
url = change_url(account)
|
||||
return '<a href="%s">%s</a>' % (url, account)
|
||||
return admin_link()(account)
|
||||
account_link.short_description = _("account")
|
||||
account_link.allow_tags = True
|
||||
account_link.admin_order_field = 'account__username'
|
||||
|
|
|
@ -85,7 +85,9 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
for website in websites:
|
||||
site_link = get_on_site_link(website.get_absolute_url())
|
||||
admin_url = change_url(website)
|
||||
link = '<a href="%s">%s %s</a>' % (admin_url, website.name, site_link)
|
||||
title = _("Edit website")
|
||||
link = '<a href="%s" title="%s">%s %s</a>' % (
|
||||
admin_url, title, website.name, site_link)
|
||||
links.append(link)
|
||||
return '<br>'.join(links)
|
||||
site_link = get_on_site_link('http://%s' % domain.name)
|
||||
|
@ -127,7 +129,7 @@ class DomainAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
|||
structured_name=Concat('top__name', 'name')
|
||||
).order_by('-structured_id', 'structured_name')
|
||||
if apps.isinstalled('orchestra.contrib.websites'):
|
||||
qs = qs.prefetch_related('websites')
|
||||
qs = qs.prefetch_related('websites__domains')
|
||||
return qs
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.contrib.domains.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('domains', '0004_auto_20150720_1121'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='name',
|
||||
field=models.CharField(max_length=256, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], db_index=True, verbose_name='name', unique=True, help_text='Domain or subdomain name.'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='top',
|
||||
field=models.ForeignKey(editable=False, verbose_name='top domain', related_name='subdomain_set', to='domains.Domain', null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='record',
|
||||
name='type',
|
||||
field=models.CharField(max_length=32, verbose_name='type', choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF'), ('SOA', 'SOA')]),
|
||||
),
|
||||
]
|
|
@ -24,7 +24,7 @@ class DomainQuerySet(models.QuerySet):
|
|||
|
||||
|
||||
class Domain(models.Model):
|
||||
name = models.CharField(_("name"), max_length=256, unique=True,
|
||||
name = models.CharField(_("name"), max_length=256, unique=True, db_index=True,
|
||||
help_text=_("Domain or subdomain name."),
|
||||
validators=[
|
||||
validators.validate_domain_name,
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mailboxes', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='mailbox',
|
||||
name='filtering',
|
||||
field=models.CharField(max_length=16, choices=[('CUSTOM', 'Custom filtering'), ('DISABLE', 'Disable'), ('REDIRECT', 'Archive spam (Score≥8)'), ('REDIRECT5', 'Archive spam (Score≥5)'), ('REJECT', 'Reject spam (Score≥8)'), ('REJECT5', 'Reject spam (Score≥5)')], default='REDIRECT'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='mailbox',
|
||||
name='name',
|
||||
field=models.CharField(max_length=64, db_index=True, unique=True, help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid mailbox name.')], verbose_name='name'),
|
||||
),
|
||||
]
|
|
@ -14,7 +14,7 @@ from . import validators, settings
|
|||
class Mailbox(models.Model):
|
||||
CUSTOM = 'CUSTOM'
|
||||
|
||||
name = models.CharField(_("name"), max_length=64, unique=True,
|
||||
name = models.CharField(_("name"), max_length=64, unique=True, db_index=True,
|
||||
help_text=_("Required. %s characters or fewer. Letters, digits and ./-/_ only.") %
|
||||
settings.MAILBOXES_NAME_MAX_LENGTH,
|
||||
validators=[
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mailer', '0004_auto_20150805_1328'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='last_try',
|
||||
field=models.DateTimeField(null=True, db_index=True, verbose_name='last try'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='priority',
|
||||
field=models.PositiveIntegerField(default=2, choices=[(0, 'Critical (not queued)'), (1, 'High'), (2, 'Normal'), (3, 'Low')], db_index=True, verbose_name='Priority'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='retries',
|
||||
field=models.PositiveIntegerField(default=0, db_index=True, verbose_name='retries'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='state',
|
||||
field=models.CharField(default='QUEUED', choices=[('QUEUED', 'Queued'), ('SENT', 'Sent'), ('DEFERRED', 'Deferred'), ('FAILED', 'Failed')], db_index=True, max_length=16, verbose_name='State'),
|
||||
),
|
||||
]
|
|
@ -27,15 +27,17 @@ class Message(models.Model):
|
|||
(LOW, _("Low")),
|
||||
)
|
||||
|
||||
state = models.CharField(_("State"), max_length=16, choices=STATES, default=QUEUED)
|
||||
priority = models.PositiveIntegerField(_("Priority"), choices=PRIORITIES, default=NORMAL)
|
||||
state = models.CharField(_("State"), max_length=16, choices=STATES, default=QUEUED,
|
||||
db_index=True)
|
||||
priority = models.PositiveIntegerField(_("Priority"), choices=PRIORITIES, default=NORMAL,
|
||||
db_index=True)
|
||||
to_address = models.CharField(max_length=256)
|
||||
from_address = models.CharField(max_length=256)
|
||||
subject = models.TextField(_("subject"))
|
||||
content = models.TextField(_("content"))
|
||||
created_at = models.DateTimeField(_("created at"), auto_now_add=True)
|
||||
retries = models.PositiveIntegerField(_("retries"), default=0)
|
||||
last_try = models.DateTimeField(_("last try"), null=True)
|
||||
retries = models.PositiveIntegerField(_("retries"), default=0, db_index=True)
|
||||
last_try = models.DateTimeField(_("last try"), null=True, db_index=True)
|
||||
|
||||
def __str__(self):
|
||||
return '%s to %s' % (self.subject, self.to_address)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.core.validators
|
||||
import orchestra.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '0005_auto_20150709_1016'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='route',
|
||||
name='backend',
|
||||
field=models.CharField(choices=[('Apache2Traffic', '[M] Apache 2 Traffic'), ('ApacheTrafficByName', '[M] ApacheTrafficByName'), ('DokuWikiMuTraffic', '[M] DokuWiki MU Traffic'), ('DovecotMaildirDisk', '[M] Dovecot Maildir size'), ('Exim4Traffic', '[M] Exim4 traffic'), ('MailmanSubscribers', '[M] Mailman subscribers'), ('MailmanTraffic', '[M] Mailman traffic'), ('MysqlDisk', '[M] MySQL disk'), ('OpenVZTraffic', '[M] OpenVZTraffic'), ('PostfixMailscannerTraffic', '[M] Postfix-Mailscanner traffic'), ('UNIXUserDisk', '[M] UNIX user disk'), ('VsFTPdTraffic', '[M] VsFTPd traffic'), ('WordpressMuTraffic', '[M] Wordpress MU Traffic'), ('OwnCloudDiskQuota', '[M] ownCloud SaaS Disk Quota'), ('OwncloudTraffic', '[M] ownCloud SaaS Traffic'), ('PhpListTraffic', '[M] phpList SaaS Traffic'), ('Apache2Backend', '[S] Apache 2'), ('BSCWBackend', '[S] BSCW SaaS'), ('Bind9MasterDomainBackend', '[S] Bind9 master domain'), ('Bind9SlaveDomainBackend', '[S] Bind9 slave domain'), ('DokuWikiMuBackend', '[S] DokuWiki multisite'), ('DrupalMuBackend', '[S] Drupal multisite'), ('GitLabSaaSBackend', '[S] GitLab SaaS'), ('AutoresponseBackend', '[S] Mail autoresponse'), ('MailScannerSpamRuleBackend', '[S] MailScanner ruleset'), ('MailmanBackend', '[S] Mailman'), ('MailmanVirtualDomainBackend', '[S] Mailman virtdomain-only'), ('MoodleBackend', '[S] Moodle'), ('MoodleWWWRootBackend', '[S] Moodle WWWRoot (required)'), ('MoodleMuBackend', '[S] Moodle multisite'), ('MySQLBackend', '[S] MySQL database'), ('MySQLUserBackend', '[S] MySQL user'), ('PHPBackend', '[S] PHP FPM/FCGID'), ('PangeaProxmoxOVZ', '[S] PangeaProxmoxOVZ'), ('PostfixAddressBackend', '[S] Postfix address'), ('PostfixAddressVirtualDomainBackend', '[S] Postfix address virtdomain-only'), ('PostfixRecipientAccessBackend', '[S] Postfix recipient access'), ('ProxmoxOVZ', '[S] ProxmoxOVZ'), ('uWSGIPythonBackend', '[S] Python uWSGI'), ('StaticBackend', '[S] Static'), ('SymbolicLinkBackend', '[S] Symbolic link webapp'), ('SyncBind9MasterDomainBackend', '[S] Sync Bind9 master domain'), ('SyncBind9SlaveDomainBackend', '[S] Sync Bind9 slave domain'), ('UNIXUserMaildirBackend', '[S] UNIX maildir user'), ('UNIXUserBackend', '[S] UNIX user'), ('WebalizerAppBackend', '[S] Webalizer App'), ('WebalizerBackend', '[S] Webalizer Content'), ('WordPressURLBackend', '[S] WordPress URL'), ('WordPressBackend', '[S] Wordpress'), ('WordpressMuBackend', '[S] Wordpress multisite'), ('OwnCloudBackend', '[S] ownCloud SaaS'), ('PhpListSaaSBackend', '[S] phpList SaaS')], max_length=256, verbose_name='backend'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='server',
|
||||
name='address',
|
||||
field=orchestra.models.fields.NullableCharField(help_text='Optional IP address or domain name. If blank, name field will be used for address resolution.<br>If the IP address never changes you can set this field and save DNS requests.', verbose_name='address', validators=[orchestra.core.validators.OrValidator(orchestra.core.validators.validate_ip_address, orchestra.core.validators.validate_hostname)], blank=True, max_length=256, unique=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='server',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Verbose name or hostname of this server.', max_length=256, verbose_name='name', unique=True),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='backendoperation',
|
||||
index_together=set([('content_type', 'object_id')]),
|
||||
),
|
||||
]
|
|
@ -148,6 +148,9 @@ class BackendOperation(models.Model):
|
|||
class Meta:
|
||||
verbose_name = _("Operation")
|
||||
verbose_name_plural = _("Operations")
|
||||
index_together = (
|
||||
('content_type', 'object_id'),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return '%s.%s(%s)' % (self.backend, self.action, self.instance or self.instance_repr)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orders', '0004_auto_20150729_0945'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='billed_metric',
|
||||
field=models.DecimalField(decimal_places=2, null=True, verbose_name='billed metric', blank=True, max_digits=16),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='order',
|
||||
name='content_object_repr',
|
||||
field=models.CharField(max_length=256, verbose_name='content object representation', help_text='Used for searches.', editable=False),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='order',
|
||||
index_together=set([('content_type', 'object_id')]),
|
||||
),
|
||||
]
|
|
@ -172,6 +172,9 @@ class Order(models.Model):
|
|||
|
||||
class Meta:
|
||||
get_latest_by = 'id'
|
||||
index_together = (
|
||||
('content_type', 'object_id'),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.service)
|
||||
|
|
|
@ -134,6 +134,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
list_display = ('id', 'file_url', 'display_transactions', 'created_at')
|
||||
fields = ('data', 'file_url', 'created_at')
|
||||
readonly_fields = ('data', 'file_url', 'display_transactions', 'created_at')
|
||||
list_prefetch_related = ('transactions',)
|
||||
inlines = [TransactionInline]
|
||||
change_view_actions = (
|
||||
actions.mark_process_as_executed, actions.abort, actions.commit, actions.report
|
||||
|
@ -150,8 +151,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
ids = []
|
||||
lines = []
|
||||
counter = 0
|
||||
# Because of values_list this query doesn't benefit from prefetch_related
|
||||
for trans in process.transactions.only('id', 'state'):
|
||||
for trans in process.transactions.all():
|
||||
color = STATE_COLORS.get(trans.state, 'black')
|
||||
state = trans.get_state_display()
|
||||
ids.append('<span style="color:%s" title="%s">%i</span>' % (color, state, trans.id))
|
||||
|
@ -163,7 +163,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
lines.append(','.join(ids))
|
||||
transactions = '<br'.join(lines)
|
||||
url = reverse('admin:payments_transaction_changelist')
|
||||
url += '?processes=%i' % process.id
|
||||
url += '?process_id=%i' % process.id
|
||||
return '<a href="%s">%s</a>' % (url, transactions)
|
||||
display_transactions.short_description = _("Transactions")
|
||||
display_transactions.allow_tags = True
|
||||
|
@ -172,7 +172,7 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
return False
|
||||
|
||||
def get_change_view_actions(self, obj=None):
|
||||
actions = super(TransactionProcessAdmin, self).get_change_view_actions()
|
||||
actions = super().get_change_view_actions()
|
||||
exclude = []
|
||||
if obj:
|
||||
if obj.state == TransactionProcess.EXECUTED:
|
||||
|
@ -186,13 +186,11 @@ class TransactionProcessAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
|
|||
def delete_view(self, request, object_id, extra_context=None):
|
||||
queryset = self.model.objects.filter(id=object_id)
|
||||
related_transactions = helpers.pre_delete_processes(self, request, queryset)
|
||||
response = super(TransactionProcessAdmin, self).delete_view(
|
||||
request, object_id, extra_context)
|
||||
response = super().delete_view(request, object_id, extra_context)
|
||||
if isinstance(response, HttpResponseRedirect):
|
||||
helpers.post_delete_processes(self, request, related_transactions)
|
||||
return response
|
||||
|
||||
|
||||
admin.site.register(PaymentSource, PaymentSourceAdmin)
|
||||
admin.site.register(Transaction, TransactionAdmin)
|
||||
admin.site.register(TransactionProcess, TransactionProcessAdmin)
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('resources', '0009_auto_20150804_1450'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='monitordata',
|
||||
name='monitor',
|
||||
field=models.CharField(db_index=True, choices=[('Apache2Traffic', '[M] Apache 2 Traffic'), ('ApacheTrafficByName', '[M] ApacheTrafficByName'), ('DokuWikiMuTraffic', '[M] DokuWiki MU Traffic'), ('DovecotMaildirDisk', '[M] Dovecot Maildir size'), ('Exim4Traffic', '[M] Exim4 traffic'), ('MailmanSubscribers', '[M] Mailman subscribers'), ('MailmanTraffic', '[M] Mailman traffic'), ('MysqlDisk', '[M] MySQL disk'), ('OpenVZTraffic', '[M] OpenVZTraffic'), ('PostfixMailscannerTraffic', '[M] Postfix-Mailscanner traffic'), ('UNIXUserDisk', '[M] UNIX user disk'), ('VsFTPdTraffic', '[M] VsFTPd traffic'), ('WordpressMuTraffic', '[M] Wordpress MU Traffic'), ('OwnCloudDiskQuota', '[M] ownCloud SaaS Disk Quota'), ('OwncloudTraffic', '[M] ownCloud SaaS Traffic'), ('PhpListTraffic', '[M] phpList SaaS Traffic')], verbose_name='monitor', max_length=256),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='monitordata',
|
||||
name='object_id',
|
||||
field=models.PositiveIntegerField(verbose_name='object id'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='resource',
|
||||
name='disable_trigger',
|
||||
field=models.BooleanField(help_text='Disables monitors exeeded and recovery triggers', verbose_name='disable trigger', default=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='resource',
|
||||
name='monitors',
|
||||
field=orchestra.models.fields.MultiSelectField(help_text='Monitor backends used for monitoring this resource.', blank=True, verbose_name='monitors', max_length=256, choices=[('Apache2Traffic', '[M] Apache 2 Traffic'), ('ApacheTrafficByName', '[M] ApacheTrafficByName'), ('DokuWikiMuTraffic', '[M] DokuWiki MU Traffic'), ('DovecotMaildirDisk', '[M] Dovecot Maildir size'), ('Exim4Traffic', '[M] Exim4 traffic'), ('MailmanSubscribers', '[M] Mailman subscribers'), ('MailmanTraffic', '[M] Mailman traffic'), ('MysqlDisk', '[M] MySQL disk'), ('OpenVZTraffic', '[M] OpenVZTraffic'), ('PostfixMailscannerTraffic', '[M] Postfix-Mailscanner traffic'), ('UNIXUserDisk', '[M] UNIX user disk'), ('VsFTPdTraffic', '[M] VsFTPd traffic'), ('WordpressMuTraffic', '[M] Wordpress MU Traffic'), ('OwnCloudDiskQuota', '[M] ownCloud SaaS Disk Quota'), ('OwncloudTraffic', '[M] ownCloud SaaS Traffic'), ('PhpListTraffic', '[M] phpList SaaS Traffic')]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='resourcedata',
|
||||
name='object_id',
|
||||
field=models.PositiveIntegerField(verbose_name='object id'),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='monitordata',
|
||||
index_together=set([('content_type', 'object_id')]),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='resourcedata',
|
||||
index_together=set([('content_type', 'object_id')]),
|
||||
),
|
||||
]
|
|
@ -179,8 +179,8 @@ class ResourceDataQuerySet(models.QuerySet):
|
|||
class ResourceData(models.Model):
|
||||
""" Stores computed resource usage and allocation """
|
||||
resource = models.ForeignKey(Resource, related_name='dataset', verbose_name=_("resource"))
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_("content type"), db_index=True)
|
||||
object_id = models.PositiveIntegerField(_("object id"), db_index=True)
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_("content type"))
|
||||
object_id = models.PositiveIntegerField(_("object id"))
|
||||
used = models.DecimalField(_("used"), max_digits=16, decimal_places=3, null=True,
|
||||
editable=False)
|
||||
updated_at = models.DateTimeField(_("updated"), null=True, editable=False)
|
||||
|
@ -194,6 +194,9 @@ class ResourceData(models.Model):
|
|||
class Meta:
|
||||
unique_together = ('resource', 'content_type', 'object_id')
|
||||
verbose_name_plural = _("resource data")
|
||||
index_together = (
|
||||
('content_type', 'object_id'),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return "%s: %s" % (self.resource, self.content_object)
|
||||
|
@ -264,8 +267,8 @@ class MonitorData(models.Model):
|
|||
""" Stores monitored data """
|
||||
monitor = models.CharField(_("monitor"), max_length=256, db_index=True,
|
||||
choices=ServiceMonitor.get_choices())
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_("content type"), db_index=True)
|
||||
object_id = models.PositiveIntegerField(_("object id"), db_index=True)
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_("content type"))
|
||||
object_id = models.PositiveIntegerField(_("object id"))
|
||||
created_at = models.DateTimeField(_("created"), default=timezone.now, db_index=True)
|
||||
value = models.DecimalField(_("value"), max_digits=16, decimal_places=2)
|
||||
state = models.DecimalField(_("state"), max_digits=16, decimal_places=2, null=True,
|
||||
|
@ -279,6 +282,9 @@ class MonitorData(models.Model):
|
|||
class Meta:
|
||||
get_latest_by = 'id'
|
||||
verbose_name_plural = _("monitor data")
|
||||
index_together = (
|
||||
('content_type', 'object_id'),
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.monitor)
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.encoding import force_text
|
|||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
||||
from orchestra.admin import ExtendedModelAdmin
|
||||
from orchestra.admin.utils import change_url, get_modeladmin
|
||||
from orchestra.admin.utils import admin_link, get_modeladmin
|
||||
from orchestra.contrib.accounts.actions import list_accounts
|
||||
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
||||
from orchestra.forms.widgets import DynamicHelpTextSelect
|
||||
|
@ -72,9 +72,8 @@ class WebAppAdmin(SelectPluginAdminMixin, AccountAdminMixin, ExtendedModelAdmin)
|
|||
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)
|
||||
link = '<a href="%s">%s %s</a>' % (admin_url, name, site_link)
|
||||
name = "%s on %s %s" % (website.name, content.path, site_link)
|
||||
link = admin_link(display=name)(website)
|
||||
websites.append(link)
|
||||
if not websites:
|
||||
add_url = reverse('admin:websites_website_add')
|
||||
|
|
|
@ -87,7 +87,7 @@ class WebsiteAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|||
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()
|
||||
detail = _("Edit Webapp") + ' ' + webapp.get_type_display()
|
||||
try:
|
||||
detail += ' ' + webapp.type_instance.get_detail()
|
||||
except KeyError:
|
||||
|
|
|
@ -55,15 +55,18 @@ class Apache2Backend(ServiceController):
|
|||
return '\n'.join([conf for location, conf in extra_conf])
|
||||
|
||||
def render_virtual_host(self, site, context, ssl=False):
|
||||
context['port'] = self.HTTPS_PORT if ssl else self.HTTP_PORT
|
||||
context['vhost_set_fcgid'] = False
|
||||
context.update({
|
||||
'port': self.HTTPS_PORT if ssl else self.HTTP_PORT,
|
||||
'vhost_set_fcgid': False,
|
||||
'server_alias_lines': ' \\\n '.join(context['server_alias'])
|
||||
})
|
||||
context['extra_conf'] = self.get_extra_conf(site, context, ssl)
|
||||
return Template(textwrap.dedent("""\
|
||||
<VirtualHost{% for ip in ips %} {{ ip }}:{{ port }}{% endfor %}>
|
||||
IncludeOptional /etc/apache2/site[s]-override/{{ site_unique_name }}.con[f]
|
||||
ServerName {{ server_name }}\
|
||||
{% if server_alias %}
|
||||
ServerAlias {{ server_alias|join:' ' }}{% endif %}\
|
||||
ServerAlias {{ server_alias_lines }}{% endif %}\
|
||||
{% if access_log %}
|
||||
CustomLog {{ access_log }} common{% endif %}\
|
||||
{% if error_log %}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('websites', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='website',
|
||||
name='domains',
|
||||
field=models.ManyToManyField(to='domains.Domain', related_name='websites', verbose_name='domains', blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='websitedirective',
|
||||
name='name',
|
||||
field=models.CharField(choices=[(None, '-------'), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS'), ('moodle-saas', 'Moodle SaaS')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')])], db_index=True, verbose_name='name', max_length=128),
|
||||
),
|
||||
]
|
|
@ -115,7 +115,7 @@ class Website(models.Model):
|
|||
class WebsiteDirective(models.Model):
|
||||
website = models.ForeignKey(Website, verbose_name=_("web site"),
|
||||
related_name='directives')
|
||||
name = models.CharField(_("name"), max_length=128,
|
||||
name = models.CharField(_("name"), max_length=128, db_index=True,
|
||||
choices=SiteDirective.get_choices())
|
||||
value = models.CharField(_("value"), max_length=256)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ from ipaddress import ip_address
|
|||
import phonenumbers
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.deconstruct import deconstructible
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..utils.python import import_class
|
||||
|
@ -37,6 +38,7 @@ def all_valid(*args):
|
|||
raise ValidationError(errors)
|
||||
|
||||
|
||||
@deconstructible
|
||||
class OrValidator(object):
|
||||
"""
|
||||
Run validators with an OR logic
|
||||
|
|
Loading…
Reference in a new issue