From 3964a0752eb06a7f76e6b94ee94ee5ddb5989a43 Mon Sep 17 00:00:00 2001
From: goei <JsXLRu>
Date: Wed, 7 Oct 2020 13:04:50 +0200
Subject: [PATCH] TMSS-322 Add log_url to SubTasks. Pipeline will have a link
 based on RADBID (so subtask needs at least be scheduled). Observation will
 have a link to cobalt error log based on its subtask id. Also convenient
 function for scheduling_unit_blueprint added

---
 SAS/TMSS/src/tmss/settings.py                 |  6 +++++
 .../src/tmss/tmssapp/models/scheduling.py     | 25 ++++++++++++++++++-
 .../tmss/tmssapp/serializers/scheduling.py    |  2 +-
 .../tmss/tmssapp/viewsets/specification.py    | 15 +++++++++++
 SAS/TMSS/test/t_subtasks.py                   | 15 +++++++++++
 5 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/SAS/TMSS/src/tmss/settings.py b/SAS/TMSS/src/tmss/settings.py
index 3fcb6ea5e99..b98b0d83147 100644
--- a/SAS/TMSS/src/tmss/settings.py
+++ b/SAS/TMSS/src/tmss/settings.py
@@ -337,3 +337,9 @@ 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"
diff --git a/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py b/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
index a3ebd865de7..cdaa1663907 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/scheduling.py
@@ -21,7 +21,8 @@ from lofar.messaging.messagebus import ToBus, DEFAULT_BROKER, DEFAULT_BUSNAME
 from lofar.messaging.messages import EventMessage
 from lofar.sas.tmss.client.tmssbuslistener import DEFAULT_TMSS_SUBTASK_NOTIFICATION_PREFIX
 from lofar.common.util import single_line_with_single_spaces
-
+from django.conf import settings
+from lofar.sas.resourceassignment.resourceassignmentservice.rpc import RADBRPC
 #
 # I/O
 #
@@ -219,6 +220,28 @@ class Subtask(BasicCommon):
             # update the previous state value
             self.__original_state = self.state
 
+    @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
+            with RADBRPC.create() as radbrpc:
+                radb_id = radbrpc.getTask(tmss_id=self.id)
+            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):
     """
     History of state changes on subtasks
diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py b/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py
index 889ecdefb10..8f0515ea5ea 100644
--- a/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py
+++ b/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py
@@ -85,7 +85,7 @@ class SubtaskSerializer(RelationalHyperlinkedModelSerializer):
     class Meta:
         model = models.Subtask
         fields = '__all__'
-        extra_fields = ['cluster_value']
+        extra_fields = ['cluster_value', 'log_url']
 
 
 class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer):
diff --git a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
index ce3fa163142..2e8feb8016a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/viewsets/specification.py
@@ -21,6 +21,7 @@ from drf_yasg.openapi import Parameter
 from lofar.sas.tmss.tmss.tmssapp.viewsets.lofar_viewset import LOFARViewSet, LOFARNestedViewSet, AbstractTemplateViewSet, LOFARCopyViewSet
 from lofar.sas.tmss.tmss.tmssapp import models
 from lofar.sas.tmss.tmss.tmssapp import serializers
+from django.http import JsonResponse
 
 from datetime import datetime
 from lofar.common.json_utils import get_default_json_object_for_schema
@@ -616,6 +617,20 @@ class SchedulingUnitBlueprintViewSet(LOFARViewSet):
         return Response(serializers.SchedulingUnitBlueprintSerializer(scheduling_unit_blueprint, context={'request':request}).data,
                         status=status.HTTP_201_CREATED)
 
+    @swagger_auto_schema(responses={200: 'The available logging urls for all Subtasks of this SchedulingUnitBlueprint.',
+                                    403: 'forbidden'},
+                         operation_description="Get the subtask logging urls of this schedulingunit blueprint.")
+    @action(methods=['get'], detail=True, url_name='get_all_subtasks_log_urls')
+    def get_all_subtasks_log_urls(self, request, pk=None):
+        subtasks = models.Subtask.objects.filter(task_blueprint__scheduling_unit_blueprint_id=pk)
+        result = []
+        for subtask in subtasks:
+            if subtask.log_url != "":
+                result.append({"subtaskid": subtask.id, "type": subtask.specifications_template.type.value, "log_url": subtask.log_url})
+        # TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
+        # result is list of dict so thats why
+        return JsonResponse(result, safe=False)
+
 
 class SchedulingUnitBlueprintNestedViewSet(LOFARNestedViewSet):
     queryset = models.SchedulingUnitBlueprint.objects.all()
diff --git a/SAS/TMSS/test/t_subtasks.py b/SAS/TMSS/test/t_subtasks.py
index ca94d9eb33b..fbadd375fe6 100755
--- a/SAS/TMSS/test/t_subtasks.py
+++ b/SAS/TMSS/test/t_subtasks.py
@@ -325,6 +325,21 @@ class SettingTest(unittest.TestCase):
         with self.assertRaises(SubtaskSchedulingException):
             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
+        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("scu199", subtask_pipeline.log_url)
+        self.assertEqual("", subtask_qa_plots.log_url)
 
 if __name__ == "__main__":
     os.environ['TZ'] = 'UTC'
-- 
GitLab