diff --git a/TODO.md b/TODO.md index 403fd06c..874cbd98 100644 --- a/TODO.md +++ b/TODO.md @@ -354,4 +354,4 @@ make django admin taskstate uncollapse fucking traceback, ( if exists ?) # backend.context and backned.instance provided when an action is called? like forms.cleaned_data: do it on manager.generation(backend.context = backend.get_context()) or in backend.__getattr__ ? also backend.head,tail,content switching on manager.generate()? -# replace return_code by exit_code everywhere +resorce monitoring more efficient, less mem an better queries for calc current data diff --git a/orchestra/admin/actions.py b/orchestra/admin/actions.py index cbdac596..3d9440cb 100644 --- a/orchestra/admin/actions.py +++ b/orchestra/admin/actions.py @@ -5,6 +5,7 @@ from django.utils.translation import ungettext, ugettext_lazy as _ from .. import settings +from .decorators import action_with_confirmation from .forms import SendEmailForm @@ -107,3 +108,25 @@ class SendEmail(object): }) # Display the confirmation page return render(request, self.template, self.context) + + +@action_with_confirmation() +def disable(modeladmin, request, queryset): + num = 0 + for obj in queryset: + obj.disable() + modeladmin.log_change(request, obj, _("Disabled")) + num += 1 + opts = modeladmin.model._meta + context = { + 'verbose_name': opts.verbose_name, + 'verbose_name_plural': opts.verbose_name_plural, + 'num': num + } + msg = ungettext( + _("Selected %(verbose_name)s and related services has been disabled.") % context, + _("%(num)s selected %(verbose_name_plural)s and related services have been disabled.") % context, + num) + modeladmin.message_user(request, msg) +disable.url_name = 'disable' +disable.verbose_name = _("Disable") diff --git a/orchestra/contrib/accounts/actions.py b/orchestra/contrib/accounts/actions.py index a507c043..27f00bf6 100644 --- a/orchestra/contrib/accounts/actions.py +++ b/orchestra/contrib/accounts/actions.py @@ -12,28 +12,11 @@ from django.utils.html import format_html from django.utils.text import capfirst from django.utils.translation import ungettext, ugettext_lazy as _ -from orchestra.admin.decorators import action_with_confirmation from orchestra.core import services from . import settings -@action_with_confirmation() -def disable(modeladmin, request, queryset): - num = 0 - for account in queryset: - account.disable() - modeladmin.log_change(request, account, _("Disabled")) - num += 1 - msg = ungettext( - _("Selected account and related services has been disabled."), - _("%s selected accounts and related services have been disabled.") % num, - num) - modeladmin.message_user(request, msg) -disable.url_name = 'disable' -disable.verbose_name = _("Disable") - - def list_contacts(modeladmin, request, queryset): ids = queryset.values_list('id', flat=True) if not ids: diff --git a/orchestra/contrib/accounts/admin.py b/orchestra/contrib/accounts/admin.py index 6a385ebf..2d5e4e6c 100644 --- a/orchestra/contrib/accounts/admin.py +++ b/orchestra/contrib/accounts/admin.py @@ -12,12 +12,12 @@ from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin -from orchestra.admin.actions import SendEmail +from orchestra.admin.actions import SendEmail, disable from orchestra.admin.utils import wrap_admin_view, admin_link, set_url_query, change_url from orchestra.core import services, accounts from orchestra.forms import UserChangeForm -from .actions import disable, list_contacts, service_report, delete_related_services +from .actions import list_contacts, service_report, delete_related_services from .filters import HasMainUserListFilter from .forms import AccountCreationForm from .models import Account diff --git a/orchestra/contrib/domains/tests/functional_tests/tests.py b/orchestra/contrib/domains/tests/functional_tests/tests.py index 5bff4901..3ed2f34f 100644 --- a/orchestra/contrib/domains/tests/functional_tests/tests.py +++ b/orchestra/contrib/domains/tests/functional_tests/tests.py @@ -114,7 +114,7 @@ class DomainTestMixin(object): 'server_addr': server_addr } dig_soa = 'dig @%(server_addr)s %(domain_name)s|grep "\sSOA\s"' - soa = run(dig_soa % context, error_codes=[0,1]).stdout + soa = run(dig_soa % context, valid_codes=(0, 1)).stdout if soa: soa = soa.split() self.assertEqual('IN', soa[2]) diff --git a/orchestra/contrib/domains/validators.py b/orchestra/contrib/domains/validators.py index 0b5a67b2..a5d786d4 100644 --- a/orchestra/contrib/domains/validators.py +++ b/orchestra/contrib/domains/validators.py @@ -118,11 +118,11 @@ def validate_zone(zone): with open(zone_path, 'wb') as f: f.write(zone.encode('ascii')) # Don't use /dev/stdin becuase the 'argument list is too long' error - check = run(' '.join([checkzone, zone_name, zone_path]), error_codes=[0,1,127], display=False) + check = run(' '.join([checkzone, zone_name, zone_path]), valid_codes=(0,1,127), display=False) finally: os.unlink(zone_path) - if check.return_code == 127: + if check.exit_code == 127: logger.error("Cannot validate domain zone: %s not installed." % checkzone) - elif check.return_code == 1: + elif check.exit_code == 1: errors = re.compile(r'zone.*: (.*)').findall(check.stdout)[:-1] raise ValidationError(', '.join(errors)) diff --git a/orchestra/contrib/lists/admin.py b/orchestra/contrib/lists/admin.py index 5a643579..dcf9592b 100644 --- a/orchestra/contrib/lists/admin.py +++ b/orchestra/contrib/lists/admin.py @@ -4,6 +4,7 @@ from django.contrib.auth.admin import UserAdmin from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin +from orchestra.admin.actions import disable from orchestra.admin.utils import admin_link from orchestra.contrib.accounts.admin import SelectAccountAdminMixin from orchestra.contrib.accounts.filters import IsActiveListFilter @@ -52,6 +53,7 @@ class ListAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModel add_form = ListCreationForm list_select_related = ('account', 'address_domain',) filter_by_account_fields = ['address_domain'] + actions = (disable,) address_domain_link = admin_link('address_domain', order='address_domain__name') diff --git a/orchestra/contrib/lists/models.py b/orchestra/contrib/lists/models.py index cb9caefa..75c01b53 100644 --- a/orchestra/contrib/lists/models.py +++ b/orchestra/contrib/lists/models.py @@ -55,6 +55,10 @@ class List(models.Model): def active(self): return self.is_active and self.account.is_active + def disable(self): + self.is_active = False + self.save(update_fields=('is_active',)) + def get_address_name(self): return self.address_name or self.name diff --git a/orchestra/contrib/mailboxes/admin.py b/orchestra/contrib/mailboxes/admin.py index 9a53688f..1d9dc367 100644 --- a/orchestra/contrib/mailboxes/admin.py +++ b/orchestra/contrib/mailboxes/admin.py @@ -8,6 +8,7 @@ from django.db.models.functions import Concat from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin +from orchestra.admin.actions import disable from orchestra.admin.utils import admin_link, change_url from orchestra.contrib.accounts.admin import SelectAccountAdminMixin from orchestra.contrib.accounts.filters import IsActiveListFilter @@ -65,6 +66,12 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo add_form = MailboxCreationForm form = MailboxChangeForm list_prefetch_related = ('addresses__domain',) + actions = (disable,) + + def __init__(self, *args, **kwargs): + super(MailboxAdmin, self).__init__(*args, **kwargs) + if settings.MAILBOXES_LOCAL_ADDRESS_DOMAIN: + type(self).actions = self.actions + (SendMailboxEmail(),) def display_addresses(self, mailbox): addresses = [] @@ -82,13 +89,6 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo display_filtering.admin_order_field = 'filtering' display_filtering.allow_tags = True - def get_actions(self, request): - if settings.MAILBOXES_LOCAL_ADDRESS_DOMAIN: - type(self).actions = (SendMailboxEmail(),) - else: - type(self).actions = () - return super(MailboxAdmin, self).get_actions(request) - def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == 'filtering': kwargs['widget'] = OpenCustomFilteringOnSelect() diff --git a/orchestra/contrib/mailboxes/models.py b/orchestra/contrib/mailboxes/models.py index 8f4cad4b..41617c00 100644 --- a/orchestra/contrib/mailboxes/models.py +++ b/orchestra/contrib/mailboxes/models.py @@ -42,6 +42,10 @@ class Mailbox(models.Model): except type(self).account.field.rel.to.DoesNotExist: return self.is_active + def disable(self): + self.is_active = False + self.save(update_fields=('is_active',)) + def set_password(self, raw_password): self.password = make_password(raw_password) diff --git a/orchestra/contrib/mailboxes/validators.py b/orchestra/contrib/mailboxes/validators.py index ce547a77..26ecee88 100644 --- a/orchestra/contrib/mailboxes/validators.py +++ b/orchestra/contrib/mailboxes/validators.py @@ -62,7 +62,7 @@ def validate_sieve(value): test = run(' '.join([sievetest, test_path, '/dev/null']), silent=True) finally: os.unlink(test_path) - if test.return_code: + if test.exit_code: errors = [] for line in test.stderr.decode('utf8').splitlines(): error = re.match(r'^.*(line\s+[0-9]+:.*)', line) diff --git a/orchestra/contrib/plans/rating.py b/orchestra/contrib/plans/ratings.py similarity index 100% rename from orchestra/contrib/plans/rating.py rename to orchestra/contrib/plans/ratings.py diff --git a/orchestra/contrib/plans/settings.py b/orchestra/contrib/plans/settings.py index f787b86d..853f6e48 100644 --- a/orchestra/contrib/plans/settings.py +++ b/orchestra/contrib/plans/settings.py @@ -3,13 +3,13 @@ from orchestra.contrib.settings import Setting PLANS_RATE_METHODS = Setting('PLANS_RATE_METHODS', ( - 'orchestra.contrib.plans.rating.step_price', - 'orchestra.contrib.plans.rating.match_price', - 'orchestra.contrib.plans.rating.best_price', + 'orchestra.contrib.plans.ratings.step_price', + 'orchestra.contrib.plans.ratings.match_price', + 'orchestra.contrib.plans.ratings.best_price', ) ) PLANS_DEFAULT_RATE_METHOD = Setting('PLANS_DEFAULT_RATE_METHOD', - 'orchestra.contrib.plans.rating.step_price', + 'orchestra.contrib.plans.ratings.step_price', ) diff --git a/orchestra/contrib/resources/tasks.py b/orchestra/contrib/resources/tasks.py index e440a36c..f1da8395 100644 --- a/orchestra/contrib/resources/tasks.py +++ b/orchestra/contrib/resources/tasks.py @@ -8,7 +8,7 @@ from .backends import ServiceMonitor @task(name='resources.Monitor') def monitor(resource_id, ids=None): - with LockFile('/dev/shm/resources.monitor-%i.lock' % resource_id, expire=60*60): + with LockFile('/dev/shm/resources.monitor-%i.lock' % resource_id, expire=60*60, unlocked=bool(ids)): from .models import ResourceData, Resource resource = Resource.objects.get(pk=resource_id) resource_model = resource.content_type.model_class() diff --git a/orchestra/contrib/saas/admin.py b/orchestra/contrib/saas/admin.py index 2d24e240..de7a7578 100644 --- a/orchestra/contrib/saas/admin.py +++ b/orchestra/contrib/saas/admin.py @@ -2,6 +2,7 @@ from django.contrib import admin from django.utils.translation import ugettext_lazy as _ from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin +from orchestra.admin.actions import disable from orchestra.contrib.accounts.admin import AccountAdminMixin from orchestra.plugins.admin import SelectPluginAdminMixin @@ -17,6 +18,7 @@ class SaaSAdmin(SelectPluginAdminMixin, ChangePasswordAdminMixin, AccountAdminMi plugin = SoftwareService plugin_field = 'service' plugin_title = 'Software as a Service' + actions = (disable,) def display_site_domain(self, saas): site_domain = saas.get_site_domain() diff --git a/orchestra/contrib/saas/models.py b/orchestra/contrib/saas/models.py index 2647be97..b67a17ee 100644 --- a/orchestra/contrib/saas/models.py +++ b/orchestra/contrib/saas/models.py @@ -61,6 +61,10 @@ class SaaS(models.Model): def active(self): return self.is_active and self.account.is_active + def disable(self): + self.is_active = False + self.save(update_fields=('is_active',)) + def clean(self): if not self.pk: self.name = self.name.lower() diff --git a/orchestra/contrib/services/templates/admin/services/service/change_form.html b/orchestra/contrib/services/templates/admin/services/service/change_form.html index 45cce7f6..07642046 100644 --- a/orchestra/contrib/services/templates/admin/services/service/change_form.html +++ b/orchestra/contrib/services/templates/admin/services/service/change_form.html @@ -23,7 +23,7 @@ nominal_price=28.10& tax=21& pricing_period=BILLING_PERIOD& - rate_algorithm=STEP_PRICE& + rate_algorithm=orchestra.contrib.plans.ratings.step_price& on_cancel=COMPENSATE& payment_style=PREPAY">Mailbox {% endoneliner %} diff --git a/orchestra/contrib/settings/admin.py b/orchestra/contrib/settings/admin.py index c3d6d688..0f73fca2 100644 --- a/orchestra/contrib/settings/admin.py +++ b/orchestra/contrib/settings/admin.py @@ -66,7 +66,7 @@ class SettingView(generic.edit.FormView): if not self.request.POST.get('confirmation'): settings_file = parser.get_settings_file() new_content = parser.apply(changes) - diff = sys.run("cat < %(file)s" % context, display=True) - elif diff.return_code == 1: + elif diff.exit_code == 1: # File is different, save the old one if interactive: msg = ("\n\nFile %(file)s be updated, do you like to overide " @@ -244,13 +245,13 @@ class Command(BaseCommand): if server_name: run('ln -s /etc/nginx/sites-available/%(server_name)s.conf /etc/nginx/sites-enabled/' % context, - error_codes=[0,1], display=True) + valid_codes=[0,1], display=True) else: run('rm /etc/nginx/sites-enabled/default') run('ln -s /etc/nginx/sites-available/%(project_name)s.conf /etc/nginx/sites-enabled/' % context, - error_codes=[0,1], display=True) + valid_codes=[0,1], display=True) run('ln -s /etc/uwsgi/apps-available/%(project_name)s.ini /etc/uwsgi/apps-enabled/' % context, - error_codes=[0,1], display=True) + valid_codes=[0,1], display=True) rotate = textwrap.dedent("""\ /var/log/nginx/*.log { diff --git a/orchestra/management/commands/setuppostfix.py b/orchestra/management/commands/setuppostfix.py index 7dd116b9..a3a75239 100644 --- a/orchestra/management/commands/setuppostfix.py +++ b/orchestra/management/commands/setuppostfix.py @@ -223,7 +223,7 @@ password_query = \ run("chmod go= %(dovecot_dir)s/dovecot-sql.conf.ext" % context) file_name = "%(postfix_dir)s/master.cf" % context - grep_dovecot = run("grep dovecot %s" % file_name, error_codes=[0,1]) + grep_dovecot = run("grep dovecot %s" % file_name, valid_codes=(0,1)) if grep_dovecot == '': run("#Processing %s" % file_name) dovecot_master=""" @@ -264,8 +264,8 @@ amavis unix - - n - 5 smtp #Postfix - mailname = run("cat /etc/mailname", error_codes=[0,1]) - hostname = run("hostname", error_codes=[0,1]) + mailname = run("cat /etc/mailname", vallid_codes=[0,1]) + hostname = run("hostname", valid_codes=[0,1]) if mailname != hostname: file_name = "/etc/mailname" run("#Processing %s" % file_name) diff --git a/orchestra/management/commands/setuppostgres.py b/orchestra/management/commands/setuppostgres.py index 38524777..626507d2 100644 --- a/orchestra/management/commands/setuppostgres.py +++ b/orchestra/management/commands/setuppostgres.py @@ -40,11 +40,11 @@ class Command(BaseCommand): 'db_host': options.get('db_host'), 'db_port': options.get('db_port') } - run('su postgres -c "psql -c \\"CREATE USER %(db_user)s PASSWORD \'%(db_password)s\';\\""' % context, error_codes=[0,1]) - run('su postgres -c "psql -c \\"CREATE DATABASE %(db_name)s OWNER %(db_user)s;\\""' % context, error_codes=[0,1]) + run('su postgres -c "psql -c \\"CREATE USER %(db_user)s PASSWORD \'%(db_password)s\';\\""' % context, valid_codes=(0,1)) + run('su postgres -c "psql -c \\"CREATE DATABASE %(db_name)s OWNER %(db_user)s;\\""' % context, valid_codes=(0,1)) context.update({'settings': os.path.join(get_project_dir(), 'settings.py')}) - if run("grep 'DATABASES' %(settings)s" % context, error_codes=[0,1]).return_code == 0: + if run("grep 'DATABASES' %(settings)s" % context, valid_codes=(0,1)).exit_code == 0: # Update existing settings_file run("sed -i \"s/'ENGINE': '\w*',/'ENGINE': 'django.db.backends.postgresql_psycopg2',/\" %(settings)s" % context) run("sed -i \"s/'NAME': '.*',/'NAME': '%(db_name)s',/\" %(settings)s" % context) diff --git a/orchestra/management/commands/startservices.py b/orchestra/management/commands/startservices.py index 7566acf0..1099802d 100644 --- a/orchestra/management/commands/startservices.py +++ b/orchestra/management/commands/startservices.py @@ -11,9 +11,9 @@ def run_tuple(services, action, options, optional=False): services = [services] for service in services: if options.get(service): - error_codes = [0,1] if optional else [0] - e = run('service %s %s' % (service, action), error_codes=error_codes) - if e.return_code == 1: + valid_codes = (0,1) if optional else (0,) + e = run('service %s %s' % (service, action), valid_codes=valid_codes) + if e.exit_code == 1: return False return True diff --git a/orchestra/management/commands/upgradeorchestra.py b/orchestra/management/commands/upgradeorchestra.py index ecd8ec23..3b7fd846 100644 --- a/orchestra/management/commands/upgradeorchestra.py +++ b/orchestra/management/commands/upgradeorchestra.py @@ -17,7 +17,7 @@ r = functools.partial(run, silent=False) def get_existing_pip_installation(): """ returns current pip installation path """ - if run("pip freeze|grep django-orchestra", error_codes=[0,1]).return_code == 0: + if run("pip freeze|grep django-orchestra", valid_codes=(0,1)).exit_code == 0: for lib_path in get_python_lib(), get_python_lib(prefix="/usr/local"): existing_path = os.path.abspath(os.path.join(lib_path, "orchestra")) if os.path.exists(existing_path): diff --git a/orchestra/utils/sys.py b/orchestra/utils/sys.py index 29dbed56..1865f4e9 100644 --- a/orchestra/utils/sys.py +++ b/orchestra/utils/sys.py @@ -93,16 +93,16 @@ def runiterator(command, display=False, stdin=b''): state = _Attribute(stdout) state.stderr = stderr - state.return_code = p.poll() + state.exit_code = p.poll() state.command = command yield state - if state.return_code != None: + if state.exit_code != None: p.stdout.close() p.stderr.close() raise StopIteration -def join(iterator, display=False, silent=False, error_codes=[0]): +def join(iterator, display=False, silent=False, valid_codes=(0,)): """ joins the iterator process """ stdout = b'' stderr = b'' @@ -110,18 +110,18 @@ def join(iterator, display=False, silent=False, error_codes=[0]): stdout += state.stdout stderr += state.stderr - return_code = state.return_code + exit_code = state.exit_code out = _Attribute(stdout.strip()) err = stderr.strip() out.failed = False - out.return_code = return_code + out.exit_code = exit_code out.stderr = err - if return_code not in error_codes: + if exit_code not in valid_codes: out.failed = True msg = "\nrun() encountered an error (return code %s) while executing '%s'\n" - msg = msg % (return_code, state.command) + msg = msg % (exit_code, state.command) if display: sys.stderr.write("\n\033[1;31mCommandError: %s %s\033[m\n" % (msg, err)) if not silent: @@ -131,12 +131,12 @@ def join(iterator, display=False, silent=False, error_codes=[0]): return out -def run(command, display=False, error_codes=[0], silent=False, stdin=b'', async=False): +def run(command, display=False, valid_codes=(0,), silent=False, stdin=b'', async=False): iterator = runiterator(command, display, stdin) next(iterator) if async: return iterator - return join(iterator, display=display, silent=silent, error_codes=error_codes) + return join(iterator, display=display, silent=silent, valid_codes=valie_codes) def sshrun(addr, command, *args, **kwargs):