OpenDroneMap-WebODM/app/api/processingnodes.py

101 wiersze
3.5 KiB
Python

import django_filters
from django_filters.rest_framework import FilterSet
from guardian.shortcuts import get_objects_for_user
from rest_framework import serializers, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from nodeodm.models import ProcessingNode
from webodm import settings
class ProcessingNodeSerializer(serializers.ModelSerializer):
online = serializers.SerializerMethodField()
label = serializers.SerializerMethodField()
def get_online(self, obj):
return obj.is_online()
def get_label(self, obj):
return str(obj)
class Meta:
model = ProcessingNode
fields = '__all__'
class ProcessingNodeFilter(FilterSet):
has_available_options = django_filters.CharFilter(method='filter_has_available_options')
# noinspection PyMethodMayBeStatic
def filter_has_available_options(self, queryset, name, value):
if value.lower() in ['true', '1']:
return queryset.exclude(available_options=dict())
else:
return queryset.filter(available_options=dict())
class Meta:
model = ProcessingNode
fields = ['has_available_options', 'id', 'hostname', 'port', 'api_version', 'queue_count', 'max_images', 'label', 'engine', 'engine_version', ]
class ProcessingNodeViewSet(viewsets.ModelViewSet):
"""
Processing node get/add/delete/update
Processing nodes are associated with zero or more tasks and
take care of processing input images.
"""
filter_class = ProcessingNodeFilter
pagination_class = None
serializer_class = ProcessingNodeSerializer
queryset = ProcessingNode.objects.all()
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
if settings.UI_MAX_PROCESSING_NODES is not None:
queryset = queryset[:settings.UI_MAX_PROCESSING_NODES]
if settings.NODE_OPTIMISTIC_MODE:
for pn in queryset:
pn.update_node_info()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class ProcessingNodeOptionsView(APIView):
"""
Display the common options available among all online processing nodes. This is calculated by intersecting the available_options field of all online processing nodes visible to the current user.
"""
queryset = ProcessingNode.objects.all()
def get(self, request):
nodes = get_objects_for_user(request.user, 'view_processingnode', ProcessingNode, accept_global_perms=False)
common_options = []
for node in nodes:
# Skip offline nodes
if not node.is_online():
continue
# First? Just populate
if len(common_options) == 0 and len(node.available_options) > 0:
common_options = node.available_options
else:
# Remove all options that are in common_options,
# but that are not in node.available_options
for common_option in common_options:
found = False
for option in node.available_options:
if common_option['name'] == option['name']:
found = True
break
# Mark for deletion
if not found:
common_option['_delete'] = True
common_options = [co for co in common_options if not '_delete' in co]
return Response(common_options)