Incorrect FTS transfer_link on messages sent by receiver
Motivation
----------

The transfer_link is generated here: 
https://github.com/rucio/rucio/blob/07fb2776928b7b030d570bd1f911d2ce5c43f30a/lib/rucio/transfertool/fts3.py#L396

Which uses external_host as passed into the constructor: 
https://github.com/rucio/rucio/blob/876904d4dab98386cd6e6ea6513d63ab03adae1f/lib/rucio/daemons/conveyor/receiver.py#L83

This field comes from an FTS config file parameter, which may not be initialized the same way as rucio expects it to be. As a result, rucio will generate monitoring links which don't point to a correct fts fqdn. 

Modification
------------
Under normal operation, when we get a notification from FTS about a transfer completion, we know about the transfer and we retrieve it from the database. It doesn't cost us anything to use the request.external_host field from the database, which has the correct format. 

We can ignore the ocurances when it's not the case. It means that we got a notification from FTS about a transfer submitted by rucio, but about which rucio doesn't know anything.... we would have bigger problems to investigate in such case than a wrong monitoring link :D 


diff --git a/lib/rucio/tests/test_conveyor.py b/lib/rucio/tests/test_conveyor.py
index 6017a9756..6dc5698cf 100644
--- a/lib/rucio/tests/test_conveyor.py
+++ b/lib/rucio/tests/test_conveyor.py
@@ -480,6 +480,7 @@ def test_multisource_receiver(vo, did_factory, replica_client, root_account, met
         assert msg_done['payload']['datatype'] == 'RAW'
         assert msg_done['payload']['datasetScope'] == dataset['scope'].external
         assert msg_done['payload']['dataset'] == dataset['name']
+        assert msg_done['payload']['transfer_link'].startswith('https://fts:8449/')
     finally:
         receiver_graceful_stop.set()
         receiver_thread.join(timeout=5)
diff --git a/lib/rucio/transfertool/fts3.py b/lib/rucio/transfertool/fts3.py
index 11a10922b..a9ab264ee 100644
--- a/lib/rucio/transfertool/fts3.py
+++ b/lib/rucio/transfertool/fts3.py
@@ -355,6 +355,7 @@ class Fts3TransferStatusReport(TransferStatusReport):
         # Initialized in child class initialize():
         self._reason = None
         self._src_rse = None
+        self._fts_address = self.external_host
         # Supported db fields bellow:
         self.state = None
         self.external_id = None
@@ -390,7 +391,7 @@ class Fts3TransferStatusReport(TransferStatusReport):
         return fields
 
     def _transfer_link(self):
-        return '%s/fts3/ftsmon/#/job/%s' % (self.external_host.replace('8446', '8449'), self._transfer_id)
+        return '%s/fts3/ftsmon/#/job/%s' % (self._fts_address.replace('8446', '8449'), self._transfer_id)
 
     def _find_attribute_updates(self, request, new_state, reason, overwrite_corrupted_files):
         attributes = None
@@ -511,6 +512,7 @@ class FTS3CompletionMessageTransferStatusReport(Fts3TransferStatusReport):
 
                 self._reason = reason
                 self._src_rse = src_rse_name
+                self._fts_address = request['external_host'] or self._fts_address
 
                 self.state = new_state
                 self.external_id = transfer_id
['lib/rucio/transfertool/fts3.py', 'lib/rucio/tests/test_conveyor.py']