diff --git a/SAS/TriggerEmailService/Server/lib/TriggerEmailService.py b/SAS/TriggerEmailService/Server/lib/TriggerEmailService.py index 856c2a4e31234c4c2540a7ef740ce1ae84e6a220..faa539ca1abaa93a0ffe0f3dcec47d1862ae29cb 100644 --- a/SAS/TriggerEmailService/Server/lib/TriggerEmailService.py +++ b/SAS/TriggerEmailService/Server/lib/TriggerEmailService.py @@ -239,18 +239,30 @@ class TriggerNotificationListener(AbstractBusListener): start_times = doc.getroot().findall('specification/activity/observation/timeWindowSpecification/startTime') - start_time = datetime.strptime(start_times[0].text, '%Y-%m-%dT%H:%M:%S') + if start_times: # Not dwelling + start_time = datetime.strptime(start_times[0].text, '%Y-%m-%dT%H:%M:%S') - durations = doc.getroot().findall( - 'specification/activity/observation/timeWindowSpecification/duration/duration') + durations = doc.getroot().findall( + 'specification/activity/observation/timeWindowSpecification/duration/duration') - duration = durations[0].text + duration = durations[0].text - duration_seconds = self._iso8601_duration_as_seconds(duration) + duration_seconds = self._iso8601_duration_as_seconds(duration) - stop_time = start_time + timedelta(seconds=duration_seconds) + stop_time = start_time + timedelta(seconds=duration_seconds) + + return start_time, stop_time + else: # Dwelling + min_start_times = doc.getroot().findall('specification/activity/observation/timeWindowSpecification/minStartTime') + + min_start_time = datetime.strptime(min_start_times[0].text, '%Y-%m-%dT%H:%M:%S') + + max_end_times = doc.getroot().findall('specification/activity/observation/timeWindowSpecification/maxEndTime') + + max_end_time = datetime.strptime(max_end_times[0].text, '%Y-%m-%dT%H:%M:%S') + + return min_start_time, max_end_time - return start_time, stop_time def start_listening(self, **kwargs): self.mom_rpc_client.open() diff --git a/SAS/TriggerEmailService/Server/test/t_TriggerEmailService.py b/SAS/TriggerEmailService/Server/test/t_TriggerEmailService.py index 4ed760e16074d6cc5ffeb9a62ddd3346c0a9604c..6be1eaa3912a9cb28167c5e81409da811f5a2a85 100755 --- a/SAS/TriggerEmailService/Server/test/t_TriggerEmailService.py +++ b/SAS/TriggerEmailService/Server/test/t_TriggerEmailService.py @@ -294,6 +294,9 @@ class TestTriggerNotificationListener(unittest.TestCase): obs_mom_id = 44 start_time = "2016-11-23 15:21:44" stop_time = "2016-11-23 16:21:44" + min_start_time = "2017-05-23 15:21:44" + max_end_time = "2017-05-23 17:21:44" + xml = """<?xml version="1.0" encoding="UTF-8"?> <trigger:trigger xsi:schemaLocation="http://www.astron.nl/LofarTrigger LofarTrigger.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spec="http://www.astron.nl/LofarSpecification" @@ -425,7 +428,522 @@ class TestTriggerNotificationListener(unittest.TestCase): </stationSelectionSpecification> <timeWindowSpecification> <timeFrame>UT</timeFrame> - <startTime>2016-11-23T15:21:44</startTime> + <startTime>2016-11-23T15:21:44</startTime> + <duration> + <duration>PT3600S</duration> + </duration> + </timeWindowSpecification> + </observation> + <status>approved</status> + <qualityOfService>LATENCY</qualityOfService> + <priority>10</priority> + <triggerId> + <source>0</source> + <identifier>0</identifier> + </triggerId> + </activity> + + <!-- SAP 0 --> + <activity> + <temporaryIdentifier> + <source>0</source> + <identifier>300</identifier> + <description>0</description> + </temporaryIdentifier> + <measurement xsi:type="base:BeamMeasurement"> + <name>Target</name> + <description>Target</description> + <ra>204.648425</ra> + <dec>-0.172222222222</dec> + <equinox>J2000</equinox> + <subbandsSpecification> + <subbands>160..399</subbands> + </subbandsSpecification> + <measurementType>Target</measurementType> + </measurement> + + <status>approved</status> + <qualityOfService>LATENCY</qualityOfService> + <priority>10</priority> + <triggerId> + <source>0</source> + <identifier>0</identifier> + </triggerId> + </activity> + + <!-- SAP 1 --> + <activity> + <temporaryIdentifier> + <source>0</source> + <identifier>301</identifier> + <description>0</description> + </temporaryIdentifier> + <measurement xsi:type="base:BeamMeasurement"> + <name>Calibrator</name> + <description>Calibrator</description> + <ra>123.400291667</ra> + <dec>48.2173833333</dec> + <equinox>J2000</equinox> + <subbandsSpecification> + <subbands>160..339</subbands> + </subbandsSpecification> + <measurementType>Calibration</measurementType> + </measurement> + + <status>approved</status> + <qualityOfService>LATENCY</qualityOfService> + <priority>10</priority> + <triggerId> + <source>0</source> + <identifier>0</identifier> + </triggerId> + </activity> + + <!-- Calibrator Averaging Pipeline --> + <activity> + <temporaryIdentifier> + <source>0</source> + <identifier>201</identifier> + <description>0</description> + </temporaryIdentifier> + <pipeline xsi:type="base:AveragingPipeline"> + <name>Calibrator/1/CPT</name> + <description>Calibrator/1/CPT (Preprocessing)</description> + <processingCluster> + <name>CEP4</name> + <partition>cpu</partition> + <numberOfTasks>24</numberOfTasks> + <minRAMPerTask unit="byte">1000000000</minRAMPerTask> + <minScratchPerTask unit="byte">100000000</minScratchPerTask> + <maxDurationPerTask>PT600S</maxDurationPerTask> + <numberOfCoresPerTask>20</numberOfCoresPerTask> + <runSimultaneous>true</runSimultaneous> + </processingCluster> + <defaultTemplate>Preprocessing Pipeline</defaultTemplate> + <demixingParameters> + <averagingFreqStep>16</averagingFreqStep> + <averagingTimeStep>1</averagingTimeStep> + <demixFreqStep>16</demixFreqStep> + <demixTimeStep>5</demixTimeStep> + <demixAlways /> + <demixIfNeeded /> + <ignoreTarget>false</ignoreTarget> + </demixingParameters> + <flaggingStrategy>LBAdefault</flaggingStrategy> + </pipeline> + <status>approved</status> + <qualityOfService>LATENCY</qualityOfService> + <priority>10</priority> + <triggerId> + <source>0</source> + <identifier>0</identifier> + </triggerId> + </activity> + + <!-- Target Averaging Pipeline --> + <activity> + <temporaryIdentifier> + <source>0</source> + <identifier>202</identifier> + <description>0</description> + </temporaryIdentifier> + <pipeline xsi:type="base:AveragingPipeline"> + <name>Calibrator/1/CPT</name> + <description>Calibrator/1/CPT (Preprocessing)</description> + <processingCluster> + <name>CEP4</name> + <partition>cpu</partition> + <numberOfTasks>24</numberOfTasks> + <minRAMPerTask unit="byte">1000000000</minRAMPerTask> + <minScratchPerTask unit="byte">100000000</minScratchPerTask> + <maxDurationPerTask>PT600S</maxDurationPerTask> + <numberOfCoresPerTask>20</numberOfCoresPerTask> + <runSimultaneous>true</runSimultaneous> + </processingCluster> + <defaultTemplate>Preprocessing Pipeline</defaultTemplate> + <demixingParameters> + <averagingFreqStep>16</averagingFreqStep> + <averagingTimeStep>1</averagingTimeStep> + <demixFreqStep>16</demixFreqStep> + <demixTimeStep>5</demixTimeStep> + <demixAlways /> + <demixIfNeeded /> + <ignoreTarget>false</ignoreTarget> + </demixingParameters> + <flaggingStrategy>LBAdefault</flaggingStrategy> + </pipeline> + <status>approved</status> + <qualityOfService>LATENCY</qualityOfService> + <priority>10</priority> + <triggerId> + <source>0</source> + <identifier>0</identifier> + </triggerId> + </activity> + + <!-- SAP 0 data products --> + <entity> + <temporaryIdentifier> + <source>0</source> + <identifier>400</identifier> + </temporaryIdentifier> + <dataproductType>UVDataProduct</dataproductType> + <storageCluster> + + <name>CEP4</name> + <partition>/data/projects/</partition> + </storageCluster> + </entity> + + <!-- SAP 1 data products --> + <entity> + <temporaryIdentifier> + <source>0</source> + <identifier>401</identifier> + </temporaryIdentifier> + <dataproductType>UVDataProduct</dataproductType> + <storageCluster> + <name>CEP4</name> + <partition>/data/projects/</partition> + </storageCluster> + </entity> + + <!-- Calibrator Pipeline dataproducts --> + <entity> + <temporaryIdentifier> + <source>0</source> + <identifier>402</identifier> + </temporaryIdentifier> + <dataproductType>UVDataProduct</dataproductType> + <storageCluster> + <name>CEP4</name> + <partition>/data/projects/</partition> + </storageCluster> + </entity> + + <!-- Target Pipeline dataproducts --> + <entity> + <temporaryIdentifier> + <source>0</source> + <identifier>403</identifier> + </temporaryIdentifier> + <dataproductType>UVDataProduct</dataproductType> + <storageCluster> + <name>CEP4</name> + <partition>/data/projects/</partition> + </storageCluster> + </entity> + + <!-- folder 101 is child of folder 100 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>100</identifier> + </parent> + <child> + <source>0</source> + <identifier>101</identifier> + </child> + <type>folder-folder</type> + </relation> + + <!-- observation 200 is child of folder 101 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>101</identifier> + </parent> + <child> + <source>0</source> + <identifier>200</identifier> + </child> + <type>folder-activity</type> + </relation> + + <!-- measurements 300 is a child of observation 200 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>200</identifier> + </parent> + <child> + <source>0</source> + <identifier>300</identifier> + </child> + <type>observation-measurement</type> + </relation> + + <!-- measurement 301 is a child of observation 200 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>200</identifier> + <description>0</description> + </parent> + <child> + <source>0</source> + <identifier>301</identifier> + <description>0</description> + </child> + <type>observation-measurement</type> + </relation> + + <!-- dataproducts 400 are output of measurement 300 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>400</identifier> + </entity> + <activity> + <source>0</source> + <identifier>300</identifier> + </activity> + <type>producer</type> + </relation> + + <!-- dataproducts 401 are output of measurement 301 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>401</identifier> + </entity> + <activity> + <source>0</source> + <identifier>301</identifier> + </activity> + <type>producer</type> + </relation> + + + <!-- SAP 1 is the calibrator for SAP 0 --> + <relation xsi:type="spec:TwinRelation"> + <first> + <source>0</source> + <identifier>301</identifier> + </first> + <second> + <source>0</source> + <identifier>300</identifier> + </second> + <type>calibrator-target</type> + </relation> + + + <!-- dataproducts 401 are input for pipeline 201 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>401</identifier> + </entity> + <activity> + <source>0</source> + <identifier>201</identifier> + </activity> + <type>user</type> + </relation> + + <!-- dataproducts 402 are output of pipeline 201 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>402</identifier> + </entity> + <activity> + <source>0</source> + <identifier>201</identifier> + </activity> + <type>producer</type> + </relation> + + <!-- pipeline 201 is child of folder 101 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>101</identifier> + </parent> + <child> + <source>0</source> + <identifier>201</identifier> + </child> + <type>folder-activity</type> + </relation> + + <!-- dataproducts 400 are input for pipeline 202 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>400</identifier> + </entity> + <activity> + <source>0</source> + <identifier>202</identifier> + </activity> + <type>user</type> + </relation> + + <!-- pipeline 202 is child of folder 101 --> + <relation xsi:type="spec:ChildRelation"> + <parent> + <source>0</source> + <identifier>101</identifier> + </parent> + <child> + <source>0</source> + <identifier>202</identifier> + </child> + <type>folder-activity</type> + </relation> + + <!-- dataproducts 403 are output of pipeline 202 --> + <relation xsi:type="spec:ActivityEntityRelation"> + <entity> + <source>0</source> + <identifier>403</identifier> + </entity> + <activity> + <source>0</source> + <identifier>202</identifier> + </activity> + <type>producer</type> + </relation> + </specification> + <generatorName>Jan David Mol</generatorName> + <generatorVersion>0.0</generatorVersion> +</trigger:trigger> +""" + xml_dwell = """<?xml version="1.0" encoding="UTF-8"?> +<trigger:trigger xsi:schemaLocation="http://www.astron.nl/LofarTrigger LofarTrigger.xsd" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:spec="http://www.astron.nl/LofarSpecification" + xmlns:trigger="http://www.astron.nl/LofarTrigger" xmlns:base="http://www.astron.nl/LofarBase"> + <version>version</version> + <name>name</name> + <description>description</description> + <projectReference> + <ProjectCode>test-lofar</ProjectCode> + </projectReference> + <contactInformation> + <name>Sander ter Veen</name> + <email>veen@astron.nl</email> + <phoneNumber>711</phoneNumber> + <affiliation>ASTRON</affiliation> + </contactInformation> + <userName>veen</userName> + <comment>comment</comment> + <event> + <identification>none</identification> + <description>none</description> + <type>VOEvent</type> + </event> + <specification> + <version>2.20</version> + <projectReference> + <ProjectCode>test-lofar</ProjectCode> + </projectReference> + <userName>veen</userName> + <comment>comment</comment> + <generatorName>Jan David Mol</generatorName> + <generatorVersion>0.0</generatorVersion> + + <!-- folders --> + <container> + <temporaryIdentifier> + <source>0</source> + <identifier>100</identifier> + </temporaryIdentifier> + <addToExistingContainer>false</addToExistingContainer> + <folder> + <name>TARGET_A</name> + <description>First target</description> + <topology>0</topology> + </folder> + </container> + <container> + <temporaryIdentifier> + <source>0</source> + <identifier>101</identifier> + </temporaryIdentifier> + <addToExistingContainer>false</addToExistingContainer> + <folder> + <name>AARTFAAC-TRIGGERED</name> + <description>Triggered observation by AARTFAAC (Preprocessing)</description> + <topology>0</topology> + </folder> + </container> + + <!-- observation --> + <activity> + <temporaryIdentifier> + <source>0</source> + <identifier>200</identifier> + <description>0</description> + </temporaryIdentifier> + <observation> + <name>Target/1/TO</name> + <description>Target/1/TO (Target Observation)</description> + <instrument>Beam Observation</instrument> + <defaultTemplate>BeamObservation</defaultTemplate> + <tbbPiggybackAllowed>true</tbbPiggybackAllowed> + <aartfaacPiggybackAllowed>true</aartfaacPiggybackAllowed> + <correlatedData>true</correlatedData> + <coherentStokesData>false</coherentStokesData> + <incoherentStokesData>false</incoherentStokesData> + <antenna>LBA Outer</antenna> + <clock units="MHz">200</clock> + <instrumentFilter>30-90 MHz</instrumentFilter> + <integrationInterval>2.0</integrationInterval> + <channelsPerSubband>64</channelsPerSubband> + <bypassPff>false</bypassPff> + <enableSuperterp>false</enableSuperterp> + <numberOfBitsPerSample>8</numberOfBitsPerSample> + <stationSelectionSpecification> + <stationSelection> + <stationSet>Custom</stationSet> + <stations> + <station><name>CS001</name></station> + <station><name>CS002</name></station> + <station><name>CS003</name></station> + <station><name>CS004</name></station> + <station><name>CS005</name></station> + <station><name>CS006</name></station> + <station><name>CS007</name></station> + <station><name>CS011</name></station> + <station><name>CS013</name></station> + <station><name>CS017</name></station> + <station><name>CS021</name></station> + <station><name>CS024</name></station> + <station><name>CS026</name></station> + <station><name>CS028</name></station> + <station><name>CS030</name></station> + <station><name>CS031</name></station> + <station><name>CS032</name></station> + <station><name>CS101</name></station> + <station><name>CS103</name></station> + <station><name>CS201</name></station> + <station><name>CS301</name></station> + <station><name>CS302</name></station> + <station><name>CS401</name></station> + <station><name>CS501</name></station> + <station><name>RS106</name></station> + <station><name>RS205</name></station> + <station><name>RS208</name></station> + <station><name>RS210</name></station> + <station><name>RS305</name></station> + <station><name>RS306</name></station> + <station><name>RS307</name></station> + <station><name>RS310</name></station> + <station><name>RS406</name></station> + <station><name>RS407</name></station> + <station><name>RS409</name></station> + <station><name>RS503</name></station> + <station><name>RS508</name></station> + <station><name>RS509</name></station> + </stations> + </stationSelection> + </stationSelectionSpecification> + <timeWindowSpecification> + <timeFrame>UT</timeFrame> + <minStartTime>2017-05-23T15:21:44</minStartTime> + <maxEndTime>2017-05-23T17:21:44</maxEndTime> <duration> <duration>PT3600S</duration> </duration> @@ -511,7 +1029,7 @@ class TestTriggerNotificationListener(unittest.TestCase): <partition>cpu</partition> <numberOfTasks>24</numberOfTasks> <minRAMPerTask unit="byte">1000000000</minRAMPerTask> - <minScratchPerTask unit="byte">100000000</minScratchPerTask> + <minScratchPerTask unit="byte">100000000</minScratchPerTask> <maxDurationPerTask>PT600S</maxDurationPerTask> <numberOfCoresPerTask>20</numberOfCoresPerTask> <runSimultaneous>true</runSimultaneous> @@ -552,7 +1070,7 @@ class TestTriggerNotificationListener(unittest.TestCase): <partition>cpu</partition> <numberOfTasks>24</numberOfTasks> <minRAMPerTask unit="byte">1000000000</minRAMPerTask> - <minScratchPerTask unit="byte">100000000</minScratchPerTask> + <minScratchPerTask unit="byte">100000000</minScratchPerTask> <maxDurationPerTask>PT600S</maxDurationPerTask> <numberOfCoresPerTask>20</numberOfCoresPerTask> <runSimultaneous>true</runSimultaneous> @@ -815,6 +1333,13 @@ class TestTriggerNotificationListener(unittest.TestCase): "metadata": xml } + dwell_message_content = { + "trigger_id": trigger_id, + "project": project_name, + "metadata": xml_dwell + } + + def setUp(self): self.momqueryrpc_mock = mock.MagicMock() self.momqueryrpc_mock.getProjects.return_value = [{"name": self.project_name, "mom2id": self.project_mom_id}] @@ -829,6 +1354,9 @@ class TestTriggerNotificationListener(unittest.TestCase): self.message = mock.MagicMock() self.message.content = self.message_content + self.dwell_message = mock.MagicMock() + self.dwell_message.content = self.dwell_message_content + @mock.patch('lofar.messaging.messagebus.AbstractBusListener.start_listening') def test_start_listening_should_open_momquery_rpc(self, super_mock): listener = TriggerNotificationListener(self.momqueryrpc_mock) @@ -872,6 +1400,16 @@ class TestTriggerNotificationListener(unittest.TestCase): self.assertIn(str(self.start_time), self.email_mock.call_args[0][2]) self.assertIn(str(self.stop_time), self.email_mock.call_args[0][2]) + def test_handleMessage_should_set_correct_body_for_dwell_spec(self): + listener = TriggerNotificationListener(self.momqueryrpc_mock) + + listener._handleMessage(self.dwell_message) + + self.assertIn(str(self.trigger_id), self.email_mock.call_args[0][2]) + self.assertIn(self.project_name, self.email_mock.call_args[0][2]) + self.assertIn(str(self.min_start_time), self.email_mock.call_args[0][2]) + self.assertIn(str(self.max_end_time), self.email_mock.call_args[0][2]) + if __name__ == "__main__": unittest.main()