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();
           })