You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2019/05/28 13:22:32 UTC
[airavata-django-portal] 02/06: AIRAVATA-3032 Upload input files to
tmp directory
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch airavata-3016
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit f56ca58345ab964709af10cec56077e9f48d2fb1
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Sun May 26 13:58:32 2019 -0400
AIRAVATA-3032 Upload input files to tmp directory
---
django_airavata/apps/api/data_products_helper.py | 22 ++++++++++++---
django_airavata/apps/api/datastore.py | 2 +-
django_airavata/apps/api/urls.py | 1 +
django_airavata/apps/api/views.py | 19 ++++++++++++-
.../experiment/input-editors/FileInputEditor.vue | 31 ++++++++++++++--------
5 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/django_airavata/apps/api/data_products_helper.py b/django_airavata/apps/api/data_products_helper.py
index 785bb68..eb7f0ad 100644
--- a/django_airavata/apps/api/data_products_helper.py
+++ b/django_airavata/apps/api/data_products_helper.py
@@ -16,6 +16,7 @@ from airavata.model.data.replica.ttypes import (
from . import datastore, models
logger = logging.getLogger(__name__)
+TMP_INPUT_FILE_UPLOAD_DIR = "tmp"
def save(request, path, file):
@@ -26,6 +27,15 @@ def save(request, path, file):
return data_product
+def save_input_file_upload(request, file):
+ """Save input file in staging area for input file uploads."""
+ username = request.user.username
+ file_name = os.path.basename(file.name)
+ full_path = datastore.save(username, TMP_INPUT_FILE_UPLOAD_DIR, file)
+ data_product = _save_data_product(request, full_path, name=file_name)
+ return data_product
+
+
def open(request, data_product):
"Return file object for replica if it exists in user storage."
path = _get_replica_filepath(data_product)
@@ -124,9 +134,10 @@ def _get_data_product_uri(request, full_path):
return product_uri
-def _save_data_product(request, full_path):
+def _save_data_product(request, full_path, name=None):
"Create, register and record in DB a data product for full_path."
- data_product = _create_data_product(request.user.username, full_path)
+ data_product = _create_data_product(
+ request.user.username, full_path, name=name)
product_uri = request.airavata_client.registerDataProduct(
request.authz_token, data_product)
data_product.productUri = product_uri
@@ -147,11 +158,14 @@ def _delete_data_product(request, full_path):
user_file.delete()
-def _create_data_product(username, full_path):
+def _create_data_product(username, full_path, name=None):
data_product = DataProductModel()
data_product.gatewayId = settings.GATEWAY_ID
data_product.ownerName = username
- file_name = os.path.basename(full_path)
+ if name is not None:
+ file_name = name
+ else:
+ file_name = os.path.basename(full_path)
data_product.productName = file_name
data_product.dataProductType = DataProductType.FILE
data_replica_location = DataReplicaLocationModel()
diff --git a/django_airavata/apps/api/datastore.py b/django_airavata/apps/api/datastore.py
index aab6e8d..124949f 100644
--- a/django_airavata/apps/api/datastore.py
+++ b/django_airavata/apps/api/datastore.py
@@ -29,7 +29,7 @@ def open(username, path):
def save(username, path, file):
- """Save file to username/project name/experiment_name in data store."""
+ """Save file to username/path in data store."""
# file.name may be full path, so get just the name of the file
file_name = os.path.basename(file.name)
user_data_storage = _user_data_storage(username)
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index 9150e7c..6b80b19 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -49,6 +49,7 @@ urlpatterns = [
# url(r'^get-ufiles$', views.get_user_files, name='get_user_files'),
# url(r'^upload-ufiles$', views.upload_user_file, name='upload_user_file'),
# url(r'^delete-ufiles$', views.delete_user_file, name='delete_user_file'),
+ url(r'^upload$', views.upload_input_file, name='upload_input_file'),
url(r'^download', views.download_file, name='download_file'),
url(r'^delete-file$', views.delete_file, name='delete_file'),
url(r'^data-products', views.DataProductView.as_view(),
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index c93df77..819b16b 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -4,7 +4,7 @@ import os
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
-from django.http import FileResponse, Http404, HttpResponse
+from django.http import FileResponse, Http404, HttpResponse, JsonResponse
from django.urls import reverse
from rest_framework import mixins
from rest_framework.decorators import action, detail_route, list_route
@@ -858,6 +858,23 @@ class DataProductView(APIView):
@login_required
+def upload_input_file(request):
+ try:
+ input_file = request.FILES['file']
+ data_product = data_products_helper.save_input_file_upload(
+ request, input_file)
+ serializer = serializers.DataProductSerializer(
+ data_product, context={'request': request})
+ return JsonResponse({'uploaded': True,
+ 'data-product': serializer.data})
+ except Exception as e:
+ log.error("Failed to upload file", exc_info=True)
+ resp = JsonResponse({'uploaded': False, 'error': str(e)})
+ resp.status_code = 500
+ return resp
+
+
+@login_required
def download_file(request):
# TODO check that user has access to this file using sharing API
data_product_uri = request.GET.get('data-product-uri', '')
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue
index 84c1bcd..b37bf2a 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/input-editors/FileInputEditor.vue
@@ -75,24 +75,33 @@ export default {
},
deleteDataProduct() {
utils.FetchUtils.delete(
- "/api/delete-file?data-product-uri=" + encodeURIComponent(this.value)
- ).then(() => {
- this.data = null;
- this.valueChanged();
- });
+ "/api/delete-file?data-product-uri=" + encodeURIComponent(this.value),
+ { ignoreErrors: true }
+ )
+ .then(() => {
+ this.data = null;
+ this.valueChanged();
+ })
+ .catch(err => {
+ // Ignore 404 Not Found errors, file no longer exists so assume was
+ // already deleted
+ if (err.details.status === 404) {
+ this.data = null;
+ this.valueChanged();
+ } else {
+ throw err;
+ }
+ })
+ .catch(err => utils.FetchUtils.reportError);
},
fileChanged() {
if (this.file) {
let data = new FormData();
data.append("file", this.file);
- data.append("project-id", this.experiment.projectId);
- data.append("experiment-name", this.experiment.experimentName);
this.$emit("uploadstart");
- // TODO: use the experimentDataDir off the experiment model as the path
- // to upload to
- utils.FetchUtils.post("/api/user-storage/~/tmp/", data, "", { showSpinner: false })
+ utils.FetchUtils.post("/api/upload", data, "", { showSpinner: false })
.then(result => {
- this.dataProduct = new models.DataProduct(result["uploaded"]);
+ this.dataProduct = new models.DataProduct(result["data-product"]);
this.data = this.dataProduct.productUri;
this.valueChanged();
})