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 2020/09/22 21:07:34 UTC
[airavata-django-portal] 01/05: AIRAVATA-3346 Use remote API to
launch experiment and get relative data directory
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch AIRAVATA-3346-implement-remote-fs-abstraction-of-user-storage
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
commit 88a3e9b86055d01df484979d190c2cded3c0dff1
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Wed Sep 16 14:22:27 2020 -0400
AIRAVATA-3346 Use remote API to launch experiment and get relative data directory
---
django_airavata/apps/api/serializers.py | 61 ++++++++++++++++++++++++++-------
django_airavata/apps/api/views.py | 45 ++++++++++++++++++------
django_airavata/apps/auth/views.py | 4 +++
3 files changed, 86 insertions(+), 24 deletions(-)
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 5622c65..0ecd926 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -64,6 +64,7 @@ from airavata.model.workspace.ttypes import (
from airavata_django_portal_sdk import user_storage
from . import models, thrift_utils
+import requests
log = logging.getLogger(__name__)
@@ -457,11 +458,26 @@ class ExperimentSerializer(
ResourcePermissionType.WRITE)
def get_relativeExperimentDataDir(self, experiment):
+
if (experiment.userConfigurationData and
experiment.userConfigurationData.experimentDataDir):
request = self.context['request']
data_dir = experiment.userConfigurationData.experimentDataDir
- if user_storage.dir_exists(request, data_dir):
+ if getattr(
+ settings,
+ 'GATEWAY_DATA_STORE_REMOTE_API',
+ None) is not None:
+ # Load the relativeExperimentDataDir from the remote Django
+ # portal instance
+ headers = {
+ 'Authorization': f'Bearer {request.authz_token.accessToken}'}
+ r = requests.get(
+ f'{settings.GATEWAY_DATA_STORE_REMOTE_API}/experiments/{quote(experiment.experimentId)}/',
+ headers=headers,
+ )
+ r.raise_for_status()
+ return r.json()['relativeExperimentDataDir']
+ elif user_storage.dir_exists(request, data_dir):
return user_storage.get_rel_path(request, data_dir)
else:
return None
@@ -673,7 +689,8 @@ class SharedEntitySerializer(serializers.Serializer):
raise Exception("Not implemented")
def update(self, instance, validated_data):
- # Compute lists of ids to grant/revoke READ/WRITE/MANAGE_SHARING permission
+ # Compute lists of ids to grant/revoke READ/WRITE/MANAGE_SHARING
+ # permission
existing_user_permissions = {
user['user'].airavataInternalUserId: user['permissionType']
for user in instance['userPermissions']}
@@ -682,10 +699,15 @@ class SharedEntitySerializer(serializers.Serializer):
user['permissionType']
for user in validated_data['userPermissions']}
- (user_grant_read_permission, user_grant_write_permission, user_grant_manage_sharing_permission,
- user_revoke_read_permission, user_revoke_write_permission, user_revoke_manage_sharing_permission) = \
- self._compute_all_revokes_and_grants(existing_user_permissions,
- new_user_permissions)
+ (
+ user_grant_read_permission,
+ user_grant_write_permission,
+ user_grant_manage_sharing_permission,
+ user_revoke_read_permission,
+ user_revoke_write_permission,
+ user_revoke_manage_sharing_permission) = self._compute_all_revokes_and_grants(
+ existing_user_permissions,
+ new_user_permissions)
existing_group_permissions = {
group['group'].id: group['permissionType']
@@ -694,10 +716,15 @@ class SharedEntitySerializer(serializers.Serializer):
group['group']['id']: group['permissionType']
for group in validated_data['groupPermissions']}
- (group_grant_read_permission, group_grant_write_permission, group_grant_manage_sharing_permission,
- group_revoke_read_permission, group_revoke_write_permission, group_revoke_manage_sharing_permission) = \
- self._compute_all_revokes_and_grants(existing_group_permissions,
- new_group_permissions)
+ (
+ group_grant_read_permission,
+ group_grant_write_permission,
+ group_grant_manage_sharing_permission,
+ group_revoke_read_permission,
+ group_revoke_write_permission,
+ group_revoke_manage_sharing_permission) = self._compute_all_revokes_and_grants(
+ existing_group_permissions,
+ new_group_permissions)
instance['_user_grant_read_permission'] = user_grant_read_permission
instance['_user_grant_write_permission'] = user_grant_write_permission
@@ -749,15 +776,23 @@ class SharedEntitySerializer(serializers.Serializer):
grant_write_permission.append(id)
if ResourcePermissionType.MANAGE_SHARING in grants:
grant_manage_sharing_permission.append(id)
- return (grant_read_permission, grant_write_permission, grant_manage_sharing_permission,
- revoke_read_permission, revoke_write_permission, revoke_manage_sharing_permission)
+ return (
+ grant_read_permission,
+ grant_write_permission,
+ grant_manage_sharing_permission,
+ revoke_read_permission,
+ revoke_write_permission,
+ revoke_manage_sharing_permission)
def _compute_revokes_and_grants(self, current_permission=None,
new_permission=None):
read_permissions = set((ResourcePermissionType.READ,))
write_permissions = set((ResourcePermissionType.READ,
ResourcePermissionType.WRITE))
- manage_share_permissions = set((ResourcePermissionType.READ, ResourcePermissionType.WRITE, ResourcePermissionType.MANAGE_SHARING))
+ manage_share_permissions = set(
+ (ResourcePermissionType.READ,
+ ResourcePermissionType.WRITE,
+ ResourcePermissionType.MANAGE_SHARING))
current_permissions_set = set()
new_permissions_set = set()
if current_permission == ResourcePermissionType.READ:
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 13224ff..90273bb 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -3,18 +3,25 @@ import json
import logging
import os
from datetime import datetime, timedelta
+from urllib.parse import quote
+import requests
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, JsonResponse
from django.urls import reverse
from rest_framework import mixins
-from rest_framework.decorators import action, api_view, detail_route, list_route
+from rest_framework.decorators import (
+ action,
+ api_view,
+ detail_route,
+ list_route
+)
from rest_framework.exceptions import ParseError
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
-from rest_framework.status import HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST
+from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND
from rest_framework.views import APIView
from airavata.model.appcatalog.computeresource.ttypes import (
@@ -278,15 +285,31 @@ class ExperimentViewSet(APIBackedViewSet):
@detail_route(methods=['post'])
def launch(self, request, experiment_id=None):
try:
- experiment = request.airavata_client.getExperiment(
- self.authz_token, experiment_id)
- self._set_storage_id_and_data_dir(experiment)
- self._move_tmp_input_file_uploads_to_data_dir(experiment)
- request.airavata_client.updateExperiment(
- self.authz_token, experiment_id, experiment)
- request.airavata_client.launchExperiment(
- request.authz_token, experiment_id, self.gateway_id)
- return Response({'success': True})
+ if getattr(
+ settings,
+ 'GATEWAY_DATA_STORE_REMOTE_API',
+ None) is not None:
+ # Proxy the launch/ request to the remote Django portal
+ # instance since it must setup the experiment data directory
+ # which is only on the remote Django portal instance
+ headers = {
+ 'Authorization': f'Bearer {request.authz_token.accessToken}'}
+ r = requests.post(
+ f'{settings.GATEWAY_DATA_STORE_REMOTE_API}/experiments/{quote(experiment_id)}/launch/',
+ headers=headers,
+ )
+ r.raise_for_status()
+ return Response(r.json())
+ else:
+ experiment = request.airavata_client.getExperiment(
+ self.authz_token, experiment_id)
+ self._set_storage_id_and_data_dir(experiment)
+ self._move_tmp_input_file_uploads_to_data_dir(experiment)
+ request.airavata_client.updateExperiment(
+ self.authz_token, experiment_id, experiment)
+ request.airavata_client.launchExperiment(
+ request.authz_token, experiment_id, self.gateway_id)
+ return Response({'success': True})
except Exception as e:
return Response({'success': False, 'errorMessage': e.message})
diff --git a/django_airavata/apps/auth/views.py b/django_airavata/apps/auth/views.py
index 568d6a9..d87b031 100644
--- a/django_airavata/apps/auth/views.py
+++ b/django_airavata/apps/auth/views.py
@@ -93,6 +93,10 @@ def handle_login(request):
logger.debug("authenticated user: {}".format(user))
try:
if user is not None:
+ # Middleware will add authz_token attr to request, but since user
+ # just authenticated, authz_token won't be added yet. Login signals
+ # need the authz_token so adding it to the request now.
+ request.authz_token = utils.get_authz_token(request, user=user)
login(request, user)
if login_desktop:
return _create_login_desktop_success_response(request)