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 ]] && {