Repository: rucio/rucio
Issue: rucio-admin config set silently fails

Motivation
----------
 rucio-admin config set silently fails, e.g. :
```
rucio-admin config set --section throttler --option "Data Consolidation,xyz" --value 2000
Set configuration: throttler.Data Consolidation,xyz=2000
```
But on the server side, it returns a `500`






Changed files:
lib/rucio/web/rest/webpy/v1/config.py, lib/rucio/client/downloadclient.py, lib/rucio/client/baseclient.py, lib/rucio/client/configclient.py, lib/rucio/web/rest/flaskapi/v1/config.py

diff --git a/lib/rucio/client/baseclient.py b/lib/rucio/client/baseclient.py
index d1f5ebdd2..3f88e2b0a 100644
--- a/lib/rucio/client/baseclient.py
+++ b/lib/rucio/client/baseclient.py
@@ -357,7 +357,7 @@ class BaseClient(object):
             raise exc_cls(exc_msg)
 
         self.auth_token = result.headers['x-rucio-auth-token']
-        LOG.debug('got new token \\'%s\\'' % self.auth_token)
+        LOG.debug('got new token')
         return True
 
     def __get_token_x509(self):
@@ -418,7 +418,7 @@ class BaseClient(object):
             raise exc_cls(exc_msg)
 
         self.auth_token = result.headers['x-rucio-auth-token']
-        LOG.debug('got new token \\'%s\\'' % self.auth_token)
+        LOG.debug('got new token')
         return True
 
     def __get_token_ssh(self):
@@ -497,7 +497,7 @@ class BaseClient(object):
             raise exc_cls(exc_msg)
 
         self.auth_token = result.headers['x-rucio-auth-token']
-        LOG.debug('got new token \\'%s\\'' % self.auth_token)
+        LOG.debug('got new token')
         return True
 
     def __get_token_gss(self):
@@ -535,7 +535,7 @@ class BaseClient(object):
             raise exc_cls(exc_msg)
 
         self.auth_token = result.headers['x-rucio-auth-token']
-        LOG.debug('got new token \\'%s\\'' % self.auth_token)
+        LOG.debug('got new token')
         return True
 
     def __get_token(self):
@@ -586,7 +586,7 @@ class BaseClient(object):
         except Exception:
             raise
 
-        LOG.debug('read token \\'%s\\' from file' % self.auth_token)
+        LOG.debug('got token from file')
         return True
 
     def __write_token(self):
diff --git a/lib/rucio/client/configclient.py b/lib/rucio/client/configclient.py
index cee0f6f66..11c184eb6 100644
--- a/lib/rucio/client/configclient.py
+++ b/lib/rucio/client/configclient.py
@@ -18,6 +18,7 @@
 # - Vincent Garonne <vgaronne@gmail.com>, 2014-2018
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2015
 # - Martin Barisits <martin.barisits@cern.ch>, 2018
+# - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2019
 #
 # PY3K COMPATIBLE
 
@@ -82,8 +83,7 @@ class ConfigClient(BaseClient):
         url = build_url(choice(self.list_hosts), path=path)
 
         r = self._send_request(url, type='PUT')
-
-        if r.status_code != codes.ok:
+        if r.status_code == codes.created:
             return True
         else:
             exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
diff --git a/lib/rucio/client/downloadclient.py b/lib/rucio/client/downloadclient.py
index 7be3ca247..d374d0a96 100644
--- a/lib/rucio/client/downloadclient.py
+++ b/lib/rucio/client/downloadclient.py
@@ -16,7 +16,7 @@
 # - Tomas Javurek <tomasjavurek09@gmail.com>, 2018
 # - Vincent Garonne <vgaronne@gmail.com>, 2018
 # - Joaquin Bogado <jbogado@linti.unlp.edu.ar>, 2018
-# - Nicolo Magini <nicolo.magini@cern.ch>, 2018
+# - Nicolo Magini <nicolo.magini@cern.ch>, 2018-2019
 # - Tobias Wegner <tobias.wegner@cern.ch>, 2018
 # - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018-2019
 #
@@ -330,7 +330,9 @@ class DownloadClient:
             dest_file_path = os.path.join(dest_dir_path, did_name)
             item['dest_file_paths'] = [dest_file_path]
             item['temp_file_path'] = '%s.part' % dest_file_path
-            item.setdefault('ignore_checksum', True)
+            options = item.setdefault('merged_options', {})
+            options.setdefault('ignore_checksum', item.pop('ignore_checksum', True))
+            options.setdefault('transfer_timeout', item.pop('transfer_timeout', None))
 
             input_items.append(item)
 
@@ -653,7 +655,7 @@ class DownloadClient:
                 start_time = time.time()
 
                 try:
-                    protocol.get(pfn, temp_file_path, transfer_timeout=item.get('transfer_timeout'))
+                    protocol.get(pfn, temp_file_path, transfer_timeout=item.get('merged_options', {}).get('transfer_timeout'))
                     success = True
                 except Exception as error:
                     logger.debug(error)
@@ -661,7 +663,7 @@ class DownloadClient:
 
                 end_time = time.time()
 
-                if success and not item.get('ignore_checksum', False):
+                if success and not item.get('merged_options', {}).get('ignore_checksum', False):
                     rucio_checksum = item.get('adler32')
                     local_checksum = None
                     if not rucio_checksum:
diff --git a/lib/rucio/web/rest/flaskapi/v1/config.py b/lib/rucio/web/rest/flaskapi/v1/config.py
index b0eba6e75..581f78a0e 100755
--- a/lib/rucio/web/rest/flaskapi/v1/config.py
+++ b/lib/rucio/web/rest/flaskapi/v1/config.py
@@ -25,8 +25,10 @@ import json
 from logging import getLogger, StreamHandler, DEBUG
 from flask import Flask, Blueprint, Response, request as request
 from flask.views import MethodView
+from traceback import format_exc
 
 from rucio.api import config
+from rucio.common.exception import ConfigurationError
 from rucio.common.utils import generate_http_error_flask
 from rucio.web.rest.flaskapi.v1.common import before_request, after_request, check_accept_header_wrapper_flask
 
@@ -152,8 +154,11 @@ class OptionSet(MethodView):
 
         try:
             config.set(section=section, option=option, value=value, issuer=request.environ.get('issuer'))
-        except Exception:
+        except ConfigurationError:
             return generate_http_error_flask(500, 'ConfigurationError', 'Could not set value \\'%s\\' for section \\'%s\\' option \\'%s\\'' % (value, section, option))
+        except Exception as error:
+            print(format_exc())
+            return error, 500
         return "Created", 201
 
 
diff --git a/lib/rucio/web/rest/webpy/v1/config.py b/lib/rucio/web/rest/webpy/v1/config.py
index 0fa150ac5..bdc994471 100755
--- a/lib/rucio/web/rest/webpy/v1/config.py
+++ b/lib/rucio/web/rest/webpy/v1/config.py
@@ -23,10 +23,11 @@
 import json
 
 from logging import getLogger, StreamHandler, DEBUG
-
-from web import application, ctx, Created, loadhook, header
+from traceback import format_exc
+from web import application, ctx, Created, loadhook, header, InternalError
 
 from rucio.api import config
+from rucio.common.exception import ConfigurationError
 from rucio.common.utils import generate_http_error
 from rucio.web.rest.common import rucio_loadhook, RucioController, exception_wrapper, check_accept_header_wrapper
 
@@ -166,8 +167,11 @@ class OptionSet(RucioController):
 
         try:
             config.set(section=section, option=option, value=value, issuer=ctx.env.get('issuer'))
-        except:
+        except ConfigurationError:
             raise generate_http_error(500, 'ConfigurationError', 'Could not set value \\'%s\\' for section \\'%s\\' option \\'%s\\'' % (value, section, option))
+        except Exception as error:
+            print(format_exc())
+            raise InternalError(error)
         raise Created()