Added multiple IPs support per virtualhost

This commit is contained in:
Marc Aymerich 2015-04-21 14:14:07 +00:00
parent 28f644f4e6
commit 43d70fe83d
9 changed files with 55 additions and 38 deletions

View File

@ -1,18 +0,0 @@
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext as _
class UsedContentTypeFilter(SimpleListFilter):
title = _('Content type')
parameter_name = 'content_type'
def lookups(self, request, model_admin):
qset = model_admin.model._default_manager.all().order_by()
result = ()
for pk, name in qset.values_list('content_type', 'content_type__model').distinct():
result += ((str(pk), name.capitalize()),)
return result
def queryset(self, request, queryset):
if self.value():
return queryset.filter(content_type=self.value())

View File

@ -183,4 +183,5 @@ def copy_lines(modeladmin, request, queryset):
def delete_lines(modeladmin, request, queryset): def delete_lines(modeladmin, request, queryset):
# Call contrib.admin delete action if all lines in open bill
pass pass

View File

@ -100,12 +100,37 @@ class ClosedBillLineInline(BillLineInline):
class BillLineAdmin(admin.ModelAdmin): class BillLineAdmin(admin.ModelAdmin):
list_display = ('description', 'bill_link', 'rate', 'quantity', 'tax', 'subtotal') list_display = (
'description', 'bill_link', 'rate', 'quantity', 'tax', 'subtotal', 'display_sublinetotal',
'display_total'
)
actions = (actions.undo_billing, actions.move_lines, actions.copy_lines,) actions = (actions.undo_billing, actions.move_lines, actions.copy_lines,)
list_filter = ('tax', ('bill', admin.RelatedOnlyFieldListFilter))
list_select_related = ('bill',) list_select_related = ('bill',)
search_fields = ('description', 'bill__number')
bill_link = admin_link('bill') bill_link = admin_link('bill')
def display_sublinetotal(self, instance):
return instance.subline_total or ''
display_sublinetotal.short_description = _("Subline")
display_sublinetotal.admin_order_field = 'subline_total'
def display_total(self, instance):
return round(instance.computed_total or 0, 2)
display_total.short_description = _("Total")
display_total.admin_order_field = 'computed_total'
def get_queryset(self, request):
qs = super(BillLineAdmin, self).get_queryset(request)
qs = qs.annotate(
subline_total=Sum('sublines__total'),
computed_total=Sum(
(F('subtotal') + Coalesce(F('sublines__total'), 0)) * (1+F('tax')/100)
),
)
return qs
class BillLineManagerAdmin(BillLineAdmin): class BillLineManagerAdmin(BillLineAdmin):
def get_queryset(self, request): def get_queryset(self, request):
@ -119,7 +144,7 @@ class BillLineManagerAdmin(BillLineAdmin):
bill_ids = GET.pop('ids', None) bill_ids = GET.pop('ids', None)
if bill_ids: if bill_ids:
request.GET = GET request.GET = GET
bill_ids = list(map(int, bill_ids.split(','))) bill_ids = list(map(int, bill_ids))
self.bill_ids = bill_ids self.bill_ids = bill_ids
if bill_ids and len(bill_ids) == 1: if bill_ids and len(bill_ids) == 1:
bill_url = reverse('admin:bills_bill_change', args=(bill_ids[0],)) bill_url = reverse('admin:bills_bill_change', args=(bill_ids[0],))

View File

@ -22,9 +22,9 @@ class Command(BaseCommand):
parser.add_argument('--action', action='store', dest='action', parser.add_argument('--action', action='store', dest='action',
default='save', help='Executes action. Defaults to "save".') default='save', help='Executes action. Defaults to "save".')
parser.add_argument('--servers', action='store', dest='servers', parser.add_argument('--servers', action='store', dest='servers',
default='save', help='Overrides route server resolution with the provided server.') default='', help='Overrides route server resolution with the provided server.')
parser.add_argument('--backends', action='store', dest='backends', parser.add_argument('--backends', action='store', dest='backends',
default='save', help='Overrides backend.') default='', help='Overrides backend.')
parser.add_argument('--listbackends', action='store_true', dest='list_backends', default=False, parser.add_argument('--listbackends', action='store_true', dest='list_backends', default=False,
help='List available baclends.') help='List available baclends.')
parser.add_argument('--dry-run', action='store_true', dest='dry', default=False, parser.add_argument('--dry-run', action='store_true', dest='dry', default=False,
@ -39,8 +39,8 @@ class Command(BaseCommand):
model = get_model(*options['model'].split('.')) model = get_model(*options['model'].split('.'))
action = options.get('action') action = options.get('action')
interactive = options.get('interactive') interactive = options.get('interactive')
servers = options.get('servers', '').split(',') servers = options.get('servers')
backends = options.get('backends', '').split(',') backends = options.get('backends')
if (servers and not backends) or (not servers and backends): if (servers and not backends) or (not servers and backends):
raise CommandError("--backends and --servers go in tandem.") raise CommandError("--backends and --servers go in tandem.")
dry = options.get('dry') dry = options.get('dry')
@ -53,13 +53,17 @@ class Command(BaseCommand):
route_cache = {} route_cache = {}
queryset = model.objects.filter(**kwargs).order_by('id') queryset = model.objects.filter(**kwargs).order_by('id')
if servers: if servers:
servers = servers.split(',')
backends = backends.split(',')
server_objects = [] server_objects = []
# Get and create missing Servers # Get and create missing Servers
for server in servers: for server in servers:
try: try:
server = Server.objects.get(address=server) server = Server.objects.get(address=server)
except Server.DoesNotExist: except Server.DoesNotExist:
server = Server.objects.create(name=server, address=server) server = Server(name=server, address=server)
server.full_clean()
server.save()
server_objects.append(server) server_objects.append(server)
# Generate operations for the given backend # Generate operations for the given backend
for instance in queryset: for instance in queryset:

View File

@ -8,7 +8,6 @@ from django.utils.functional import cached_property
from django.utils.translation import ungettext, ugettext, ugettext_lazy as _ from django.utils.translation import ungettext, ugettext, ugettext_lazy as _
from orchestra.admin import ExtendedModelAdmin from orchestra.admin import ExtendedModelAdmin
from orchestra.admin.filters import UsedContentTypeFilter
from orchestra.admin.utils import insertattr, get_modeladmin, admin_link, admin_date from orchestra.admin.utils import insertattr, get_modeladmin, admin_link, admin_date
from orchestra.contrib.orchestration.models import Route from orchestra.contrib.orchestration.models import Route
from orchestra.core import services from orchestra.core import services
@ -27,7 +26,10 @@ class ResourceAdmin(ExtendedModelAdmin):
) )
list_display_links = ('id', 'verbose_name') list_display_links = ('id', 'verbose_name')
list_editable = ('default_allocation', 'crontab', 'is_active',) list_editable = ('default_allocation', 'crontab', 'is_active',)
list_filter = (UsedContentTypeFilter, 'aggregation', 'on_demand', 'disable_trigger') list_filter = (
('content_type', admin.RelatedOnlyFieldListFilter), 'aggregation', 'on_demand',
'disable_trigger'
)
fieldsets = ( fieldsets = (
(None, { (None, {
'fields': ('verbose_name', 'name', 'content_type', 'aggregation'), 'fields': ('verbose_name', 'name', 'content_type', 'aggregation'),

View File

@ -7,7 +7,6 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ChangeViewActionsMixin from orchestra.admin import ChangeViewActionsMixin
from orchestra.admin.filters import UsedContentTypeFilter
from orchestra.core import services from orchestra.core import services
from .actions import update_orders, view_help, clone from .actions import update_orders, view_help, clone
@ -18,7 +17,9 @@ class ServiceAdmin(ChangeViewActionsMixin, admin.ModelAdmin):
list_display = ( list_display = (
'description', 'content_type', 'handler_type', 'num_orders', 'is_active' 'description', 'content_type', 'handler_type', 'num_orders', 'is_active'
) )
list_filter = ('is_active', 'handler_type', UsedContentTypeFilter) list_filter = (
'is_active', 'handler_type', ('content_type', admin.RelatedOnlyFieldListFilter),
)
fieldsets = ( fieldsets = (
(None, { (None, {
'classes': ('wide',), 'classes': ('wide',),

View File

@ -106,13 +106,13 @@ class PHPBackend(WebAppServiceMixin, ServiceController):
echo -n "$state" > /dev/shm/restart.apache2 echo -n "$state" > /dev/shm/restart.apache2
if [[ $UPDATED_APACHE -eq 1 ]]; then if [[ $UPDATED_APACHE -eq 1 ]]; then
if [[ $locked == 0 ]]; then if [[ $locked == 0 ]]; then
service apache2 reload service apache2 status && service apache2 reload || service apache2 start
else else
echo "PHPBackend RESTART" >> /dev/shm/restart.apache2 echo "PHPBackend RESTART" >> /dev/shm/restart.apache2
fi fi
elif [[ "$state" =~ .*RESTART$ ]]; then elif [[ "$state" =~ .*RESTART$ ]]; then
rm /dev/shm/restart.apache2 rm /dev/shm/restart.apache2
service apache2 reload service apache2 status && service apache2 reload || service apache2 start
fi fi
""") """)
) )

View File

@ -40,7 +40,7 @@ class Apache2Backend(ServiceController):
extra_conf = sorted(extra_conf, key=lambda a: len(a[0]), reverse=True) extra_conf = sorted(extra_conf, key=lambda a: len(a[0]), reverse=True)
context['extra_conf'] = '\n'.join([conf for location, conf in extra_conf]) context['extra_conf'] = '\n'.join([conf for location, conf in extra_conf])
return Template(textwrap.dedent("""\ return Template(textwrap.dedent("""\
<VirtualHost {{ ip }}:{{ port }}> <VirtualHost {% for ip in ips %}{{ ip }}:{{ port }} {% endfor %}>
IncludeOptional /etc/apache2/site[s]-override/{{ site_unique_name }}.con[f] IncludeOptional /etc/apache2/site[s]-override/{{ site_unique_name }}.con[f]
ServerName {{ server_name }}\ ServerName {{ server_name }}\
{% if server_alias %} {% if server_alias %}
@ -59,7 +59,7 @@ class Apache2Backend(ServiceController):
def render_redirect_https(self, context): def render_redirect_https(self, context):
context['port'] = self.HTTP_PORT context['port'] = self.HTTP_PORT
return Template(textwrap.dedent(""" return Template(textwrap.dedent("""
<VirtualHost {{ ip }}:{{ port }}> <VirtualHost {% for ip in ips %}{{ ip }}:{{ port }} {% endfor %}>
ServerName {{ server_name }}\ ServerName {{ server_name }}\
{% if server_alias %} {% if server_alias %}
ServerAlias {{ server_alias|join:' ' }}{% endif %}\ ServerAlias {{ server_alias|join:' ' }}{% endif %}\
@ -127,13 +127,13 @@ class Apache2Backend(ServiceController):
echo -n "$state" > /dev/shm/restart.apache2 echo -n "$state" > /dev/shm/restart.apache2
if [[ $UPDATED == 1 ]]; then if [[ $UPDATED == 1 ]]; then
if [[ $locked == 0 ]]; then if [[ $locked == 0 ]]; then
service apache2 reload service apache2 satus && service apache2 reload || service apache2 start
else else
echo "Apache2Backend RESTART" >> /dev/shm/restart.apache2 echo "Apache2Backend RESTART" >> /dev/shm/restart.apache2
fi fi
elif [[ "$state" =~ .*RESTART$ ]]; then elif [[ "$state" =~ .*RESTART$ ]]; then
rm /dev/shm/restart.apache2 rm /dev/shm/restart.apache2
service apache2 reload service apache2 satus && service apache2 reload || service apache2 start
fi""") fi""")
) )
super(Apache2Backend, self).commit() super(Apache2Backend, self).commit()
@ -332,7 +332,7 @@ class Apache2Backend(ServiceController):
context = { context = {
'site': site, 'site': site,
'site_name': site.name, 'site_name': site.name,
'ip': settings.WEBSITES_DEFAULT_IP, 'ips': settings.WEBSITES_DEFAULT_IPS,
'site_unique_name': site.unique_name, 'site_unique_name': site.unique_name,
'user': self.get_username(site), 'user': self.get_username(site),
'group': self.get_groupname(site), 'group': self.get_groupname(site),
@ -344,6 +344,8 @@ class Apache2Backend(ServiceController):
'error_log': site.get_www_error_log_path(), 'error_log': site.get_www_error_log_path(),
'banner': self.get_banner(), 'banner': self.get_banner(),
} }
if not context['ips']:
raise ValueError("WEBSITES_DEFAULT_IPS is empty.")
return replace(context, "'", '"') return replace(context, "'", '"')
def set_content_context(self, content, context): def set_content_context(self, content, context):

View File

@ -26,9 +26,9 @@ WEBSITES_DEFAULT_PROTOCOL = getattr(settings, 'WEBSITES_DEFAULT_PROTOCOL',
) )
WEBSITES_DEFAULT_IP = getattr(settings, 'WEBSITES_DEFAULT_IP', WEBSITES_DEFAULT_IPS = getattr(settings, 'WEBSITES_DEFAULT_IPS', (
'*' '*'
) ))
WEBSITES_DOMAIN_MODEL = getattr(settings, 'WEBSITES_DOMAIN_MODEL', WEBSITES_DOMAIN_MODEL = getattr(settings, 'WEBSITES_DOMAIN_MODEL',