2016-07-15 12:44:38 +00:00
|
|
|
from collections import defaultdict
|
|
|
|
|
2016-02-15 13:08:49 +00:00
|
|
|
from django.contrib import messages
|
|
|
|
from django.contrib.admin import helpers
|
|
|
|
from django.shortcuts import render
|
|
|
|
from django.utils.safestring import mark_safe
|
|
|
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
|
|
|
|
|
|
|
from orchestra.admin.utils import get_object_from_url, change_url
|
|
|
|
from orchestra.contrib.orchestration.helpers import message_user
|
2016-07-15 12:44:38 +00:00
|
|
|
from orchestra.utils.python import OrderedSet
|
2016-02-15 13:08:49 +00:00
|
|
|
|
2016-07-15 12:44:38 +00:00
|
|
|
from . import manager, Operation
|
|
|
|
from .models import BackendOperation, Route, Server
|
2016-02-15 13:08:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
def retry_backend(modeladmin, request, queryset):
|
2016-02-16 09:47:08 +00:00
|
|
|
related_operations = queryset.values_list('operations__id', flat=True).distinct()
|
|
|
|
related_operations = BackendOperation.objects.filter(pk__in=related_operations)
|
|
|
|
related_operations = related_operations.select_related('log__server').prefetch_related('instance')
|
2016-02-15 13:08:49 +00:00
|
|
|
if request.POST.get('post') == 'generic_confirmation':
|
|
|
|
operations = []
|
2016-02-16 09:47:08 +00:00
|
|
|
for operation in related_operations:
|
|
|
|
if operation.instance:
|
|
|
|
op = Operation.load(operation)
|
|
|
|
operations.append(op)
|
2016-02-15 13:08:49 +00:00
|
|
|
if not operations:
|
|
|
|
messages.warning(request, _("No backend operation has been executed."))
|
|
|
|
else:
|
|
|
|
logs = Operation.execute(operations)
|
|
|
|
message_user(request, logs)
|
2016-07-19 22:45:04 +00:00
|
|
|
for backendlog in queryset:
|
|
|
|
modeladmin.log_change(request, backendlog, 'Retried')
|
2016-02-15 13:08:49 +00:00
|
|
|
return
|
|
|
|
opts = modeladmin.model._meta
|
|
|
|
display_objects = []
|
|
|
|
deleted_objects = []
|
2016-02-16 09:47:08 +00:00
|
|
|
for op in related_operations:
|
2016-02-15 13:08:49 +00:00
|
|
|
if not op.instance:
|
|
|
|
deleted_objects.append(op)
|
|
|
|
else:
|
|
|
|
context = {
|
|
|
|
'backend': op.log.backend,
|
|
|
|
'action': op.action,
|
|
|
|
'instance': op.instance,
|
|
|
|
'instance_url': change_url(op.instance),
|
|
|
|
'server': op.log.server,
|
|
|
|
'server_url': change_url(op.log.server),
|
|
|
|
}
|
|
|
|
display_objects.append(mark_safe(
|
|
|
|
'%(backend)s.%(action)s(<a href="%(instance_url)s">%(instance)s</a>) @ <a href="%(server_url)s">%(server)s</a>' % context
|
|
|
|
))
|
|
|
|
context = {
|
|
|
|
'title': _("Are you sure to execute the following backends?"),
|
|
|
|
'action_name': _('Retry backend'),
|
|
|
|
'action_value': 'retry_backend',
|
|
|
|
'display_objects': display_objects,
|
|
|
|
'deleted_objects': deleted_objects,
|
|
|
|
'queryset': queryset,
|
|
|
|
'opts': opts,
|
|
|
|
'app_label': opts.app_label,
|
|
|
|
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
|
|
|
'obj': get_object_from_url(modeladmin, request),
|
|
|
|
}
|
|
|
|
return render(request, 'admin/orchestration/backends/retry.html', context)
|
|
|
|
retry_backend.short_description = _("Retry")
|
|
|
|
retry_backend.url_name = 'retry'
|
2016-07-15 12:44:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
def orchestrate(modeladmin, request, queryset):
|
|
|
|
operations = set()
|
|
|
|
action = Operation.SAVE
|
|
|
|
operations = OrderedSet()
|
|
|
|
if queryset.model is Route:
|
|
|
|
for route in queryset:
|
|
|
|
routes = [route]
|
|
|
|
backend = route.backend_class
|
|
|
|
if action not in backend.actions:
|
|
|
|
continue
|
|
|
|
for instance in backend.model_class().objects.all():
|
|
|
|
if route.matches(instance):
|
|
|
|
operations.add(Operation(backend, instance, action, routes=routes))
|
|
|
|
elif queryset.model is Server:
|
|
|
|
models = set()
|
|
|
|
for server in queryset:
|
|
|
|
routes = server.routes.all()
|
|
|
|
for route in routes.filter(is_active=True):
|
|
|
|
model = route.backend_class.model_class()
|
|
|
|
models.add(model)
|
|
|
|
querysets = [model.objects.order_by('id') for model in models]
|
|
|
|
|
|
|
|
route_cache = {}
|
|
|
|
for model in models:
|
|
|
|
for instance in model.objects.all():
|
|
|
|
manager.collect(instance, action, operations=operations, route_cache=route_cache)
|
|
|
|
routes = []
|
|
|
|
result = []
|
|
|
|
for operation in operations:
|
|
|
|
routes = [route for route in operation.routes if route.host in queryset]
|
|
|
|
operation.routes = routes
|
|
|
|
if routes:
|
|
|
|
result.append(operation)
|
|
|
|
operations = result
|
|
|
|
if not operations:
|
2016-07-19 22:45:04 +00:00
|
|
|
messages.warning(request, _("No related operations."))
|
|
|
|
return
|
2016-07-15 12:44:38 +00:00
|
|
|
|
|
|
|
if request.POST.get('post') == 'generic_confirmation':
|
|
|
|
logs = Operation.execute(operations)
|
|
|
|
message_user(request, logs)
|
2016-07-19 22:45:04 +00:00
|
|
|
for obj in queryset:
|
|
|
|
modeladmin.log_change(request, obj, 'Orchestrated')
|
2016-07-15 12:44:38 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
opts = modeladmin.model._meta
|
|
|
|
display_objects = {}
|
|
|
|
for operation in operations:
|
|
|
|
try:
|
|
|
|
display_objects[operation.backend].append(operation)
|
|
|
|
except KeyError:
|
|
|
|
display_objects[operation.backend] = [operation]
|
|
|
|
context = {
|
|
|
|
'title': _("Are you sure to execute the following operations?"),
|
|
|
|
'action_name': _('Orchestrate'),
|
|
|
|
'action_value': 'orchestrate',
|
|
|
|
'display_objects': display_objects,
|
|
|
|
'queryset': queryset,
|
|
|
|
'opts': opts,
|
|
|
|
'app_label': opts.app_label,
|
|
|
|
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
|
|
|
|
'obj': get_object_from_url(modeladmin, request),
|
|
|
|
}
|
|
|
|
return render(request, 'admin/orchestration/orchestrate.html', context)
|
2016-07-19 22:45:04 +00:00
|
|
|
orchestrate.help_text = _("Execute all related operations on the server(s)")
|