anon-iclr-submission/benchname-bug-localization huggingface dataset:
Repository: rucio/rucio
Issue: Globus transfers not being handled properly by MONIT

Motivation
----------

The protocol is not properly extracted, see:
https://monit-grafana.cern.ch/dashboard/snapshot/en9K4Tc2vSpD54ToTLr5pydfei1GSAil

Modification
------------

Not sure whether something to address on our side or MONIT’s.

Changed files:
lib/rucio/transfertool/globus.py, lib/rucio/core/request.py

diff --git a/lib/rucio/core/request.py b/lib/rucio/core/request.py
index 7a9767237..7485d1ee7 100644
--- a/lib/rucio/core/request.py
+++ b/lib/rucio/core/request.py
@@ -1571,8 +1571,12 @@ def add_monitor_message(new_state, request, additional_fields, session=None):
 
     if message['started_at'] and message['transferred_at']:
         message['duration'] = (message['transferred_at'] - message['started_at']).seconds
-    if message['dst-url']:
-        message['protocol'] = message['dst-url'].split(':')[0]
+    if not message.get('protocol'):
+        dst_url = message['dst-url']
+        if dst_url and ':' in dst_url:
+            message['protocol'] = dst_url.split(':')[0]
+        elif request.get('transfertool'):
+            message['protocol'] = request['transfertool']
     if not message.get('src-rse'):
         src_rse_id = request.get('source_rse_id', None)
         if src_rse_id:
diff --git a/lib/rucio/transfertool/globus.py b/lib/rucio/transfertool/globus.py
index 19248e8e8..4b0a2865b 100644
--- a/lib/rucio/transfertool/globus.py
+++ b/lib/rucio/transfertool/globus.py
@@ -80,7 +80,7 @@ class GlobusTransferStatusReport(TransferStatusReport):
         pass
 
     def get_monitor_msg_fields(self, session, logger=logging.log):
-        return {}
+        return {'protocol': 'globus'}
 
 
 class GlobusTransferTool(Transfertool):
Repository: rucio/rucio
Issue: Deprecation message in Paramiko

Motivation
----------
Paramiko outputs a deprecation message due to an outdated security algorithm. We do not depend on that algorithm.
https://github.com/paramiko/paramiko/pull/2039

Modification
------------
The paramiko team is aware of the problem. They opened a PR to fix it.



Changed files:
lib/rucio/common/extra.py

diff --git a/lib/rucio/common/extra.py b/lib/rucio/common/extra.py
index 45dc344fc..dd8010d47 100644
--- a/lib/rucio/common/extra.py
+++ b/lib/rucio/common/extra.py
@@ -17,6 +17,7 @@
 # - Benedikt Ziemons <benedikt.ziemons@cern.ch>, 2021
 
 import importlib
+import warnings
 
 
 def import_extras(module_list):
@@ -24,7 +25,12 @@ def import_extras(module_list):
     for mod in module_list:
         out[mod] = None
         try:
-            out[mod] = importlib.import_module(mod)
+            with warnings.catch_warnings():
+                # TODO: remove when https://github.com/paramiko/paramiko/issues/2038 is fixed
+                warnings.filterwarnings('ignore', 'Blowfish has been deprecated', module='paramiko')
+                # TODO: deprecated python 2 and 3.6 too ...
+                warnings.filterwarnings('ignore', 'Python .* is no longer supported', module='paramiko')
+                out[mod] = importlib.import_module(mod)
         except ImportError:
             pass
     return out
Repository: rucio/rucio
Issue: reaper busy-looping over rses with greedyDeletion even if nothing to delete

Motivation
----------
A recent change in reaper reworked the greedy_deletion workflow. This resulted in a regression due to this line:
https://github.com/rucio/rucio/blob/c7636d249397c4ad6ab7019d4ed1ca585d7cfaa1/lib/rucio/daemons/reaper/reaper.py#L585

Reaper is never sleeeping for greedyDeletion rses.




Changed files:
lib/rucio/daemons/reaper/reaper.py

diff --git a/lib/rucio/daemons/reaper/reaper.py b/lib/rucio/daemons/reaper/reaper.py
index 14ef4b8e3..33b5240a9 100644
--- a/lib/rucio/daemons/reaper/reaper.py
+++ b/lib/rucio/daemons/reaper/reaper.py
@@ -582,7 +582,7 @@ def _run_once(rses_to_process, chunk_size, greedy, scheme,
                                                                              only_delete_obsolete=only_delete_obsolete,
                                                                              session=None)
             logger(logging.DEBUG, 'list_and_mark_unlocked_replicas on %s for %s bytes in %s seconds: %s replicas', rse.name, needed_free_space, time.time() - del_start_time, len(replicas))
-            if not enable_greedy and len(replicas) < chunk_size:
+            if (len(replicas) == 0 and enable_greedy) or (len(replicas) < chunk_size and not enable_greedy):
                 logger(logging.DEBUG, 'Not enough replicas to delete on %s (%s requested vs %s returned). Will skip any new attempts on this RSE until next cycle', rse.name, chunk_size, len(replicas))
                 REGION.set('pause_deletion_%s' % rse.id, True)
                 work_remaining_by_rse[rse] = False
Repository: rucio/rucio
Issue: tracer-kronos too verbose at INFO level

Motivation
----------

It outputs tens of millions of messages per day. Most of them with the following useless content: 
```
2022-05-16 13:59:17,294	root	1	INFO	kronos-file[1/4] updated 1 replica(s)
```

Modification
------------
Substitute this message with a counter.



Changed files:
lib/rucio/daemons/tracer/kronos.py

diff --git a/lib/rucio/daemons/tracer/kronos.py b/lib/rucio/daemons/tracer/kronos.py
index 391a19330..0da10c9b0 100644
--- a/lib/rucio/daemons/tracer/kronos.py
+++ b/lib/rucio/daemons/tracer/kronos.py
@@ -294,7 +294,8 @@ class AMQConsumer(object):
             self.__logger(logging.ERROR, "Cannot update replicas.", exc_info=True)
             record_counter('daemons.tracer.kronos.update_error')
 
-        self.__logger(logging.INFO, 'updated %d replica(s)' % len(replicas))
+        record_counter('daemons.tracer.kronos.updated_replicas')
+        self.__logger(logging.DEBUG, 'updated %d replica(s)' % len(replicas))
 
 
 def kronos_file(thread=0, dataset_queue=None, sleep_time=60):
Repository: rucio/rucio
Issue: receiver incorrectly handles multi-source transfers

Motivation
----------

In case of multi-source transfers, receiver analyzes the message even if the job didn't yet finish:
https://github.com/rucio/rucio/blob/8acc9c9b873eef1d7e3b081821665ee03b95f4a0/lib/rucio/daemons/conveyor/receiver.py#L93

If the the message concerns one failed source, this results in a transition of the transfer to a failed state :  
https://github.com/rucio/rucio/blob/8acc9c9b873eef1d7e3b081821665ee03b95f4a0/lib/rucio/transfertool/fts3.py#L523

One may be miss-leaded, me included until now, that the `t_final_transfer_state` field is related to the job_state, but it  doesn't seem to be the case on FTS side. It depends on the file_state and the job state may not yet be final: 
https://gitlab.cern.ch/fts/fts3/-/blob/a34b78420e7f06aebca4f468e39312189e9e1454/src/url-copy/LegacyReporter.cpp#L214

This means that the receiver may transition the file to a failed state even if the job is not yet completed. 




Changed files:
lib/rucio/daemons/conveyor/receiver.py

diff --git a/lib/rucio/daemons/conveyor/receiver.py b/lib/rucio/daemons/conveyor/receiver.py
index 842b1fc00..fc10b55ce 100644
--- a/lib/rucio/daemons/conveyor/receiver.py
+++ b/lib/rucio/daemons/conveyor/receiver.py
@@ -73,9 +73,7 @@ class Receiver(object):
            and 'issuer' in msg['job_metadata'].keys() \\
            and str(msg['job_metadata']['issuer']) == str('rucio'):
 
-            if 'job_state' in msg.keys() and (
-                    str(msg['job_state']) != str('ACTIVE')
-                    or str(msg['job_state']) == str('ACTIVE') and 'job_m_replica' in msg.keys() and (str(msg['job_m_replica']).lower() == str('true'))):
+            if 'job_state' in msg.keys() and str(msg['job_state']) != str('ACTIVE'):
                 record_counter('daemons.conveyor.receiver.message_rucio')
 
                 self._perform_request_update(msg)
Repository: rucio/rucio
Issue: Query not properly executed

Motivation
----------

While reviewing #5340, I noticed that there’s a query execution that doesn’t look right (the query is not stored in `stmt`).

https://github.com/rucio/rucio/blob/35d7ce449cfcfb895d19b0ea8d4b77065ce8eb19/lib/rucio/core/replica.py#L2136-L2146

Side note: there’s room for improvement in the coding style.

Modification
------------




Changed files:
lib/rucio/core/replica.py

diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
index 9647a1974..7d470d081 100644
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -2116,7 +2116,7 @@ def __delete_replicas_without_temp_tables(rse_id, files, ignore_availability=Tru
         rowcount += result.rowcount
 
     for chunk in chunks(bad_replica_condition, 10):
-        update(models.BadReplicas).\\
+        stmt = update(models.BadReplicas).\\
             where(models.BadReplicas.rse_id == rse_id). \\
             where(or_(*chunk)). \\
             where(models.BadReplicas.state == BadFilesStatus.BAD) .\\
@@ -2126,7 +2126,7 @@ def __delete_replicas_without_temp_tables(rse_id, files, ignore_availability=Tru
                 updated_at=datetime.utcnow()
         )
 
-        result = session.execute(stmt)
+        session.execute(stmt)
 
     if rowcount != len(files):
         raise exception.ReplicaNotFound("One or several replicas don't exist.")
Repository: rucio/rucio
Issue: Tracer Kronos extremely verbose

Motivation
----------
In atlas we collected 80 million logs from kronos in last 24 hours. This is more than all other daemons combined. 
Many of those logs are completely useless as they state 
```
kronos-file[3/4] got a resubmitted report
```
or
```
kronos-file[3/4] hit locked row, resubmitted to queue
```

Having a prometheus counter would be enough. 

Modification
------------
Reduce the verbosity in logs. 



Changed files:
lib/rucio/daemons/tracer/kronos.py

diff --git a/lib/rucio/daemons/tracer/kronos.py b/lib/rucio/daemons/tracer/kronos.py
index 0da10c9b0..758ff6b6e 100644
--- a/lib/rucio/daemons/tracer/kronos.py
+++ b/lib/rucio/daemons/tracer/kronos.py
@@ -88,7 +88,6 @@ class AMQConsumer(object):
 
         if 'resubmitted' in frame.headers:
             record_counter('daemons.tracer.kronos.received_resubmitted')
-            self.__logger(logging.WARNING, 'got a resubmitted report')
 
         try:
             if appversion == 'dq2':
@@ -288,14 +287,12 @@ class AMQConsumer(object):
                         resubmit['vo'] = replica['scope'].vo
                     self.__conn.send(body=jdumps(resubmit), destination=self.__queue, headers={'appversion': 'rucio', 'resubmitted': '1'})
                     record_counter('daemons.tracer.kronos.sent_resubmitted')
-                    self.__logger(logging.WARNING, 'hit locked row, resubmitted to queue')
             record_timer('daemons.tracer.kronos.update_atime', (time() - start_time) * 1000)
         except Exception:
             self.__logger(logging.ERROR, "Cannot update replicas.", exc_info=True)
             record_counter('daemons.tracer.kronos.update_error')
 
         record_counter('daemons.tracer.kronos.updated_replicas')
-        self.__logger(logging.DEBUG, 'updated %d replica(s)' % len(replicas))
 
 
 def kronos_file(thread=0, dataset_queue=None, sleep_time=60):
Repository: rucio/rucio
Issue: config_get_list incorrectly handles empty strings

Motivation
----------
it returns `['']` rather than an empty list



Changed files:
lib/rucio/common/config.py

diff --git a/lib/rucio/common/config.py b/lib/rucio/common/config.py
index 9a229ec6c..b24cd4afd 100644
--- a/lib/rucio/common/config.py
+++ b/lib/rucio/common/config.py
@@ -289,6 +289,8 @@ def __convert_string_to_list(string):
 
     :returns: A list extracted from the string.
     """
+    if not string or not string.strip():
+        return []
     string = string.split(',')
     return [item.strip(' ') for item in string]
Repository: rucio/rucio
Issue: Rucio breaks DIRAC run

Motivation
----------
After the 1.27.0rc1 release, the DIRAC runs are throwing an error produced by Rucio. The cause is a missing `rucio.cfg` file. The `is_client` function thus throws the following error:
```
2021-11-25T05:03:46.4056355Z �[1m�[31mE               RuntimeError: Could not load Rucio configuration file. Rucio looked in the following paths for a configuration file, in order:�[0m
2021-11-25T05:03:46.4057329Z �[1m�[31mE               	/opt/rucio/etc/rucio.cfg�[0m
```

https://github.com/rucio/rucio/blob/b820877f58c975740d9ea1fd448c3dcf2eb013cf/lib/rucio/common/utils.py#L1560-L1579


Issue: DIRACGrid/DIRAC#5637

Modification
------------
@bari12 suggested that the `is_client` function should return `True` in case of a missing configuration file.

Changed files:
lib/rucio/common/utils.py

diff --git a/lib/rucio/common/utils.py b/lib/rucio/common/utils.py
index ce254ea12..06fef1841 100644
--- a/lib/rucio/common/utils.py
+++ b/lib/rucio/common/utils.py
@@ -1564,12 +1564,16 @@ def is_client():
     :returns client_mode: True if is called from a client, False if it is called from a server/daemon
     """
     if 'RUCIO_CLIENT_MODE' not in os.environ:
-        if config_has_section('database'):
-            client_mode = False
-        elif config_has_section('client'):
+        try:
+            if config_has_section('database'):
+                client_mode = False
+            elif config_has_section('client'):
+                client_mode = True
+            else:
+                client_mode = False
+        except RuntimeError:
+            # If no configuration file is found the default value should be True
             client_mode = True
-        else:
-            client_mode = False
     else:
         if os.environ['RUCIO_CLIENT_MODE']:
             client_mode = True
Repository: rucio/rucio
Issue: bring_online incorrectly set in multihops with tape source

Motivation
----------
The job parameters in fts are constructed from last hop (which is the initial transfer that triggered the multihop). This behavior was changed in https://github.com/rucio/rucio/pull/4837 . Until then, the job parameters where built from first hop because it was the first one inserted into the "transfers" dictionary and so the first one analyzed.

This results in multihop jobs being submitted for transfers from tape without bring_online set




Changed files:
lib/rucio/daemons/conveyor/common.py

diff --git a/lib/rucio/daemons/conveyor/common.py b/lib/rucio/daemons/conveyor/common.py
index cee821c48..26ab30669 100644
--- a/lib/rucio/daemons/conveyor/common.py
+++ b/lib/rucio/daemons/conveyor/common.py
@@ -342,8 +342,13 @@ def bulk_group_transfers_for_fts(transfers, policy='rule', group_bulk=200, sourc
             # for multihop transfers, all the path is submitted as a separate job
             job_params = _build_job_params(transfer_path[-1])
             for transfer in transfer_path[:-1]:
+                hop_params = _build_job_params(transfer)
                 # Only allow overwrite if all transfers in multihop allow it
-                job_params['overwrite'] = _build_job_params(transfer)['overwrite'] and job_params['overwrite']
+                job_params['overwrite'] = hop_params['overwrite'] and job_params['overwrite']
+                # Activate bring_online if it was requested by first hop (it is a multihop starting at a tape)
+                # We don't allow multihop via a tape, so bring_online should not be set on any other hop
+                if transfer is transfer_path[0] and hop_params['bring_online']:
+                    job_params['bring_online'] = hop_params['bring_online']
 
             group_key = 'multihop_%s' % transfer_path[-1].rws.request_id
             grouped_transfers[group_key] = {'transfers': transfer_path, 'job_params': job_params}
Repository: rucio/rucio
Issue: Deletion timeout does not work on GridFTP

Motivation
----------

The newly-introduced deletion timeout does not appear to work on GridFTP.

https://github.com/rucio/rucio/blob/6a853eb36b25cbbd2b49159def9d6db93dd16422/lib/rucio/rse/protocols/gfal.py#L241

Modification
------------

Replace `GSIFTP PLUGIN` with `GRIDFTP PLUGIN`.

Changed files:
lib/rucio/rse/protocols/gfal.py

diff --git a/lib/rucio/rse/protocols/gfal.py b/lib/rucio/rse/protocols/gfal.py
index a47df4bee..f238300fa 100644
--- a/lib/rucio/rse/protocols/gfal.py
+++ b/lib/rucio/rse/protocols/gfal.py
@@ -238,7 +238,7 @@ class Default(protocol.RSEProtocol):
                 timeout = int(TIMEOUT)
                 self.__ctx.set_opt_integer("HTTP PLUGIN", "OPERATION_TIMEOUT", timeout)
                 self.__ctx.set_opt_integer("SRM PLUGIN", "OPERATION_TIMEOUT", timeout)
-                self.__ctx.set_opt_integer("GSIFTP PLUGIN", "OPERATION_TIMEOUT", timeout)
+                self.__ctx.set_opt_integer("GRIDFTP PLUGIN", "OPERATION_TIMEOUT", timeout)
             except ValueError:
                 self.logger(logging.ERROR, 'wrong timeout value %s', TIMEOUT)
Repository: rucio/rucio
Issue: Incorrect variable type passed to request.core.get_next counter

Motivation
----------

https://github.com/rucio/rucio/blob/63823eceebe68294c98364884a33172d14591da9/lib/rucio/core/request.py#L313

results in this error on the statsd side: 
```
19 Nov 16:32:19 - DEBUG: Bad line:  'T'>, <RequestType.STAGEIN in msg "rucio_int_okd.core.request.get_next.[<RequestType.TRANSFER: 'T'>, <RequestType.STAGEIN: 'I'>, <RequestType.STAGEOUT: 'O'>].[<RequestState.DONE: 'D'>, <RequestState.FAILED: 'F'>, <RequestState.LOST: 'L'>, <RequestState.SUBMITTING: 'G'>, <RequestState.SUBMISSION_FAILED: 'A'>, <RequestState.NO_SOURCES: 'N'>, <RequestState.ONLY_TAPE_SOURCES: 'O'>, <RequestState.MISMATCH_SCHEME: 'M'>]:1|c"
```

The issue is probably there since the "enum" refactoring. 

Modification
------------

Request_type must be explicitly converted to a string when passing to record_counter.


Changed files:
lib/rucio/core/request.py, lib/rucio/tests/test_conveyor.py

diff --git a/lib/rucio/core/request.py b/lib/rucio/core/request.py
index 50d3dec46..16dfa29c7 100644
--- a/lib/rucio/core/request.py
+++ b/lib/rucio/core/request.py
@@ -309,8 +309,10 @@ def get_next(request_type, state, limit=100, older_than=None, rse_id=None, activ
     :param session:           Database session to use.
     :returns:                 Request as a dictionary.
     """
-
-    record_counter('core.request.get_next.{request_type}.{state}', labels={'request_type': request_type, 'state': state})
+    request_type_metric_label = '.'.join(a.name for a in request_type) if isinstance(request_type, list) else request_type.name
+    state_metric_label = '.'.join(s.name for s in state) if isinstance(state, list) else state.name
+    record_counter('core.request.get_next.{request_type}.{state}', labels={'request_type': request_type_metric_label,
+                                                                           'state': state_metric_label})
 
     # lists of one element are not allowed by SQLA, so just duplicate the item
     if type(request_type) is not list:
diff --git a/lib/rucio/tests/test_conveyor.py b/lib/rucio/tests/test_conveyor.py
index d33d72089..2cc697524 100644
--- a/lib/rucio/tests/test_conveyor.py
+++ b/lib/rucio/tests/test_conveyor.py
@@ -384,6 +384,12 @@ def test_multisource(vo, did_factory, root_account, replica_client, core_config_
     # Only one request was handled; doesn't matter that it's multisource
     assert metrics_mock.get_sample_value('rucio_daemons_conveyor_finisher_handle_requests_total') >= 1
     assert metrics_mock.get_sample_value('rucio_daemons_conveyor_poller_update_request_state_total', labels={'updated': 'True'}) >= 1
+    assert metrics_mock.get_sample_value(
+        'rucio_core_request_get_next_total',
+        labels={
+            'request_type': 'TRANSFER.STAGEIN.STAGEOUT',
+            'state': 'DONE.FAILED.LOST.SUBMITTING.SUBMISSION_FAILED.NO_SOURCES.ONLY_TAPE_SOURCES.MISMATCH_SCHEME'}
+    )
 
 
 @skip_rse_tests_with_accounts
Repository: rucio/rucio
Issue: `common/test_rucio_server` file path bug

Motivation
----------
https://github.com/rucio/rucio/blob/0e475d3edf88a466bb402dc2e7047b8496108c52/lib/rucio/common/test_rucio_server.py#L151
The dids added to the array for cleanup after the tests run are not constructed correctly. The entire path of the tmp files is added to construct the dids, while only the filename should be used.

Modification
------------
Don't use the full path of the testfiles.



Changed files:
lib/rucio/common/test_rucio_server.py

diff --git a/lib/rucio/common/test_rucio_server.py b/lib/rucio/common/test_rucio_server.py
index 6c0bf83cd..8b3a580ae 100644
--- a/lib/rucio/common/test_rucio_server.py
+++ b/lib/rucio/common/test_rucio_server.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2014-2021 CERN
+# Copyright 2021 CERN
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,16 +14,16 @@
 # limitations under the License.
 #
 # Authors:
-# - Joaquín Bogado <jbogado@linti.unlp.edu.ar>, 2014-2018
-# - Cedric Serfon <cedric.serfon@cern.ch>, 2015
-# - Martin Barisits <martin.barisits@cern.ch>, 2019
-# - Benedikt Ziemons <benedikt.ziemons@cern.ch>, 2020-2021
-# - Mayank Sharma <mayank.sharma@cern.ch>, 2021
+# - Benedikt Ziemons <benedikt.ziemons@cern.ch>, 2021
+# - Rakshita Varadarajan <rakshitajps@gmail.com>, 2021
+# - Joel Dierkes <joel.dierkes@cern.ch>, 2021
 
 from __future__ import print_function
 
 import unittest
 from os import remove
+from os.path import basename
+
 
 from rucio.common.utils import generate_uuid as uuid, execute
 
@@ -56,7 +56,7 @@ def get_scope_and_rses():
 def delete_rules(did):
     # get the rules for the file
     print('Deleting rules')
-    cmd = "rucio list-rules --did {0} | grep {0} | cut -f1 -d\\\\ ".format(did)
+    cmd = "rucio list-rules {0} | grep {0} | cut -f1 -d\\\\ ".format(did)
     print(cmd)
     exitcode, out, err = execute(cmd)
     print(out, err)
@@ -79,7 +79,7 @@ class TestRucioServer(unittest.TestCase):
     def tearDown(self):
         for did in self.generated_dids:
             delete_rules(did)
-            self.generated_dids.remove(did)
+        self.generated_dids = []
 
     def test_ping(self):
         """CLIENT (USER): rucio ping"""
@@ -145,8 +145,8 @@ class TestRucioServer(unittest.TestCase):
         self.assertEqual(exitcode, 0)
 
         # cleaning
-        remove('/tmp/{0}/'.format(tmp_dsn) + tmp_file1[5:])
-        remove('/tmp/{0}/'.format(tmp_dsn) + tmp_file2[5:])
-        remove('/tmp/{0}/'.format(tmp_dsn) + tmp_file3[5:])
-        added_dids = ['{0}:{1}'.format(self.scope, did) for did in (tmp_file1, tmp_file2, tmp_file3, tmp_dsn)]
+        remove('/tmp/{0}/'.format(tmp_dsn) + basename(tmp_file1))
+        remove('/tmp/{0}/'.format(tmp_dsn) + basename(tmp_file2))
+        remove('/tmp/{0}/'.format(tmp_dsn) + basename(tmp_file3))
+        added_dids = ['{0}:{1}'.format(self.scope, did) for did in (basename(tmp_file1), basename(tmp_file2), basename(tmp_file3), tmp_dsn)]
         self.generated_dids += added_dids
Repository: rucio/rucio
Issue: PolicyPackageNotFound: Module rucio.common.permission.generic_multi_vo not found

Hi,

While setting up an instance with multi_vo mode enabled using the default permissions package, I got the following error on the client (just from running rucio whoami):
```
2021-04-26 10:40:51,035 ERROR   Cannot authenticate.
Details: PolicyPackageNotFound: Module rucio.common.permission.generic_multi_vo not found 
```

I think this may just be a simple typo in the fallback package name here:
https://github.com/rucio/rucio/blob/b7102af49b39ed79e3fafa43d82e91620d721be6/lib/rucio/core/permission/__init__.py#L88

Is this meant to be "rucio.core.permission." instead and could it please be fixed?

Regards,
Simon


Changed files:
lib/rucio/core/permission/__init__.py

diff --git a/lib/rucio/core/permission/__init__.py b/lib/rucio/core/permission/__init__.py
index 73d81d70d..02ca47550 100644
--- a/lib/rucio/core/permission/__init__.py
+++ b/lib/rucio/core/permission/__init__.py
@@ -85,7 +85,7 @@ def load_permission_for_vo(vo):
                 POLICY = GENERIC_FALLBACK
             POLICY = 'rucio.core.permission.' + POLICY.lower()
     else:
-        POLICY = 'rucio.common.permission.' + GENERIC_FALLBACK.lower()
+        POLICY = 'rucio.core.permission.' + GENERIC_FALLBACK.lower()
 
     try:
         module = importlib.import_module(POLICY)
Repository: rucio/rucio
Issue: regression in conveyor database partition variable name

Motivation
----------
The database table is "requests". By error, we try to access "request" (singular). 




Changed files:
lib/rucio/core/transfer.py

diff --git a/lib/rucio/core/transfer.py b/lib/rucio/core/transfer.py
index 14274a6a1..2d8c887a3 100644
--- a/lib/rucio/core/transfer.py
+++ b/lib/rucio/core/transfer.py
@@ -1565,7 +1565,7 @@ def __list_transfer_requests_and_source_replicas(
     """
 
     if partition_hash_var is None:
-        partition_hash_var = 'request.id'
+        partition_hash_var = 'requests.id'
 
     if request_state is None:
         request_state = RequestState.QUEUED
Repository: rucio/rucio
Issue: `bring_online` parameter is submitted as a string, instead of int, to FTS

Motivation
----------
https://github.com/rucio/rucio/blob/e2ed93b6d315091cf4960f76b4253ce8fad27a6c/lib/rucio/daemons/conveyor/submitter.py#L107
Loads the value as a string. Later on in the workflow this is submitted to FTS as a string in the dictionary, which the new FTS3 REST interface on fts3-pilot does not like.

Modification
------------
This should be cast to int, or better loaded with `config_get_int`. Also applies to the stager.


Changed files:
lib/rucio/daemons/conveyor/submitter.py, lib/rucio/daemons/conveyor/stager.py

diff --git a/lib/rucio/daemons/conveyor/stager.py b/lib/rucio/daemons/conveyor/stager.py
index 920848140..3240d54bc 100644
--- a/lib/rucio/daemons/conveyor/stager.py
+++ b/lib/rucio/daemons/conveyor/stager.py
@@ -40,7 +40,7 @@ from six.moves.configparser import NoOptionError
 
 import rucio.db.sqla.util
 from rucio.common import exception
-from rucio.common.config import config_get, config_get_bool
+from rucio.common.config import config_get, config_get_bool, config_get_int
 from rucio.common.logging import setup_logging
 from rucio.core.monitor import record_counter, record_timer
 from rucio.core import transfer as transfer_core
@@ -68,7 +68,7 @@ def stager(once=False, rses=None, bulk=100, group_bulk=1, group_policy='rule',
         failover_scheme = None
 
     try:
-        bring_online = config_get('conveyor', 'bring_online')
+        bring_online = config_get_int('conveyor', 'bring_online')
     except NoOptionError:
         bring_online = 43200
 
diff --git a/lib/rucio/daemons/conveyor/submitter.py b/lib/rucio/daemons/conveyor/submitter.py
index 4d4109e36..45d6dd36d 100644
--- a/lib/rucio/daemons/conveyor/submitter.py
+++ b/lib/rucio/daemons/conveyor/submitter.py
@@ -48,7 +48,7 @@ from six.moves.configparser import NoOptionError
 
 import rucio.db.sqla.util
 from rucio.common import exception
-from rucio.common.config import config_get, config_get_bool
+from rucio.common.config import config_get, config_get_bool, config_get_int
 from rucio.common.logging import setup_logging
 from rucio.common.schema import get_schema_value
 from rucio.common.utils import PriorityQueue
@@ -104,7 +104,7 @@ def submitter(once=False, rses=None, partition_wait_time=10,
         timeout = None
 
     try:
-        bring_online = config_get('conveyor', 'bring_online')
+        bring_online = config_get_int('conveyor', 'bring_online')
     except NoOptionError:
         bring_online = 43200
Repository: rucio/rucio
Issue: unexpected keyword argument 'id' in receiver

Motivation
----------
Receiver fails to start:
```
TypeError: receiver() got an unexpected keyword argument 'id'
```



Changed files:
lib/rucio/daemons/conveyor/receiver.py

diff --git a/lib/rucio/daemons/conveyor/receiver.py b/lib/rucio/daemons/conveyor/receiver.py
index 62b270f2f..63fc72bb6 100644
--- a/lib/rucio/daemons/conveyor/receiver.py
+++ b/lib/rucio/daemons/conveyor/receiver.py
@@ -259,7 +259,7 @@ def run(once=False, total_threads=1, full_mode=False):
         raise exception.DatabaseException('Database was not updated, daemon won\\'t start')
 
     logging.info('starting receiver thread')
-    threads = [threading.Thread(target=receiver, kwargs={'id': i,
+    threads = [threading.Thread(target=receiver, kwargs={'id_': i,
                                                          'full_mode': full_mode,
                                                          'total_threads': total_threads}) for i in range(0, total_threads)]
Repository: rucio/rucio
Issue: pip install rucio fails with newer versions of pip

Apparently newer versions of pip don't like the three equals in the cx_oracle dependency. (Somewhere along the line internally it sticks parentheses around the version description, and then the parser chokes on that combination).

```
(rucio-test) [illingwo@fermicloud014 rucio-test]$ pip --version
pip 18.0 from /cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip (python 2.7)
(rucio-test) [illingwo@fermicloud014 rucio-test]$ pip install rucio
Collecting rucio
Exception:
Traceback (most recent call last):
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_internal/basecommand.py", line 141, in main
    status = self.run(options, args)
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_internal/commands/install.py", line 299, in run
    resolver.resolve(requirement_set)
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_internal/resolve.py", line 102, in resolve
    self._resolve_one(requirement_set, req)
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_internal/resolve.py", line 306, in _resolve_one
    set(req_to_install.extras) - set(dist.extras)
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2826, in extras
    return [dep for dep in self._dep_map if dep]
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2871, in _dep_map
    self.__dep_map = self._compute_dependencies()
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2881, in _compute_dependencies
    reqs.extend(parse_requirements(req))
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2942, in parse_requirements
    yield Requirement(line)
  File "/cloud/login/illingwo/rucio-test/lib/python2.7/site-packages/pip/_vendor/pkg_resources/__init__.py", line 2951, in __init__
    raise RequirementParseError(str(e))
RequirementParseError: Invalid requirement, parse error at "'(===6.3.'"
```



Changed files:
setup_rucio.py

diff --git a/setup_rucio.py b/setup_rucio.py
index 078dfca94..ecd935df4 100644
--- a/setup_rucio.py
+++ b/setup_rucio.py
@@ -15,7 +15,7 @@
 # Authors:
 # - Mario Lassnig <mario.lassnig@cern.ch>, 2012-2014
 # - Vincent Garonne <vgaronne@gmail.com>, 2012-2018
-# - Martin Barisits <martin.barisits@cern.ch>, 2012-2017
+# - Martin Barisits <martin.barisits@cern.ch>, 2012-2018
 # - Wen Guan <wguan.icedew@gmail.com>, 2014
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2014-2018
 
@@ -164,7 +164,7 @@ def write_requirements():
         req_file.close()
 
 
-oracle_extras = ['cx_oracle===6.3.1']
+oracle_extras = ['cx_oracle==6.3.1']
 postgresql_extras = ['psycopg2>=2.4.2']
 mysql_extras = ['PyMySQL']
 kerberos_extras = ['kerberos>=1.3.0', 'pykerberos>=1.2.1', 'requests-kerberos>=0.12.0']
Repository: rucio/rucio
Issue: error in nongrid-trace section name on rucio-cfg generation 

Motivation
----------
nogrid-trace should be nongrid-trace at: 
https://github.com/rucio/rucio/blob/d4b4f92a0155875c8d1e1ced0fa644ff09997dff/tools/merge_rucio_configs.py#L36


Changed files:
tools/merge_rucio_configs.py

diff --git a/tools/merge_rucio_configs.py b/tools/merge_rucio_configs.py
index 89b83023c..97cd80e86 100644
--- a/tools/merge_rucio_configs.py
+++ b/tools/merge_rucio_configs.py
@@ -33,7 +33,7 @@ multi_word_sections = {
     'messaging_cache': 'messaging-cache',
     'messaging_hermes': 'messaging-hermes',
     'messaging_hermes2': 'hermes',
-    'nongrid_trace': 'nogrid-trace',
+    'nongrid_trace': 'nongrid-trace',
     'tracer_kronos': 'tracer-kronos',
 }
Repository: rucio/rucio
Issue: Scope name validation regex allows single quotes

The scope validation regex for atlas/generic/icecube (but not cms) allows single quotes, which seems like a bad idea.

`"^[a-zA-Z'_'-.0-9]{1,%s}$" % SCOPE_LENGTH` looks wrong, and I'm guessing it ought to be `"^[a-zA-Z_\\\\-.0-9]{1,%s}$" % SCOPE_LENGTH`. Unless someone really does have this requirement?

Changed files:
lib/rucio/common/schema/icecube.py, lib/rucio/common/schema/generic.py, lib/rucio/common/schema/atlas.py

diff --git a/lib/rucio/common/schema/atlas.py b/lib/rucio/common/schema/atlas.py
index cf1128a74..7c398217e 100644
--- a/lib/rucio/common/schema/atlas.py
+++ b/lib/rucio/common/schema/atlas.py
@@ -52,7 +52,7 @@ SCOPE_LENGTH = 25
 
 SCOPE = {"description": "Scope name",
          "type": "string",
-         "pattern": "^[a-zA-Z'_'-.0-9]{1,%s}$" % SCOPE_LENGTH}
+         "pattern": "^[a-zA-Z_\\\\-.0-9]{1,%s}$" % SCOPE_LENGTH}
 
 R_SCOPE = {"description": "Scope name",
            "type": "string",
diff --git a/lib/rucio/common/schema/generic.py b/lib/rucio/common/schema/generic.py
index 62d9f2e5c..97fa9c5cc 100644
--- a/lib/rucio/common/schema/generic.py
+++ b/lib/rucio/common/schema/generic.py
@@ -49,7 +49,7 @@ SCOPE_LENGTH = 25
 
 SCOPE = {"description": "Scope name",
          "type": "string",
-         "pattern": "^[a-zA-Z'_'-.0-9]{1,%s}$" % SCOPE_LENGTH}
+         "pattern": "^[a-zA-Z_\\\\-.0-9]{1,%s}$" % SCOPE_LENGTH}
 
 R_SCOPE = {"description": "Scope name",
            "type": "string",
diff --git a/lib/rucio/common/schema/icecube.py b/lib/rucio/common/schema/icecube.py
index adcc87a6b..d2efd2348 100644
--- a/lib/rucio/common/schema/icecube.py
+++ b/lib/rucio/common/schema/icecube.py
@@ -50,7 +50,7 @@ SCOPE_LENGTH = 25
 
 SCOPE = {"description": "Scope name",
          "type": "string",
-         "pattern": "^[a-zA-Z'_'-.0-9]{1,%s}$" % SCOPE_LENGTH}
+         "pattern": "^[a-zA-Z_\\\\-.0-9]{1,%s}$" % SCOPE_LENGTH}
 
 R_SCOPE = {"description": "Scope name",
            "type": "string",
Repository: rucio/rucio
Issue: Conveyor submitter daemons are doing nothing if there are many requests with no sources. (Can reproduce)

For quite some time now in the ESCAPE Rucio instance there are no jobs submitted to fts unless I significantly raise the number of conveyor submitter threads every now and then.

After some digging up I found out that the conveyor submitter daemons are fed with jobs that have no sources. Then they go through them and of course do not submit them. 

The issue is that they do not mark them as unavailable or something and they stay in the requests queue. On the next loop they are picked up again and this continues as an endless cycle of doing nothing.

They continue of the loop happens here https://github.com/rucio/rucio/blob/3c840247c1c3decd37ade5b5d9b0c5adb4e0a960/lib/rucio/core/transfer.py#L656

### How to replicate
Instructions
1. Create 1001 files stuck in replicating state (by a failed upload)
2. Create replication rules for those 1001 files.
3. Do a successful upload
4. Add a replication rule for the file
5. Run the conveyor submitter as many times as you want, the valid transfer will never be picked up.

CLI Instructions
```bash
$ git clone git@github.com:rucio/rucio.git
$ cd rucio
$ docker-compose --file etc/docker/dev/docker-compose-storage-localhost.yml up -d
$ docker exec -it dev_rucio_1 /bin/bash
$ ./tools/run_tests_docker.sh -i
$ ./tools/docker_activate_rses.sh
$ rucio-admin rse add FAIL
$ rucio-admin rse add-protocol --hostname fail.com --scheme root --prefix /fail FAIL
$ seq 1010 | xargs -n 1 -I {} -P 10 touch failed_upload{}
$ seq 1010 | xargs -n 1 -I {} -P 10 rucio upload --scope test --rse FAIL failed_upload{}
$ seq 1010 | xargs -n 1 -I {} -P 10 rucio add-rule test:failed_upload{} 1 XRD1
$ rucio-conveyor-submitter --run-once
# Nothing should have happened here since the uploads to MOCK fail by default
$ touch working_upload
$ rucio upload working_upload --scope test --rse XRD1
# This upload will succeed
$ rucio add-rule test:working_upload 1 XRD2
$ rucio-conveyor-submitter --run-once
# Request about test:working_upload will not be picked even though it is valid
```



Changed files:
lib/rucio/core/transfer.py

diff --git a/lib/rucio/core/transfer.py b/lib/rucio/core/transfer.py
index 8629640ce..e95e51a48 100644
--- a/lib/rucio/core/transfer.py
+++ b/lib/rucio/core/transfer.py
@@ -662,6 +662,10 @@ def get_transfer_requests_and_source_replicas(total_workers=0, worker_number=0,
 
         multihop = False
 
+        # Add req to req_no_source list (Will be removed later if needed)
+        if req_id not in reqs_no_source:
+            reqs_no_source.append(req_id)
+
         # source_rse_id will be None if no source replicas
         # rse will be None if rse is staging area
         if source_rse_id is None or rse is None:
Repository: rucio/rucio
Issue: Off by one error in core/transfer.py

Motivation
----------

Reported by Patrick Austin

It looks like this commit https://github.com/rucio/rucio/commit/b519409488ad2af867c866e4e72cd96ecdbf86bc
introduced a bug in core/transfer.py where another field was selected out of the database, but the destination RSE in line 1254 was not updated to reflect this.


Modification
------------

Change 9 to 10 in line 1254


Changed files:
lib/rucio/core/transfer.py

diff --git a/lib/rucio/core/transfer.py b/lib/rucio/core/transfer.py
index e95e51a48..2aa364698 100644
--- a/lib/rucio/core/transfer.py
+++ b/lib/rucio/core/transfer.py
@@ -27,6 +27,7 @@
 # - Gabriele <sucre.91@hotmail.it>, 2019
 # - Jaroslav Guenther <jaroslav.guenther@cern.ch>, 2019-2020
 # - Eli Chadwick <eli.chadwick@stfc.ac.uk>, 2020
+# - Patrick Austin <patrick.austin@stfc.ac.uk>, 2020
 #
 # PY3K COMPATIBLE
 
@@ -1355,7 +1356,7 @@ def __list_transfer_requests_and_source_replicas(total_workers=0, worker_number=
     if rses:
         result = []
         for item in query.all():
-            dest_rse_id = item[9]
+            dest_rse_id = item[10]
             if dest_rse_id in rses:
                 result.append(item)
         return result
Repository: rucio/rucio
Issue:  listing archived replicas returns wrong filemeta if RSE expression

Motivation
----------

If the client requests a specific RSE expression then the returned file data (checksum, bytes, ...) is from the archive, not the constituent.

Changed files:
lib/rucio/core/replica.py

diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
index e20ba3488..1bdd141af 100644
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -39,6 +39,7 @@ from sqlalchemy.exc import DatabaseError, IntegrityError
 from sqlalchemy.orm.exc import FlushError, NoResultFound
 from sqlalchemy.sql.expression import case, bindparam, select, text, false, true
 
+import rucio.core.did
 import rucio.core.lock
 
 from rucio.common import exception
@@ -783,14 +784,27 @@ def _list_replicas(dataset_clause, file_clause, state_clause, show_pfns,
                 # then yield and continue as the replica does not exist and we don't want to return
                 # an additional empty pfn to the client
                 if rse is None:
-                    for archive in archive_result:
 
+                    # retrieve the constituents metadata so we can downport it later
+                    # otherwise the zip meta will be used which won't match the actual file
+                    # full name used due to circular import dependency between modules
+                    constituent_meta = rucio.core.did.get_metadata(scope, name, session=session)
+
+                    for archive in archive_result:
                         # RSE expression might limit the archives we're allowed to use
                         # if it's empty due to non-matching RSE expression we must skip
                         if archive['pfns'] == {}:
                             continue
 
+                        # downport the constituents meta, we are not interested in the archives meta
+                        archive['scope'] = scope
+                        archive['name'] = name
+                        archive['adler32'] = constituent_meta['adler32']
+                        archive['md5'] = constituent_meta['md5']
+                        archive['bytes'] = constituent_meta['bytes']
+
                         for tmp_archive in archive['pfns']:
+                            # declare the constituent as being in a zip file
                             archive['pfns'][tmp_archive]['domain'] = 'zip'
                             # at this point we don't know the protocol of the parent, so we have to peek
                             if tmp_archive.startswith('root://') and 'xrdcl.unzip' not in tmp_archive:
@@ -1010,6 +1024,7 @@ def _list_replicas(dataset_clause, file_clause, state_clause, show_pfns,
                 file['rses'][t_rse].append(t_pfn)
             else:
                 file['rses'][t_rse] = [t_pfn]
+
         yield file
         file = {}
Repository: rucio/rucio
Issue: Duplicate prometheus metrics when testing/importing hermes, hermes2

Motivation
----------
Importing hermes and hermes2 at the same time now fails in testing, because the prometheus metrics are named the same and are initialized on module import.

The error is:
```
ValueError: Duplicated timeseries in CollectorRegistry: set(['rucio_daemons_hermes_reconnect_total', 'rucio_daemons_hermes_reconnect_created'])
```

which is caused on this line:
https://github.com/rucio/rucio/blob/a4ea2cf45961641e9f266f07fefc0a8e8be96498/lib/rucio/daemons/hermes/hermes2.py#L73

See the checks on PR https://github.com/rucio/rucio/pull/3947


Modification
------------
Move initialization to the `run` Method

Changed files:
lib/rucio/daemons/hermes/hermes2.py

diff --git a/lib/rucio/daemons/hermes/hermes2.py b/lib/rucio/daemons/hermes/hermes2.py
index dc19a3229..e66463883 100644
--- a/lib/rucio/daemons/hermes/hermes2.py
+++ b/lib/rucio/daemons/hermes/hermes2.py
@@ -70,7 +70,7 @@ logging.basicConfig(stream=sys.stdout,
 
 GRACEFUL_STOP = threading.Event()
 
-RECONNECT_COUNTER = Counter('rucio_daemons_hermes_reconnect', 'Counts Hermes reconnects to different ActiveMQ brokers', labelnames=('host',))
+RECONNECT_COUNTER = Counter('rucio_daemons_hermes2_reconnect', 'Counts Hermes2 reconnects to different ActiveMQ brokers', labelnames=('host',))
 
 
 def default(datetype):
Repository: rucio/rucio
Issue: Unhandled exception in list_replicas

Motivation
----------
Traceback :

```
[Tue Feb 20 23:32:25.701947 2018] [:error] [pid 5431:tid 139990096934656] Traceback (most recent call last):
[Tue Feb 20 23:32:25.701980 2018] [:error] [pid 5431:tid 139990096934656]   File "/usr/lib/python2.7/site-packages/rucio/core/replica.py", line 752, in _list_replicas
[Tue Feb 20 23:32:25.701984 2018] [:error] [pid 5431:tid 139990096934656]     domain=domain)['scheme'])
[Tue Feb 20 23:32:25.701986 2018] [:error] [pid 5431:tid 139990096934656]   File "/usr/lib/python2.7/site-packages/rucio/rse/rsemanager.py", line 126, in select_protocol
[Tue Feb 20 23:32:25.701989 2018] [:error] [pid 5431:tid 139990096934656]     candidates = _get_possible_protocols(rse_settings, operation, scheme, domain)
[Tue Feb 20 23:32:25.701991 2018] [:error] [pid 5431:tid 139990096934656]   File "/usr/lib/python2.7/site-packages/rucio/rse/rsemanager.py", line 102, in _get_possible_protocols
[Tue Feb 20 23:32:25.701994 2018] [:error] [pid 5431:tid 139990096934656]     ' found : %s.' % str(rse_settings))
[Tue Feb 20 23:32:25.701996 2018] [:error] [pid 5431:tid 139990096934656] RSEProtocolNotSupported: RSE does not support requested protocol.
```

Modification
------------
Need to catch RSEProtocolNotSupported exception


Changed files:
lib/rucio/core/replica.py

diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
index 1bdd141af..6b805e5af 100644
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -868,6 +868,8 @@ def _list_replicas(dataset_clause, file_clause, state_clause, show_pfns,
                                 rse_schemes.append(rsemgr.select_protocol(rse_settings=rse_info[rse],
                                                                           operation='read',
                                                                           domain=domain)['scheme'])
+                        except exception.RSEProtocolNotSupported:
+                            pass  # no need to be verbose
                         except Exception:
                             print(format_exc())
Repository: rucio/rucio
Issue: urlparse.urlparse call in transfertool interface is wrong

Motivation
----------
This was changed in a recent PR, however, the call on `urlparse.urlparse` is wrong, `urlparse` method should be called directly.

Changed files:
lib/rucio/transfertool/fts3.py

diff --git a/lib/rucio/transfertool/fts3.py b/lib/rucio/transfertool/fts3.py
index 83ebb2898..90f0ff462 100644
--- a/lib/rucio/transfertool/fts3.py
+++ b/lib/rucio/transfertool/fts3.py
@@ -508,7 +508,7 @@ class FTS3Transfertool(Transfertool):
     @staticmethod
     def __extract_host(external_host):
         # graphite does not like the dots in the FQDN
-        return urlparse.urlparse(external_host).hostname.replace('.', '_')
+        return urlparse(external_host).hostname.replace('.', '_')
 
     def __get_transfer_baseid_voname(self):
         """
Repository: rucio/rucio
Issue: do not skip CA check on retry

Motivation
----------
If the server can't be connected the retry will ignore the CA.

https://github.com/rucio/rucio/blob/master/lib/rucio/client/baseclient.py#L353

Changed files:
lib/rucio/client/baseclient.py

diff --git a/lib/rucio/client/baseclient.py b/lib/rucio/client/baseclient.py
index 35528730c..46d2d3b7d 100644
--- a/lib/rucio/client/baseclient.py
+++ b/lib/rucio/client/baseclient.py
@@ -1,4 +1,4 @@
-# Copyright 2012-2018 CERN for the benefit of the ATLAS collaboration.
+# Copyright 2012-2020 CERN for the benefit of the ATLAS collaboration.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2012-2013
 # - Vincent Garonne <vgaronne@gmail.com>, 2012-2018
 # - Yun-Pin Sun <winter0128@gmail.com>, 2013
-# - Mario Lassnig <mario.lassnig@cern.ch>, 2013-2019
+# - Mario Lassnig <mario.lassnig@cern.ch>, 2013-2020
 # - Cedric Serfon <cedric.serfon@cern.ch>, 2014-2015
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2015
 # - Joaquin Bogado <jbogado@linti.unlp.edu.ar>, 2015
@@ -350,7 +350,6 @@ class BaseClient(object):
                     return
             except ConnectionError as error:
                 LOG.warning('ConnectionError: ' + str(error))
-                self.ca_cert = False
                 if retry > self.request_retries:
                     raise
                 continue