OpenDroneMap-WebODM/coreplugins/dronedb/api_views.py

236 wiersze
7.8 KiB
Python
Czysty Zwykły widok Historia

2022-01-04 17:13:15 +00:00
import importlib
import requests
import os
from os import path
2022-01-12 18:03:49 +00:00
2022-01-14 18:59:28 +00:00
#from requests.structures import CaseInsensitiveDict
2022-01-04 17:13:15 +00:00
from app import models, pending_actions
from app.plugins.views import TaskView
from app.plugins.worker import run_function_async
from app.plugins import get_current_plugin
from coreplugins.dronedb.ddb import DEFAULT_HUB_URL, DroneDB, parse_url, verify_url
2022-01-04 17:13:15 +00:00
from worker.celery import app
from rest_framework.response import Response
from rest_framework import status
#from .platform_helper import get_all_platforms, get_platform_by_name
2022-01-14 18:59:28 +00:00
VALID_IMAGE_EXTENSIONS = ['.tiff', '.tif', '.png', '.jpeg', '.jpg']
def is_valid(file):
_, file_extension = path.splitext(file)
return file_extension.lower() in VALID_IMAGE_EXTENSIONS or file == 'gcp_list.txt'
2022-01-17 14:47:37 +00:00
def get_settings(request):
ds = get_current_plugin().get_user_data_store(request.user)
registry_url = ds.get_string('registry_url') or DEFAULT_HUB_URL
2022-01-17 14:47:37 +00:00
username = ds.get_string('username') or None
password = ds.get_string('password') or None
token = ds.get_string('token') or None
2022-01-18 12:04:50 +00:00
return registry_url, username, password, token
2022-01-17 14:47:37 +00:00
def update_token(request, token):
ds = get_current_plugin().get_user_data_store(request.user)
ds.set_string('token', token)
def get_ddb(request):
2022-01-18 12:04:50 +00:00
registry_url, username, password, token = get_settings(request)
2022-01-17 14:47:37 +00:00
if registry_url == None or username == None or password == None:
raise ValueError('Credentials must be set.')
return DroneDB(registry_url, username, password, token, lambda token: update_token(request, token))
2022-01-07 11:55:35 +00:00
class ImportDatasetTaskView(TaskView):
def post(self, request, project_pk=None, pk=None):
2022-01-13 12:08:32 +00:00
2022-01-14 18:59:28 +00:00
task = self.get_and_check_task(request, pk)
2022-01-04 17:13:15 +00:00
# Read form data
2022-01-07 11:55:35 +00:00
ddb_url = request.data.get('ddb_url', None)
2022-01-17 14:47:37 +00:00
2022-01-07 11:55:35 +00:00
if ddb_url == None:
return Response({'error': 'DroneDB url must be set.'}, status=status.HTTP_400_BAD_REQUEST)
2022-01-04 17:13:15 +00:00
registry_url, orgSlug, dsSlug, folder = parse_url(ddb_url).values()
2022-01-14 18:59:28 +00:00
2022-01-18 12:04:50 +00:00
_, username, password, token = get_settings(request)
ddb = DroneDB(registry_url, username, password, token, lambda token: update_token(request, token))
2022-01-14 18:59:28 +00:00
# Get the files from the folder
rawfiles = ddb.get_files_list(orgSlug, dsSlug, folder)
files = [file for file in rawfiles if is_valid(file['path'])]
2022-01-07 11:55:35 +00:00
# Verify that the folder url is valid
2022-01-14 18:59:28 +00:00
if len(files) == 0:
return Response({'error': 'Empty dataset or folder.'}, status=status.HTTP_400_BAD_REQUEST)
2022-01-07 11:55:35 +00:00
# Update the task with the new information
task.console_output += "Importing {} images...\n".format(len(files))
task.images_count = len(files)
task.pending_action = pending_actions.IMPORT
task.save()
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
# Associate the folder url with the project and task
combined_id = "{}_{}".format(project_pk, pk)
2022-01-14 18:59:28 +00:00
datastore = get_current_plugin().get_global_data_store()
datastore.set_string(combined_id, {'ddbUrl': ddb_url, 'token': ddb.token})
2022-01-07 11:55:35 +00:00
# Start importing the files in the background
2022-01-14 18:59:28 +00:00
serialized = {'token': ddb.token, 'files': files}
2022-01-07 11:55:35 +00:00
run_function_async(import_files, task.id, serialized)
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
return Response({}, status=status.HTTP_200_OK)
2022-01-04 17:13:15 +00:00
2022-01-13 12:08:32 +00:00
class CheckCredentialsTaskView(TaskView):
def post(self, request):
2022-01-04 17:13:15 +00:00
2022-01-13 12:08:32 +00:00
# Read form data
hub_url = request.data.get('hubUrl', None)
username = request.data.get('userName', None)
password = request.data.get('password', None)
2022-01-04 17:13:15 +00:00
2022-01-13 12:08:32 +00:00
# Make sure both values are set
if hub_url == None or username == None or password == None:
return Response({'error': 'All fields must be set.'}, status=status.HTTP_400_BAD_REQUEST)
try:
2022-01-13 12:08:32 +00:00
ddb = DroneDB(hub_url, username, password)
return Response({'success': ddb.login()}, status=status.HTTP_200_OK)
except(Exception) as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
class OrganizationsTaskView(TaskView):
def get(self, request):
try:
2022-01-17 14:47:37 +00:00
ddb = get_ddb(request)
orgs = ddb.get_organizations()
return Response(orgs, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
class DatasetsTaskView(TaskView):
def get(self, request, org=None):
if org == None:
return Response({'error': 'Organization must be set.'}, status=status.HTTP_400_BAD_REQUEST)
try:
2022-01-17 14:47:37 +00:00
ddb = get_ddb(request)
dss = ddb.get_datasets(org)
return Response(dss, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
class FoldersTaskView(TaskView):
def get(self, request, org=None, ds=None):
if org == None or ds == None:
return Response({'error': 'Organization and dataset must be set.'}, status=status.HTTP_400_BAD_REQUEST)
try:
2022-01-17 14:47:37 +00:00
ddb = get_ddb(request)
folders = ddb.get_folders(org, ds)
return Response(folders, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
class VerifyUrlTaskView(TaskView):
def post(self, request):
# Read form data
url = request.data.get('url', None)
if url == None:
return Response({'error': 'Url must be set.'}, status=status.HTTP_400_BAD_REQUEST)
2022-01-18 12:04:50 +00:00
_, username, password, _ = get_settings(request)
try:
result, org, ds, folder, count, size = verify_url(url, username, password).values()
if (not result):
return Response({'error': 'Invalid url.'}, status=status.HTTP_400_BAD_REQUEST)
return Response({'count': count, 'success': result, 'ds' : ds, 'org': org, 'folder': folder or None, 'size': size}
2022-01-17 17:54:44 +00:00
if org else {'success': False}, status=status.HTTP_200_OK)
except Exception as e:
2022-01-14 16:49:44 +00:00
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
class InfoTaskView(TaskView):
def get(self, request):
2022-01-18 12:04:50 +00:00
registry_url, username, _, _ = get_settings(request)
2022-01-14 16:49:44 +00:00
return Response({ 'hubUrl': registry_url, 'username': username }, status=status.HTTP_200_OK)
2022-01-04 17:13:15 +00:00
2022-01-12 18:03:49 +00:00
def import_files(task_id, carrier):
2022-01-07 11:55:35 +00:00
import requests
from app import models
from app.plugins import logger
2022-01-04 17:13:15 +00:00
2022-01-14 18:59:28 +00:00
files = carrier['files']
2022-01-12 18:03:49 +00:00
2022-01-14 18:59:28 +00:00
#headers = CaseInsensitiveDict()
headers = {}
2022-01-12 18:03:49 +00:00
2022-01-17 10:06:50 +00:00
if carrier['token'] != None:
2022-01-12 18:03:49 +00:00
headers['Authorization'] = 'Token ' + carrier['token']
2022-01-07 11:55:35 +00:00
def download_file(task, file):
path = task.task_path(file['name'])
2022-01-12 18:03:49 +00:00
download_stream = requests.get(file['url'], stream=True, timeout=60, headers=headers)
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
with open(path, 'wb') as fd:
for chunk in download_stream.iter_content(4096):
fd.write(chunk)
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
models.ImageUpload.objects.create(task=task, image=path)
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
logger.info("Will import {} files".format(len(files)))
task = models.Task.objects.get(pk=task_id)
task.create_task_directories()
task.save()
2022-01-04 17:13:15 +00:00
2022-01-07 11:55:35 +00:00
try:
downloaded_total = 0
for file in files:
download_file(task, file)
task.check_if_canceled()
models.Task.objects.filter(pk=task.id).update(upload_progress=(float(downloaded_total) / float(len(files))))
downloaded_total += 1
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
raise NodeServerError(e)
task.refresh_from_db()
task.pending_action = None
task.processing_time = 0
task.partial = False
task.save()