From 1053dcf80ef1e780ddc9f3831abbf3b5989969cc Mon Sep 17 00:00:00 2001 From: Marc Aymerich Date: Fri, 24 Oct 2014 14:19:34 +0000 Subject: [PATCH] Prepopulate on admin UI --- orchestra/admin/options.py | 7 +- orchestra/apps/miscellaneous/admin.py | 12 +- orchestra/apps/orchestration/methods.py | 2 +- orchestra/apps/resources/admin.py | 7 +- orchestra/apps/services/admin.py | 7 +- orchestra/apps/systemusers/backends.py | 1 + orchestra/apps/systemusers/settings.py | 4 + orchestra/apps/webapps/admin.py | 8 +- orchestra/management/commands/setupcelery.py | 112 ++++++++++--------- scripts/migration/{domains.sh => bind9.sh} | 3 +- 10 files changed, 94 insertions(+), 69 deletions(-) rename scripts/migration/{domains.sh => bind9.sh} (96%) diff --git a/orchestra/admin/options.py b/orchestra/admin/options.py index eb95f376..0e281921 100644 --- a/orchestra/admin/options.py +++ b/orchestra/admin/options.py @@ -59,7 +59,6 @@ class AtLeastOneRequiredInlineFormSet(BaseInlineFormSet): class ChangeViewActionsMixin(object): """ Makes actions visible on the admin change view page. """ - change_view_actions = () change_form_template = 'orchestra/admin/change_form.html' @@ -111,9 +110,15 @@ class ChangeAddFieldsMixin(object): add_fields = () add_fieldsets = () add_form = None + add_prepopulated_fields = {} change_readonly_fields = () add_inlines = () + def get_prepopulated_fields(self, request, obj=None): + if not obj: + return super(ChangeAddFieldsMixin, self).get_prepopulated_fields(request, obj=obj) + return {} + def get_readonly_fields(self, request, obj=None): fields = super(ChangeAddFieldsMixin, self).get_readonly_fields(request, obj=obj) if obj: diff --git a/orchestra/apps/miscellaneous/admin.py b/orchestra/apps/miscellaneous/admin.py index a5bae270..d0bbc53a 100644 --- a/orchestra/apps/miscellaneous/admin.py +++ b/orchestra/apps/miscellaneous/admin.py @@ -4,13 +4,19 @@ from django.db import models from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ +from orchestra.admin import ExtendedModelAdmin from orchestra.apps.accounts.admin import AccountAdminMixin from .models import MiscService, Miscellaneous -class MiscServiceAdmin(admin.ModelAdmin): - list_display = ('name', 'verbose_name', 'num_instances') +class MiscServiceAdmin(ExtendedModelAdmin): + list_display = ('name', 'verbose_name', 'num_instances', 'has_amount', 'is_active') + list_editable = ('has_amount', 'is_active') + list_filter = ('has_amount', 'is_active') + fields = ('verbose_name', 'name', 'description', 'has_amount', 'is_active') + prepopulated_fields = {'name': ('verbose_name',)} + change_readonly_fields = ('name',) def num_instances(self, misc): """ return num slivers as a link to slivers changelist view """ @@ -27,7 +33,7 @@ class MiscServiceAdmin(admin.ModelAdmin): class MiscellaneousAdmin(AccountAdminMixin, admin.ModelAdmin): - list_display = ('service', 'amount', 'account_link') + list_display = ('service', 'amount', 'active', 'account_link') def get_fields(self, request, obj=None): if obj is None: diff --git a/orchestra/apps/orchestration/methods.py b/orchestra/apps/orchestration/methods.py index 129ee984..55a96f7f 100644 --- a/orchestra/apps/orchestration/methods.py +++ b/orchestra/apps/orchestration/methods.py @@ -66,7 +66,7 @@ def BashSSH(backend, log, server, cmds): cmd = ( "[[ $(md5sum %(remote_path)s|awk {'print $1'}) == %(digest)s ]] && bash %(remote_path)s\n" "RETURN_CODE=$?\n" -# TODO "rm -fr %(remote_path)s\n" + "rm -fr %(remote_path)s\n" "exit $RETURN_CODE" % context ) channel = transport.open_session() diff --git a/orchestra/apps/resources/admin.py b/orchestra/apps/resources/admin.py index 90925a3e..f5951ef3 100644 --- a/orchestra/apps/resources/admin.py +++ b/orchestra/apps/resources/admin.py @@ -15,12 +15,12 @@ from .models import Resource, ResourceData, MonitorData class ResourceAdmin(ExtendedModelAdmin): - # TODO error after saving: u"Key 'name' not found in 'ResourceForm'" -# prepopulated_fields = {'name': ('verbose_name',)} list_display = ( 'id', 'verbose_name', 'content_type', 'period', 'on_demand', - 'default_allocation', 'unit', 'disable_trigger', 'crontab', + 'default_allocation', 'unit', 'crontab', 'is_active' ) + list_display_links = ('id', 'verbose_name') + list_editable = ('default_allocation', 'crontab', 'is_active',) list_filter = (UsedContentTypeFilter, 'period', 'on_demand', 'disable_trigger') fieldsets = ( (None, { @@ -35,6 +35,7 @@ class ResourceAdmin(ExtendedModelAdmin): }), ) change_readonly_fields = ('name', 'content_type', 'period') + prepopulated_fields = {'name': ('verbose_name',)} def add_view(self, request, **kwargs): """ Warning user if the node is not fully configured """ diff --git a/orchestra/apps/services/admin.py b/orchestra/apps/services/admin.py index 7ff80239..f9be671c 100644 --- a/orchestra/apps/services/admin.py +++ b/orchestra/apps/services/admin.py @@ -4,7 +4,7 @@ from django.core.urlresolvers import reverse from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from orchestra.admin import ChangeViewActionsMixin +from orchestra.admin import ChangeViewActionsMixin, ExtendedModelAdmin from orchestra.admin.filters import UsedContentTypeFilter from orchestra.apps.accounts.admin import AccountAdminMixin from orchestra.core import services @@ -18,9 +18,12 @@ class RateInline(admin.TabularInline): ordering = ('plan', 'quantity') -class PlanAdmin(admin.ModelAdmin): +class PlanAdmin(ExtendedModelAdmin): list_display = ('name', 'is_default', 'is_combinable', 'allow_multiple') list_filter = ('is_default', 'is_combinable', 'allow_multiple') + fields = ('verbose_name', 'name', 'is_default', 'is_combinable', 'allow_multiple') + prepopulated_fields = {'name': ('verbose_name',)} + change_readonly_fields = ('name',) inlines = [RateInline] diff --git a/orchestra/apps/systemusers/backends.py b/orchestra/apps/systemusers/backends.py index 9165e5d8..8821ba67 100644 --- a/orchestra/apps/systemusers/backends.py +++ b/orchestra/apps/systemusers/backends.py @@ -47,6 +47,7 @@ class SystemUserBackend(ServiceController): if user.is_main: return user.account.systemusers.exclude(username=user.username).values_list('username', flat=True) groups = list(user.groups.values_list('username', flat=True)) + groups += list(settings.SYSTEMUSERS_DEFAULT_GROUP_MEMBERS) return groups def get_context(self, user): diff --git a/orchestra/apps/systemusers/settings.py b/orchestra/apps/systemusers/settings.py index eac6fb4f..bc6f6e80 100644 --- a/orchestra/apps/systemusers/settings.py +++ b/orchestra/apps/systemusers/settings.py @@ -17,3 +17,7 @@ SYSTEMUSERS_HOME = getattr(settings, 'SYSTEMUSERS_HOME', '/home/%(username)s') SYSTEMUSERS_FTP_LOG_PATH = getattr(settings, 'SYSTEMUSERS_FTP_LOG_PATH', '/var/log/vsftpd.log') + + +SYSTEMUSERS_DEFAULT_GROUP_MEMBERS = getattr(settings, 'SYSTEMUSERS_DEFAULT_GROUP_MEMBERS', + ('www-data',)) diff --git a/orchestra/apps/webapps/admin.py b/orchestra/apps/webapps/admin.py index eff61962..549a1e9a 100644 --- a/orchestra/apps/webapps/admin.py +++ b/orchestra/apps/webapps/admin.py @@ -1,6 +1,7 @@ from django import forms from django.contrib import admin -from django.utils.translation import ugettext_lazy as _ +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext, ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin from orchestra.admin.utils import change_url @@ -41,9 +42,10 @@ class WebAppAdmin(AccountAdminMixin, ExtendedModelAdmin): url = change_url(website) name = "%s on %s" % (website.name, content.path) websites.append('%s' % (url, name)) - add_url = reverse('admin:webapps_website_add') + add_url = reverse('admin:websites_website_add') add_url += '?account=%s' % webapp.account_id - websites.append('%s' % (add_url, _("Add website"))) + plus = '+' + websites.append('%s%s' % (add_url, plus, ugettext("Add website"))) return '
'.join(websites) display_websites.short_description = _("web sites") display_websites.allow_tags = True diff --git a/orchestra/management/commands/setupcelery.py b/orchestra/management/commands/setupcelery.py index d987a9b1..8183eb0b 100644 --- a/orchestra/management/commands/setupcelery.py +++ b/orchestra/management/commands/setupcelery.py @@ -1,3 +1,4 @@ +import textwrap from optparse import make_option from os import path @@ -33,51 +34,52 @@ class Command(BaseCommand): 'processes': options.get('processes'), } - celery_config = ( - '# Name of nodes to start, here we have a single node\n' - 'CELERYD_NODES="w1"\n' - '\n' - '# Where to chdir at start.\n' - 'CELERYD_CHDIR="%(site_root)s"\n' - '\n' - '# How to call "manage.py celeryd_multi"\n' - 'CELERYD_MULTI="$CELERYD_CHDIR/manage.py celeryd_multi"\n' - '\n' - '# Extra arguments to celeryd\n' - 'CELERYD_OPTS="-P:w1 processes -c:w1 %(processes)s -Q:w1 celery"\n' - '\n' - '# Name of the celery config module.\n' - 'CELERY_CONFIG_MODULE="celeryconfig"\n' - '\n' - '# %%n will be replaced with the nodename.\n' - 'CELERYD_LOG_FILE="/var/log/celery/%%n.log"\n' - 'CELERYD_PID_FILE="/var/run/celery/%%n.pid"\n' - 'CELERY_CREATE_DIRS=1\n' - '\n' - '# Full path to the celeryd logfile.\n' - 'CELERYEV_LOG_FILE="/var/log/celery/celeryev.log"\n' - 'CELERYEV_PID_FILE="/var/run/celery/celeryev.pid"\n' - '\n' - '# Workers should run as an unprivileged user.\n' - 'CELERYD_USER="%(username)s"\n' - 'CELERYD_GROUP="$CELERYD_USER"\n' - '\n' - '# Persistent revokes\n' - 'CELERYD_STATE_DB="$CELERYD_CHDIR/persistent_revokes"\n' - '\n' - '# Celeryev\n' - 'CELERYEV="$CELERYD_CHDIR/manage.py"\n' - 'CELERYEV_CAM="djcelery.snapshot.Camera"\n' - 'CELERYEV_USER="$CELERYD_USER"\n' - 'CELERYEV_GROUP="$CELERYD_USER"\n' - 'CELERYEV_OPTS="celerycam"\n' - '\n' - '# Celerybeat\n' - 'CELERYBEAT="${CELERYD_CHDIR}/manage.py celerybeat"\n' - 'CELERYBEAT_USER="$CELERYD_USER"\n' - 'CELERYBEAT_GROUP="$CELERYD_USER"\n' - 'CELERYBEAT_CHDIR="$CELERYD_CHDIR"\n' - 'CELERYBEAT_OPTS="--schedule=/var/run/celerybeat-schedule"\n' % context + celery_config = textwrap.dedent("""\ + # Name of nodes to start, here we have a single node + CELERYD_NODES="w1" + + # Where to chdir at start. + CELERYD_CHDIR="%(site_root)s" + + # How to call "manage.py celeryd_multi" + CELERYD_MULTI="$CELERYD_CHDIR/manage.py celeryd_multi" + + # Extra arguments to celeryd + CELERYD_OPTS="-P:w1 processes -c:w1 %(processes)s -Q:w1 celery" + + # Name of the celery config module. + CELERY_CONFIG_MODULE="celeryconfig" + + # %%n will be replaced with the nodename. + CELERYD_LOG_FILE="/var/log/celery/%%n.log" + CELERYD_PID_FILE="/var/run/celery/%%n.pid" + CELERY_CREATE_DIRS=1 + + # Full path to the celeryd logfile. + CELERYEV_LOG_FILE="/var/log/celery/celeryev.log" + CELERYEV_PID_FILE="/var/run/celery/celeryev.pid" + + # Workers should run as an unprivileged user. + CELERYD_USER="%(username)s" + CELERYD_GROUP="$CELERYD_USER" + + # Persistent revokes + CELERYD_STATE_DB="$CELERYD_CHDIR/persistent_revokes" + + # Celeryev + CELERYEV="$CELERYD_CHDIR/manage.py" + CELERYEV_CAM="djcelery.snapshot.Camera" + CELERYEV_USER="$CELERYD_USER" + CELERYEV_GROUP="$CELERYD_USER" + CELERYEV_OPTS="celerycam" + + # Celerybeat + CELERYBEAT="${CELERYD_CHDIR}/manage.py celerybeat" + CELERYBEAT_USER="$CELERYD_USER" + CELERYBEAT_GROUP="$CELERYD_USER" + CELERYBEAT_CHDIR="$CELERYD_CHDIR" + CELERYBEAT_OPTS="--schedule=/var/run/celerybeat-schedule --scheduler=djcelery.schedulers.DatabaseScheduler" + """ % context ) run("echo '%s' > /etc/default/celeryd" % celery_config) @@ -89,15 +91,15 @@ class Command(BaseCommand): run('chmod +x /etc/init.d/%(script)s' % context) run('update-rc.d %(script)s defaults' % context) - rotate = ( - '/var/log/celery/*.log {\n' - ' weekly\n' - ' missingok\n' - ' rotate 10\n' - ' compress\n' - ' delaycompress\n' - ' notifempty\n' - ' copytruncate\n' - '}' + rotate = textwrap.dedent("""\ + /var/log/celery/*.log { + weekly + missingok + rotate 10 + compress + delaycompress + notifempty + copytruncate + }""" ) run("echo '%s' > /etc/logrotate.d/celeryd" % rotate) diff --git a/scripts/migration/domains.sh b/scripts/migration/bind9.sh similarity index 96% rename from scripts/migration/domains.sh rename to scripts/migration/bind9.sh index a3555209..c588dddd 100644 --- a/scripts/migration/domains.sh +++ b/scripts/migration/bind9.sh @@ -11,11 +11,12 @@ ZONE_PATH=${1:-/etc/bind/master/} +ACCOUNT_ID=${2:-1} echo "from orchestra.apps.domains.models import Domain" echo "from orchestra.apps.accounts.models import Account" -echo "account = Account.objects.get(pk=1)" +echo "account = Account.objects.get(pk=${ACCOUNT_ID})" ERRORS="" while read name; do [[ -f $name ]] && {