Repository: rucio/rucio

Issue:
Temporary unavailable files injection fails if duplucates
Motivation
----------
Traceback :
```
Details: [u'(cx_Oracle.IntegrityError) ORA-00001: unique constraint (ATLAS_RUCIO.BAD_PFNS_PK) violated']
Rucio exited with an unexpected/unknown error, please provide the traceback below to the developers.
Traceback (most recent call last):
  File "/usr/bin/rucio-admin", line 129, in new_funct
    return function(*args, **kwargs)
  File "/usr/bin/rucio-admin", line 1034, in declare_temporary_unavailable_replicas
    client.add_bad_pfns(pfns=chunk, reason=args.reason, state='TEMPORARY_UNAVAILABLE', expires_at=expiration_date)
  File "/usr/lib/python2.7/site-packages/rucio/client/replicaclient.py", line 336, in add_bad_pfns
    raise exc_cls(exc_msg)
RucioException: An unknown exception occurred.
Details: [u'(cx_Oracle.IntegrityError) ORA-00001: unique constraint (ATLAS_RUCIO.BAD_PFNS_PK) violated']
```


RUCIO_ACCOUNT should override the Rucio configuration file
Motivation
----------
Use of the RUCIO_ACCOUNT environment variable should override the account specified in the Rucio configuration file.





Discussion:

Resolving patch:
diff --git a/lib/rucio/client/baseclient.py b/lib/rucio/client/baseclient.py
--- a/lib/rucio/client/baseclient.py
+++ b/lib/rucio/client/baseclient.py
@@ -215,12 +215,12 @@ def __init__(self, rucio_host=None, auth_host=None, account=None, ca_cert=None,
         if account is None:
             LOG.debug('no account passed. Trying to get it from the config file.')
             try:
-                self.account = config_get('client', 'account')
-            except (NoOptionError, NoSectionError):
+                self.account = environ['RUCIO_ACCOUNT']
+            except KeyError:
                 try:
-                    self.account = environ['RUCIO_ACCOUNT']
-                except KeyError:
-                    raise MissingClientParameter('Option \'account\' cannot be found in config file and RUCIO_ACCOUNT is not set.')
+                    self.account = config_get('client', 'account')
+                except (NoOptionError, NoSectionError):
+                        raise MissingClientParameter('Option \'account\' cannot be found in config file and RUCIO_ACCOUNT is not set.')
 
         token_path = self.TOKEN_PATH_PREFIX + self.account
         self.token_file = token_path + '/' + self.TOKEN_PREFIX + self.account
diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -2695,7 +2695,9 @@ def add_bad_pfns(pfns, account, state, reason=None, expires_at=None, session=Non
     pfns = clean_surls(pfns)
     for pfn in pfns:
         new_pfn = models.BadPFNs(path=str(pfn), account=account, state=rep_state, reason=reason, expires_at=expires_at)
+        new_pfn = session.merge(new_pfn)
         new_pfn.save(session=session, flush=False)
+
     try:
         session.flush()
     except IntegrityError as error:
diff --git a/lib/rucio/core/rule.py b/lib/rucio/core/rule.py
--- a/lib/rucio/core/rule.py
+++ b/lib/rucio/core/rule.py
@@ -21,6 +21,7 @@
 # - Joaquin Bogado <jbogado@linti.unlp.edu.ar>, 2014-2018
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2014-2015
 # - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018-2019
+# - Dimitrios Christidis <dimitrios.christidis@cern.ch>, 2019
 #
 # PY3K COMPATIBLE
 
@@ -1196,7 +1197,7 @@ def update_rule(rule_id, options, session=None):
     :raises:            RuleNotFound if no Rule can be found, InputValidationError if invalid option is used, ScratchDiskLifetimeConflict if wrong ScratchDiskLifetime is used.
     """
 
-    valid_options = ['locked', 'lifetime', 'account', 'state', 'activity', 'source_replica_expression', 'cancel_requests', 'priority', 'child_rule_id', 'eol_at', 'meta']
+    valid_options = ['locked', 'lifetime', 'account', 'state', 'activity', 'source_replica_expression', 'cancel_requests', 'priority', 'child_rule_id', 'eol_at', 'meta', 'purge_replicas']
 
     for key in options:
         if key not in valid_options:


Test patch: