django-orchestra/orchestra/contrib/orchestration/helpers.py

174 lines
6.9 KiB
Python
Raw Permalink Normal View History

2015-04-23 19:46:23 +00:00
import textwrap
2014-05-08 16:59:35 +00:00
from django.contrib import messages
from django.core.mail import mail_admins
from django.urls import reverse, NoReverseMatch
2014-05-08 16:59:35 +00:00
from django.utils.html import escape
2014-10-03 14:02:11 +00:00
from django.utils.safestring import mark_safe
from django.utils.translation import ngettext, gettext_lazy as _
2014-05-08 16:59:35 +00:00
from orchestra import settings as orchestra_settings
from orchestra.admin.utils import change_url
2014-05-08 16:59:35 +00:00
2015-04-23 19:46:23 +00:00
def get_backends_help_text(backends):
help_texts = {}
for backend in backends:
2015-04-24 11:39:20 +00:00
help_text = backend.__doc__ or ''
2015-04-23 19:46:23 +00:00
context = {
'model': backend.model,
'related_models': str(backend.related_models),
'script_executable': backend.script_executable,
'script_method': '.'.join(
(backend.script_method.__module__, backend.script_method.__name__)),
'function_method': '.'.join(
(backend.function_method.__module__, backend.function_method.__name__)),
2015-04-24 11:39:20 +00:00
'actions': str(backend.actions),
2015-04-23 19:46:23 +00:00
}
2015-04-24 11:39:20 +00:00
help_text += textwrap.dedent("""
- Model: <tt>'%(model)s'</tt>
- Related models: <tt>%(related_models)s</tt>
- Script executable: <tt>%(script_executable)s</tt>
- Script method: <tt>%(script_method)s</tt>
- Function method: <tt>%(function_method)s</tt>
- Actions: <tt>%(actions)s</tt>
"""
2015-04-23 19:46:23 +00:00
) % context
2015-04-24 11:39:20 +00:00
help_text = help_text.lstrip().splitlines()
help_settings = ['']
if backend.doc_settings:
module, names = backend.doc_settings
for name in names:
value = getattr(module, name)
if isinstance(value, str):
help_settings.append("<tt>%s = '%s'</tt>" % (name, value))
else:
2015-10-05 13:31:08 +00:00
help_settings.append("<tt>%s = %s</tt>" % (name, value))
2015-04-24 11:39:20 +00:00
help_text += help_settings
help_texts[backend.get_name()] = '<br>'.join(help_text)
2015-04-23 19:46:23 +00:00
return help_texts
def get_instance_url(operation):
try:
url = change_url(operation.instance)
except NoReverseMatch:
alt_repr = '%s-%s' % (operation.content_type, operation.object_id)
2015-09-20 10:57:13 +00:00
return _("Deleted {0}").format(operation.instance_repr or alt_repr)
return orchestra_settings.ORCHESTRA_SITE_URL + url
2014-05-08 16:59:35 +00:00
def send_report(method, args, log):
server = args[0]
2015-04-02 16:14:55 +00:00
backend = method.__self__.__class__.__name__
subject = '[Orchestra] %s execution %s on %s' % (backend, log.state, server)
2014-05-08 16:59:35 +00:00
separator = "\n%s\n\n" % ('~ '*40,)
operations = '\n'.join(
[' '.join((op.action, get_instance_url(op))) for op in log.operations.all()]
)
2015-06-22 14:14:16 +00:00
log_url = reverse('admin:orchestration_backendlog_change', args=(log.pk,))
log_url = orchestra_settings.ORCHESTRA_SITE_URL + log_url
2014-05-08 16:59:35 +00:00
message = separator.join([
"[EXIT CODE] %s" % log.exit_code,
"[STDERR]\n%s" % log.stderr,
"[STDOUT]\n%s" % log.stdout,
"[SCRIPT]\n%s" % log.script,
"[TRACEBACK]\n%s" % log.traceback,
"[OPERATIONS]\n%s" % operations,
2015-06-22 14:14:16 +00:00
"[BACKEND LOG] %s" % log_url,
2014-05-08 16:59:35 +00:00
])
html_message = '\n\n'.join([
'<h4 style="color:#505050;">Exit code %s</h4>' % log.exit_code,
'<h4 style="color:#505050;">Stderr</h4>'
'<pre style="margin-left:20px;font-size:11px">%s</pre>' % escape(log.stderr),
'<h4 style="color:#505050;">Stdout</h4>'
'<pre style="margin-left:20px;font-size:11px">%s</pre>' % escape(log.stdout),
'<h4 style="color:#505050;">Script</h4>'
'<pre style="margin-left:20px;font-size:11px">%s</pre>' % escape(log.script),
'<h4 style="color:#505050;">Traceback</h4>'
'<pre style="margin-left:20px;font-size:11px">%s</pre>' % escape(log.traceback),
'<h4 style="color:#505050;">Operations</h4>'
'<pre style="margin-left:20px;font-size:11px">%s</pre>' % escape(operations),
2015-06-22 14:14:16 +00:00
'<h4 style="color:#505050;">Backend log <a href="%s">%s</h4>' % (log_url, log_url),
2014-05-08 16:59:35 +00:00
])
mail_admins(subject, message, html_message=html_message)
2015-05-06 14:39:25 +00:00
def get_backend_url(ids):
if len(ids) == 1:
return reverse('admin:orchestration_backendlog_change', args=ids)
elif len(ids) > 1:
url = reverse('admin:orchestration_backendlog_changelist')
return url + '?id__in=%s' % ','.join(map(str, ids))
return ''
def get_messages(logs):
messages = []
total, successes, run_async = 0, 0, 0
2014-10-03 14:02:11 +00:00
ids = []
2015-05-06 14:39:25 +00:00
async_ids = []
2014-10-03 14:02:11 +00:00
for log in logs:
total += 1
2016-04-06 19:00:16 +00:00
try:
# Some EXCEPTION logs are not stored on the database
ids.append(log.pk)
2016-04-06 19:00:16 +00:00
except AttributeError:
pass
2015-05-12 12:38:40 +00:00
if log.is_success:
2014-10-03 14:02:11 +00:00
successes += 1
2015-05-12 12:38:40 +00:00
elif not log.has_finished:
run_async += 1
2015-05-06 14:39:25 +00:00
async_ids.append(log.id)
errors = total-successes-run_async
2015-05-06 14:39:25 +00:00
url = get_backend_url(ids)
async_url = get_backend_url(async_ids)
async_msg = ''
if run_async:
async_msg = ngettext(
2016-03-11 12:19:34 +00:00
_('<a href="{async_url}">{name}</a> is running on the background'),
_('<a href="{async_url}">{run_async} backends</a> are running on the background'),
run_async)
2014-05-08 16:59:35 +00:00
if errors:
2016-03-11 12:19:34 +00:00
if total == 1:
msg = _('<a href="{url}">{name}</a> has fail to execute')
2016-03-11 12:19:34 +00:00
else:
msg = ngettext(
2016-03-11 12:19:34 +00:00
_('<a href="{url}">{errors} out of {total} backends</a> has fail to execute'),
_('<a href="{url}">{errors} out of {total} backends</a> have fail to execute'),
errors)
2015-05-06 14:39:25 +00:00
if async_msg:
msg += ', ' + str(async_msg)
msg = msg.format(errors=errors, run_async=run_async, async_url=async_url, total=total, url=url,
2016-03-11 12:19:34 +00:00
name=log.backend)
messages.append(('error', msg + '.'))
2015-05-06 14:39:25 +00:00
elif successes:
if async_msg:
2016-03-11 12:19:34 +00:00
if total == 1:
msg = _('<a href="{url}">{name}</a> has been executed')
else:
msg = ngettext(
2016-03-11 12:19:34 +00:00
_('<a href="{url}">{successes} out of {total} backends</a> has been executed'),
_('<a href="{url}">{successes} out of {total} backends</a> have been executed'),
successes)
2015-05-06 14:39:25 +00:00
msg += ', ' + str(async_msg)
else:
msg = ngettext(
2016-03-11 12:19:34 +00:00
_('<a href="{url}">{name}</a> has been executed'),
2015-05-06 14:39:25 +00:00
_('<a href="{url}">{total} backends</a> have been executed'),
total)
msg = msg.format(
total=total, url=url, async_url=async_url, run_async=run_async, successes=successes,
2016-03-11 12:19:34 +00:00
name=log.backend
)
messages.append(('success', msg + '.'))
2014-05-08 16:59:35 +00:00
else:
msg = async_msg.format(url=url, async_url=async_url, run_async=run_async, name=log.backend)
messages.append(('success', msg + '.'))
return messages
def message_user(request, logs):
for func, msg in get_messages(logs):
getattr(messages, func)(request, mark_safe(msg))