Repository: rucio/rucio

Issue:
list-rse-usage with --show-accounts does not work
Motivation
----------
`rucio list-rse-usage --show-accounts BNL-OSG2_LOCALGROUPDISK`
fails with
```
2019-01-25 09:07:28,376	ERROR	An unknown exception occurred.
Details: no error information passed (http status code: 500 ('internal_server_error', 'server_error', '/o
', '\xe2\x9c\x97'))
```
On the server the following exception is shown:
```
[Fri Jan 25 13:25:43.381208 2019] [:error] [pid 20836:tid 139736349660928] float division by zero
[Fri Jan 25 13:25:43.383132 2019] [:error] [pid 20836:tid 139736349660928] Traceback (most recent call last):
[Fri Jan 25 13:25:43.383155 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/rucio/web/rest/rse.py", line 614, in GET
[Fri Jan 25 13:25:43.383159 2019] [:error] [pid 20836:tid 139736349660928]     usage = get_rse_usage(rse, issuer=ctx.env.get('issuer'), source=source, per_account=per_account)
[Fri Jan 25 13:25:43.383161 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/rucio/api/rse.py", line 265, in get_rse_usage
[Fri Jan 25 13:25:43.383164 2019] [:error] [pid 20836:tid 139736349660928]     return rse_module.get_rse_usage(rse=rse, source=source, per_account=per_account)
[Fri Jan 25 13:25:43.383166 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/retrying.py", line 49, in wrapped_f
[Fri Jan 25 13:25:43.383169 2019] [:error] [pid 20836:tid 139736349660928]     return Retrying(*dargs, **dkw).call(f, *args, **kw)
[Fri Jan 25 13:25:43.383171 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/retrying.py", line 206, in call
[Fri Jan 25 13:25:43.383173 2019] [:error] [pid 20836:tid 139736349660928]     return attempt.get(self._wrap_exception)
[Fri Jan 25 13:25:43.383175 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/retrying.py", line 247, in get
[Fri Jan 25 13:25:43.383178 2019] [:error] [pid 20836:tid 139736349660928]     six.reraise(self.value[0], self.value[1], self.value[2])
[Fri Jan 25 13:25:43.383180 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/retrying.py", line 200, in call
[Fri Jan 25 13:25:43.383182 2019] [:error] [pid 20836:tid 139736349660928]     attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
[Fri Jan 25 13:25:43.383184 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/rucio/db/sqla/session.py", line 270, in new_funct
[Fri Jan 25 13:25:43.383187 2019] [:error] [pid 20836:tid 139736349660928]     return function(*args, **kwargs)
[Fri Jan 25 13:25:43.383189 2019] [:error] [pid 20836:tid 139736349660928]   File "/usr/lib/python2.7/site-packages/rucio/core/rse.py", line 568, in get_rse_usage
[Fri Jan 25 13:25:43.383191 2019] [:error] [pid 20836:tid 139736349660928]     account_usages.append({'used': row.bytes, 'account': row.account, 'percentage': round(float(row.bytes) / float(total) * 100, 2)})
[Fri Jan 25 13:25:43.383194 2019] [:error] [pid 20836:tid 139736349660928] ZeroDivisionError: float division by zero
```





Discussion:

Resolving patch:
diff --git a/lib/rucio/core/rse.py b/lib/rucio/core/rse.py
--- a/lib/rucio/core/rse.py
+++ b/lib/rucio/core/rse.py
@@ -22,7 +22,7 @@
 # - Wen Guan <wguan.icedew@gmail.com>, 2015-2016
 # - Brian Bockelman <bbockelm@cse.unl.edu>, 2018
 # - Frank Berghaus <frank.berghaus@cern.ch>, 2018
-# - Dimitrios Christidis <dimitrios.christidis@cern.ch>, 2018
+# - Dimitrios Christidis <dimitrios.christidis@cern.ch>, 2018-2019
 # - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018
 #
 # PY3K COMPATIBLE
@@ -128,7 +128,7 @@ def rse_exists(rse, session=None):
 @read_session
 def sort_rses(rses, session=None):
     """
-    Sort a list of RSES by srm free space (ascending order).
+    Sort a list of RSES by free space (ascending order).
 
     :param rses: List of RSEs.
     :param session: The database session in use.
@@ -143,7 +143,7 @@ def sort_rses(rses, session=None):
 
     false_value = False
     query = session.query(models.RSE.rse, models.RSE.staging_area, models.RSEUsage.rse_id).\
-        filter(or_(models.RSEUsage.source == 'srm', models.RSEUsage.source == 'gsiftp')).\
+        filter(models.RSEUsage.source == 'storage').\
         filter(models.RSEUsage.rse_id == models.RSE.id).\
         filter(models.RSE.deleted == false_value)
     condition = []
@@ -565,7 +565,8 @@ def get_rse_usage(rse, source=None, rse_id=None, session=None, per_account=False
             account_usages = []
             for row in query_account_usage:
                 if row.bytes != 0:
-                    account_usages.append({'used': row.bytes, 'account': row.account, 'percentage': round(float(row.bytes) / float(total) * 100, 2)})
+                    percentage = round(float(row.bytes) / float(total) * 100, 2) if total else 0
+                    account_usages.append({'used': row.bytes, 'account': row.account, 'percentage': percentage})
             account_usages.sort(key=lambda x: x['used'], reverse=True)
             rse_usage['account_usages'] = account_usages
         usage.append(rse_usage)
diff --git a/lib/rucio/daemons/reaper/reaper.py b/lib/rucio/daemons/reaper/reaper.py
--- a/lib/rucio/daemons/reaper/reaper.py
+++ b/lib/rucio/daemons/reaper/reaper.py
@@ -17,6 +17,7 @@
 # - Martin Barisits <martin.barisits@cern.ch>, 2016
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2016
 # - Wen Guan <wguan.icedew@gmail.com>, 2016
+# - Dimitrios Christidis <dimitrios.christidis@cern.ch>, 2019
 
 '''
 Reaper is a daemon to manage file deletion.
@@ -360,11 +361,16 @@ def run(total_workers=1, chunk_size=100, threads_per_worker=None, once=False, gr
     """
     logging.info('main: starting processes')
 
-    rses_list = rse_core.list_rses()
+    all_rses = rse_core.list_rses()
     if rses:
-        rses = [rse for rse in rses_list if rse['rse'] in rses]
+        invalid = set(rses) - set([rse['rse'] for rse in all_rses])
+        if invalid:
+            msg = 'RSE{} {} cannot be found'.format('s' if len(invalid) > 1 else '',
+                                                    ', '.join([repr(rse) for rse in invalid]))
+            raise RSENotFound(msg)
+        rses = [rse for rse in all_rses if rse['rse'] in rses]
     else:
-        rses = rses_list
+        rses = all_rses
 
     if exclude_rses:
         excluded_rses = parse_expression(exclude_rses)
@@ -374,6 +380,10 @@ def run(total_workers=1, chunk_size=100, threads_per_worker=None, once=False, gr
         included_rses = parse_expression(include_rses)
         rses = [rse for rse in rses if rse in included_rses]
 
+    if not rses:
+        logging.error('Reaper: No RSEs found. Exiting.')
+        return
+
     logging.info('Reaper: This instance will work on RSEs: ' + ', '.join([rse['rse'] for rse in rses]))
 
     threads = []


Test patch: