Skip to content
Snippets Groups Projects
Commit 5bcb10b7 authored by Jorrit Schaap's avatar Jorrit Schaap
Browse files

TMSS-322: reimplemented this feature. As stated in the ticket: such a...

TMSS-322: reimplemented this feature. As stated in the ticket: such a convenience log_url is not part of the Subtask model, but can be a view on the model. So, implemeted it in the viewset. Now, fetching subtasks from the TMSS db is superfast again.
parent 8c06ccdd
No related branches found
No related tags found
1 merge request!267TMSS-322: reimplemented this feature. As stated in the ticket: such a...
...@@ -156,10 +156,13 @@ class TMSSsession(object): ...@@ -156,10 +156,13 @@ class TMSSsession(object):
return self.get_path_as_json_object("subtask", clauses) return self.get_path_as_json_object("subtask", clauses)
def get_full_url_for_path(self, path: str) -> str:
'''get the full URL for the given path'''
return '%s/%s' % (self.base_url, path.strip('/'))
def get_path_as_json_object(self, path: str, params={}) -> object: def get_path_as_json_object(self, path: str, params={}) -> object:
'''get resource at the given path, interpret it as json, and return it as as native object (usually a dict or a list of dicts)''' '''get resource at the given path, interpret it as json, and return it as as native object (usually a dict or a list of dicts)'''
full_url = '%s/%s' % (self.base_url, path.strip('/')) return self.get_url_as_json_object(self.get_full_url_for_path(path=path), params=params)
return self.get_url_as_json_object(full_url, params=params)
def get_url_as_json_object(self, full_url: str, params={}) -> object: def get_url_as_json_object(self, full_url: str, params={}) -> object:
'''get resource at the given full url (including http://<base_url>, interpret it as json, and return it as as native object (usually a dict or a list of dicts)''' '''get resource at the given full url (including http://<base_url>, interpret it as json, and return it as as native object (usually a dict or a list of dicts)'''
......
...@@ -355,9 +355,3 @@ SWAGGER_SETTINGS = { ...@@ -355,9 +355,3 @@ SWAGGER_SETTINGS = {
}, },
} }
# TODO Do I need distinguish more between Test and Production Environment??
# maybe a local file in Development environment for test purposes
SCU = "http://scu199" if isDevelopmentEnvironment() or isTestEnvironment() else "http://scu001"
PIPELINE_SUBTASK_LOG_URL = SCU + ".control.lofar:7412/tasks/%s/log.html"
OBSERVATION_SUBTASK_LOG_URL = "https://proxy.lofar.eu/inspect/%s/rtcp-%s.errors"
...@@ -250,31 +250,6 @@ class Subtask(BasicCommon): ...@@ -250,31 +250,6 @@ class Subtask(BasicCommon):
# update the previous state value # update the previous state value
self.__original_state_id = self.state_id self.__original_state_id = self.state_id
@property
def log_url(self):
"""
Return the link to the pipeline log in case of pipeline or
link to COBALT error log in case of an observation
otherwise just an empty string
"""
if self.specifications_template.type.value == SubtaskType.Choices.OBSERVATION.value:
url = settings.OBSERVATION_SUBTASK_LOG_URL % (self.id, self.id)
elif self.specifications_template.type.value == SubtaskType.Choices.PIPELINE.value:
# Get RADBID, subtask must be at least 'scheduled' to exist in radb
# If RA is not started don't wait longer than 10 seconds
with RADBRPC.create(timeout=10) as radbrpc:
try:
radb_id = radbrpc.getTask(tmss_id=self.id)
except:
radb_id = None
if radb_id is None:
url = "not available (missing radbid)"
else:
url = settings.PIPELINE_SUBTASK_LOG_URL % radb_id['id']
else:
url = ""
return url
class SubtaskStateLog(BasicCommon): class SubtaskStateLog(BasicCommon):
""" """
......
...@@ -85,7 +85,7 @@ class SubtaskSerializer(RelationalHyperlinkedModelSerializer): ...@@ -85,7 +85,7 @@ class SubtaskSerializer(RelationalHyperlinkedModelSerializer):
class Meta: class Meta:
model = models.Subtask model = models.Subtask
fields = '__all__' fields = '__all__'
extra_fields = ['cluster_value', 'log_url'] extra_fields = ['cluster_value']
class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer): class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer):
......
...@@ -16,9 +16,10 @@ from drf_yasg.utils import swagger_auto_schema ...@@ -16,9 +16,10 @@ from drf_yasg.utils import swagger_auto_schema
from drf_yasg.inspectors import SwaggerAutoSchema from drf_yasg.inspectors import SwaggerAutoSchema
from rest_framework.decorators import action from rest_framework.decorators import action
from django.http import HttpResponse, JsonResponse from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, HttpResponseNotFound
from rest_framework.response import Response as RestResponse from rest_framework.response import Response as RestResponse
from lofar.common import isProductionEnvironment, isTestEnvironment
from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet
from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp import models
from lofar.sas.tmss.tmss.tmssapp import serializers from lofar.sas.tmss.tmss.tmssapp import serializers
...@@ -209,6 +210,49 @@ class SubtaskViewSet(LOFARViewSet): ...@@ -209,6 +210,49 @@ class SubtaskViewSet(LOFARViewSet):
return RestResponse(serializer.data) return RestResponse(serializer.data)
@swagger_auto_schema(responses={302: 'A redirect url to the task log for this Subtask.',
403: 'forbidden'},
operation_description="Get the task log for this Subtask.")
@action(methods=['get'], detail=True)
def task_log(self, request, pk=None):
"""
Return a redirect to the the link to the pipeline log in case of pipeline or
link to COBALT error log in case of an observation.
"""
subtask = get_object_or_404(models.Subtask, pk=pk)
# redirect to cobalt log served at proxy.lofar.eu
if subtask.specifications_template.type.value == models.SubtaskType.Choices.OBSERVATION.value:
url = "https://proxy.lofar.eu/inspect/%s/rtcp-%s.errors" % (subtask.id, subtask.id)
return HttpResponseRedirect(redirect_to=url)
# redirect to pipeline log served via webscheduler
if subtask.specifications_template.type.value == models.SubtaskType.Choices.PIPELINE.value:
# import here and not at top of module to "loosen" dependency on external packages, such as in this case the RADB RPC.
from lofar.sas.resourceassignment.resourceassignmentservice.rpc import RADBRPC
# Get RADBID, subtask must be at least 'scheduled' to exist in radb
try:
with RADBRPC.create(timeout=2) as radbrpc:
radb_id = radbrpc.getTask(tmss_id=subtask.id)
if radb_id is None:
return HttpResponseNotFound(
content='No RADB task found for subtask id=%s type="%s status=%s". Cannot redirect to pipeline log.' % (
subtask.id, subtask.specifications_template.type.value, subtask.state))
WEBSCHEDULER_URL = "http://scu001.control.lofar:7412" if isProductionEnvironment() else \
"http://scu199.control.lofar:7412" if isTestEnvironment() else \
"http://localhost:7412"
url = "%s/tasks/%s/log.html" % (WEBSCHEDULER_URL, radb_id)
return HttpResponseRedirect(redirect_to=url)
except Exception as e:
return HttpResponseNotFound(content='No RADB task found for subtask id=%s type="%s". Cannot redirect to pipeline log.' % (subtask.id, subtask.specifications_template.type.value))
# unknown log
return HttpResponseNotFound(content='No log (url) available for subtask id=%s type="%s"' % (subtask.id, subtask.specifications_template.type.value) )
@swagger_auto_schema(responses={200: 'The input dataproducts of this subtask.', @swagger_auto_schema(responses={200: 'The input dataproducts of this subtask.',
403: 'forbidden'}, 403: 'forbidden'},
operation_description="Get the input dataproducts of this subtask.") operation_description="Get the input dataproducts of this subtask.")
......
...@@ -34,12 +34,7 @@ tmss_test_env.populate_schemas() ...@@ -34,12 +34,7 @@ tmss_test_env.populate_schemas()
from lofar.sas.tmss.test.tmss_test_data_django_models import * from lofar.sas.tmss.test.tmss_test_data_django_models import *
# import and setup rest test data creator
from lofar.sas.tmss.test.tmss_test_data_rest import TMSSRESTTestDataCreator
from lofar.sas.tmss.tmss.tmssapp import models from lofar.sas.tmss.tmss.tmssapp import models
from lofar.sas.tmss.tmss.tmssapp.subtasks import * from lofar.sas.tmss.tmss.tmssapp.subtasks import *
...@@ -347,6 +342,31 @@ class SubtaskInputSelectionFilteringTest(unittest.TestCase): ...@@ -347,6 +342,31 @@ class SubtaskInputSelectionFilteringTest(unittest.TestCase):
selection = {'sap': ['target0'], 'is_relevant': True} selection = {'sap': ['target0'], 'is_relevant': True}
self.assertFalse(specifications_doc_meets_selection_doc(specs, selection)) self.assertFalse(specifications_doc_meets_selection_doc(specs, selection))
def test_links_to_log_files(self):
"""
Test redirect urls to subtask logfiles.
"""
# the link to log files is a 'view' on the subtask, and NOT part of the subtask model.
# the link is served as an action on the REST API, redirecting to externally served log files.
# check/test the redirect urls.
with tmss_test_env.create_tmss_client() as client:
# observation
subtask_observation = create_subtask_object_for_testing("observation", "defined")
response = client.session.get(url=client.get_full_url_for_path('/subtask/%s/task_log' % (subtask_observation.id,)), allow_redirects=False)
self.assertTrue(response.is_redirect)
self.assertIn("proxy.lofar.eu", response.headers['Location'])
self.assertIn("rtcp-%s.errors" % subtask_observation.id, response.headers['Location'])
# pipeline
subtask_pipeline = create_subtask_object_for_testing("pipeline", "defined")
response = client.session.get(url=client.get_full_url_for_path('/subtask/%s/task_log' % (subtask_pipeline.id,)), allow_redirects=False)
self.assertEqual(404, response.status_code) # no log (yet) for unscheduled pipeline
# other (qa_plots)
subtask_qa_plots = create_subtask_object_for_testing("qa_plots", "defined")
self.assertEqual(404, response.status_code) # no log for other subtasktypes
class SettingTest(unittest.TestCase): class SettingTest(unittest.TestCase):
...@@ -359,22 +379,6 @@ class SettingTest(unittest.TestCase): ...@@ -359,22 +379,6 @@ class SettingTest(unittest.TestCase):
with self.assertRaises(SubtaskSchedulingException): with self.assertRaises(SubtaskSchedulingException):
schedule_observation_subtask(obs_st) schedule_observation_subtask(obs_st)
def test_links_to_log_files(self):
"""
Test if the links to logging of a subtasks is correct:
For an observation the subtaskid is in the logging url
For a pipeline the radbid of the subtaskid is in the link, BUT because RA is not started is should
return "not available"
All other subtask types (like qa) should have an empty string (no logging)
"""
subtask_pipeline = create_subtask_object_for_testing("pipeline", "defined")
subtask_qa_plots = create_subtask_object_for_testing("qa_plots", "defined")
subtask_observation = create_subtask_object_for_testing("observation", "defined")
self.assertIn("proxy.lofar.eu", subtask_observation.log_url)
self.assertIn("rtcp-%s.errors" % subtask_observation.id, subtask_observation.log_url)
self.assertIn("not available", subtask_pipeline.log_url)
self.assertEqual("", subtask_qa_plots.log_url)
if __name__ == "__main__": if __name__ == "__main__":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment