django-orchestra/orchestra/apps/lists/backends.py

199 lines
7.6 KiB
Python
Raw Normal View History

2014-10-15 12:47:28 +00:00
import re
2014-07-25 15:17:50 +00:00
import textwrap
2014-07-11 14:48:46 +00:00
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
2014-05-08 16:59:35 +00:00
2014-07-09 16:17:43 +00:00
from orchestra.apps.orchestration import ServiceController
from orchestra.apps.resources import ServiceMonitor
2014-05-08 16:59:35 +00:00
2014-07-11 14:48:46 +00:00
from . import settings
2014-10-09 17:04:12 +00:00
from .models import List
2014-07-11 14:48:46 +00:00
2014-05-08 16:59:35 +00:00
2014-07-09 16:17:43 +00:00
class MailmanBackend(ServiceController):
2014-05-08 16:59:35 +00:00
verbose_name = "Mailman"
model = 'lists.List'
2014-10-15 12:47:28 +00:00
addresses = [
'',
'-admin',
'-bounces',
'-confirm',
'-join',
'-leave',
'-owner',
'-request',
'-subscribe',
'-unsubscribe'
]
2014-10-09 17:04:12 +00:00
def include_virtual_alias_domain(self, context):
2014-10-15 12:47:28 +00:00
# TODO for list virtual_domains cleaning up we need to know the old domain name when a list changes its address
# domain, but this is not possible with the current design.
# sync the whole file everytime?
2014-10-15 19:29:58 +00:00
# TODO same for mailbox virtual domains
2014-10-09 17:04:12 +00:00
if context['address_domain']:
self.append(textwrap.dedent("""
[[ $(grep "^\s*%(address_domain)s\s*$" %(virtual_alias_domains)s) ]] || {
echo "%(address_domain)s" >> %(virtual_alias_domains)s
UPDATED_VIRTUAL_ALIAS_DOMAINS=1
2014-11-27 19:17:26 +00:00
}""") % context
)
2014-10-09 17:04:12 +00:00
def exclude_virtual_alias_domain(self, context):
address_domain = context['address_domain']
if not List.objects.filter(address_domain=address_domain).exists():
2014-10-27 14:31:04 +00:00
self.append('sed -i "/^%(address_domain)s\s*$/d" %(virtual_alias_domains)s' % context)
2014-10-09 17:04:12 +00:00
def get_virtual_aliases(self, context):
aliases = []
2014-10-15 12:47:28 +00:00
for address in self.addresses:
2014-10-09 17:04:12 +00:00
context['address'] = address
aliases.append("%(address_name)s%(address)s@%(domain)s\t%(name)s%(address)s" % context)
return '\n'.join(aliases)
def save(self, mail_list):
context = self.get_context(mail_list)
2014-10-15 12:47:28 +00:00
# Create list
self.append(textwrap.dedent("""\
[[ ! -e %(mailman_root)s/lists/%(name)s ]] && {
newlist --quiet --emailhost='%(domain)s' '%(name)s' '%(admin)s' '%(password)s'
2014-11-27 19:17:26 +00:00
}""") % context)
2014-10-15 12:47:28 +00:00
# Custom domain
2014-10-09 17:04:12 +00:00
if mail_list.address:
2014-11-27 19:17:26 +00:00
context['aliases'] = self.get_virtual_aliases(context)
2014-10-15 12:47:28 +00:00
# Preserve indentation
self.append(textwrap.dedent("""\
if [[ ! $(grep '\s\s*%(name)s\s*$' %(virtual_alias)s) ]]; then
echo '# %(banner)s\n%(aliases)s
' >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
else
if [[ ! $(grep '^\s*%(address_name)s@%(address_domain)s\s\s*%(name)s\s*$' %(virtual_alias)s) ]]; then
2014-10-27 15:15:22 +00:00
sed -i -e '/^.*\s%(name)s\(%(address_regex)s\)\s*$/d' \\
-e 'N; /^\s*\\n\s*$/d; P; D' %(virtual_alias)s
2014-10-15 12:47:28 +00:00
echo '# %(banner)s\n%(aliases)s
' >> %(virtual_alias)s
UPDATED_VIRTUAL_ALIAS=1
fi
2014-11-27 19:17:26 +00:00
fi""") % context
)
self.append(
'echo "require_explicit_destination = 0" | '
'%(mailman_root)s/bin/config_list -i /dev/stdin %(name)s' % context
)
2014-10-15 12:47:28 +00:00
self.append(textwrap.dedent("""\
echo "host_name = '%(address_domain)s'" | \
2014-11-27 19:17:26 +00:00
%(mailman_root)s/bin/config_list -i /dev/stdin %(name)s""") % context
)
2014-10-15 12:47:28 +00:00
else:
# Cleanup shit
self.append(textwrap.dedent("""\
if [[ ! $(grep '\s\s*%(name)s\s*$' %(virtual_alias)s) ]]; then
2014-10-27 14:31:04 +00:00
sed -i "/^.*\s%(name)s\s*$/d" %(virtual_alias)s
2014-11-27 19:17:26 +00:00
fi""") % context
)
2014-10-15 12:47:28 +00:00
# Update
if context['password'] is not None:
2014-11-27 19:17:26 +00:00
self.append(
'%(mailman_root)s/bin/change_pw --listname="%(name)s" --password="%(password)s"' % context
)
2014-10-09 17:04:12 +00:00
self.include_virtual_alias_domain(context)
def delete(self, mail_list):
2014-10-15 12:47:28 +00:00
context = self.get_context(mail_list)
self.exclude_virtual_alias_domain(context)
2014-10-27 15:15:22 +00:00
self.append(textwrap.dedent("""\
sed -i -e '/^.*\s%(name)s\(%(address_regex)s\)\s*$/d' \\
2014-11-27 19:17:26 +00:00
-e 'N; /^\s*\\n\s*$/d; P; D' %(virtual_alias)s""") % context
)
2014-10-27 14:31:04 +00:00
self.append("rmlist -a %(name)s" % context)
2014-10-09 17:04:12 +00:00
def commit(self):
context = self.get_context_files()
self.append(textwrap.dedent("""
[[ $UPDATED_VIRTUAL_ALIAS == 1 ]] && { postmap %(virtual_alias)s; }
[[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]] && { /etc/init.d/postfix reload; }
2014-11-27 19:17:26 +00:00
""") % context
)
2014-10-09 17:04:12 +00:00
def get_context_files(self):
return {
'virtual_alias': settings.LISTS_VIRTUAL_ALIAS_PATH,
2014-10-15 12:47:28 +00:00
'virtual_alias_domains': settings.LISTS_VIRTUAL_ALIAS_DOMAINS_PATH,
2014-10-09 17:04:12 +00:00
}
2014-10-27 14:31:04 +00:00
def get_banner(self, mail_list):
banner = super(MailmanBackend, self).get_banner()
return '%s %s' % (banner, mail_list.name)
2014-10-09 17:04:12 +00:00
def get_context(self, mail_list):
context = self.get_context_files()
context.update({
2014-10-27 15:15:22 +00:00
'banner': self.get_banner(mail_list),
2014-10-09 17:04:12 +00:00
'name': mail_list.name,
'password': mail_list.password,
'domain': mail_list.address_domain or settings.LISTS_DEFAULT_DOMAIN,
2014-10-23 21:25:44 +00:00
'address_name': mail_list.get_address_name(),
2014-10-09 17:04:12 +00:00
'address_domain': mail_list.address_domain,
2014-10-27 15:15:22 +00:00
'address_regex': '\|'.join(self.addresses),
2014-10-09 17:04:12 +00:00
'admin': mail_list.admin_email,
2014-10-15 12:47:28 +00:00
'mailman_root': settings.LISTS_MAILMAN_ROOT_PATH,
2014-10-09 17:04:12 +00:00
})
return context
2014-07-09 16:17:43 +00:00
class MailmanTraffic(ServiceMonitor):
model = 'lists.List'
resource = ServiceMonitor.TRAFFIC
verbose_name = _("Mailman traffic")
2014-07-09 16:17:43 +00:00
2014-07-25 15:17:50 +00:00
def prepare(self):
super(MailmanTraffic, self).prepare()
2014-07-25 15:17:50 +00:00
current_date = timezone.localtime(self.current_date)
current_date = current_date.strftime("%b %d %H:%M:%S")
2014-10-15 12:47:28 +00:00
self.append(textwrap.dedent("""\
2014-07-25 15:17:50 +00:00
function monitor () {
OBJECT_ID=$1
LAST_DATE=$2
LIST_NAME="$3"
MAILMAN_LOG="$4"
SUBSCRIBERS=$(list_members ${LIST_NAME} | wc -l)
SIZE=$(grep ' post to ${LIST_NAME} ' "${MAILMAN_LOG}" \\
| awk '"$LAST_DATE"<=$0 && $0<="%s"' \\
| sed 's/.*size=\([0-9]*\).*/\\1/' \\
| tr '\\n' '+' \\
2014-07-25 15:17:50 +00:00
| xargs -i echo {} )
echo ${OBJECT_ID} $(( ${SIZE}*${SUBSCRIBERS} ))
2014-11-27 19:17:26 +00:00
}""") % current_date)
2014-07-25 15:17:50 +00:00
2014-07-11 14:48:46 +00:00
def monitor(self, mail_list):
context = self.get_context(mail_list)
2014-07-09 16:17:43 +00:00
self.append(
'monitor %(object_id)i %(last_date)s "%(list_name)s" "%(mailman_log)s{,.1}"' % context)
2014-07-11 14:48:46 +00:00
def get_context(self, mail_list):
2014-07-14 14:56:48 +00:00
last_date = timezone.localtime(self.get_last_date(mail_list.pk))
2014-07-11 14:48:46 +00:00
return {
'mailman_log': settings.LISTS_MAILMAN_POST_LOG_PATH,
'list_name': mail_list.name,
'object_id': mail_list.pk,
2014-07-14 14:56:48 +00:00
'last_date': last_date.strftime("%b %d %H:%M:%S"),
2014-07-11 14:48:46 +00:00
}
2014-10-27 13:29:02 +00:00
class MailmanSubscribers(ServiceMonitor):
model = 'lists.List'
verbose_name = _("Mailman subscribers")
def monitor(self, mail_list):
context = self.get_context(mail_list)
self.append('echo %(object_id)i $(list_members %(list_name)s | wc -l)' % context)
def get_context(self, mail_list):
return {
'list_name': mail_list.name,
'object_id': mail_list.pk,
}